linux/drivers/i2c/busses/i2c-ocores.c
<<
>>
Prefs
   1/*
   2 * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
   3 * (http://www.opencores.org/projects.cgi/web/i2c/overview).
   4 *
   5 * Peter Korsgaard <jacmet@sunsite.dk>
   6 *
   7 * This file is licensed under the terms of the GNU General Public License
   8 * version 2.  This program is licensed "as is" without any warranty of any
   9 * kind, whether express or implied.
  10 */
  11
  12/*
  13 * Device tree configuration:
  14 *
  15 * Required properties:
  16 * - compatible      : "opencores,i2c-ocores"
  17 * - reg             : bus address start and address range size of device
  18 * - interrupts      : interrupt number
  19 * - regstep         : size of device registers in bytes
  20 * - clock-frequency : frequency of bus clock in Hz
  21 * 
  22 * Example:
  23 *
  24 *  i2c0: ocores@a0000000 {
  25 *              compatible = "opencores,i2c-ocores";
  26 *              reg = <0xa0000000 0x8>;
  27 *              interrupts = <10>;
  28 *
  29 *              regstep = <1>;
  30 *              clock-frequency = <20000000>;
  31 *
  32 * -- Devices connected on this I2C bus get
  33 * -- defined here; address- and size-cells
  34 * -- apply to these child devices
  35 *
  36 *              #address-cells = <1>;
  37 *              #size-cells = <0>;
  38 *
  39 *              dummy@60 {
  40 *                     compatible = "dummy";
  41 *                     reg = <60>;
  42 *              };
  43 *  };
  44 *
  45 */
  46
  47#include <linux/kernel.h>
  48#include <linux/module.h>
  49#include <linux/init.h>
  50#include <linux/errno.h>
  51#include <linux/platform_device.h>
  52#include <linux/i2c.h>
  53#include <linux/interrupt.h>
  54#include <linux/wait.h>
  55#include <linux/i2c-ocores.h>
  56#include <linux/slab.h>
  57#include <linux/io.h>
  58
  59struct ocores_i2c {
  60        void __iomem *base;
  61        int regstep;
  62        wait_queue_head_t wait;
  63        struct i2c_adapter adap;
  64        struct i2c_msg *msg;
  65        int pos;
  66        int nmsgs;
  67        int state; /* see STATE_ */
  68        int clock_khz;
  69};
  70
  71/* registers */
  72#define OCI2C_PRELOW            0
  73#define OCI2C_PREHIGH           1
  74#define OCI2C_CONTROL           2
  75#define OCI2C_DATA              3
  76#define OCI2C_CMD               4 /* write only */
  77#define OCI2C_STATUS            4 /* read only, same address as OCI2C_CMD */
  78
  79#define OCI2C_CTRL_IEN          0x40
  80#define OCI2C_CTRL_EN           0x80
  81
  82#define OCI2C_CMD_START         0x91
  83#define OCI2C_CMD_STOP          0x41
  84#define OCI2C_CMD_READ          0x21
  85#define OCI2C_CMD_WRITE         0x11
  86#define OCI2C_CMD_READ_ACK      0x21
  87#define OCI2C_CMD_READ_NACK     0x29
  88#define OCI2C_CMD_IACK          0x01
  89
  90#define OCI2C_STAT_IF           0x01
  91#define OCI2C_STAT_TIP          0x02
  92#define OCI2C_STAT_ARBLOST      0x20
  93#define OCI2C_STAT_BUSY         0x40
  94#define OCI2C_STAT_NACK         0x80
  95
  96#define STATE_DONE              0
  97#define STATE_START             1
  98#define STATE_WRITE             2
  99#define STATE_READ              3
 100#define STATE_ERROR             4
 101
 102static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
 103{
 104        iowrite8(value, i2c->base + reg * i2c->regstep);
 105}
 106
 107static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
 108{
 109        return ioread8(i2c->base + reg * i2c->regstep);
 110}
 111
 112static void ocores_process(struct ocores_i2c *i2c)
 113{
 114        struct i2c_msg *msg = i2c->msg;
 115        u8 stat = oc_getreg(i2c, OCI2C_STATUS);
 116
 117        if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
 118                /* stop has been sent */
 119                oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
 120                wake_up(&i2c->wait);
 121                return;
 122        }
 123
 124        /* error? */
 125        if (stat & OCI2C_STAT_ARBLOST) {
 126                i2c->state = STATE_ERROR;
 127                oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
 128                return;
 129        }
 130
 131        if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) {
 132                i2c->state =
 133                        (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
 134
 135                if (stat & OCI2C_STAT_NACK) {
 136                        i2c->state = STATE_ERROR;
 137                        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
 138                        return;
 139                }
 140        } else
 141                msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
 142
 143        /* end of msg? */
 144        if (i2c->pos == msg->len) {
 145                i2c->nmsgs--;
 146                i2c->msg++;
 147                i2c->pos = 0;
 148                msg = i2c->msg;
 149
 150                if (i2c->nmsgs) {       /* end? */
 151                        /* send start? */
 152                        if (!(msg->flags & I2C_M_NOSTART)) {
 153                                u8 addr = (msg->addr << 1);
 154
 155                                if (msg->flags & I2C_M_RD)
 156                                        addr |= 1;
 157
 158                                i2c->state = STATE_START;
 159
 160                                oc_setreg(i2c, OCI2C_DATA, addr);
 161                                oc_setreg(i2c, OCI2C_CMD,  OCI2C_CMD_START);
 162                                return;
 163                        } else
 164                                i2c->state = (msg->flags & I2C_M_RD)
 165                                        ? STATE_READ : STATE_WRITE;
 166                } else {
 167                        i2c->state = STATE_DONE;
 168                        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
 169                        return;
 170                }
 171        }
 172
 173        if (i2c->state == STATE_READ) {
 174                oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
 175                          OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
 176        } else {
 177                oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
 178                oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
 179        }
 180}
 181
 182static irqreturn_t ocores_isr(int irq, void *dev_id)
 183{
 184        struct ocores_i2c *i2c = dev_id;
 185
 186        ocores_process(i2c);
 187
 188        return IRQ_HANDLED;
 189}
 190
 191static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 192{
 193        struct ocores_i2c *i2c = i2c_get_adapdata(adap);
 194
 195        i2c->msg = msgs;
 196        i2c->pos = 0;
 197        i2c->nmsgs = num;
 198        i2c->state = STATE_START;
 199
 200        oc_setreg(i2c, OCI2C_DATA,
 201                        (i2c->msg->addr << 1) |
 202                        ((i2c->msg->flags & I2C_M_RD) ? 1:0));
 203
 204        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
 205
 206        if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
 207                               (i2c->state == STATE_DONE), HZ))
 208                return (i2c->state == STATE_DONE) ? num : -EIO;
 209        else
 210                return -ETIMEDOUT;
 211}
 212
 213static void ocores_init(struct ocores_i2c *i2c)
 214{
 215        int prescale;
 216        u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
 217
 218        /* make sure the device is disabled */
 219        oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 220
 221        prescale = (i2c->clock_khz / (5*100)) - 1;
 222        oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
 223        oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
 224
 225        /* Init the device */
 226        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
 227        oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN);
 228}
 229
 230
 231static u32 ocores_func(struct i2c_adapter *adap)
 232{
 233        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 234}
 235
 236static const struct i2c_algorithm ocores_algorithm = {
 237        .master_xfer    = ocores_xfer,
 238        .functionality  = ocores_func,
 239};
 240
 241static struct i2c_adapter ocores_adapter = {
 242        .owner          = THIS_MODULE,
 243        .name           = "i2c-ocores",
 244        .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 245        .algo           = &ocores_algorithm,
 246};
 247
 248#ifdef CONFIG_OF
 249static int ocores_i2c_of_probe(struct platform_device* pdev,
 250                                struct ocores_i2c* i2c)
 251{
 252        const __be32* val;
 253
 254        val = of_get_property(pdev->dev.of_node, "regstep", NULL);
 255        if (!val) {
 256                dev_err(&pdev->dev, "Missing required parameter 'regstep'");
 257                return -ENODEV;
 258        }
 259        i2c->regstep = be32_to_cpup(val);
 260
 261        val = of_get_property(pdev->dev.of_node, "clock-frequency", NULL);
 262        if (!val) {
 263                dev_err(&pdev->dev,
 264                        "Missing required parameter 'clock-frequency'");
 265                return -ENODEV;
 266        }
 267        i2c->clock_khz = be32_to_cpup(val) / 1000;
 268
 269        return 0;
 270}
 271#else
 272#define ocores_i2c_of_probe(pdev,i2c) -ENODEV
 273#endif
 274
 275static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 276{
 277        struct ocores_i2c *i2c;
 278        struct ocores_i2c_platform_data *pdata;
 279        struct resource *res, *res2;
 280        int ret;
 281        int i;
 282
 283        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 284        if (!res)
 285                return -ENODEV;
 286
 287        res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 288        if (!res2)
 289                return -ENODEV;
 290
 291        i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 292        if (!i2c)
 293                return -ENOMEM;
 294
 295        if (!devm_request_mem_region(&pdev->dev, res->start,
 296                                     resource_size(res), pdev->name)) {
 297                dev_err(&pdev->dev, "Memory region busy\n");
 298                return -EBUSY;
 299        }
 300
 301        i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
 302                                         resource_size(res));
 303        if (!i2c->base) {
 304                dev_err(&pdev->dev, "Unable to map registers\n");
 305                return -EIO;
 306        }
 307
 308        pdata = pdev->dev.platform_data;
 309        if (pdata) {
 310                i2c->regstep = pdata->regstep;
 311                i2c->clock_khz = pdata->clock_khz;
 312        } else {
 313                ret = ocores_i2c_of_probe(pdev, i2c);
 314                if (ret)
 315                        return ret;
 316        }
 317
 318        ocores_init(i2c);
 319
 320        init_waitqueue_head(&i2c->wait);
 321        ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0,
 322                               pdev->name, i2c);
 323        if (ret) {
 324                dev_err(&pdev->dev, "Cannot claim IRQ\n");
 325                return ret;
 326        }
 327
 328        /* hook up driver to tree */
 329        platform_set_drvdata(pdev, i2c);
 330        i2c->adap = ocores_adapter;
 331        i2c_set_adapdata(&i2c->adap, i2c);
 332        i2c->adap.dev.parent = &pdev->dev;
 333#ifdef CONFIG_OF
 334        i2c->adap.dev.of_node = pdev->dev.of_node;
 335#endif
 336
 337        /* add i2c adapter to i2c tree */
 338        ret = i2c_add_adapter(&i2c->adap);
 339        if (ret) {
 340                dev_err(&pdev->dev, "Failed to add adapter\n");
 341                return ret;
 342        }
 343
 344        /* add in known devices to the bus */
 345        if (pdata) {
 346                for (i = 0; i < pdata->num_devices; i++)
 347                        i2c_new_device(&i2c->adap, pdata->devices + i);
 348        }
 349
 350        return 0;
 351}
 352
 353static int __devexit ocores_i2c_remove(struct platform_device* pdev)
 354{
 355        struct ocores_i2c *i2c = platform_get_drvdata(pdev);
 356
 357        /* disable i2c logic */
 358        oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL)
 359                  & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 360
 361        /* remove adapter & data */
 362        i2c_del_adapter(&i2c->adap);
 363        platform_set_drvdata(pdev, NULL);
 364
 365        return 0;
 366}
 367
 368#ifdef CONFIG_PM
 369static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state)
 370{
 371        struct ocores_i2c *i2c = platform_get_drvdata(pdev);
 372        u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
 373
 374        /* make sure the device is disabled */
 375        oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 376
 377        return 0;
 378}
 379
 380static int ocores_i2c_resume(struct platform_device *pdev)
 381{
 382        struct ocores_i2c *i2c = platform_get_drvdata(pdev);
 383
 384        ocores_init(i2c);
 385
 386        return 0;
 387}
 388#else
 389#define ocores_i2c_suspend      NULL
 390#define ocores_i2c_resume       NULL
 391#endif
 392
 393#ifdef CONFIG_OF
 394static struct of_device_id ocores_i2c_match[] = {
 395        {
 396                .compatible = "opencores,i2c-ocores",
 397        },
 398        {},
 399};
 400MODULE_DEVICE_TABLE(of, ocores_i2c_match);
 401#endif
 402
 403/* work with hotplug and coldplug */
 404MODULE_ALIAS("platform:ocores-i2c");
 405
 406static struct platform_driver ocores_i2c_driver = {
 407        .probe   = ocores_i2c_probe,
 408        .remove  = __devexit_p(ocores_i2c_remove),
 409        .suspend = ocores_i2c_suspend,
 410        .resume  = ocores_i2c_resume,
 411        .driver  = {
 412                .owner = THIS_MODULE,
 413                .name = "ocores-i2c",
 414#ifdef CONFIG_OF
 415                .of_match_table = ocores_i2c_match,
 416#endif
 417        },
 418};
 419
 420static int __init ocores_i2c_init(void)
 421{
 422        return platform_driver_register(&ocores_i2c_driver);
 423}
 424
 425static void __exit ocores_i2c_exit(void)
 426{
 427        platform_driver_unregister(&ocores_i2c_driver);
 428}
 429
 430module_init(ocores_i2c_init);
 431module_exit(ocores_i2c_exit);
 432
 433MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
 434MODULE_DESCRIPTION("OpenCores I2C bus driver");
 435MODULE_LICENSE("GPL");
 436