linux-bk/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/config.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/sched.h>
  20#include <linux/init.h>
  21#include <linux/pci.h>
  22#include <asm/io.h>
  23#ifdef CONFIG_FSL_OCP
  24#include <asm/ocp.h>
  25#define FSL_I2C_DEV_SEPARATE_DFSRR FS_I2C_SEPARATE_DFSRR
  26#define FSL_I2C_DEV_CLOCK_5200 FS_I2C_CLOCK_5200
  27#else
  28#include <linux/fsl_devices.h>
  29#endif
  30#include <linux/i2c.h>
  31#include <linux/interrupt.h>
  32#include <linux/delay.h>
  33
  34#define MPC_I2C_ADDR  0x00
  35#define MPC_I2C_FDR     0x04
  36#define MPC_I2C_CR      0x08
  37#define MPC_I2C_SR      0x0c
  38#define MPC_I2C_DR      0x10
  39#define MPC_I2C_DFSRR 0x14
  40#define MPC_I2C_REGION 0x20
  41
  42#define CCR_MEN  0x80
  43#define CCR_MIEN 0x40
  44#define CCR_MSTA 0x20
  45#define CCR_MTX  0x10
  46#define CCR_TXAK 0x08
  47#define CCR_RSTA 0x04
  48
  49#define CSR_MCF  0x80
  50#define CSR_MAAS 0x40
  51#define CSR_MBB  0x20
  52#define CSR_MAL  0x10
  53#define CSR_SRW  0x04
  54#define CSR_MIF  0x02
  55#define CSR_RXAK 0x01
  56
  57struct mpc_i2c {
  58        char *base;
  59        u32 interrupt;
  60        wait_queue_head_t queue;
  61        struct i2c_adapter adap;
  62        int irq;
  63        u32 flags;
  64};
  65
  66static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
  67{
  68        writeb(x, i2c->base + MPC_I2C_CR);
  69}
  70
  71static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
  72{
  73        struct mpc_i2c *i2c = dev_id;
  74        if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
  75                /* Read again to allow register to stabilise */
  76                i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
  77                writeb(0, i2c->base + MPC_I2C_SR);
  78                wake_up_interruptible(&i2c->queue);
  79        }
  80        return IRQ_HANDLED;
  81}
  82
  83static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
  84{
  85        unsigned long orig_jiffies = jiffies;
  86        u32 x;
  87        int result = 0;
  88
  89        if (i2c->irq == 0)
  90        {
  91                while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
  92                        schedule();
  93                        if (time_after(jiffies, orig_jiffies + timeout)) {
  94                                pr_debug("I2C: timeout\n");
  95                                result = -EIO;
  96                                break;
  97                        }
  98                }
  99                x = readb(i2c->base + MPC_I2C_SR);
 100                writeb(0, i2c->base + MPC_I2C_SR);
 101        } else {
 102                /* Interrupt mode */
 103                result = wait_event_interruptible_timeout(i2c->queue,
 104                        (i2c->interrupt & CSR_MIF), timeout * HZ);
 105
 106                if (unlikely(result < 0))
 107                        pr_debug("I2C: wait interrupted\n");
 108                else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
 109                        pr_debug("I2C: wait timeout\n");
 110                        result = -ETIMEDOUT;
 111                }
 112
 113                x = i2c->interrupt;
 114                i2c->interrupt = 0;
 115        }
 116
 117        if (result < 0)
 118                return result;
 119
 120        if (!(x & CSR_MCF)) {
 121                pr_debug("I2C: unfinished\n");
 122                return -EIO;
 123        }
 124
 125        if (x & CSR_MAL) {
 126                pr_debug("I2C: MAL\n");
 127                return -EIO;
 128        }
 129
 130        if (writing && (x & CSR_RXAK)) {
 131                pr_debug("I2C: No RXAK\n");
 132                /* generate stop */
 133                writeccr(i2c, CCR_MEN);
 134                return -EIO;
 135        }
 136        return 0;
 137}
 138
 139static void mpc_i2c_setclock(struct mpc_i2c *i2c)
 140{
 141        /* Set clock and filters */
 142        if (i2c->flags & FSL_I2C_DEV_SEPARATE_DFSRR) {
 143                writeb(0x31, i2c->base + MPC_I2C_FDR);
 144                writeb(0x10, i2c->base + MPC_I2C_DFSRR);
 145        } else if (i2c->flags & FSL_I2C_DEV_CLOCK_5200)
 146                writeb(0x3f, i2c->base + MPC_I2C_FDR);
 147        else
 148                writel(0x1031, i2c->base + MPC_I2C_FDR);
 149}
 150
 151static void mpc_i2c_start(struct mpc_i2c *i2c)
 152{
 153        /* Clear arbitration */
 154        writeb(0, i2c->base + MPC_I2C_SR);
 155        /* Start with MEN */
 156        writeccr(i2c, CCR_MEN);
 157}
 158
 159static void mpc_i2c_stop(struct mpc_i2c *i2c)
 160{
 161        writeccr(i2c, CCR_MEN);
 162}
 163
 164static int mpc_write(struct mpc_i2c *i2c, int target,
 165                     const u8 * data, int length, int restart)
 166{
 167        int i;
 168        unsigned timeout = i2c->adap.timeout;
 169        u32 flags = restart ? CCR_RSTA : 0;
 170
 171        /* Start with MEN */
 172        if (!restart)
 173                writeccr(i2c, CCR_MEN);
 174        /* Start as master */
 175        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 176        /* Write target byte */
 177        writeb((target << 1), i2c->base + MPC_I2C_DR);
 178
 179        if (i2c_wait(i2c, timeout, 1) < 0)
 180                return -1;
 181
 182        for (i = 0; i < length; i++) {
 183                /* Write data byte */
 184                writeb(data[i], i2c->base + MPC_I2C_DR);
 185
 186                if (i2c_wait(i2c, timeout, 1) < 0)
 187                        return -1;
 188        }
 189
 190        return 0;
 191}
 192
 193static int mpc_read(struct mpc_i2c *i2c, int target,
 194                    u8 * data, int length, int restart)
 195{
 196        unsigned timeout = i2c->adap.timeout;
 197        int i;
 198        u32 flags = restart ? CCR_RSTA : 0;
 199
 200        /* Start with MEN */
 201        if (!restart)
 202                writeccr(i2c, CCR_MEN);
 203        /* Switch to read - restart */
 204        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
 205        /* Write target address byte - this time with the read flag set */
 206        writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
 207
 208        if (i2c_wait(i2c, timeout, 1) < 0)
 209                return -1;
 210
 211        if (length) {
 212                if (length == 1)
 213                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
 214                else
 215                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
 216                /* Dummy read */
 217                readb(i2c->base + MPC_I2C_DR);
 218        }
 219
 220        for (i = 0; i < length; i++) {
 221                if (i2c_wait(i2c, timeout, 0) < 0)
 222                        return -1;
 223
 224                /* Generate txack on next to last byte */
 225                if (i == length - 2)
 226                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
 227                /* Generate stop on last byte */
 228                if (i == length - 1)
 229                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
 230                data[i] = readb(i2c->base + MPC_I2C_DR);
 231        }
 232
 233        return length;
 234}
 235
 236static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 237{
 238        struct i2c_msg *pmsg;
 239        int i;
 240        int ret = 0;
 241        unsigned long orig_jiffies = jiffies;
 242        struct mpc_i2c *i2c = i2c_get_adapdata(adap);
 243
 244        mpc_i2c_start(i2c);
 245
 246        /* Allow bus up to 1s to become not busy */
 247        while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
 248                if (signal_pending(current)) {
 249                        pr_debug("I2C: Interrupted\n");
 250                        return -EINTR;
 251                }
 252                if (time_after(jiffies, orig_jiffies + HZ)) {
 253                        pr_debug("I2C: timeout\n");
 254                        return -EIO;
 255                }
 256                schedule();
 257        }
 258
 259        for (i = 0; ret >= 0 && i < num; i++) {
 260                pmsg = &msgs[i];
 261                pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n",
 262                         pmsg->flags & I2C_M_RD ? "read" : "write",
 263                         pmsg->len, pmsg->addr, i + 1, num);
 264                if (pmsg->flags & I2C_M_RD)
 265                        ret =
 266                            mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
 267                else
 268                        ret =
 269                            mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
 270        }
 271        mpc_i2c_stop(i2c);
 272        return (ret < 0) ? ret : num;
 273}
 274
 275static u32 mpc_functionality(struct i2c_adapter *adap)
 276{
 277        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 278}
 279
 280static struct i2c_algorithm mpc_algo = {
 281        .name = "MPC algorithm",
 282        .id = I2C_ALGO_MPC107,
 283        .master_xfer = mpc_xfer,
 284        .functionality = mpc_functionality,
 285};
 286
 287static struct i2c_adapter mpc_ops = {
 288        .owner = THIS_MODULE,
 289        .name = "MPC adapter",
 290        .id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
 291        .algo = &mpc_algo,
 292        .class = I2C_CLASS_HWMON,
 293        .timeout = 1,
 294        .retries = 1
 295};
 296
 297#ifdef CONFIG_FSL_OCP
 298static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
 299{
 300        int result = 0;
 301        struct mpc_i2c *i2c;
 302
 303        if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
 304                return -ENOMEM;
 305        }
 306        memset(i2c, 0, sizeof(*i2c));
 307
 308        i2c->irq = ocp->def->irq;
 309        i2c->flags = ((struct ocp_fs_i2c_data *)ocp->def->additions)->flags;
 310        init_waitqueue_head(&i2c->queue);
 311
 312        if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) {
 313                printk(KERN_ERR "i2c-mpc - resource unavailable\n");
 314                return -ENODEV;
 315        }
 316
 317        i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION);
 318
 319        if (!i2c->base) {
 320                printk(KERN_ERR "i2c-mpc - failed to map controller\n");
 321                result = -ENOMEM;
 322                goto fail_map;
 323        }
 324
 325        if (i2c->irq != OCP_IRQ_NA)
 326        {
 327                if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
 328                                          0, "i2c-mpc", i2c)) < 0) {
 329                        printk(KERN_ERR
 330                               "i2c-mpc - failed to attach interrupt\n");
 331                        goto fail_irq;
 332                }
 333        } else
 334                i2c->irq = 0;
 335
 336        i2c->adap = mpc_ops;
 337        i2c_set_adapdata(&i2c->adap, i2c);
 338
 339        if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
 340                printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
 341                goto fail_add;
 342        }
 343
 344        mpc_i2c_setclock(i2c);
 345        ocp_set_drvdata(ocp, i2c);
 346        return result;
 347
 348      fail_add:
 349        if (ocp->def->irq != OCP_IRQ_NA)
 350                free_irq(ocp->def->irq, 0);
 351      fail_irq:
 352        iounmap(i2c->base);
 353      fail_map:
 354        release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
 355        kfree(i2c);
 356        return result;
 357}
 358static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
 359{
 360        struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
 361        ocp_set_drvdata(ocp, NULL);
 362        i2c_del_adapter(&i2c->adap);
 363
 364        if (ocp->def->irq != OCP_IRQ_NA)
 365                free_irq(i2c->irq, i2c);
 366        iounmap(i2c->base);
 367        release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
 368        kfree(i2c);
 369}
 370
 371static struct ocp_device_id mpc_iic_ids[] __devinitdata = {
 372        {.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC},
 373        {.vendor = OCP_VENDOR_INVALID}
 374};
 375
 376MODULE_DEVICE_TABLE(ocp, mpc_iic_ids);
 377
 378static struct ocp_driver mpc_iic_driver = {
 379        .name = "iic",
 380        .id_table = mpc_iic_ids,
 381        .probe = mpc_i2c_probe,
 382        .remove = __devexit_p(mpc_i2c_remove)
 383};
 384
 385static int __init iic_init(void)
 386{
 387        return ocp_register_driver(&mpc_iic_driver);
 388}
 389
 390static void __exit iic_exit(void)
 391{
 392        ocp_unregister_driver(&mpc_iic_driver);
 393}
 394
 395module_init(iic_init);
 396module_exit(iic_exit);
 397#else
 398static int fsl_i2c_probe(struct device *device)
 399{
 400        int result = 0;
 401        struct mpc_i2c *i2c;
 402        struct platform_device *pdev = to_platform_device(device);
 403        struct fsl_i2c_platform_data *pdata;
 404        struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 405
 406        pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
 407
 408        if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
 409                return -ENOMEM;
 410        }
 411        memset(i2c, 0, sizeof(*i2c));
 412
 413        i2c->irq = platform_get_irq(pdev, 0);
 414        i2c->flags = pdata->device_flags;
 415        init_waitqueue_head(&i2c->queue);
 416
 417        i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
 418
 419        if (!i2c->base) {
 420                printk(KERN_ERR "i2c-mpc - failed to map controller\n");
 421                result = -ENOMEM;
 422                goto fail_map;
 423        }
 424
 425        if (i2c->irq != 0)
 426                if ((result = request_irq(i2c->irq, mpc_i2c_isr,
 427                                          0, "fsl-i2c", i2c)) < 0) {
 428                        printk(KERN_ERR
 429                               "i2c-mpc - failed to attach interrupt\n");
 430                        goto fail_irq;
 431                }
 432
 433        i2c->adap = mpc_ops;
 434        i2c_set_adapdata(&i2c->adap, i2c);
 435        i2c->adap.dev.parent = &pdev->dev;
 436        if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
 437                printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
 438                goto fail_add;
 439        }
 440
 441        mpc_i2c_setclock(i2c);
 442        dev_set_drvdata(device, i2c);
 443        return result;
 444
 445      fail_add:
 446        if (i2c->irq != 0)
 447                free_irq(i2c->irq, 0);
 448      fail_irq:
 449        iounmap(i2c->base);
 450      fail_map:
 451        kfree(i2c);
 452        return result;
 453};
 454
 455static int fsl_i2c_remove(struct device *device)
 456{
 457        struct mpc_i2c *i2c = dev_get_drvdata(device);
 458
 459        dev_set_drvdata(device, NULL);
 460        i2c_del_adapter(&i2c->adap);
 461
 462        if (i2c->irq != 0)
 463                free_irq(i2c->irq, i2c);
 464
 465        iounmap(i2c->base);
 466        kfree(i2c);
 467        return 0;
 468};
 469
 470/* Structure for a device driver */
 471static struct device_driver fsl_i2c_driver = {
 472        .name = "fsl-i2c",
 473        .bus = &platform_bus_type,
 474        .probe = fsl_i2c_probe,
 475        .remove = fsl_i2c_remove,
 476};
 477
 478static int __init fsl_i2c_init(void)
 479{
 480        return driver_register(&fsl_i2c_driver);
 481}
 482
 483static void __exit fsl_i2c_exit(void)
 484{
 485        driver_unregister(&fsl_i2c_driver);
 486}
 487
 488module_init(fsl_i2c_init);
 489module_exit(fsl_i2c_exit);
 490
 491#endif /* CONFIG_FSL_OCP */
 492
 493MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
 494MODULE_DESCRIPTION
 495    ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
 496MODULE_LICENSE("GPL");
 497
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.