root/drivers/sbus/char/bbc_i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_device_claimage
  2. bbc_i2c_getdev
  3. bbc_i2c_attach
  4. bbc_i2c_detach
  5. wait_for_pin
  6. bbc_i2c_writeb
  7. bbc_i2c_readb
  8. bbc_i2c_write_buf
  9. bbc_i2c_read_buf
  10. bbc_i2c_interrupt
  11. reset_one_i2c
  12. attach_one_i2c
  13. bbc_i2c_probe
  14. bbc_i2c_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
   3  *            platforms.
   4  *
   5  * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/kernel.h>
  10 #include <linux/types.h>
  11 #include <linux/slab.h>
  12 #include <linux/sched.h>
  13 #include <linux/wait.h>
  14 #include <linux/delay.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 
  54 static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_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 
  69 struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index)
  70 {
  71         struct platform_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 
  83 out:
  84         if (curidx == index)
  85                 return op;
  86         return NULL;
  87 }
  88 
  89 struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_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->dev.of_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 
 114 void bbc_i2c_detach(struct bbc_i2c_client *client)
 115 {
 116         struct bbc_i2c_bus *bp = client->bp;
 117         struct platform_device *op = client->op;
 118 
 119         release_device(bp, op);
 120         kfree(client);
 121 }
 122 
 123 static 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 
 150 int 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 
 176 out:
 177         writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
 178         return ret;
 179 }
 180 
 181 int 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 
 223 out:
 224         writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
 225         (void) readb(bp->i2c_control_regs + 0x1);
 226 
 227         return ret;
 228 }
 229 
 230 int 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                 ret = bbc_i2c_writeb(client, *buf, off);
 237                 if (ret < 0)
 238                         break;
 239                 len--;
 240                 buf++;
 241                 off++;
 242         }
 243         return ret;
 244 }
 245 
 246 int bbc_i2c_read_buf(struct bbc_i2c_client *client,
 247                      char *buf, int len, int off)
 248 {
 249         int ret = 0;
 250 
 251         while (len > 0) {
 252                 ret = bbc_i2c_readb(client, buf, off);
 253                 if (ret < 0)
 254                         break;
 255                 len--;
 256                 buf++;
 257                 off++;
 258         }
 259 
 260         return ret;
 261 }
 262 
 263 EXPORT_SYMBOL(bbc_i2c_getdev);
 264 EXPORT_SYMBOL(bbc_i2c_attach);
 265 EXPORT_SYMBOL(bbc_i2c_detach);
 266 EXPORT_SYMBOL(bbc_i2c_writeb);
 267 EXPORT_SYMBOL(bbc_i2c_readb);
 268 EXPORT_SYMBOL(bbc_i2c_write_buf);
 269 EXPORT_SYMBOL(bbc_i2c_read_buf);
 270 
 271 static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
 272 {
 273         struct bbc_i2c_bus *bp = dev_id;
 274 
 275         /* PIN going from set to clear is the only event which
 276          * makes the i2c assert an interrupt.
 277          */
 278         if (bp->waiting &&
 279             !(readb(bp->i2c_control_regs + 0x0) & I2C_PCF_PIN))
 280                 wake_up_interruptible(&bp->wq);
 281 
 282         return IRQ_HANDLED;
 283 }
 284 
 285 static void reset_one_i2c(struct bbc_i2c_bus *bp)
 286 {
 287         writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
 288         writeb(bp->own, bp->i2c_control_regs + 0x1);
 289         writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
 290         writeb(bp->clock, bp->i2c_control_regs + 0x1);
 291         writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
 292 }
 293 
 294 static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index)
 295 {
 296         struct bbc_i2c_bus *bp;
 297         struct device_node *dp;
 298         int entry;
 299 
 300         bp = kzalloc(sizeof(*bp), GFP_KERNEL);
 301         if (!bp)
 302                 return NULL;
 303 
 304         INIT_LIST_HEAD(&bp->temps);
 305         INIT_LIST_HEAD(&bp->fans);
 306 
 307         bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
 308         if (!bp->i2c_control_regs)
 309                 goto fail;
 310 
 311         if (op->num_resources == 2) {
 312                 bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
 313                 if (!bp->i2c_bussel_reg)
 314                         goto fail;
 315         }
 316 
 317         bp->waiting = 0;
 318         init_waitqueue_head(&bp->wq);
 319         if (request_irq(op->archdata.irqs[0], bbc_i2c_interrupt,
 320                         IRQF_SHARED, "bbc_i2c", bp))
 321                 goto fail;
 322 
 323         bp->index = index;
 324         bp->op = op;
 325 
 326         spin_lock_init(&bp->lock);
 327 
 328         entry = 0;
 329         for (dp = op->dev.of_node->child;
 330              dp && entry < 8;
 331              dp = dp->sibling, entry++) {
 332                 struct platform_device *child_op;
 333 
 334                 child_op = of_find_device_by_node(dp);
 335                 bp->devs[entry].device = child_op;
 336                 bp->devs[entry].client_claimed = 0;
 337         }
 338 
 339         writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
 340         bp->own = readb(bp->i2c_control_regs + 0x01);
 341         writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
 342         bp->clock = readb(bp->i2c_control_regs + 0x01);
 343 
 344         printk(KERN_INFO "i2c-%d: Regs at %p, %d devices, own %02x, clock %02x.\n",
 345                bp->index, bp->i2c_control_regs, entry, bp->own, bp->clock);
 346 
 347         reset_one_i2c(bp);
 348 
 349         return bp;
 350 
 351 fail:
 352         if (bp->i2c_bussel_reg)
 353                 of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1);
 354         if (bp->i2c_control_regs)
 355                 of_iounmap(&op->resource[0], bp->i2c_control_regs, 2);
 356         kfree(bp);
 357         return NULL;
 358 }
 359 
 360 extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
 361 extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
 362 
 363 static int bbc_i2c_probe(struct platform_device *op)
 364 {
 365         struct bbc_i2c_bus *bp;
 366         int err, index = 0;
 367 
 368         bp = attach_one_i2c(op, index);
 369         if (!bp)
 370                 return -EINVAL;
 371 
 372         err = bbc_envctrl_init(bp);
 373         if (err) {
 374                 free_irq(op->archdata.irqs[0], bp);
 375                 if (bp->i2c_bussel_reg)
 376                         of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
 377                 if (bp->i2c_control_regs)
 378                         of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
 379                 kfree(bp);
 380         } else {
 381                 dev_set_drvdata(&op->dev, bp);
 382         }
 383 
 384         return err;
 385 }
 386 
 387 static int bbc_i2c_remove(struct platform_device *op)
 388 {
 389         struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev);
 390 
 391         bbc_envctrl_cleanup(bp);
 392 
 393         free_irq(op->archdata.irqs[0], bp);
 394 
 395         if (bp->i2c_bussel_reg)
 396                 of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
 397         if (bp->i2c_control_regs)
 398                 of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
 399 
 400         kfree(bp);
 401 
 402         return 0;
 403 }
 404 
 405 static const struct of_device_id bbc_i2c_match[] = {
 406         {
 407                 .name = "i2c",
 408                 .compatible = "SUNW,bbc-i2c",
 409         },
 410         {},
 411 };
 412 MODULE_DEVICE_TABLE(of, bbc_i2c_match);
 413 
 414 static struct platform_driver bbc_i2c_driver = {
 415         .driver = {
 416                 .name = "bbc_i2c",
 417                 .of_match_table = bbc_i2c_match,
 418         },
 419         .probe          = bbc_i2c_probe,
 420         .remove         = bbc_i2c_remove,
 421 };
 422 
 423 module_platform_driver(bbc_i2c_driver);
 424 
 425 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */