hwmon updates for 3.13-rc1
Introduce new hwmon API functions hwmon_device_register_with_groups and devm_hwmon_device_register_with_groups, and convert several drivers to use the new API. Add support for EMC1404, EMC1424, LTC2977, LTC2978A, LM25063 to exiting drivers Various cleanups in several drivers -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJSex4PAAoJEMsfJm/On5mBVxcP/2BQMEBJppOEU6QSS1IpY2GC 9i2NW3QFPSa/2VIMY1E9PY1YNIfdHv4LZE62V+CQdmgK5soNEZtwpzFhTMrphaRI ET3kn0YmWkHYFq2VKguJPRzM3wUGq/Bt+FTF0ONKM+vl0qoxwEkDUDSBFw/zZsjv gDa+cUjVQ5E5axZ8y4u2Sf0B4l+7FXJbyVXQuHQ4a6sgwp9IVDX1MTFdb0Ih1wj9 SxGX1msZTFHRHG849NZa7msIKz/TMabaIPJQwBCb3Vh+VQtr/zmQfxTlbEDiU0WY I3BEH7td5OOdLxuuvn24IDlgd7eA9wCj0P1Rtur/ucvWeDrIaweUBri7h5qO2cbX CEc7MISeggEAszcxM7QQ2oiuy9SrDB9swNC41WbGrrMX3elmMUmI0m70RXukN/Vs uTMomKekrb6LuXUyl0x0k2hkin56rXKoNGi7oTCjMS8/IriCI2Dne1WmQnr5oOMR ImawiNuvEw79eHYJYdnXFdQfIgAm7yWWVOxQxDI3eO6HwNWzZ2oohsBKmSLUvJ7Q cfijyCuXm0TWHdGiWz7ResMEZ0oxibsWB8tym5bJM2GSJrX99t0Qj9nSN8y9mwJy FGraTnxwXZxIAamZBVRsfO/j7cUGi75yKhyKjMr81OCOSCkynGeU3in1DST0ImN1 e1XRv2z5+d95f1uXlYWu =+bF4 -----END PGP SIGNATURE----- Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "Introduce new hwmon API functions hwmon_device_register_with_groups and devm_hwmon_device_register_with_groups, and convert several drivers to use the new API. Add support for EMC1404, EMC1424, LTC2977, LTC2978A, LM25063 to existing drivers Various cleanups in several drivers" * tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (49 commits) hwmon: (w83793) Clean up a signedness issue hwmon: (nct6775) Remove an unused variable hwmon: (emc1403) Add support for EMC1404 and EMC1424 hwmon: (emc1403) Convert to use devm_hwmon_device_register_with_groups hwmon: (pmbus/ltc2978): Add support for LTC2978A hwmon: (pmbus/ltc2978): Add support for LTC2977 hwmon: (pmbus/lm25066) Add support for LM25063 hwmon: Correct some typos hwmon: (gpio-fan) Include linux/of.h header hwmon: (lm70) Remove redundant spi_set_drvdata hwmon: (adcxx) Remove redundant spi_set_drvdata hwmon: (jc42) fix coccinelle warnings hwmon: (ltc4261) fix coccinelle warnings hwmon: (lm95234) fix coccinelle warnings hwmon: (max6697) fix coccinelle warnings hwmon: (max6642 fix coccinelle warnings hwmon: (ds1621) fix coccinelle warnings hwmon: (nct6775) fix coccinelle warnings hwmon: (jc42) Convert to use devm_hwmon_device_register_with_groups hwmon: (ltc4261) Convert to use devm_hwmon_device_register_with_groups ...
This commit is contained in:
commit
7e238a2ecd
|
@ -8,6 +8,11 @@ Supported chips:
|
||||||
Datasheets:
|
Datasheets:
|
||||||
http://www.ti.com/lit/gpn/lm25056
|
http://www.ti.com/lit/gpn/lm25056
|
||||||
http://www.ti.com/lit/gpn/lm25056a
|
http://www.ti.com/lit/gpn/lm25056a
|
||||||
|
* TI LM25063
|
||||||
|
Prefix: 'lm25063'
|
||||||
|
Addresses scanned: -
|
||||||
|
Datasheet:
|
||||||
|
To be announced
|
||||||
* National Semiconductor LM25066
|
* National Semiconductor LM25066
|
||||||
Prefix: 'lm25066'
|
Prefix: 'lm25066'
|
||||||
Addresses scanned: -
|
Addresses scanned: -
|
||||||
|
@ -32,7 +37,7 @@ Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This driver supports hardware montoring for National Semiconductor / TI LM25056,
|
This driver supports hardware montoring for National Semiconductor / TI LM25056,
|
||||||
LM25066, LM5064, and LM5064 Power Management, Monitoring, Control, and
|
LM25063, LM25066, LM5064, and LM5066 Power Management, Monitoring, Control, and
|
||||||
Protection ICs.
|
Protection ICs.
|
||||||
|
|
||||||
The driver is a client driver to the core PMBus driver. Please see
|
The driver is a client driver to the core PMBus driver. Please see
|
||||||
|
@ -64,8 +69,12 @@ in1_input Measured input voltage.
|
||||||
in1_average Average measured input voltage.
|
in1_average Average measured input voltage.
|
||||||
in1_min Minimum input voltage.
|
in1_min Minimum input voltage.
|
||||||
in1_max Maximum input voltage.
|
in1_max Maximum input voltage.
|
||||||
|
in1_crit Critical high input voltage (LM25063 only).
|
||||||
|
in1_lcrit Critical low input voltage (LM25063 only).
|
||||||
in1_min_alarm Input voltage low alarm.
|
in1_min_alarm Input voltage low alarm.
|
||||||
in1_max_alarm Input voltage high alarm.
|
in1_max_alarm Input voltage high alarm.
|
||||||
|
in1_lcrit_alarm Input voltage critical low alarm (LM25063 only).
|
||||||
|
in1_crit_alarm Input voltage critical high alarm. (LM25063 only).
|
||||||
|
|
||||||
in2_label "vmon"
|
in2_label "vmon"
|
||||||
in2_input Measured voltage on VAUX pin
|
in2_input Measured voltage on VAUX pin
|
||||||
|
@ -80,12 +89,16 @@ in3_input Measured output voltage.
|
||||||
in3_average Average measured output voltage.
|
in3_average Average measured output voltage.
|
||||||
in3_min Minimum output voltage.
|
in3_min Minimum output voltage.
|
||||||
in3_min_alarm Output voltage low alarm.
|
in3_min_alarm Output voltage low alarm.
|
||||||
|
in3_highest Historical minimum output voltage (LM25063 only).
|
||||||
|
in3_lowest Historical maximum output voltage (LM25063 only).
|
||||||
|
|
||||||
curr1_label "iin"
|
curr1_label "iin"
|
||||||
curr1_input Measured input current.
|
curr1_input Measured input current.
|
||||||
curr1_average Average measured input current.
|
curr1_average Average measured input current.
|
||||||
curr1_max Maximum input current.
|
curr1_max Maximum input current.
|
||||||
|
curr1_crit Critical input current (LM25063 only).
|
||||||
curr1_max_alarm Input current high alarm.
|
curr1_max_alarm Input current high alarm.
|
||||||
|
curr1_crit_alarm Input current critical high alarm (LM25063 only).
|
||||||
|
|
||||||
power1_label "pin"
|
power1_label "pin"
|
||||||
power1_input Measured input power.
|
power1_input Measured input power.
|
||||||
|
@ -95,6 +108,11 @@ power1_alarm Input power alarm
|
||||||
power1_input_highest Historical maximum power.
|
power1_input_highest Historical maximum power.
|
||||||
power1_reset_history Write any value to reset maximum power history.
|
power1_reset_history Write any value to reset maximum power history.
|
||||||
|
|
||||||
|
power2_label "pout". LM25063 only.
|
||||||
|
power2_input Measured output power.
|
||||||
|
power2_max Maximum output power limit.
|
||||||
|
power2_crit Critical output power limit.
|
||||||
|
|
||||||
temp1_input Measured temperature.
|
temp1_input Measured temperature.
|
||||||
temp1_max Maximum temperature.
|
temp1_max Maximum temperature.
|
||||||
temp1_crit Critical high temperature.
|
temp1_crit Critical high temperature.
|
||||||
|
|
|
@ -6,10 +6,15 @@ Supported chips:
|
||||||
Prefix: 'ltc2974'
|
Prefix: 'ltc2974'
|
||||||
Addresses scanned: -
|
Addresses scanned: -
|
||||||
Datasheet: http://www.linear.com/product/ltc2974
|
Datasheet: http://www.linear.com/product/ltc2974
|
||||||
* Linear Technology LTC2978
|
* Linear Technology LTC2977
|
||||||
|
Prefix: 'ltc2977'
|
||||||
|
Addresses scanned: -
|
||||||
|
Datasheet: http://www.linear.com/product/ltc2977
|
||||||
|
* Linear Technology LTC2978, LTC2978A
|
||||||
Prefix: 'ltc2978'
|
Prefix: 'ltc2978'
|
||||||
Addresses scanned: -
|
Addresses scanned: -
|
||||||
Datasheet: http://www.linear.com/product/ltc2978
|
Datasheet: http://www.linear.com/product/ltc2978
|
||||||
|
http://www.linear.com/product/ltc2978a
|
||||||
* Linear Technology LTC3880
|
* Linear Technology LTC3880
|
||||||
Prefix: 'ltc3880'
|
Prefix: 'ltc3880'
|
||||||
Addresses scanned: -
|
Addresses scanned: -
|
||||||
|
@ -26,8 +31,9 @@ Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
|
LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
|
||||||
monitor. LTC3880 is a dual output poly-phase step-down DC/DC controller. LTC3883
|
monitor. LTC2977 is a pin compatible replacement for LTC2978. LTC3880 is a dual
|
||||||
is a single phase step-down DC/DC controller.
|
output poly-phase step-down DC/DC controller. LTC3883 is a single phase
|
||||||
|
step-down DC/DC controller.
|
||||||
|
|
||||||
|
|
||||||
Usage Notes
|
Usage Notes
|
||||||
|
@ -49,21 +55,25 @@ Sysfs attributes
|
||||||
in1_label "vin"
|
in1_label "vin"
|
||||||
in1_input Measured input voltage.
|
in1_input Measured input voltage.
|
||||||
in1_min Minimum input voltage.
|
in1_min Minimum input voltage.
|
||||||
in1_max Maximum input voltage. LTC2974 and LTC2978 only.
|
in1_max Maximum input voltage.
|
||||||
in1_lcrit Critical minimum input voltage. LTC2974 and LTC2978
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
only.
|
in1_lcrit Critical minimum input voltage.
|
||||||
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
in1_crit Critical maximum input voltage.
|
in1_crit Critical maximum input voltage.
|
||||||
in1_min_alarm Input voltage low alarm.
|
in1_min_alarm Input voltage low alarm.
|
||||||
in1_max_alarm Input voltage high alarm. LTC2974 and LTC2978 only.
|
in1_max_alarm Input voltage high alarm.
|
||||||
in1_lcrit_alarm Input voltage critical low alarm. LTC2974 and LTC2978
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
only.
|
in1_lcrit_alarm Input voltage critical low alarm.
|
||||||
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
in1_crit_alarm Input voltage critical high alarm.
|
in1_crit_alarm Input voltage critical high alarm.
|
||||||
in1_lowest Lowest input voltage. LTC2974 and LTC2978 only.
|
in1_lowest Lowest input voltage.
|
||||||
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
in1_highest Highest input voltage.
|
in1_highest Highest input voltage.
|
||||||
in1_reset_history Reset input voltage history.
|
in1_reset_history Reset input voltage history.
|
||||||
|
|
||||||
in[N]_label "vout[1-8]".
|
in[N]_label "vout[1-8]".
|
||||||
LTC2974: N=2-5
|
LTC2974: N=2-5
|
||||||
|
LTC2977: N=2-9
|
||||||
LTC2978: N=2-9
|
LTC2978: N=2-9
|
||||||
LTC3880: N=2-3
|
LTC3880: N=2-3
|
||||||
LTC3883: N=2
|
LTC3883: N=2
|
||||||
|
@ -83,21 +93,23 @@ in[N]_reset_history Reset output voltage history.
|
||||||
temp[N]_input Measured temperature.
|
temp[N]_input Measured temperature.
|
||||||
On LTC2974, temp[1-4] report external temperatures,
|
On LTC2974, temp[1-4] report external temperatures,
|
||||||
and temp5 reports the chip temperature.
|
and temp5 reports the chip temperature.
|
||||||
On LTC2978, only one temperature measurement is
|
On LTC2977 and LTC2978, only one temperature measurement
|
||||||
supported and reports the chip temperature.
|
is supported and reports the chip temperature.
|
||||||
On LTC3880, temp1 and temp2 report external
|
On LTC3880, temp1 and temp2 report external
|
||||||
temperatures, and temp3 reports the chip temperature.
|
temperatures, and temp3 reports the chip temperature.
|
||||||
On LTC3883, temp1 reports an external temperature,
|
On LTC3883, temp1 reports an external temperature,
|
||||||
and temp2 reports the chip temperature.
|
and temp2 reports the chip temperature.
|
||||||
temp[N]_min Mimimum temperature. LTC2974 and LTC2978 only.
|
temp[N]_min Mimimum temperature. LTC2974, LCT2977, and LTC2978 only.
|
||||||
temp[N]_max Maximum temperature.
|
temp[N]_max Maximum temperature.
|
||||||
temp[N]_lcrit Critical low temperature.
|
temp[N]_lcrit Critical low temperature.
|
||||||
temp[N]_crit Critical high temperature.
|
temp[N]_crit Critical high temperature.
|
||||||
temp[N]_min_alarm Temperature low alarm. LTC2974 and LTC2978 only.
|
temp[N]_min_alarm Temperature low alarm.
|
||||||
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
temp[N]_max_alarm Temperature high alarm.
|
temp[N]_max_alarm Temperature high alarm.
|
||||||
temp[N]_lcrit_alarm Temperature critical low alarm.
|
temp[N]_lcrit_alarm Temperature critical low alarm.
|
||||||
temp[N]_crit_alarm Temperature critical high alarm.
|
temp[N]_crit_alarm Temperature critical high alarm.
|
||||||
temp[N]_lowest Lowest measured temperature. LTC2974 and LTC2978 only.
|
temp[N]_lowest Lowest measured temperature.
|
||||||
|
LTC2974, LTC2977, and LTC2978 only.
|
||||||
Not supported for chip temperature sensor on LTC2974.
|
Not supported for chip temperature sensor on LTC2974.
|
||||||
temp[N]_highest Highest measured temperature. Not supported for chip
|
temp[N]_highest Highest measured temperature. Not supported for chip
|
||||||
temperature sensor on LTC2974.
|
temperature sensor on LTC2974.
|
||||||
|
@ -109,6 +121,7 @@ power1_input Measured input power.
|
||||||
|
|
||||||
power[N]_label "pout[1-4]".
|
power[N]_label "pout[1-4]".
|
||||||
LTC2974: N=1-4
|
LTC2974: N=1-4
|
||||||
|
LTC2977: Not supported
|
||||||
LTC2978: Not supported
|
LTC2978: Not supported
|
||||||
LTC3880: N=1-2
|
LTC3880: N=1-2
|
||||||
LTC3883: N=2
|
LTC3883: N=2
|
||||||
|
@ -123,6 +136,7 @@ curr1_reset_history Reset input current history. LTC3883 only.
|
||||||
|
|
||||||
curr[N]_label "iout[1-4]".
|
curr[N]_label "iout[1-4]".
|
||||||
LTC2974: N=1-4
|
LTC2974: N=1-4
|
||||||
|
LTC2977: not supported
|
||||||
LTC2978: not supported
|
LTC2978: not supported
|
||||||
LTC3880: N=2-3
|
LTC3880: N=2-3
|
||||||
LTC3883: N=2
|
LTC3883: N=2
|
||||||
|
|
|
@ -164,7 +164,7 @@ static const u8 abituguru_bank2_max_threshold = 50;
|
||||||
static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 };
|
static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 };
|
||||||
/*
|
/*
|
||||||
* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
|
* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
|
||||||
* special case the minium allowed pwm% setting for this is 30% (77) on
|
* special case the minimum allowed pwm% setting for this is 30% (77) on
|
||||||
* some MB's this special case is handled in the code!
|
* some MB's this special case is handled in the code!
|
||||||
*/
|
*/
|
||||||
static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 };
|
static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 };
|
||||||
|
@ -517,7 +517,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
|
||||||
|
|
||||||
ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
|
ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
|
||||||
/*
|
/*
|
||||||
* Volt sensor test, enable volt low alarm, set min value ridicously
|
* Volt sensor test, enable volt low alarm, set min value ridiculously
|
||||||
* high, or vica versa if the reading is very high. If its a volt
|
* high, or vica versa if the reading is very high. If its a volt
|
||||||
* sensor this should always give us an alarm.
|
* sensor this should always give us an alarm.
|
||||||
*/
|
*/
|
||||||
|
@ -564,7 +564,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Temp sensor test, enable sensor as a temp sensor, set beep value
|
* Temp sensor test, enable sensor as a temp sensor, set beep value
|
||||||
* ridicously low (but not too low, otherwise uguru ignores it).
|
* ridiculously low (but not too low, otherwise uguru ignores it).
|
||||||
* If its a temp sensor this should always give us an alarm.
|
* If its a temp sensor this should always give us an alarm.
|
||||||
*/
|
*/
|
||||||
buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE;
|
buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE;
|
||||||
|
|
|
@ -176,7 +176,7 @@ struct abituguru3_data {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The abituguru3 supports up to 48 sensors, and thus has registers
|
* The abituguru3 supports up to 48 sensors, and thus has registers
|
||||||
* sets for 48 sensors, for convienence reasons / simplicity of the
|
* sets for 48 sensors, for convenience reasons / simplicity of the
|
||||||
* code we always read and store all registers for all 48 sensors
|
* code we always read and store all registers for all 48 sensors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -381,8 +381,10 @@ static ssize_t show_str(struct device *dev,
|
||||||
val = resource->oem_info;
|
val = resource->oem_info;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
WARN(1, "Implementation error: unexpected attribute index %d\n",
|
||||||
|
attr->index);
|
||||||
val = "";
|
val = "";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", val);
|
return sprintf(buf, "%s\n", val);
|
||||||
|
@ -436,7 +438,9 @@ static ssize_t show_val(struct device *dev,
|
||||||
val = resource->trip[attr->index - 7] * 1000;
|
val = resource->trip[attr->index - 7] * 1000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
WARN(1, "Implementation error: unexpected attribute index %d\n",
|
||||||
|
attr->index);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(buf, "%llu\n", val);
|
return sprintf(buf, "%llu\n", val);
|
||||||
|
@ -855,7 +859,8 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
|
||||||
dev_info(&device->dev, "Capping in progress.\n");
|
dev_info(&device->dev, "Capping in progress.\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
WARN(1, "Unexpected event %d\n", event);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&resource->lock);
|
mutex_unlock(&resource->lock);
|
||||||
|
|
||||||
|
@ -991,7 +996,7 @@ static int __init acpi_power_meter_init(void)
|
||||||
|
|
||||||
result = acpi_bus_register_driver(&acpi_power_meter_driver);
|
result = acpi_bus_register_driver(&acpi_power_meter_driver);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -ENODEV;
|
return result;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,6 @@ out_err:
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
|
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
|
||||||
|
|
||||||
spi_set_drvdata(spi, NULL);
|
|
||||||
mutex_unlock(&adc->lock);
|
mutex_unlock(&adc->lock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +217,6 @@ static int adcxx_remove(struct spi_device *spi)
|
||||||
for (i = 0; i < 3 + adc->channels; i++)
|
for (i = 0; i < 3 + adc->channels; i++)
|
||||||
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
|
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
|
||||||
|
|
||||||
spi_set_drvdata(spi, NULL);
|
|
||||||
mutex_unlock(&adc->lock);
|
mutex_unlock(&adc->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -616,7 +616,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
|
||||||
data->gpio = gpio;
|
data->gpio = gpio;
|
||||||
|
|
||||||
data->last_reading = jiffies;
|
data->last_reading = jiffies;
|
||||||
}; /* last_reading */
|
} /* last_reading */
|
||||||
|
|
||||||
if (!data->valid ||
|
if (!data->valid ||
|
||||||
time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
|
time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
|
||||||
|
@ -700,7 +700,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
data->last_config = jiffies;
|
data->last_config = jiffies;
|
||||||
}; /* last_config */
|
} /* last_config */
|
||||||
|
|
||||||
data->valid = 1;
|
data->valid = 1;
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
@ -1791,7 +1791,7 @@ static int adm1026_detect(struct i2c_client *client,
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||||
/* We need to be able to do byte I/O */
|
/* We need to be able to do byte I/O */
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
};
|
}
|
||||||
|
|
||||||
/* Now, we do the remaining detection. */
|
/* Now, we do the remaining detection. */
|
||||||
|
|
||||||
|
|
|
@ -700,7 +700,7 @@ static int find_trange_value(int trange)
|
||||||
if (trange_values[i] == trange)
|
if (trange_values[i] == trange)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
return -ENODEV;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct adt7462_data *adt7462_update_device(struct device *dev)
|
static struct adt7462_data *adt7462_update_device(struct device *dev)
|
||||||
|
@ -1294,9 +1294,8 @@ static ssize_t set_pwm_tmax(struct device *dev,
|
||||||
/* trange = tmax - tmin */
|
/* trange = tmax - tmin */
|
||||||
tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
|
tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
|
||||||
trange_value = find_trange_value(trange - tmin);
|
trange_value = find_trange_value(trange - tmin);
|
||||||
|
|
||||||
if (trange_value < 0)
|
if (trange_value < 0)
|
||||||
return -EINVAL;
|
return trange_value;
|
||||||
|
|
||||||
temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
|
temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
|
||||||
temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
|
temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
|
||||||
|
|
|
@ -138,7 +138,7 @@ static inline u8 read_byte(struct i2c_client *client, u8 reg)
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"Unable to read from register 0x%02x.\n", reg);
|
"Unable to read from register 0x%02x.\n", reg);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
}
|
||||||
return res & 0xff;
|
return res & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"Unable to write value 0x%02x to register 0x%02x.\n",
|
"Unable to write value 0x%02x to register 0x%02x.\n",
|
||||||
data, reg);
|
data, reg);
|
||||||
};
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1030,7 +1030,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->last_high_reading = jiffies;
|
data->last_high_reading = jiffies;
|
||||||
}; /* last_reading */
|
} /* last_reading */
|
||||||
|
|
||||||
/* Read all the low priority registers. */
|
/* Read all the low priority registers. */
|
||||||
|
|
||||||
|
@ -1044,7 +1044,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->last_low_reading = jiffies;
|
data->last_low_reading = jiffies;
|
||||||
}; /* last_reading */
|
} /* last_reading */
|
||||||
|
|
||||||
data->valid = 1;
|
data->valid = 1;
|
||||||
|
|
||||||
|
@ -1084,11 +1084,11 @@ static void asc7621_init_client(struct i2c_client *client)
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"Client (%d,0x%02x) config is locked.\n",
|
"Client (%d,0x%02x) config is locked.\n",
|
||||||
i2c_adapter_id(client->adapter), client->addr);
|
i2c_adapter_id(client->adapter), client->addr);
|
||||||
};
|
}
|
||||||
if (!(value & 0x04)) {
|
if (!(value & 0x04)) {
|
||||||
dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
|
dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
|
||||||
i2c_adapter_id(client->adapter), client->addr);
|
i2c_adapter_id(client->adapter), client->addr);
|
||||||
};
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start monitoring
|
* Start monitoring
|
||||||
|
|
|
@ -119,7 +119,7 @@ struct atk_data {
|
||||||
acpi_handle rtmp_handle;
|
acpi_handle rtmp_handle;
|
||||||
acpi_handle rvlt_handle;
|
acpi_handle rvlt_handle;
|
||||||
acpi_handle rfan_handle;
|
acpi_handle rfan_handle;
|
||||||
/* new inteface */
|
/* new interface */
|
||||||
acpi_handle enumerate_handle;
|
acpi_handle enumerate_handle;
|
||||||
acpi_handle read_handle;
|
acpi_handle read_handle;
|
||||||
acpi_handle write_handle;
|
acpi_handle write_handle;
|
||||||
|
|
|
@ -147,10 +147,9 @@ static ssize_t atxp1_storevcore(struct device *dev,
|
||||||
|
|
||||||
/* Calculate VID */
|
/* Calculate VID */
|
||||||
vid = vid_to_reg(vcore, data->vrm);
|
vid = vid_to_reg(vcore, data->vrm);
|
||||||
|
|
||||||
if (vid < 0) {
|
if (vid < 0) {
|
||||||
dev_err(dev, "VID calculation failed.\n");
|
dev_err(dev, "VID calculation failed.\n");
|
||||||
return -1;
|
return vid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -120,7 +120,7 @@ static const u8 DS1621_REG_TEMP[3] = {
|
||||||
|
|
||||||
/* Each client has this additional data */
|
/* Each client has this additional data */
|
||||||
struct ds1621_data {
|
struct ds1621_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
char valid; /* !=0 if following fields are valid */
|
char valid; /* !=0 if following fields are valid */
|
||||||
unsigned long last_updated; /* In jiffies */
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
@ -151,10 +151,10 @@ static inline u16 DS1621_TEMP_TO_REG(long temp, u8 zbits)
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ds1621_init_client(struct i2c_client *client)
|
static void ds1621_init_client(struct ds1621_data *data,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
u8 conf, new_conf, sreg, resol;
|
u8 conf, new_conf, sreg, resol;
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
|
new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
|
||||||
/* switch to continuous conversion mode */
|
/* switch to continuous conversion mode */
|
||||||
|
@ -197,8 +197,8 @@ static void ds1621_init_client(struct i2c_client *client)
|
||||||
|
|
||||||
static struct ds1621_data *ds1621_update_client(struct device *dev)
|
static struct ds1621_data *ds1621_update_client(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
u8 new_conf;
|
u8 new_conf;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
@ -247,8 +247,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
|
||||||
long val;
|
long val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -258,7 +257,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits);
|
data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits);
|
||||||
i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
|
i2c_smbus_write_word_swapped(data->client, DS1621_REG_TEMP[attr->index],
|
||||||
data->temp[attr->index]);
|
data->temp[attr->index]);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
return count;
|
return count;
|
||||||
|
@ -282,16 +281,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
|
||||||
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
|
||||||
return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
|
return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
unsigned long convrate;
|
unsigned long convrate;
|
||||||
s32 err;
|
s32 err;
|
||||||
int resol = 0;
|
int resol = 0;
|
||||||
|
@ -343,8 +341,7 @@ static umode_t ds1621_attribute_visible(struct kobject *kobj,
|
||||||
struct attribute *attr, int index)
|
struct attribute *attr, int index)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
if (attr == &dev_attr_update_interval.attr)
|
if (attr == &dev_attr_update_interval.attr)
|
||||||
if (data->kind == ds1621 || data->kind == ds1625)
|
if (data->kind == ds1621 || data->kind == ds1625)
|
||||||
|
@ -357,52 +354,31 @@ static const struct attribute_group ds1621_group = {
|
||||||
.attrs = ds1621_attributes,
|
.attrs = ds1621_attributes,
|
||||||
.is_visible = ds1621_attribute_visible
|
.is_visible = ds1621_attribute_visible
|
||||||
};
|
};
|
||||||
|
__ATTRIBUTE_GROUPS(ds1621);
|
||||||
|
|
||||||
static int ds1621_probe(struct i2c_client *client,
|
static int ds1621_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct ds1621_data *data;
|
struct ds1621_data *data;
|
||||||
int err;
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data),
|
data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
data->kind = id->driver_data;
|
data->kind = id->driver_data;
|
||||||
|
data->client = client;
|
||||||
|
|
||||||
/* Initialize the DS1621 chip */
|
/* Initialize the DS1621 chip */
|
||||||
ds1621_init_client(client);
|
ds1621_init_client(data, client);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
|
||||||
err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
|
client->name, data,
|
||||||
if (err)
|
ds1621_groups);
|
||||||
return err;
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove_files:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ds1621_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id ds1621_id[] = {
|
static const struct i2c_device_id ds1621_id[] = {
|
||||||
|
@ -422,7 +398,6 @@ static struct i2c_driver ds1621_driver = {
|
||||||
.name = "ds1621",
|
.name = "ds1621",
|
||||||
},
|
},
|
||||||
.probe = ds1621_probe,
|
.probe = ds1621_probe,
|
||||||
.remove = ds1621_remove,
|
|
||||||
.id_table = ds1621_id,
|
.id_table = ds1621_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
*
|
*
|
||||||
* TODO
|
* TODO
|
||||||
* - cache alarm and critical limit registers
|
* - cache alarm and critical limit registers
|
||||||
* - add emc1404 support
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -40,7 +39,8 @@
|
||||||
#define THERMAL_REVISION_REG 0xff
|
#define THERMAL_REVISION_REG 0xff
|
||||||
|
|
||||||
struct thermal_data {
|
struct thermal_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
const struct attribute_group *groups[3];
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
/*
|
/*
|
||||||
* Cache the hyst value so we don't keep re-reading it. In theory
|
* Cache the hyst value so we don't keep re-reading it. In theory
|
||||||
|
@ -53,10 +53,11 @@ struct thermal_data {
|
||||||
static ssize_t show_temp(struct device *dev,
|
static ssize_t show_temp(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
||||||
int retval = i2c_smbus_read_byte_data(client, sda->index);
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = i2c_smbus_read_byte_data(data->client, sda->index);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
return sprintf(buf, "%d000\n", retval);
|
return sprintf(buf, "%d000\n", retval);
|
||||||
|
@ -65,27 +66,27 @@ static ssize_t show_temp(struct device *dev,
|
||||||
static ssize_t show_bit(struct device *dev,
|
static ssize_t show_bit(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
|
struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
|
||||||
int retval = i2c_smbus_read_byte_data(client, sda->nr);
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = i2c_smbus_read_byte_data(data->client, sda->nr);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
retval &= sda->index;
|
return sprintf(buf, "%d\n", !!(retval & sda->index));
|
||||||
return sprintf(buf, "%d\n", retval ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_temp(struct device *dev,
|
static ssize_t store_temp(struct device *dev,
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (kstrtoul(buf, 10, &val))
|
if (kstrtoul(buf, 10, &val))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
retval = i2c_smbus_write_byte_data(client, sda->index,
|
retval = i2c_smbus_write_byte_data(data->client, sda->index,
|
||||||
DIV_ROUND_CLOSEST(val, 1000));
|
DIV_ROUND_CLOSEST(val, 1000));
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -95,9 +96,9 @@ static ssize_t store_temp(struct device *dev,
|
||||||
static ssize_t store_bit(struct device *dev,
|
static ssize_t store_bit(struct device *dev,
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct thermal_data *data = i2c_get_clientdata(client);
|
|
||||||
struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
|
struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
|
||||||
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -124,9 +125,9 @@ fail:
|
||||||
static ssize_t show_hyst(struct device *dev,
|
static ssize_t show_hyst(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct thermal_data *data = i2c_get_clientdata(client);
|
|
||||||
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
||||||
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
int retval;
|
int retval;
|
||||||
int hyst;
|
int hyst;
|
||||||
|
|
||||||
|
@ -147,9 +148,9 @@ static ssize_t show_hyst(struct device *dev,
|
||||||
static ssize_t store_hyst(struct device *dev,
|
static ssize_t store_hyst(struct device *dev,
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct thermal_data *data = i2c_get_clientdata(client);
|
|
||||||
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
|
||||||
|
struct thermal_data *data = dev_get_drvdata(dev);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
int retval;
|
int retval;
|
||||||
int hyst;
|
int hyst;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
@ -232,10 +233,26 @@ static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO,
|
||||||
static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,
|
static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,
|
||||||
show_hyst, store_hyst, 0x1A);
|
show_hyst, store_hyst, 0x1A);
|
||||||
|
|
||||||
|
static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR,
|
||||||
|
show_temp, store_temp, 0x2D);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR,
|
||||||
|
show_temp, store_temp, 0x2C);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
|
||||||
|
show_temp, store_temp, 0x30);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 0x2A);
|
||||||
|
static SENSOR_DEVICE_ATTR_2(temp4_min_alarm, S_IRUGO,
|
||||||
|
show_bit, NULL, 0x36, 0x08);
|
||||||
|
static SENSOR_DEVICE_ATTR_2(temp4_max_alarm, S_IRUGO,
|
||||||
|
show_bit, NULL, 0x35, 0x08);
|
||||||
|
static SENSOR_DEVICE_ATTR_2(temp4_crit_alarm, S_IRUGO,
|
||||||
|
show_bit, NULL, 0x37, 0x08);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp4_crit_hyst, S_IRUGO | S_IWUSR,
|
||||||
|
show_hyst, store_hyst, 0x30);
|
||||||
|
|
||||||
static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR,
|
static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR,
|
||||||
show_bit, store_bit, 0x03, 0x40);
|
show_bit, store_bit, 0x03, 0x40);
|
||||||
|
|
||||||
static struct attribute *mid_att_thermal[] = {
|
static struct attribute *emc1403_attrs[] = {
|
||||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
||||||
|
@ -264,8 +281,24 @@ static struct attribute *mid_att_thermal[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct attribute_group m_thermal_gr = {
|
static const struct attribute_group emc1403_group = {
|
||||||
.attrs = mid_att_thermal
|
.attrs = emc1403_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute *emc1404_attrs[] = {
|
||||||
|
&sensor_dev_attr_temp4_min.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_max.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_crit.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_input.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp4_crit_hyst.dev_attr.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group emc1404_group = {
|
||||||
|
.attrs = emc1404_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int emc1403_detect(struct i2c_client *client,
|
static int emc1403_detect(struct i2c_client *client,
|
||||||
|
@ -286,10 +319,12 @@ static int emc1403_detect(struct i2c_client *client,
|
||||||
case 0x23:
|
case 0x23:
|
||||||
strlcpy(info->type, "emc1423", I2C_NAME_SIZE);
|
strlcpy(info->type, "emc1423", I2C_NAME_SIZE);
|
||||||
break;
|
break;
|
||||||
/*
|
case 0x25:
|
||||||
* Note: 0x25 is the 1404 which is very similar and this
|
strlcpy(info->type, "emc1404", I2C_NAME_SIZE);
|
||||||
* driver could be extended
|
break;
|
||||||
*/
|
case 0x27:
|
||||||
|
strlcpy(info->type, "emc1424", I2C_NAME_SIZE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -304,43 +339,29 @@ static int emc1403_detect(struct i2c_client *client,
|
||||||
static int emc1403_probe(struct i2c_client *client,
|
static int emc1403_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
struct thermal_data *data;
|
struct thermal_data *data;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(struct thermal_data),
|
data = devm_kzalloc(&client->dev, sizeof(struct thermal_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->mutex);
|
mutex_init(&data->mutex);
|
||||||
data->hyst_valid = jiffies - 1; /* Expired */
|
data->hyst_valid = jiffies - 1; /* Expired */
|
||||||
|
|
||||||
res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);
|
data->groups[0] = &emc1403_group;
|
||||||
if (res) {
|
if (id->driver_data)
|
||||||
dev_warn(&client->dev, "create group failed\n");
|
data->groups[1] = &emc1404_group;
|
||||||
return res;
|
|
||||||
}
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
res = PTR_ERR(data->hwmon_dev);
|
|
||||||
dev_warn(&client->dev, "register hwmon dev failed\n");
|
|
||||||
goto thermal_error;
|
|
||||||
}
|
|
||||||
dev_info(&client->dev, "EMC1403 Thermal chip found\n");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
thermal_error:
|
hwmon_dev = hwmon_device_register_with_groups(&client->dev,
|
||||||
sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
|
client->name, data,
|
||||||
return res;
|
data->groups);
|
||||||
}
|
if (IS_ERR(hwmon_dev))
|
||||||
|
return PTR_ERR(hwmon_dev);
|
||||||
|
|
||||||
static int emc1403_remove(struct i2c_client *client)
|
dev_info(&client->dev, "%s Thermal chip found\n", id->name);
|
||||||
{
|
|
||||||
struct thermal_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +371,9 @@ static const unsigned short emc1403_address_list[] = {
|
||||||
|
|
||||||
static const struct i2c_device_id emc1403_idtable[] = {
|
static const struct i2c_device_id emc1403_idtable[] = {
|
||||||
{ "emc1403", 0 },
|
{ "emc1403", 0 },
|
||||||
|
{ "emc1404", 1 },
|
||||||
{ "emc1423", 0 },
|
{ "emc1423", 0 },
|
||||||
|
{ "emc1424", 1 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
|
MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
|
||||||
|
@ -362,7 +385,6 @@ static struct i2c_driver sensor_emc1403 = {
|
||||||
},
|
},
|
||||||
.detect = emc1403_detect,
|
.detect = emc1403_detect,
|
||||||
.probe = emc1403_probe,
|
.probe = emc1403_probe,
|
||||||
.remove = emc1403_remove,
|
|
||||||
.id_table = emc1403_idtable,
|
.id_table = emc1403_idtable,
|
||||||
.address_list = emc1403_address_list,
|
.address_list = emc1403_address_list,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2420,7 +2420,6 @@ static int f71882fg_probe(struct platform_device *pdev)
|
||||||
exit_unregister_sysfs:
|
exit_unregister_sysfs:
|
||||||
f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
|
f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
|
||||||
return err; /* f71882fg_remove() also frees our data */
|
return err; /* f71882fg_remove() also frees our data */
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int f71882fg_remove(struct platform_device *pdev)
|
static int f71882fg_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -275,7 +275,7 @@ static bool duty_mode_enabled(u8 pwm_enable)
|
||||||
case 3: /* Manual, speed mode */
|
case 3: /* Manual, speed mode */
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
BUG();
|
WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ static bool auto_mode_enabled(u8 pwm_enable)
|
||||||
case 4: /* Auto, duty mode */
|
case 4: /* Auto, duty mode */
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
BUG();
|
WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/gpio-fan.h>
|
#include <linux/gpio-fan.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data)
|
||||||
dev_warn(&fan_data->pdev->dev,
|
dev_warn(&fan_data->pdev->dev,
|
||||||
"missing speed array entry for GPIO value 0x%x\n", ctrl_val);
|
"missing speed array entry for GPIO value 0x%x\n", ctrl_val);
|
||||||
|
|
||||||
return -EINVAL;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
|
static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
|
||||||
|
@ -309,12 +310,6 @@ exit_unlock:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_name(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "gpio-fan\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
|
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
|
||||||
static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
|
||||||
show_pwm_enable, set_pwm_enable);
|
show_pwm_enable, set_pwm_enable);
|
||||||
|
@ -324,26 +319,23 @@ static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
|
||||||
static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
|
static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
|
||||||
static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
|
static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
|
||||||
|
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
|
||||||
|
|
||||||
static umode_t gpio_fan_is_visible(struct kobject *kobj,
|
static umode_t gpio_fan_is_visible(struct kobject *kobj,
|
||||||
struct attribute *attr, int index)
|
struct attribute *attr, int index)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
struct gpio_fan_data *data = dev_get_drvdata(dev);
|
struct gpio_fan_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (index == 1 && !data->alarm)
|
if (index == 0 && !data->alarm)
|
||||||
return 0;
|
return 0;
|
||||||
if (index > 1 && !data->ctrl)
|
if (index > 0 && !data->ctrl)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return attr->mode;
|
return attr->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attribute *gpio_fan_attributes[] = {
|
static struct attribute *gpio_fan_attributes[] = {
|
||||||
&dev_attr_name.attr,
|
&dev_attr_fan1_alarm.attr, /* 0 */
|
||||||
&dev_attr_fan1_alarm.attr, /* 1 */
|
&dev_attr_pwm1.attr, /* 1 */
|
||||||
&dev_attr_pwm1.attr, /* 2 */
|
|
||||||
&dev_attr_pwm1_enable.attr,
|
&dev_attr_pwm1_enable.attr,
|
||||||
&dev_attr_pwm1_mode.attr,
|
&dev_attr_pwm1_mode.attr,
|
||||||
&dev_attr_fan1_input.attr,
|
&dev_attr_fan1_input.attr,
|
||||||
|
@ -358,6 +350,11 @@ static const struct attribute_group gpio_fan_group = {
|
||||||
.is_visible = gpio_fan_is_visible,
|
.is_visible = gpio_fan_is_visible,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group *gpio_fan_groups[] = {
|
||||||
|
&gpio_fan_group,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int fan_ctrl_init(struct gpio_fan_data *fan_data,
|
static int fan_ctrl_init(struct gpio_fan_data *fan_data,
|
||||||
struct gpio_fan_platform_data *pdata)
|
struct gpio_fan_platform_data *pdata)
|
||||||
{
|
{
|
||||||
|
@ -384,7 +381,7 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
|
||||||
fan_data->pwm_enable = true; /* Enable manual fan speed control. */
|
fan_data->pwm_enable = true; /* Enable manual fan speed control. */
|
||||||
fan_data->speed_index = get_fan_speed_index(fan_data);
|
fan_data->speed_index = get_fan_speed_index(fan_data);
|
||||||
if (fan_data->speed_index < 0)
|
if (fan_data->speed_index < 0)
|
||||||
return -ENODEV;
|
return fan_data->speed_index;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -539,24 +536,16 @@ static int gpio_fan_probe(struct platform_device *pdev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_group);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* Make this driver part of hwmon class. */
|
/* Make this driver part of hwmon class. */
|
||||||
fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
|
fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
|
||||||
if (IS_ERR(fan_data->hwmon_dev)) {
|
"gpio-fan", fan_data,
|
||||||
err = PTR_ERR(fan_data->hwmon_dev);
|
gpio_fan_groups);
|
||||||
goto err_remove;
|
if (IS_ERR(fan_data->hwmon_dev))
|
||||||
}
|
return PTR_ERR(fan_data->hwmon_dev);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "GPIO fan initialized\n");
|
dev_info(&pdev->dev, "GPIO fan initialized\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_remove:
|
|
||||||
sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gpio_fan_remove(struct platform_device *pdev)
|
static int gpio_fan_remove(struct platform_device *pdev)
|
||||||
|
@ -564,7 +553,6 @@ static int gpio_fan_remove(struct platform_device *pdev)
|
||||||
struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
|
struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
hwmon_device_unregister(fan_data->hwmon_dev);
|
hwmon_device_unregister(fan_data->hwmon_dev);
|
||||||
sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
|
@ -25,10 +26,110 @@
|
||||||
#define HWMON_ID_PREFIX "hwmon"
|
#define HWMON_ID_PREFIX "hwmon"
|
||||||
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
|
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
|
||||||
|
|
||||||
static struct class *hwmon_class;
|
struct hwmon_device {
|
||||||
|
const char *name;
|
||||||
|
struct device dev;
|
||||||
|
};
|
||||||
|
#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||||
|
|
||||||
|
static struct attribute *hwmon_dev_attrs[] = {
|
||||||
|
&dev_attr_name.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static umode_t hwmon_dev_name_is_visible(struct kobject *kobj,
|
||||||
|
struct attribute *attr, int n)
|
||||||
|
{
|
||||||
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
|
|
||||||
|
if (to_hwmon_device(dev)->name == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return attr->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct attribute_group hwmon_dev_attr_group = {
|
||||||
|
.attrs = hwmon_dev_attrs,
|
||||||
|
.is_visible = hwmon_dev_name_is_visible,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group *hwmon_dev_attr_groups[] = {
|
||||||
|
&hwmon_dev_attr_group,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void hwmon_dev_release(struct device *dev)
|
||||||
|
{
|
||||||
|
kfree(to_hwmon_device(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct class hwmon_class = {
|
||||||
|
.name = "hwmon",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.dev_groups = hwmon_dev_attr_groups,
|
||||||
|
.dev_release = hwmon_dev_release,
|
||||||
|
};
|
||||||
|
|
||||||
static DEFINE_IDA(hwmon_ida);
|
static DEFINE_IDA(hwmon_ida);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hwmon_device_register_with_groups - register w/ hwmon
|
||||||
|
* @dev: the parent device
|
||||||
|
* @name: hwmon name attribute
|
||||||
|
* @drvdata: driver data to attach to created device
|
||||||
|
* @groups: List of attribute groups to create
|
||||||
|
*
|
||||||
|
* hwmon_device_unregister() must be called when the device is no
|
||||||
|
* longer needed.
|
||||||
|
*
|
||||||
|
* Returns the pointer to the new device.
|
||||||
|
*/
|
||||||
|
struct device *
|
||||||
|
hwmon_device_register_with_groups(struct device *dev, const char *name,
|
||||||
|
void *drvdata,
|
||||||
|
const struct attribute_group **groups)
|
||||||
|
{
|
||||||
|
struct hwmon_device *hwdev;
|
||||||
|
int err, id;
|
||||||
|
|
||||||
|
id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
|
||||||
|
if (id < 0)
|
||||||
|
return ERR_PTR(id);
|
||||||
|
|
||||||
|
hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
|
||||||
|
if (hwdev == NULL) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto ida_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
hwdev->name = name;
|
||||||
|
hwdev->dev.class = &hwmon_class;
|
||||||
|
hwdev->dev.parent = dev;
|
||||||
|
hwdev->dev.groups = groups;
|
||||||
|
hwdev->dev.of_node = dev ? dev->of_node : NULL;
|
||||||
|
dev_set_drvdata(&hwdev->dev, drvdata);
|
||||||
|
dev_set_name(&hwdev->dev, HWMON_ID_FORMAT, id);
|
||||||
|
err = device_register(&hwdev->dev);
|
||||||
|
if (err)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
return &hwdev->dev;
|
||||||
|
|
||||||
|
free:
|
||||||
|
kfree(hwdev);
|
||||||
|
ida_remove:
|
||||||
|
ida_simple_remove(&hwmon_ida, id);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hwmon_device_register - register w/ hwmon
|
* hwmon_device_register - register w/ hwmon
|
||||||
* @dev: the device to register
|
* @dev: the device to register
|
||||||
|
@ -40,20 +141,7 @@ static DEFINE_IDA(hwmon_ida);
|
||||||
*/
|
*/
|
||||||
struct device *hwmon_device_register(struct device *dev)
|
struct device *hwmon_device_register(struct device *dev)
|
||||||
{
|
{
|
||||||
struct device *hwdev;
|
return hwmon_device_register_with_groups(dev, NULL, NULL, NULL);
|
||||||
int id;
|
|
||||||
|
|
||||||
id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
|
|
||||||
if (id < 0)
|
|
||||||
return ERR_PTR(id);
|
|
||||||
|
|
||||||
hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
|
|
||||||
HWMON_ID_FORMAT, id);
|
|
||||||
|
|
||||||
if (IS_ERR(hwdev))
|
|
||||||
ida_simple_remove(&hwmon_ida, id);
|
|
||||||
|
|
||||||
return hwdev;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hwmon_device_register);
|
EXPORT_SYMBOL_GPL(hwmon_device_register);
|
||||||
|
|
||||||
|
@ -75,6 +163,69 @@ void hwmon_device_unregister(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hwmon_device_unregister);
|
EXPORT_SYMBOL_GPL(hwmon_device_unregister);
|
||||||
|
|
||||||
|
static void devm_hwmon_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
struct device *hwdev = *(struct device **)res;
|
||||||
|
|
||||||
|
hwmon_device_unregister(hwdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_hwmon_device_register_with_groups - register w/ hwmon
|
||||||
|
* @dev: the parent device
|
||||||
|
* @name: hwmon name attribute
|
||||||
|
* @drvdata: driver data to attach to created device
|
||||||
|
* @groups: List of attribute groups to create
|
||||||
|
*
|
||||||
|
* Returns the pointer to the new device. The new device is automatically
|
||||||
|
* unregistered with the parent device.
|
||||||
|
*/
|
||||||
|
struct device *
|
||||||
|
devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
|
||||||
|
void *drvdata,
|
||||||
|
const struct attribute_group **groups)
|
||||||
|
{
|
||||||
|
struct device **ptr, *hwdev;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
|
||||||
|
if (!ptr)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
|
||||||
|
if (IS_ERR(hwdev))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
*ptr = hwdev;
|
||||||
|
devres_add(dev, ptr);
|
||||||
|
return hwdev;
|
||||||
|
|
||||||
|
error:
|
||||||
|
devres_free(ptr);
|
||||||
|
return hwdev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
|
||||||
|
|
||||||
|
static int devm_hwmon_match(struct device *dev, void *res, void *data)
|
||||||
|
{
|
||||||
|
struct device **hwdev = res;
|
||||||
|
|
||||||
|
return *hwdev == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_hwmon_device_unregister - removes a previously registered hwmon device
|
||||||
|
*
|
||||||
|
* @dev: the parent device of the device to unregister
|
||||||
|
*/
|
||||||
|
void devm_hwmon_device_unregister(struct device *dev)
|
||||||
|
{
|
||||||
|
WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
|
||||||
|
|
||||||
static void __init hwmon_pci_quirks(void)
|
static void __init hwmon_pci_quirks(void)
|
||||||
{
|
{
|
||||||
#if defined CONFIG_X86 && defined CONFIG_PCI
|
#if defined CONFIG_X86 && defined CONFIG_PCI
|
||||||
|
@ -105,19 +256,21 @@ static void __init hwmon_pci_quirks(void)
|
||||||
|
|
||||||
static int __init hwmon_init(void)
|
static int __init hwmon_init(void)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
hwmon_pci_quirks();
|
hwmon_pci_quirks();
|
||||||
|
|
||||||
hwmon_class = class_create(THIS_MODULE, "hwmon");
|
err = class_register(&hwmon_class);
|
||||||
if (IS_ERR(hwmon_class)) {
|
if (err) {
|
||||||
pr_err("couldn't create sysfs class\n");
|
pr_err("couldn't register hwmon sysfs class\n");
|
||||||
return PTR_ERR(hwmon_class);
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit hwmon_exit(void)
|
static void __exit hwmon_exit(void)
|
||||||
{
|
{
|
||||||
class_destroy(hwmon_class);
|
class_unregister(&hwmon_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
subsys_initcall(hwmon_init);
|
subsys_initcall(hwmon_init);
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#define INA209_SHUNT_DEFAULT 10000 /* uOhm */
|
#define INA209_SHUNT_DEFAULT 10000 /* uOhm */
|
||||||
|
|
||||||
struct ina209_data {
|
struct ina209_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
@ -78,8 +78,8 @@ struct ina209_data {
|
||||||
|
|
||||||
static struct ina209_data *ina209_update_device(struct device *dev)
|
static struct ina209_data *ina209_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ina209_data *data = dev_get_drvdata(dev);
|
||||||
struct ina209_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct ina209_data *ret = data;
|
struct ina209_data *ret = data;
|
||||||
s32 val;
|
s32 val;
|
||||||
int i;
|
int i;
|
||||||
|
@ -234,7 +234,6 @@ static ssize_t ina209_set_interval(struct device *dev,
|
||||||
struct device_attribute *da,
|
struct device_attribute *da,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ina209_data *data = ina209_update_device(dev);
|
struct ina209_data *data = ina209_update_device(dev);
|
||||||
long val;
|
long val;
|
||||||
u16 regval;
|
u16 regval;
|
||||||
|
@ -250,7 +249,8 @@ static ssize_t ina209_set_interval(struct device *dev,
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
|
regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
|
||||||
val);
|
val);
|
||||||
i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION, regval);
|
i2c_smbus_write_word_swapped(data->client, INA209_CONFIGURATION,
|
||||||
|
regval);
|
||||||
data->regs[INA209_CONFIGURATION] = regval;
|
data->regs[INA209_CONFIGURATION] = regval;
|
||||||
data->update_interval = ina209_interval_from_reg(regval);
|
data->update_interval = ina209_interval_from_reg(regval);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
@ -260,8 +260,7 @@ static ssize_t ina209_set_interval(struct device *dev,
|
||||||
static ssize_t ina209_show_interval(struct device *dev,
|
static ssize_t ina209_show_interval(struct device *dev,
|
||||||
struct device_attribute *da, char *buf)
|
struct device_attribute *da, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ina209_data *data = dev_get_drvdata(dev);
|
||||||
struct ina209_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
|
return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
|
||||||
}
|
}
|
||||||
|
@ -285,9 +284,9 @@ static ssize_t ina209_reset_history(struct device *dev,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ina209_data *data = i2c_get_clientdata(client);
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct ina209_data *data = dev_get_drvdata(dev);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
u32 mask = attr->index;
|
u32 mask = attr->index;
|
||||||
long val;
|
long val;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -312,7 +311,6 @@ static ssize_t ina209_set_value(struct device *dev,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ina209_data *data = ina209_update_device(dev);
|
struct ina209_data *data = ina209_update_device(dev);
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
int reg = attr->index;
|
int reg = attr->index;
|
||||||
|
@ -332,7 +330,7 @@ static ssize_t ina209_set_value(struct device *dev,
|
||||||
count = ret;
|
count = ret;
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
i2c_smbus_write_word_swapped(client, reg, ret);
|
i2c_smbus_write_word_swapped(data->client, reg, ret);
|
||||||
data->regs[reg] = ret;
|
data->regs[reg] = ret;
|
||||||
abort:
|
abort:
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
@ -457,7 +455,7 @@ static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
|
||||||
* Finally, construct an array of pointers to members of the above objects,
|
* Finally, construct an array of pointers to members of the above objects,
|
||||||
* as required for sysfs_create_group()
|
* as required for sysfs_create_group()
|
||||||
*/
|
*/
|
||||||
static struct attribute *ina209_attributes[] = {
|
static struct attribute *ina209_attrs[] = {
|
||||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_in0_input_highest.dev_attr.attr,
|
&sensor_dev_attr_in0_input_highest.dev_attr.attr,
|
||||||
&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
|
&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
|
||||||
|
@ -498,10 +496,7 @@ static struct attribute *ina209_attributes[] = {
|
||||||
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(ina209);
|
||||||
static const struct attribute_group ina209_group = {
|
|
||||||
.attrs = ina209_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ina209_restore_conf(struct i2c_client *client,
|
static void ina209_restore_conf(struct i2c_client *client,
|
||||||
struct ina209_data *data)
|
struct ina209_data *data)
|
||||||
|
@ -565,6 +560,7 @@ static int ina209_probe(struct i2c_client *client,
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct ina209_data *data;
|
struct ina209_data *data;
|
||||||
|
struct device *hwmon_dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||||
|
@ -575,27 +571,23 @@ static int ina209_probe(struct i2c_client *client,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
i2c_set_clientdata(client, data);
|
||||||
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
ret = ina209_init_client(client, data);
|
ret = ina209_init_client(client, data);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
|
||||||
ret = sysfs_create_group(&client->dev.kobj, &ina209_group);
|
client->name,
|
||||||
if (ret)
|
data, ina209_groups);
|
||||||
|
if (IS_ERR(hwmon_dev)) {
|
||||||
|
ret = PTR_ERR(hwmon_dev);
|
||||||
goto out_restore_conf;
|
goto out_restore_conf;
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto out_hwmon_device_register;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_hwmon_device_register:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ina209_group);
|
|
||||||
out_restore_conf:
|
out_restore_conf:
|
||||||
ina209_restore_conf(client, data);
|
ina209_restore_conf(client, data);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -605,8 +597,6 @@ static int ina209_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct ina209_data *data = i2c_get_clientdata(client);
|
struct ina209_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ina209_group);
|
|
||||||
ina209_restore_conf(client, data);
|
ina209_restore_conf(client, data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -78,7 +78,7 @@ struct ina2xx_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ina2xx_data {
|
struct ina2xx_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
const struct ina2xx_config *config;
|
const struct ina2xx_config *config;
|
||||||
|
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
|
@ -112,8 +112,8 @@ static const struct ina2xx_config ina2xx_config[] = {
|
||||||
|
|
||||||
static struct ina2xx_data *ina2xx_update_device(struct device *dev)
|
static struct ina2xx_data *ina2xx_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ina2xx_data *data = dev_get_drvdata(dev);
|
||||||
struct ina2xx_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct ina2xx_data *ret = data;
|
struct ina2xx_data *ret = data;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
@ -203,41 +203,39 @@ static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
|
||||||
INA2XX_POWER);
|
INA2XX_POWER);
|
||||||
|
|
||||||
/* pointers to created device attributes */
|
/* pointers to created device attributes */
|
||||||
static struct attribute *ina2xx_attributes[] = {
|
static struct attribute *ina2xx_attrs[] = {
|
||||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_power1_input.dev_attr.attr,
|
&sensor_dev_attr_power1_input.dev_attr.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(ina2xx);
|
||||||
static const struct attribute_group ina2xx_group = {
|
|
||||||
.attrs = ina2xx_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int ina2xx_probe(struct i2c_client *client,
|
static int ina2xx_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct ina2xx_data *data;
|
|
||||||
struct ina2xx_platform_data *pdata;
|
struct ina2xx_platform_data *pdata;
|
||||||
int ret;
|
struct device *dev = &client->dev;
|
||||||
u32 val;
|
struct ina2xx_data *data;
|
||||||
|
struct device *hwmon_dev;
|
||||||
long shunt = 10000; /* default shunt value 10mOhms */
|
long shunt = 10000; /* default shunt value 10mOhms */
|
||||||
|
u32 val;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dev_get_platdata(&client->dev)) {
|
if (dev_get_platdata(dev)) {
|
||||||
pdata = dev_get_platdata(&client->dev);
|
pdata = dev_get_platdata(dev);
|
||||||
shunt = pdata->shunt_uohms;
|
shunt = pdata->shunt_uohms;
|
||||||
} else if (!of_property_read_u32(client->dev.of_node,
|
} else if (!of_property_read_u32(dev->of_node,
|
||||||
"shunt-resistor", &val)) {
|
"shunt-resistor", &val)) {
|
||||||
shunt = val;
|
shunt = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shunt <= 0)
|
if (shunt <= 0)
|
||||||
|
@ -255,37 +253,18 @@ static int ina2xx_probe(struct i2c_client *client,
|
||||||
i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
|
i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
|
||||||
data->config->calibration_factor / shunt);
|
data->config->calibration_factor / shunt);
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
ret = sysfs_create_group(&client->dev.kobj, &ina2xx_group);
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
if (ret)
|
data, ina2xx_groups);
|
||||||
return ret;
|
if (IS_ERR(hwmon_dev))
|
||||||
|
return PTR_ERR(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto out_err_hwmon;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n",
|
|
||||||
id->name, shunt);
|
id->name, shunt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err_hwmon:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ina2xx_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct ina2xx_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id ina2xx_id[] = {
|
static const struct i2c_device_id ina2xx_id[] = {
|
||||||
|
@ -302,7 +281,6 @@ static struct i2c_driver ina2xx_driver = {
|
||||||
.name = "ina2xx",
|
.name = "ina2xx",
|
||||||
},
|
},
|
||||||
.probe = ina2xx_probe,
|
.probe = ina2xx_probe,
|
||||||
.remove = ina2xx_remove,
|
|
||||||
.id_table = ina2xx_id,
|
.id_table = ina2xx_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ static struct jc42_chips jc42_chips[] = {
|
||||||
|
|
||||||
/* Each client has this additional data */
|
/* Each client has this additional data */
|
||||||
struct jc42_data {
|
struct jc42_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
struct mutex update_lock; /* protect register access */
|
struct mutex update_lock; /* protect register access */
|
||||||
bool extended; /* true if extended range supported */
|
bool extended; /* true if extended range supported */
|
||||||
bool valid;
|
bool valid;
|
||||||
|
@ -193,21 +193,21 @@ MODULE_DEVICE_TABLE(i2c, jc42_id);
|
||||||
|
|
||||||
static int jc42_suspend(struct device *dev)
|
static int jc42_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct jc42_data *data = dev_get_drvdata(dev);
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
data->config |= JC42_CFG_SHUTDOWN;
|
data->config |= JC42_CFG_SHUTDOWN;
|
||||||
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
|
i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
|
||||||
|
data->config);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jc42_resume(struct device *dev)
|
static int jc42_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct jc42_data *data = dev_get_drvdata(dev);
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
data->config &= ~JC42_CFG_SHUTDOWN;
|
data->config &= ~JC42_CFG_SHUTDOWN;
|
||||||
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
|
i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
|
||||||
|
data->config);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,15 +317,14 @@ static ssize_t set_##value(struct device *dev, \
|
||||||
struct device_attribute *attr, \
|
struct device_attribute *attr, \
|
||||||
const char *buf, size_t count) \
|
const char *buf, size_t count) \
|
||||||
{ \
|
{ \
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
struct jc42_data *data = dev_get_drvdata(dev); \
|
||||||
struct jc42_data *data = i2c_get_clientdata(client); \
|
|
||||||
int err, ret = count; \
|
int err, ret = count; \
|
||||||
long val; \
|
long val; \
|
||||||
if (kstrtol(buf, 10, &val) < 0) \
|
if (kstrtol(buf, 10, &val) < 0) \
|
||||||
return -EINVAL; \
|
return -EINVAL; \
|
||||||
mutex_lock(&data->update_lock); \
|
mutex_lock(&data->update_lock); \
|
||||||
data->value = jc42_temp_to_reg(val, data->extended); \
|
data->value = jc42_temp_to_reg(val, data->extended); \
|
||||||
err = i2c_smbus_write_word_swapped(client, reg, data->value); \
|
err = i2c_smbus_write_word_swapped(data->client, reg, data->value); \
|
||||||
if (err < 0) \
|
if (err < 0) \
|
||||||
ret = err; \
|
ret = err; \
|
||||||
mutex_unlock(&data->update_lock); \
|
mutex_unlock(&data->update_lock); \
|
||||||
|
@ -344,8 +343,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct jc42_data *data = dev_get_drvdata(dev);
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int diff, hyst;
|
int diff, hyst;
|
||||||
int err;
|
int err;
|
||||||
|
@ -368,7 +366,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->config = (data->config & ~JC42_CFG_HYST_MASK)
|
data->config = (data->config & ~JC42_CFG_HYST_MASK)
|
||||||
| (hyst << JC42_CFG_HYST_SHIFT);
|
| (hyst << JC42_CFG_HYST_SHIFT);
|
||||||
err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
|
err = i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
|
||||||
data->config);
|
data->config);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
ret = err;
|
ret = err;
|
||||||
|
@ -430,8 +428,7 @@ static umode_t jc42_attribute_mode(struct kobject *kobj,
|
||||||
struct attribute *attr, int index)
|
struct attribute *attr, int index)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct jc42_data *data = dev_get_drvdata(dev);
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
|
||||||
unsigned int config = data->config;
|
unsigned int config = data->config;
|
||||||
bool readonly;
|
bool readonly;
|
||||||
|
|
||||||
|
@ -452,6 +449,7 @@ static const struct attribute_group jc42_group = {
|
||||||
.attrs = jc42_attributes,
|
.attrs = jc42_attributes,
|
||||||
.is_visible = jc42_attribute_mode,
|
.is_visible = jc42_attribute_mode,
|
||||||
};
|
};
|
||||||
|
__ATTRIBUTE_GROUPS(jc42);
|
||||||
|
|
||||||
/* Return 0 if detection is successful, -ENODEV otherwise */
|
/* Return 0 if detection is successful, -ENODEV otherwise */
|
||||||
static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
|
static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||||
|
@ -487,14 +485,16 @@ static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||||
|
|
||||||
static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct jc42_data *data;
|
|
||||||
int config, cap, err;
|
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct jc42_data *data;
|
||||||
|
int config, cap;
|
||||||
|
|
||||||
data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->client = client;
|
||||||
i2c_set_clientdata(client, data);
|
i2c_set_clientdata(client, data);
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
|
@ -515,29 +515,15 @@ static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
}
|
}
|
||||||
data->config = config;
|
data->config = config;
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
err = sysfs_create_group(&dev->kobj, &jc42_group);
|
data,
|
||||||
if (err)
|
jc42_groups);
|
||||||
return err;
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
sysfs_remove_group(&dev->kobj, &jc42_group);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jc42_remove(struct i2c_client *client)
|
static int jc42_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
struct jc42_data *data = i2c_get_clientdata(client);
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &jc42_group);
|
|
||||||
|
|
||||||
/* Restore original configuration except hysteresis */
|
/* Restore original configuration except hysteresis */
|
||||||
if ((data->config & ~JC42_CFG_HYST_MASK) !=
|
if ((data->config & ~JC42_CFG_HYST_MASK) !=
|
||||||
|
@ -553,8 +539,8 @@ static int jc42_remove(struct i2c_client *client)
|
||||||
|
|
||||||
static struct jc42_data *jc42_update_device(struct device *dev)
|
static struct jc42_data *jc42_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct jc42_data *data = dev_get_drvdata(dev);
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct jc42_data *ret = data;
|
struct jc42_data *ret = data;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,6 @@ out_dev_reg_failed:
|
||||||
out_dev_create_file_failed:
|
out_dev_create_file_failed:
|
||||||
device_remove_file(&spi->dev, &dev_attr_temp1_input);
|
device_remove_file(&spi->dev, &dev_attr_temp1_input);
|
||||||
out_dev_create_temp_file_failed:
|
out_dev_create_temp_file_failed:
|
||||||
spi_set_drvdata(spi, NULL);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +184,6 @@ static int lm70_remove(struct spi_device *spi)
|
||||||
hwmon_device_unregister(p_lm70->hwmon_dev);
|
hwmon_device_unregister(p_lm70->hwmon_dev);
|
||||||
device_remove_file(&spi->dev, &dev_attr_temp1_input);
|
device_remove_file(&spi->dev, &dev_attr_temp1_input);
|
||||||
device_remove_file(&spi->dev, &dev_attr_name);
|
device_remove_file(&spi->dev, &dev_attr_name);
|
||||||
spi_set_drvdata(spi, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ static const unsigned short lm73_convrates[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lm73_data {
|
struct lm73_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
u8 ctrl; /* control register value */
|
u8 ctrl; /* control register value */
|
||||||
};
|
};
|
||||||
|
@ -66,7 +66,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm73_data *data = dev_get_drvdata(dev);
|
||||||
long temp;
|
long temp;
|
||||||
short value;
|
short value;
|
||||||
s32 err;
|
s32 err;
|
||||||
|
@ -77,7 +77,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||||
|
|
||||||
/* Write value */
|
/* Write value */
|
||||||
value = clamp_val(temp / 250, LM73_TEMP_MIN, LM73_TEMP_MAX) << 5;
|
value = clamp_val(temp / 250, LM73_TEMP_MIN, LM73_TEMP_MAX) << 5;
|
||||||
err = i2c_smbus_write_word_swapped(client, attr->index, value);
|
err = i2c_smbus_write_word_swapped(data->client, attr->index, value);
|
||||||
return (err < 0) ? err : count;
|
return (err < 0) ? err : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,10 +85,10 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm73_data *data = dev_get_drvdata(dev);
|
||||||
int temp;
|
int temp;
|
||||||
|
|
||||||
s32 err = i2c_smbus_read_word_swapped(client, attr->index);
|
s32 err = i2c_smbus_read_word_swapped(data->client, attr->index);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -101,8 +101,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
|
||||||
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm73_data *data = dev_get_drvdata(dev);
|
||||||
struct lm73_data *data = i2c_get_clientdata(client);
|
|
||||||
unsigned long convrate;
|
unsigned long convrate;
|
||||||
s32 err;
|
s32 err;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
@ -124,7 +123,8 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
||||||
mutex_lock(&data->lock);
|
mutex_lock(&data->lock);
|
||||||
data->ctrl &= LM73_CTRL_TO_MASK;
|
data->ctrl &= LM73_CTRL_TO_MASK;
|
||||||
data->ctrl |= res << LM73_CTRL_RES_SHIFT;
|
data->ctrl |= res << LM73_CTRL_RES_SHIFT;
|
||||||
err = i2c_smbus_write_byte_data(client, LM73_REG_CTRL, data->ctrl);
|
err = i2c_smbus_write_byte_data(data->client, LM73_REG_CTRL,
|
||||||
|
data->ctrl);
|
||||||
mutex_unlock(&data->lock);
|
mutex_unlock(&data->lock);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -136,8 +136,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
||||||
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm73_data *data = dev_get_drvdata(dev);
|
||||||
struct lm73_data *data = i2c_get_clientdata(client);
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
|
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
|
||||||
|
@ -147,13 +146,12 @@ static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
||||||
static ssize_t show_maxmin_alarm(struct device *dev,
|
static ssize_t show_maxmin_alarm(struct device *dev,
|
||||||
struct device_attribute *da, char *buf)
|
struct device_attribute *da, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
struct lm73_data *data = i2c_get_clientdata(client);
|
struct lm73_data *data = dev_get_drvdata(dev);
|
||||||
s32 ctrl;
|
s32 ctrl;
|
||||||
|
|
||||||
mutex_lock(&data->lock);
|
mutex_lock(&data->lock);
|
||||||
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
|
ctrl = i2c_smbus_read_byte_data(data->client, LM73_REG_CTRL);
|
||||||
if (ctrl < 0)
|
if (ctrl < 0)
|
||||||
goto abort;
|
goto abort;
|
||||||
data->ctrl = ctrl;
|
data->ctrl = ctrl;
|
||||||
|
@ -183,7 +181,7 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
|
||||||
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
|
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
|
||||||
show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
|
show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
|
||||||
|
|
||||||
static struct attribute *lm73_attributes[] = {
|
static struct attribute *lm73_attrs[] = {
|
||||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||||
|
@ -192,10 +190,7 @@ static struct attribute *lm73_attributes[] = {
|
||||||
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
|
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(lm73);
|
||||||
static const struct attribute_group lm73_group = {
|
|
||||||
.attrs = lm73_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -204,16 +199,16 @@ static const struct attribute_group lm73_group = {
|
||||||
static int
|
static int
|
||||||
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
int status;
|
struct device *dev = &client->dev;
|
||||||
|
struct device *hwmon_dev;
|
||||||
struct lm73_data *data;
|
struct lm73_data *data;
|
||||||
int ctrl;
|
int ctrl;
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(struct lm73_data),
|
data = devm_kzalloc(dev, sizeof(struct lm73_data), GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->lock);
|
mutex_init(&data->lock);
|
||||||
|
|
||||||
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
|
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
|
||||||
|
@ -221,33 +216,13 @@ lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
return ctrl;
|
return ctrl;
|
||||||
data->ctrl = ctrl;
|
data->ctrl = ctrl;
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
status = sysfs_create_group(&client->dev.kobj, &lm73_group);
|
data, lm73_groups);
|
||||||
if (status)
|
if (IS_ERR(hwmon_dev))
|
||||||
return status;
|
return PTR_ERR(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
dev_info(dev, "sensor '%s'\n", client->name);
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
status = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "%s: sensor '%s'\n",
|
|
||||||
dev_name(data->hwmon_dev), client->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm73_group);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lm73_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct lm73_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm73_group);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +275,6 @@ static struct i2c_driver lm73_driver = {
|
||||||
.name = "lm73",
|
.name = "lm73",
|
||||||
},
|
},
|
||||||
.probe = lm73_probe,
|
.probe = lm73_probe,
|
||||||
.remove = lm73_remove,
|
|
||||||
.id_table = lm73_ids,
|
.id_table = lm73_ids,
|
||||||
.detect = lm73_detect,
|
.detect = lm73_detect,
|
||||||
.address_list = normal_i2c,
|
.address_list = normal_i2c,
|
||||||
|
|
|
@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
|
||||||
|
|
||||||
/* Client data (each client gets its own) */
|
/* Client data (each client gets its own) */
|
||||||
struct lm95234_data {
|
struct lm95234_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
unsigned long last_updated, interval; /* in jiffies */
|
unsigned long last_updated, interval; /* in jiffies */
|
||||||
bool valid; /* false until following fields are valid */
|
bool valid; /* false until following fields are valid */
|
||||||
|
@ -114,9 +114,9 @@ static u16 update_intervals[] = { 143, 364, 1000, 2500 };
|
||||||
|
|
||||||
/* Fill value cache. Must be called with update lock held. */
|
/* Fill value cache. Must be called with update lock held. */
|
||||||
|
|
||||||
static int lm95234_fill_cache(struct i2c_client *client)
|
static int lm95234_fill_cache(struct lm95234_data *data,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
|
ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
|
||||||
|
@ -157,9 +157,9 @@ static int lm95234_fill_cache(struct i2c_client *client)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lm95234_update_device(struct i2c_client *client,
|
static int lm95234_update_device(struct lm95234_data *data)
|
||||||
struct lm95234_data *data)
|
|
||||||
{
|
{
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
@ -169,7 +169,7 @@ static int lm95234_update_device(struct i2c_client *client,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!data->valid) {
|
if (!data->valid) {
|
||||||
ret = lm95234_fill_cache(client);
|
ret = lm95234_fill_cache(data, client);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
@ -209,10 +209,9 @@ abort:
|
||||||
static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -224,10 +223,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t show_alarm(struct device *dev,
|
static ssize_t show_alarm(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
u32 mask = to_sensor_dev_attr(attr)->index;
|
u32 mask = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -238,10 +236,9 @@ static ssize_t show_alarm(struct device *dev,
|
||||||
static ssize_t show_type(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_type(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
u8 mask = to_sensor_dev_attr(attr)->index;
|
u8 mask = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -252,11 +249,10 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_type(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_type(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
u8 mask = to_sensor_dev_attr(attr)->index;
|
u8 mask = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -274,7 +270,7 @@ static ssize_t set_type(struct device *dev, struct device_attribute *attr,
|
||||||
else
|
else
|
||||||
data->sensor_type &= ~mask;
|
data->sensor_type &= ~mask;
|
||||||
data->valid = false;
|
data->valid = false;
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_REM_MODEL,
|
||||||
data->sensor_type);
|
data->sensor_type);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
@ -284,10 +280,9 @@ static ssize_t set_type(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -298,11 +293,10 @@ static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
long val;
|
long val;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -315,7 +309,7 @@ static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->tcrit2[index] = val;
|
data->tcrit2[index] = val;
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT2(index), val);
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT2(index), val);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -324,10 +318,9 @@ static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t show_tcrit2_hyst(struct device *dev,
|
static ssize_t show_tcrit2_hyst(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -340,8 +333,7 @@ static ssize_t show_tcrit2_hyst(struct device *dev,
|
||||||
static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
|
|
||||||
return sprintf(buf, "%u", data->tcrit1[index] * 1000);
|
return sprintf(buf, "%u", data->tcrit1[index] * 1000);
|
||||||
|
@ -350,11 +342,10 @@ static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
|
int ret = lm95234_update_device(data);
|
||||||
long val;
|
long val;
|
||||||
int ret = lm95234_update_device(client, data);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -367,7 +358,7 @@ static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->tcrit1[index] = val;
|
data->tcrit1[index] = val;
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT1(index), val);
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT1(index), val);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -376,10 +367,9 @@ static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t show_tcrit1_hyst(struct device *dev,
|
static ssize_t show_tcrit1_hyst(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -393,11 +383,10 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
|
int ret = lm95234_update_device(data);
|
||||||
long val;
|
long val;
|
||||||
int ret = lm95234_update_device(client, data);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -411,7 +400,7 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->thyst = val;
|
data->thyst = val;
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT_HYST, val);
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT_HYST, val);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -420,10 +409,9 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
|
||||||
static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
int ret = lm95234_update_device(client, data);
|
int ret = lm95234_update_device(data);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -434,11 +422,10 @@ static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
int index = to_sensor_dev_attr(attr)->index;
|
int index = to_sensor_dev_attr(attr)->index;
|
||||||
|
int ret = lm95234_update_device(data);
|
||||||
long val;
|
long val;
|
||||||
int ret = lm95234_update_device(client, data);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -452,7 +439,7 @@ static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->toffset[index] = val;
|
data->toffset[index] = val;
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_OFFSET(index), val);
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_OFFSET(index), val);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -461,9 +448,8 @@ static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
int ret = lm95234_update_device(data);
|
||||||
int ret = lm95234_update_device(client, data);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -475,11 +461,10 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct lm95234_data *data = dev_get_drvdata(dev);
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
int ret = lm95234_update_device(data);
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
u8 regval;
|
u8 regval;
|
||||||
int ret = lm95234_update_device(client, data);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -495,7 +480,7 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->interval = msecs_to_jiffies(update_intervals[regval]);
|
data->interval = msecs_to_jiffies(update_intervals[regval]);
|
||||||
i2c_smbus_write_byte_data(client, LM95234_REG_CONVRATE, regval);
|
i2c_smbus_write_byte_data(data->client, LM95234_REG_CONVRATE, regval);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -579,7 +564,7 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
|
||||||
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
|
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
|
||||||
set_interval);
|
set_interval);
|
||||||
|
|
||||||
static struct attribute *lm95234_attributes[] = {
|
static struct attribute *lm95234_attrs[] = {
|
||||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||||
|
@ -621,10 +606,7 @@ static struct attribute *lm95234_attributes[] = {
|
||||||
&dev_attr_update_interval.attr,
|
&dev_attr_update_interval.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(lm95234);
|
||||||
static const struct attribute_group lm95234_group = {
|
|
||||||
.attrs = lm95234_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int lm95234_detect(struct i2c_client *client,
|
static int lm95234_detect(struct i2c_client *client,
|
||||||
struct i2c_board_info *info)
|
struct i2c_board_info *info)
|
||||||
|
@ -701,13 +683,14 @@ static int lm95234_probe(struct i2c_client *client,
|
||||||
{
|
{
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
struct lm95234_data *data;
|
struct lm95234_data *data;
|
||||||
|
struct device *hwmon_dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
/* Initialize the LM95234 chip */
|
/* Initialize the LM95234 chip */
|
||||||
|
@ -715,32 +698,10 @@ static int lm95234_probe(struct i2c_client *client,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
err = sysfs_create_group(&dev->kobj, &lm95234_group);
|
data,
|
||||||
if (err)
|
lm95234_groups);
|
||||||
return err;
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove_files:
|
|
||||||
sysfs_remove_group(&dev->kobj, &lm95234_group);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lm95234_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct lm95234_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm95234_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Driver data (common to all clients) */
|
/* Driver data (common to all clients) */
|
||||||
|
@ -756,7 +717,6 @@ static struct i2c_driver lm95234_driver = {
|
||||||
.name = DRVNAME,
|
.name = DRVNAME,
|
||||||
},
|
},
|
||||||
.probe = lm95234_probe,
|
.probe = lm95234_probe,
|
||||||
.remove = lm95234_remove,
|
|
||||||
.id_table = lm95234_id,
|
.id_table = lm95234_id,
|
||||||
.detect = lm95234_detect,
|
.detect = lm95234_detect,
|
||||||
.address_list = normal_i2c,
|
.address_list = normal_i2c,
|
||||||
|
|
|
@ -51,7 +51,9 @@ enum ltc4245_cmd {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ltc4245_data {
|
struct ltc4245_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
|
||||||
|
const struct attribute_group *groups[3];
|
||||||
|
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
@ -77,8 +79,8 @@ struct ltc4245_data {
|
||||||
*/
|
*/
|
||||||
static void ltc4245_update_gpios(struct device *dev)
|
static void ltc4245_update_gpios(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ltc4245_data *data = dev_get_drvdata(dev);
|
||||||
struct ltc4245_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
u8 gpio_curr, gpio_next, gpio_reg;
|
u8 gpio_curr, gpio_next, gpio_reg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -130,8 +132,8 @@ static void ltc4245_update_gpios(struct device *dev)
|
||||||
|
|
||||||
static struct ltc4245_data *ltc4245_update_device(struct device *dev)
|
static struct ltc4245_data *ltc4245_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ltc4245_data *data = dev_get_drvdata(dev);
|
||||||
struct ltc4245_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
s32 val;
|
s32 val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -455,41 +457,14 @@ static const struct attribute_group ltc4245_gpio_group = {
|
||||||
.attrs = ltc4245_gpio_attributes,
|
.attrs = ltc4245_gpio_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ltc4245_sysfs_create_groups(struct i2c_client *client)
|
static void ltc4245_sysfs_add_groups(struct ltc4245_data *data)
|
||||||
{
|
{
|
||||||
struct ltc4245_data *data = i2c_get_clientdata(client);
|
/* standard sysfs attributes */
|
||||||
struct device *dev = &client->dev;
|
data->groups[0] = <c4245_std_group;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* register the standard sysfs attributes */
|
|
||||||
ret = sysfs_create_group(&dev->kobj, <c4245_std_group);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "unable to register standard attributes\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we're using the extra gpio support, register it's attributes */
|
/* if we're using the extra gpio support, register it's attributes */
|
||||||
if (data->use_extra_gpios) {
|
|
||||||
ret = sysfs_create_group(&dev->kobj, <c4245_gpio_group);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "unable to register gpio attributes\n");
|
|
||||||
sysfs_remove_group(&dev->kobj, <c4245_std_group);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ltc4245_sysfs_remove_groups(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct ltc4245_data *data = i2c_get_clientdata(client);
|
|
||||||
struct device *dev = &client->dev;
|
|
||||||
|
|
||||||
if (data->use_extra_gpios)
|
if (data->use_extra_gpios)
|
||||||
sysfs_remove_group(&dev->kobj, <c4245_gpio_group);
|
data->groups[1] = <c4245_gpio_group;
|
||||||
|
|
||||||
sysfs_remove_group(&dev->kobj, <c4245_std_group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ltc4245_use_extra_gpios(struct i2c_client *client)
|
static bool ltc4245_use_extra_gpios(struct i2c_client *client)
|
||||||
|
@ -517,7 +492,7 @@ static int ltc4245_probe(struct i2c_client *client,
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct ltc4245_data *data;
|
struct ltc4245_data *data;
|
||||||
int ret;
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -526,7 +501,7 @@ static int ltc4245_probe(struct i2c_client *client,
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
data->use_extra_gpios = ltc4245_use_extra_gpios(client);
|
data->use_extra_gpios = ltc4245_use_extra_gpios(client);
|
||||||
|
|
||||||
|
@ -534,30 +509,25 @@ static int ltc4245_probe(struct i2c_client *client,
|
||||||
i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
|
i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
|
||||||
i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
|
i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* Add sysfs hooks */
|
||||||
ret = ltc4245_sysfs_create_groups(client);
|
ltc4245_sysfs_add_groups(data);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
hwmon_dev = hwmon_device_register_with_groups(&client->dev,
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
client->name, data,
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
data->groups);
|
||||||
goto out_hwmon_device_register;
|
if (IS_ERR(hwmon_dev))
|
||||||
}
|
return PTR_ERR(hwmon_dev);
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, hwmon_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_hwmon_device_register:
|
|
||||||
ltc4245_sysfs_remove_groups(client);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ltc4245_remove(struct i2c_client *client)
|
static int ltc4245_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct ltc4245_data *data = i2c_get_clientdata(client);
|
struct device *hwmon_dev = i2c_get_clientdata(client);
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
hwmon_device_unregister(hwmon_dev);
|
||||||
ltc4245_sysfs_remove_groups(client);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
#define FAULT_OC (1<<2)
|
#define FAULT_OC (1<<2)
|
||||||
|
|
||||||
struct ltc4261_data {
|
struct ltc4261_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
@ -67,8 +67,8 @@ struct ltc4261_data {
|
||||||
|
|
||||||
static struct ltc4261_data *ltc4261_update_device(struct device *dev)
|
static struct ltc4261_data *ltc4261_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct ltc4261_data *data = dev_get_drvdata(dev);
|
||||||
struct ltc4261_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct ltc4261_data *ret = data;
|
struct ltc4261_data *ret = data;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
@ -150,7 +150,6 @@ static ssize_t ltc4261_show_bool(struct device *dev,
|
||||||
struct device_attribute *da, char *buf)
|
struct device_attribute *da, char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ltc4261_data *data = ltc4261_update_device(dev);
|
struct ltc4261_data *data = ltc4261_update_device(dev);
|
||||||
u8 fault;
|
u8 fault;
|
||||||
|
|
||||||
|
@ -159,7 +158,7 @@ static ssize_t ltc4261_show_bool(struct device *dev,
|
||||||
|
|
||||||
fault = data->regs[LTC4261_FAULT] & attr->index;
|
fault = data->regs[LTC4261_FAULT] & attr->index;
|
||||||
if (fault) /* Clear reported faults in chip register */
|
if (fault) /* Clear reported faults in chip register */
|
||||||
i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
|
i2c_smbus_write_byte_data(data->client, LTC4261_FAULT, ~fault);
|
||||||
|
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
|
return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +196,7 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL,
|
||||||
static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
|
static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
|
||||||
FAULT_OC);
|
FAULT_OC);
|
||||||
|
|
||||||
static struct attribute *ltc4261_attributes[] = {
|
static struct attribute *ltc4261_attrs[] = {
|
||||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
|
&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
|
||||||
&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
|
&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
|
||||||
|
@ -210,62 +209,38 @@ static struct attribute *ltc4261_attributes[] = {
|
||||||
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(ltc4261);
|
||||||
static const struct attribute_group ltc4261_group = {
|
|
||||||
.attrs = ltc4261_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int ltc4261_probe(struct i2c_client *client,
|
static int ltc4261_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
|
struct device *dev = &client->dev;
|
||||||
struct ltc4261_data *data;
|
struct ltc4261_data *data;
|
||||||
int ret;
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
|
if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
|
||||||
dev_err(&client->dev, "Failed to read status register\n");
|
dev_err(dev, "Failed to read status register\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
/* Clear faults */
|
/* Clear faults */
|
||||||
i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
|
i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
ret = sysfs_create_group(&client->dev.kobj, <c4261_group);
|
data,
|
||||||
if (ret)
|
ltc4261_groups);
|
||||||
return ret;
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto out_hwmon_device_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_hwmon_device_register:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, <c4261_group);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ltc4261_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct ltc4261_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, <c4261_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id ltc4261_id[] = {
|
static const struct i2c_device_id ltc4261_id[] = {
|
||||||
|
@ -281,7 +256,6 @@ static struct i2c_driver ltc4261_driver = {
|
||||||
.name = "ltc4261",
|
.name = "ltc4261",
|
||||||
},
|
},
|
||||||
.probe = ltc4261_probe,
|
.probe = ltc4261_probe,
|
||||||
.remove = ltc4261_remove,
|
|
||||||
.id_table = ltc4261_id,
|
.id_table = ltc4261_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,8 @@ static const bool max16065_have_current[] = {
|
||||||
|
|
||||||
struct max16065_data {
|
struct max16065_data {
|
||||||
enum chips type;
|
enum chips type;
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
const struct attribute_group *groups[4];
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
bool valid;
|
bool valid;
|
||||||
unsigned long last_updated; /* in jiffies */
|
unsigned long last_updated; /* in jiffies */
|
||||||
|
@ -144,8 +145,8 @@ static int max16065_read_adc(struct i2c_client *client, int reg)
|
||||||
|
|
||||||
static struct max16065_data *max16065_update_device(struct device *dev)
|
static struct max16065_data *max16065_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max16065_data *data = dev_get_drvdata(dev);
|
||||||
struct max16065_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
||||||
|
@ -186,7 +187,7 @@ static ssize_t max16065_show_alarm(struct device *dev,
|
||||||
|
|
||||||
val &= (1 << attr2->index);
|
val &= (1 << attr2->index);
|
||||||
if (val)
|
if (val)
|
||||||
i2c_smbus_write_byte_data(to_i2c_client(dev),
|
i2c_smbus_write_byte_data(data->client,
|
||||||
MAX16065_FAULT(attr2->nr), val);
|
MAX16065_FAULT(attr2->nr), val);
|
||||||
|
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
|
return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
|
||||||
|
@ -223,8 +224,7 @@ static ssize_t max16065_set_limit(struct device *dev,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
|
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max16065_data *data = dev_get_drvdata(dev);
|
||||||
struct max16065_data *data = i2c_get_clientdata(client);
|
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int err;
|
int err;
|
||||||
int limit;
|
int limit;
|
||||||
|
@ -238,7 +238,7 @@ static ssize_t max16065_set_limit(struct device *dev,
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->limit[attr2->nr][attr2->index]
|
data->limit[attr2->nr][attr2->index]
|
||||||
= LIMIT_TO_MV(limit, data->range[attr2->index]);
|
= LIMIT_TO_MV(limit, data->range[attr2->index]);
|
||||||
i2c_smbus_write_byte_data(client,
|
i2c_smbus_write_byte_data(data->client,
|
||||||
MAX16065_LIMIT(attr2->nr, attr2->index),
|
MAX16065_LIMIT(attr2->nr, attr2->index),
|
||||||
limit);
|
limit);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
@ -250,8 +250,7 @@ static ssize_t max16065_show_limit(struct device *dev,
|
||||||
struct device_attribute *da, char *buf)
|
struct device_attribute *da, char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
|
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max16065_data *data = dev_get_drvdata(dev);
|
||||||
struct max16065_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||||
data->limit[attr2->nr][attr2->index]);
|
data->limit[attr2->nr][attr2->index]);
|
||||||
|
@ -516,8 +515,32 @@ static struct attribute *max16065_max_attributes[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static umode_t max16065_basic_is_visible(struct kobject *kobj,
|
||||||
|
struct attribute *a, int n)
|
||||||
|
{
|
||||||
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
|
struct max16065_data *data = dev_get_drvdata(dev);
|
||||||
|
int index = n / 4;
|
||||||
|
|
||||||
|
if (index >= data->num_adc || !data->range[index])
|
||||||
|
return 0;
|
||||||
|
return a->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static umode_t max16065_secondary_is_visible(struct kobject *kobj,
|
||||||
|
struct attribute *a, int index)
|
||||||
|
{
|
||||||
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
|
struct max16065_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (index >= data->num_adc)
|
||||||
|
return 0;
|
||||||
|
return a->mode;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct attribute_group max16065_basic_group = {
|
static const struct attribute_group max16065_basic_group = {
|
||||||
.attrs = max16065_basic_attributes,
|
.attrs = max16065_basic_attributes,
|
||||||
|
.is_visible = max16065_basic_is_visible,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct attribute_group max16065_current_group = {
|
static const struct attribute_group max16065_current_group = {
|
||||||
|
@ -526,38 +549,35 @@ static const struct attribute_group max16065_current_group = {
|
||||||
|
|
||||||
static const struct attribute_group max16065_min_group = {
|
static const struct attribute_group max16065_min_group = {
|
||||||
.attrs = max16065_min_attributes,
|
.attrs = max16065_min_attributes,
|
||||||
|
.is_visible = max16065_secondary_is_visible,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct attribute_group max16065_max_group = {
|
static const struct attribute_group max16065_max_group = {
|
||||||
.attrs = max16065_max_attributes,
|
.attrs = max16065_max_attributes,
|
||||||
|
.is_visible = max16065_secondary_is_visible,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void max16065_cleanup(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max16065_max_group);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max16065_min_group);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max16065_current_group);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max16065_basic_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max16065_probe(struct i2c_client *client,
|
static int max16065_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct max16065_data *data;
|
struct max16065_data *data;
|
||||||
int i, j, val, ret;
|
struct device *dev = &client->dev;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
int i, j, val;
|
||||||
bool have_secondary; /* true if chip has secondary limits */
|
bool have_secondary; /* true if chip has secondary limits */
|
||||||
bool secondary_is_max = false; /* secondary limits reflect max */
|
bool secondary_is_max = false; /* secondary limits reflect max */
|
||||||
|
int groups = 0;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
||||||
| I2C_FUNC_SMBUS_READ_WORD_DATA))
|
| I2C_FUNC_SMBUS_READ_WORD_DATA))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (unlikely(!data))
|
if (unlikely(!data))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
data->num_adc = max16065_num_adc[id->driver_data];
|
data->num_adc = max16065_num_adc[id->driver_data];
|
||||||
|
@ -596,38 +616,16 @@ static int max16065_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* sysfs hooks */
|
||||||
for (i = 0; i < data->num_adc * 4; i++) {
|
data->groups[groups++] = &max16065_basic_group;
|
||||||
/* Do not create sysfs entry if channel is disabled */
|
if (have_secondary)
|
||||||
if (!data->range[i / 4])
|
data->groups[groups++] = secondary_is_max ?
|
||||||
continue;
|
&max16065_max_group : &max16065_min_group;
|
||||||
|
|
||||||
ret = sysfs_create_file(&client->dev.kobj,
|
|
||||||
max16065_basic_attributes[i]);
|
|
||||||
if (unlikely(ret))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_secondary) {
|
|
||||||
struct attribute **attr = secondary_is_max ?
|
|
||||||
max16065_max_attributes : max16065_min_attributes;
|
|
||||||
|
|
||||||
for (i = 0; i < data->num_adc; i++) {
|
|
||||||
if (!data->range[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ret = sysfs_create_file(&client->dev.kobj, attr[i]);
|
|
||||||
if (unlikely(ret))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->have_current) {
|
if (data->have_current) {
|
||||||
val = i2c_smbus_read_byte_data(client, MAX16065_CURR_CONTROL);
|
val = i2c_smbus_read_byte_data(client, MAX16065_CURR_CONTROL);
|
||||||
if (unlikely(val < 0)) {
|
if (unlikely(val < 0))
|
||||||
ret = val;
|
return val;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (val & MAX16065_CURR_ENABLE) {
|
if (val & MAX16065_CURR_ENABLE) {
|
||||||
/*
|
/*
|
||||||
* Current gain is 6, 12, 24, 48 based on values in
|
* Current gain is 6, 12, 24, 48 based on values in
|
||||||
|
@ -636,33 +634,16 @@ static int max16065_probe(struct i2c_client *client,
|
||||||
data->curr_gain = 6 << ((val >> 2) & 0x03);
|
data->curr_gain = 6 << ((val >> 2) & 0x03);
|
||||||
data->range[MAX16065_NUM_ADC]
|
data->range[MAX16065_NUM_ADC]
|
||||||
= max16065_csp_adc_range[(val >> 1) & 0x01];
|
= max16065_csp_adc_range[(val >> 1) & 0x01];
|
||||||
ret = sysfs_create_group(&client->dev.kobj,
|
data->groups[groups++] = &max16065_current_group;
|
||||||
&max16065_current_group);
|
|
||||||
if (unlikely(ret))
|
|
||||||
goto out;
|
|
||||||
} else {
|
} else {
|
||||||
data->have_current = false;
|
data->have_current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
if (unlikely(IS_ERR(data->hwmon_dev))) {
|
data, data->groups);
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
if (unlikely(IS_ERR(hwmon_dev)))
|
||||||
goto out;
|
return PTR_ERR(hwmon_dev);
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
max16065_cleanup(client);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max16065_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct max16065_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
max16065_cleanup(client);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -685,7 +666,6 @@ static struct i2c_driver max16065_driver = {
|
||||||
.name = "max16065",
|
.name = "max16065",
|
||||||
},
|
},
|
||||||
.probe = max16065_probe,
|
.probe = max16065_probe,
|
||||||
.remove = max16065_remove,
|
|
||||||
.id_table = max16065_id,
|
.id_table = max16065_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ static int temp_to_reg(int val)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct max6642_data {
|
struct max6642_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
bool valid; /* zero until following fields are valid */
|
bool valid; /* zero until following fields are valid */
|
||||||
unsigned long last_updated; /* in jiffies */
|
unsigned long last_updated; /* in jiffies */
|
||||||
|
@ -102,10 +102,10 @@ struct max6642_data {
|
||||||
* Real code
|
* Real code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void max6642_init_client(struct i2c_client *client)
|
static void max6642_init_client(struct max6642_data *data,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
u8 config;
|
u8 config;
|
||||||
struct max6642_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the conversions.
|
* Start the conversions.
|
||||||
|
@ -168,14 +168,14 @@ static int max6642_detect(struct i2c_client *client,
|
||||||
|
|
||||||
static struct max6642_data *max6642_update_device(struct device *dev)
|
static struct max6642_data *max6642_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max6642_data *data = dev_get_drvdata(dev);
|
||||||
struct max6642_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
u16 val, tmp;
|
u16 val, tmp;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
||||||
dev_dbg(&client->dev, "Updating max6642 data.\n");
|
dev_dbg(dev, "Updating max6642 data.\n");
|
||||||
val = i2c_smbus_read_byte_data(client,
|
val = i2c_smbus_read_byte_data(client,
|
||||||
MAX6642_REG_R_LOCAL_TEMPL);
|
MAX6642_REG_R_LOCAL_TEMPL);
|
||||||
tmp = (val >> 6) & 3;
|
tmp = (val >> 6) & 3;
|
||||||
|
@ -209,8 +209,8 @@ static struct max6642_data *max6642_update_device(struct device *dev)
|
||||||
static ssize_t show_temp_max10(struct device *dev,
|
static ssize_t show_temp_max10(struct device *dev,
|
||||||
struct device_attribute *dev_attr, char *buf)
|
struct device_attribute *dev_attr, char *buf)
|
||||||
{
|
{
|
||||||
struct max6642_data *data = max6642_update_device(dev);
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
|
||||||
|
struct max6642_data *data = max6642_update_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "%d\n",
|
return sprintf(buf, "%d\n",
|
||||||
temp_from_reg10(data->temp_input[attr->index]));
|
temp_from_reg10(data->temp_input[attr->index]));
|
||||||
|
@ -219,8 +219,8 @@ static ssize_t show_temp_max10(struct device *dev,
|
||||||
static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct max6642_data *data = max6642_update_device(dev);
|
|
||||||
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
|
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
|
||||||
|
struct max6642_data *data = max6642_update_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
|
return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
|
||||||
}
|
}
|
||||||
|
@ -228,11 +228,10 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
|
||||||
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
|
||||||
|
struct max6642_data *data = dev_get_drvdata(dev);
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int err;
|
int err;
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct max6642_data *data = i2c_get_clientdata(client);
|
|
||||||
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
|
|
||||||
|
|
||||||
err = kstrtoul(buf, 10, &val);
|
err = kstrtoul(buf, 10, &val);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -240,7 +239,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
|
data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
|
||||||
i2c_smbus_write_byte_data(client, attr2->index,
|
i2c_smbus_write_byte_data(data->client, attr2->index,
|
||||||
data->temp_high[attr2->nr]);
|
data->temp_high[attr2->nr]);
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
return count;
|
return count;
|
||||||
|
@ -264,7 +263,7 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
|
||||||
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
|
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
|
||||||
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
|
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
|
||||||
|
|
||||||
static struct attribute *max6642_attributes[] = {
|
static struct attribute *max6642_attrs[] = {
|
||||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||||
|
@ -275,54 +274,29 @@ static struct attribute *max6642_attributes[] = {
|
||||||
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
|
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
ATTRIBUTE_GROUPS(max6642);
|
||||||
|
|
||||||
static const struct attribute_group max6642_group = {
|
static int max6642_probe(struct i2c_client *client,
|
||||||
.attrs = max6642_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int max6642_probe(struct i2c_client *new_client,
|
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
struct device *dev = &client->dev;
|
||||||
struct max6642_data *data;
|
struct max6642_data *data;
|
||||||
int err;
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
data = devm_kzalloc(&new_client->dev, sizeof(struct max6642_data),
|
data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(new_client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
/* Initialize the MAX6642 chip */
|
/* Initialize the MAX6642 chip */
|
||||||
max6642_init_client(new_client);
|
max6642_init_client(data, client);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
|
||||||
err = sysfs_create_group(&new_client->dev.kobj, &max6642_group);
|
client->name, data,
|
||||||
if (err)
|
max6642_groups);
|
||||||
return err;
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&new_client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove_files:
|
|
||||||
sysfs_remove_group(&new_client->dev.kobj, &max6642_group);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max6642_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct max6642_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max6642_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -341,7 +315,6 @@ static struct i2c_driver max6642_driver = {
|
||||||
.name = "max6642",
|
.name = "max6642",
|
||||||
},
|
},
|
||||||
.probe = max6642_probe,
|
.probe = max6642_probe,
|
||||||
.remove = max6642_remove,
|
|
||||||
.id_table = max6642_id,
|
.id_table = max6642_id,
|
||||||
.detect = max6642_detect,
|
.detect = max6642_detect,
|
||||||
.address_list = normal_i2c,
|
.address_list = normal_i2c,
|
||||||
|
|
|
@ -660,7 +660,7 @@ static int max6650_init_client(struct i2c_client *client)
|
||||||
/*
|
/*
|
||||||
* If mode is set to "full off", we change it to "open loop" and
|
* If mode is set to "full off", we change it to "open loop" and
|
||||||
* set DAC to 255, which has the same effect. We do this because
|
* set DAC to 255, which has the same effect. We do this because
|
||||||
* there's no "full off" mode defined in hwmon specifcations.
|
* there's no "full off" mode defined in hwmon specifications.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
|
if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct max6697_chip_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct max6697_data {
|
struct max6697_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
|
||||||
enum chips type;
|
enum chips type;
|
||||||
const struct max6697_chip_data *chip;
|
const struct max6697_chip_data *chip;
|
||||||
|
@ -181,8 +181,8 @@ static const struct max6697_chip_data max6697_chip_data[] = {
|
||||||
|
|
||||||
static struct max6697_data *max6697_update_device(struct device *dev)
|
static struct max6697_data *max6697_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max6697_data *data = dev_get_drvdata(dev);
|
||||||
struct max6697_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct max6697_data *ret = data;
|
struct max6697_data *ret = data;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
int i;
|
||||||
|
@ -303,8 +303,7 @@ static ssize_t set_temp(struct device *dev,
|
||||||
{
|
{
|
||||||
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||||
int index = to_sensor_dev_attr_2(devattr)->index;
|
int index = to_sensor_dev_attr_2(devattr)->index;
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max6697_data *data = dev_get_drvdata(dev);
|
||||||
struct max6697_data *data = i2c_get_clientdata(client);
|
|
||||||
long temp;
|
long temp;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -316,7 +315,7 @@ static ssize_t set_temp(struct device *dev,
|
||||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
|
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
|
||||||
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
|
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
|
||||||
data->temp[nr][index] = temp;
|
data->temp[nr][index] = temp;
|
||||||
ret = i2c_smbus_write_byte_data(client,
|
ret = i2c_smbus_write_byte_data(data->client,
|
||||||
index == 2 ? MAX6697_REG_MAX[nr]
|
index == 2 ? MAX6697_REG_MAX[nr]
|
||||||
: MAX6697_REG_CRIT[nr],
|
: MAX6697_REG_CRIT[nr],
|
||||||
temp);
|
temp);
|
||||||
|
@ -405,8 +404,7 @@ static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct max6697_data *data = dev_get_drvdata(dev);
|
||||||
struct max6697_data *data = i2c_get_clientdata(client);
|
|
||||||
const struct max6697_chip_data *chip = data->chip;
|
const struct max6697_chip_data *chip = data->chip;
|
||||||
int channel = index / 6; /* channel number */
|
int channel = index / 6; /* channel number */
|
||||||
int nr = index % 6; /* attribute index within channel */
|
int nr = index % 6; /* attribute index within channel */
|
||||||
|
@ -489,6 +487,7 @@ static struct attribute *max6697_attributes[] = {
|
||||||
static const struct attribute_group max6697_group = {
|
static const struct attribute_group max6697_group = {
|
||||||
.attrs = max6697_attributes, .is_visible = max6697_is_visible,
|
.attrs = max6697_attributes, .is_visible = max6697_is_visible,
|
||||||
};
|
};
|
||||||
|
__ATTRIBUTE_GROUPS(max6697);
|
||||||
|
|
||||||
static void max6697_get_config_of(struct device_node *node,
|
static void max6697_get_config_of(struct device_node *node,
|
||||||
struct max6697_platform_data *pdata)
|
struct max6697_platform_data *pdata)
|
||||||
|
@ -525,9 +524,9 @@ static void max6697_get_config_of(struct device_node *node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max6697_init_chip(struct i2c_client *client)
|
static int max6697_init_chip(struct max6697_data *data,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct max6697_data *data = i2c_get_clientdata(client);
|
|
||||||
struct max6697_platform_data *pdata = dev_get_platdata(&client->dev);
|
struct max6697_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
struct max6697_platform_data p;
|
struct max6697_platform_data p;
|
||||||
const struct max6697_chip_data *chip = data->chip;
|
const struct max6697_chip_data *chip = data->chip;
|
||||||
|
@ -625,6 +624,7 @@ static int max6697_probe(struct i2c_client *client,
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
struct max6697_data *data;
|
struct max6697_data *data;
|
||||||
|
struct device *hwmon_dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
|
@ -636,39 +636,17 @@ static int max6697_probe(struct i2c_client *client,
|
||||||
|
|
||||||
data->type = id->driver_data;
|
data->type = id->driver_data;
|
||||||
data->chip = &max6697_chip_data[data->type];
|
data->chip = &max6697_chip_data[data->type];
|
||||||
|
data->client = client;
|
||||||
i2c_set_clientdata(client, data);
|
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
err = max6697_init_chip(client);
|
err = max6697_init_chip(data, client);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = sysfs_create_group(&client->dev.kobj, &max6697_group);
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
if (err)
|
data,
|
||||||
return err;
|
max6697_groups);
|
||||||
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max6697_group);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int max6697_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct max6697_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &max6697_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id max6697_id[] = {
|
static const struct i2c_device_id max6697_id[] = {
|
||||||
|
@ -692,7 +670,6 @@ static struct i2c_driver max6697_driver = {
|
||||||
.name = "max6697",
|
.name = "max6697",
|
||||||
},
|
},
|
||||||
.probe = max6697_probe,
|
.probe = max6697_probe,
|
||||||
.remove = max6697_remove,
|
|
||||||
.id_table = max6697_id,
|
.id_table = max6697_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
struct mc13783_adc_priv {
|
struct mc13783_adc_priv {
|
||||||
struct mc13xxx *mc13xxx;
|
struct mc13xxx *mc13xxx;
|
||||||
struct device *hwmon_dev;
|
struct device *hwmon_dev;
|
||||||
char name[10];
|
char name[PLATFORM_NAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
|
static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
|
||||||
|
|
|
@ -724,11 +724,8 @@ struct nct6775_data {
|
||||||
enum kinds kind;
|
enum kinds kind;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
struct device *hwmon_dev;
|
int num_attr_groups;
|
||||||
struct attribute_group *group_in;
|
const struct attribute_group *groups[6];
|
||||||
struct attribute_group *group_fan;
|
|
||||||
struct attribute_group *group_temp;
|
|
||||||
struct attribute_group *group_pwm;
|
|
||||||
|
|
||||||
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
|
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
|
||||||
* 3=temp_crit, 4=temp_lcrit
|
* 3=temp_crit, 4=temp_lcrit
|
||||||
|
@ -942,7 +939,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
|
||||||
struct sensor_device_attribute_2 *a2;
|
struct sensor_device_attribute_2 *a2;
|
||||||
struct attribute **attrs;
|
struct attribute **attrs;
|
||||||
struct sensor_device_template **t;
|
struct sensor_device_template **t;
|
||||||
int err, i, j, count;
|
int i, count;
|
||||||
|
|
||||||
if (repeat <= 0)
|
if (repeat <= 0)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
@ -973,7 +970,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
|
||||||
|
|
||||||
for (i = 0; i < repeat; i++) {
|
for (i = 0; i < repeat; i++) {
|
||||||
t = tg->templates;
|
t = tg->templates;
|
||||||
for (j = 0; *t != NULL; j++) {
|
while (*t != NULL) {
|
||||||
snprintf(su->name, sizeof(su->name),
|
snprintf(su->name, sizeof(su->name),
|
||||||
(*t)->dev_attr.attr.name, tg->base + i);
|
(*t)->dev_attr.attr.name, tg->base + i);
|
||||||
if ((*t)->s2) {
|
if ((*t)->s2) {
|
||||||
|
@ -1002,10 +999,6 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sysfs_create_group(&dev->kobj, group);
|
|
||||||
if (err)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1457,7 +1450,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
|
||||||
= nct6775_read_temp(data,
|
= nct6775_read_temp(data,
|
||||||
data->reg_temp[j][i]);
|
data->reg_temp[j][i]);
|
||||||
}
|
}
|
||||||
if (!(data->have_temp_fixed & (1 << i)))
|
if (i >= NUM_TEMP_FIXED ||
|
||||||
|
!(data->have_temp_fixed & (1 << i)))
|
||||||
continue;
|
continue;
|
||||||
data->temp_offset[i]
|
data->temp_offset[i]
|
||||||
= nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
|
= nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
|
||||||
|
@ -1545,7 +1539,7 @@ static int find_temp_source(struct nct6775_data *data, int index, int count)
|
||||||
if (src == source)
|
if (src == source)
|
||||||
return nr;
|
return nr;
|
||||||
}
|
}
|
||||||
return -1;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
|
@ -1644,7 +1638,7 @@ store_temp_beep(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
|
nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
|
||||||
if (nr < 0)
|
if (nr < 0)
|
||||||
return -ENODEV;
|
return nr;
|
||||||
|
|
||||||
bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
|
bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
|
||||||
regindex = bit >> 3;
|
regindex = bit >> 3;
|
||||||
|
@ -2725,16 +2719,6 @@ store_fan_time(struct device *dev, struct device_attribute *attr,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct nct6775_data *data = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", data->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
|
show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -3061,16 +3045,16 @@ static umode_t nct6775_other_is_visible(struct kobject *kobj,
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
struct nct6775_data *data = dev_get_drvdata(dev);
|
struct nct6775_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (index == 1 && !data->have_vid)
|
if (index == 0 && !data->have_vid)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (index == 2 || index == 3) {
|
if (index == 1 || index == 2) {
|
||||||
if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
|
if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 4 || index == 5) {
|
if (index == 3 || index == 4) {
|
||||||
if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
|
if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3083,13 +3067,12 @@ static umode_t nct6775_other_is_visible(struct kobject *kobj,
|
||||||
* Any change in order or content must be matched.
|
* Any change in order or content must be matched.
|
||||||
*/
|
*/
|
||||||
static struct attribute *nct6775_attributes_other[] = {
|
static struct attribute *nct6775_attributes_other[] = {
|
||||||
&dev_attr_name.attr,
|
&dev_attr_cpu0_vid.attr, /* 0 */
|
||||||
&dev_attr_cpu0_vid.attr, /* 1 */
|
&sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
|
||||||
&sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
|
&sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
|
||||||
&sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
|
&sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
|
||||||
&sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
|
&sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
|
||||||
&sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
|
&sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
|
||||||
&sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
|
|
||||||
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -3099,27 +3082,6 @@ static const struct attribute_group nct6775_group_other = {
|
||||||
.is_visible = nct6775_other_is_visible,
|
.is_visible = nct6775_other_is_visible,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Driver and device management
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void nct6775_device_remove_files(struct device *dev)
|
|
||||||
{
|
|
||||||
struct nct6775_data *data = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
if (data->group_pwm)
|
|
||||||
sysfs_remove_group(&dev->kobj, data->group_pwm);
|
|
||||||
if (data->group_in)
|
|
||||||
sysfs_remove_group(&dev->kobj, data->group_in);
|
|
||||||
if (data->group_fan)
|
|
||||||
sysfs_remove_group(&dev->kobj, data->group_fan);
|
|
||||||
if (data->group_temp)
|
|
||||||
sysfs_remove_group(&dev->kobj, data->group_temp);
|
|
||||||
|
|
||||||
sysfs_remove_group(&dev->kobj, &nct6775_group_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the monitoring functions started */
|
|
||||||
static inline void nct6775_init_device(struct nct6775_data *data)
|
static inline void nct6775_init_device(struct nct6775_data *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -3296,6 +3258,7 @@ static int nct6775_probe(struct platform_device *pdev)
|
||||||
int num_reg_temp;
|
int num_reg_temp;
|
||||||
u8 cr2a;
|
u8 cr2a;
|
||||||
struct attribute_group *group;
|
struct attribute_group *group;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
|
if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
|
||||||
|
@ -3870,61 +3833,36 @@ static int nct6775_probe(struct platform_device *pdev)
|
||||||
/* Register sysfs hooks */
|
/* Register sysfs hooks */
|
||||||
group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
|
group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
|
||||||
data->pwm_num);
|
data->pwm_num);
|
||||||
if (IS_ERR(group)) {
|
if (IS_ERR(group))
|
||||||
err = PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
goto exit_remove;
|
|
||||||
}
|
data->groups[data->num_attr_groups++] = group;
|
||||||
data->group_pwm = group;
|
|
||||||
|
|
||||||
group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
|
group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
|
||||||
fls(data->have_in));
|
fls(data->have_in));
|
||||||
if (IS_ERR(group)) {
|
if (IS_ERR(group))
|
||||||
err = PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
goto exit_remove;
|
|
||||||
}
|
data->groups[data->num_attr_groups++] = group;
|
||||||
data->group_in = group;
|
|
||||||
|
|
||||||
group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
|
group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
|
||||||
fls(data->has_fan));
|
fls(data->has_fan));
|
||||||
if (IS_ERR(group)) {
|
if (IS_ERR(group))
|
||||||
err = PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
goto exit_remove;
|
|
||||||
}
|
data->groups[data->num_attr_groups++] = group;
|
||||||
data->group_fan = group;
|
|
||||||
|
|
||||||
group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
|
group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
|
||||||
fls(data->have_temp));
|
fls(data->have_temp));
|
||||||
if (IS_ERR(group)) {
|
if (IS_ERR(group))
|
||||||
err = PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
data->group_temp = group;
|
|
||||||
|
|
||||||
err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
|
data->groups[data->num_attr_groups++] = group;
|
||||||
if (err)
|
data->groups[data->num_attr_groups++] = &nct6775_group_other;
|
||||||
goto exit_remove;
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
data, data->groups);
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
nct6775_device_remove_files(dev);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nct6775_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct nct6775_data *data = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
nct6775_device_remove_files(&pdev->dev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
@ -4013,7 +3951,6 @@ static struct platform_driver nct6775_driver = {
|
||||||
.pm = NCT6775_DEV_PM_OPS,
|
.pm = NCT6775_DEV_PM_OPS,
|
||||||
},
|
},
|
||||||
.probe = nct6775_probe,
|
.probe = nct6775_probe,
|
||||||
.remove = nct6775_remove,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const nct6775_sio_names[] __initconst = {
|
static const char * const nct6775_sio_names[] __initconst = {
|
||||||
|
@ -4101,7 +4038,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
|
||||||
/*
|
/*
|
||||||
* when Super-I/O functions move to a separate file, the Super-I/O
|
* when Super-I/O functions move to a separate file, the Super-I/O
|
||||||
* bus will manage the lifetime of the device and this module will only keep
|
* bus will manage the lifetime of the device and this module will only keep
|
||||||
* track of the nct6775 driver. But since we platform_device_alloc(), we
|
* track of the nct6775 driver. But since we use platform_device_alloc(), we
|
||||||
* must keep track of the device
|
* must keep track of the device
|
||||||
*/
|
*/
|
||||||
static struct platform_device *pdev[2];
|
static struct platform_device *pdev[2];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
|
* Hardware monitoring driver for LM25056 / LM25063 / LM25066 / LM5064 / LM5066
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 Ericsson AB.
|
* Copyright (c) 2011 Ericsson AB.
|
||||||
* Copyright (c) 2013 Guenter Roeck
|
* Copyright (c) 2013 Guenter Roeck
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include "pmbus.h"
|
#include "pmbus.h"
|
||||||
|
|
||||||
enum chips { lm25056, lm25066, lm5064, lm5066 };
|
enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
|
||||||
|
|
||||||
#define LM25066_READ_VAUX 0xd0
|
#define LM25066_READ_VAUX 0xd0
|
||||||
#define LM25066_MFR_READ_IIN 0xd1
|
#define LM25066_MFR_READ_IIN 0xd1
|
||||||
|
@ -52,6 +52,11 @@ enum chips { lm25056, lm25066, lm5064, lm5066 };
|
||||||
#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
|
#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
|
||||||
#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
|
#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
|
||||||
|
|
||||||
|
/* LM25063 only */
|
||||||
|
|
||||||
|
#define LM25063_READ_VOUT_MAX 0xe5
|
||||||
|
#define LM25063_READ_VOUT_MIN 0xe6
|
||||||
|
|
||||||
struct __coeff {
|
struct __coeff {
|
||||||
short m, b, R;
|
short m, b, R;
|
||||||
};
|
};
|
||||||
|
@ -59,7 +64,7 @@ struct __coeff {
|
||||||
#define PSC_CURRENT_IN_L (PSC_NUM_CLASSES)
|
#define PSC_CURRENT_IN_L (PSC_NUM_CLASSES)
|
||||||
#define PSC_POWER_L (PSC_NUM_CLASSES + 1)
|
#define PSC_POWER_L (PSC_NUM_CLASSES + 1)
|
||||||
|
|
||||||
static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
|
static struct __coeff lm25066_coeff[5][PSC_NUM_CLASSES + 2] = {
|
||||||
[lm25056] = {
|
[lm25056] = {
|
||||||
[PSC_VOLTAGE_IN] = {
|
[PSC_VOLTAGE_IN] = {
|
||||||
.m = 16296,
|
.m = 16296,
|
||||||
|
@ -116,6 +121,36 @@ static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
|
||||||
.m = 16,
|
.m = 16,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[lm25063] = {
|
||||||
|
[PSC_VOLTAGE_IN] = {
|
||||||
|
.m = 16000,
|
||||||
|
.R = -2,
|
||||||
|
},
|
||||||
|
[PSC_VOLTAGE_OUT] = {
|
||||||
|
.m = 16000,
|
||||||
|
.R = -2,
|
||||||
|
},
|
||||||
|
[PSC_CURRENT_IN] = {
|
||||||
|
.m = 10000,
|
||||||
|
.R = -2,
|
||||||
|
},
|
||||||
|
[PSC_CURRENT_IN_L] = {
|
||||||
|
.m = 10000,
|
||||||
|
.R = -2,
|
||||||
|
},
|
||||||
|
[PSC_POWER] = {
|
||||||
|
.m = 5000,
|
||||||
|
.R = -3,
|
||||||
|
},
|
||||||
|
[PSC_POWER_L] = {
|
||||||
|
.m = 5000,
|
||||||
|
.R = -3,
|
||||||
|
},
|
||||||
|
[PSC_TEMPERATURE] = {
|
||||||
|
.m = 15596,
|
||||||
|
.R = -3,
|
||||||
|
},
|
||||||
|
},
|
||||||
[lm5064] = {
|
[lm5064] = {
|
||||||
[PSC_VOLTAGE_IN] = {
|
[PSC_VOLTAGE_IN] = {
|
||||||
.m = 4611,
|
.m = 4611,
|
||||||
|
@ -178,6 +213,7 @@ static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
|
||||||
|
|
||||||
struct lm25066_data {
|
struct lm25066_data {
|
||||||
int id;
|
int id;
|
||||||
|
u16 rlimit; /* Maximum register value */
|
||||||
struct pmbus_driver_info info;
|
struct pmbus_driver_info info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,6 +236,10 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
|
||||||
/* VIN: 6.14 mV VAUX: 293 uV LSB */
|
/* VIN: 6.14 mV VAUX: 293 uV LSB */
|
||||||
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
|
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
|
||||||
break;
|
break;
|
||||||
|
case lm25063:
|
||||||
|
/* VIN: 6.25 mV VAUX: 200.0 uV LSB */
|
||||||
|
ret = DIV_ROUND_CLOSEST(ret * 20, 625);
|
||||||
|
break;
|
||||||
case lm25066:
|
case lm25066:
|
||||||
/* VIN: 4.54 mV VAUX: 283.2 uV LSB */
|
/* VIN: 4.54 mV VAUX: 283.2 uV LSB */
|
||||||
ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
|
ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
|
||||||
|
@ -253,6 +293,24 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lm25063_read_word_data(struct i2c_client *client, int page, int reg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case PMBUS_VIRT_READ_VOUT_MAX:
|
||||||
|
ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MAX);
|
||||||
|
break;
|
||||||
|
case PMBUS_VIRT_READ_VOUT_MIN:
|
||||||
|
ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MIN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = lm25066_read_word_data(client, page, reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
|
static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -308,27 +366,34 @@ static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||||
static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
|
static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
|
||||||
u16 word)
|
u16 word)
|
||||||
{
|
{
|
||||||
|
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||||
|
const struct lm25066_data *data = to_lm25066_data(info);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
|
case PMBUS_POUT_OP_FAULT_LIMIT:
|
||||||
|
case PMBUS_POUT_OP_WARN_LIMIT:
|
||||||
case PMBUS_VOUT_UV_WARN_LIMIT:
|
case PMBUS_VOUT_UV_WARN_LIMIT:
|
||||||
case PMBUS_OT_FAULT_LIMIT:
|
case PMBUS_OT_FAULT_LIMIT:
|
||||||
case PMBUS_OT_WARN_LIMIT:
|
case PMBUS_OT_WARN_LIMIT:
|
||||||
|
case PMBUS_IIN_OC_FAULT_LIMIT:
|
||||||
case PMBUS_VIN_UV_WARN_LIMIT:
|
case PMBUS_VIN_UV_WARN_LIMIT:
|
||||||
|
case PMBUS_VIN_UV_FAULT_LIMIT:
|
||||||
|
case PMBUS_VIN_OV_FAULT_LIMIT:
|
||||||
case PMBUS_VIN_OV_WARN_LIMIT:
|
case PMBUS_VIN_OV_WARN_LIMIT:
|
||||||
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
|
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
|
||||||
ret = pmbus_write_word_data(client, 0, reg, word);
|
ret = pmbus_write_word_data(client, 0, reg, word);
|
||||||
pmbus_clear_cache(client);
|
pmbus_clear_cache(client);
|
||||||
break;
|
break;
|
||||||
case PMBUS_IIN_OC_WARN_LIMIT:
|
case PMBUS_IIN_OC_WARN_LIMIT:
|
||||||
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
|
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
|
||||||
ret = pmbus_write_word_data(client, 0,
|
ret = pmbus_write_word_data(client, 0,
|
||||||
LM25066_MFR_IIN_OC_WARN_LIMIT,
|
LM25066_MFR_IIN_OC_WARN_LIMIT,
|
||||||
word);
|
word);
|
||||||
pmbus_clear_cache(client);
|
pmbus_clear_cache(client);
|
||||||
break;
|
break;
|
||||||
case PMBUS_PIN_OP_WARN_LIMIT:
|
case PMBUS_PIN_OP_WARN_LIMIT:
|
||||||
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
|
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
|
||||||
ret = pmbus_write_word_data(client, 0,
|
ret = pmbus_write_word_data(client, 0,
|
||||||
LM25066_MFR_PIN_OP_WARN_LIMIT,
|
LM25066_MFR_PIN_OP_WARN_LIMIT,
|
||||||
word);
|
word);
|
||||||
|
@ -337,7 +402,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
|
||||||
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
|
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
|
||||||
/* Adjust from VIN coefficients (for LM25056) */
|
/* Adjust from VIN coefficients (for LM25056) */
|
||||||
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
|
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
|
||||||
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
|
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
|
||||||
ret = pmbus_write_word_data(client, 0,
|
ret = pmbus_write_word_data(client, 0,
|
||||||
LM25056_VAUX_UV_WARN_LIMIT, word);
|
LM25056_VAUX_UV_WARN_LIMIT, word);
|
||||||
pmbus_clear_cache(client);
|
pmbus_clear_cache(client);
|
||||||
|
@ -345,7 +410,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
|
||||||
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
|
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
|
||||||
/* Adjust from VIN coefficients (for LM25056) */
|
/* Adjust from VIN coefficients (for LM25056) */
|
||||||
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
|
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
|
||||||
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
|
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
|
||||||
ret = pmbus_write_word_data(client, 0,
|
ret = pmbus_write_word_data(client, 0,
|
||||||
LM25056_VAUX_OV_WARN_LIMIT, word);
|
LM25056_VAUX_OV_WARN_LIMIT, word);
|
||||||
pmbus_clear_cache(client);
|
pmbus_clear_cache(client);
|
||||||
|
@ -399,9 +464,16 @@ static int lm25066_probe(struct i2c_client *client,
|
||||||
info->func[0] |= PMBUS_HAVE_STATUS_VMON;
|
info->func[0] |= PMBUS_HAVE_STATUS_VMON;
|
||||||
info->read_word_data = lm25056_read_word_data;
|
info->read_word_data = lm25056_read_word_data;
|
||||||
info->read_byte_data = lm25056_read_byte_data;
|
info->read_byte_data = lm25056_read_byte_data;
|
||||||
|
data->rlimit = 0x0fff;
|
||||||
|
} else if (data->id == lm25063) {
|
||||||
|
info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
||||||
|
| PMBUS_HAVE_POUT;
|
||||||
|
info->read_word_data = lm25063_read_word_data;
|
||||||
|
data->rlimit = 0xffff;
|
||||||
} else {
|
} else {
|
||||||
info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||||
info->read_word_data = lm25066_read_word_data;
|
info->read_word_data = lm25066_read_word_data;
|
||||||
|
data->rlimit = 0x0fff;
|
||||||
}
|
}
|
||||||
info->write_word_data = lm25066_write_word_data;
|
info->write_word_data = lm25066_write_word_data;
|
||||||
|
|
||||||
|
@ -432,6 +504,7 @@ static int lm25066_probe(struct i2c_client *client,
|
||||||
|
|
||||||
static const struct i2c_device_id lm25066_id[] = {
|
static const struct i2c_device_id lm25066_id[] = {
|
||||||
{"lm25056", lm25056},
|
{"lm25056", lm25056},
|
||||||
|
{"lm25063", lm25063},
|
||||||
{"lm25066", lm25066},
|
{"lm25066", lm25066},
|
||||||
{"lm5064", lm5064},
|
{"lm5064", lm5064},
|
||||||
{"lm5066", lm5066},
|
{"lm5066", lm5066},
|
||||||
|
@ -453,5 +526,5 @@ static struct i2c_driver lm25066_driver = {
|
||||||
module_i2c_driver(lm25066_driver);
|
module_i2c_driver(lm25066_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Guenter Roeck");
|
MODULE_AUTHOR("Guenter Roeck");
|
||||||
MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
|
MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Hardware monitoring driver for LTC2974, LTC2978, LTC3880, and LTC3883
|
* Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880,
|
||||||
|
* and LTC3883
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 Ericsson AB.
|
* Copyright (c) 2011 Ericsson AB.
|
||||||
* Copyright (c) 2013 Guenter Roeck
|
* Copyright (c) 2013 Guenter Roeck
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include "pmbus.h"
|
#include "pmbus.h"
|
||||||
|
|
||||||
enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
|
enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883 };
|
||||||
|
|
||||||
/* Common for all chips */
|
/* Common for all chips */
|
||||||
#define LTC2978_MFR_VOUT_PEAK 0xdd
|
#define LTC2978_MFR_VOUT_PEAK 0xdd
|
||||||
|
@ -35,7 +36,7 @@ enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
|
||||||
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
|
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
|
||||||
#define LTC2978_MFR_SPECIAL_ID 0xe7
|
#define LTC2978_MFR_SPECIAL_ID 0xe7
|
||||||
|
|
||||||
/* LTC2974 and LTC2978 */
|
/* LTC2974, LCT2977, and LTC2978 */
|
||||||
#define LTC2978_MFR_VOUT_MIN 0xfb
|
#define LTC2978_MFR_VOUT_MIN 0xfb
|
||||||
#define LTC2978_MFR_VIN_MIN 0xfc
|
#define LTC2978_MFR_VIN_MIN 0xfc
|
||||||
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
|
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
|
||||||
|
@ -53,8 +54,10 @@ enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
|
||||||
#define LTC3883_MFR_IIN_PEAK 0xe1
|
#define LTC3883_MFR_IIN_PEAK 0xe1
|
||||||
|
|
||||||
#define LTC2974_ID 0x0212
|
#define LTC2974_ID 0x0212
|
||||||
|
#define LTC2977_ID 0x0130
|
||||||
#define LTC2978_ID_REV1 0x0121
|
#define LTC2978_ID_REV1 0x0121
|
||||||
#define LTC2978_ID_REV2 0x0122
|
#define LTC2978_ID_REV2 0x0122
|
||||||
|
#define LTC2978A_ID 0x0124
|
||||||
#define LTC3880_ID 0x4000
|
#define LTC3880_ID 0x4000
|
||||||
#define LTC3880_ID_MASK 0xff00
|
#define LTC3880_ID_MASK 0xff00
|
||||||
#define LTC3883_ID 0x4300
|
#define LTC3883_ID 0x4300
|
||||||
|
@ -363,6 +366,7 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
|
||||||
|
|
||||||
static const struct i2c_device_id ltc2978_id[] = {
|
static const struct i2c_device_id ltc2978_id[] = {
|
||||||
{"ltc2974", ltc2974},
|
{"ltc2974", ltc2974},
|
||||||
|
{"ltc2977", ltc2977},
|
||||||
{"ltc2978", ltc2978},
|
{"ltc2978", ltc2978},
|
||||||
{"ltc3880", ltc3880},
|
{"ltc3880", ltc3880},
|
||||||
{"ltc3883", ltc3883},
|
{"ltc3883", ltc3883},
|
||||||
|
@ -392,7 +396,10 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||||
|
|
||||||
if (chip_id == LTC2974_ID) {
|
if (chip_id == LTC2974_ID) {
|
||||||
data->id = ltc2974;
|
data->id = ltc2974;
|
||||||
} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
|
} else if (chip_id == LTC2977_ID) {
|
||||||
|
data->id = ltc2977;
|
||||||
|
} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 ||
|
||||||
|
chip_id == LTC2978A_ID) {
|
||||||
data->id = ltc2978;
|
data->id = ltc2978;
|
||||||
} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
|
} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
|
||||||
data->id = ltc3880;
|
data->id = ltc3880;
|
||||||
|
@ -438,6 +445,7 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
|
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ltc2977:
|
||||||
case ltc2978:
|
case ltc2978:
|
||||||
info->read_word_data = ltc2978_read_word_data;
|
info->read_word_data = ltc2978_read_word_data;
|
||||||
info->pages = LTC2978_NUM_PAGES;
|
info->pages = LTC2978_NUM_PAGES;
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct pmbus_data {
|
||||||
int max_attributes;
|
int max_attributes;
|
||||||
int num_attributes;
|
int num_attributes;
|
||||||
struct attribute_group group;
|
struct attribute_group group;
|
||||||
|
const struct attribute_group *groups[2];
|
||||||
|
|
||||||
struct pmbus_sensor *sensors;
|
struct pmbus_sensor *sensors;
|
||||||
|
|
||||||
|
@ -156,7 +157,7 @@ EXPORT_SYMBOL_GPL(pmbus_write_byte);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
|
* _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
|
||||||
* a device specific mapping funcion exists and calls it if necessary.
|
* a device specific mapping function exists and calls it if necessary.
|
||||||
*/
|
*/
|
||||||
static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value)
|
static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +349,7 @@ static struct _pmbus_status {
|
||||||
|
|
||||||
static struct pmbus_data *pmbus_update_device(struct device *dev)
|
static struct pmbus_data *pmbus_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev->parent);
|
||||||
struct pmbus_data *data = i2c_get_clientdata(client);
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
const struct pmbus_driver_info *info = data->info;
|
const struct pmbus_driver_info *info = data->info;
|
||||||
struct pmbus_sensor *sensor;
|
struct pmbus_sensor *sensor;
|
||||||
|
@ -686,7 +687,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
|
||||||
if (!s1 && !s2) {
|
if (!s1 && !s2) {
|
||||||
ret = !!regval;
|
ret = !!regval;
|
||||||
} else if (!s1 || !s2) {
|
} else if (!s1 || !s2) {
|
||||||
BUG();
|
WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
long v1, v2;
|
long v1, v2;
|
||||||
|
@ -733,7 +734,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
|
||||||
struct device_attribute *devattr,
|
struct device_attribute *devattr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev->parent);
|
||||||
struct pmbus_data *data = i2c_get_clientdata(client);
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
|
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
|
||||||
ssize_t rv = count;
|
ssize_t rv = count;
|
||||||
|
@ -1768,22 +1769,16 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
|
||||||
goto out_kfree;
|
goto out_kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
data->groups[0] = &data->group;
|
||||||
ret = sysfs_create_group(&dev->kobj, &data->group);
|
data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
|
||||||
if (ret) {
|
data, data->groups);
|
||||||
dev_err(dev, "Failed to create sysfs entries\n");
|
|
||||||
goto out_kfree;
|
|
||||||
}
|
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
if (IS_ERR(data->hwmon_dev)) {
|
||||||
ret = PTR_ERR(data->hwmon_dev);
|
ret = PTR_ERR(data->hwmon_dev);
|
||||||
dev_err(dev, "Failed to register hwmon device\n");
|
dev_err(dev, "Failed to register hwmon device\n");
|
||||||
goto out_hwmon_device_register;
|
goto out_kfree;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_hwmon_device_register:
|
|
||||||
sysfs_remove_group(&dev->kobj, &data->group);
|
|
||||||
out_kfree:
|
out_kfree:
|
||||||
kfree(data->group.attrs);
|
kfree(data->group.attrs);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1794,7 +1789,6 @@ int pmbus_do_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct pmbus_data *data = i2c_get_clientdata(client);
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
sysfs_remove_group(&client->dev.kobj, &data->group);
|
|
||||||
kfree(data->group.attrs);
|
kfree(data->group.attrs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,8 @@ MODULE_DEVICE_TABLE(i2c, tmp401_id);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tmp401_data {
|
struct tmp401_data {
|
||||||
struct device *hwmon_dev;
|
struct i2c_client *client;
|
||||||
|
const struct attribute_group *groups[3];
|
||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
char valid; /* zero until following fields are valid */
|
char valid; /* zero until following fields are valid */
|
||||||
unsigned long last_updated; /* in jiffies */
|
unsigned long last_updated; /* in jiffies */
|
||||||
|
@ -231,8 +232,8 @@ static int tmp401_update_device_reg16(struct i2c_client *client,
|
||||||
|
|
||||||
static struct tmp401_data *tmp401_update_device(struct device *dev)
|
static struct tmp401_data *tmp401_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct tmp401_data *data = dev_get_drvdata(dev);
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
struct tmp401_data *ret = data;
|
struct tmp401_data *ret = data;
|
||||||
int i, val;
|
int i, val;
|
||||||
unsigned long next_update;
|
unsigned long next_update;
|
||||||
|
@ -350,15 +351,12 @@ static ssize_t store_temp(struct device *dev, struct device_attribute *devattr,
|
||||||
{
|
{
|
||||||
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||||
int index = to_sensor_dev_attr_2(devattr)->index;
|
int index = to_sensor_dev_attr_2(devattr)->index;
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct tmp401_data *data = dev_get_drvdata(dev);
|
||||||
struct tmp401_data *data = tmp401_update_device(dev);
|
struct i2c_client *client = data->client;
|
||||||
long val;
|
long val;
|
||||||
u16 reg;
|
u16 reg;
|
||||||
u8 regaddr;
|
u8 regaddr;
|
||||||
|
|
||||||
if (IS_ERR(data))
|
|
||||||
return PTR_ERR(data);
|
|
||||||
|
|
||||||
if (kstrtol(buf, 10, &val))
|
if (kstrtol(buf, 10, &val))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -405,7 +403,7 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
|
||||||
val = clamp_val(val, temp - 255000, temp);
|
val = clamp_val(val, temp - 255000, temp);
|
||||||
reg = ((temp - val) + 500) / 1000;
|
reg = ((temp - val) + 500) / 1000;
|
||||||
|
|
||||||
i2c_smbus_write_byte_data(to_i2c_client(dev), TMP401_TEMP_CRIT_HYST,
|
i2c_smbus_write_byte_data(data->client, TMP401_TEMP_CRIT_HYST,
|
||||||
reg);
|
reg);
|
||||||
|
|
||||||
data->temp_crit_hyst = reg;
|
data->temp_crit_hyst = reg;
|
||||||
|
@ -423,8 +421,8 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
|
||||||
static ssize_t reset_temp_history(struct device *dev,
|
static ssize_t reset_temp_history(struct device *dev,
|
||||||
struct device_attribute *devattr, const char *buf, size_t count)
|
struct device_attribute *devattr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct tmp401_data *data = dev_get_drvdata(dev);
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
long val;
|
long val;
|
||||||
|
|
||||||
if (kstrtol(buf, 10, &val))
|
if (kstrtol(buf, 10, &val))
|
||||||
|
@ -447,8 +445,7 @@ static ssize_t reset_temp_history(struct device *dev,
|
||||||
static ssize_t show_update_interval(struct device *dev,
|
static ssize_t show_update_interval(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct tmp401_data *data = dev_get_drvdata(dev);
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
return sprintf(buf, "%u\n", data->update_interval);
|
return sprintf(buf, "%u\n", data->update_interval);
|
||||||
}
|
}
|
||||||
|
@ -457,8 +454,8 @@ static ssize_t set_update_interval(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct tmp401_data *data = dev_get_drvdata(dev);
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
struct i2c_client *client = data->client;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int err, rate;
|
int err, rate;
|
||||||
|
|
||||||
|
@ -616,10 +613,10 @@ static const struct attribute_group tmp432_group = {
|
||||||
* Begin non sysfs callback code (aka Real code)
|
* Begin non sysfs callback code (aka Real code)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void tmp401_init_client(struct i2c_client *client)
|
static void tmp401_init_client(struct tmp401_data *data,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
int config, config_orig;
|
int config, config_orig;
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
/* Set the conversion rate to 2 Hz */
|
/* Set the conversion rate to 2 Hz */
|
||||||
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
|
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
|
||||||
|
@ -705,77 +702,45 @@ static int tmp401_detect(struct i2c_client *client,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tmp401_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct device *dev = &client->dev;
|
|
||||||
struct tmp401_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
if (data->hwmon_dev)
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
|
|
||||||
sysfs_remove_group(&dev->kobj, &tmp401_group);
|
|
||||||
|
|
||||||
if (data->kind == tmp411)
|
|
||||||
sysfs_remove_group(&dev->kobj, &tmp411_group);
|
|
||||||
|
|
||||||
if (data->kind == tmp432)
|
|
||||||
sysfs_remove_group(&dev->kobj, &tmp432_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tmp401_probe(struct i2c_client *client,
|
static int tmp401_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct device *dev = &client->dev;
|
|
||||||
int err;
|
|
||||||
struct tmp401_data *data;
|
|
||||||
const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
|
const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
|
||||||
|
struct device *dev = &client->dev;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct tmp401_data *data;
|
||||||
|
int groups = 0;
|
||||||
|
|
||||||
data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
|
data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
data->client = client;
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
data->kind = id->driver_data;
|
data->kind = id->driver_data;
|
||||||
|
|
||||||
/* Initialize the TMP401 chip */
|
/* Initialize the TMP401 chip */
|
||||||
tmp401_init_client(client);
|
tmp401_init_client(data, client);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* Register sysfs hooks */
|
||||||
err = sysfs_create_group(&dev->kobj, &tmp401_group);
|
data->groups[groups++] = &tmp401_group;
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* Register additional tmp411 sysfs hooks */
|
/* Register additional tmp411 sysfs hooks */
|
||||||
if (data->kind == tmp411) {
|
if (data->kind == tmp411)
|
||||||
err = sysfs_create_group(&dev->kobj, &tmp411_group);
|
data->groups[groups++] = &tmp411_group;
|
||||||
if (err)
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register additional tmp432 sysfs hooks */
|
/* Register additional tmp432 sysfs hooks */
|
||||||
if (data->kind == tmp432) {
|
if (data->kind == tmp432)
|
||||||
err = sysfs_create_group(&dev->kobj, &tmp432_group);
|
data->groups[groups++] = &tmp432_group;
|
||||||
if (err)
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(dev);
|
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
data, data->groups);
|
||||||
err = PTR_ERR(data->hwmon_dev);
|
if (IS_ERR(hwmon_dev))
|
||||||
data->hwmon_dev = NULL;
|
return PTR_ERR(hwmon_dev);
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(dev, "Detected TI %s chip\n", names[data->kind]);
|
dev_info(dev, "Detected TI %s chip\n", names[data->kind]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
tmp401_remove(client);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct i2c_driver tmp401_driver = {
|
static struct i2c_driver tmp401_driver = {
|
||||||
|
@ -784,7 +749,6 @@ static struct i2c_driver tmp401_driver = {
|
||||||
.name = "tmp401",
|
.name = "tmp401",
|
||||||
},
|
},
|
||||||
.probe = tmp401_probe,
|
.probe = tmp401_probe,
|
||||||
.remove = tmp401_remove,
|
|
||||||
.id_table = tmp401_id,
|
.id_table = tmp401_id,
|
||||||
.detect = tmp401_detect,
|
.detect = tmp401_detect,
|
||||||
.address_list = normal_i2c,
|
.address_list = normal_i2c,
|
||||||
|
|
|
@ -1043,7 +1043,7 @@ static struct sensor_device_attribute sda_temp_alarm[] = {
|
||||||
SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
|
SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* get reatime status of all sensors items: voltage, temp, fan */
|
/* get realtime status of all sensors items: voltage, temp, fan */
|
||||||
static ssize_t show_alarms_reg(struct device *dev,
|
static ssize_t show_alarms_reg(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -579,7 +579,7 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get reatime status of all sensors items: voltage, temp, fan */
|
/* get realtime status of all sensors items: voltage, temp, fan */
|
||||||
static ssize_t
|
static ssize_t
|
||||||
show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -808,7 +808,7 @@ show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
if (nr == TEMP_FAN_MAP) {
|
if (nr == TEMP_FAN_MAP) {
|
||||||
val = data->temp_fan_map[index];
|
val = data->temp_fan_map[index];
|
||||||
} else if (nr == TEMP_PWM_ENABLE) {
|
} else if (nr == TEMP_PWM_ENABLE) {
|
||||||
/* +2 to transfrom into 2 and 3 to conform with sysfs intf */
|
/* +2 to transform into 2 and 3 to conform with sysfs intf */
|
||||||
val = ((data->pwm_enable >> index) & 0x01) + 2;
|
val = ((data->pwm_enable >> index) & 0x01) + 2;
|
||||||
} else if (nr == TEMP_CRUISE) {
|
} else if (nr == TEMP_CRUISE) {
|
||||||
val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
|
val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
|
||||||
|
@ -1199,7 +1199,8 @@ static void w83793_init_client(struct i2c_client *client)
|
||||||
|
|
||||||
static int watchdog_set_timeout(struct w83793_data *data, int timeout)
|
static int watchdog_set_timeout(struct w83793_data *data, int timeout)
|
||||||
{
|
{
|
||||||
int ret, mtimeout;
|
unsigned int mtimeout;
|
||||||
|
int ret;
|
||||||
|
|
||||||
mtimeout = DIV_ROUND_UP(timeout, 60);
|
mtimeout = DIV_ROUND_UP(timeout, 60);
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ static inline int vid_to_reg(int val, u8 vrm)
|
||||||
return ((val >= 1100) && (val <= 1850) ?
|
return ((val >= 1100) && (val <= 1850) ?
|
||||||
((18499 - val * 10) / 25 + 5) / 10 : -1);
|
((18499 - val * 10) / 25 + 5) / 10 : -1);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,19 @@
|
||||||
#define _HWMON_H_
|
#define _HWMON_H_
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
struct attribute_group;
|
||||||
|
|
||||||
struct device *hwmon_device_register(struct device *dev);
|
struct device *hwmon_device_register(struct device *dev);
|
||||||
|
struct device *
|
||||||
|
hwmon_device_register_with_groups(struct device *dev, const char *name,
|
||||||
|
void *drvdata,
|
||||||
|
const struct attribute_group **groups);
|
||||||
|
struct device *
|
||||||
|
devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
|
||||||
|
void *drvdata,
|
||||||
|
const struct attribute_group **groups);
|
||||||
|
|
||||||
void hwmon_device_unregister(struct device *dev);
|
void hwmon_device_unregister(struct device *dev);
|
||||||
|
void devm_hwmon_device_unregister(struct device *dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue