aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-30 01:34:14 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-30 01:34:14 -0400
commite21e245bcd9d5244735799387d14421789b20557 (patch)
treed8bfe0be5ac850764203b440566ef279cd47c7b5 /drivers/sbus
parent6b8c90f24e24505f97efaef1a46572d6b45929b9 (diff)
bbc_i2c: Convert to pure OF driver.
This thing was a mess, who wrote this junk? :) Luckily we'll soon have nice generic I2C layer drivers for this PCF based I2C stuff on sparc64. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/sbus')
-rw-r--r--drivers/sbus/char/bbc_envctrl.c121
-rw-r--r--drivers/sbus/char/bbc_i2c.c267
-rw-r--r--drivers/sbus/char/bbc_i2c.h75
3 files changed, 214 insertions, 249 deletions
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 0bde26989a23..abe4d50de21d 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -1,15 +1,15 @@
1/* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $ 1/* bbc_envctrl.c: UltraSPARC-III environment control driver.
2 * bbc_envctrl.c: UltraSPARC-III environment control driver.
3 * 2 *
4 * Copyright (C) 2001 David S. Miller (davem@redhat.com) 3 * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
5 */ 4 */
6 5
7#include <linux/kthread.h> 6#include <linux/kthread.h>
8#include <linux/delay.h> 7#include <linux/delay.h>
9#include <linux/kmod.h> 8#include <linux/kmod.h>
10#include <linux/reboot.h> 9#include <linux/reboot.h>
10#include <linux/of.h>
11#include <linux/of_device.h>
11#include <asm/oplib.h> 12#include <asm/oplib.h>
12#include <asm/ebus.h>
13 13
14#include "bbc_i2c.h" 14#include "bbc_i2c.h"
15#include "max1617.h" 15#include "max1617.h"
@@ -75,43 +75,8 @@ static struct temp_limits amb_temp_limits[2] = {
75 { 65, 55, 40, 5, -5, -10 }, 75 { 65, 55, 40, 5, -5, -10 },
76}; 76};
77 77
78enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; 78static LIST_HEAD(all_temps);
79 79static LIST_HEAD(all_fans);
80struct bbc_cpu_temperature {
81 struct bbc_cpu_temperature *next;
82
83 struct bbc_i2c_client *client;
84 int index;
85
86 /* Current readings, and history. */
87 s8 curr_cpu_temp;
88 s8 curr_amb_temp;
89 s8 prev_cpu_temp;
90 s8 prev_amb_temp;
91 s8 avg_cpu_temp;
92 s8 avg_amb_temp;
93
94 int sample_tick;
95
96 enum fan_action fan_todo[2];
97#define FAN_AMBIENT 0
98#define FAN_CPU 1
99};
100
101struct bbc_cpu_temperature *all_bbc_temps;
102
103struct bbc_fan_control {
104 struct bbc_fan_control *next;
105
106 struct bbc_i2c_client *client;
107 int index;
108
109 int psupply_fan_on;
110 int cpu_fan_speed;
111 int system_fan_speed;
112};
113
114struct bbc_fan_control *all_bbc_fans;
115 80
116#define CPU_FAN_REG 0xf0 81#define CPU_FAN_REG 0xf0
117#define SYS_FAN_REG 0xf2 82#define SYS_FAN_REG 0xf2
@@ -330,7 +295,7 @@ static enum fan_action prioritize_fan_action(int which_fan)
330 * recommend we do, and perform that action on all the 295 * recommend we do, and perform that action on all the
331 * fans. 296 * fans.
332 */ 297 */
333 for (tp = all_bbc_temps; tp; tp = tp->next) { 298 list_for_each_entry(tp, &all_temps, glob_list) {
334 if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { 299 if (tp->fan_todo[which_fan] == FAN_FULLBLAST) {
335 decision = FAN_FULLBLAST; 300 decision = FAN_FULLBLAST;
336 break; 301 break;
@@ -439,7 +404,7 @@ static void fans_full_blast(void)
439 /* Since we will not be monitoring things anymore, put 404 /* Since we will not be monitoring things anymore, put
440 * the fans on full blast. 405 * the fans on full blast.
441 */ 406 */
442 for (fp = all_bbc_fans; fp; fp = fp->next) { 407 list_for_each_entry(fp, &all_fans, glob_list) {
443 fp->cpu_fan_speed = FAN_SPEED_MAX; 408 fp->cpu_fan_speed = FAN_SPEED_MAX;
444 fp->system_fan_speed = FAN_SPEED_MAX; 409 fp->system_fan_speed = FAN_SPEED_MAX;
445 fp->psupply_fan_on = 1; 410 fp->psupply_fan_on = 1;
@@ -463,11 +428,11 @@ static int kenvctrld(void *__unused)
463 if (kthread_should_stop()) 428 if (kthread_should_stop())
464 break; 429 break;
465 430
466 for (tp = all_bbc_temps; tp; tp = tp->next) { 431 list_for_each_entry(tp, &all_temps, glob_list) {
467 get_current_temps(tp); 432 get_current_temps(tp);
468 analyze_temps(tp, &last_warning_jiffies); 433 analyze_temps(tp, &last_warning_jiffies);
469 } 434 }
470 for (fp = all_bbc_fans; fp; fp = fp->next) 435 list_for_each_entry(fp, &all_fans, glob_list)
471 maybe_new_fan_speeds(fp); 436 maybe_new_fan_speeds(fp);
472 } 437 }
473 printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); 438 printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n");
@@ -477,7 +442,8 @@ static int kenvctrld(void *__unused)
477 return 0; 442 return 0;
478} 443}
479 444
480static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) 445static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op,
446 int temp_idx)
481{ 447{
482 struct bbc_cpu_temperature *tp; 448 struct bbc_cpu_temperature *tp;
483 449
@@ -485,20 +451,17 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
485 if (!tp) 451 if (!tp)
486 return; 452 return;
487 453
488 tp->client = bbc_i2c_attach(echild); 454 tp->client = bbc_i2c_attach(op);
489 if (!tp->client) { 455 if (!tp->client) {
490 kfree(tp); 456 kfree(tp);
491 return; 457 return;
492 } 458 }
493 459
460
494 tp->index = temp_idx; 461 tp->index = temp_idx;
495 { 462
496 struct bbc_cpu_temperature **tpp = &all_bbc_temps; 463 list_add(&tp->glob_list, &all_temps);
497 while (*tpp) 464 list_add(&tp->bp_list, &bp->temps);
498 tpp = &((*tpp)->next);
499 tp->next = NULL;
500 *tpp = tp;
501 }
502 465
503 /* Tell it to convert once every 5 seconds, clear all cfg 466 /* Tell it to convert once every 5 seconds, clear all cfg
504 * bits. 467 * bits.
@@ -524,7 +487,8 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
524 tp->fan_todo[FAN_CPU] = FAN_SAME; 487 tp->fan_todo[FAN_CPU] = FAN_SAME;
525} 488}
526 489
527static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) 490static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
491 int fan_idx)
528{ 492{
529 struct bbc_fan_control *fp; 493 struct bbc_fan_control *fp;
530 494
@@ -532,7 +496,7 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
532 if (!fp) 496 if (!fp)
533 return; 497 return;
534 498
535 fp->client = bbc_i2c_attach(echild); 499 fp->client = bbc_i2c_attach(op);
536 if (!fp->client) { 500 if (!fp->client) {
537 kfree(fp); 501 kfree(fp);
538 return; 502 return;
@@ -540,13 +504,8 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
540 504
541 fp->index = fan_idx; 505 fp->index = fan_idx;
542 506
543 { 507 list_add(&fp->glob_list, &all_fans);
544 struct bbc_fan_control **fpp = &all_bbc_fans; 508 list_add(&fp->bp_list, &bp->fans);
545 while (*fpp)
546 fpp = &((*fpp)->next);
547 fp->next = NULL;
548 *fpp = fp;
549 }
550 509
551 /* The i2c device controlling the fans is write-only. 510 /* The i2c device controlling the fans is write-only.
552 * So the only way to keep track of the current power 511 * So the only way to keep track of the current power
@@ -563,18 +522,18 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
563 set_fan_speeds(fp); 522 set_fan_speeds(fp);
564} 523}
565 524
566int bbc_envctrl_init(void) 525int bbc_envctrl_init(struct bbc_i2c_bus *bp)
567{ 526{
568 struct linux_ebus_child *echild; 527 struct of_device *op;
569 int temp_index = 0; 528 int temp_index = 0;
570 int fan_index = 0; 529 int fan_index = 0;
571 int devidx = 0; 530 int devidx = 0;
572 531
573 while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { 532 while ((op = bbc_i2c_getdev(devidx++)) != NULL) {
574 if (!strcmp(echild->prom_node->name, "temperature")) 533 if (!strcmp(op->node->name, "temperature"))
575 attach_one_temp(echild, temp_index++); 534 attach_one_temp(bp, op, temp_index++);
576 if (!strcmp(echild->prom_node->name, "fan-control")) 535 if (!strcmp(op->node->name, "fan-control"))
577 attach_one_fan(echild, fan_index++); 536 attach_one_fan(bp, op, fan_index++);
578 } 537 }
579 if (temp_index != 0 && fan_index != 0) { 538 if (temp_index != 0 && fan_index != 0) {
580 kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); 539 kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
@@ -597,26 +556,22 @@ static void destroy_one_fan(struct bbc_fan_control *fp)
597 kfree(fp); 556 kfree(fp);
598} 557}
599 558
600void bbc_envctrl_cleanup(void) 559void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
601{ 560{
602 struct bbc_cpu_temperature *tp; 561 struct bbc_cpu_temperature *tp, *tpos;
603 struct bbc_fan_control *fp; 562 struct bbc_fan_control *fp, *fpos;
604 563
605 kthread_stop(kenvctrld_task); 564 kthread_stop(kenvctrld_task);
606 565
607 tp = all_bbc_temps; 566 list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
608 while (tp != NULL) { 567 list_del(&tp->bp_list);
609 struct bbc_cpu_temperature *next = tp->next; 568 list_del(&tp->glob_list);
610 destroy_one_temp(tp); 569 destroy_one_temp(tp);
611 tp = next;
612 } 570 }
613 all_bbc_temps = NULL;
614 571
615 fp = all_bbc_fans; 572 list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
616 while (fp != NULL) { 573 list_del(&fp->bp_list);
617 struct bbc_fan_control *next = fp->next; 574 list_del(&fp->glob_list);
618 destroy_one_fan(fp); 575 destroy_one_fan(fp);
619 fp = next;
620 } 576 }
621 all_bbc_fans = NULL;
622} 577}
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");
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h
index fb01bd17704b..83c4811b7b5e 100644
--- a/drivers/sbus/char/bbc_i2c.h
+++ b/drivers/sbus/char/bbc_i2c.h
@@ -1,14 +1,79 @@
1/* $Id: bbc_i2c.h,v 1.2 2001/04/02 09:59:25 davem Exp $ */
2#ifndef _BBC_I2C_H 1#ifndef _BBC_I2C_H
3#define _BBC_I2C_H 2#define _BBC_I2C_H
4 3
5#include <asm/ebus.h> 4#include <linux/of.h>
5#include <linux/of_device.h>
6#include <linux/list.h>
6 7
7struct bbc_i2c_client; 8struct bbc_i2c_client {
9 struct bbc_i2c_bus *bp;
10 struct of_device *op;
11 int bus;
12 int address;
13};
14
15enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX };
16
17struct bbc_cpu_temperature {
18 struct list_head bp_list;
19 struct list_head glob_list;
20
21 struct bbc_i2c_client *client;
22 int index;
23
24 /* Current readings, and history. */
25 s8 curr_cpu_temp;
26 s8 curr_amb_temp;
27 s8 prev_cpu_temp;
28 s8 prev_amb_temp;
29 s8 avg_cpu_temp;
30 s8 avg_amb_temp;
31
32 int sample_tick;
33
34 enum fan_action fan_todo[2];
35#define FAN_AMBIENT 0
36#define FAN_CPU 1
37};
38
39struct bbc_fan_control {
40 struct list_head bp_list;
41 struct list_head glob_list;
42
43 struct bbc_i2c_client *client;
44 int index;
45
46 int psupply_fan_on;
47 int cpu_fan_speed;
48 int system_fan_speed;
49};
50
51#define NUM_CHILDREN 8
52
53struct bbc_i2c_bus {
54 struct bbc_i2c_bus *next;
55 int index;
56 spinlock_t lock;
57 void __iomem *i2c_bussel_reg;
58 void __iomem *i2c_control_regs;
59 unsigned char own, clock;
60
61 wait_queue_head_t wq;
62 volatile int waiting;
63
64 struct list_head temps;
65 struct list_head fans;
66
67 struct of_device *op;
68 struct {
69 struct of_device *device;
70 int client_claimed;
71 } devs[NUM_CHILDREN];
72};
8 73
9/* Probing and attachment. */ 74/* Probing and attachment. */
10extern struct linux_ebus_child *bbc_i2c_getdev(int); 75extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int);
11extern struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *); 76extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *);
12extern void bbc_i2c_detach(struct bbc_i2c_client *); 77extern void bbc_i2c_detach(struct bbc_i2c_client *);
13 78
14/* Register read/write. NOTE: Blocking! */ 79/* Register read/write. NOTE: Blocking! */