2626#include <linux/math64.h>
2727#include <linux/platform_device.h>
2828#include <linux/err.h>
29+ #include <linux/of.h>
30+ #include <linux/of_device.h>
2931
3032#include <linux/platform_data/ntc_thermistor.h>
3133
34+ #include <linux/iio/iio.h>
35+ #include <linux/iio/machine.h>
36+ #include <linux/iio/driver.h>
37+ #include <linux/iio/consumer.h>
38+
3239#include <linux/hwmon.h>
3340#include <linux/hwmon-sysfs.h>
3441
@@ -37,6 +44,15 @@ struct ntc_compensation {
3744 unsigned int ohm ;
3845};
3946
47+ static const struct platform_device_id ntc_thermistor_id [] = {
48+ { "ncp15wb473" , TYPE_NCPXXWB473 },
49+ { "ncp18wb473" , TYPE_NCPXXWB473 },
50+ { "ncp21wb473" , TYPE_NCPXXWB473 },
51+ { "ncp03wb473" , TYPE_NCPXXWB473 },
52+ { "ncp15wl333" , TYPE_NCPXXWL333 },
53+ { },
54+ };
55+
4056/*
4157 * A compensation table should be sorted by the values of .ohm
4258 * in descending order.
@@ -125,6 +141,92 @@ struct ntc_data {
125141 char name [PLATFORM_NAME_SIZE ];
126142};
127143
144+ #ifdef CONFIG_OF
145+ static int ntc_adc_iio_read (struct ntc_thermistor_platform_data * pdata )
146+ {
147+ struct iio_channel * channel = pdata -> chan ;
148+ unsigned int result ;
149+ int val , ret ;
150+
151+ ret = iio_read_channel_raw (channel , & val );
152+ if (ret < 0 ) {
153+ pr_err ("read channel() error: %d\n" , ret );
154+ return ret ;
155+ }
156+
157+ /* unit: mV */
158+ result = pdata -> pullup_uV * val ;
159+ result >>= 12 ;
160+
161+ return result ;
162+ }
163+
164+ static const struct of_device_id ntc_match [] = {
165+ { .compatible = "ntc,ncp15wb473" ,
166+ .data = & ntc_thermistor_id [TYPE_NCPXXWB473 ] },
167+ { .compatible = "ntc,ncp18wb473" ,
168+ .data = & ntc_thermistor_id [TYPE_NCPXXWB473 ] },
169+ { .compatible = "ntc,ncp21wb473" ,
170+ .data = & ntc_thermistor_id [TYPE_NCPXXWB473 ] },
171+ { .compatible = "ntc,ncp03wb473" ,
172+ .data = & ntc_thermistor_id [TYPE_NCPXXWB473 ] },
173+ { .compatible = "ntc,ncp15wl333" ,
174+ .data = & ntc_thermistor_id [TYPE_NCPXXWL333 ] },
175+ { },
176+ };
177+ MODULE_DEVICE_TABLE (of , ntc_match );
178+
179+ static struct ntc_thermistor_platform_data *
180+ ntc_thermistor_parse_dt (struct platform_device * pdev )
181+ {
182+ struct iio_channel * chan ;
183+ struct device_node * np = pdev -> dev .of_node ;
184+ struct ntc_thermistor_platform_data * pdata ;
185+
186+ if (!np )
187+ return NULL ;
188+
189+ pdata = devm_kzalloc (& pdev -> dev , sizeof (* pdata ), GFP_KERNEL );
190+ if (!pdata )
191+ return ERR_PTR (- ENOMEM );
192+
193+ chan = iio_channel_get (& pdev -> dev , NULL );
194+ if (IS_ERR (chan ))
195+ return ERR_CAST (chan );
196+
197+ if (of_property_read_u32 (np , "pullup-uv" , & pdata -> pullup_uV ))
198+ return ERR_PTR (- ENODEV );
199+ if (of_property_read_u32 (np , "pullup-ohm" , & pdata -> pullup_ohm ))
200+ return ERR_PTR (- ENODEV );
201+ if (of_property_read_u32 (np , "pulldown-ohm" , & pdata -> pulldown_ohm ))
202+ return ERR_PTR (- ENODEV );
203+
204+ if (of_find_property (np , "connected-positive" , NULL ))
205+ pdata -> connect = NTC_CONNECTED_POSITIVE ;
206+ else /* status change should be possible if not always on. */
207+ pdata -> connect = NTC_CONNECTED_GROUND ;
208+
209+ pdata -> chan = chan ;
210+ pdata -> read_uV = ntc_adc_iio_read ;
211+
212+ return pdata ;
213+ }
214+ static void ntc_iio_channel_release (struct ntc_thermistor_platform_data * pdata )
215+ {
216+ if (pdata -> chan )
217+ iio_channel_release (pdata -> chan );
218+ }
219+ #else
220+ static struct ntc_thermistor_platform_data *
221+ ntc_thermistor_parse_dt (struct platform_device * pdev )
222+ {
223+ return NULL ;
224+ }
225+
226+ static void ntc_iio_channel_release (struct ntc_thermistor_platform_data * pdata )
227+ { }
228+ #endif
229+
128230static inline u64 div64_u64_safe (u64 dividend , u64 divisor )
129231{
130232 if (divisor == 0 && dividend == 0 )
@@ -259,7 +361,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
259361 return data -> pdata -> read_ohm ();
260362
261363 if (data -> pdata -> read_uV ) {
262- read_uV = data -> pdata -> read_uV ();
364+ read_uV = data -> pdata -> read_uV (data -> pdata );
263365 if (read_uV < 0 )
264366 return read_uV ;
265367 return get_ohm_of_thermistor (data , read_uV );
@@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {
311413
312414static int ntc_thermistor_probe (struct platform_device * pdev )
313415{
416+ const struct of_device_id * of_id =
417+ of_match_device (of_match_ptr (ntc_match ), & pdev -> dev );
418+ const struct platform_device_id * pdev_id ;
419+ struct ntc_thermistor_platform_data * pdata ;
314420 struct ntc_data * data ;
315- struct ntc_thermistor_platform_data * pdata = pdev -> dev .platform_data ;
316- int ret = 0 ;
421+ int ret ;
422+
423+ pdata = ntc_thermistor_parse_dt (pdev );
424+ if (IS_ERR (pdata ))
425+ return PTR_ERR (pdata );
426+ else if (pdata == NULL )
427+ pdata = pdev -> dev .platform_data ;
317428
318429 if (!pdata ) {
319430 dev_err (& pdev -> dev , "No platform init data supplied.\n" );
@@ -349,11 +460,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
349460 if (!data )
350461 return - ENOMEM ;
351462
463+ pdev_id = of_id ? of_id -> data : platform_get_device_id (pdev );
464+
352465 data -> dev = & pdev -> dev ;
353466 data -> pdata = pdata ;
354- strlcpy (data -> name , pdev -> id_entry -> name , sizeof (data -> name ));
467+ strlcpy (data -> name , pdev_id -> name , sizeof (data -> name ));
355468
356- switch (pdev -> id_entry -> driver_data ) {
469+ switch (pdev_id -> driver_data ) {
357470 case TYPE_NCPXXWB473 :
358471 data -> comp = ncpXXwb473 ;
359472 data -> n_comp = ARRAY_SIZE (ncpXXwb473 );
@@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
364477 break ;
365478 default :
366479 dev_err (& pdev -> dev , "Unknown device type: %lu(%s)\n" ,
367- pdev -> id_entry -> driver_data ,
368- pdev -> id_entry -> name );
480+ pdev_id -> driver_data , pdev_id -> name );
369481 return - EINVAL ;
370482 }
371483
@@ -384,39 +496,34 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
384496 goto err_after_sysfs ;
385497 }
386498
387- dev_info (& pdev -> dev , "Thermistor %s:%d ( type: %s/%lu) successfully probed.\n" ,
388- pdev -> name , pdev -> id , pdev -> id_entry -> name ,
389- pdev -> id_entry -> driver_data );
499+ dev_info (& pdev -> dev , "Thermistor type: %s successfully probed.\n" ,
500+ pdev -> name );
501+
390502 return 0 ;
391503err_after_sysfs :
392504 sysfs_remove_group (& data -> dev -> kobj , & ntc_attr_group );
505+ ntc_iio_channel_release (pdata );
393506 return ret ;
394507}
395508
396509static int ntc_thermistor_remove (struct platform_device * pdev )
397510{
398511 struct ntc_data * data = platform_get_drvdata (pdev );
512+ struct ntc_thermistor_platform_data * pdata = data -> pdata ;
399513
400514 hwmon_device_unregister (data -> hwmon_dev );
401515 sysfs_remove_group (& data -> dev -> kobj , & ntc_attr_group );
516+ ntc_iio_channel_release (pdata );
402517 platform_set_drvdata (pdev , NULL );
403518
404519 return 0 ;
405520}
406521
407- static const struct platform_device_id ntc_thermistor_id [] = {
408- { "ncp15wb473" , TYPE_NCPXXWB473 },
409- { "ncp18wb473" , TYPE_NCPXXWB473 },
410- { "ncp21wb473" , TYPE_NCPXXWB473 },
411- { "ncp03wb473" , TYPE_NCPXXWB473 },
412- { "ncp15wl333" , TYPE_NCPXXWL333 },
413- { },
414- };
415-
416522static struct platform_driver ntc_thermistor_driver = {
417523 .driver = {
418524 .name = "ntc-thermistor" ,
419525 .owner = THIS_MODULE ,
526+ .of_match_table = of_match_ptr (ntc_match ),
420527 },
421528 .probe = ntc_thermistor_probe ,
422529 .remove = ntc_thermistor_remove ,
0 commit comments