static int ds620_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct ds620_data *data; data = devm_kzalloc(dev, sizeof(struct ds620_data), GFP_KERNEL); if (!data) return -ENOMEM; data->client = client; mutex_init(&data->update_lock); /* Initialize the DS620 chip */ ds620_init_client(client); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, ds620_groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int ltc4260_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct regmap *regmap; regmap = devm_regmap_init_i2c(client, <c4260_regmap_config); if (IS_ERR(regmap)) { dev_err(dev, "failed to allocate register map\n"); return PTR_ERR(regmap); } /* Clear faults */ regmap_write(regmap, LTC4260_FAULT, 0x00); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, regmap, ltc4260_groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int lm78_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct lm78_data *data; data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL); if (!data) return -ENOMEM; data->client = client; data->type = id->driver_data; /* Initialize the LM78 chip */ lm78_init_device(data); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, lm78_groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int lm63_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct lm63_data *data; int groups = 0; data = devm_kzalloc(dev, sizeof(struct lm63_data), GFP_KERNEL); if (!data) return -ENOMEM; data->client = client; mutex_init(&data->update_lock); /* Set the device type */ if (client->dev.of_node) data->kind = (enum chips)of_device_get_match_data(&client->dev); else data->kind = id->driver_data; if (data->kind == lm64) data->temp2_offset = 16000; /* Initialize chip */ lm63_init_client(data); /* Register sysfs hooks */ data->groups[groups++] = &lm63_group; if (data->config & 0x04) /* tachometer enabled */ data->groups[groups++] = &lm63_group_fan1; if (data->kind == lm96163) { data->groups[groups++] = &lm63_group_temp2_type; data->groups[groups++] = &lm63_group_extra_lut; } hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, data->groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int lm92_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { struct device *hwmon_dev; struct lm92_data *data; data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data), GFP_KERNEL); if (!data) return -ENOMEM; data->client = new_client; mutex_init(&data->update_lock); /* Initialize the chipset */ lm92_init_client(new_client); hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev, new_client->name, data, lm92_groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int tmp421_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct tmp421_data *data; int err; data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL); if (!data) return -ENOMEM; mutex_init(&data->update_lock); data->channels = id->driver_data; data->client = client; err = tmp421_init_client(client); if (err) return err; hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, tmp421_groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
/* called from igb_main.c */ int igb_sysfs_init(struct igb_adapter *adapter) { struct hwmon_buff *igb_hwmon; struct i2c_client *client; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) struct device *hwmon_dev; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) */ unsigned int i; int rc = 0; /* If this method isn't defined we don't support thermals */ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) goto exit; /* Don't create thermal hwmon interface if no sensors present */ rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)); if (rc) goto exit; igb_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*igb_hwmon), GFP_KERNEL); if (!igb_hwmon) { rc = -ENOMEM; goto exit; } adapter->igb_hwmon_buff = igb_hwmon; for (i = 0; i < E1000_MAX_SENSORS; i++) { /* Only create hwmon sysfs entries for sensors that have * meaningful data. */ if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) continue; /* Bail if any hwmon attr struct fails to initialize */ rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION); if (rc) goto exit; rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC); if (rc) goto exit; rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP); if (rc) goto exit; rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX); if (rc) goto exit; } /* init i2c_client */ client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); if (client == NULL) { dev_info(&adapter->pdev->dev, "Failed to create new i2c device.\n"); rc = -ENODEV; goto exit; } adapter->i2c_client = client; igb_hwmon->groups[0] = &igb_hwmon->group; igb_hwmon->group.attrs = igb_hwmon->attrs; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, client->name, igb_hwmon, igb_hwmon->groups); if (IS_ERR(hwmon_dev)) { rc = PTR_ERR(hwmon_dev); goto err; } goto exit; err: #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) */ igb_sysfs_del_adapter(adapter); exit: return rc; }
static int sun4i_ts_probe(struct platform_device *pdev) { struct sun4i_ts_data *ts; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device *hwmon; int error; u32 reg; bool ts_attached; u32 tp_sensitive_adjust = 15; u32 filter_type = 1; ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); if (!ts) return -ENOMEM; ts->dev = dev; ts->ignore_fifo_data = true; ts->temp_data = -1; if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { /* Allwinner SDK has temperature (C) = (value / 6) - 271 */ ts->temp_offset = 271000; ts->temp_step = 167; } else if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) { /* * The A10 temperature sensor has quite a wide spread, these * parameters are based on the averaging of the calibration * results of 4 completely different boards, with a spread of * temp_step from 0.096 - 0.170 and temp_offset from 176 - 331. */ ts->temp_offset = 257000; ts->temp_step = 133; } else { /* * The user manuals do not contain the formula for calculating * the temperature. The formula used here is from the AXP209, * which is designed by X-Powers, an affiliate of Allwinner: * * temperature (C) = (value * 0.1) - 144.7 * * Allwinner does not have any documentation whatsoever for * this hardware. Moreover, it is claimed that the sensor * is inaccurate and cannot work properly. */ ts->temp_offset = 144700; ts->temp_step = 100; } ts_attached = of_property_read_bool(np, "allwinner,ts-attached"); if (ts_attached) { ts->input = devm_input_allocate_device(dev); if (!ts->input) return -ENOMEM; ts->input->name = pdev->name; ts->input->phys = "sun4i_ts/input0"; ts->input->open = sun4i_ts_open; ts->input->close = sun4i_ts_close; ts->input->id.bustype = BUS_HOST; ts->input->id.vendor = 0x0001; ts->input->id.product = 0x0001; ts->input->id.version = 0x0100; ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); __set_bit(BTN_TOUCH, ts->input->keybit); input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0); input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0); input_set_drvdata(ts->input, ts); } ts->base = devm_ioremap_resource(dev, platform_get_resource(pdev, IORESOURCE_MEM, 0)); if (IS_ERR(ts->base)) return PTR_ERR(ts->base); ts->irq = platform_get_irq(pdev, 0); error = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts); if (error) return error; /* * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192, * t_acq = clkin / (16 * 64) */ writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63), ts->base + TP_CTRL0); /* * tp_sensitive_adjust is an optional property * tp_mode = 0 : only x and y coordinates, as we don't use dual touch */ of_property_read_u32(np, "allwinner,tp-sensitive-adjust", &tp_sensitive_adjust); writel(TP_SENSITIVE_ADJUST(tp_sensitive_adjust) | TP_MODE_SELECT(0), ts->base + TP_CTRL2); /* * Enable median and averaging filter, optional property for * filter type. */ of_property_read_u32(np, "allwinner,filter-type", &filter_type); writel(FILTER_EN(1) | FILTER_TYPE(filter_type), ts->base + TP_CTRL3); /* Enable temperature measurement, period 1953 (2 seconds) */ writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); /* * Set stylus up debounce to aprox 10 ms, enable debounce, and * finally enable tp mode. */ reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) reg |= SUN6I_TP_MODE_EN(1); else reg |= TP_MODE_EN(1); writel(reg, ts->base + TP_CTRL1); /* * The thermal core does not register hwmon devices for DT-based * thermal zone sensors, such as this one. */ hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts", ts, sun4i_ts_groups); if (IS_ERR(hwmon)) return PTR_ERR(hwmon); devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, &sun4i_ts_tz_ops); writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); if (ts_attached) { error = input_register_device(ts->input); if (error) { writel(0, ts->base + TP_INT_FIFOC); return error; } } platform_set_drvdata(pdev, ts); return 0; }
static int tmp102_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct device *hwmon_dev; struct tmp102 *tmp102; unsigned int regval; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { dev_err(dev, "adapter doesn't support SMBus word transactions\n"); return -ENODEV; } tmp102 = devm_kzalloc(dev, sizeof(*tmp102), GFP_KERNEL); if (!tmp102) return -ENOMEM; i2c_set_clientdata(client, tmp102); tmp102->regmap = devm_regmap_init_i2c(client, &tmp102_regmap_config); if (IS_ERR(tmp102->regmap)) return PTR_ERR(tmp102->regmap); err = regmap_read(tmp102->regmap, TMP102_CONF_REG, ®val); if (err < 0) { dev_err(dev, "error reading config register\n"); return err; } if ((regval & ~TMP102_CONFREG_MASK) != (TMP102_CONF_R0 | TMP102_CONF_R1)) { dev_err(dev, "unexpected config register value\n"); return -ENODEV; } tmp102->config_orig = regval; devm_add_action(dev, tmp102_restore_config, tmp102); regval &= ~TMP102_CONFIG_CLEAR; regval |= TMP102_CONFIG_SET; err = regmap_write(tmp102->regmap, TMP102_CONF_REG, regval); if (err < 0) { dev_err(dev, "error writing config register\n"); return err; } tmp102->ready_time = jiffies; if (tmp102->config_orig & TMP102_CONF_SD) { /* * Mark that we are not ready with data until the first * conversion is complete */ tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS); } hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, tmp102, tmp102_groups); if (IS_ERR(hwmon_dev)) { dev_dbg(dev, "unable to register hwmon device\n"); return PTR_ERR(hwmon_dev); } devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, &tmp102_of_thermal_ops); dev_info(dev, "initialized\n"); return 0; }
static int pem_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; struct device *dev = &client->dev; struct device *hwmon_dev; struct pem_data *data; int ret, idx = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_BYTE)) return -ENODEV; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; data->client = client; mutex_init(&data->update_lock); /* * We use the next two commands to determine if the device is really * there. */ ret = pem_read_block(client, PEM_READ_FIRMWARE_REV, data->firmware_rev, sizeof(data->firmware_rev)); if (ret < 0) return ret; ret = i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS); if (ret < 0) return ret; dev_info(dev, "Firmware revision %d.%d.%d\n", data->firmware_rev[0], data->firmware_rev[1], data->firmware_rev[2]); /* sysfs hooks */ data->groups[idx++] = &pem_group; /* * Check if input readings are supported. * This is the case if we can read input data, * and if the returned data is not all zeros. * Note that input alarms are always supported. */ ret = pem_read_block(client, PEM_READ_INPUT_STRING, data->input_string, sizeof(data->input_string) - 1); if (!ret && (data->input_string[0] || data->input_string[1] || data->input_string[2])) data->input_length = sizeof(data->input_string) - 1; else if (ret < 0) { /* Input string is one byte longer for some devices */ ret = pem_read_block(client, PEM_READ_INPUT_STRING, data->input_string, sizeof(data->input_string)); if (!ret && (data->input_string[0] || data->input_string[1] || data->input_string[2] || data->input_string[3])) data->input_length = sizeof(data->input_string); } if (data->input_length) data->groups[idx++] = &pem_input_group; /* * Check if fan speed readings are supported. * This is the case if we can read fan speed data, * and if the returned data is not all zeros. * Note that the fan alarm is always supported. */ ret = pem_read_block(client, PEM_READ_FAN_SPEED, data->fan_speed, sizeof(data->fan_speed)); if (!ret && (data->fan_speed[0] || data->fan_speed[1] || data->fan_speed[2] || data->fan_speed[3])) { data->fans_supported = true; data->groups[idx++] = &pem_fan_group; } hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, data->groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
/* * sysfs hook function */ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct twl4030_madc_request req = { .channels = 1 << attr->index, .method = TWL4030_MADC_SW2, .type = TWL4030_MADC_WAIT, }; long val; val = twl4030_madc_conversion(&req); if (val < 0) return val; return sprintf(buf, "%d\n", req.rbuf[attr->index]); } /* sysfs nodes to read individual channels from user side */ static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2); static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3); static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4); static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7); static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8); static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9); static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10); static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); static struct attribute *twl4030_madc_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, &sensor_dev_attr_in8_input.dev_attr.attr, &sensor_dev_attr_in9_input.dev_attr.attr, &sensor_dev_attr_curr10_input.dev_attr.attr, &sensor_dev_attr_in11_input.dev_attr.attr, &sensor_dev_attr_in12_input.dev_attr.attr, &sensor_dev_attr_in15_input.dev_attr.attr, NULL }; ATTRIBUTE_GROUPS(twl4030_madc); static int twl4030_madc_hwmon_probe(struct platform_device *pdev) { struct device *hwmon; hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "twl4030_madc", NULL, twl4030_madc_groups); return PTR_ERR_OR_ZERO(hwmon); } static struct platform_driver twl4030_madc_hwmon_driver = { .probe = twl4030_madc_hwmon_probe, .driver = { .name = "twl4030_madc_hwmon", .owner = THIS_MODULE, }, }; module_platform_driver(twl4030_madc_hwmon_driver); MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("J Keerthy"); MODULE_ALIAS("platform:twl4030_madc_hwmon");
static int sun4i_ts_probe(struct platform_device *pdev) { struct sun4i_ts_data *ts; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device *hwmon; int error; bool ts_attached; ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); if (!ts) return -ENOMEM; ts->dev = dev; ts->ignore_fifo_data = true; ts->temp_data = -1; ts_attached = of_property_read_bool(np, "allwinner,ts-attached"); if (ts_attached) { ts->input = devm_input_allocate_device(dev); if (!ts->input) return -ENOMEM; ts->input->name = pdev->name; ts->input->phys = "sun4i_ts/input0"; ts->input->open = sun4i_ts_open; ts->input->close = sun4i_ts_close; ts->input->id.bustype = BUS_HOST; ts->input->id.vendor = 0x0001; ts->input->id.product = 0x0001; ts->input->id.version = 0x0100; ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); __set_bit(BTN_TOUCH, ts->input->keybit); input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0); input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0); input_set_drvdata(ts->input, ts); } ts->base = devm_ioremap_resource(dev, platform_get_resource(pdev, IORESOURCE_MEM, 0)); if (IS_ERR(ts->base)) return PTR_ERR(ts->base); ts->irq = platform_get_irq(pdev, 0); error = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts); if (error) return error; /* * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192, * t_acq = clkin / (16 * 64) */ writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63), ts->base + TP_CTRL0); /* * sensitive_adjust = 15 : max, which is not all that sensitive, * tp_mode = 0 : only x and y coordinates, as we don't use dual touch */ writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0), ts->base + TP_CTRL2); /* Enable median filter, type 1 : 5/3 */ writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3); /* Enable temperature measurement, period 1953 (2 seconds) */ writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); /* * Set stylus up debounce to aprox 10 ms, enable debounce, and * finally enable tp mode. */ writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1), ts->base + TP_CTRL1); hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts", ts, sun4i_ts_groups); if (IS_ERR(hwmon)) return PTR_ERR(hwmon); writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); if (ts_attached) { error = input_register_device(ts->input); if (error) { writel(0, ts->base + TP_INT_FIFOC); return error; } } platform_set_drvdata(pdev, ts); return 0; }
static int iio_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_hwmon_state *st; struct sensor_device_attribute *a; int ret, i; int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1; enum iio_chan_type type; struct iio_channel *channels; const char *name = "iio_hwmon"; struct device *hwmon_dev; char *sname; if (dev->of_node && dev->of_node->name) name = dev->of_node->name; channels = devm_iio_channel_get_all(dev); if (IS_ERR(channels)) { if (PTR_ERR(channels) == -ENODEV) return -EPROBE_DEFER; return PTR_ERR(channels); } st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); if (st == NULL) return -ENOMEM; st->channels = channels; /* count how many attributes we have */ while (st->channels[st->num_channels].indio_dev) st->num_channels++; st->attrs = devm_kcalloc(dev, st->num_channels + 1, sizeof(*st->attrs), GFP_KERNEL); if (st->attrs == NULL) return -ENOMEM; for (i = 0; i < st->num_channels; i++) { a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL); if (a == NULL) return -ENOMEM; sysfs_attr_init(&a->dev_attr.attr); ret = iio_get_channel_type(&st->channels[i], &type); if (ret < 0) return ret; switch (type) { case IIO_VOLTAGE: a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "in%d_input", in_i++); break; case IIO_TEMP: a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "temp%d_input", temp_i++); break; case IIO_CURRENT: a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "curr%d_input", curr_i++); break; case IIO_HUMIDITYRELATIVE: a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "humidity%d_input", humidity_i++); break; default: return -EINVAL; } if (a->dev_attr.attr.name == NULL) return -ENOMEM; a->dev_attr.show = iio_hwmon_read_val; a->dev_attr.attr.mode = S_IRUGO; a->index = i; st->attrs[i] = &a->dev_attr.attr; } st->attr_group.attrs = st->attrs; st->groups[0] = &st->attr_group; sname = devm_kstrdup(dev, name, GFP_KERNEL); if (!sname) return -ENOMEM; strreplace(sname, '-', '_'); hwmon_dev = devm_hwmon_device_register_with_groups(dev, sname, st, st->groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
/* * Module stuff */ static int imanager_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct imanager_device_data *ec = dev_get_drvdata(dev->parent); struct imanager_hwmon_data *data; struct device *hwmon_dev; int err, i, num_attr_groups = 0; if (!ec) { dev_err(dev, "Invalid platform data\n"); return -EINVAL; } err = hwm_core_init(); if (err) { dev_err(dev, "Hwmon core init failed\n"); return -EIO; } data = devm_kzalloc(dev, sizeof(struct imanager_hwmon_data), GFP_KERNEL); if (!data) return -ENOMEM; data->ec = ec; platform_set_drvdata(pdev, data); data->adc_num = hwm_core_adc_get_max_count(); data->fan_num = hwm_core_fan_get_max_count(); for (i = 0; i < data->fan_num; i++) { /* set active fan to automatic speed control */ hwm_core_fan_set_ctrl(i, MODE_AUTO, CTRL_RPM, 0, 0, NULL, NULL); hwm_core_fan_get_ctrl(i, &data->hwm.fan[i]); } data->groups[num_attr_groups++] = &imanager_group_in; if (data->adc_num > 3) data->groups[num_attr_groups++] = &imanager_group_other; if (data->fan_num) data->groups[num_attr_groups++] = &imanager_group_fan; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) err = sysfs_create_groups(&dev->kobj, data->groups); if (err < 0) return err; hwmon_dev = hwmon_device_register(dev); if (IS_ERR(hwmon_dev)) { sysfs_remove_groups(&dev->kobj, data->groups); return PTR_ERR(data->hwmon_dev); } data->hwmon_dev = hwmon_dev; #else hwmon_dev = devm_hwmon_device_register_with_groups(dev, "imanager_hwmon", data, data->groups); #endif return PTR_ERR_OR_ZERO(hwmon_dev); }
static int nct6683_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct nct6683_sio_data *sio_data = dev->platform_data; struct attribute_group *group; struct nct6683_data *data; struct device *hwmon_dev; struct resource *res; int groups = 0; char build[16]; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME)) return -EBUSY; data = devm_kzalloc(dev, sizeof(struct nct6683_data), GFP_KERNEL); if (!data) return -ENOMEM; data->kind = sio_data->kind; data->sioreg = sio_data->sioreg; data->addr = res->start; mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); data->customer_id = nct6683_read16(data, NCT6683_REG_CUSTOMER_ID); /* By default only instantiate driver if the customer ID is known */ switch (data->customer_id) { case NCT6683_CUSTOMER_ID_INTEL: break; case NCT6683_CUSTOMER_ID_MITAC: break; default: if (!force) return -ENODEV; } nct6683_init_device(data); nct6683_setup_fans(data); nct6683_setup_sensors(data); /* Register sysfs hooks */ if (data->have_pwm) { group = nct6683_create_attr_group(dev, &nct6683_pwm_template_group, fls(data->have_pwm)); if (IS_ERR(group)) return PTR_ERR(group); data->groups[groups++] = group; } if (data->in_num) { group = nct6683_create_attr_group(dev, &nct6683_in_template_group, data->in_num); if (IS_ERR(group)) return PTR_ERR(group); data->groups[groups++] = group; } if (data->have_fan) { group = nct6683_create_attr_group(dev, &nct6683_fan_template_group, fls(data->have_fan)); if (IS_ERR(group)) return PTR_ERR(group); data->groups[groups++] = group; } if (data->temp_num) { group = nct6683_create_attr_group(dev, &nct6683_temp_template_group, data->temp_num); if (IS_ERR(group)) return PTR_ERR(group); data->groups[groups++] = group; } data->groups[groups++] = &nct6683_group_other; if (data->customer_id == NCT6683_CUSTOMER_ID_INTEL) scnprintf(build, sizeof(build), "%02x/%02x/%02x", nct6683_read(data, NCT6683_REG_BUILD_MONTH), nct6683_read(data, NCT6683_REG_BUILD_DAY), nct6683_read(data, NCT6683_REG_BUILD_YEAR)); else scnprintf(build, sizeof(build), "%02d/%02d/%02d", nct6683_read(data, NCT6683_REG_BUILD_MONTH), nct6683_read(data, NCT6683_REG_BUILD_DAY), nct6683_read(data, NCT6683_REG_BUILD_YEAR)); dev_info(dev, "%s EC firmware version %d.%d build %s\n", nct6683_chip_names[data->kind], nct6683_read(data, NCT6683_REG_VERSION_HI), nct6683_read(data, NCT6683_REG_VERSION_LO), build); hwmon_dev = devm_hwmon_device_register_with_groups(dev, nct6683_device_names[data->kind], data, data->groups); return PTR_ERR_OR_ZERO(hwmon_dev); }