summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-davinci.c26
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c9
-rw-r--r--drivers/i2c/busses/i2c-omap.c60
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c5
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c4
-rw-r--r--drivers/i2c/busses/i2c-simtec.c2
-rw-r--r--drivers/i2c/busses/i2c-stu300.c157
-rw-r--r--drivers/i2c/chips/tsl2550.c17
9 files changed, 177 insertions, 104 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index aa87b6a3bbe..8206442fbab 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -328,6 +328,7 @@ config I2C_DAVINCI
config I2C_DESIGNWARE
tristate "Synopsys DesignWare"
+ depends on HAVE_CLK
help
If you say yes to this option, support will be included for the
Synopsys DesignWare I2C adapter. Only master mode is supported.
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 3fae3a91ce5..c89687a1083 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -187,6 +187,11 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
+ /* Respond at reserved "SMBus Host" slave address" (and zero);
+ * we seem to have no option to not respond...
+ */
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
+
dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
dev_dbg(dev->dev, "PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
@@ -387,7 +392,7 @@ static void terminate_write(struct davinci_i2c_dev *dev)
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
if (!dev->terminate)
- dev_err(dev->dev, "TDR IRQ while no data to send\n");
+ dev_dbg(dev->dev, "TDR IRQ while no data to send\n");
}
/*
@@ -473,9 +478,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
break;
case DAVINCI_I2C_IVR_AAS:
- dev_warn(dev->dev, "Address as slave interrupt\n");
- }/* switch */
- }/* while */
+ dev_dbg(dev->dev, "Address as slave interrupt\n");
+ break;
+
+ default:
+ dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat);
+ break;
+ }
+ }
return count ? IRQ_HANDLED : IRQ_NONE;
}
@@ -505,7 +515,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
return -ENODEV;
}
- ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+ ioarea = request_mem_region(mem->start, resource_size(mem),
pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -523,7 +533,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->irq = irq->start;
platform_set_drvdata(pdev, dev);
- dev->clk = clk_get(&pdev->dev, "I2CCLK");
+ dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) {
r = -ENODEV;
goto err_free_mem;
@@ -568,7 +578,7 @@ err_free_mem:
put_device(&pdev->dev);
kfree(dev);
err_release_region:
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
+ release_mem_region(mem->start, resource_size(mem));
return r;
}
@@ -591,7 +601,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
+ release_mem_region(mem->start, resource_size(mem));
return 0;
}
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index e4476743f20..b1bc6e277d2 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header);
- printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n"
- KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n"
- KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n"
- KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n",
+ printk(KERN_DEBUG
+ " cntl = 0x%02x, mdcntl = 0x%02x\n"
+ " sts = 0x%02x, extsts = 0x%02x\n"
+ " clkdiv = 0x%02x, xfrcnt = 0x%02x\n"
+ " xtcntlss = 0x%02x, directcntl = 0x%02x\n",
in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
in_8(&iic->xtcntlss), in_8(&iic->directcntl));
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ad8d2010c92..827da085813 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -672,9 +672,17 @@ omap_i2c_isr(int this_irq, void *dev_id)
break;
}
- omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
-
err = 0;
+complete:
+ /*
+ * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
+ * acked after the data operation is complete.
+ * Ref: TRM SWPU114Q Figure 18-31
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+ ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+ OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+
if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
@@ -685,16 +693,22 @@ omap_i2c_isr(int this_irq, void *dev_id)
err |= OMAP_I2C_STAT_AL;
}
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
- OMAP_I2C_STAT_AL))
+ OMAP_I2C_STAT_AL)) {
+ omap_i2c_ack_stat(dev, stat &
+ (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+ OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
omap_i2c_complete_cmd(dev, err);
+ return IRQ_HANDLED;
+ }
if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
u8 num_bytes = 1;
if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_RRDY)
num_bytes = dev->fifo_size;
- else
- num_bytes = omap_i2c_read_reg(dev,
- OMAP_I2C_BUFSTAT_REG);
+ else /* read RXSTAT on RDR interrupt */
+ num_bytes = (omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG)
+ >> 8) & 0x3F;
}
while (num_bytes) {
num_bytes--;
@@ -731,9 +745,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_XRDY)
num_bytes = dev->fifo_size;
- else
+ else /* read TXSTAT on XDR interrupt */
num_bytes = omap_i2c_read_reg(dev,
- OMAP_I2C_BUFSTAT_REG);
+ OMAP_I2C_BUFSTAT_REG)
+ & 0x3F;
}
while (num_bytes) {
num_bytes--;
@@ -760,6 +775,27 @@ omap_i2c_isr(int this_irq, void *dev_id)
"data to send\n");
break;
}
+
+ /*
+ * OMAP3430 Errata 1.153: When an XRDY/XDR
+ * is hit, wait for XUDF before writing data
+ * to DATA_REG. Otherwise some data bytes can
+ * be lost while transferring them from the
+ * memory to the I2C interface.
+ */
+
+ if (dev->rev <= OMAP_I2C_REV_ON_3430) {
+ while (!(stat & OMAP_I2C_STAT_XUDF)) {
+ if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+ omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+ err |= OMAP_I2C_STAT_XUDF;
+ goto complete;
+ }
+ cpu_relax();
+ stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ }
+ }
+
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
}
omap_i2c_ack_stat(dev,
@@ -806,7 +842,7 @@ omap_i2c_probe(struct platform_device *pdev)
return -ENODEV;
}
- ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+ ioarea = request_mem_region(mem->start, resource_size(mem),
pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -879,7 +915,7 @@ omap_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON;
- strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+ strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
adap->algo = &omap_i2c_algo;
adap->dev.parent = &pdev->dev;
@@ -905,7 +941,7 @@ err_free_mem:
platform_set_drvdata(pdev, NULL);
kfree(dev);
err_release_region:
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
+ release_mem_region(mem->start, resource_size(mem));
return r;
}
@@ -925,7 +961,7 @@ omap_i2c_remove(struct platform_device *pdev)
iounmap(dev->base);
kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
+ release_mem_region(mem->start, resource_size(mem));
return 0;
}
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 8f42a4536cd..20bb0ceb027 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
- /* check for s3c2440 i2c controller */
-
- if (s3c24xx_i2c_is2440(i2c))
- writel(0x0, i2c->regs + S3C2440_IICLC);
-
return 0;
}
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 1c01083b01b..820487d0d5c 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -563,7 +563,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
goto err_irq;
}
- size = (res->end - res->start) + 1;
+ size = resource_size(res);
pd->reg = ioremap(res->start, size);
if (pd->reg == NULL) {
@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void)
platform_driver_unregister(&sh_mobile_i2c_driver);
}
-module_init(sh_mobile_i2c_adap_init);
+subsys_initcall(sh_mobile_i2c_adap_init);
module_exit(sh_mobile_i2c_adap_exit);
MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
index 042fda295f3..6407f47bda8 100644
--- a/drivers/i2c/busses/i2c-simtec.c
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -92,7 +92,7 @@ static int simtec_i2c_probe(struct platform_device *dev)
goto err;
}
- size = (res->end-res->start)+1;
+ size = resource_size(res);
pd->ioarea = request_mem_region(res->start, size, dev->name);
if (pd->ioarea == NULL) {
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 182e711318b..d2728a28a8d 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -117,7 +117,8 @@ enum stu300_error {
STU300_ERROR_NONE = 0,
STU300_ERROR_ACKNOWLEDGE_FAILURE,
STU300_ERROR_BUS_ERROR,
- STU300_ERROR_ARBITRATION_LOST
+ STU300_ERROR_ARBITRATION_LOST,
+ STU300_ERROR_UNKNOWN
};
/* timeout waiting for the controller to respond */
@@ -127,7 +128,7 @@ enum stu300_error {
* The number of address send athemps tried before giving up.
* If the first one failes it seems like 5 to 8 attempts are required.
*/
-#define NUM_ADDR_RESEND_ATTEMPTS 10
+#define NUM_ADDR_RESEND_ATTEMPTS 12
/* I2C clock speed, in Hz 0-400kHz*/
static unsigned int scl_frequency = 100000;
@@ -149,6 +150,7 @@ module_param(scl_frequency, uint, 0644);
* @msg_index: index of current message
* @msg_len: length of current message
*/
+
struct stu300_dev {
struct platform_device *pdev;
struct i2c_adapter adapter;
@@ -188,6 +190,27 @@ static inline u32 stu300_r8(void __iomem *address)
return readl(address) & 0x000000FFU;
}
+static void stu300_irq_enable(struct stu300_dev *dev)
+{
+ u32 val;
+ val = stu300_r8(dev->virtbase + I2C_CR);
+ val |= I2C_CR_INTERRUPT_ENABLE;
+ /* Twice paranoia (possible HW glitch) */
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+static void stu300_irq_disable(struct stu300_dev *dev)
+{
+ u32 val;
+ val = stu300_r8(dev->virtbase + I2C_CR);
+ val &= ~I2C_CR_INTERRUPT_ENABLE;
+ /* Twice paranoia (possible HW glitch) */
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+ stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+
/*
* Tells whether a certain event or events occurred in
* response to a command. The events represent states in
@@ -196,9 +219,10 @@ static inline u32 stu300_r8(void __iomem *address)
* documentation and can only be treated as abstract state
* machine states.
*
- * @ret 0 = event has not occurred, any other value means
- * the event occurred.
+ * @ret 0 = event has not occurred or unknown error, any
+ * other value means the correct event occurred or an error.
*/
+
static int stu300_event_occurred(struct stu300_dev *dev,
enum stu300_event mr_event) {
u32 status1;
@@ -206,11 +230,28 @@ static int stu300_event_occurred(struct stu300_dev *dev,
/* What event happened? */
status1 = stu300_r8(dev->virtbase + I2C_SR1);
+
if (!(status1 & I2C_SR1_EVF_IND))
/* No event at all */
return 0;
+
status2 = stu300_r8(dev->virtbase + I2C_SR2);
+ /* Block any multiple interrupts */
+ stu300_irq_disable(dev);
+
+ /* Check for errors first */
+ if (status2 & I2C_SR2_AF_IND) {
+ dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
+ return 1;
+ } else if (status2 & I2C_SR2_BERR_IND) {
+ dev->cmd_err = STU300_ERROR_BUS_ERROR;
+ return 1;
+ } else if (status2 & I2C_SR2_ARLO_IND) {
+ dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+ return 1;
+ }
+
switch (mr_event) {
case STU300_EVENT_1:
if (status1 & I2C_SR1_ADSL_IND)
@@ -221,10 +262,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
case STU300_EVENT_7:
case STU300_EVENT_8:
if (status1 & I2C_SR1_BTF_IND) {
- if (status2 & I2C_SR2_AF_IND)
- dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
- else if (status2 & I2C_SR2_BERR_IND)
- dev->cmd_err = STU300_ERROR_BUS_ERROR;
return 1;
}
break;
@@ -240,8 +277,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
case STU300_EVENT_6:
if (status2 & I2C_SR2_ENDAD_IND) {
/* First check for any errors */
- if (status2 & I2C_SR2_AF_IND)
- dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
return 1;
}
break;
@@ -252,8 +287,15 @@ static int stu300_event_occurred(struct stu300_dev *dev,
default:
break;
}
- if (status2 & I2C_SR2_ARLO_IND)
- dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+ /* If we get here, we're on thin ice.
+ * Here we are in a status where we have
+ * gotten a response that does not match
+ * what we requested.
+ */
+ dev->cmd_err = STU300_ERROR_UNKNOWN;
+ dev_err(&dev->pdev->dev,
+ "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n",
+ mr_event, status1, status2);
return 0;
}
@@ -262,21 +304,20 @@ static irqreturn_t stu300_irh(int irq, void *data)
struct stu300_dev *dev = data;
int res;
+ /* Just make sure that the block is clocked */
+ clk_enable(dev->clk);
+
/* See if this was what we were waiting for */
spin_lock(&dev->cmd_issue_lock);
- if (dev->cmd_event != STU300_EVENT_NONE) {
- res = stu300_event_occurred(dev, dev->cmd_event);
- if (res || dev->cmd_err != STU300_ERROR_NONE) {
- u32 val;
-
- complete(&dev->cmd_complete);
- /* Block any multiple interrupts */
- val = stu300_r8(dev->virtbase + I2C_CR);
- val &= ~I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
- }
- }
+
+ res = stu300_event_occurred(dev, dev->cmd_event);
+ if (res || dev->cmd_err != STU300_ERROR_NONE)
+ complete(&dev->cmd_complete);
+
spin_unlock(&dev->cmd_issue_lock);
+
+ clk_disable(dev->clk);
+
return IRQ_HANDLED;
}
@@ -308,7 +349,6 @@ static int stu300_start_and_await_event(struct stu300_dev *dev,
stu300_wr8(cr_value, dev->virtbase + I2C_CR);
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
STU300_TIMEOUT);
-
if (ret < 0) {
dev_err(&dev->pdev->dev,
"wait_for_completion_interruptible_timeout() "
@@ -342,7 +382,6 @@ static int stu300_await_event(struct stu300_dev *dev,
enum stu300_event mr_event)
{
int ret;
- u32 val;
if (unlikely(irqs_disabled())) {
/* TODO: implement polling for this case if need be. */
@@ -354,36 +393,18 @@ static int stu300_await_event(struct stu300_dev *dev,
/* Is it already here? */
spin_lock_irq(&dev->cmd_issue_lock);
dev->cmd_err = STU300_ERROR_NONE;
- if (stu300_event_occurred(dev, mr_event)) {
- spin_unlock_irq(&dev->cmd_issue_lock);
- goto exit_await_check_err;
- }
- init_completion(&dev->cmd_complete);
- dev->cmd_err = STU300_ERROR_NONE;
dev->cmd_event = mr_event;
- /* Turn on the I2C interrupt for current operation */
- val = stu300_r8(dev->virtbase + I2C_CR);
- val |= I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
-
- /* Twice paranoia (possible HW glitch) */
- stu300_wr8(val, dev->virtbase + I2C_CR);
+ init_completion(&dev->cmd_complete);
- /* Check again: is it already here? */
- if (unlikely(stu300_event_occurred(dev, mr_event))) {
- /* Disable IRQ again. */
- val &= ~I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
- spin_unlock_irq(&dev->cmd_issue_lock);
- goto exit_await_check_err;
- }
+ /* Turn on the I2C interrupt for current operation */
+ stu300_irq_enable(dev);
/* Unlock the command block and wait for the event to occur */
spin_unlock_irq(&dev->cmd_issue_lock);
+
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
STU300_TIMEOUT);
-
if (ret < 0) {
dev_err(&dev->pdev->dev,
"wait_for_completion_interruptible_timeout()"
@@ -401,7 +422,6 @@ static int stu300_await_event(struct stu300_dev *dev,
return -ETIMEDOUT;
}
- exit_await_check_err:
if (dev->cmd_err != STU300_ERROR_NONE) {
if (mr_event != STU300_EVENT_6) {
dev_err(&dev->pdev->dev, "controller "
@@ -457,18 +477,19 @@ struct stu300_clkset {
};
static const struct stu300_clkset stu300_clktable[] = {
- { 0, 0xFFU },
- { 2500000, I2C_OAR2_FR_25_10MHZ },
- { 10000000, I2C_OAR2_FR_10_1667MHZ },
- { 16670000, I2C_OAR2_FR_1667_2667MHZ },
- { 26670000, I2C_OAR2_FR_2667_40MHZ },
- { 40000000, I2C_OAR2_FR_40_5333MHZ },
- { 53330000, I2C_OAR2_FR_5333_66MHZ },
- { 66000000, I2C_OAR2_FR_66_80MHZ },
- { 80000000, I2C_OAR2_FR_80_100MHZ },
+ { 0, 0xFFU },
+ { 2500000, I2C_OAR2_FR_25_10MHZ },
+ { 10000000, I2C_OAR2_FR_10_1667MHZ },
+ { 16670000, I2C_OAR2_FR_1667_2667MHZ },
+ { 26670000, I2C_OAR2_FR_2667_40MHZ },
+ { 40000000, I2C_OAR2_FR_40_5333MHZ },
+ { 53330000, I2C_OAR2_FR_5333_66MHZ },
+ { 66000000, I2C_OAR2_FR_66_80MHZ },
+ { 80000000, I2C_OAR2_FR_80_100MHZ },
{ 100000000, 0xFFU },
};
+
static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
{
@@ -494,10 +515,10 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
if (dev->speed > 100000)
/* Fast Mode I2C */
- val = ((clkrate/dev->speed)-9)/3;
+ val = ((clkrate/dev->speed) - 9)/3 + 1;
else
/* Standard Mode I2C */
- val = ((clkrate/dev->speed)-7)/2;
+ val = ((clkrate/dev->speed) - 7)/2 + 1;
/* According to spec the divider must be > 2 */
if (val < 0x002) {
@@ -557,6 +578,7 @@ static int stu300_init_hw(struct stu300_dev *dev)
*/
clkrate = clk_get_rate(dev->clk);
ret = stu300_set_clk(dev, clkrate);
+
if (ret)
return ret;
/*
@@ -641,7 +663,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
int attempts = 0;
struct stu300_dev *dev = i2c_get_adapdata(adap);
-
clk_enable(dev->clk);
/* Remove this if (0) to trace each and every message. */
@@ -715,14 +736,15 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) {
dev_dbg(&dev->pdev->dev, "managed to get address "
- "through after %d attempts\n", attempts);
+ "through after %d attempts\n", attempts);
} else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) {
dev_dbg(&dev->pdev->dev, "I give up, tried %d times "
- "to resend address.\n",
- NUM_ADDR_RESEND_ATTEMPTS);
+ "to resend address.\n",
+ NUM_ADDR_RESEND_ATTEMPTS);
goto exit_disable;
}
+
if (msg->flags & I2C_M_RD) {
/* READ: we read the actual bytes one at a time */
for (i = 0; i < msg->len; i++) {
@@ -804,8 +826,10 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
{
int ret = -1;
int i;
+
struct stu300_dev *dev = i2c_get_adapdata(adap);
dev->msg_len = num;
+
for (i = 0; i < num; i++) {
/*
* Another driver appears to send stop for each message,
@@ -817,6 +841,7 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
dev->msg_index = i;
ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+
if (ret != 0) {
num = ret;
break;
@@ -845,6 +870,7 @@ stu300_probe(struct platform_device *pdev)
struct resource *res;
int bus_nr;
int ret = 0;
+ char clk_name[] = "I2C0";
dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL);
if (!dev) {
@@ -854,7 +880,8 @@ stu300_probe(struct platform_device *pdev)
}
bus_nr = pdev->id;
- dev->clk = clk_get(&pdev->dev, NULL);
+ clk_name[3] += (char)bus_nr;
+ dev->clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
index 1a9cc135219..b96f3025e58 100644
--- a/drivers/i2c/chips/tsl2550.c
+++ b/drivers/i2c/chips/tsl2550.c
@@ -27,7 +27,7 @@
#include <linux/delay.h>
#define TSL2550_DRV_NAME "tsl2550"
-#define DRIVER_VERSION "1.1.1"
+#define DRIVER_VERSION "1.1.2"
/*
* Defines
@@ -189,13 +189,16 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
u8 r = 128;
/* Avoid division by 0 and count 1 cannot be greater than count 0 */
- if (c0 && (c1 <= c0))
- r = c1 * 128 / c0;
+ if (c1 <= c0)
+ if (c0) {
+ r = c1 * 128 / c0;
+
+ /* Calculate LUX */
+ lux = ((c0 - c1) * ratio_lut[r]) / 256;
+ } else
+ lux = 0;
else
- return -1;
-
- /* Calculate LUX */
- lux = ((c0 - c1) * ratio_lut[r]) / 256;
+ return -EAGAIN;
/* LUX range check */
return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;