in pc87360.c [1193:1345]
static int pc87360_probe(struct platform_device *pdev)
{
int i;
struct pc87360_data *data;
int err = 0;
const char *name;
int use_thermistors = 0;
struct device *dev = &pdev->dev;
data = devm_kzalloc(dev, sizeof(struct pc87360_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
switch (devid) {
default:
name = "pc87360";
data->fannr = 2;
break;
case 0xe8:
name = "pc87363";
data->fannr = 2;
break;
case 0xe4:
name = "pc87364";
data->fannr = 3;
break;
case 0xe5:
name = "pc87365";
data->fannr = extra_isa[0] ? 3 : 0;
data->innr = extra_isa[1] ? 11 : 0;
data->tempnr = extra_isa[2] ? 2 : 0;
break;
case 0xe9:
name = "pc87366";
data->fannr = extra_isa[0] ? 3 : 0;
data->innr = extra_isa[1] ? 14 : 0;
data->tempnr = extra_isa[2] ? 3 : 0;
break;
}
data->name = name;
mutex_init(&data->lock);
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
for (i = 0; i < LDNI_MAX; i++) {
data->address[i] = extra_isa[i];
if (data->address[i]
&& !devm_request_region(dev, extra_isa[i], PC87360_EXTENT,
pc87360_driver.driver.name)) {
dev_err(dev,
"Region 0x%x-0x%x already in use!\n",
extra_isa[i], extra_isa[i]+PC87360_EXTENT-1);
return -EBUSY;
}
}
/* Retrieve the fans configuration from Super-I/O space */
if (data->fannr)
data->fan_conf = confreg[0] | (confreg[1] << 8);
/*
* Use the correct reference voltage
* Unless both the VLM and the TMS logical devices agree to
* use an external Vref, the internal one is used.
*/
if (data->innr) {
i = pc87360_read_value(data, LD_IN, NO_BANK,
PC87365_REG_IN_CONFIG);
if (data->tempnr) {
i &= pc87360_read_value(data, LD_TEMP, NO_BANK,
PC87365_REG_TEMP_CONFIG);
}
data->in_vref = (i&0x02) ? 3025 : 2966;
dev_dbg(dev, "Using %s reference voltage\n",
(i&0x02) ? "external" : "internal");
data->vid_conf = confreg[3];
data->vrm = vid_which_vrm();
}
/* Fan clock dividers may be needed before any data is read */
for (i = 0; i < data->fannr; i++) {
if (FAN_CONFIG_MONITOR(data->fan_conf, i))
data->fan_status[i] = pc87360_read_value(data,
LD_FAN, NO_BANK,
PC87360_REG_FAN_STATUS(i));
}
if (init > 0) {
if (devid == 0xe9 && data->address[1]) /* PC87366 */
use_thermistors = confreg[2] & 0x40;
pc87360_init_device(pdev, use_thermistors);
}
/* Register all-or-nothing sysfs groups */
if (data->innr) {
err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group);
if (err)
goto error;
}
if (data->innr == 14) {
err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group);
if (err)
goto error;
}
/* create device attr-files for varying sysfs groups */
if (data->tempnr) {
for (i = 0; i < data->tempnr; i++) {
err = sysfs_create_group(&dev->kobj,
&pc8736x_temp_attr_group[i]);
if (err)
goto error;
}
err = device_create_file(dev, &dev_attr_alarms_temp);
if (err)
goto error;
}
for (i = 0; i < data->fannr; i++) {
if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
err = sysfs_create_group(&dev->kobj,
&pc8736x_fan_attr_group[i]);
if (err)
goto error;
}
if (FAN_CONFIG_CONTROL(data->fan_conf, i)) {
err = device_create_file(dev, &pwm[i].dev_attr);
if (err)
goto error;
}
}
err = device_create_file(dev, &dev_attr_name);
if (err)
goto error;
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto error;
}
return 0;
error:
pc87360_remove_files(dev);
return err;
}