aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorUwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>2012-03-23 05:02:19 -0400
committerJean Delvare <khali@endymion.delvare>2012-03-23 05:02:19 -0400
commit0c2732152a5813a870d0b96f0844f4dfe1436519 (patch)
treee9ba0ad606d58085217b9a179b9bb508fc4d1d0a /drivers/hwmon
parentcb88200490d723048994753ed59dc0abddc51e77 (diff)
hwmon: (mc13783-adc) Add support for the MC13892 PMIC
Based on a patch by David Jander that mostly did s/mc13783/mc13xxx/ . Additionally use dev_get_drvdata instead of to_platform_device + platform_get_drvdata in mc13783_adc_read (spotted by Jean Delvare). Cc: David Jander <david.jander@protonic.nl> Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig6
-rw-r--r--drivers/hwmon/mc13783-adc.c101
2 files changed, 80 insertions, 27 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index fc3f4e1cad2c..7190a3f4a827 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1360,10 +1360,10 @@ config SENSORS_APPLESMC
1360 the awesome power of applesmc. 1360 the awesome power of applesmc.
1361 1361
1362config SENSORS_MC13783_ADC 1362config SENSORS_MC13783_ADC
1363 tristate "Freescale MC13783 ADC" 1363 tristate "Freescale MC13783/MC13892 ADC"
1364 depends on MFD_MC13783 1364 depends on MFD_MC13XXX
1365 help 1365 help
1366 Support for the A/D converter on MC13783 PMIC. 1366 Support for the A/D converter on MC13783 and MC13892 PMIC.
1367 1367
1368if ACPI 1368if ACPI
1369 1369
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 04d13b31aacd..6c6b240a782e 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for the Freescale Semiconductor MC13783 adc. 2 * Driver for the ADC on Freescale Semiconductor MC13783 and MC13892 PMICs.
3 * 3 *
4 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. 4 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
5 * Copyright (C) 2009 Sascha Hauer, Pengutronix 5 * Copyright (C) 2009 Sascha Hauer, Pengutronix
@@ -18,7 +18,7 @@
18 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */ 19 */
20 20
21#include <linux/mfd/mc13783.h> 21#include <linux/mfd/mc13xxx.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/hwmon-sysfs.h> 23#include <linux/hwmon-sysfs.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
@@ -28,24 +28,30 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/err.h> 29#include <linux/err.h>
30 30
31#define MC13783_ADC_NAME "mc13783-adc" 31#define DRIVER_NAME "mc13783-adc"
32
33/* platform device id driver data */
34#define MC13783_ADC_16CHANS 1
35#define MC13783_ADC_BPDIV2 2
32 36
33struct mc13783_adc_priv { 37struct mc13783_adc_priv {
34 struct mc13xxx *mc13xxx; 38 struct mc13xxx *mc13xxx;
35 struct device *hwmon_dev; 39 struct device *hwmon_dev;
40 char name[10];
36}; 41};
37 42
38static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute 43static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
39 *devattr, char *buf) 44 *devattr, char *buf)
40{ 45{
41 return sprintf(buf, "mc13783_adc\n"); 46 struct mc13783_adc_priv *priv = dev_get_drvdata(dev);
47
48 return sprintf(buf, "%s\n", priv->name);
42} 49}
43 50
44static int mc13783_adc_read(struct device *dev, 51static int mc13783_adc_read(struct device *dev,
45 struct device_attribute *devattr, unsigned int *val) 52 struct device_attribute *devattr, unsigned int *val)
46{ 53{
47 struct platform_device *pdev = to_platform_device(dev); 54 struct mc13783_adc_priv *priv = dev_get_drvdata(dev);
48 struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
49 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 55 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
50 unsigned int channel = attr->index; 56 unsigned int channel = attr->index;
51 unsigned int sample[4]; 57 unsigned int sample[4];
@@ -68,16 +74,21 @@ static ssize_t mc13783_adc_read_bp(struct device *dev,
68 struct device_attribute *devattr, char *buf) 74 struct device_attribute *devattr, char *buf)
69{ 75{
70 unsigned val; 76 unsigned val;
77 struct platform_device *pdev = to_platform_device(dev);
78 kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
71 int ret = mc13783_adc_read(dev, devattr, &val); 79 int ret = mc13783_adc_read(dev, devattr, &val);
72 80
73 if (ret) 81 if (ret)
74 return ret; 82 return ret;
75 83
76 /* 84 if (driver_data & MC13783_ADC_BPDIV2)
77 * BP (channel 2) reports with offset 2.4V to the actual value to fit 85 val = DIV_ROUND_CLOSEST(val * 9, 2);
78 * the input range of the ADC. unit = 2.25mV = 9/4 mV. 86 else
79 */ 87 /*
80 val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400; 88 * BP (channel 2) reports with offset 2.4V to the actual value
89 * to fit the input range of the ADC. unit = 2.25mV = 9/4 mV.
90 */
91 val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400;
81 92
82 return sprintf(buf, "%u\n", val); 93 return sprintf(buf, "%u\n", val);
83} 94}
@@ -114,12 +125,21 @@ static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13);
114static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14); 125static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14);
115static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15); 126static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15);
116 127
117static struct attribute *mc13783_attr[] = { 128static struct attribute *mc13783_attr_base[] = {
118 &dev_attr_name.attr, 129 &dev_attr_name.attr,
119 &sensor_dev_attr_in2_input.dev_attr.attr, 130 &sensor_dev_attr_in2_input.dev_attr.attr,
120 &sensor_dev_attr_in5_input.dev_attr.attr, 131 &sensor_dev_attr_in5_input.dev_attr.attr,
121 &sensor_dev_attr_in6_input.dev_attr.attr, 132 &sensor_dev_attr_in6_input.dev_attr.attr,
122 &sensor_dev_attr_in7_input.dev_attr.attr, 133 &sensor_dev_attr_in7_input.dev_attr.attr,
134 NULL
135};
136
137static const struct attribute_group mc13783_group_base = {
138 .attrs = mc13783_attr_base,
139};
140
141/* these are only used if MC13783_ADC_16CHANS is provided in driver data */
142static struct attribute *mc13783_attr_16chans[] = {
123 &sensor_dev_attr_in8_input.dev_attr.attr, 143 &sensor_dev_attr_in8_input.dev_attr.attr,
124 &sensor_dev_attr_in9_input.dev_attr.attr, 144 &sensor_dev_attr_in9_input.dev_attr.attr,
125 &sensor_dev_attr_in10_input.dev_attr.attr, 145 &sensor_dev_attr_in10_input.dev_attr.attr,
@@ -127,8 +147,8 @@ static struct attribute *mc13783_attr[] = {
127 NULL 147 NULL
128}; 148};
129 149
130static const struct attribute_group mc13783_group = { 150static const struct attribute_group mc13783_group_16chans = {
131 .attrs = mc13783_attr, 151 .attrs = mc13783_attr_16chans,
132}; 152};
133 153
134/* last four channels may be occupied by the touchscreen */ 154/* last four channels may be occupied by the touchscreen */
@@ -156,24 +176,37 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
156{ 176{
157 struct mc13783_adc_priv *priv; 177 struct mc13783_adc_priv *priv;
158 int ret; 178 int ret;
179 const struct platform_device_id *id = platform_get_device_id(pdev);
180 char *dash;
159 181
160 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 182 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
161 if (!priv) 183 if (!priv)
162 return -ENOMEM; 184 return -ENOMEM;
163 185
164 priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); 186 priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
187 snprintf(priv->name, ARRAY_SIZE(priv->name), "%s", id->name);
188 dash = strchr(priv->name, '-');
189 if (dash)
190 *dash = '\0';
165 191
166 platform_set_drvdata(pdev, priv); 192 platform_set_drvdata(pdev, priv);
167 193
168 /* Register sysfs hooks */ 194 /* Register sysfs hooks */
169 ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group); 195 ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_base);
170 if (ret) 196 if (ret)
171 goto out_err_create1; 197 goto out_err_create_base;
198
199 if (id->driver_data & MC13783_ADC_16CHANS) {
200 ret = sysfs_create_group(&pdev->dev.kobj,
201 &mc13783_group_16chans);
202 if (ret)
203 goto out_err_create_16chans;
204 }
172 205
173 if (!mc13783_adc_use_touchscreen(pdev)) { 206 if (!mc13783_adc_use_touchscreen(pdev)) {
174 ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); 207 ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts);
175 if (ret) 208 if (ret)
176 goto out_err_create2; 209 goto out_err_create_ts;
177 } 210 }
178 211
179 priv->hwmon_dev = hwmon_device_register(&pdev->dev); 212 priv->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -184,17 +217,20 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
184 goto out_err_register; 217 goto out_err_register;
185 } 218 }
186 219
187
188 return 0; 220 return 0;
189 221
190out_err_register: 222out_err_register:
191 223
192 if (!mc13783_adc_use_touchscreen(pdev)) 224 if (!mc13783_adc_use_touchscreen(pdev))
193 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); 225 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
194out_err_create2: 226out_err_create_ts:
195 227
196 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); 228 if (id->driver_data & MC13783_ADC_16CHANS)
197out_err_create1: 229 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans);
230out_err_create_16chans:
231
232 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base);
233out_err_create_base:
198 234
199 platform_set_drvdata(pdev, NULL); 235 platform_set_drvdata(pdev, NULL);
200 kfree(priv); 236 kfree(priv);
@@ -205,13 +241,17 @@ out_err_create1:
205static int __devexit mc13783_adc_remove(struct platform_device *pdev) 241static int __devexit mc13783_adc_remove(struct platform_device *pdev)
206{ 242{
207 struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); 243 struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
244 kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
208 245
209 hwmon_device_unregister(priv->hwmon_dev); 246 hwmon_device_unregister(priv->hwmon_dev);
210 247
211 if (!mc13783_adc_use_touchscreen(pdev)) 248 if (!mc13783_adc_use_touchscreen(pdev))
212 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); 249 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
213 250
214 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); 251 if (driver_data & MC13783_ADC_16CHANS)
252 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans);
253
254 sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base);
215 255
216 platform_set_drvdata(pdev, NULL); 256 platform_set_drvdata(pdev, NULL);
217 kfree(priv); 257 kfree(priv);
@@ -219,12 +259,26 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev)
219 return 0; 259 return 0;
220} 260}
221 261
262static const struct platform_device_id mc13783_adc_idtable[] = {
263 {
264 .name = "mc13783-adc",
265 .driver_data = MC13783_ADC_16CHANS,
266 }, {
267 .name = "mc13892-adc",
268 .driver_data = MC13783_ADC_BPDIV2,
269 }, {
270 /* sentinel */
271 }
272};
273MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
274
222static struct platform_driver mc13783_adc_driver = { 275static struct platform_driver mc13783_adc_driver = {
223 .remove = __devexit_p(mc13783_adc_remove), 276 .remove = __devexit_p(mc13783_adc_remove),
224 .driver = { 277 .driver = {
225 .owner = THIS_MODULE, 278 .owner = THIS_MODULE,
226 .name = MC13783_ADC_NAME, 279 .name = DRIVER_NAME,
227 }, 280 },
281 .id_table = mc13783_adc_idtable,
228}; 282};
229 283
230static int __init mc13783_adc_init(void) 284static int __init mc13783_adc_init(void)
@@ -243,4 +297,3 @@ module_exit(mc13783_adc_exit);
243MODULE_DESCRIPTION("MC13783 ADC driver"); 297MODULE_DESCRIPTION("MC13783 ADC driver");
244MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); 298MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
245MODULE_LICENSE("GPL"); 299MODULE_LICENSE("GPL");
246MODULE_ALIAS("platform:" MC13783_ADC_NAME);