linux/drivers/i2c/busses/i2c-at91.c
<<
>>
Prefs
   1/*
   2    i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
   3
   4    Copyright (C) 2004 Rick Bronson
   5    Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
   6
   7    Borrowed heavily from original work by:
   8    Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
   9
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 2 of the License, or
  13    (at your option) any later version.
  14*/
  15
  16#include <linux/module.h>
  17#include <linux/kernel.h>
  18#include <linux/err.h>
  19#include <linux/slab.h>
  20#include <linux/types.h>
  21#include <linux/delay.h>
  22#include <linux/i2c.h>
  23#include <linux/init.h>
  24#include <linux/clk.h>
  25#include <linux/platform_device.h>
  26#include <linux/io.h>
  27
  28#include <mach/at91_twi.h>
  29#include <mach/board.h>
  30#include <mach/cpu.h>
  31
  32#define TWI_CLOCK               100000          /* Hz. max 400 Kbits/sec */
  33
  34
  35static struct clk *twi_clk;
  36static void __iomem *twi_base;
  37
  38#define at91_twi_read(reg)              __raw_readl(twi_base + (reg))
  39#define at91_twi_write(reg, val)        __raw_writel((val), twi_base + (reg))
  40
  41
  42/*
  43 * Initialize the TWI hardware registers.
  44 */
  45static void __devinit at91_twi_hwinit(void)
  46{
  47        unsigned long cdiv, ckdiv;
  48
  49        at91_twi_write(AT91_TWI_IDR, 0xffffffff);       /* Disable all interrupts */
  50        at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST);    /* Reset peripheral */
  51        at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN);     /* Set Master mode */
  52
  53        /* Calcuate clock dividers */
  54        cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
  55        cdiv = cdiv + 1;        /* round up */
  56        ckdiv = 0;
  57        while (cdiv > 255) {
  58                ckdiv++;
  59                cdiv = cdiv >> 1;
  60        }
  61
  62        if (cpu_is_at91rm9200()) {                      /* AT91RM9200 Errata #22 */
  63                if (ckdiv > 5) {
  64                        printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
  65                        ckdiv = 5;
  66                }
  67        }
  68
  69        at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
  70}
  71
  72/*
  73 * Poll the i2c status register until the specified bit is set.
  74 * Returns 0 if timed out (100 msec).
  75 */
  76static short at91_poll_status(unsigned long bit)
  77{
  78        int loop_cntr = 10000;
  79
  80        do {
  81                udelay(10);
  82        } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
  83
  84        return (loop_cntr > 0);
  85}
  86
  87static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
  88{
  89        /* Send Start */
  90        at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
  91
  92        /* Read data */
  93        while (length--) {
  94                if (!length)    /* need to send Stop before reading last byte */
  95                        at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
  96                if (!at91_poll_status(AT91_TWI_RXRDY)) {
  97                        dev_dbg(&adap->dev, "RXRDY timeout\n");
  98                        return -ETIMEDOUT;
  99                }
 100                *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
 101        }
 102
 103        return 0;
 104}
 105
 106static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
 107{
 108        /* Load first byte into transmitter */
 109        at91_twi_write(AT91_TWI_THR, *buf++);
 110
 111        /* Send Start */
 112        at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
 113
 114        do {
 115                if (!at91_poll_status(AT91_TWI_TXRDY)) {
 116                        dev_dbg(&adap->dev, "TXRDY timeout\n");
 117                        return -ETIMEDOUT;
 118                }
 119
 120                length--;       /* byte was transmitted */
 121
 122                if (length > 0)         /* more data to send? */
 123                        at91_twi_write(AT91_TWI_THR, *buf++);
 124        } while (length);
 125
 126        /* Send Stop */
 127        at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
 128
 129        return 0;
 130}
 131
 132/*
 133 * Generic i2c master transfer entrypoint.
 134 *
 135 * Note: We do not use Atmel's feature of storing the "internal device address".
 136 * Instead the "internal device address" has to be written using a separate
 137 * i2c message.
 138 * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
 139 */
 140static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
 141{
 142        int i, ret;
 143
 144        dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
 145
 146        for (i = 0; i < num; i++) {
 147                dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
 148                        pmsg->flags & I2C_M_RD ? "read" : "writ",
 149                        pmsg->len, pmsg->len > 1 ? "s" : "",
 150                        pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
 151
 152                at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
 153                        | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
 154
 155                if (pmsg->len && pmsg->buf) {   /* sanity check */
 156                        if (pmsg->flags & I2C_M_RD)
 157                                ret = xfer_read(adap, pmsg->buf, pmsg->len);
 158                        else
 159                                ret = xfer_write(adap, pmsg->buf, pmsg->len);
 160
 161                        if (ret)
 162                                return ret;
 163
 164                        /* Wait until transfer is finished */
 165                        if (!at91_poll_status(AT91_TWI_TXCOMP)) {
 166                                dev_dbg(&adap->dev, "TXCOMP timeout\n");
 167                                return -ETIMEDOUT;
 168                        }
 169                }
 170                dev_dbg(&adap->dev, "transfer complete\n");
 171                pmsg++;         /* next message */
 172        }
 173        return i;
 174}
 175
 176/*
 177 * Return list of supported functionality.
 178 */
 179static u32 at91_func(struct i2c_adapter *adapter)
 180{
 181        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 182}
 183
 184static struct i2c_algorithm at91_algorithm = {
 185        .master_xfer    = at91_xfer,
 186        .functionality  = at91_func,
 187};
 188
 189/*
 190 * Main initialization routine.
 191 */
 192static int __devinit at91_i2c_probe(struct platform_device *pdev)
 193{
 194        struct i2c_adapter *adapter;
 195        struct resource *res;
 196        int rc;
 197
 198        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 199        if (!res)
 200                return -ENXIO;
 201
 202        if (!request_mem_region(res->start, resource_size(res), "at91_i2c"))
 203                return -EBUSY;
 204
 205        twi_base = ioremap(res->start, resource_size(res));
 206        if (!twi_base) {
 207                rc = -ENOMEM;
 208                goto fail0;
 209        }
 210
 211        twi_clk = clk_get(NULL, "twi_clk");
 212        if (IS_ERR(twi_clk)) {
 213                dev_err(&pdev->dev, "no clock defined\n");
 214                rc = -ENODEV;
 215                goto fail1;
 216        }
 217
 218        adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
 219        if (adapter == NULL) {
 220                dev_err(&pdev->dev, "can't allocate inteface!\n");
 221                rc = -ENOMEM;
 222                goto fail2;
 223        }
 224        snprintf(adapter->name, sizeof(adapter->name), "AT91");
 225        adapter->algo = &at91_algorithm;
 226        adapter->class = I2C_CLASS_HWMON;
 227        adapter->dev.parent = &pdev->dev;
 228        /* adapter->id == 0 ... only one TWI controller for now */
 229
 230        platform_set_drvdata(pdev, adapter);
 231
 232        clk_enable(twi_clk);            /* enable peripheral clock */
 233        at91_twi_hwinit();              /* initialize TWI controller */
 234
 235        rc = i2c_add_numbered_adapter(adapter);
 236        if (rc) {
 237                dev_err(&pdev->dev, "Adapter %s registration failed\n",
 238                                adapter->name);
 239                goto fail3;
 240        }
 241
 242        dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
 243        return 0;
 244
 245fail3:
 246        platform_set_drvdata(pdev, NULL);
 247        kfree(adapter);
 248        clk_disable(twi_clk);
 249fail2:
 250        clk_put(twi_clk);
 251fail1:
 252        iounmap(twi_base);
 253fail0:
 254        release_mem_region(res->start, resource_size(res));
 255
 256        return rc;
 257}
 258
 259static int __devexit at91_i2c_remove(struct platform_device *pdev)
 260{
 261        struct i2c_adapter *adapter = platform_get_drvdata(pdev);
 262        struct resource *res;
 263        int rc;
 264
 265        rc = i2c_del_adapter(adapter);
 266        platform_set_drvdata(pdev, NULL);
 267
 268        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 269        iounmap(twi_base);
 270        release_mem_region(res->start, resource_size(res));
 271
 272        clk_disable(twi_clk);           /* disable peripheral clock */
 273        clk_put(twi_clk);
 274
 275        return rc;
 276}
 277
 278#ifdef CONFIG_PM
 279
 280/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
 281
 282static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg)
 283{
 284        clk_disable(twi_clk);
 285        return 0;
 286}
 287
 288static int at91_i2c_resume(struct platform_device *pdev)
 289{
 290        return clk_enable(twi_clk);
 291}
 292
 293#else
 294#define at91_i2c_suspend        NULL
 295#define at91_i2c_resume         NULL
 296#endif
 297
 298/* work with "modprobe at91_i2c" from hotplugging or coldplugging */
 299MODULE_ALIAS("platform:at91_i2c");
 300
 301static struct platform_driver at91_i2c_driver = {
 302        .probe          = at91_i2c_probe,
 303        .remove         = __devexit_p(at91_i2c_remove),
 304        .suspend        = at91_i2c_suspend,
 305        .resume         = at91_i2c_resume,
 306        .driver         = {
 307                .name   = "at91_i2c",
 308                .owner  = THIS_MODULE,
 309        },
 310};
 311
 312static int __init at91_i2c_init(void)
 313{
 314        return platform_driver_register(&at91_i2c_driver);
 315}
 316
 317static void __exit at91_i2c_exit(void)
 318{
 319        platform_driver_unregister(&at91_i2c_driver);
 320}
 321
 322module_init(at91_i2c_init);
 323module_exit(at91_i2c_exit);
 324
 325MODULE_AUTHOR("Rick Bronson");
 326MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
 327MODULE_LICENSE("GPL");
 328