static const char driver_name[] = "i2c_omap";
#define MODULE_NAME "OMAP I2C"
-#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(500)) /* timeout waiting for the controller to respond */
+#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) /* timeout waiting for the controller to respond */
#define DEFAULT_OWN 1 /* default own I2C address */
#define MAX_MESSAGES 65536 /* max number of messages */
return __raw_readw(i2c_dev->base + reg);
}
-#ifdef CONFIG_ARCH_OMAP24XX
-static int omap_i2c_get_clocks(struct omap_i2c_dev *dev, int bus)
+static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
- if (!cpu_is_omap24xx())
- return 0;
-
- dev->iclk = clk_get(NULL,
- bus == 1 ? "i2c1_ick" : "i2c2_ick");
- if (IS_ERR(dev->iclk)) {
- return -ENODEV;
+ if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ dev->iclk = clk_get(dev->dev, "i2c_ick");
+ if (IS_ERR(dev->iclk))
+ return -ENODEV;
}
- dev->fclk = clk_get(NULL,
- bus == 1 ? "i2c1_fck" : "i2c2_fck");
+ dev->fclk = clk_get(dev->dev, "i2c_fck");
if (IS_ERR(dev->fclk)) {
- clk_put(dev->fclk);
+ if (dev->iclk != NULL)
+ clk_put(dev->iclk);
return -ENODEV;
}
static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
{
clk_put(dev->fclk);
- clk_put(dev->iclk);
+ dev->fclk = NULL;
+ if (dev->iclk != NULL) {
+ clk_put(dev->iclk);
+ dev->iclk = NULL;
+ }
}
static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
{
- clk_enable(dev->iclk);
+ if (dev->iclk != NULL)
+ clk_enable(dev->iclk);
clk_enable(dev->fclk);
}
static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
{
- clk_disable(dev->iclk);
+ if (dev->iclk != NULL)
+ clk_disable(dev->iclk);
clk_disable(dev->fclk);
}
-#else
-#define omap_i2c_get_clocks(x, y) 0
-#define omap_i2c_enable_clocks(x) do {} while (0)
-#define omap_i2c_disable_clocks(x) do {} while (0)
-#define omap_i2c_put_clocks(x) do {} while (0)
-#endif
-
static void omap_i2c_reset(struct omap_i2c_dev *dev)
{
u16 psc;
break;
}
- if (r == 0 && num > 1)
+ if (r == 0)
r = num;
out:
omap_i2c_disable_clocks(dev);
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+#ifdef CONFIG_ARCH_OMAP15XX
+static irqreturn_t
+omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+ struct omap_i2c_dev *dev = dev_id;
+ u16 iv, w;
+
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+ switch (iv) {
+ case 0x00: /* None */
+ break;
+ case 0x01: /* Arbitration lost */
+ dev_err(dev->dev, "Arbitration lost\n");
+ omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+ break;
+ case 0x02: /* No acknowledgement */
+ omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
+ break;
+ case 0x03: /* Register access ready */
+ omap_i2c_complete_cmd(dev, 0);
+ break;
+ case 0x04: /* Receive data ready */
+ if (dev->buf_len) {
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+ *dev->buf++ = w;
+ dev->buf_len--;
+ if (dev->buf_len) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ } else
+ dev_err(dev->dev, "RRDY IRQ while no data requested\n");
+ break;
+ case 0x05: /* Transmit data ready */
+ if (dev->buf_len) {
+ w = *dev->buf++;
+ dev->buf_len--;
+ if (dev->buf_len) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ } else
+ dev_err(dev->dev, "XRDY IRQ while no data to send\n");
+ break;
+ default:
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+#endif
+
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
{
u16 bits;
u16 stat, w;
int count = 0;
- u16 iv_read;
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
if (stat & OMAP_I2C_STAT_ARDY) {
omap_i2c_complete_cmd(dev, 0);
- if (dev->rev1)
- iv_read = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
continue;
}
if (stat & OMAP_I2C_STAT_RRDY) {
*dev->buf++ = w >> 8;
dev->buf_len--;
}
- if (dev->rev1 && !dev->buf_len)
- omap_i2c_complete_cmd(dev, 0);
} else
dev_err(dev->dev, "RRDY IRQ while no data requested\n");
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
- if (dev->rev1)
- iv_read = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
continue;
}
if (stat & OMAP_I2C_STAT_XRDY) {
#endif
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
- if (dev->rev1) {
- iv_read = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
- if (!dev->buf_len)
- omap_i2c_complete_cmd(dev, 0);
- }
if (bail_out)
omap_i2c_complete_cmd(dev, 1 << 15);
continue;
dev_err(dev->dev, "Arbitration lost\n");
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
}
- if (dev->rev1)
- iv_read = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
}
return count ? IRQ_HANDLED : IRQ_NONE;
dev->base = (void __iomem *) IO_ADDRESS(mem->start);
platform_set_drvdata(pdev, dev);
- if ((r = omap_i2c_get_clocks(dev, pdev->id)) != 0)
+ if ((r = omap_i2c_get_clocks(dev)) != 0)
goto do_free_mem;
omap_i2c_enable_clocks(dev);
/* reset ASAP, clearing any IRQs */
omap_i2c_reset(dev);
- r = request_irq(dev->irq, omap_i2c_isr, 0,
- driver_name, dev);
+#ifdef CONFIG_ARCH_OMAP15XX
+ r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
+ 0, driver_name, dev);
+#else
+ r = request_irq(dev->irq, omap_i2c_isr, 0, driver_name, dev);
+#endif
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto do_unuse_clocks;
do_free_irq:
free_irq(dev->irq, dev);
do_unuse_clocks:
- omap_i2c_enable_clocks(dev);
+ omap_i2c_disable_clocks(dev);
omap_i2c_put_clocks(dev);
do_free_mem:
kfree(dev);