diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-30 01:34:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-30 01:34:14 -0400 |
commit | e21e245bcd9d5244735799387d14421789b20557 (patch) | |
tree | d8bfe0be5ac850764203b440566ef279cd47c7b5 /drivers/sbus/char/bbc_envctrl.c | |
parent | 6b8c90f24e24505f97efaef1a46572d6b45929b9 (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/char/bbc_envctrl.c')
-rw-r--r-- | drivers/sbus/char/bbc_envctrl.c | 121 |
1 files changed, 38 insertions, 83 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 | ||
78 | enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; | 78 | static LIST_HEAD(all_temps); |
79 | 79 | static LIST_HEAD(all_fans); | |
80 | struct 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 | |||
101 | struct bbc_cpu_temperature *all_bbc_temps; | ||
102 | |||
103 | struct 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 | |||
114 | struct 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 | ||
480 | static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | 445 | static 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 | ||
527 | static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | 490 | static 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 | ||
566 | int bbc_envctrl_init(void) | 525 | int 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 | ||
600 | void bbc_envctrl_cleanup(void) | 559 | void 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 | } |