Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3ad33c9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus/i2c-2635' of git://git.fluff.org/bjdooks/linux

* 'for-linus/i2c-2635' of git://git.fluff.org/bjdooks/linux: (21 commits)
  i2c-highlander: remover superflous variable
  i2c-ibm-iic: drop NO_IRQ
  i2c-cpm: drop NO_IRQ
  i2c-mpc: drop NO_IRQ
  MAINTAINERS: add i2c tree for embedded platforms
  i2c-pxa: only define 'blue_murder'-function if DEBUG is #defined
  i2c-pxa: remove unused macro
  i2c-nomadik: fix operator precedence warning
  i2c-nomadik: release region when removed
  OMAP3: I2C: Clean up Errata 1p153 handling
  OMAP2/3: I2C: Errata ID i207: Clear wrong RDR interrupt
  omap: i2c: add a timeout to the busy waiting
  omap: i2c: make errata 1.153 workaround a separate function
  i2c-omap: add mpu wake up latency constraint in i2c
  omap: i2c: Add i2c support on omap4 platform
  i2c-bfin-twi: return completion in interrupt for smbus quick transfers
  i2c-bfin-twi: remove redundant retry
  i2c-bfin-twi: fix lost interrupts at high speeds
  i2c-bfin-twi: add debug output for error status
  i2c-bfin-twi: integrate timeout timer with completion interface
  ...
parents fb091be0 b5c80bc5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2747,6 +2747,7 @@ M: "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
L:	linux-i2c@vger.kernel.org
W:	http://i2c.wiki.kernel.org/
T:	quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
T:	git git://git.fluff.org/bjdooks/linux.git
S:	Maintained
F:	Documentation/i2c/
F:	drivers/i2c/
+27 −12
Original line number Diff line number Diff line
@@ -26,9 +26,12 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-omap.h>

#include <mach/irqs.h>
#include <plat/mux.h>
#include <plat/i2c.h>
#include <plat/omap-pm.h>

#define OMAP_I2C_SIZE		0x3f
#define OMAP1_I2C_BASE		0xfffb3800
@@ -70,14 +73,14 @@ static struct resource i2c_resources[][2] = {
		},					\
	}

static u32 i2c_rate[ARRAY_SIZE(i2c_resources)];
static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)];
static struct platform_device omap_i2c_devices[] = {
	I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]),
	I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
#if	defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
	I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]),
	I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]),
#endif
#if	defined(CONFIG_ARCH_OMAP3)
	I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]),
	I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]),
#endif
};

@@ -100,10 +103,12 @@ static int __init omap_i2c_nr_ports(void)
static int __init omap_i2c_add_bus(int bus_id)
{
	struct platform_device *pdev;
	struct omap_i2c_bus_platform_data *pd;
	struct resource *res;
	resource_size_t base, irq;

	pdev = &omap_i2c_devices[bus_id - 1];
	pd = pdev->dev.platform_data;
	if (bus_id == 1) {
		res = pdev->resource;
		if (cpu_class_is_omap1()) {
@@ -123,6 +128,15 @@ static int __init omap_i2c_add_bus(int bus_id)
	if (cpu_class_is_omap2())
		omap2_i2c_mux_pins(bus_id);

	/*
	 * When waiting for completion of a i2c transfer, we need to
	 * set a wake up latency constraint for the MPU. This is to
	 * ensure quick enough wakeup from idle, when transfer
	 * completes.
	 */
	if (cpu_is_omap34xx())
		pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat;

	return platform_device_register(pdev);
}

@@ -146,8 +160,8 @@ static int __init omap_i2c_bus_setup(char *str)
	get_options(str, 3, ints);
	if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
		return 0;
	i2c_rate[ints[1] - 1] = ints[2];
	i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP;
	i2c_pdata[ints[1] - 1].clkrate = ints[2];
	i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;

	return 1;
}
@@ -161,9 +175,9 @@ static int __init omap_register_i2c_bus_cmdline(void)
{
	int i, err = 0;

	for (i = 0; i < ARRAY_SIZE(i2c_rate); i++)
		if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) {
			i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP;
	for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
		if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
			i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
			err = omap_i2c_add_bus(i + 1);
			if (err)
				goto out;
@@ -197,9 +211,10 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
			return err;
	}

	if (!i2c_rate[bus_id - 1])
		i2c_rate[bus_id - 1] = clkrate;
	i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP;
	if (!i2c_pdata[bus_id - 1].clkrate)
		i2c_pdata[bus_id - 1].clkrate = clkrate;

	i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;

	return omap_i2c_add_bus(bus_id);
}
+78 −90
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@
#include <asm/portmux.h>
#include <asm/irq.h>

#define POLL_TIMEOUT       (2 * HZ)

/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD		1
#define TWI_I2C_MODE_STANDARDSUB	2
@@ -44,8 +42,6 @@ struct bfin_twi_iface {
	int			cur_mode;
	int			manual_stop;
	int			result;
	int			timeout_count;
	struct timer_list	timeout_timer;
	struct i2c_adapter	adap;
	struct completion	complete;
	struct i2c_msg 		*pmsg;
@@ -85,14 +81,15 @@ static const u16 pin_req[2][3] = {
	{P_TWI1_SCL, P_TWI1_SDA, 0},
};

static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
					unsigned short twi_int_status)
{
	unsigned short twi_int_status = read_INT_STAT(iface);
	unsigned short mast_stat = read_MASTER_STAT(iface);

	if (twi_int_status & XMTSERV) {
		/* Transmit next data */
		if (iface->writeNum > 0) {
			SSYNC();
			write_XMT_DATA8(iface, *(iface->transPtr++));
			iface->writeNum--;
		}
@@ -114,10 +111,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
				write_MASTER_CTL(iface,
					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
		}
		SSYNC();
		/* Clear status */
		write_INT_STAT(iface, XMTSERV);
		SSYNC();
	}
	if (twi_int_status & RCVSERV) {
		if (iface->readNum > 0) {
@@ -139,7 +132,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
		} else if (iface->manual_stop) {
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) | STOP);
			SSYNC();
		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
		           iface->cur_msg + 1 < iface->msg_num) {
			if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
@@ -148,44 +140,37 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			else
				write_MASTER_CTL(iface,
					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
			SSYNC();
		}
		/* Clear interrupt source */
		write_INT_STAT(iface, RCVSERV);
		SSYNC();
	}
	if (twi_int_status & MERR) {
		write_INT_STAT(iface, MERR);
		write_INT_MASK(iface, 0);
		write_MASTER_STAT(iface, 0x3e);
		write_MASTER_CTL(iface, 0);
		SSYNC();
		iface->result = -EIO;
		/* if both err and complete int stats are set, return proper
		 * results.
		 */
		if (twi_int_status & MCOMP) {
			write_INT_STAT(iface, MCOMP);
			write_INT_MASK(iface, 0);
			write_MASTER_CTL(iface, 0);
			SSYNC();
			/* If it is a quick transfer, only address bug no data,

		if (mast_stat & LOSTARB)
			dev_dbg(&iface->adap.dev, "Lost Arbitration\n");
		if (mast_stat & ANAK)
			dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n");
		if (mast_stat & DNAK)
			dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n");
		if (mast_stat & BUFRDERR)
			dev_dbg(&iface->adap.dev, "Buffer Read Error\n");
		if (mast_stat & BUFWRERR)
			dev_dbg(&iface->adap.dev, "Buffer Write Error\n");

		/* If it is a quick transfer, only address without data,
		 * not an err, return 1.
		 */
			if (iface->writeNum == 0 && (mast_stat & BUFRDERR))
		if (iface->cur_mode == TWI_I2C_MODE_STANDARD &&
			iface->transPtr == NULL &&
			(twi_int_status & MCOMP) && (mast_stat & DNAK))
			iface->result = 1;
			/* If address not acknowledged return -1,
			 * else return 0.
			 */
			else if (!(mast_stat & ANAK))
				iface->result = 0;
		}

		complete(&iface->complete);
		return;
	}
	if (twi_int_status & MCOMP) {
		write_INT_STAT(iface, MCOMP);
		SSYNC();
		if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
			if (iface->readNum == 0) {
				/* set the read number to 1 and ask for manual
@@ -207,7 +192,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			/* remove restart bit and enable master receive */
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) & ~RSTART);
			SSYNC();
		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
				iface->cur_msg+1 < iface->msg_num) {
			iface->cur_msg++;
@@ -226,7 +210,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
					write_XMT_DATA8(iface,
						*(iface->transPtr++));
					iface->writeNum--;
					SSYNC();
				}
			}

@@ -244,15 +227,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			/* remove restart bit and enable master receive */
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) & ~RSTART);
			SSYNC();
		} else {
			iface->result = 1;
			write_INT_MASK(iface, 0);
			write_MASTER_CTL(iface, 0);
			SSYNC();
			complete(&iface->complete);
		}
	}
	complete(&iface->complete);
}

/* Interrupt handler */
@@ -260,38 +241,26 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
{
	struct bfin_twi_iface *iface = dev_id;
	unsigned long flags;
	unsigned short twi_int_status;

	spin_lock_irqsave(&iface->lock, flags);
	del_timer(&iface->timeout_timer);
	bfin_twi_handle_interrupt(iface);
	spin_unlock_irqrestore(&iface->lock, flags);
	return IRQ_HANDLED;
}

static void bfin_twi_timeout(unsigned long data)
{
	struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data;
	unsigned long flags;

	spin_lock_irqsave(&iface->lock, flags);
	bfin_twi_handle_interrupt(iface);
	if (iface->result == 0) {
		iface->timeout_count--;
		if (iface->timeout_count > 0) {
			iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
			add_timer(&iface->timeout_timer);
		} else {
			iface->result = -1;
			complete(&iface->complete);
		}
	while (1) {
		twi_int_status = read_INT_STAT(iface);
		if (!twi_int_status)
			break;
		/* Clear interrupt status */
		write_INT_STAT(iface, twi_int_status);
		bfin_twi_handle_interrupt(iface, twi_int_status);
		SSYNC();
	}
	spin_unlock_irqrestore(&iface->lock, flags);
	return IRQ_HANDLED;
}

/*
 * Generic i2c master transfer entrypoint
 * One i2c master transfer
 */
static int bfin_twi_master_xfer(struct i2c_adapter *adap,
static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
				struct i2c_msg *msgs, int num)
{
	struct bfin_twi_iface *iface = adap->algo_data;
@@ -319,7 +288,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
	iface->transPtr = pmsg->buf;
	iface->writeNum = iface->readNum = pmsg->len;
	iface->result = 0;
	iface->timeout_count = 10;
	init_completion(&(iface->complete));
	/* Set Transmit device address */
	write_MASTER_ADDR(iface, pmsg->addr);
@@ -358,30 +326,41 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
		iface->manual_stop = 1;
	}

	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
	add_timer(&iface->timeout_timer);

	/* Master enable */
	write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
		((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
		((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
	SSYNC();

	wait_for_completion(&iface->complete);
	while (!iface->result) {
		if (!wait_for_completion_timeout(&iface->complete,
			adap->timeout)) {
			iface->result = -1;
			dev_err(&adap->dev, "master transfer timeout\n");
		}
	}

	if (iface->result == 1)
		rc = iface->cur_msg + 1;
	else
		rc = iface->result;

	if (rc == 1)
		return num;
	else
	return rc;
}

/*
 * SMBus type transfer entrypoint
 * Generic i2c master transfer entrypoint
 */
static int bfin_twi_master_xfer(struct i2c_adapter *adap,
				struct i2c_msg *msgs, int num)
{
	return bfin_twi_do_master_xfer(adap, msgs, num);
}

int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
/*
 * One I2C SMBus transfer
 */
int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
			unsigned short flags, char read_write,
			u8 command, int size, union i2c_smbus_data *data)
{
@@ -469,7 +448,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
	iface->manual_stop = 0;
	iface->read_write = read_write;
	iface->command = command;
	iface->timeout_count = 10;
	init_completion(&(iface->complete));

	/* FIFO Initiation. Data in FIFO should be discarded before
@@ -486,9 +464,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
	write_MASTER_ADDR(iface, addr);
	SSYNC();

	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
	add_timer(&iface->timeout_timer);

	switch (iface->cur_mode) {
	case TWI_I2C_MODE_STANDARDSUB:
		write_XMT_DATA8(iface, iface->command);
@@ -550,12 +525,10 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
				else if (iface->readNum > 255) {
					write_MASTER_CTL(iface, 0xff << 6);
					iface->manual_stop = 1;
				} else {
					del_timer(&iface->timeout_timer);
				} else
					break;
			}
		}
		}
		write_INT_MASK(iface, MCOMP | MERR |
			((iface->read_write == I2C_SMBUS_READ) ?
			RCVSERV : XMTSERV));
@@ -569,13 +542,30 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
	}
	SSYNC();

	wait_for_completion(&iface->complete);
	while (!iface->result) {
		if (!wait_for_completion_timeout(&iface->complete,
			adap->timeout)) {
			iface->result = -1;
			dev_err(&adap->dev, "smbus transfer timeout\n");
		}
	}

	rc = (iface->result >= 0) ? 0 : -1;

	return rc;
}

/*
 * Generic I2C SMBus transfer entrypoint
 */
int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
			unsigned short flags, char read_write,
			u8 command, int size, union i2c_smbus_data *data)
{
	return bfin_twi_do_smbus_xfer(adap, addr, flags,
			read_write, command, size, data);
}

/*
 * Return what the adapter supports
 */
@@ -667,10 +657,6 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
		goto out_error_no_irq;
	}

	init_timer(&(iface->timeout_timer));
	iface->timeout_timer.function = bfin_twi_timeout;
	iface->timeout_timer.data = (unsigned long)iface;

	p_adap = &iface->adap;
	p_adap->nr = pdev->id;
	strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
@@ -678,6 +664,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
	p_adap->algo_data = iface;
	p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
	p_adap->dev.parent = &pdev->dev;
	p_adap->timeout = 5 * HZ;
	p_adap->retries = 3;

	rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
	if (rc) {
+1 −1
Original line number Diff line number Diff line
@@ -441,7 +441,7 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
	init_waitqueue_head(&cpm->i2c_wait);

	cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL);
	if (cpm->irq == NO_IRQ)
	if (!cpm->irq)
		return -EINVAL;

	/* Install interrupt handler. */
+2 −3
Original line number Diff line number Diff line
@@ -282,7 +282,6 @@ static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
				  union i2c_smbus_data *data)
{
	struct highlander_i2c_dev *dev = i2c_get_adapdata(adap);
	int read = read_write & I2C_SMBUS_READ;
	u16 tmp;

	init_completion(&dev->cmd_complete);
@@ -337,11 +336,11 @@ static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
	highlander_i2c_done(dev);

	/* Set slave address */
	iowrite16((addr << 1) | read, dev->base + SMSMADR);
	iowrite16((addr << 1) | read_write, dev->base + SMSMADR);

	highlander_i2c_command(dev, command, dev->buf_len);

	if (read)
	if (read_write == I2C_SMBUS_READ)
		return highlander_i2c_read(dev);
	else
		return highlander_i2c_write(dev);
Loading