You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck: "New drivers for DA9052/53 PMIC as well as HIH-6130/HIH-6131 humidity and temperature sensors. Convert drivers to use devm_ functions and to use dev_pm_ops. Address a couple of Coverity errors/warnings as well as compile warnings. Some functional improvements in applesmc driver." * tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (72 commits) hwmon: (applesmc) Ignore some temperature registers hwmon: (applesmc) Allow negative temperature values hwmon: (s3c-hwmon) Use devm_kzalloc instead of kzalloc hwmon: (w83781d) Fix compile warning hwmon: (applesmc) Shorten minimum wait time hwmon: (exynos4_tmu) Use struct dev_pm_ops for power management hwmon: (gpio-fan) Use struct dev_pm_ops for power management hwmon: (abituguru3) Use struct dev_pm_ops for power management hwmon: (abituguru) Use struct dev_pm_ops for power management hwmon: (acpi_power_meter) Fix unintentional integer overflow hwmon: (acpi_power_meter) Cleanup and optimizations hwmon: Honeywell Humidicon HIH-6130/HIH-6131 humidity and temperature sensor driver hwmon: (applesmc) Skip sensor mapping hwmon: (ntc_thermistor) Ensure that data->name string is terminated hwmon: (w83l785ts) Convert to use devm_ functions hwmon: (w83l785ts) Simplify code and improve readability hwmon: (smsc47m192) Convert to use devm_ functions hwmon: (smsc47m1) Convert to use devm_ functions hwmon: (smsc47b397) Convert to use devm_ functions hwmon: (k8temp) Convert to use devm_ functions ...
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
Supported chips:
|
||||
* Dialog Semiconductors DA9052-BC and DA9053-AA/Bx PMICs
|
||||
Prefix: 'da9052'
|
||||
Datasheet: Datasheet is not publicly available.
|
||||
|
||||
Authors: David Dajun Chen <dchen@diasemi.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The DA9052/53 provides an Analogue to Digital Converter (ADC) with 10 bits
|
||||
resolution and track and hold circuitry combined with an analogue input
|
||||
multiplexer. The analogue input multiplexer will allow conversion of up to 10
|
||||
different inputs. The track and hold circuit ensures stable input voltages at
|
||||
the input of the ADC during the conversion.
|
||||
|
||||
The ADC is used to measure the following inputs:
|
||||
Channel 0: VDDOUT - measurement of the system voltage
|
||||
Channel 1: ICH - internal battery charger current measurement
|
||||
Channel 2: TBAT - output from the battery NTC
|
||||
Channel 3: VBAT - measurement of the battery voltage
|
||||
Channel 4: ADC_IN4 - high impedance input (0 - 2.5V)
|
||||
Channel 5: ADC_IN5 - high impedance input (0 - 2.5V)
|
||||
Channel 6: ADC_IN6 - high impedance input (0 - 2.5V)
|
||||
Channel 7: XY - TSI interface to measure the X and Y voltage of the touch
|
||||
screen resistive potentiometers
|
||||
Channel 8: Internal Tjunc. - sense (internal temp. sensor)
|
||||
Channel 9: VBBAT - measurement of the backup battery voltage
|
||||
|
||||
By using sysfs attributes we can measure the system voltage VDDOUT, the battery
|
||||
charging current ICH, battery temperature TBAT, battery junction temperature
|
||||
TJUNC, battery voltage VBAT and the back up battery voltage VBBAT.
|
||||
|
||||
Voltage Monitoring
|
||||
------------------
|
||||
|
||||
Voltages are sampled by a 10 bit ADC.
|
||||
|
||||
The battery voltage is calculated as:
|
||||
Milli volt = ((ADC value * 1000) / 512) + 2500
|
||||
|
||||
The backup battery voltage is calculated as:
|
||||
Milli volt = (ADC value * 2500) / 512;
|
||||
|
||||
The voltages on ADC channels 4, 5 and 6 are calculated as:
|
||||
Milli volt = (ADC value * 2500) / 1023
|
||||
|
||||
Temperature Monitoring
|
||||
----------------------
|
||||
|
||||
Temperatures are sampled by a 10 bit ADC. Junction and battery temperatures
|
||||
are monitored by the ADC channels.
|
||||
|
||||
The junction temperature is calculated:
|
||||
Degrees celsius = 1.708 * (TJUNC_RES - T_OFFSET) - 108.8
|
||||
The junction temperature attribute is supported by the driver.
|
||||
|
||||
The battery temperature is calculated:
|
||||
Degree Celcius = 1 / (t1 + 1/298)- 273
|
||||
where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
|
||||
Default values of R25, B, ITBAT are 10e3, 3380 and 50e-6 respectively.
|
||||
@@ -0,0 +1,37 @@
|
||||
Kernel driver hih6130
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Honeywell HIH-6130 / HIH-6131
|
||||
Prefix: 'hih6130'
|
||||
Addresses scanned: none
|
||||
Datasheet: Publicly available at the Honeywell website
|
||||
http://sensing.honeywell.com/index.php?ci_id=3106&la_id=1&defId=44872
|
||||
|
||||
Author:
|
||||
Iain Paton <ipaton0@gmail.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The HIH-6130 & HIH-6131 are humidity and temperature sensors in a SO8 package.
|
||||
The difference between the two devices is that the HIH-6131 has a condensation
|
||||
filter.
|
||||
|
||||
The devices communicate with the I2C protocol. All sensors are set to the same
|
||||
I2C address 0x27 by default, so an entry with I2C_BOARD_INFO("hih6130", 0x27)
|
||||
can be used in the board setup code.
|
||||
|
||||
Please see Documentation/i2c/instantiating-devices for details on how to
|
||||
instantiate I2C devices.
|
||||
|
||||
sysfs-Interface
|
||||
---------------
|
||||
|
||||
temp1_input - temperature input
|
||||
humidity1_input - humidity input
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
Command mode and alarms are not currently supported.
|
||||
@@ -70,6 +70,9 @@ increase the chances of your change being accepted.
|
||||
review more difficult. It may also result in code which is more complicated
|
||||
than necessary. Use inline functions or just regular functions instead.
|
||||
|
||||
* Use devres functions whenever possible to allocate resources. For rationale
|
||||
and supported functions, please see Documentation/driver-model/devres.txt.
|
||||
|
||||
* If the driver has a detect function, make sure it is silent. Debug messages
|
||||
and messages printed after a successful detection are acceptable, but it
|
||||
must not print messages such as "Chip XXX not found/supported".
|
||||
|
||||
@@ -314,6 +314,16 @@ config SENSORS_DS1621
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called ds1621.
|
||||
|
||||
config SENSORS_DA9052_ADC
|
||||
tristate "Dialog DA9052/DA9053 ADC"
|
||||
depends on PMIC_DA9052
|
||||
help
|
||||
Say y here to support the ADC found on Dialog Semiconductor
|
||||
DA9052-BC and DA9053-AA/Bx PMICs.
|
||||
|
||||
This driver can also be built as module. If so, the module
|
||||
will be called da9052-hwmon.
|
||||
|
||||
config SENSORS_EXYNOS4_TMU
|
||||
tristate "Temperature sensor on Samsung EXYNOS4"
|
||||
depends on ARCH_EXYNOS4
|
||||
@@ -433,6 +443,16 @@ config SENSORS_GPIO_FAN
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called gpio-fan.
|
||||
|
||||
config SENSORS_HIH6130
|
||||
tristate "Honeywell Humidicon HIH-6130 humidity/temperature sensor"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for Honeywell Humidicon
|
||||
HIH-6130 and HIH-6131 Humidicon humidity sensors.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called hih6130.
|
||||
|
||||
config SENSORS_CORETEMP
|
||||
tristate "Intel Core/Core2/Atom temperature sensor"
|
||||
depends on X86 && PCI && EXPERIMENTAL
|
||||
|
||||
@@ -42,6 +42,7 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
|
||||
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
|
||||
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
|
||||
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
|
||||
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
|
||||
obj-$(CONFIG_SENSORS_DS620) += ds620.o
|
||||
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
|
||||
@@ -58,6 +59,7 @@ obj-$(CONFIG_SENSORS_G760A) += g760a.o
|
||||
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
|
||||
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
|
||||
obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
|
||||
obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
|
||||
obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
|
||||
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
|
||||
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
|
||||
|
||||
@@ -1513,10 +1513,10 @@ LEAVE_UPDATE:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int abituguru_suspend(struct device *dev)
|
||||
{
|
||||
struct abituguru_data *data = platform_get_drvdata(pdev);
|
||||
struct abituguru_data *data = dev_get_drvdata(dev);
|
||||
/*
|
||||
* make sure all communications with the uguru are done and no new
|
||||
* ones are started
|
||||
@@ -1525,29 +1525,30 @@ static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abituguru_resume(struct platform_device *pdev)
|
||||
static int abituguru_resume(struct device *dev)
|
||||
{
|
||||
struct abituguru_data *data = platform_get_drvdata(pdev);
|
||||
struct abituguru_data *data = dev_get_drvdata(dev);
|
||||
/* See if the uGuru is still ready */
|
||||
if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT)
|
||||
data->uguru_ready = 0;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(abituguru_pm, abituguru_suspend, abituguru_resume);
|
||||
#define ABIT_UGURU_PM &abituguru_pm
|
||||
#else
|
||||
#define abituguru_suspend NULL
|
||||
#define abituguru_resume NULL
|
||||
#define ABIT_UGURU_PM NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct platform_driver abituguru_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = ABIT_UGURU_NAME,
|
||||
.pm = ABIT_UGURU_PM,
|
||||
},
|
||||
.probe = abituguru_probe,
|
||||
.remove = __devexit_p(abituguru_remove),
|
||||
.suspend = abituguru_suspend,
|
||||
.resume = abituguru_resume,
|
||||
};
|
||||
|
||||
static int __init abituguru_detect(void)
|
||||
|
||||
@@ -1141,10 +1141,10 @@ LEAVE_UPDATE:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int abituguru3_suspend(struct device *dev)
|
||||
{
|
||||
struct abituguru3_data *data = platform_get_drvdata(pdev);
|
||||
struct abituguru3_data *data = dev_get_drvdata(dev);
|
||||
/*
|
||||
* make sure all communications with the uguru3 are done and no new
|
||||
* ones are started
|
||||
@@ -1153,26 +1153,27 @@ static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abituguru3_resume(struct platform_device *pdev)
|
||||
static int abituguru3_resume(struct device *dev)
|
||||
{
|
||||
struct abituguru3_data *data = platform_get_drvdata(pdev);
|
||||
struct abituguru3_data *data = dev_get_drvdata(dev);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume);
|
||||
#define ABIT_UGURU3_PM &abituguru3_pm
|
||||
#else
|
||||
#define abituguru3_suspend NULL
|
||||
#define abituguru3_resume NULL
|
||||
#define ABIT_UGURU3_PM NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct platform_driver abituguru3_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = ABIT_UGURU3_NAME,
|
||||
.pm = ABIT_UGURU3_PM
|
||||
},
|
||||
.probe = abituguru3_probe,
|
||||
.remove = __devexit_p(abituguru3_remove),
|
||||
.suspend = abituguru3_suspend,
|
||||
.resume = abituguru3_resume
|
||||
};
|
||||
|
||||
static int __init abituguru3_dmi_detect(void)
|
||||
|
||||
@@ -101,7 +101,7 @@ struct acpi_power_meter_resource {
|
||||
unsigned long sensors_last_updated;
|
||||
struct sensor_device_attribute sensors[NUM_SENSORS];
|
||||
int num_sensors;
|
||||
int trip[2];
|
||||
s64 trip[2];
|
||||
int num_domain_devices;
|
||||
struct acpi_device **domain_devices;
|
||||
struct kobject *holders_dir;
|
||||
@@ -237,7 +237,7 @@ static ssize_t set_cap(struct device *dev, struct device_attribute *devattr,
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
temp /= 1000;
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
if (temp > resource->caps.max_cap || temp < resource->caps.min_cap)
|
||||
return -EINVAL;
|
||||
arg0.integer.value = temp;
|
||||
@@ -307,9 +307,7 @@ static ssize_t set_trip(struct device *dev, struct device_attribute *devattr,
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
temp /= 1000;
|
||||
if (temp < 0)
|
||||
return -EINVAL;
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
|
||||
mutex_lock(&resource->lock);
|
||||
resource->trip[attr->index - 7] = temp;
|
||||
|
||||
+7
-11
@@ -366,11 +366,11 @@ static int adm1021_probe(struct i2c_client *client,
|
||||
struct adm1021_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct adm1021_data),
|
||||
GFP_KERNEL);
|
||||
if (!data) {
|
||||
pr_debug("adm1021: detect failed, kzalloc failed!\n");
|
||||
err = -ENOMEM;
|
||||
goto error0;
|
||||
pr_debug("adm1021: detect failed, devm_kzalloc failed!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
@@ -384,21 +384,18 @@ static int adm1021_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&client->dev.kobj, &adm1021_group);
|
||||
if (err)
|
||||
goto error1;
|
||||
return err;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
goto error3;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error3:
|
||||
error:
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1021_group);
|
||||
error1:
|
||||
kfree(data);
|
||||
error0:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -418,7 +415,6 @@ static int adm1021_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1021_group);
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -477,11 +477,10 @@ static int adm1025_probe(struct i2c_client *client,
|
||||
int err;
|
||||
u8 config;
|
||||
|
||||
data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct adm1025_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@@ -492,7 +491,7 @@ static int adm1025_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&client->dev.kobj, &adm1025_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
/* Pin 11 is either in4 (+12V) or VID4 */
|
||||
config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
|
||||
@@ -513,9 +512,6 @@ static int adm1025_probe(struct i2c_client *client,
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -569,7 +565,6 @@ static int adm1025_remove(struct i2c_client *client)
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -1834,11 +1834,10 @@ static int adm1026_probe(struct i2c_client *client,
|
||||
struct adm1026_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct adm1026_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@@ -1852,7 +1851,7 @@ static int adm1026_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&client->dev.kobj, &adm1026_group);
|
||||
if (err)
|
||||
goto exitfree;
|
||||
return err;
|
||||
if (data->config1 & CFG1_AIN8_9)
|
||||
err = sysfs_create_group(&client->dev.kobj,
|
||||
&adm1026_group_in8_9);
|
||||
@@ -1877,9 +1876,6 @@ exitremove:
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
|
||||
else
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
|
||||
exitfree:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1892,7 +1888,6 @@ static int adm1026_remove(struct i2c_client *client)
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
|
||||
else
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -954,11 +954,10 @@ static int adm1031_probe(struct i2c_client *client,
|
||||
struct adm1031_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct adm1031_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
data->chip_type = id->driver_data;
|
||||
@@ -975,7 +974,7 @@ static int adm1031_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
if (data->chip_type == adm1031) {
|
||||
err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
|
||||
@@ -994,9 +993,6 @@ static int adm1031_probe(struct i2c_client *client,
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1007,7 +1003,6 @@ static int adm1031_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+4
-10
@@ -650,11 +650,9 @@ static int adm9240_probe(struct i2c_client *new_client,
|
||||
struct adm9240_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&new_client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(new_client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@@ -664,7 +662,7 @@ static int adm9240_probe(struct i2c_client *new_client,
|
||||
/* populate sysfs filesystem */
|
||||
err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
@@ -676,9 +674,6 @@ static int adm9240_probe(struct i2c_client *new_client,
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -689,7 +684,6 @@ static int adm9240_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm9240_group);
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1260,7 +1260,7 @@ static int adt7475_probe(struct i2c_client *client,
|
||||
int i, ret = 0, revision;
|
||||
u8 config2, config3;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1344,7 +1344,7 @@ static int adt7475_probe(struct i2c_client *client,
|
||||
|
||||
ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group);
|
||||
if (ret)
|
||||
goto efree;
|
||||
return ret;
|
||||
|
||||
/* Features that can be disabled individually */
|
||||
if (data->has_fan4) {
|
||||
@@ -1410,8 +1410,6 @@ static int adt7475_probe(struct i2c_client *client,
|
||||
|
||||
eremove:
|
||||
adt7475_remove_files(client, data);
|
||||
efree:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1421,7 +1419,6 @@ static int adt7475_remove(struct i2c_client *client)
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
adt7475_remove_files(client, data);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+67
-66
@@ -54,7 +54,7 @@
|
||||
#define APPLESMC_MAX_DATA_LENGTH 32
|
||||
|
||||
/* wait up to 32 ms for a status change. */
|
||||
#define APPLESMC_MIN_WAIT 0x0040
|
||||
#define APPLESMC_MIN_WAIT 0x0010
|
||||
#define APPLESMC_MAX_WAIT 0x8000
|
||||
|
||||
#define APPLESMC_STATUS_MASK 0x0f
|
||||
@@ -80,6 +80,8 @@
|
||||
#define FANS_MANUAL "FS! " /* r-w ui16 */
|
||||
#define FAN_ID_FMT "F%dID" /* r-o char[16] */
|
||||
|
||||
#define TEMP_SENSOR_TYPE "sp78"
|
||||
|
||||
/* List of keys used to read/write fan speeds */
|
||||
static const char *const fan_speed_fmt[] = {
|
||||
"F%dAc", /* actual speed */
|
||||
@@ -96,10 +98,6 @@ static const char *const fan_speed_fmt[] = {
|
||||
#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
|
||||
#define APPLESMC_INPUT_FLAT 4
|
||||
|
||||
#define SENSOR_X 0
|
||||
#define SENSOR_Y 1
|
||||
#define SENSOR_Z 2
|
||||
|
||||
#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
|
||||
#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
|
||||
|
||||
@@ -135,11 +133,13 @@ static struct applesmc_registers {
|
||||
unsigned int temp_count; /* number of temperature registers */
|
||||
unsigned int temp_begin; /* temperature lower index bound */
|
||||
unsigned int temp_end; /* temperature upper index bound */
|
||||
unsigned int index_count; /* size of temperature index array */
|
||||
int num_light_sensors; /* number of light sensors */
|
||||
bool has_accelerometer; /* has motion sensor */
|
||||
bool has_key_backlight; /* has keyboard backlight */
|
||||
bool init_complete; /* true when fully initialized */
|
||||
struct applesmc_entry *cache; /* cached key entries */
|
||||
const char **index; /* temperature key index */
|
||||
} smcreg = {
|
||||
.mutex = __MUTEX_INITIALIZER(smcreg.mutex),
|
||||
};
|
||||
@@ -432,30 +432,19 @@ static int applesmc_has_key(const char *key, bool *value)
|
||||
}
|
||||
|
||||
/*
|
||||
* applesmc_read_motion_sensor - Read motion sensor (X, Y or Z).
|
||||
* applesmc_read_s16 - Read 16-bit signed big endian register
|
||||
*/
|
||||
static int applesmc_read_motion_sensor(int index, s16 *value)
|
||||
static int applesmc_read_s16(const char *key, s16 *value)
|
||||
{
|
||||
u8 buffer[2];
|
||||
int ret;
|
||||
|
||||
switch (index) {
|
||||
case SENSOR_X:
|
||||
ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2);
|
||||
break;
|
||||
case SENSOR_Y:
|
||||
ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
|
||||
break;
|
||||
case SENSOR_Z:
|
||||
ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
ret = applesmc_read_key(key, buffer, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*value = ((s16)buffer[0] << 8) | buffer[1];
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -482,6 +471,30 @@ static void applesmc_device_init(void)
|
||||
pr_warn("failed to init the device\n");
|
||||
}
|
||||
|
||||
static int applesmc_init_index(struct applesmc_registers *s)
|
||||
{
|
||||
const struct applesmc_entry *entry;
|
||||
unsigned int i;
|
||||
|
||||
if (s->index)
|
||||
return 0;
|
||||
|
||||
s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL);
|
||||
if (!s->index)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = s->temp_begin; i < s->temp_end; i++) {
|
||||
entry = applesmc_get_entry_by_index(i);
|
||||
if (IS_ERR(entry))
|
||||
continue;
|
||||
if (strcmp(entry->type, TEMP_SENSOR_TYPE))
|
||||
continue;
|
||||
s->index[s->index_count++] = entry->key;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
|
||||
*/
|
||||
@@ -517,6 +530,10 @@ static int applesmc_init_smcreg_try(void)
|
||||
return ret;
|
||||
s->temp_count = s->temp_end - s->temp_begin;
|
||||
|
||||
ret = applesmc_init_index(s);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -533,8 +550,8 @@ static int applesmc_init_smcreg_try(void)
|
||||
s->num_light_sensors = left_light_sensor + right_light_sensor;
|
||||
s->init_complete = true;
|
||||
|
||||
pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n",
|
||||
s->key_count, s->fan_count, s->temp_count,
|
||||
pr_info("key=%d fan=%d temp=%d index=%d acc=%d lux=%d kbd=%d\n",
|
||||
s->key_count, s->fan_count, s->temp_count, s->index_count,
|
||||
s->has_accelerometer,
|
||||
s->num_light_sensors,
|
||||
s->has_key_backlight);
|
||||
@@ -542,6 +559,15 @@ static int applesmc_init_smcreg_try(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void applesmc_destroy_smcreg(void)
|
||||
{
|
||||
kfree(smcreg.index);
|
||||
smcreg.index = NULL;
|
||||
kfree(smcreg.cache);
|
||||
smcreg.cache = NULL;
|
||||
smcreg.init_complete = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* applesmc_init_smcreg - Initialize register cache.
|
||||
*
|
||||
@@ -562,19 +588,11 @@ static int applesmc_init_smcreg(void)
|
||||
msleep(INIT_WAIT_MSECS);
|
||||
}
|
||||
|
||||
kfree(smcreg.cache);
|
||||
smcreg.cache = NULL;
|
||||
applesmc_destroy_smcreg();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void applesmc_destroy_smcreg(void)
|
||||
{
|
||||
kfree(smcreg.cache);
|
||||
smcreg.cache = NULL;
|
||||
smcreg.init_complete = false;
|
||||
}
|
||||
|
||||
/* Device model stuff */
|
||||
static int applesmc_probe(struct platform_device *dev)
|
||||
{
|
||||
@@ -624,8 +642,8 @@ static struct platform_driver applesmc_driver = {
|
||||
*/
|
||||
static void applesmc_calibrate(void)
|
||||
{
|
||||
applesmc_read_motion_sensor(SENSOR_X, &rest_x);
|
||||
applesmc_read_motion_sensor(SENSOR_Y, &rest_y);
|
||||
applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x);
|
||||
applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y);
|
||||
rest_x = -rest_x;
|
||||
}
|
||||
|
||||
@@ -634,9 +652,9 @@ static void applesmc_idev_poll(struct input_polled_dev *dev)
|
||||
struct input_dev *idev = dev->input;
|
||||
s16 x, y;
|
||||
|
||||
if (applesmc_read_motion_sensor(SENSOR_X, &x))
|
||||
if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x))
|
||||
return;
|
||||
if (applesmc_read_motion_sensor(SENSOR_Y, &y))
|
||||
if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y))
|
||||
return;
|
||||
|
||||
x = -x;
|
||||
@@ -659,13 +677,13 @@ static ssize_t applesmc_position_show(struct device *dev,
|
||||
int ret;
|
||||
s16 x, y, z;
|
||||
|
||||
ret = applesmc_read_motion_sensor(SENSOR_X, &x);
|
||||
ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = applesmc_read_motion_sensor(SENSOR_Y, &y);
|
||||
ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = applesmc_read_motion_sensor(SENSOR_Z, &z);
|
||||
ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -718,44 +736,27 @@ out:
|
||||
static ssize_t applesmc_show_sensor_label(struct device *dev,
|
||||
struct device_attribute *devattr, char *sysfsbuf)
|
||||
{
|
||||
int index = smcreg.temp_begin + to_index(devattr);
|
||||
const struct applesmc_entry *entry;
|
||||
const char *key = smcreg.index[to_index(devattr)];
|
||||
|
||||
entry = applesmc_get_entry_by_index(index);
|
||||
if (IS_ERR(entry))
|
||||
return PTR_ERR(entry);
|
||||
|
||||
return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
|
||||
return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
|
||||
}
|
||||
|
||||
/* Displays degree Celsius * 1000 */
|
||||
static ssize_t applesmc_show_temperature(struct device *dev,
|
||||
struct device_attribute *devattr, char *sysfsbuf)
|
||||
{
|
||||
int index = smcreg.temp_begin + to_index(devattr);
|
||||
const struct applesmc_entry *entry;
|
||||
const char *key = smcreg.index[to_index(devattr)];
|
||||
int ret;
|
||||
u8 buffer[2];
|
||||
unsigned int temp;
|
||||
s16 value;
|
||||
int temp;
|
||||
|
||||
entry = applesmc_get_entry_by_index(index);
|
||||
if (IS_ERR(entry))
|
||||
return PTR_ERR(entry);
|
||||
if (entry->len > 2)
|
||||
return -EINVAL;
|
||||
|
||||
ret = applesmc_read_entry(entry, buffer, entry->len);
|
||||
ret = applesmc_read_s16(key, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (entry->len == 2) {
|
||||
temp = buffer[0] * 1000;
|
||||
temp += (buffer[1] >> 6) * 250;
|
||||
} else {
|
||||
temp = buffer[0] * 4000;
|
||||
}
|
||||
temp = 250 * (value >> 6);
|
||||
|
||||
return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
|
||||
return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp);
|
||||
}
|
||||
|
||||
static ssize_t applesmc_show_fan_speed(struct device *dev,
|
||||
@@ -1265,7 +1266,7 @@ static int __init applesmc_init(void)
|
||||
if (ret)
|
||||
goto out_info;
|
||||
|
||||
ret = applesmc_create_nodes(temp_group, smcreg.temp_count);
|
||||
ret = applesmc_create_nodes(temp_group, smcreg.index_count);
|
||||
if (ret)
|
||||
goto out_fans;
|
||||
|
||||
|
||||
@@ -1109,7 +1109,8 @@ asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EIO;
|
||||
|
||||
data = kzalloc(sizeof(struct asc7621_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct asc7621_data),
|
||||
GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1143,7 +1144,6 @@ exit_remove:
|
||||
&(asc7621_params[i].sda.dev_attr));
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1192,7 +1192,6 @@ static int asc7621_remove(struct i2c_client *client)
|
||||
&(asc7621_params[i].sda.dev_attr));
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-11
@@ -345,11 +345,10 @@ static int atxp1_probe(struct i2c_client *new_client,
|
||||
struct atxp1_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&new_client->dev, sizeof(struct atxp1_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get VRM */
|
||||
data->vrm = vid_which_vrm();
|
||||
@@ -362,7 +361,7 @@ static int atxp1_probe(struct i2c_client *new_client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
@@ -377,9 +376,6 @@ static int atxp1_probe(struct i2c_client *new_client,
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
};
|
||||
|
||||
@@ -390,8 +386,6 @@ static int atxp1_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &atxp1_group);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* HWMON Driver for Dialog DA9052
|
||||
*
|
||||
* Copyright(c) 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: David Dajun Chen <dchen@diasemi.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/mfd/da9052/da9052.h>
|
||||
#include <linux/mfd/da9052/reg.h>
|
||||
|
||||
struct da9052_hwmon {
|
||||
struct da9052 *da9052;
|
||||
struct device *class_device;
|
||||
struct mutex hwmon_lock;
|
||||
};
|
||||
|
||||
static const char * const input_names[] = {
|
||||
[DA9052_ADC_VDDOUT] = "VDDOUT",
|
||||
[DA9052_ADC_ICH] = "CHARGING CURRENT",
|
||||
[DA9052_ADC_TBAT] = "BATTERY TEMP",
|
||||
[DA9052_ADC_VBAT] = "BATTERY VOLTAGE",
|
||||
[DA9052_ADC_IN4] = "ADC IN4",
|
||||
[DA9052_ADC_IN5] = "ADC IN5",
|
||||
[DA9052_ADC_IN6] = "ADC IN6",
|
||||
[DA9052_ADC_TJUNC] = "BATTERY JUNCTION TEMP",
|
||||
[DA9052_ADC_VBBAT] = "BACK-UP BATTERY VOLTAGE",
|
||||
};
|
||||
|
||||
/* Conversion function for VDDOUT and VBAT */
|
||||
static inline int volt_reg_to_mV(int value)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(value * 1000, 512) + 2500;
|
||||
}
|
||||
|
||||
/* Conversion function for ADC channels 4, 5 and 6 */
|
||||
static inline int input_reg_to_mV(int value)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(value * 2500, 1023);
|
||||
}
|
||||
|
||||
/* Conversion function for VBBAT */
|
||||
static inline int vbbat_reg_to_mV(int value)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(value * 2500, 512);
|
||||
}
|
||||
|
||||
static int da9052_enable_vddout_channel(struct da9052 *da9052)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret |= DA9052_ADCCONT_AUTOVDDEN;
|
||||
|
||||
return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
|
||||
}
|
||||
|
||||
static int da9052_disable_vddout_channel(struct da9052 *da9052)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~DA9052_ADCCONT_AUTOVDDEN;
|
||||
|
||||
return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_vddout(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int ret, vdd;
|
||||
|
||||
mutex_lock(&hwmon->hwmon_lock);
|
||||
|
||||
ret = da9052_enable_vddout_channel(hwmon->da9052);
|
||||
if (ret < 0)
|
||||
goto hwmon_err;
|
||||
|
||||
vdd = da9052_reg_read(hwmon->da9052, DA9052_VDD_RES_REG);
|
||||
if (vdd < 0) {
|
||||
ret = vdd;
|
||||
goto hwmon_err_release;
|
||||
}
|
||||
|
||||
ret = da9052_disable_vddout_channel(hwmon->da9052);
|
||||
if (ret < 0)
|
||||
goto hwmon_err;
|
||||
|
||||
mutex_unlock(&hwmon->hwmon_lock);
|
||||
return sprintf(buf, "%d\n", volt_reg_to_mV(vdd));
|
||||
|
||||
hwmon_err_release:
|
||||
da9052_disable_vddout_channel(hwmon->da9052);
|
||||
hwmon_err:
|
||||
mutex_unlock(&hwmon->hwmon_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_ich(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(hwmon->da9052, DA9052_ICHG_AV_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Equivalent to 3.9mA/bit in register ICHG_AV */
|
||||
return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(ret * 39, 10));
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_tbat(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", da9052_adc_read_temp(hwmon->da9052));
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_vbat(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_adc_manual_read(hwmon->da9052, DA9052_ADC_VBAT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", volt_reg_to_mV(ret));
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_misc_channel(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int channel = to_sensor_dev_attr(devattr)->index;
|
||||
int ret;
|
||||
|
||||
ret = da9052_adc_manual_read(hwmon->da9052, channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", input_reg_to_mV(ret));
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_tjunc(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int tjunc;
|
||||
int toffset;
|
||||
|
||||
tjunc = da9052_reg_read(hwmon->da9052, DA9052_TJUNC_RES_REG);
|
||||
if (tjunc < 0)
|
||||
return tjunc;
|
||||
|
||||
toffset = da9052_reg_read(hwmon->da9052, DA9052_T_OFFSET_REG);
|
||||
if (toffset < 0)
|
||||
return toffset;
|
||||
|
||||
/*
|
||||
* Degrees celsius = 1.708 * (TJUNC_RES - T_OFFSET) - 108.8
|
||||
* T_OFFSET is a trim value used to improve accuracy of the result
|
||||
*/
|
||||
return sprintf(buf, "%d\n", 1708 * (tjunc - toffset) - 108800);
|
||||
}
|
||||
|
||||
static ssize_t da9052_read_vbbat(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_adc_manual_read(hwmon->da9052, DA9052_ADC_VBBAT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", vbbat_reg_to_mV(ret));
|
||||
}
|
||||
|
||||
static ssize_t da9052_hwmon_show_name(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "da9052-hwmon\n");
|
||||
}
|
||||
|
||||
static ssize_t show_label(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n",
|
||||
input_names[to_sensor_dev_attr(devattr)->index]);
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9052_read_vddout, NULL,
|
||||
DA9052_ADC_VDDOUT);
|
||||
static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_VDDOUT);
|
||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9052_read_vbat, NULL,
|
||||
DA9052_ADC_VBAT);
|
||||
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_VBAT);
|
||||
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, da9052_read_misc_channel, NULL,
|
||||
DA9052_ADC_IN4);
|
||||
static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_IN4);
|
||||
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, da9052_read_misc_channel, NULL,
|
||||
DA9052_ADC_IN5);
|
||||
static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_IN5);
|
||||
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, da9052_read_misc_channel, NULL,
|
||||
DA9052_ADC_IN6);
|
||||
static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_IN6);
|
||||
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, da9052_read_vbbat, NULL,
|
||||
DA9052_ADC_VBBAT);
|
||||
static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_VBBAT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, da9052_read_ich, NULL,
|
||||
DA9052_ADC_ICH);
|
||||
static SENSOR_DEVICE_ATTR(curr1_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_ICH);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, da9052_read_tbat, NULL,
|
||||
DA9052_ADC_TBAT);
|
||||
static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_TBAT);
|
||||
static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, da9052_read_tjunc, NULL,
|
||||
DA9052_ADC_TJUNC);
|
||||
static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_label, NULL,
|
||||
DA9052_ADC_TJUNC);
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, da9052_hwmon_show_name, NULL);
|
||||
|
||||
static struct attribute *da9052_attr[] = {
|
||||
&dev_attr_name.attr,
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_label.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_label.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_label.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_label.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_label.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_label.dev_attr.attr,
|
||||
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr1_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_label.dev_attr.attr,
|
||||
&sensor_dev_attr_temp8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp8_label.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group da9052_attr_group = {.attrs = da9052_attr};
|
||||
|
||||
static int __devinit da9052_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_hwmon *hwmon;
|
||||
int ret;
|
||||
|
||||
hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9052_hwmon),
|
||||
GFP_KERNEL);
|
||||
if (!hwmon)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&hwmon->hwmon_lock);
|
||||
hwmon->da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
platform_set_drvdata(pdev, hwmon);
|
||||
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &da9052_attr_group);
|
||||
if (ret)
|
||||
goto err_mem;
|
||||
|
||||
hwmon->class_device = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(hwmon->class_device)) {
|
||||
ret = PTR_ERR(hwmon->class_device);
|
||||
goto err_sysfs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_sysfs:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &da9052_attr_group);
|
||||
err_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
|
||||
|
||||
hwmon_device_unregister(hwmon->class_device);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &da9052_attr_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9052_hwmon_driver = {
|
||||
.probe = da9052_hwmon_probe,
|
||||
.remove = __devexit_p(da9052_hwmon_remove),
|
||||
.driver = {
|
||||
.name = "da9052-hwmon",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(da9052_hwmon_driver);
|
||||
|
||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
||||
MODULE_DESCRIPTION("DA9052 HWMON driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9052-hwmon");
|
||||
+5
-11
@@ -249,11 +249,10 @@ static int ds1621_probe(struct i2c_client *client,
|
||||
struct ds1621_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@@ -264,7 +263,7 @@ static int ds1621_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
@@ -276,9 +275,6 @@ static int ds1621_probe(struct i2c_client *client,
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -289,8 +285,6 @@ static int ds1621_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -492,11 +492,10 @@ static int emc6w201_probe(struct i2c_client *client,
|
||||
struct emc6w201_data *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(struct emc6w201_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct emc6w201_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@@ -504,7 +503,7 @@ static int emc6w201_probe(struct i2c_client *client,
|
||||
/* Create sysfs attribute */
|
||||
err = sysfs_create_group(&client->dev.kobj, &emc6w201_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
return err;
|
||||
|
||||
/* Expose as a hwmon device */
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
@@ -517,9 +516,6 @@ static int emc6w201_probe(struct i2c_client *client,
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -529,7 +525,6 @@ static int emc6w201_remove(struct i2c_client *client)
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user