From 6faecba0b3da7b617bf72bef422bf0d3bb6dfe7d Mon Sep 17 00:00:00 2001 From: Shikhar Dogra Date: Mon, 27 Mar 2017 16:16:44 -0700 Subject: [PATCH 01/36] driver: (adm1275) set the m,b and R coefficients correctly for power Seems like coefficient values for m, b and R under power have been put in the wrong order. Rearranging them properly to get correct values of coefficients for power. For specs, please refer to table 7 (page 35) on http://www.analog.com/media/en/technical-documentation/data-sheets/ADM1075.pdf Fixes: 904b296f308d ("hwmon: (adm1275) Introduce configuration data structure for coeffcients") Signed-off-by: Shikhar Dogra Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/adm1275.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 4ab5293c7bf0..00d6995af4c2 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -101,8 +101,8 @@ static const struct coefficients adm1075_coefficients[] = { [0] = { 27169, 0, -1 }, /* voltage */ [1] = { 806, 20475, -1 }, /* current, irange25 */ [2] = { 404, 20475, -1 }, /* current, irange50 */ - [3] = { 0, -1, 8549 }, /* power, irange25 */ - [4] = { 0, -1, 4279 }, /* power, irange50 */ + [3] = { 8549, 0, -1 }, /* power, irange25 */ + [4] = { 4279, 0, -1 }, /* power, irange50 */ }; static const struct coefficients adm1275_coefficients[] = { From 3dead5d59631ebc72c327637e1053b7c26723709 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 21 Feb 2017 22:30:47 +1300 Subject: [PATCH 02/36] docs: hwmon: Fix typo "Microship" should be "Microchip" Signed-off-by: Chris Packham Signed-off-by: Guenter Roeck --- Documentation/hwmon/tc654 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/hwmon/tc654 b/Documentation/hwmon/tc654 index 91a2843f5f98..47636a8077b4 100644 --- a/Documentation/hwmon/tc654 +++ b/Documentation/hwmon/tc654 @@ -2,7 +2,7 @@ Kernel driver tc654 =================== Supported chips: - * Microship TC654 and TC655 + * Microchip TC654 and TC655 Prefix: 'tc654' Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20001734C.pdf From 0d0235301b3a530e1e8ffedab72ba38ca9aa2ac6 Mon Sep 17 00:00:00 2001 From: Katsumi Sato Date: Wed, 22 Feb 2017 13:32:10 +0900 Subject: [PATCH 03/36] hwmon: (w83627ehf) Use request_muxed_region Serialize access to the hardware by using "request_muxed_region". Call to this macro will hold off the requestor if the resource is currently busy. "superio_enter" will return an error if call to "request_muxed_region" fails. Signed-off-by: Katsumi Sato Signed-off-by: Atsushi Nemoto Signed-off-by: Guenter Roeck --- drivers/hwmon/w83627ehf.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index ab346ed142de..ad68b6d9ff17 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -135,11 +135,16 @@ superio_select(int ioreg, int ld) outb(ld, ioreg + 1); } -static inline void +static inline int superio_enter(int ioreg) { + if (!request_muxed_region(ioreg, 2, DRVNAME)) + return -EBUSY; + outb(0x87, ioreg); outb(0x87, ioreg); + + return 0; } static inline void @@ -148,6 +153,7 @@ superio_exit(int ioreg) outb(0xaa, ioreg); outb(0x02, ioreg); outb(0x02, ioreg + 1); + release_region(ioreg, 2); } /* @@ -1970,8 +1976,6 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, return; } - superio_enter(sio_data->sioreg); - /* fan4 and fan5 share some pins with the GPIO and serial flash */ if (sio_data->kind == nct6775) { /* On NCT6775, fan4 shares pins with the fdc interface */ @@ -2013,8 +2017,6 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, fan4min = fan4pin; } - superio_exit(sio_data->sioreg); - data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */ data->has_fan |= (fan3pin << 2); data->has_fan_min |= (fan3pin << 2); @@ -2352,7 +2354,11 @@ static int w83627ehf_probe(struct platform_device *pdev) w83627ehf_init_device(data, sio_data->kind); data->vrm = vid_which_vrm(); - superio_enter(sio_data->sioreg); + + err = superio_enter(sio_data->sioreg); + if (err) + goto exit_release; + /* Read VID value */ if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b || sio_data->kind == nct6775 || sio_data->kind == nct6776) { @@ -2364,8 +2370,10 @@ static int w83627ehf_probe(struct platform_device *pdev) superio_select(sio_data->sioreg, W83667HG_LD_VID); data->vid = superio_inb(sio_data->sioreg, 0xe3); err = device_create_file(dev, &dev_attr_cpu0_vid); - if (err) + if (err) { + superio_exit(sio_data->sioreg); goto exit_release; + } } else if (sio_data->kind != w83627uhg) { superio_select(sio_data->sioreg, W83627EHF_LD_HWM); if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { @@ -2401,8 +2409,10 @@ static int w83627ehf_probe(struct platform_device *pdev) data->vid &= 0x3f; err = device_create_file(dev, &dev_attr_cpu0_vid); - if (err) + if (err) { + superio_exit(sio_data->sioreg); goto exit_release; + } } else { dev_info(dev, "VID pins in output mode, CPU VID not available\n"); @@ -2424,10 +2434,10 @@ static int w83627ehf_probe(struct platform_device *pdev) pr_info("Enabled fan debounce for chip %s\n", data->name); } - superio_exit(sio_data->sioreg); - w83627ehf_check_fan_inputs(sio_data, data); + superio_exit(sio_data->sioreg); + /* Read fan clock dividers immediately */ w83627ehf_update_fan_div_common(dev, data); @@ -2712,8 +2722,11 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, u16 val; const char *sio_name; + int err; - superio_enter(sioaddr); + err = superio_enter(sioaddr); + if (err) + return err; if (force_id) val = force_id; From 72edf311edbcd0d04928e656421ecdfc4c9ed16a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:54 -0300 Subject: [PATCH 04/36] hwmon: (ad7414) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/ad7414.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 763490acc0df..cec227f13874 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -217,9 +217,16 @@ static const struct i2c_device_id ad7414_id[] = { }; MODULE_DEVICE_TABLE(i2c, ad7414_id); +static const struct of_device_id ad7414_of_match[] = { + { .compatible = "ad,ad7414" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7414_of_match); + static struct i2c_driver ad7414_driver = { .driver = { .name = "ad7414", + .of_match_table = of_match_ptr(ad7414_of_match), }, .probe = ad7414_probe, .id_table = ad7414_id, From d593e665f31c09d6421f92a99314313d09a9631d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:55 -0300 Subject: [PATCH 05/36] hwmon: (adc128d818) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/adc128d818.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index bbe3a5c5b3f5..a557b46dbe8e 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -546,10 +546,17 @@ static const struct i2c_device_id adc128_id[] = { }; MODULE_DEVICE_TABLE(i2c, adc128_id); +static const struct of_device_id adc128_of_match[] = { + { .compatible = "ti,adc128d818" }, + { }, +}; +MODULE_DEVICE_TABLE(of, adc128_of_match); + static struct i2c_driver adc128_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "adc128d818", + .of_match_table = of_match_ptr(adc128_of_match), }, .probe = adc128_probe, .remove = adc128_remove, From a140986fd0708607dbbd6321386964e44fef59a2 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:56 -0300 Subject: [PATCH 06/36] hwmon: (ads1015) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/ads1015.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 2b3105c8aed3..5140c27d16dd 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -268,7 +269,12 @@ static int ads1015_probe(struct i2c_client *client, GFP_KERNEL); if (!data) return -ENOMEM; - data->id = id->driver_data; + + if (client->dev.of_node) + data->id = (enum ads1015_chips) + of_device_get_match_data(&client->dev); + else + data->id = id->driver_data; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -303,9 +309,23 @@ static const struct i2c_device_id ads1015_id[] = { }; MODULE_DEVICE_TABLE(i2c, ads1015_id); +static const struct of_device_id ads1015_of_match[] = { + { + .compatible = "ti,ads1015", + .data = (void *)ads1015 + }, + { + .compatible = "ti,ads1115", + .data = (void *)ads1115 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, ads1015_of_match); + static struct i2c_driver ads1015_driver = { .driver = { .name = "ads1015", + .of_match_table = of_match_ptr(ads1015_of_match), }, .probe = ads1015_probe, .remove = ads1015_remove, From 2d688f1413aba35b3861a1d709a98693a5b0b58f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:57 -0300 Subject: [PATCH 07/36] hwmon: (ads7828) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/ads7828.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index ee396ff167d9..b0ef66687816 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,7 @@ static int ads7828_probe(struct i2c_client *client, bool diff_input = false; bool ext_vref = false; unsigned int regval; + enum ads7828_chips chip; data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); if (!data) @@ -133,12 +135,18 @@ static int ads7828_probe(struct i2c_client *client, vref_mv = pdata->vref_mv; } + if (client->dev.of_node) + chip = (enum ads7828_chips) + of_device_get_match_data(&client->dev); + else + chip = id->driver_data; + /* Bound Vref with min/max values */ vref_mv = clamp_val(vref_mv, ADS7828_EXT_VREF_MV_MIN, ADS7828_EXT_VREF_MV_MAX); /* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */ - if (id->driver_data == ads7828) { + if (chip == ads7828) { data->lsb_resol = DIV_ROUND_CLOSEST(vref_mv * 1000, 4096); data->regmap = devm_regmap_init_i2c(client, &ads2828_regmap_config); @@ -177,9 +185,23 @@ static const struct i2c_device_id ads7828_device_ids[] = { }; MODULE_DEVICE_TABLE(i2c, ads7828_device_ids); +static const struct of_device_id ads7828_of_match[] = { + { + .compatible = "ti,ads7828", + .data = (void *)ads7828 + }, + { + .compatible = "ti,ads7830", + .data = (void *)ads7830 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, ads7828_of_match); + static struct i2c_driver ads7828_driver = { .driver = { .name = "ads7828", + .of_match_table = of_match_ptr(ads7828_of_match), }, .id_table = ads7828_device_ids, From 4e2496e419a159d907e744237384d3c1c103c76d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:58 -0300 Subject: [PATCH 08/36] hwmon: (adt7475) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index c646670b9ea9..fcfa48222145 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -161,6 +162,27 @@ static const struct i2c_device_id adt7475_id[] = { }; MODULE_DEVICE_TABLE(i2c, adt7475_id); +static const struct of_device_id adt7475_of_match[] = { + { + .compatible = "adi,adt7473", + .data = (void *)adt7473 + }, + { + .compatible = "adi,adt7475", + .data = (void *)adt7475 + }, + { + .compatible = "adi,adt7476", + .data = (void *)adt7476 + }, + { + .compatible = "adi,adt7490", + .data = (void *)adt7490 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, adt7475_of_match); + struct adt7475_data { struct device *hwmon_dev; struct mutex lock; @@ -1250,6 +1272,7 @@ static void adt7475_remove_files(struct i2c_client *client, static int adt7475_probe(struct i2c_client *client, const struct i2c_device_id *id) { + enum chips chip; static const char * const names[] = { [adt7473] = "ADT7473", [adt7475] = "ADT7475", @@ -1268,8 +1291,13 @@ static int adt7475_probe(struct i2c_client *client, mutex_init(&data->lock); i2c_set_clientdata(client, data); + if (client->dev.of_node) + chip = (enum chips)of_device_get_match_data(&client->dev); + else + chip = id->driver_data; + /* Initialize device-specific values */ - switch (id->driver_data) { + switch (chip) { case adt7476: data->has_voltage = 0x0e; /* in1 to in3 */ revision = adt7475_read(REG_DEVID2) & 0x07; @@ -1428,6 +1456,7 @@ static struct i2c_driver adt7475_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "adt7475", + .of_match_table = of_match_ptr(adt7475_of_match), }, .probe = adt7475_probe, .remove = adt7475_remove, From 0b7abe59bee79e92563e5d3a7c2aad81a78c7ba5 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:12:59 -0300 Subject: [PATCH 09/36] hwmon: (ina209) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/ina209.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c index 5378fdefc1f7..c5f20f03e0be 100644 --- a/drivers/hwmon/ina209.c +++ b/drivers/hwmon/ina209.c @@ -608,11 +608,18 @@ static const struct i2c_device_id ina209_id[] = { }; MODULE_DEVICE_TABLE(i2c, ina209_id); +static const struct of_device_id ina209_of_match[] = { + { .compatible = "ti,ina209" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ina209_of_match); + /* This is the driver that will be inserted */ static struct i2c_driver ina209_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "ina209", + .of_match_table = of_match_ptr(ina209_of_match), }, .probe = ina209_probe, .remove = ina209_remove, From bd0ddd4d0883a95e6a3d49e7174e546b2f1845cf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:00 -0300 Subject: [PATCH 10/36] hwmon: (ina2xx) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/ina2xx.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index b24f1d3045f0..62e38fa8cda2 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -424,13 +425,19 @@ static int ina2xx_probe(struct i2c_client *client, struct device *hwmon_dev; u32 val; int ret, group = 0; + enum ina2xx_ids chip; + + if (client->dev.of_node) + chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev); + else + chip = id->driver_data; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; /* set the device type */ - data->config = &ina2xx_config[id->driver_data]; + data->config = &ina2xx_config[chip]; if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) { struct ina2xx_platform_data *pdata = dev_get_platdata(dev); @@ -487,9 +494,35 @@ static const struct i2c_device_id ina2xx_id[] = { }; MODULE_DEVICE_TABLE(i2c, ina2xx_id); +static const struct of_device_id ina2xx_of_match[] = { + { + .compatible = "ti,ina219", + .data = (void *)ina219 + }, + { + .compatible = "ti,ina220", + .data = (void *)ina219 + }, + { + .compatible = "ti,ina226", + .data = (void *)ina226 + }, + { + .compatible = "ti,ina230", + .data = (void *)ina226 + }, + { + .compatible = "ti,ina231", + .data = (void *)ina226 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, ina2xx_of_match); + static struct i2c_driver ina2xx_driver = { .driver = { .name = "ina2xx", + .of_match_table = of_match_ptr(ina2xx_of_match), }, .probe = ina2xx_probe, .id_table = ina2xx_id, From b25f663b91f1adca566cbe6d9387ee155dca5a04 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:01 -0300 Subject: [PATCH 11/36] hwmon: (lm63) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm63.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 2e1948699114..4c1770920d29 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -1115,6 +1116,10 @@ static int lm63_probe(struct i2c_client *client, mutex_init(&data->update_lock); /* Set the device type */ + if (client->dev.of_node) + data->kind = (enum chips)of_device_get_match_data(&client->dev); + else + data->kind = id->driver_data; data->kind = id->driver_data; if (data->kind == lm64) data->temp2_offset = 16000; @@ -1149,10 +1154,28 @@ static const struct i2c_device_id lm63_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm63_id); +static const struct of_device_id lm63_of_match[] = { + { + .compatible = "national,lm63", + .data = (void *)lm63 + }, + { + .compatible = "national,lm64", + .data = (void *)lm64 + }, + { + .compatible = "national,lm96163", + .data = (void *)lm96163 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm63_of_match); + static struct i2c_driver lm63_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm63", + .of_match_table = of_match_ptr(lm63_of_match), }, .probe = lm63_probe, .id_table = lm63_id, From e97a45f1b460b5ba7438fe77b7282bf25acfbed9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:02 -0300 Subject: [PATCH 12/36] hwmon: (lm75) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm75.c | 98 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index eff3b24d8473..005ffb5ffa92 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include "lm75.h" @@ -273,7 +274,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) int status, err; u8 set_mask, clr_mask; int new; - enum lm75_type kind = id->driver_data; + enum lm75_type kind; + + if (client->dev.of_node) + kind = (enum lm75_type)of_device_get_match_data(&client->dev); + else + kind = id->driver_data; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) @@ -424,6 +430,95 @@ static const struct i2c_device_id lm75_ids[] = { }; MODULE_DEVICE_TABLE(i2c, lm75_ids); +static const struct of_device_id lm75_of_match[] = { + { + .compatible = "adi,adt75", + .data = (void *)adt75 + }, + { + .compatible = "dallas,ds1775", + .data = (void *)ds1775 + }, + { + .compatible = "dallas,ds75", + .data = (void *)ds75 + }, + { + .compatible = "dallas,ds7505", + .data = (void *)ds7505 + }, + { + .compatible = "gmt,g751", + .data = (void *)g751 + }, + { + .compatible = "national,lm75", + .data = (void *)lm75 + }, + { + .compatible = "national,lm75a", + .data = (void *)lm75a + }, + { + .compatible = "national,lm75b", + .data = (void *)lm75b + }, + { + .compatible = "maxim,max6625", + .data = (void *)max6625 + }, + { + .compatible = "maxim,max6626", + .data = (void *)max6626 + }, + { + .compatible = "maxim,mcp980x", + .data = (void *)mcp980x + }, + { + .compatible = "st,stds75", + .data = (void *)stds75 + }, + { + .compatible = "microchip,tcn75", + .data = (void *)tcn75 + }, + { + .compatible = "ti,tmp100", + .data = (void *)tmp100 + }, + { + .compatible = "ti,tmp101", + .data = (void *)tmp101 + }, + { + .compatible = "ti,tmp105", + .data = (void *)tmp105 + }, + { + .compatible = "ti,tmp112", + .data = (void *)tmp112 + }, + { + .compatible = "ti,tmp175", + .data = (void *)tmp175 + }, + { + .compatible = "ti,tmp275", + .data = (void *)tmp275 + }, + { + .compatible = "ti,tmp75", + .data = (void *)tmp75 + }, + { + .compatible = "ti,tmp75c", + .data = (void *)tmp75c + }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm75_of_match); + #define LM75A_ID 0xA1 /* Return 0 if detection is successful, -ENODEV otherwise */ @@ -560,6 +655,7 @@ static struct i2c_driver lm75_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm75", + .of_match_table = of_match_ptr(lm75_of_match), .pm = LM75_DEV_PM_OPS, }, .probe = lm75_probe, From 00c0f9d3aedc3c3061700b9441c1d63500070be9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:03 -0300 Subject: [PATCH 13/36] hwmon: (lm85) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm85.c | 56 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 691469ffa24e..0a325878e8f5 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -1552,7 +1553,10 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id) return -ENOMEM; data->client = client; - data->type = id->driver_data; + if (client->dev.of_node) + data->type = (enum chips)of_device_get_match_data(&client->dev); + else + data->type = id->driver_data; mutex_init(&data->update_lock); /* Fill in the chip specific driver values */ @@ -1623,10 +1627,60 @@ static const struct i2c_device_id lm85_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm85_id); +static const struct of_device_id lm85_of_match[] = { + { + .compatible = "adi,adm1027", + .data = (void *)adm1027 + }, + { + .compatible = "adi,adt7463", + .data = (void *)adt7463 + }, + { + .compatible = "adi,adt7468", + .data = (void *)adt7468 + }, + { + .compatible = "national,lm85", + .data = (void *)lm85 + }, + { + .compatible = "national,lm85b", + .data = (void *)lm85 + }, + { + .compatible = "national,lm85c", + .data = (void *)lm85 + }, + { + .compatible = "smsc,emc6d100", + .data = (void *)emc6d100 + }, + { + .compatible = "smsc,emc6d101", + .data = (void *)emc6d100 + }, + { + .compatible = "smsc,emc6d102", + .data = (void *)emc6d102 + }, + { + .compatible = "smsc,emc6d103", + .data = (void *)emc6d103 + }, + { + .compatible = "smsc,emc6d103s", + .data = (void *)emc6d103s + }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm85_of_match); + static struct i2c_driver lm85_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm85", + .of_match_table = of_match_ptr(lm85_of_match), }, .probe = lm85_probe, .id_table = lm85_id, From df8d57bf8a4ec6fbf43ce11a9d0b41985337ed0c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:04 -0300 Subject: [PATCH 14/36] hwmon: (lm90) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm90.c | 100 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index aff5297bc2bc..c2f411c290bf 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,99 @@ static const struct i2c_device_id lm90_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm90_id); +static const struct of_device_id lm90_of_match[] = { + { + .compatible = "adi,adm1032", + .data = (void *)adm1032 + }, + { + .compatible = "adi,adt7461", + .data = (void *)adt7461 + }, + { + .compatible = "adi,adt7461a", + .data = (void *)adt7461 + }, + { + .compatible = "gmt,g781", + .data = (void *)g781 + }, + { + .compatible = "national,lm90", + .data = (void *)lm90 + }, + { + .compatible = "national,lm86", + .data = (void *)lm86 + }, + { + .compatible = "national,lm89", + .data = (void *)lm86 + }, + { + .compatible = "national,lm99", + .data = (void *)lm99 + }, + { + .compatible = "dallas,max6646", + .data = (void *)max6646 + }, + { + .compatible = "dallas,max6647", + .data = (void *)max6646 + }, + { + .compatible = "dallas,max6649", + .data = (void *)max6646 + }, + { + .compatible = "dallas,max6657", + .data = (void *)max6657 + }, + { + .compatible = "dallas,max6658", + .data = (void *)max6657 + }, + { + .compatible = "dallas,max6659", + .data = (void *)max6659 + }, + { + .compatible = "dallas,max6680", + .data = (void *)max6680 + }, + { + .compatible = "dallas,max6681", + .data = (void *)max6680 + }, + { + .compatible = "dallas,max6695", + .data = (void *)max6696 + }, + { + .compatible = "dallas,max6696", + .data = (void *)max6696 + }, + { + .compatible = "onnn,nct1008", + .data = (void *)adt7461 + }, + { + .compatible = "winbond,w83l771", + .data = (void *)w83l771 + }, + { + .compatible = "nxp,sa56004", + .data = (void *)sa56004 + }, + { + .compatible = "ti,tmp451", + .data = (void *)tmp451 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm90_of_match); + /* * chip type specific parameters */ @@ -1677,7 +1771,10 @@ static int lm90_probe(struct i2c_client *client, mutex_init(&data->update_lock); /* Set the device type */ - data->kind = id->driver_data; + if (client->dev.of_node) + data->kind = (enum chips)of_device_get_match_data(&client->dev); + else + data->kind = id->driver_data; if (data->kind == adm1032) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) client->flags &= ~I2C_CLIENT_PEC; @@ -1816,6 +1913,7 @@ static struct i2c_driver lm90_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm90", + .of_match_table = of_match_ptr(lm90_of_match), }, .probe = lm90_probe, .alert = lm90_alert, From 5ada7055f29800bf0f7092092a8ea4b8551e8979 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:05 -0300 Subject: [PATCH 15/36] hwmon: (lm95245) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm95245.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c index a3bfd88752ca..27cb06d65594 100644 --- a/drivers/hwmon/lm95245.c +++ b/drivers/hwmon/lm95245.c @@ -622,10 +622,18 @@ static const struct i2c_device_id lm95245_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm95245_id); +static const struct of_device_id lm95245_of_match[] = { + { .compatible = "national,lm95235" }, + { .compatible = "national,lm95245" }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm95245_of_match); + static struct i2c_driver lm95245_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm95245", + .of_match_table = of_match_ptr(lm95245_of_match), }, .probe = lm95245_probe, .id_table = lm95245_id, From 9e427083c3cec46435988f2ee80d643a82ec9e4c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:06 -0300 Subject: [PATCH 16/36] hwmon: (max6697) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/max6697.c | 52 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index f03a71722849..221fd1492057 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -632,7 +633,10 @@ static int max6697_probe(struct i2c_client *client, if (!data) return -ENOMEM; - data->type = id->driver_data; + if (client->dev.of_node) + data->type = (enum chips)of_device_get_match_data(&client->dev); + else + data->type = id->driver_data; data->chip = &max6697_chip_data[data->type]; data->client = client; mutex_init(&data->update_lock); @@ -662,10 +666,56 @@ static const struct i2c_device_id max6697_id[] = { }; MODULE_DEVICE_TABLE(i2c, max6697_id); +static const struct of_device_id max6697_of_match[] = { + { + .compatible = "maxim,max6581", + .data = (void *)max6581 + }, + { + .compatible = "maxim,max6602", + .data = (void *)max6602 + }, + { + .compatible = "maxim,max6622", + .data = (void *)max6622 + }, + { + .compatible = "maxim,max6636", + .data = (void *)max6636 + }, + { + .compatible = "maxim,max6689", + .data = (void *)max6689 + }, + { + .compatible = "maxim,max6693", + .data = (void *)max6693 + }, + { + .compatible = "maxim,max6694", + .data = (void *)max6694 + }, + { + .compatible = "maxim,max6697", + .data = (void *)max6697 + }, + { + .compatible = "maxim,max6698", + .data = (void *)max6698 + }, + { + .compatible = "maxim,max6699", + .data = (void *)max6699 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, max6697_of_match); + static struct i2c_driver max6697_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "max6697", + .of_match_table = of_match_ptr(max6697_of_match), }, .probe = max6697_probe, .id_table = max6697_id, From 8881a19187e452e72e8b1782342b2687e4c9b21d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:07 -0300 Subject: [PATCH 17/36] hwmon: (ucd9000) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/ucd9000.c | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 3e3aa950277f..3518f0c08934 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -119,6 +120,35 @@ static const struct i2c_device_id ucd9000_id[] = { }; MODULE_DEVICE_TABLE(i2c, ucd9000_id); +static const struct of_device_id ucd9000_of_match[] = { + { + .compatible = "ti,ucd9000", + .data = (void *)ucd9000 + }, + { + .compatible = "ti,ucd90120", + .data = (void *)ucd90120 + }, + { + .compatible = "ti,ucd90124", + .data = (void *)ucd90124 + }, + { + .compatible = "ti,ucd90160", + .data = (void *)ucd90160 + }, + { + .compatible = "ti,ucd9090", + .data = (void *)ucd9090 + }, + { + .compatible = "ti,ucd90910", + .data = (void *)ucd90910 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, ucd9000_of_match); + static int ucd9000_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -126,6 +156,7 @@ static int ucd9000_probe(struct i2c_client *client, struct ucd9000_data *data; struct pmbus_driver_info *info; const struct i2c_device_id *mid; + enum chips chip; int i, ret; if (!i2c_check_functionality(client->adapter, @@ -151,7 +182,12 @@ static int ucd9000_probe(struct i2c_client *client, return -ENODEV; } - if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) + if (client->dev.of_node) + chip = (enum chips)of_device_get_match_data(&client->dev); + else + chip = id->driver_data; + + if (chip != ucd9000 && chip != mid->driver_data) dev_notice(&client->dev, "Device mismatch: Configured %s, detected %s\n", id->name, mid->name); @@ -234,6 +270,7 @@ static int ucd9000_probe(struct i2c_client *client, static struct i2c_driver ucd9000_driver = { .driver = { .name = "ucd9000", + .of_match_table = of_match_ptr(ucd9000_of_match), }, .probe = ucd9000_probe, .remove = pmbus_do_remove, From 02331c3a1a8ddf8b47bb190294138d2a76e4b8d0 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:08 -0300 Subject: [PATCH 18/36] hwmon: (ucd9200) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/ucd9200.c | 48 ++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index 033d6aca47d3..a8712c5ded4e 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -46,12 +47,50 @@ static const struct i2c_device_id ucd9200_id[] = { }; MODULE_DEVICE_TABLE(i2c, ucd9200_id); +static const struct of_device_id ucd9200_of_match[] = { + { + .compatible = "ti,cd9200", + .data = (void *)ucd9200 + }, + { + .compatible = "ti,cd9220", + .data = (void *)ucd9220 + }, + { + .compatible = "ti,cd9222", + .data = (void *)ucd9222 + }, + { + .compatible = "ti,cd9224", + .data = (void *)ucd9224 + }, + { + .compatible = "ti,cd9240", + .data = (void *)ucd9240 + }, + { + .compatible = "ti,cd9244", + .data = (void *)ucd9244 + }, + { + .compatible = "ti,cd9246", + .data = (void *)ucd9246 + }, + { + .compatible = "ti,cd9248", + .data = (void *)ucd9248 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, ucd9200_of_match); + static int ucd9200_probe(struct i2c_client *client, const struct i2c_device_id *id) { u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; struct pmbus_driver_info *info; const struct i2c_device_id *mid; + enum chips chip; int i, j, ret; if (!i2c_check_functionality(client->adapter, @@ -76,7 +115,13 @@ static int ucd9200_probe(struct i2c_client *client, dev_err(&client->dev, "Unsupported device\n"); return -ENODEV; } - if (id->driver_data != ucd9200 && id->driver_data != mid->driver_data) + + if (client->dev.of_node) + chip = (enum chips)of_device_get_match_data(&client->dev); + else + chip = id->driver_data; + + if (chip != ucd9200 && chip != mid->driver_data) dev_notice(&client->dev, "Device mismatch: Configured %s, detected %s\n", id->name, mid->name); @@ -167,6 +212,7 @@ static int ucd9200_probe(struct i2c_client *client, static struct i2c_driver ucd9200_driver = { .driver = { .name = "ucd9200", + .of_match_table = of_match_ptr(ucd9200_of_match), }, .probe = ucd9200_probe, .remove = pmbus_do_remove, From 1c1a7b75bf6f705d9f9440dea0e6d682882e3284 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:09 -0300 Subject: [PATCH 19/36] hwmon: (stts751) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/stts751.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index 55450680fb58..d56251d6eec2 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -85,6 +85,12 @@ static const struct i2c_device_id stts751_id[] = { { } }; +static const struct of_device_id stts751_of_match[] = { + { .compatible = "stts751" }, + { }, +}; +MODULE_DEVICE_TABLE(of, stts751_of_match); + struct stts751_priv { struct device *dev; struct i2c_client *client; @@ -819,6 +825,7 @@ static struct i2c_driver stts751_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = DEVNAME, + .of_match_table = of_match_ptr(stts751_of_match), }, .probe = stts751_probe, .id_table = stts751_id, From 15390c610fd373117607a45d67fe0a8ae381edd3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:10 -0300 Subject: [PATCH 20/36] hwmon: (tmp102) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp102.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 36bba2a816a4..5eafbaada795 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -323,8 +323,15 @@ static const struct i2c_device_id tmp102_id[] = { }; MODULE_DEVICE_TABLE(i2c, tmp102_id); +static const struct of_device_id tmp102_of_match[] = { + { .compatible = "ti,tmp102" }, + { }, +}; +MODULE_DEVICE_TABLE(of, tmp102_of_match); + static struct i2c_driver tmp102_driver = { .driver.name = DRIVER_NAME, + .driver.of_match_table = of_match_ptr(tmp102_of_match), .driver.pm = &tmp102_dev_pm_ops, .probe = tmp102_probe, .id_table = tmp102_id, From 72fc64c68decf119466d3fff61875f2958352a93 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:11 -0300 Subject: [PATCH 21/36] hwmon: (tmp103) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp103.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index ad571ec795a3..d0bb28b0d4c3 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -183,9 +183,16 @@ static const struct i2c_device_id tmp103_id[] = { }; MODULE_DEVICE_TABLE(i2c, tmp103_id); +static const struct of_device_id tmp103_of_match[] = { + { .compatible = "ti,tmp103" }, + { }, +}; +MODULE_DEVICE_TABLE(of, tmp103_of_match); + static struct i2c_driver tmp103_driver = { .driver = { .name = "tmp103", + .of_match_table = of_match_ptr(tmp103_of_match), .pm = TMP103_DEV_PM_OPS, }, .probe = tmp103_probe, From a1253027b74e74f67245798a1d71f383a84d6a37 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 24 Feb 2017 10:13:12 -0300 Subject: [PATCH 22/36] hwmon: (tmp421) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp421.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index bfb98b96c781..e36399213324 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -29,6 +29,7 @@ #include #include #include +#include #include /* Addresses to scan */ @@ -69,6 +70,31 @@ static const struct i2c_device_id tmp421_id[] = { }; MODULE_DEVICE_TABLE(i2c, tmp421_id); +static const struct of_device_id tmp421_of_match[] = { + { + .compatible = "ti,tmp421", + .data = (void *)2 + }, + { + .compatible = "ti,tmp422", + .data = (void *)3 + }, + { + .compatible = "ti,tmp423", + .data = (void *)4 + }, + { + .compatible = "ti,tmp441", + .data = (void *)2 + }, + { + .compatible = "ti,tmp422", + .data = (void *)3 + }, + { }, +}; +MODULE_DEVICE_TABLE(of, tmp421_of_match); + struct tmp421_data { struct i2c_client *client; struct mutex update_lock; @@ -78,7 +104,7 @@ struct tmp421_data { struct hwmon_chip_info chip; char valid; unsigned long last_updated; - int channels; + unsigned long channels; u8 config; s16 temp[4]; }; @@ -272,7 +298,11 @@ static int tmp421_probe(struct i2c_client *client, return -ENOMEM; mutex_init(&data->update_lock); - data->channels = id->driver_data; + if (client->dev.of_node) + data->channels = (unsigned long) + of_device_get_match_data(&client->dev); + else + data->channels = id->driver_data; data->client = client; err = tmp421_init_client(client); @@ -301,6 +331,7 @@ static struct i2c_driver tmp421_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "tmp421", + .of_match_table = of_match_ptr(tmp421_of_match), }, .probe = tmp421_probe, .id_table = tmp421_id, From b3ee2785eedaaaf2fe4166594953ddcb2a85c415 Mon Sep 17 00:00:00 2001 From: Marco Franchi Date: Thu, 16 Feb 2017 10:23:44 -0200 Subject: [PATCH 23/36] dt: Add vendor prefix for Sensirion Sensirion is a sensor manufacturer, providing relative humidity sensors, temperature sensor and flow sensor solutions. Signed-off-by: Marco Franchi Reviewed-by: Guenter Roeck Acked-by: Rob Herring Signed-off-by: Guenter Roeck --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ec0bfb9bbebd..830c9987fa02 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -265,6 +265,7 @@ sbs Smart Battery System schindler Schindler seagate Seagate Technology PLC semtech Semtech Corporation +sensirion Sensirion AG sgx SGX Sensortech sharp Sharp Corporation si-en Si-En Technology Ltd. From 5ba6bcbc335771c37d05b88cbfcad5441b57130b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 7 Mar 2017 06:15:15 -0800 Subject: [PATCH 24/36] hwmon: Constify str parameter of hwmon_ops->read_string The read_string callback is supposed to retrieve a pointer to a constant string. Signed-off-by: Jean Delvare Reviewed-by: Peter Huewe Signed-off-by: Guenter Roeck --- drivers/hwmon/hwmon.c | 2 +- include/linux/hwmon.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 28375d59cc36..dd6e17c1076b 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -186,7 +186,7 @@ static ssize_t hwmon_attr_show_string(struct device *dev, char *buf) { struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); - char *s; + const char *s; int ret; ret = hattr->ops->read_string(dev, hattr->type, hattr->attr, diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h index 88b673749121..ceb751987c40 100644 --- a/include/linux/hwmon.h +++ b/include/linux/hwmon.h @@ -337,7 +337,7 @@ struct hwmon_ops { int (*read)(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val); int (*read_string)(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, char **str); + u32 attr, int channel, const char **str); int (*write)(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val); }; From a4811b6cb4069eb2f17ffebcd29f2e5b0f76ee31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 3 Mar 2017 23:41:52 +0100 Subject: [PATCH 25/36] hwmon: (dell-smm) Add Dell XPS 15 9560 into DMI list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was reported that dell-smm-hwmon is working fine on Dell XPS 15 9560. Link: http://www.spinics.net/lists/platform-driver-x86/msg10751.html Reported-by: Vasile Dumitrescu Signed-off-by: Pali Rohár Signed-off-by: Guenter Roeck --- drivers/hwmon/dell-smm-hwmon.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 34704b0451b4..3189246302a6 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -995,6 +995,13 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = { }, .driver_data = (void *)&i8k_config_data[DELL_XPS], }, + { + .ident = "Dell XPS 15 9560", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9560"), + }, + }, { } }; From a8ddfea09566c37aabe70fbb6d07ff232982c9f4 Mon Sep 17 00:00:00 2001 From: Sam Povilus Date: Wed, 29 Mar 2017 21:46:37 -0600 Subject: [PATCH 26/36] hwmon: (ads7828) Accept optional parameters from device tree Adding the ability for the ads7828 and ads7830 to use device tree to get optional parameters instead of using platform devices. This allows people using custom boards to also use the ads7828 in a non-default manner. Signed-off-by: Sam Povilus [groeck: Fixed whitespace errors in ads7828.txt] Signed-off-by: Guenter Roeck --- .../devicetree/bindings/hwmon/ads7828.txt | 25 +++++++++++++++++++ drivers/hwmon/ads7828.c | 15 +++++++++++ 2 files changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/ads7828.txt diff --git a/Documentation/devicetree/bindings/hwmon/ads7828.txt b/Documentation/devicetree/bindings/hwmon/ads7828.txt new file mode 100644 index 000000000000..fe0cc4ad7ea9 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/ads7828.txt @@ -0,0 +1,25 @@ +ads7828 properties + +Required properties: +- compatible: Should be one of + ti,ads7828 + ti,ads7830 +- reg: I2C address + +Optional properties: + +- ti,differential-input + Set to use the device in differential mode. +- vref-supply + The external reference on the device is set to this regulators output. If it + does not exists the internal reference will be used and output by the ads78xx + on the "external vref" pin. + + Example ADS7828 node: + + ads7828: ads@48 { + comatible = "ti,ads7828"; + reg = <0x48>; + vref-supply = <&vref>; + ti,differential-input; + }; diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index b0ef66687816..898607bf682b 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -35,6 +35,7 @@ #include #include #include +#include /* The ADS7828 registers */ #define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ @@ -119,10 +120,12 @@ static int ads7828_probe(struct i2c_client *client, struct ads7828_data *data; struct device *hwmon_dev; unsigned int vref_mv = ADS7828_INT_VREF_MV; + unsigned int vref_uv; bool diff_input = false; bool ext_vref = false; unsigned int regval; enum ads7828_chips chip; + struct regulator *reg; data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); if (!data) @@ -133,6 +136,18 @@ static int ads7828_probe(struct i2c_client *client, ext_vref = pdata->ext_vref; if (ext_vref && pdata->vref_mv) vref_mv = pdata->vref_mv; + } else if (dev->of_node) { + diff_input = of_property_read_bool(dev->of_node, + "ti,differential-input"); + reg = devm_regulator_get_optional(dev, "vref"); + if (!IS_ERR(reg)) { + vref_uv = regulator_get_voltage(reg); + vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000); + if (vref_mv < ADS7828_EXT_VREF_MV_MIN || + vref_mv > ADS7828_EXT_VREF_MV_MAX) + return -EINVAL; + ext_vref = true; + } } if (client->dev.of_node) From 36df6fb6efa1e7c29debdba9bedff57c366b8347 Mon Sep 17 00:00:00 2001 From: Mahoda Ratnayaka Date: Fri, 31 Mar 2017 12:00:59 +1300 Subject: [PATCH 27/36] Documentation: dtb: lm87: Add hwmon binding documentation This patch adds lm87 hwmon device tree node documentation. Signed-off-by: Mahoda Ratnayaka Signed-off-by: Chris Packham Acked-by: Rob Herring Signed-off-by: Guenter Roeck --- .../devicetree/bindings/hwmon/lm87.txt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/lm87.txt diff --git a/Documentation/devicetree/bindings/hwmon/lm87.txt b/Documentation/devicetree/bindings/hwmon/lm87.txt new file mode 100644 index 000000000000..e1b79903f204 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/lm87.txt @@ -0,0 +1,30 @@ +*LM87 hwmon sensor. + +Required properties: +- compatible: Should be + "ti,lm87" + +- reg: I2C address + +optional properties: +- has-temp3: This configures pins 18 and 19 to be used as a second + remote temperature sensing channel. By default the pins + are configured as voltage input pins in0 and in5. + +- has-in6: When set, pin 5 is configured to be used as voltage input + in6. Otherwise the pin is set as FAN1 input. + +- has-in7: When set, pin 6 is configured to be used as voltage input + in7. Otherwise the pin is set as FAN2 input. + +- vcc-supply: a Phandle for the regulator supplying power, can be + cofigured to measure 5.0V power supply. Default is 3.3V. + +Example: + +lm87@2e { + compatible = "ti,lm87"; + reg = <0x2e>; + has-temp3; + vcc-supply = <®_5v0>; +}; From 67043d1853d67e3a03038654ab51df3aa8f66ae4 Mon Sep 17 00:00:00 2001 From: Mahoda Ratnayaka Date: Fri, 31 Mar 2017 12:01:00 +1300 Subject: [PATCH 28/36] hwmon: (lm87) Allow channel data to be set from dts file Currently there is no method for setting the channel value from the DTS file. When, the driver uses a dts file to initialize the driver platform_data is not set. As a result channel variable may not be set correctly. Without the channel variable set correctly, some of the sensors will not be initialized correctly. For example temp3 sensor sysfs entries. This implements the schema agreed with the device tree binding document. Signed-off-by: Mahoda Ratnayaka Tested-by: Chris Packham Signed-off-by: Chris Packham Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index e06faf9d3f0f..04a7a1ddb030 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -66,6 +66,7 @@ #include #include #include +#include /* * Addresses to scan @@ -855,8 +856,26 @@ static int lm87_init_client(struct i2c_client *client) { struct lm87_data *data = i2c_get_clientdata(client); int rc; + struct device_node *of_node = client->dev.of_node; + u8 val = 0; + struct regulator *vcc = NULL; - if (dev_get_platdata(&client->dev)) { + if (of_node) { + if (of_property_read_bool(of_node, "has-temp3")) + val |= CHAN_TEMP3; + if (of_property_read_bool(of_node, "has-in6")) + val |= CHAN_NO_FAN(0); + if (of_property_read_bool(of_node, "has-in7")) + val |= CHAN_NO_FAN(1); + vcc = devm_regulator_get_optional(&client->dev, "vcc"); + if (!IS_ERR(vcc)) { + if (regulator_get_voltage(vcc) == 5000000) + val |= CHAN_VCC_5V; + } + data->channel = val; + lm87_write_value(client, + LM87_REG_CHANNEL_MODE, data->channel); + } else if (dev_get_platdata(&client->dev)) { data->channel = *(u8 *)dev_get_platdata(&client->dev); lm87_write_value(client, LM87_REG_CHANNEL_MODE, data->channel); From d702b353b9d3fccbeabba96ed530ffc87f303465 Mon Sep 17 00:00:00 2001 From: Jaghathiswari Rankappagounder Natarajan Date: Tue, 4 Apr 2017 17:52:40 -0700 Subject: [PATCH 29/36] Documentation: dt-bindings: Document bindings for ASPEED AST2400/AST2500 PWM and Fan tach controller device driver This binding provides interface for adding values related to ASPEED AST2400/2500 PWM and Fan tach controller support. The PWM controller can support upto 8 PWM output ports. The Fan tach controller can support upto 16 tachometer inputs. Signed-off-by: Jaghathiswari Rankappagounder Natarajan Acked-by: Rob Herring Signed-off-by: Guenter Roeck --- .../bindings/hwmon/aspeed-pwm-tacho.txt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt diff --git a/Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt b/Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt new file mode 100644 index 000000000000..cf4460564adb --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt @@ -0,0 +1,68 @@ +ASPEED AST2400/AST2500 PWM and Fan Tacho controller device driver + +The ASPEED PWM controller can support upto 8 PWM outputs. The ASPEED Fan Tacho +controller can support upto 16 Fan tachometer inputs. + +There can be upto 8 fans supported. Each fan can have one PWM output and +one/two Fan tach inputs. + +Required properties for pwm-tacho node: +- #address-cells : should be 1. + +- #size-cells : should be 1. + +- reg : address and length of the register set for the device. + +- pinctrl-names : a pinctrl state named "default" must be defined. + +- pinctrl-0 : phandle referencing pin configuration of the PWM ports. + +- compatible : should be "aspeed,ast2400-pwm-tacho" for AST2400 and + "aspeed,ast2500-pwm-tacho" for AST2500. + +- clocks : a fixed clock providing input clock frequency(PWM + and Fan Tach clock) + +fan subnode format: +=================== +Under fan subnode there can upto 8 child nodes, with each child node +representing a fan. If there are 8 fans each fan can have one PWM port and +one/two Fan tach inputs. + +Required properties for each child node: +- reg : should specify PWM source port. + integer value in the range 0 to 7 with 0 indicating PWM port A and + 7 indicating PWM port H. + +- aspeed,fan-tach-ch : should specify the Fan tach input channel. + integer value in the range 0 through 15, with 0 indicating + Fan tach channel 0 and 15 indicating Fan tach channel 15. + Atleast one Fan tach input channel is required. + +Examples: + +pwm_tacho_fixed_clk: fixedclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; +}; + +pwm_tacho: pwmtachocontroller@1e786000 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0x1E786000 0x1000>; + compatible = "aspeed,ast2500-pwm-tacho"; + clocks = <&pwm_tacho_fixed_clk>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>; + + fan@0 { + reg = <0x00>; + aspeed,fan-tach-ch = /bits/ 8 <0x00>; + }; + + fan@1 { + reg = <0x01>; + aspeed,fan-tach-ch = /bits/ 8 <0x01 0x02>; + }; +}; From 2d7a548a3eff382da5cd743670693b7657327714 Mon Sep 17 00:00:00 2001 From: Jaghathiswari Rankappagounder Natarajan Date: Tue, 4 Apr 2017 17:52:41 -0700 Subject: [PATCH 30/36] drivers: hwmon: Support for ASPEED PWM/Fan tach The ASPEED AST2400/2500 PWM controller supports 8 PWM output ports. The ASPEED AST2400/2500 Fan tach controller supports 16 tachometer inputs. The device driver matches on the device tree node. The configuration values are read from the device tree and written to the respective registers. The driver provides a sysfs entries through which the user can configure the duty-cycle value (ranging from 0 to 100 percent) and read the fan tach rpm value. Signed-off-by: Jaghathiswari Rankappagounder Natarajan Signed-off-by: Guenter Roeck --- Documentation/hwmon/aspeed-pwm-tacho | 22 + drivers/hwmon/Kconfig | 9 + drivers/hwmon/Makefile | 1 + drivers/hwmon/aspeed-pwm-tacho.c | 835 +++++++++++++++++++++++++++ 4 files changed, 867 insertions(+) create mode 100644 Documentation/hwmon/aspeed-pwm-tacho create mode 100644 drivers/hwmon/aspeed-pwm-tacho.c diff --git a/Documentation/hwmon/aspeed-pwm-tacho b/Documentation/hwmon/aspeed-pwm-tacho new file mode 100644 index 000000000000..7cfb34977460 --- /dev/null +++ b/Documentation/hwmon/aspeed-pwm-tacho @@ -0,0 +1,22 @@ +Kernel driver aspeed-pwm-tacho +============================== + +Supported chips: + ASPEED AST2400/2500 + +Authors: + + +Description: +------------ +This driver implements support for ASPEED AST2400/2500 PWM and Fan Tacho +controller. The PWM controller supports upto 8 PWM outputs. The Fan tacho +controller supports up to 16 tachometer inputs. + +The driver provides the following sensor accesses in sysfs: + +fanX_input ro provide current fan rotation value in RPM as reported + by the fan to the device. + +pwmX rw get or set PWM fan control value. This is an integer + value between 0(off) and 255(full speed). diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0649d53f3d16..337e9078df0a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -341,6 +341,15 @@ config SENSORS_ASB100 This driver can also be built as a module. If so, the module will be called asb100. +config SENSORS_ASPEED + tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver" + help + This driver provides support for ASPEED AST2400/AST2500 PWM + and Fan Tacho controllers. + + This driver can also be built as a module. If so, the module + will be called aspeed_pwm_tacho. + config SENSORS_ATXP1 tristate "Attansic ATXP1 VID controller" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 5509edf6186a..d2bdccc000e6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o +obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c new file mode 100644 index 000000000000..48403a2115be --- /dev/null +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or later as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ASPEED PWM & FAN Tach Register Definition */ +#define ASPEED_PTCR_CTRL 0x00 +#define ASPEED_PTCR_CLK_CTRL 0x04 +#define ASPEED_PTCR_DUTY0_CTRL 0x08 +#define ASPEED_PTCR_DUTY1_CTRL 0x0c +#define ASPEED_PTCR_TYPEM_CTRL 0x10 +#define ASPEED_PTCR_TYPEM_CTRL1 0x14 +#define ASPEED_PTCR_TYPEN_CTRL 0x18 +#define ASPEED_PTCR_TYPEN_CTRL1 0x1c +#define ASPEED_PTCR_TACH_SOURCE 0x20 +#define ASPEED_PTCR_TRIGGER 0x28 +#define ASPEED_PTCR_RESULT 0x2c +#define ASPEED_PTCR_INTR_CTRL 0x30 +#define ASPEED_PTCR_INTR_STS 0x34 +#define ASPEED_PTCR_TYPEM_LIMIT 0x38 +#define ASPEED_PTCR_TYPEN_LIMIT 0x3C +#define ASPEED_PTCR_CTRL_EXT 0x40 +#define ASPEED_PTCR_CLK_CTRL_EXT 0x44 +#define ASPEED_PTCR_DUTY2_CTRL 0x48 +#define ASPEED_PTCR_DUTY3_CTRL 0x4c +#define ASPEED_PTCR_TYPEO_CTRL 0x50 +#define ASPEED_PTCR_TYPEO_CTRL1 0x54 +#define ASPEED_PTCR_TACH_SOURCE_EXT 0x60 +#define ASPEED_PTCR_TYPEO_LIMIT 0x78 + +/* ASPEED_PTCR_CTRL : 0x00 - General Control Register */ +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15 +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6 +#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15)) + +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14 +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5 +#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14)) + +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13 +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4 +#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13)) + +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12 +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3 +#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12)) + +#define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x)) + +#define ASPEED_PTCR_CTRL_PWMD_EN BIT(11) +#define ASPEED_PTCR_CTRL_PWMC_EN BIT(10) +#define ASPEED_PTCR_CTRL_PWMB_EN BIT(9) +#define ASPEED_PTCR_CTRL_PWMA_EN BIT(8) + +#define ASPEED_PTCR_CTRL_CLK_SRC BIT(1) +#define ASPEED_PTCR_CTRL_CLK_EN BIT(0) + +/* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */ +/* TYPE N */ +#define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16) +#define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24 +#define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20 +#define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16 +/* TYPE M */ +#define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0) +#define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8 +#define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4 +#define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0 + +/* + * ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control + * 0/1/2/3 register + */ +#define DUTY_CTRL_PWM2_FALL_POINT 24 +#define DUTY_CTRL_PWM2_RISE_POINT 16 +#define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16) +#define DUTY_CTRL_PWM1_FALL_POINT 8 +#define DUTY_CTRL_PWM1_RISE_POINT 0 +#define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0) + +/* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */ +#define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16)) +#define TYPE_CTRL_FAN1_MASK GENMASK(31, 0) +#define TYPE_CTRL_FAN_PERIOD 16 +#define TYPE_CTRL_FAN_MODE 4 +#define TYPE_CTRL_FAN_DIVISION 1 +#define TYPE_CTRL_FAN_TYPE_EN 1 + +/* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */ +/* bit [0,1] at 0x20, bit [2] at 0x60 */ +#define TACH_PWM_SOURCE_BIT01(x) ((x) * 2) +#define TACH_PWM_SOURCE_BIT2(x) ((x) * 2) +#define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2)) +#define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2) + +/* ASPEED_PTCR_RESULT : 0x2c - Result Register */ +#define RESULT_STATUS_MASK BIT(31) +#define RESULT_VALUE_MASK 0xfffff + +/* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */ +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15 +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6 +#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15)) + +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14 +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5 +#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14)) + +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13 +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4 +#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13)) + +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12 +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3 +#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12)) + +#define ASPEED_PTCR_CTRL_PWMH_EN BIT(11) +#define ASPEED_PTCR_CTRL_PWMG_EN BIT(10) +#define ASPEED_PTCR_CTRL_PWMF_EN BIT(9) +#define ASPEED_PTCR_CTRL_PWME_EN BIT(8) + +/* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */ +/* TYPE O */ +#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0) +#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8 +#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4 +#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0 + +#define PWM_MAX 255 + +#define M_PWM_DIV_H 0x00 +#define M_PWM_DIV_L 0x05 +#define M_PWM_PERIOD 0x5F +#define M_TACH_CLK_DIV 0x00 +#define M_TACH_MODE 0x00 +#define M_TACH_UNIT 0x1000 +#define INIT_FAN_CTRL 0xFF + +struct aspeed_pwm_tacho_data { + struct regmap *regmap; + unsigned long clk_freq; + bool pwm_present[8]; + bool fan_tach_present[16]; + u8 type_pwm_clock_unit[3]; + u8 type_pwm_clock_division_h[3]; + u8 type_pwm_clock_division_l[3]; + u8 type_fan_tach_clock_division[3]; + u16 type_fan_tach_unit[3]; + u8 pwm_port_type[8]; + u8 pwm_port_fan_ctrl[8]; + u8 fan_tach_ch_source[16]; + const struct attribute_group *groups[3]; +}; + +enum type { TYPEM, TYPEN, TYPEO }; + +struct type_params { + u32 l_value; + u32 h_value; + u32 unit_value; + u32 clk_ctrl_mask; + u32 clk_ctrl_reg; + u32 ctrl_reg; + u32 ctrl_reg1; +}; + +static const struct type_params type_params[] = { + [TYPEM] = { + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L, + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H, + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT, + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK, + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, + .ctrl_reg = ASPEED_PTCR_TYPEM_CTRL, + .ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1, + }, + [TYPEN] = { + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L, + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H, + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT, + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK, + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, + .ctrl_reg = ASPEED_PTCR_TYPEN_CTRL, + .ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1, + }, + [TYPEO] = { + .l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L, + .h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H, + .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT, + .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK, + .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT, + .ctrl_reg = ASPEED_PTCR_TYPEO_CTRL, + .ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1, + } +}; + +enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH }; + +struct pwm_port_params { + u32 pwm_en; + u32 ctrl_reg; + u32 type_part1; + u32 type_part2; + u32 type_mask; + u32 duty_ctrl_rise_point; + u32 duty_ctrl_fall_point; + u32 duty_ctrl_reg; + u32 duty_ctrl_rise_fall_mask; +}; + +static const struct pwm_port_params pwm_port_params[] = { + [PWMA] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMA_EN, + .ctrl_reg = ASPEED_PTCR_CTRL, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, + }, + [PWMB] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMB_EN, + .ctrl_reg = ASPEED_PTCR_CTRL, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, + }, + [PWMC] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMC_EN, + .ctrl_reg = ASPEED_PTCR_CTRL, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, + }, + [PWMD] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMD_EN, + .ctrl_reg = ASPEED_PTCR_CTRL, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, + }, + [PWME] = { + .pwm_en = ASPEED_PTCR_CTRL_PWME_EN, + .ctrl_reg = ASPEED_PTCR_CTRL_EXT, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, + }, + [PWMF] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMF_EN, + .ctrl_reg = ASPEED_PTCR_CTRL_EXT, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, + }, + [PWMG] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMG_EN, + .ctrl_reg = ASPEED_PTCR_CTRL_EXT, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, + }, + [PWMH] = { + .pwm_en = ASPEED_PTCR_CTRL_PWMH_EN, + .ctrl_reg = ASPEED_PTCR_CTRL_EXT, + .type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1, + .type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2, + .type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK, + .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, + .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, + .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, + .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, + } +}; + +static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + void __iomem *regs = (void __iomem *)context; + + writel(val, regs + reg); + return 0; +} + +static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + void __iomem *regs = (void __iomem *)context; + + *val = readl(regs + reg); + return 0; +} + +static const struct regmap_config aspeed_pwm_tacho_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = ASPEED_PTCR_TYPEO_LIMIT, + .reg_write = regmap_aspeed_pwm_tacho_reg_write, + .reg_read = regmap_aspeed_pwm_tacho_reg_read, + .fast_io = true, +}; + +static void aspeed_set_clock_enable(struct regmap *regmap, bool val) +{ + regmap_update_bits(regmap, ASPEED_PTCR_CTRL, + ASPEED_PTCR_CTRL_CLK_EN, + val ? ASPEED_PTCR_CTRL_CLK_EN : 0); +} + +static void aspeed_set_clock_source(struct regmap *regmap, int val) +{ + regmap_update_bits(regmap, ASPEED_PTCR_CTRL, + ASPEED_PTCR_CTRL_CLK_SRC, + val ? ASPEED_PTCR_CTRL_CLK_SRC : 0); +} + +static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type, + u8 div_high, u8 div_low, u8 unit) +{ + u32 reg_value = ((div_high << type_params[type].h_value) | + (div_low << type_params[type].l_value) | + (unit << type_params[type].unit_value)); + + regmap_update_bits(regmap, type_params[type].clk_ctrl_reg, + type_params[type].clk_ctrl_mask, reg_value); +} + +static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port, + bool enable) +{ + regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, + pwm_port_params[pwm_port].pwm_en, + enable ? pwm_port_params[pwm_port].pwm_en : 0); +} + +static void aspeed_set_pwm_port_type(struct regmap *regmap, + u8 pwm_port, u8 type) +{ + u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1; + + reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2; + + regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, + pwm_port_params[pwm_port].type_mask, reg_value); +} + +static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap, + u8 pwm_port, u8 rising, + u8 falling) +{ + u32 reg_value = (rising << + pwm_port_params[pwm_port].duty_ctrl_rise_point); + reg_value |= (falling << + pwm_port_params[pwm_port].duty_ctrl_fall_point); + + regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg, + pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask, + reg_value); +} + +static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type, + bool enable) +{ + regmap_update_bits(regmap, type_params[type].ctrl_reg, + TYPE_CTRL_FAN_TYPE_EN, + enable ? TYPE_CTRL_FAN_TYPE_EN : 0); +} + +static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type, + u8 mode, u16 unit, u8 division) +{ + u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) | + (unit << TYPE_CTRL_FAN_PERIOD) | + (division << TYPE_CTRL_FAN_DIVISION)); + + regmap_update_bits(regmap, type_params[type].ctrl_reg, + TYPE_CTRL_FAN_MASK, reg_value); + regmap_update_bits(regmap, type_params[type].ctrl_reg1, + TYPE_CTRL_FAN1_MASK, unit << 16); +} + +static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch, + bool enable) +{ + regmap_update_bits(regmap, ASPEED_PTCR_CTRL, + ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch), + enable ? + ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0); +} + +static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch, + u8 fan_tach_ch_source) +{ + u32 reg_value1 = ((fan_tach_ch_source & 0x3) << + TACH_PWM_SOURCE_BIT01(fan_tach_ch)); + u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) << + TACH_PWM_SOURCE_BIT2(fan_tach_ch)); + + regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE, + TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch), + reg_value1); + + regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT, + TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch), + reg_value2); +} + +static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv, + u8 index, u8 fan_ctrl) +{ + u16 period, dc_time_on; + + period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]]; + period += 1; + dc_time_on = (fan_ctrl * period) / PWM_MAX; + + if (dc_time_on == 0) { + aspeed_set_pwm_port_enable(priv->regmap, index, false); + } else { + if (dc_time_on == period) + dc_time_on = 0; + + aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0, + dc_time_on); + aspeed_set_pwm_port_enable(priv->regmap, index, true); + } +} + +static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data + *priv, u8 type) +{ + u32 clk; + u16 tacho_unit; + u8 clk_unit, div_h, div_l, tacho_div; + + clk = priv->clk_freq; + clk_unit = priv->type_pwm_clock_unit[type]; + div_h = priv->type_pwm_clock_division_h[type]; + div_h = 0x1 << div_h; + div_l = priv->type_pwm_clock_division_l[type]; + if (div_l == 0) + div_l = 1; + else + div_l = div_l * 2; + + tacho_unit = priv->type_fan_tach_unit[type]; + tacho_div = priv->type_fan_tach_clock_division[type]; + + tacho_div = 0x4 << (tacho_div * 2); + return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit); +} + +static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, + u8 fan_tach_ch) +{ + u32 raw_data, tach_div, clk_source, sec, val; + u8 fan_tach_ch_source, type; + + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); + + fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch]; + type = priv->pwm_port_type[fan_tach_ch_source]; + + sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type)); + msleep(sec); + + regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val); + raw_data = val & RESULT_VALUE_MASK; + tach_div = priv->type_fan_tach_clock_division[type]; + tach_div = 0x4 << (tach_div * 2); + clk_source = priv->clk_freq; + + if (raw_data == 0) + return 0; + + return (clk_source * 60) / (2 * raw_data * tach_div); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int index = sensor_attr->index; + int ret; + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); + long fan_ctrl; + + ret = kstrtol(buf, 10, &fan_ctrl); + if (ret != 0) + return ret; + + if (fan_ctrl < 0 || fan_ctrl > PWM_MAX) + return -EINVAL; + + if (priv->pwm_port_fan_ctrl[index] == fan_ctrl) + return count; + + priv->pwm_port_fan_ctrl[index] = fan_ctrl; + aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl); + + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int index = sensor_attr->index; + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]); +} + +static ssize_t show_rpm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int index = sensor_attr->index; + u32 rpm; + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); + + rpm = aspeed_get_fan_tach_ch_rpm(priv, index); + + return sprintf(buf, "%u\n", rpm); +} + +static umode_t pwm_is_visible(struct kobject *kobj, + struct attribute *a, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); + + if (!priv->pwm_present[index]) + return 0; + return a->mode; +} + +static umode_t fan_dev_is_visible(struct kobject *kobj, + struct attribute *a, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); + + if (!priv->fan_tach_present[index]) + return 0; + return a->mode; +} + +static SENSOR_DEVICE_ATTR(pwm0, 0644, + show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm1, 0644, + show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm2, 0644, + show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm3, 0644, + show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm4, 0644, + show_pwm, set_pwm, 4); +static SENSOR_DEVICE_ATTR(pwm5, 0644, + show_pwm, set_pwm, 5); +static SENSOR_DEVICE_ATTR(pwm6, 0644, + show_pwm, set_pwm, 6); +static SENSOR_DEVICE_ATTR(pwm7, 0644, + show_pwm, set_pwm, 7); +static struct attribute *pwm_dev_attrs[] = { + &sensor_dev_attr_pwm0.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + &sensor_dev_attr_pwm6.dev_attr.attr, + &sensor_dev_attr_pwm7.dev_attr.attr, + NULL, +}; + +static const struct attribute_group pwm_dev_group = { + .attrs = pwm_dev_attrs, + .is_visible = pwm_is_visible, +}; + +static SENSOR_DEVICE_ATTR(fan0_input, 0444, + show_rpm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_input, 0444, + show_rpm, NULL, 1); +static SENSOR_DEVICE_ATTR(fan2_input, 0444, + show_rpm, NULL, 2); +static SENSOR_DEVICE_ATTR(fan3_input, 0444, + show_rpm, NULL, 3); +static SENSOR_DEVICE_ATTR(fan4_input, 0444, + show_rpm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan5_input, 0444, + show_rpm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan6_input, 0444, + show_rpm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan7_input, 0444, + show_rpm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan8_input, 0444, + show_rpm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan9_input, 0444, + show_rpm, NULL, 9); +static SENSOR_DEVICE_ATTR(fan10_input, 0444, + show_rpm, NULL, 10); +static SENSOR_DEVICE_ATTR(fan11_input, 0444, + show_rpm, NULL, 11); +static SENSOR_DEVICE_ATTR(fan12_input, 0444, + show_rpm, NULL, 12); +static SENSOR_DEVICE_ATTR(fan13_input, 0444, + show_rpm, NULL, 13); +static SENSOR_DEVICE_ATTR(fan14_input, 0444, + show_rpm, NULL, 14); +static SENSOR_DEVICE_ATTR(fan15_input, 0444, + show_rpm, NULL, 15); +static struct attribute *fan_dev_attrs[] = { + &sensor_dev_attr_fan0_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan14_input.dev_attr.attr, + &sensor_dev_attr_fan15_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group fan_dev_group = { + .attrs = fan_dev_attrs, + .is_visible = fan_dev_is_visible, +}; + +/* + * The clock type is type M : + * The PWM frequency = 24MHz / (type M clock division L bit * + * type M clock division H bit * (type M PWM period bit + 1)) + */ +static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv) +{ + priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H; + priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L; + priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD; + aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H, + M_PWM_DIV_L, M_PWM_PERIOD); + aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true); + priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV; + priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT; + aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE, + M_TACH_UNIT, M_TACH_CLK_DIV); +} + +static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv, + u8 pwm_port) +{ + aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true); + priv->pwm_present[pwm_port] = true; + + priv->pwm_port_type[pwm_port] = TYPEM; + aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM); + + priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL; + aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL); +} + +static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv, + u8 *fan_tach_ch, + int count, + u8 pwm_source) +{ + u8 val, index; + + for (val = 0; val < count; val++) { + index = fan_tach_ch[val]; + aspeed_set_fan_tach_ch_enable(priv->regmap, index, true); + priv->fan_tach_present[index] = true; + priv->fan_tach_ch_source[index] = pwm_source; + aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source); + } +} + +static int aspeed_create_fan(struct device *dev, + struct device_node *child, + struct aspeed_pwm_tacho_data *priv) +{ + u8 *fan_tach_ch; + u32 pwm_port; + int ret, count; + + ret = of_property_read_u32(child, "reg", &pwm_port); + if (ret) + return ret; + aspeed_create_pwm_port(priv, (u8)pwm_port); + + count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); + if (count < 1) + return -EINVAL; + fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count, + GFP_KERNEL); + if (!fan_tach_ch) + return -ENOMEM; + ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch", + fan_tach_ch, count); + if (ret) + return ret; + aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port); + + return 0; +} + +static int aspeed_pwm_tacho_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np, *child; + struct aspeed_pwm_tacho_data *priv; + void __iomem *regs; + struct resource *res; + struct device *hwmon; + struct clk *clk; + int ret; + + np = dev->of_node; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENOENT; + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, + &aspeed_pwm_tacho_regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0); + regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0); + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) + return -ENODEV; + priv->clk_freq = clk_get_rate(clk); + aspeed_set_clock_enable(priv->regmap, true); + aspeed_set_clock_source(priv->regmap, 0); + + aspeed_create_type(priv); + + for_each_child_of_node(np, child) { + ret = aspeed_create_fan(dev, child, priv); + of_node_put(child); + if (ret) + return ret; + } + of_node_put(np); + + priv->groups[0] = &pwm_dev_group; + priv->groups[1] = &fan_dev_group; + priv->groups[2] = NULL; + hwmon = devm_hwmon_device_register_with_groups(dev, + "aspeed_pwm_tacho", + priv, priv->groups); + return PTR_ERR_OR_ZERO(hwmon); +} + +static const struct of_device_id of_pwm_tacho_match_table[] = { + { .compatible = "aspeed,ast2400-pwm-tacho", }, + { .compatible = "aspeed,ast2500-pwm-tacho", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table); + +static struct platform_driver aspeed_pwm_tacho_driver = { + .probe = aspeed_pwm_tacho_probe, + .driver = { + .name = "aspeed_pwm_tacho", + .of_match_table = of_pwm_tacho_match_table, + }, +}; + +module_platform_driver(aspeed_pwm_tacho_driver); + +MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan "); +MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver"); +MODULE_LICENSE("GPL"); From 0439bf71c383a6b5a325dfd30414539b87ddf933 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 12 Apr 2017 21:21:38 -0300 Subject: [PATCH 31/36] hwmon: (lm87) Remove unused I2C devices driver_data The I2C device ID entries set a .driver_data but this data is never looked up by the driver. So don't set it and also remove the enum. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 04a7a1ddb030..c0766e7392d3 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -75,8 +75,6 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; -enum chips { lm87, adm1024 }; - /* * The LM87 registers */ @@ -981,8 +979,8 @@ static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id) */ static const struct i2c_device_id lm87_id[] = { - { "lm87", lm87 }, - { "adm1024", adm1024 }, + { "lm87", 0 }, + { "adm1024", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, lm87_id); From a02c24a321583e7970393488834501e15a69b656 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 12 Apr 2017 21:21:39 -0300 Subject: [PATCH 32/36] hwmon: (lm87) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index c0766e7392d3..b48d30760388 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -985,10 +985,18 @@ static const struct i2c_device_id lm87_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm87_id); +static const struct of_device_id lm87_of_match[] = { + { .compatible = "ti,lm87" }, + { .compatible = "adi,adm1024" }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm87_of_match); + static struct i2c_driver lm87_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "lm87", + .of_match_table = lm87_of_match, }, .probe = lm87_probe, .id_table = lm87_id, From bdaf9c40b2d1d67617b259c59ce1858eda54b4ce Mon Sep 17 00:00:00 2001 From: Joe Schaack Date: Tue, 18 Apr 2017 07:15:50 -0500 Subject: [PATCH 33/36] hwmon: (ina209) Handled signed registers The shunt voltage and current registers are signed 16-bit values so handle them as such. Signed-off-by: Joe Schaack Reviewed-by: Aaron Sierra Signed-off-by: Guenter Roeck --- drivers/hwmon/ina209.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c index c5f20f03e0be..aa0768ce8aea 100644 --- a/drivers/hwmon/ina209.c +++ b/drivers/hwmon/ina209.c @@ -117,7 +117,7 @@ static long ina209_from_reg(const u8 reg, const u16 val) case INA209_SHUNT_VOLTAGE_POS_WARN: case INA209_SHUNT_VOLTAGE_NEG_WARN: /* LSB=10 uV. Convert to mV. */ - return DIV_ROUND_CLOSEST(val, 100); + return DIV_ROUND_CLOSEST((s16)val, 100); case INA209_BUS_VOLTAGE: case INA209_BUS_VOLTAGE_MAX_PEAK: @@ -146,7 +146,7 @@ static long ina209_from_reg(const u8 reg, const u16 val) case INA209_CURRENT: /* LSB=1 mA (selected). Is in mA */ - return val; + return (s16)val; } /* programmer goofed */ From 4abdf38d206fdc22f7a3f7bf79eef78734ec84ab Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Sat, 22 Apr 2017 07:08:09 +1200 Subject: [PATCH 34/36] hwmon: (adt7475) set start bit in probe The ADT7475 and ADT7476 have the STRT bit cleared by default[1]. Before any monitoring activities the STRT bit needs to be set. Logically this needs to happen before any of the sensors are read so the probe() function seems the best place for it. [1] - https://www.onsemi.com/pub/Collateral/ADT7475-D.PDF Signed-off-by: Chris Packham Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index fcfa48222145..c803e3c5fcd4 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -59,6 +59,8 @@ #define REG_VENDID 0x3E #define REG_DEVID2 0x3F +#define REG_CONFIG1 0x40 + #define REG_STATUS1 0x41 #define REG_STATUS2 0x42 @@ -1371,6 +1373,17 @@ static int adt7475_probe(struct i2c_client *client, for (i = 0; i < ADT7475_PWM_COUNT; i++) adt7475_read_pwm(client, i); + /* Start monitoring */ + switch (chip) { + case adt7475: + case adt7476: + i2c_smbus_write_byte_data(client, REG_CONFIG1, + adt7475_read(REG_CONFIG1) | 0x01); + break; + default: + break; + } + ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group); if (ret) return ret; From 39c382a3109400f5abb5adc2040510e75f93b4cb Mon Sep 17 00:00:00 2001 From: Rahul Bedarkar Date: Sun, 23 Apr 2017 19:40:51 +0530 Subject: [PATCH 35/36] hwmon: (tmp103) Use SIMPLE_DEV_PM_OPS helper macro Replace ifdefs with SIMPLE_DEV_PM_OPS helper macro. Signed-off-by: Rahul Bedarkar Acked-by: Heiko Schocher Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp103.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index d0bb28b0d4c3..7f85b14544df 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -150,8 +150,7 @@ static int tmp103_probe(struct i2c_client *client, return PTR_ERR_OR_ZERO(hwmon_dev); } -#ifdef CONFIG_PM -static int tmp103_suspend(struct device *dev) +static int __maybe_unused tmp103_suspend(struct device *dev) { struct regmap *regmap = dev_get_drvdata(dev); @@ -159,7 +158,7 @@ static int tmp103_suspend(struct device *dev) TMP103_CONF_SD_MASK, 0); } -static int tmp103_resume(struct device *dev) +static int __maybe_unused tmp103_resume(struct device *dev) { struct regmap *regmap = dev_get_drvdata(dev); @@ -167,15 +166,7 @@ static int tmp103_resume(struct device *dev) TMP103_CONF_SD_MASK, TMP103_CONF_SD); } -static const struct dev_pm_ops tmp103_dev_pm_ops = { - .suspend = tmp103_suspend, - .resume = tmp103_resume, -}; - -#define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops) -#else -#define TMP103_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ +static SIMPLE_DEV_PM_OPS(tmp103_dev_pm_ops, tmp103_suspend, tmp103_resume); static const struct i2c_device_id tmp103_id[] = { { "tmp103", 0 }, @@ -193,7 +184,7 @@ static struct i2c_driver tmp103_driver = { .driver = { .name = "tmp103", .of_match_table = of_match_ptr(tmp103_of_match), - .pm = TMP103_DEV_PM_OPS, + .pm = &tmp103_dev_pm_ops, }, .probe = tmp103_probe, .id_table = tmp103_id, From 09d9d82745801ca69c00f91f89c8f047b586e8cc Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 27 Apr 2017 17:30:06 +0200 Subject: [PATCH 36/36] hwmon: (twl4030-madc) drop driver This driver is no longer needed: * It has no mainline users * It has no DT support and OMAP is DT only * iio-hwmon can be used for madc, which also works with DT Signed-off-by: Sebastian Reichel Acked-by: Guenter Roeck Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 10 --- drivers/hwmon/Makefile | 1 - drivers/hwmon/twl4030-madc-hwmon.c | 118 ----------------------------- 3 files changed, 129 deletions(-) delete mode 100644 drivers/hwmon/twl4030-madc-hwmon.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 337e9078df0a..22d5eafd6815 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1652,16 +1652,6 @@ config SENSORS_TMP421 This driver can also be built as a module. If so, the module will be called tmp421. -config SENSORS_TWL4030_MADC - tristate "Texas Instruments TWL4030 MADC Hwmon" - depends on TWL4030_MADC - help - If you say yes here you get hwmon support for triton - TWL4030-MADC. - - This driver can also be built as a module. If so it will be called - twl4030-madc-hwmon. - config SENSORS_VEXPRESS tristate "Versatile Express" depends on VEXPRESS_CONFIG diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d2bdccc000e6..d4641a9f16c1 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -158,7 +158,6 @@ obj-$(CONFIG_SENSORS_TMP103) += tmp103.o obj-$(CONFIG_SENSORS_TMP108) += tmp108.o obj-$(CONFIG_SENSORS_TMP401) += tmp401.o obj-$(CONFIG_SENSORS_TMP421) += tmp421.o -obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress-hwmon.o obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c deleted file mode 100644 index b5caf7fdb487..000000000000 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * TWL4030 MADC Hwmon driver-This driver monitors the real time - * conversion of analog signals like battery temperature, - * battery type, battery level etc. User can ask for the conversion on a - * particular channel using the sysfs nodes. - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * J Keerthy - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * sysfs hook function - */ -static ssize_t madc_read(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req = { - .channels = 1 << attr->index, - .method = TWL4030_MADC_SW2, - .type = TWL4030_MADC_WAIT, - }; - long val; - - val = twl4030_madc_conversion(&req); - if (val < 0) - return val; - - return sprintf(buf, "%d\n", req.rbuf[attr->index]); -} - -/* sysfs nodes to read individual channels from user side */ -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9); -static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); - -static struct attribute *twl4030_madc_attrs[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_curr10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in15_input.dev_attr.attr, - NULL -}; -ATTRIBUTE_GROUPS(twl4030_madc); - -static int twl4030_madc_hwmon_probe(struct platform_device *pdev) -{ - struct device *hwmon; - - hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, - "twl4030_madc", NULL, - twl4030_madc_groups); - return PTR_ERR_OR_ZERO(hwmon); -} - -static struct platform_driver twl4030_madc_hwmon_driver = { - .probe = twl4030_madc_hwmon_probe, - .driver = { - .name = "twl4030_madc_hwmon", - }, -}; - -module_platform_driver(twl4030_madc_hwmon_driver); - -MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("J Keerthy"); -MODULE_ALIAS("platform:twl4030_madc_hwmon");