/* i2c Support for Atmel's AT91 Two-Wire Interface (TWI) Copyright (C) 2004 Rick Bronson Converted to 2.6 by Andrew Victor Borrowed heavily from original work by: Copyright (C) 2000 Philip Edelbrock This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. D. Gilbert [20100318 AT91SAM9G20] - Check for NACK, a NACK will abort current tranfser, returned as errno=EREMOTEIO unless I2C_M_IGNORE_NAK is set - Only supports 7 bit I2C device (slave) address - clockrate adjustable (module_param). */ /* Uncomment following line to see dev_dbg() output in logs */ /* #define DEBUG 1 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */ static unsigned int clockrate = TWI_CLOCK; static unsigned int prev_clockrate = TWI_CLOCK; static struct clk *twi_clk; static void __iomem *twi_base; #define at91_twi_read(reg) __raw_readl(twi_base + (reg)) #define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg)) /* * Set TWI clock dividers based on clockrate (clock rate for SCL) */ static void at91_twi_clock_dividers(void) { unsigned long cdiv, ckdiv; if (clockrate < 1000) clockrate = 1000; else if (clockrate > 400000) clockrate = 400000; /* Calculate clock dividers */ cdiv = (clk_get_rate(twi_clk) / (2 * clockrate)) - 3; cdiv = cdiv + 1; /* round up */ ckdiv = 0; while (cdiv > 255) { ckdiv++; cdiv = cdiv >> 1; } if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */ if (ckdiv > 5) { printk(KERN_ERR "i2c-at91: Invalid AT91RM9200 clock rate\n"); ckdiv = 5; } } /* AT91SAM9G20 has 3 bits for ckdiv so it cannot exceed 7 */ if (cpu_is_at91sam9g20()) { if (ckdiv > 7) { printk(KERN_ERR "i2c-at91: Invalid AT91SAM9G20 clock " "rate, ckdiv=%lu\n", ckdiv); ckdiv = 7; } } at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv); prev_clockrate = clockrate; } /* * Initialize the TWI hardware registers. */ static void __devinit at91_twi_hwinit(void) { at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */ at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */ /* Set Master mode; Atmel suggests disabling slave mode */ at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN | AT91_TWI_SVDIS); at91_twi_clock_dividers(); } /* * Poll the i2c status register until the specified bit is set or a NACK * occurs. Returns 0 if timed out (50 msec). If nack_seen_p is non-NULL * then write 0 to it first, then if the NACK bit is set in the status * register then write 1 to it and immediately return with a value of 1. */ static short at91_poll_status(unsigned long bit, int * nack_seen_p) { int loop_cntr = 5000; unsigned long stat; if (nack_seen_p) *nack_seen_p = 0; if (clockrate <= 20000) loop_cntr = 100; do { if (clockrate <= 20000) udelay(100); else if (clockrate <= 100000) udelay(10); else udelay(3); stat = at91_twi_read(AT91_TWI_SR); if ((stat & AT91_TWI_NACK) && nack_seen_p) { *nack_seen_p = 1; return 1; } } while (!(stat & bit) && (--loop_cntr > 0)); return (loop_cntr > 0); } static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) { int nack_seen = 0; int sent_stop = 0; /* Send Start */ if (1 == length) { at91_twi_write(AT91_TWI_CR, AT91_TWI_START | AT91_TWI_STOP); sent_stop = 1; } else at91_twi_write(AT91_TWI_CR, AT91_TWI_START); /* Read data */ while (length--) { /* send Stop before reading last byte (if not already done) */ if ((0 == length) && (0 == sent_stop)) at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); if (!at91_poll_status(AT91_TWI_RXRDY, &nack_seen)) { dev_dbg(&adap->dev, "RXRDY timeout\n"); return -ETIMEDOUT; } else if (nack_seen) { dev_dbg(&adap->dev, "read NACKed\n"); /* NACK supplies Stop */ return -EREMOTEIO; } *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff); } return 0; } static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) { int nack_seen = 0; /* Load first byte into transmitter */ at91_twi_write(AT91_TWI_THR, *buf++); /* Send Start [AT91SAM9G20 does not need this on write] */ at91_twi_write(AT91_TWI_CR, AT91_TWI_START); do { if (!at91_poll_status(AT91_TWI_TXRDY, &nack_seen)) { dev_dbg(&adap->dev, "TXRDY timeout\n"); /* Set Master mode again */ at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); return -ETIMEDOUT; } else if (nack_seen) { dev_dbg(&adap->dev, "write NACKed\n"); /* NACK supplies Stop */ return -EREMOTEIO; } length--; /* byte was transmitted */ if (length > 0) /* more data to send? */ at91_twi_write(AT91_TWI_THR, *buf++); } while (length); /* Send Stop [AT91SAM9G20 does not need this on write] */ at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); return 0; } /* * Generic i2c master transfer entrypoint. * * Note: We do not use Atmel's feature of storing the "internal device address". * Instead the "internal device address" has to be written using a separate * i2c message. * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html * [dpg] By 2010 silicon bugs should be fixed, will need IADR for 10 bit device address */ static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) { int i, ret; int nack_seen = 0; if (prev_clockrate != clockrate) { dev_dbg(&adap->dev, "at91_xfer: prev_clockrate=%u " "clockrate=%u, change\n", prev_clockrate, clockrate); at91_twi_clock_dividers(); msleep(1); /* let things settle */ } dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); for (i = 0; i < num; i++) { dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, pmsg->flags & I2C_M_RD ? "read" : "writ", pmsg->len, pmsg->len > 1 ? "s" : "", pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16) | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); if (pmsg->len && pmsg->buf) { /* sanity check */ if (pmsg->flags & I2C_M_RD) ret = xfer_read(adap, pmsg->buf, pmsg->len); else ret = xfer_write(adap, pmsg->buf, pmsg->len); if (ret) { if ((I2C_M_IGNORE_NAK & pmsg->flags) && (-EREMOTEIO == ret)) { dev_dbg(&adap->dev, "transfer " "NACKed, skip to next\n"); pmsg++; continue; } else return ret; } /* Wait until transfer is finished */ if (!at91_poll_status(AT91_TWI_TXCOMP, &nack_seen)) { dev_dbg(&adap->dev, "TXCOMP timeout\n"); return -ETIMEDOUT; } else if (nack_seen) { dev_dbg(&adap->dev, "TXCOMP NACKed\n"); return -EREMOTEIO; } } dev_dbg(&adap->dev, "transfer complete\n"); pmsg++; /* next message */ } return i; } /* * Return list of supported functionality. */ static u32 at91_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static struct i2c_algorithm at91_algorithm = { .master_xfer = at91_xfer, .functionality = at91_func, }; /* * Main initialization routine. */ static int __devinit at91_i2c_probe(struct platform_device *pdev) { struct i2c_adapter *adapter; struct resource *res; int rc; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENXIO; if (!request_mem_region(res->start, resource_size(res), "at91_i2c")) return -EBUSY; twi_base = ioremap(res->start, resource_size(res)); if (!twi_base) { rc = -ENOMEM; goto fail0; } twi_clk = clk_get(NULL, "twi_clk"); if (IS_ERR(twi_clk)) { dev_err(&pdev->dev, "no clock defined\n"); rc = -ENODEV; goto fail1; } adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); if (adapter == NULL) { dev_err(&pdev->dev, "can't allocate inteface!\n"); rc = -ENOMEM; goto fail2; } snprintf(adapter->name, sizeof(adapter->name), "AT91"); adapter->algo = &at91_algorithm; adapter->class = I2C_CLASS_HWMON; adapter->dev.parent = &pdev->dev; /* adapter->id == 0 ... only one TWI controller for now */ platform_set_drvdata(pdev, adapter); clk_enable(twi_clk); /* enable peripheral clock */ at91_twi_hwinit(); /* initialize TWI controller */ rc = i2c_add_numbered_adapter(adapter); if (rc) { dev_err(&pdev->dev, "Adapter %s registration failed\n", adapter->name); goto fail3; } dev_info(&pdev->dev, "AT91 TWI (I2C) bus driver [SCL %d Hz]\n", clockrate); return 0; fail3: platform_set_drvdata(pdev, NULL); kfree(adapter); clk_disable(twi_clk); fail2: clk_put(twi_clk); fail1: iounmap(twi_base); fail0: release_mem_region(res->start, resource_size(res)); return rc; } static int __devexit at91_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); struct resource *res; int rc; rc = i2c_del_adapter(adapter); platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(twi_base); release_mem_region(res->start, resource_size(res)); clk_disable(twi_clk); /* disable peripheral clock */ clk_put(twi_clk); return rc; } #ifdef CONFIG_PM /* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */ static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) { clk_disable(twi_clk); return 0; } static int at91_i2c_resume(struct platform_device *pdev) { return clk_enable(twi_clk); } #else #define at91_i2c_suspend NULL #define at91_i2c_resume NULL #endif /* I2C clock speed, in Hz 0-400kHz*/ module_param(clockrate, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(clockrate, "SCL clock rate, 1000 to 400000 Hz (def: 100 kHz)"); /* work with "modprobe at91_i2c" from hotplugging or coldplugging */ MODULE_ALIAS("platform:at91_i2c"); static struct platform_driver at91_i2c_driver = { .probe = at91_i2c_probe, .remove = __devexit_p(at91_i2c_remove), .suspend = at91_i2c_suspend, .resume = at91_i2c_resume, .driver = { .name = "at91_i2c", .owner = THIS_MODULE, }, }; static int __init at91_i2c_init(void) { return platform_driver_register(&at91_i2c_driver); } static void __exit at91_i2c_exit(void) { platform_driver_unregister(&at91_i2c_driver); } module_init(at91_i2c_init); module_exit(at91_i2c_exit); MODULE_AUTHOR("Rick Bronson"); MODULE_DESCRIPTION("I2C (TWI) master driver for Atmel AT91"); MODULE_LICENSE("GPL");