in char/envctrl.c [860:950]
static void envctrl_init_i2c_child(struct device_node *dp,
struct i2c_child_t *pchild)
{
int len, i, tbls_size = 0;
const void *pval;
/* Get device address. */
pval = of_get_property(dp, "reg", &len);
memcpy(&pchild->addr, pval, len);
/* Get tables property. Read firmware temperature tables. */
pval = of_get_property(dp, "translation", &len);
if (pval && len > 0) {
memcpy(pchild->tblprop_array, pval, len);
pchild->total_tbls = len / sizeof(struct pcf8584_tblprop);
for (i = 0; i < pchild->total_tbls; i++) {
if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) {
tbls_size = pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset;
}
}
pchild->tables = kmalloc(tbls_size, GFP_KERNEL);
if (pchild->tables == NULL){
printk(KERN_ERR PFX "Failed to allocate table.\n");
return;
}
pval = of_get_property(dp, "tables", &len);
if (!pval || len <= 0) {
printk(KERN_ERR PFX "Failed to get table.\n");
return;
}
memcpy(pchild->tables, pval, len);
}
/* 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) {
struct device_node *root_node;
int len;
root_node = of_find_node_by_path("/");
if (of_node_name_eq(root_node, "SUNW,UltraSPARC-IIi-cEngine")) {
for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
pchild->mon_type[len] = ENVCTRL_NOMON;
}
of_node_put(root_node);
return;
}
of_node_put(root_node);
}
/* Get the monitor channels. */
pval = of_get_property(dp, "channels-in-use", &len);
memcpy(pchild->chnl_array, pval, len);
pchild->total_chnls = len / sizeof(struct pcf8584_channel);
for (i = 0; i < pchild->total_chnls; i++) {
switch (pchild->chnl_array[i].type) {
case PCF8584_TEMP_TYPE:
envctrl_init_adc(pchild, dp);
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;
break;
case PCF8584_VOLTAGE_TYPE:
if (pchild->i2ctype == I2C_ADC) {
envctrl_init_adc(pchild,dp);
} else {
envctrl_init_voltage_status(pchild);
}
i = pchild->total_chnls;
break;
default:
break;
}
}
}