aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus/char/bbc_envctrl.c
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/char/bbc_envctrl.c
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/char/bbc_envctrl.c')
-rw-r--r--drivers/sbus/char/bbc_envctrl.c121
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
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}