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