linux/drivers/sbus/char/bbc_i2c.c
<<
>>
Prefs
   1/* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
   2 *            platforms.
   3 *
   4 * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/kernel.h>
   9#include <linux/types.h>
  10#include <linux/slab.h>
  11#include <linux/sched.h>
  12#include <linux/wait.h>
  13#include <linux/delay.h>
  14#include <linux/init.h>
  15#include <linux/interrupt.h>
  16#include <linux/of.h>
  17#include <linux/of_device.h>
  18#include <asm/bbc.h>
  19#include <asm/io.h>
  20
  21#include "bbc_i2c.h"
  22
  23/* Convert this driver to use i2c bus layer someday... */
  24#define I2C_PCF_PIN     0x80
  25#define I2C_PCF_ESO     0x40
  26#define I2C_PCF_ES1     0x20
  27#define I2C_PCF_ES2     0x10
  28#define I2C_PCF_ENI     0x08
  29#define I2C_PCF_STA     0x04
  30#define I2C_PCF_STO     0x02
  31#define I2C_PCF_ACK     0x01
  32
  33#define I2C_PCF_START    (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_ENI | I2C_PCF_STA | I2C_PCF_ACK)
  34#define I2C_PCF_STOP     (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STO | I2C_PCF_ACK)
  35#define I2C_PCF_REPSTART (              I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK)
  36#define I2C_PCF_IDLE     (I2C_PCF_PIN | I2C_PCF_ESO               | I2C_PCF_ACK)
  37
  38#define I2C_PCF_INI 0x40   /* 1 if not initialized */
  39#define I2C_PCF_STS 0x20
  40#define I2C_PCF_BER 0x10
  41#define I2C_PCF_AD0 0x08
  42#define I2C_PCF_LRB 0x08
  43#define I2C_PCF_AAS 0x04
  44#define I2C_PCF_LAB 0x02
  45#define I2C_PCF_BB  0x01
  46
  47/* The BBC devices have two I2C controllers.  The first I2C controller
  48 * connects mainly to configuration proms (NVRAM, cpu configuration,
  49 * dimm types, etc.).  Whereas the second I2C controller connects to
  50 * environmental control devices such as fans and temperature sensors.
  51 * The second controller also connects to the smartcard reader, if present.
  52 */
  53
  54static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val)
  55{
  56        int i;
  57
  58        for (i = 0; i < NUM_CHILDREN; i++) {
  59                if (bp->devs[i].device == op) {
  60                        bp->devs[i].client_claimed = val;
  61                        return;
  62                }
  63        }
  64}
  65
  66#define claim_device(BP,ECHILD)         set_device_claimage(BP,ECHILD,1)
  67#define release_device(BP,ECHILD)       set_device_claimage(BP,ECHILD,0)
  68
  69struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index)
  70{
  71        struct of_device *op = NULL;
  72        int curidx = 0, i;
  73
  74        for (i = 0; i < NUM_CHILDREN; i++) {
  75                if (!(op = bp->devs[i].device))
  76                        break;
  77                if (curidx == index)
  78                        goto out;
  79                op = NULL;
  80                curidx++;
  81        }
  82
  83out:
  84        if (curidx == index)
  85                return op;
  86        return NULL;
  87}
  88
  89struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op)
  90{
  91        struct bbc_i2c_client *client;
  92        const u32 *reg;
  93
  94        client = kzalloc(sizeof(*client), GFP_KERNEL);
  95        if (!client)
  96                return NULL;
  97        client->bp = bp;
  98        client->op = op;
  99
 100        reg = of_get_property(op->node, "reg", NULL);
 101        if (!reg) {
 102                kfree(client);
 103                return NULL;
 104        }
 105
 106        client->bus = reg[0];
 107        client->address = reg[1];
 108
 109        claim_device(bp, op);
 110
 111        return client;
 112}
 113
 114void bbc_i2c_detach(struct bbc_i2c_client *client)
 115{
 116        struct bbc_i2c_bus *bp = client->bp;
 117        struct of_device *op = client->op;
 118
 119        release_device(bp, op);
 120        kfree(client);
 121}
 122
 123static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
 124{
 125        DECLARE_WAITQUEUE(wait, current);
 126        int limit = 32;
 127        int ret = 1;
 128
 129        bp->waiting = 1;
 130        add_wait_queue(&bp->wq, &wait);
 131        while (limit-- > 0) {
 132                long val;
 133
 134                val = wait_event_interruptible_timeout(
 135                                bp->wq,
 136                                (((*status = readb(bp->i2c_control_regs + 0))
 137                                  & I2C_PCF_PIN) == 0),
 138                                msecs_to_jiffies(250));
 139                if (val > 0) {
 140                        ret = 0;
 141                        break;
 142                }
 143        }
 144        remove_wait_queue(&bp->wq, &wait);
 145        bp->waiting = 0;
 146
 147        return ret;
 148}
 149
 150int bbc_i2c_writeb(struct bbc_i2c_client *client, unsigned char val, int off)
 151{
 152        struct bbc_i2c_bus *bp = client->bp;
 153        int address = client->address;
 154        u8 status;
 155        int ret = -1;
 156
 157        if (bp->i2c_bussel_reg != NULL)
 158                writeb(client->bus, bp->i2c_bussel_reg);
 159
 160        writeb(address, bp->i2c_control_regs + 0x1);
 161        writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
 162        if (wait_for_pin(bp, &status))
 163                goto out;
 164
 165        writeb(off, bp->i2c_control_regs + 0x1);
 166        if (wait_for_pin(bp, &status) ||
 167            (status & I2C_PCF_LRB) != 0)
 168                goto out;
 169
 170        writeb(val, bp->i2c_control_regs + 0x1);
 171        if (wait_for_pin(bp, &status))
 172                goto out;
 173
 174        ret = 0;
 175
 176out:
 177        writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
 178        return ret;
 179}
 180
 181int bbc_i2c_readb(struct bbc_i2c_client *client, unsigned char *byte, int off)
 182{
 183        struct bbc_i2c_bus *bp = client->bp;
 184        unsigned char address = client->address, status;
 185        int ret = -1;
 186
 187        if (bp->i2c_bussel_reg != NULL)
 188                writeb(client->bus, bp->i2c_bussel_reg);
 189
 190        writeb(address, bp->i2c_control_regs + 0x1);
 191        writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
 192        if (wait_for_pin(bp, &status))
 193                goto out;
 194
 195        writeb(off, bp->i2c_control_regs + 0x1);
 196        if (wait_for_pin(bp, &status) ||
 197            (status & I2C_PCF_LRB) != 0)
 198                goto out;
 199
 200        writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
 201
 202        address |= 0x1; /* READ */
 203
 204        writeb(address, bp->i2c_control_regs + 0x1);
 205        writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
 206        if (wait_for_pin(bp, &status))
 207                goto out;
 208
 209        /* Set PIN back to one so the device sends the first
 210         * byte.
 211         */
 212        (void) readb(bp->i2c_control_regs + 0x1);
 213        if (wait_for_pin(bp, &status))
 214                goto out;
 215
 216        writeb(I2C_PCF_ESO | I2C_PCF_ENI, bp->i2c_control_regs + 0x0);
 217        *byte = readb(bp->i2c_control_regs + 0x1);
 218        if (wait_for_pin(bp, &status))
 219                goto out;
 220
 221        ret = 0;
 222
 223out:
 224        writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
 225        (void) readb(bp->i2c_control_regs + 0x1);
 226
 227        return ret;
 228}
 229
 230int bbc_i2c_write_buf(struct bbc_i2c_client *client,
 231                      char *buf, int len, int off)
 232{
 233        int ret = 0;
 234
 235        while (len > 0) {
 236                int err = bbc_i2c_writeb(client, *buf, off);
 237
 238                if (err < 0) {
 239                        ret = err;
 240                        break;
 241                }
 242
 243                len--;
 244                buf++;
 245                off++;
 246        }
 247        return ret;
 248}
 249
 250int bbc_i2c_read_buf(struct bbc_i2c_client *client,
 251                     char *buf, int len, int off)
 252{
 253        int ret = 0;
 254
 255        while (len > 0) {
 256                int err = bbc_i2c_readb(client, buf, off);
 257                if (err < 0) {
 258                        ret = err;
 259                        break;
 260                }
 261                len--;
 262                buf++;
 263                off++;
 264        }
 265
 266        return ret;
 267}
 268
 269EXPORT_SYMBOL(bbc_i2c_getdev);
 270EXPORT_SYMBOL(bbc_i2c_attach);
 271EXPORT_SYMBOL(bbc_i2c_detach);
 272EXPORT_SYMBOL(bbc_i2c_writeb);
 273EXPORT_SYMBOL(bbc_i2c_readb);
 274EXPORT_SYMBOL(bbc_i2c_write_buf);
 275EXPORT_SYMBOL(bbc_i2c_read_buf);
 276
 277static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
 278{
 279        struct bbc_i2c_bus *bp = dev_id;
 280
 281        /* PIN going from set to clear is the only event which
 282         * makes the i2c assert an interrupt.
 283         */
 284        if (bp->waiting &&
 285            !(readb(bp->i2c_control_regs + 0x0) & I2C_PCF_PIN))
 286                wake_up_interruptible(&bp->wq);
 287
 288        return IRQ_HANDLED;
 289}
 290
 291static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
 292{
 293        writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
 294        writeb(bp->own, bp->i2c_control_regs + 0x1);
 295        writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
 296        writeb(bp->clock, bp->i2c_control_regs + 0x1);
 297        writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
 298}
 299
 300static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index)
 301{
 302        struct bbc_i2c_bus *bp;
 303        struct device_node *dp;
 304        int entry;
 305
 306        bp = kzalloc(sizeof(*bp), GFP_KERNEL);
 307        if (!bp)
 308                return NULL;
 309
 310        bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
 311        if (!bp->i2c_control_regs)
 312                goto fail;
 313
 314        bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
 315        if (!bp->i2c_bussel_reg)
 316                goto fail;
 317
 318        bp->waiting = 0;
 319        init_waitqueue_head(&bp->wq);
 320        if (request_irq(op->irqs[0], bbc_i2c_interrupt,
 321                        IRQF_SHARED, "bbc_i2c", bp))
 322                goto fail;
 323
 324        bp->index = index;
 325        bp->op = op;
 326
 327        spin_lock_init(&bp->lock);
 328
 329        entry = 0;
 330        for (dp = op->node->child;
 331             dp && entry < 8;
 332             dp = dp->sibling, entry++) {
 333                struct of_device *child_op;
 334
 335                child_op = of_find_device_by_node(dp);
 336                bp->devs[entry].device = child_op;
 337                bp->devs[entry].client_claimed = 0;
 338        }
 339
 340        writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
 341        bp->own = readb(bp->i2c_control_regs + 0x01);
 342        writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
 343        bp->clock = readb(bp->i2c_control_regs + 0x01);
 344
 345        printk(KERN_INFO "i2c-%d: Regs at %p, %d devices, own %02x, clock %02x.\n",
 346               bp->index, bp->i2c_control_regs, entry, bp->own, bp->clock);
 347
 348        reset_one_i2c(bp);
 349
 350        return bp;
 351
 352fail:
 353        if (bp->i2c_bussel_reg)
 354                of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1);
 355        if (bp->i2c_control_regs)
 356                of_iounmap(&op->resource[0], bp->i2c_control_regs, 2);
 357        kfree(bp);
 358        return NULL;
 359}
 360
 361extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
 362extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
 363
 364static int __devinit bbc_i2c_probe(struct of_device *op,
 365                                   const struct of_device_id *match)
 366{
 367        struct bbc_i2c_bus *bp;
 368        int err, index = 0;
 369
 370        bp = attach_one_i2c(op, index);
 371        if (!bp)
 372                return -EINVAL;
 373
 374        err = bbc_envctrl_init(bp);
 375        if (err) {
 376                free_irq(op->irqs[0], bp);
 377                if (bp->i2c_bussel_reg)
 378                        of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
 379                if (bp->i2c_control_regs)
 380                        of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
 381                kfree(bp);
 382        } else {
 383                dev_set_drvdata(&op->dev, bp);
 384        }
 385
 386        return err;
 387}
 388
 389static int __devexit bbc_i2c_remove(struct of_device *op)
 390{
 391        struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev);
 392
 393        bbc_envctrl_cleanup(bp);
 394
 395        free_irq(op->irqs[0], bp);
 396
 397        if (bp->i2c_bussel_reg)
 398                of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
 399        if (bp->i2c_control_regs)
 400                of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
 401
 402        kfree(bp);
 403
 404        return 0;
 405}
 406
 407static const struct of_device_id bbc_i2c_match[] = {
 408        {
 409                .name = "i2c",
 410                .compatible = "SUNW,bbc-i2c",
 411        },
 412        {},
 413};
 414MODULE_DEVICE_TABLE(of, bbc_i2c_match);
 415
 416static struct of_platform_driver bbc_i2c_driver = {
 417        .name           = "bbc_i2c",
 418        .match_table    = bbc_i2c_match,
 419        .probe          = bbc_i2c_probe,
 420        .remove         = __devexit_p(bbc_i2c_remove),
 421};
 422
 423static int __init bbc_i2c_init(void)
 424{
 425        return of_register_driver(&bbc_i2c_driver, &of_bus_type);
 426}
 427
 428static void __exit bbc_i2c_exit(void)
 429{
 430        of_unregister_driver(&bbc_i2c_driver);
 431}
 432
 433module_init(bbc_i2c_init);
 434module_exit(bbc_i2c_exit);
 435
 436MODULE_LICENSE("GPL");
 437