aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus/char/bbc_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sbus/char/bbc_i2c.c')
-rw-r--r--drivers/sbus/char/bbc_i2c.c267
1 files changed, 106 insertions, 161 deletions
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index ac8ef2ce07fb..af7f4af6c5fb 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -1,8 +1,7 @@
1/* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $ 1/* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
2 * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
3 * platforms. 2 * platforms.
4 * 3 *
5 * Copyright (C) 2001 David S. Miller (davem@redhat.com) 4 * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
6 */ 5 */
7 6
8#include <linux/module.h> 7#include <linux/module.h>
@@ -14,9 +13,8 @@
14#include <linux/delay.h> 13#include <linux/delay.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/interrupt.h> 15#include <linux/interrupt.h>
17#include <asm/oplib.h> 16#include <linux/of.h>
18#include <asm/ebus.h> 17#include <linux/of_device.h>
19#include <asm/spitfire.h>
20#include <asm/bbc.h> 18#include <asm/bbc.h>
21#include <asm/io.h> 19#include <asm/io.h>
22 20
@@ -53,54 +51,12 @@
53 * The second controller also connects to the smartcard reader, if present. 51 * The second controller also connects to the smartcard reader, if present.
54 */ 52 */
55 53
56#define NUM_CHILDREN 8 54static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val)
57struct bbc_i2c_bus {
58 struct bbc_i2c_bus *next;
59 int index;
60 spinlock_t lock;
61 void __iomem *i2c_bussel_reg;
62 void __iomem *i2c_control_regs;
63 unsigned char own, clock;
64
65 wait_queue_head_t wq;
66 volatile int waiting;
67
68 struct linux_ebus_device *bus_edev;
69 struct {
70 struct linux_ebus_child *device;
71 int client_claimed;
72 } devs[NUM_CHILDREN];
73};
74
75static struct bbc_i2c_bus *all_bbc_i2c;
76
77struct bbc_i2c_client {
78 struct bbc_i2c_bus *bp;
79 struct linux_ebus_child *echild;
80 int bus;
81 int address;
82};
83
84static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild)
85{ 55{
86 int i; 56 int i;
87 57
88 for (i = 0; i < NUM_CHILDREN; i++) { 58 for (i = 0; i < NUM_CHILDREN; i++) {
89 if (bp->devs[i].device == echild) { 59 if (bp->devs[i].device == op) {
90 if (bp->devs[i].client_claimed)
91 return 0;
92 return 1;
93 }
94 }
95 return 0;
96}
97
98static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val)
99{
100 int i;
101
102 for (i = 0; i < NUM_CHILDREN; i++) {
103 if (bp->devs[i].device == echild) {
104 bp->devs[i].client_claimed = val; 60 bp->devs[i].client_claimed = val;
105 return; 61 return;
106 } 62 }
@@ -110,61 +66,47 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child
110#define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) 66#define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1)
111#define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) 67#define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0)
112 68
113static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild) 69struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index)
114{ 70{
115 struct bbc_i2c_bus *bp = all_bbc_i2c; 71 struct of_device *op = NULL;
72 int curidx = 0, i;
116 73
117 while (bp != NULL) { 74 for (i = 0; i < NUM_CHILDREN; i++) {
118 if (find_device(bp, echild) != 0) 75 if (!(op = bp->devs[i].device))
119 break; 76 break;
120 bp = bp->next; 77 if (curidx == index)
78 goto out;
79 op = NULL;
80 curidx++;
121 } 81 }
122 82
123 return bp;
124}
125
126struct linux_ebus_child *bbc_i2c_getdev(int index)
127{
128 struct bbc_i2c_bus *bp = all_bbc_i2c;
129 struct linux_ebus_child *echild = NULL;
130 int curidx = 0;
131
132 while (bp != NULL) {
133 struct bbc_i2c_bus *next = bp->next;
134 int i;
135
136 for (i = 0; i < NUM_CHILDREN; i++) {
137 if (!(echild = bp->devs[i].device))
138 break;
139 if (curidx == index)
140 goto out;
141 echild = NULL;
142 curidx++;
143 }
144 bp = next;
145 }
146out: 83out:
147 if (curidx == index) 84 if (curidx == index)
148 return echild; 85 return op;
149 return NULL; 86 return NULL;
150} 87}
151 88
152struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) 89struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op)
153{ 90{
154 struct bbc_i2c_bus *bp = find_bus_for_device(echild);
155 struct bbc_i2c_client *client; 91 struct bbc_i2c_client *client;
92 const u32 *reg;
156 93
157 if (!bp)
158 return NULL;
159 client = kzalloc(sizeof(*client), GFP_KERNEL); 94 client = kzalloc(sizeof(*client), GFP_KERNEL);
160 if (!client) 95 if (!client)
161 return NULL; 96 return NULL;
162 client->bp = bp; 97 client->bp = bp;
163 client->echild = echild; 98 client->op = op;
164 client->bus = echild->resource[0].start; 99
165 client->address = echild->resource[1].start; 100 reg = of_get_property(op->node, "reg", NULL);
101 if (!reg) {
102 kfree(client);
103 return NULL;
104 }
166 105
167 claim_device(bp, echild); 106 client->bus = reg[0];
107 client->address = reg[1];
108
109 claim_device(bp, op);
168 110
169 return client; 111 return client;
170} 112}
@@ -172,9 +114,9 @@ struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild)
172void bbc_i2c_detach(struct bbc_i2c_client *client) 114void bbc_i2c_detach(struct bbc_i2c_client *client)
173{ 115{
174 struct bbc_i2c_bus *bp = client->bp; 116 struct bbc_i2c_bus *bp = client->bp;
175 struct linux_ebus_child *echild = client->echild; 117 struct of_device *op = client->op;
176 118
177 release_device(bp, echild); 119 release_device(bp, op);
178 kfree(client); 120 kfree(client);
179} 121}
180 122
@@ -355,44 +297,43 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
355 writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); 297 writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
356} 298}
357 299
358static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) 300static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index)
359{ 301{
360 struct bbc_i2c_bus *bp; 302 struct bbc_i2c_bus *bp;
361 struct linux_ebus_child *echild; 303 struct device_node *dp;
362 int entry; 304 int entry;
363 305
364 bp = kzalloc(sizeof(*bp), GFP_KERNEL); 306 bp = kzalloc(sizeof(*bp), GFP_KERNEL);
365 if (!bp) 307 if (!bp)
366 return -ENOMEM; 308 return NULL;
367 309
368 bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2); 310 bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
369 if (!bp->i2c_control_regs) 311 if (!bp->i2c_control_regs)
370 goto fail; 312 goto fail;
371 313
372 if (edev->num_addrs == 2) { 314 bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
373 bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1); 315 if (!bp->i2c_bussel_reg)
374 if (!bp->i2c_bussel_reg) 316 goto fail;
375 goto fail;
376 }
377 317
378 bp->waiting = 0; 318 bp->waiting = 0;
379 init_waitqueue_head(&bp->wq); 319 init_waitqueue_head(&bp->wq);
380 if (request_irq(edev->irqs[0], bbc_i2c_interrupt, 320 if (request_irq(op->irqs[0], bbc_i2c_interrupt,
381 IRQF_SHARED, "bbc_i2c", bp)) 321 IRQF_SHARED, "bbc_i2c", bp))
382 goto fail; 322 goto fail;
383 323
384 bp->index = index; 324 bp->index = index;
385 bp->bus_edev = edev; 325 bp->op = op;
386 326
387 spin_lock_init(&bp->lock); 327 spin_lock_init(&bp->lock);
388 bp->next = all_bbc_i2c;
389 all_bbc_i2c = bp;
390 328
391 entry = 0; 329 entry = 0;
392 for (echild = edev->children; 330 for (dp = op->node->child;
393 echild && entry < 8; 331 dp && entry < 8;
394 echild = echild->next, entry++) { 332 dp = dp->sibling, entry++) {
395 bp->devs[entry].device = echild; 333 struct of_device *child_op;
334
335 child_op = of_find_device_by_node(dp);
336 bp->devs[entry].device = child_op;
396 bp->devs[entry].client_claimed = 0; 337 bp->devs[entry].client_claimed = 0;
397 } 338 }
398 339
@@ -406,86 +347,90 @@ static int __init attach_one_i2c(struct linux_ebus_device *edev, int index)
406 347
407 reset_one_i2c(bp); 348 reset_one_i2c(bp);
408 349
409 return 0; 350 return bp;
410 351
411fail: 352fail:
412 if (bp->i2c_bussel_reg) 353 if (bp->i2c_bussel_reg)
413 iounmap(bp->i2c_bussel_reg); 354 of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1);
414 if (bp->i2c_control_regs) 355 if (bp->i2c_control_regs)
415 iounmap(bp->i2c_control_regs); 356 of_iounmap(&op->resource[0], bp->i2c_control_regs, 2);
416 kfree(bp); 357 kfree(bp);
417 return -EINVAL; 358 return NULL;
418}
419
420static int __init bbc_present(void)
421{
422 struct linux_ebus *ebus = NULL;
423 struct linux_ebus_device *edev = NULL;
424
425 for_each_ebus(ebus) {
426 for_each_ebusdev(edev, ebus) {
427 if (!strcmp(edev->prom_node->name, "bbc"))
428 return 1;
429 }
430 }
431 return 0;
432} 359}
433 360
434extern int bbc_envctrl_init(void); 361extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
435extern void bbc_envctrl_cleanup(void); 362extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
436static void bbc_i2c_cleanup(void);
437 363
438static int __init bbc_i2c_init(void) 364static int __devinit bbc_i2c_probe(struct of_device *op,
365 const struct of_device_id *match)
439{ 366{
440 struct linux_ebus *ebus = NULL; 367 struct bbc_i2c_bus *bp;
441 struct linux_ebus_device *edev = NULL;
442 int err, index = 0; 368 int err, index = 0;
443 369
444 if ((tlb_type != cheetah && tlb_type != cheetah_plus) || 370 bp = attach_one_i2c(op, index);
445 !bbc_present()) 371 if (!bp)
446 return -ENODEV; 372 return -EINVAL;
447 373
448 for_each_ebus(ebus) { 374 err = bbc_envctrl_init(bp);
449 for_each_ebusdev(edev, ebus) { 375 if (err) {
450 if (!strcmp(edev->prom_node->name, "i2c")) { 376 free_irq(op->irqs[0], bp);
451 if (!attach_one_i2c(edev, index)) 377 if (bp->i2c_bussel_reg)
452 index++; 378 of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
453 } 379 if (bp->i2c_control_regs)
454 } 380 of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
381 kfree(bp);
382 } else {
383 dev_set_drvdata(&op->dev, bp);
455 } 384 }
456 385
457 if (!index)
458 return -ENODEV;
459
460 err = bbc_envctrl_init();
461 if (err)
462 bbc_i2c_cleanup();
463 return err; 386 return err;
464} 387}
465 388
466static void bbc_i2c_cleanup(void) 389static int __devexit bbc_i2c_remove(struct of_device *op)
467{ 390{
468 struct bbc_i2c_bus *bp = all_bbc_i2c; 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);
469 396
470 bbc_envctrl_cleanup(); 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);
471 401
472 while (bp != NULL) { 402 kfree(bp);
473 struct bbc_i2c_bus *next = bp->next;
474 403
475 free_irq(bp->bus_edev->irqs[0], bp); 404 return 0;
405}
476 406
477 if (bp->i2c_bussel_reg) 407static struct of_device_id bbc_i2c_match[] = {
478 iounmap(bp->i2c_bussel_reg); 408 {
479 if (bp->i2c_control_regs) 409 .name = "i2c",
480 iounmap(bp->i2c_control_regs); 410 .compatible = "SUNW,bbc-i2c",
411 },
412 {},
413};
414MODULE_DEVICE_TABLE(of, bbc_i2c_match);
481 415
482 kfree(bp); 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};
483 422
484 bp = next; 423static int __init bbc_i2c_init(void)
485 } 424{
486 all_bbc_i2c = NULL; 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);
487} 431}
488 432
489module_init(bbc_i2c_init); 433module_init(bbc_i2c_init);
490module_exit(bbc_i2c_cleanup); 434module_exit(bbc_i2c_exit);
435
491MODULE_LICENSE("GPL"); 436MODULE_LICENSE("GPL");