linux/drivers/i2c/busses/i2c-mpc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003-2004
   3 * Humboldt Solutions Ltd, adrian@humboldt.co.uk.
   4
   5 * This is a combined i2c adapter and algorithm driver for the
   6 * MPC107/Tsi107 PowerPC northbridge and processors that include
   7 * the same I2C unit (8240, 8245, 85xx).
   8 *
   9 * Release 0.8
  10 *
  11 * This file is licensed under the terms of the GNU General Public
  12 * License version 2. This program is licensed "as is" without any
  13 * warranty of any kind, whether express or implied.
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/sched.h>
  19#include <linux/init.h>
  20#include <linux/platform_device.h>
  21
  22#include <asm/io.h>
  23#include <linux/fsl_devices.h>
  24#include <linux/i2c.h>
  25#include <linux/interrupt.h>
  26#include <linux/delay.h>
  27
  28#define MPC_I2C_ADDR  0x00
  29#define MPC_I2C_FDR     0x04
  30#define MPC_I2C_CR      0x08
  31#define MPC_I2C_SR      0x0c
  32#define MPC_I2C_DR      0x10
  33#define MPC_I2C_DFSRR 0x14
  34#define MPC_I2C_REGION 0x20
  35
  36#define CCR_MEN  0x80
  37#define CCR_MIEN 0x40
  38#define CCR_MSTA 0x20
  39#define CCR_MTX  0x10
  40#define CCR_TXAK 0x08
  41#define CCR_RSTA 0x04
  42
  43#define CSR_MCF  0x80
  44#define CSR_MAAS 0x40
  45#define CSR_MBB  0x20
  46#define CSR_MAL  0x10
  47#define CSR_SRW  0x04
  48#define CSR_MIF  0x02
  49#define CSR_RXAK 0x01
  50
  51struct mpc_i2c {
  52        void __iomem *base;
  53        u32 interrupt;
  54        wait_queue_head_t queue;
  55        struct i2c_adapter adap;
  56        int irq;
  57        u32 flags;
  58};
  59
  60static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
  61{
  62        writeb(x, i2c->base + MPC_I2C_CR);
  63}
  64
  65static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
  66{
  67        struct mpc_i2c *i2c = dev_id;
  68        if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
  69                /* Read again to allow register to stabilise */
  70                i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
  71                writeb(0, i2c->base + MPC_I2C_SR);
  72                wake_up_interruptible(&i2c->queue);
  73        }
  74        return IRQ_HANDLED;
  75}
  76
  77/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
  78 * the bus, because it wants to send ACK.
  79 * Following sequence of enabling/disabling and sending start/stop generates
  80 * the pulse, so it's all OK.
  81 */
  82static void mpc_i2c_fixup(struct mpc_i2c *i2c)
  83{
  84        writeccr(i2c, 0);
  85        udelay(30);
  86        writeccr(i2c, CCR_MEN);
  87        udelay(30);
  88        writeccr(i2c, CCR_MSTA | CCR_MTX);
  89        udelay(30);
  90        writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
  91        udelay(30);
  92        writeccr(i2c, CCR_MEN);
  93        udelay(30);
  94}
  95
  96static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
  97{
  98        unsigned long orig_jiffies = jiffies;
  99        u32 x;
 100        int result = 0;
 101
 102        if (i2c->irq == 0)
 103        {
 104                while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
 105                        schedule();
 106                        if (time_after(jiffies, orig_jiffies + timeout)) {
 107                                pr_debug("I2C: timeout\n");
 108                                writeccr(i2c, 0);
 109                                result = -EIO;
 110                                break;
 111                        }
 112                }
 113                x = readb(i2c->base + MPC_I2C_SR);
 114                writeb(0, i2c->base + MPC_I2C_SR);
 115        } else {
 116                /* Interrupt mode */
 117                result = wait_event_interruptible_timeout(i2c->queue,
 118                        (i2c->interrupt & CSR_MIF), timeout * HZ);
 119
 120                if (unlikely(result < 0)) {
 121                        pr_debug("I2C: wait interrupted\n");
 122                        writeccr(i2c, 0);
 123                } else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
 124                        pr_debug("I2C: wait timeout\n");
 125                        writeccr(i2c, 0);
 126                        result = -ETIMEDOUT;
 127                }
 128
 129                x = i2c->interrupt;
 130                i2c->interrupt = 0;
 131        }
 132
 133        if (result < 0)
 134                return result;
 135
 136        if (!(x & CSR_MCF)) {
 137                pr_debug("I2C: unfinished\n");
 138                return -EIO;
 139        }
 140
 141        if (x & CSR_MAL) {
 142                pr_debug("I2C: MAL\n");
 143                return -EIO;
 144        }
 145
 146        if (writing && (x & CSR_RXAK)) {
 147                pr_debug("I2C: No RXAK\n");
 148                /* generate stop */
 149                writeccr(i2c, CCR_MEN);
 150                return -EIO;
 151        }
 152        return 0;
 153}
 154
 155static void mpc_i2c_setclock(struct mpc_i2c *i2c)
 156{
 157        /* Set clock and filters */
 158        if (i2c->flags & FSL_I2C_DEV_SEPARATE_DFSRR) {
 159                writeb(0x31, i2c->base + MPC_I2C_FDR);
 160                writeb(0x10, i2c->base + MPC_I2C_DFSRR);
 161        } else if (i2c->flags & FSL_I2C_DEV_CLOCK_5200)
 162                writeb(0x3f, i2c->base + MPC_I2C_FDR);
 163        else
 164                writel(0x1031, i2c->base + MPC_I2C_FDR);
 165}
 166
 167static void mpc_i2c_start(struct mpc_i2c *i2c)
 168{
 169        /* Clear arbitration */
 170        writeb(0, i2c->base + MPC_I2C_SR);
 171        /* Start with MEN */
 172        writeccr(i2c, CCR_MEN);
 173}
 174
 175static void mpc_i2c_stop(struct mpc_i2c *i2c)
 176{
 177        writeccr(i2c, CCR_MEN);
 178}
 179
 180static int mpc_write(struct mpc_i2c *i2c, int target,
 181                     const u8 * data, int length, int restart)
 182{
 183        int i, result;
 184        unsigned timeout = i2c->adap.timeout;
 185        u32 flags = restart ? CCR_RSTA : 0;
 186
 187        /* Start with MEN */
 188        if (!restart)
 189                writeccr(i2c, CCR_MEN);
 190        /* Start as master */
 191        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 192        /* Write target byte */
 193        writeb((target << 1), i2c->base + MPC_I2C_DR);
 194
 195        result = i2c_wait(i2c, timeout, 1);
 196        if (result < 0)
 197                return result;
 198
 199        for (i = 0; i < length; i++) {
 200                /* Write data byte */
 201                writeb(data[i], i2c->base + MPC_I2C_DR);
 202
 203                result = i2c_wait(i2c, timeout, 1);
 204                if (result < 0)
 205                        return result;
 206        }
 207
 208        return 0;
 209}
 210
 211static int mpc_read(struct mpc_i2c *i2c, int target,
 212                    u8 * data, int length, int restart)
 213{
 214        unsigned timeout = i2c->adap.timeout;
 215        int i, result;
 216        u32 flags = restart ? CCR_RSTA : 0;
 217
 218        /* Start with MEN */
 219        if (!restart)
 220                writeccr(i2c, CCR_MEN);
 221        /* Switch to read - restart */
 222        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 223        /* Write target address byte - this time with the read flag set */
 224        writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
 225
 226        result = i2c_wait(i2c, timeout, 1);
 227        if (result < 0)
 228                return result;
 229
 230        if (length) {
 231                if (length == 1)
 232                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
 233                else
 234                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
 235                /* Dummy read */
 236                readb(i2c->base + MPC_I2C_DR);
 237        }
 238
 239        for (i = 0; i < length; i++) {
 240                result = i2c_wait(i2c, timeout, 0);
 241                if (result < 0)
 242                        return result;
 243
 244                /* Generate txack on next to last byte */
 245                if (i == length - 2)
 246                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
 247                /* Generate stop on last byte */
 248                if (i == length - 1)
 249                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
 250                data[i] = readb(i2c->base + MPC_I2C_DR);
 251        }
 252
 253        return length;
 254}
 255
 256static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 257{
 258        struct i2c_msg *pmsg;
 259        int i;
 260        int ret = 0;
 261        unsigned long orig_jiffies = jiffies;
 262        struct mpc_i2c *i2c = i2c_get_adapdata(adap);
 263
 264        mpc_i2c_start(i2c);
 265
 266        /* Allow bus up to 1s to become not busy */
 267        while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
 268                if (signal_pending(current)) {
 269                        pr_debug("I2C: Interrupted\n");
 270                        writeccr(i2c, 0);
 271                        return -EINTR;
 272                }
 273                if (time_after(jiffies, orig_jiffies + HZ)) {
 274                        pr_debug("I2C: timeout\n");
 275                        if (readb(i2c->base + MPC_I2C_SR) ==
 276                            (CSR_MCF | CSR_MBB | CSR_RXAK))
 277                                mpc_i2c_fixup(i2c);
 278                        return -EIO;
 279                }
 280                schedule();
 281        }
 282
 283        for (i = 0; ret >= 0 && i < num; i++) {
 284                pmsg = &msgs[i];
 285                pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n",
 286                         pmsg->flags & I2C_M_RD ? "read" : "write",
 287                         pmsg->len, pmsg->addr, i + 1, num);
 288                if (pmsg->flags & I2C_M_RD)
 289                        ret =
 290                            mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
 291                else
 292                        ret =
 293                            mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
 294        }
 295        mpc_i2c_stop(i2c);
 296        return (ret < 0) ? ret : num;
 297}
 298
 299static u32 mpc_functionality(struct i2c_adapter *adap)
 300{
 301        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 302}
 303
 304static const struct i2c_algorithm mpc_algo = {
 305        .master_xfer = mpc_xfer,
 306        .functionality = mpc_functionality,
 307};
 308
 309static struct i2c_adapter mpc_ops = {
 310        .owner = THIS_MODULE,
 311        .name = "MPC adapter",
 312        .id = I2C_HW_MPC107,
 313        .algo = &mpc_algo,
 314        .class = I2C_CLASS_HWMON,
 315        .timeout = 1,
 316};
 317
 318static int fsl_i2c_probe(struct platform_device *pdev)
 319{
 320        int result = 0;
 321        struct mpc_i2c *i2c;
 322        struct fsl_i2c_platform_data *pdata;
 323        struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 324
 325        pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
 326
 327        i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
 328        if (!i2c)
 329                return -ENOMEM;
 330
 331        i2c->irq = platform_get_irq(pdev, 0);
 332        if (i2c->irq < 0) {
 333                result = -ENXIO;
 334                goto fail_get_irq;
 335        }
 336        i2c->flags = pdata->device_flags;
 337        init_waitqueue_head(&i2c->queue);
 338
 339        i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
 340
 341        if (!i2c->base) {
 342                printk(KERN_ERR "i2c-mpc - failed to map controller\n");
 343                result = -ENOMEM;
 344                goto fail_map;
 345        }
 346
 347        if (i2c->irq != 0)
 348                if ((result = request_irq(i2c->irq, mpc_i2c_isr,
 349                                          IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
 350                        printk(KERN_ERR
 351                               "i2c-mpc - failed to attach interrupt\n");
 352                        goto fail_irq;
 353                }
 354
 355        mpc_i2c_setclock(i2c);
 356        platform_set_drvdata(pdev, i2c);
 357
 358        i2c->adap = mpc_ops;
 359        i2c->adap.nr = pdev->id;
 360        i2c_set_adapdata(&i2c->adap, i2c);
 361        i2c->adap.dev.parent = &pdev->dev;
 362        if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
 363                printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
 364                goto fail_add;
 365        }
 366
 367        return result;
 368
 369      fail_add:
 370        if (i2c->irq != 0)
 371                free_irq(i2c->irq, i2c);
 372      fail_irq:
 373        iounmap(i2c->base);
 374      fail_map:
 375      fail_get_irq:
 376        kfree(i2c);
 377        return result;
 378};
 379
 380static int fsl_i2c_remove(struct platform_device *pdev)
 381{
 382        struct mpc_i2c *i2c = platform_get_drvdata(pdev);
 383
 384        i2c_del_adapter(&i2c->adap);
 385        platform_set_drvdata(pdev, NULL);
 386
 387        if (i2c->irq != 0)
 388                free_irq(i2c->irq, i2c);
 389
 390        iounmap(i2c->base);
 391        kfree(i2c);
 392        return 0;
 393};
 394
 395/* Structure for a device driver */
 396static struct platform_driver fsl_i2c_driver = {
 397        .probe = fsl_i2c_probe,
 398        .remove = fsl_i2c_remove,
 399        .driver = {
 400                .owner = THIS_MODULE,
 401                .name = "fsl-i2c",
 402        },
 403};
 404
 405static int __init fsl_i2c_init(void)
 406{
 407        return platform_driver_register(&fsl_i2c_driver);
 408}
 409
 410static void __exit fsl_i2c_exit(void)
 411{
 412        platform_driver_unregister(&fsl_i2c_driver);
 413}
 414
 415module_init(fsl_i2c_init);
 416module_exit(fsl_i2c_exit);
 417
 418MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
 419MODULE_DESCRIPTION
 420    ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
 421MODULE_LICENSE("GPL");
 422
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.