patch-2.2.18 linux/drivers/sbus/char/envctrl.c
Next file: linux/drivers/sbus/char/rtc.c
Previous file: linux/drivers/sbus/audio/Config.in
Back to the patch index
Back to the overall index
- Lines: 238
- Date:
Wed Nov 8 22:48:54 2000
- Orig file:
v2.2.17/drivers/sbus/char/envctrl.c
- Orig date:
Sun Jun 11 21:44:15 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.9.2.1 2000/05/02 04:23:33 davem Exp $
+/* $Id: envctrl.c,v 1.9.2.2 2000/11/08 09:43:04 davem Exp $
* envctrl.c: Temperature and Fan monitoring on Machines providing it.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
@@ -11,6 +11,9 @@
* http://www-eu2.semiconductors.com/pip/PCF8584P
* http://www-eu2.semiconductors.com/pip/PCF8574AP
* http://www-eu2.semiconductors.com/pip/PCF8591P
+ *
+ * EB - Added support for CP1500 Global Address and PS/Voltage monitoring.
+ * Eric Brower <ebrower@usa.net>
*
*/
@@ -74,15 +77,16 @@
* Firmware definitions.
*/
#define PCF8584_MAX_CHANNELS 8
+#define PCF8584_GLOBALADDR_TYPE 6 /* global address monitor */
#define PCF8584_FANSTAT_TYPE 3 /* fan status monitor */
#define PCF8584_VOLTAGE_TYPE 2 /* voltage monitor */
-#define PCF8584_TEMP_TYPE 1 /* temperature monitor*/
+#define PCF8584_TEMP_TYPE 1 /* temperature monitor*/
/* Monitor type of i2c child device.
* Driver definitions.
*/
-#define ENVCTRL_NOMON 0
-#define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */
+#define ENVCTRL_NOMON 0
+#define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */
#define ENVCTRL_CPUVOLTAGE_MON 2 /* voltage monitor */
#define ENVCTRL_FANSTAT_MON 3 /* fan status monitor */
#define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperarture */
@@ -90,6 +94,7 @@
#define ENVCTRL_VOLTAGESTAT_MON 5 /* voltage status monitor */
#define ENVCTRL_MTHRBDTEMP_MON 6 /* motherboard temperature */
#define ENVCTRL_SCSITEMP_MON 7 /* scsi temperarture */
+#define ENVCTRL_GLOBALADDR_MON 8 /* global address */
/* Child device type.
* Driver definitions.
@@ -111,6 +116,15 @@
#define ENVCTRL_MAX_CPU 4
#define CHANNEL_DESC_SZ 256
+/* Mask values for combined GlobalAddress/PowerStatus node */
+#define ENVCTRL_GLOBALADDR_ADDR_MASK 0x1F
+#define ENVCTRL_GLOBALADDR_PSTAT_MASK 0x60
+
+/* Node 0x70 ignored on CompactPCI CP1400/1500 platforms
+ * (see envctrl_init_i2c_child)
+ */
+#define ENVCTRL_CPCI_IGNORED_NODE 0x70
+
struct pcf8584_reg {
unsigned char data;
unsigned char csr;
@@ -198,7 +212,7 @@
int limit = 1000000;
while (--limit > 0) {
- if(!(envctrl_readb(&i2c->csr) & STATUS_PIN))
+ if (!(envctrl_readb(&i2c->csr) & STATUS_PIN))
break;
udelay(1);
}
@@ -472,6 +486,31 @@
return 1;
}
+/* Function Description: Read global addressing line.
+ * Return : Always 1 byte. Status stored in bufdata.
+ */
+static int envctrl_i2c_globaladdr(struct i2c_child_t *pchild,
+ unsigned char data,
+ char *bufdata)
+{
+ /* Translatation table is not necessary, as global
+ * addr is the integer value of the GA# bits.
+ *
+ * NOTE: MSB is documented as zero, but I see it as '1' always....
+ *
+ * -----------------------------------------------
+ * | 0 | FAL | DEG | GA4 | GA3 | GA2 | GA1 | GA0 |
+ * -----------------------------------------------
+ * GA0 - GA4 integer value of Global Address (backplane slot#)
+ * DEG 0 = cPCI Power supply output is starting to degrade
+ * 1 = cPCI Power supply output is OK
+ * FAL 0 = cPCI Power supply has failed
+ * 1 = cPCI Power supply output is OK
+ */
+ bufdata[0] = (data & ENVCTRL_GLOBALADDR_ADDR_MASK);
+ return 1;
+}
+
/* Function Description: Read voltage and power supply status.
* Return : Always 1 byte. Status stored in bufdata.
*/
@@ -598,9 +637,19 @@
copy_to_user((unsigned char*)buf, data, ret);
break;
+ case ENVCTRL_RD_GLOBALADDRESS:
+ if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON)))
+ return 0;
+ data[0] = envctrl_i2c_read_8574(pchild->addr);
+ ret = envctrl_i2c_globaladdr(pchild, data[0], data);
+ copy_to_user((unsigned char*)buf, data, ret);
+ break;
+
case ENVCTRL_RD_VOLTAGE_STATUS:
if (!(pchild = envctrl_get_i2c_child(ENVCTRL_VOLTAGESTAT_MON)))
- return 0;
+ /* If voltage monitor not present, check for CPCI equivalent */
+ if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON)))
+ return 0;
data[0] = envctrl_i2c_read_8574(pchild->addr);
ret = envctrl_i2c_voltage_status(pchild, data[0], data);
copy_to_user((unsigned char*)buf, data, ret);
@@ -631,6 +680,7 @@
case ENVCTRL_RD_VOLTAGE_STATUS:
case ENVCTRL_RD_ETHERNET_TEMPERATURE:
case ENVCTRL_RD_SCSI_TEMPERATURE:
+ case ENVCTRL_RD_GLOBALADDRESS:
file->private_data = (void *)(long)cmd;
break;
@@ -729,9 +779,6 @@
if (!(strcmp(chnl_desc,"temp,ethernet")))
pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON;
-
- if (!(strcmp(chnl_desc,"temp,ethernet")))
- pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON;
}
/* Function Description: Initialize monitor channel with channel desc,
@@ -785,6 +832,39 @@
pchild->mon_type[0] = ENVCTRL_FANSTAT_MON;
}
+/* Function Description: Initialize child device for global addressing line.
+ * Return: None.
+ */
+static void envctrl_init_globaladdr(struct i2c_child_t *pchild)
+{
+ int i;
+
+ /* Voltage/PowerSupply monitoring is piggybacked
+ * with Global Address on CompactPCI. See comments
+ * within envctrl_i2c_globaladdr for bit assignments.
+ *
+ * The mask is created here by assigning mask bits to each
+ * bit position that represents PCF8584_VOLTAGE_TYPE data.
+ * Channel numbers are not consecutive within the globaladdr
+ * node (why?), so we use the actual counter value as chnls_mask
+ * index instead of the chnl_array[x].chnl_no value.
+ *
+ * NOTE: This loop could be replaced with a constant representing
+ * a mask of bits 5&6 (ENVCTRL_GLOBALADDR_PSTAT_MASK).
+ */
+ for (i = 0; i < pchild->total_chnls; i++) {
+ if (PCF8584_VOLTAGE_TYPE == pchild->chnl_array[i].type) {
+ pchild->voltage_mask |= chnls_mask[i];
+ }
+ }
+
+ /* We only need to know if this child has global addressing
+ * line monitored. We dont care which channels since we know
+ * the mask already (ENVCTRL_GLOBALADDR_ADDR_MASK).
+ */
+ pchild->mon_type[0] = ENVCTRL_GLOBALADDR_MON;
+}
+
/* Initialize child device monitoring voltage status. */
static void envctrl_init_voltage_status(struct i2c_child_t *pchild)
{
@@ -832,6 +912,26 @@
}
}
+ /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04)
+ * sections 2.5, 3.5, 4.5 state node 0x70 for CP1400/1500 is
+ * "For Factory Use Only."
+ *
+ * We ignore the node on these platforms by assigning the
+ * 'NULL' monitor type.
+ */
+ if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) {
+ int len;
+ char prop[56];
+
+ len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
+ if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len))) {
+ for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
+ pchild->mon_type[len] = ENVCTRL_NOMON;
+ }
+ return;
+ }
+ }
+
/* Get the monitor channels. */
len = prom_getproperty(node, "channels-in-use", (char *)pchild->chnl_array,
PCF8584_MAX_CHANNELS*sizeof(struct pcf8584_channel));
@@ -843,6 +943,11 @@
envctrl_init_adc(pchild, node);
break;
+ case PCF8584_GLOBALADDR_TYPE:
+ envctrl_init_globaladdr(pchild);
+ i = pchild->total_chnls;
+ break;
+
case PCF8584_FANSTAT_TYPE:
envctrl_init_fanstat(pchild);
i = pchild->total_chnls;
@@ -940,6 +1045,18 @@
if (misc_register(&envctrl_dev)) {
printk("envctrl: Unable to get misc minor %d\n",
envctrl_dev.minor);
+ }
+
+ /* Note above traversal routine post-incremented 'i' to accomodate
+ * a next child device, so we decrement before reverse-traversal of
+ * child devices.
+ */
+ printk("envctrl: initialized ");
+ for (--i; i >= 0; --i) {
+ printk("[%s 0x%lx]%s",
+ (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") :
+ ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")),
+ i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
}
return 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)