21 #include <linux/module.h>
28 #include <linux/reboot.h>
29 #include <linux/slab.h>
33 #include <asm/uaccess.h>
37 #define DRIVER_NAME "envctrl"
38 #define PFX DRIVER_NAME ": "
40 #define ENVCTRL_MINOR 162
42 #define PCF8584_ADDRESS 0x55
44 #define CONTROL_PIN 0x80
45 #define CONTROL_ES0 0x40
46 #define CONTROL_ES1 0x20
47 #define CONTROL_ES2 0x10
48 #define CONTROL_ENI 0x08
49 #define CONTROL_STA 0x04
50 #define CONTROL_STO 0x02
51 #define CONTROL_ACK 0x01
53 #define STATUS_PIN 0x80
54 #define STATUS_STS 0x20
55 #define STATUS_BER 0x10
56 #define STATUS_LRB 0x08
57 #define STATUS_AD0 0x08
58 #define STATUS_AAB 0x04
59 #define STATUS_LAB 0x02
60 #define STATUS_BB 0x01
65 #define BUS_CLK_90 0x00
66 #define BUS_CLK_45 0x01
67 #define BUS_CLK_11 0x02
68 #define BUS_CLK_1_5 0x03
76 #define OBD_SEND_START 0xc5
77 #define OBD_SEND_STOP 0xc3
82 #define PCF8584_MAX_CHANNELS 8
83 #define PCF8584_GLOBALADDR_TYPE 6
84 #define PCF8584_FANSTAT_TYPE 3
85 #define PCF8584_VOLTAGE_TYPE 2
86 #define PCF8584_TEMP_TYPE 1
91 #define ENVCTRL_NOMON 0
92 #define ENVCTRL_CPUTEMP_MON 1
93 #define ENVCTRL_CPUVOLTAGE_MON 2
94 #define ENVCTRL_FANSTAT_MON 3
95 #define ENVCTRL_ETHERTEMP_MON 4
97 #define ENVCTRL_VOLTAGESTAT_MON 5
98 #define ENVCTRL_MTHRBDTEMP_MON 6
99 #define ENVCTRL_SCSITEMP_MON 7
100 #define ENVCTRL_GLOBALADDR_MON 8
112 #define ENVCTRL_TRANSLATE_NO 0
113 #define ENVCTRL_TRANSLATE_PARTIAL 1
114 #define ENVCTRL_TRANSLATE_COMBINED 2
115 #define ENVCTRL_TRANSLATE_FULL 3
116 #define ENVCTRL_TRANSLATE_SCALE 4
119 #define ENVCTRL_MAX_CPU 4
120 #define CHANNEL_DESC_SZ 256
123 #define ENVCTRL_GLOBALADDR_ADDR_MASK 0x1F
124 #define ENVCTRL_GLOBALADDR_PSTAT_MASK 0x60
129 #define ENVCTRL_CPCI_IGNORED_NODE 0x70
131 #define PCF8584_DATA 0x00
132 #define PCF8584_CSR 0x01
176 static unsigned char chnls_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
177 static unsigned int warning_temperature = 0;
178 static unsigned int shutdown_temperature = 0;
179 static char read_cpu;
182 static struct i2c_child_t *envctrl_get_i2c_child(
unsigned char);
188 static void envtrl_i2c_test_pin(
void)
192 while (--limit > 0) {
205 static void envctrl_i2c_test_bb(
void)
209 while (--limit > 0) {
223 static int envctrl_i2c_read_addr(
unsigned char addr)
225 envctrl_i2c_test_bb();
230 envctrl_i2c_test_bb();
235 envtrl_i2c_test_pin();
249 static void envctrl_i2c_write_addr(
unsigned char addr)
251 envctrl_i2c_test_bb();
262 static unsigned char envctrl_i2c_read_data(
void)
264 envtrl_i2c_test_pin();
272 static void envctrl_i2c_write_data(
unsigned char port)
274 envtrl_i2c_test_pin();
281 static void envctrl_i2c_stop(
void)
283 envtrl_i2c_test_pin();
290 static unsigned char envctrl_i2c_read_8591(
unsigned char addr,
unsigned char port)
293 envctrl_i2c_write_addr(addr);
296 envctrl_i2c_write_data(port);
300 envctrl_i2c_read_addr(addr);
303 envctrl_i2c_read_data();
312 static unsigned char envctrl_i2c_read_8574(
unsigned char addr)
316 envctrl_i2c_read_addr(addr);
319 rd = envctrl_i2c_read_data();
328 static int envctrl_i2c_data_translate(
unsigned char data,
int translate_type,
329 int scale,
char *tbl,
char *bufdata)
333 switch (translate_type) {
343 bufdata[0] = tbl[
data];
348 sprintf(bufdata,
"%d ", (tbl[data] * 10) / (scale));
350 bufdata[len - 1] = bufdata[len - 2];
351 bufdata[len - 2] =
'.';
364 static int envctrl_read_cpu_info(
int cpu,
struct i2c_child_t *pchild,
365 char mon_type,
unsigned char *bufdata)
373 if (pchild->
mon_type[i] == mon_type) {
384 data = envctrl_i2c_read_8591((
unsigned char)pchild->
addr,
385 (
unsigned char)pchild->
chnl_array[i].chnl_no);
390 return envctrl_i2c_data_translate(data, pchild->
tblprop_array[i].type,
399 static int envctrl_read_noncpu_info(
struct i2c_child_t *pchild,
400 char mon_type,
unsigned char *bufdata)
407 if (pchild->
mon_type[i] == mon_type)
411 if (i >= PCF8584_MAX_CHANNELS)
415 data = envctrl_i2c_read_8591((
unsigned char)pchild->
addr,
416 (
unsigned char)pchild->
chnl_array[i].chnl_no);
421 return envctrl_i2c_data_translate(data, pchild->
tblprop_array[i].type,
429 static int envctrl_i2c_fan_status(
struct i2c_child_t *pchild,
433 unsigned char tmp,
ret = 0;
441 }
else if (tmp == 0) {
452 if (pchild->
fan_mask & chnls_mask[i]) {
453 if (!(chnls_mask[i] & tmp))
454 ret |= chnls_mask[
j];
468 static int envctrl_i2c_globaladdr(
struct i2c_child_t *pchild,
493 static unsigned char envctrl_i2c_voltage_status(
struct i2c_child_t *pchild,
497 unsigned char tmp, ret = 0;
506 }
else if (tmp == 0) {
516 if (!(chnls_mask[i] & tmp))
539 envctrl_read(
struct file *
file,
char __user *
buf,
size_t count, loff_t *ppos)
542 unsigned char data[10];
552 if (warning_temperature == 0)
555 data[0] = (
unsigned char)(warning_temperature);
562 if (shutdown_temperature == 0)
565 data[0] = (
unsigned char)(shutdown_temperature);
618 data[0] = envctrl_i2c_read_8574(pchild->
addr);
619 ret = envctrl_i2c_fan_status(pchild,data[0], data);
627 data[0] = envctrl_i2c_read_8574(pchild->
addr);
628 ret = envctrl_i2c_globaladdr(pchild, data[0], data);
638 data[0] = envctrl_i2c_read_8574(pchild->
addr);
639 ret = envctrl_i2c_voltage_status(pchild, data[0], data);
656 envctrl_ioctl(
struct file *file,
unsigned int cmd,
unsigned long arg)
677 infobuf = (
char __user *) arg;
678 if (infobuf ==
NULL) {
699 envctrl_open(
struct inode *
inode,
struct file *file)
709 envctrl_release(
struct inode *
inode,
struct file *file)
716 .read = envctrl_read,
717 .unlocked_ioctl = envctrl_ioctl,
719 .compat_ioctl = envctrl_ioctl,
721 .open = envctrl_open,
722 .release = envctrl_release,
735 static void envctrl_set_mon(
struct i2c_child_t *pchild,
736 const char *chnl_desc,
743 if (!(
strcmp(chnl_desc,
"temp,cpu")) ||
744 !(
strcmp(chnl_desc,
"temp,cpu0")) ||
745 !(
strcmp(chnl_desc,
"temp,cpu1")) ||
746 !(
strcmp(chnl_desc,
"temp,cpu2")) ||
747 !(
strcmp(chnl_desc,
"temp,cpu3")))
750 if (!(
strcmp(chnl_desc,
"vddcore,cpu0")) ||
751 !(
strcmp(chnl_desc,
"vddcore,cpu1")) ||
752 !(
strcmp(chnl_desc,
"vddcore,cpu2")) ||
753 !(
strcmp(chnl_desc,
"vddcore,cpu3")))
756 if (!(
strcmp(chnl_desc,
"temp,motherboard")))
759 if (!(
strcmp(chnl_desc,
"temp,scsi")))
762 if (!(
strcmp(chnl_desc,
"temp,ethernet")))
774 const unsigned int *pval;
781 envctrl_set_mon(pchild, pos, i++);
789 warning_temperature = *pval;
793 shutdown_temperature = *pval;
799 static void envctrl_init_fanstat(
struct i2c_child_t *pchild)
816 static void envctrl_init_globaladdr(
struct i2c_child_t *pchild)
847 static void envctrl_init_voltage_status(
struct i2c_child_t *pchild)
864 static void envctrl_init_i2c_child(
struct device_node *dp,
867 int len,
i, tbls_size = 0;
876 if (pval && len > 0) {
891 if (!pval || len <= 0) {
910 if (!
strcmp(root_node->
name,
"SUNW,UltraSPARC-IIi-cEngine")) {
926 envctrl_init_adc(pchild, dp);
930 envctrl_init_globaladdr(pchild);
935 envctrl_init_fanstat(pchild);
941 envctrl_init_adc(pchild,dp);
943 envctrl_init_voltage_status(pchild);
957 static struct i2c_child_t *envctrl_get_i2c_child(
unsigned char mon_type)
963 if (i2c_childlist[i].mon_type[j] == mon_type) {
971 static void envctrl_do_shutdown(
void)
973 static int inprog = 0;
980 printk(
KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n");
990 static int kenvctrld(
void *
__unused)
999 "kenvctrld unable to monitor CPU temp-- exiting\n");
1003 poll_interval = 5000;
1013 if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
1016 if (tempbuf[0] >= shutdown_temperature) {
1018 "%s: WARNING: CPU%i temperature %i C meets or exceeds "\
1019 "shutdown threshold %i C\n",
1021 tempbuf[0], shutdown_temperature);
1022 envctrl_do_shutdown();
1044 dp = op->
dev.of_node->child;
1048 envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
1051 envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
1082 for (--index; index >= 0; --
index) {
1084 (
I2C_ADC == i2c_childlist[index].i2ctype) ?
"adc" :
1085 ((
I2C_GPIO == i2c_childlist[index].i2ctype) ?
"gpio" :
"unknown"),
1086 i2c_childlist[index].addr, (0 == index) ?
"\n" :
" ");
1090 if (IS_ERR(kenvctrld_task)) {
1091 err = PTR_ERR(kenvctrld_task);
1092 goto out_deregister;
1101 for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
1116 for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
1125 .compatible =
"i2cpcf,8584",
1135 .of_match_table = envctrl_match,
1137 .probe = envctrl_probe,