brintos

brintos / linux-shallow public Read only

0
0
Text · 19.6 KiB · b535290 Raw
710 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ntc_thermistor.c - NTC Thermistors4 *5 *  Copyright (C) 2010 Samsung Electronics6 *  MyungJoo Ham <myungjoo.ham@samsung.com>7 */8 9#include <linux/slab.h>10#include <linux/module.h>11#include <linux/math64.h>12#include <linux/mod_devicetable.h>13#include <linux/platform_device.h>14#include <linux/property.h>15#include <linux/err.h>16#include <linux/fixp-arith.h>17#include <linux/iio/consumer.h>18#include <linux/hwmon.h>19 20enum ntc_thermistor_type {21	TYPE_B57330V2103,22	TYPE_B57891S0103,23	TYPE_NCPXXWB473,24	TYPE_NCPXXWF104,25	TYPE_NCPXXWL333,26	TYPE_NCPXXXH103,27};28 29struct ntc_compensation {30	int		temp_c;31	unsigned int	ohm;32};33 34/*35 * Used as index in a zero-terminated array, holes not allowed so36 * that NTC_LAST is the first empty array entry.37 */38enum {39	NTC_B57330V2103,40	NTC_B57891S0103,41	NTC_NCP03WB473,42	NTC_NCP03WF104,43	NTC_NCP15WB473,44	NTC_NCP15WL333,45	NTC_NCP15XH103,46	NTC_NCP18WB473,47	NTC_NCP21WB473,48	NTC_SSG1404001221,49	NTC_LAST,50};51 52static const struct platform_device_id ntc_thermistor_id[] = {53	[NTC_B57330V2103]     = { "b57330v2103",     TYPE_B57330V2103 },54	[NTC_B57891S0103]     = { "b57891s0103",     TYPE_B57891S0103 },55	[NTC_NCP03WB473]      = { "ncp03wb473",      TYPE_NCPXXWB473 },56	[NTC_NCP03WF104]      = { "ncp03wf104",      TYPE_NCPXXWF104 },57	[NTC_NCP15WB473]      = { "ncp15wb473",      TYPE_NCPXXWB473 },58	[NTC_NCP15WL333]      = { "ncp15wl333",      TYPE_NCPXXWL333 },59	[NTC_NCP15XH103]      = { "ncp15xh103",      TYPE_NCPXXXH103 },60	[NTC_NCP18WB473]      = { "ncp18wb473",      TYPE_NCPXXWB473 },61	[NTC_NCP21WB473]      = { "ncp21wb473",      TYPE_NCPXXWB473 },62	[NTC_SSG1404001221]   = { "ssg1404_001221",  TYPE_NCPXXWB473 },63	[NTC_LAST]            = { },64};65MODULE_DEVICE_TABLE(platform, ntc_thermistor_id);66 67/*68 * A compensation table should be sorted by the values of .ohm69 * in descending order.70 * The following compensation tables are from the specification of Murata NTC71 * Thermistors Datasheet72 */73static const struct ntc_compensation ncpXXwb473[] = {74	{ .temp_c	= -40, .ohm	= 1747920 },75	{ .temp_c	= -35, .ohm	= 1245428 },76	{ .temp_c	= -30, .ohm	= 898485 },77	{ .temp_c	= -25, .ohm	= 655802 },78	{ .temp_c	= -20, .ohm	= 483954 },79	{ .temp_c	= -15, .ohm	= 360850 },80	{ .temp_c	= -10, .ohm	= 271697 },81	{ .temp_c	= -5, .ohm	= 206463 },82	{ .temp_c	= 0, .ohm	= 158214 },83	{ .temp_c	= 5, .ohm	= 122259 },84	{ .temp_c	= 10, .ohm	= 95227 },85	{ .temp_c	= 15, .ohm	= 74730 },86	{ .temp_c	= 20, .ohm	= 59065 },87	{ .temp_c	= 25, .ohm	= 47000 },88	{ .temp_c	= 30, .ohm	= 37643 },89	{ .temp_c	= 35, .ohm	= 30334 },90	{ .temp_c	= 40, .ohm	= 24591 },91	{ .temp_c	= 45, .ohm	= 20048 },92	{ .temp_c	= 50, .ohm	= 16433 },93	{ .temp_c	= 55, .ohm	= 13539 },94	{ .temp_c	= 60, .ohm	= 11209 },95	{ .temp_c	= 65, .ohm	= 9328 },96	{ .temp_c	= 70, .ohm	= 7798 },97	{ .temp_c	= 75, .ohm	= 6544 },98	{ .temp_c	= 80, .ohm	= 5518 },99	{ .temp_c	= 85, .ohm	= 4674 },100	{ .temp_c	= 90, .ohm	= 3972 },101	{ .temp_c	= 95, .ohm	= 3388 },102	{ .temp_c	= 100, .ohm	= 2902 },103	{ .temp_c	= 105, .ohm	= 2494 },104	{ .temp_c	= 110, .ohm	= 2150 },105	{ .temp_c	= 115, .ohm	= 1860 },106	{ .temp_c	= 120, .ohm	= 1615 },107	{ .temp_c	= 125, .ohm	= 1406 },108};109static const struct ntc_compensation ncpXXwl333[] = {110	{ .temp_c	= -40, .ohm	= 1610154 },111	{ .temp_c	= -35, .ohm	= 1130850 },112	{ .temp_c	= -30, .ohm	= 802609 },113	{ .temp_c	= -25, .ohm	= 575385 },114	{ .temp_c	= -20, .ohm	= 416464 },115	{ .temp_c	= -15, .ohm	= 304219 },116	{ .temp_c	= -10, .ohm	= 224193 },117	{ .temp_c	= -5, .ohm	= 166623 },118	{ .temp_c	= 0, .ohm	= 124850 },119	{ .temp_c	= 5, .ohm	= 94287 },120	{ .temp_c	= 10, .ohm	= 71747 },121	{ .temp_c	= 15, .ohm	= 54996 },122	{ .temp_c	= 20, .ohm	= 42455 },123	{ .temp_c	= 25, .ohm	= 33000 },124	{ .temp_c	= 30, .ohm	= 25822 },125	{ .temp_c	= 35, .ohm	= 20335 },126	{ .temp_c	= 40, .ohm	= 16115 },127	{ .temp_c	= 45, .ohm	= 12849 },128	{ .temp_c	= 50, .ohm	= 10306 },129	{ .temp_c	= 55, .ohm	= 8314 },130	{ .temp_c	= 60, .ohm	= 6746 },131	{ .temp_c	= 65, .ohm	= 5503 },132	{ .temp_c	= 70, .ohm	= 4513 },133	{ .temp_c	= 75, .ohm	= 3721 },134	{ .temp_c	= 80, .ohm	= 3084 },135	{ .temp_c	= 85, .ohm	= 2569 },136	{ .temp_c	= 90, .ohm	= 2151 },137	{ .temp_c	= 95, .ohm	= 1809 },138	{ .temp_c	= 100, .ohm	= 1529 },139	{ .temp_c	= 105, .ohm	= 1299 },140	{ .temp_c	= 110, .ohm	= 1108 },141	{ .temp_c	= 115, .ohm	= 949 },142	{ .temp_c	= 120, .ohm	= 817 },143	{ .temp_c	= 125, .ohm	= 707 },144};145 146static const struct ntc_compensation ncpXXwf104[] = {147	{ .temp_c	= -40, .ohm	= 4397119 },148	{ .temp_c	= -35, .ohm	= 3088599 },149	{ .temp_c	= -30, .ohm	= 2197225 },150	{ .temp_c	= -25, .ohm	= 1581881 },151	{ .temp_c	= -20, .ohm	= 1151037 },152	{ .temp_c	= -15, .ohm	= 846579 },153	{ .temp_c	= -10, .ohm	= 628988 },154	{ .temp_c	= -5, .ohm	= 471632 },155	{ .temp_c	= 0, .ohm	= 357012 },156	{ .temp_c	= 5, .ohm	= 272500 },157	{ .temp_c	= 10, .ohm	= 209710 },158	{ .temp_c	= 15, .ohm	= 162651 },159	{ .temp_c	= 20, .ohm	= 127080 },160	{ .temp_c	= 25, .ohm	= 100000 },161	{ .temp_c	= 30, .ohm	= 79222 },162	{ .temp_c	= 35, .ohm	= 63167 },163	{ .temp_c	= 40, .ohm	= 50677 },164	{ .temp_c	= 45, .ohm	= 40904 },165	{ .temp_c	= 50, .ohm	= 33195 },166	{ .temp_c	= 55, .ohm	= 27091 },167	{ .temp_c	= 60, .ohm	= 22224 },168	{ .temp_c	= 65, .ohm	= 18323 },169	{ .temp_c	= 70, .ohm	= 15184 },170	{ .temp_c	= 75, .ohm	= 12635 },171	{ .temp_c	= 80, .ohm	= 10566 },172	{ .temp_c	= 85, .ohm	= 8873 },173	{ .temp_c	= 90, .ohm	= 7481 },174	{ .temp_c	= 95, .ohm	= 6337 },175	{ .temp_c	= 100, .ohm	= 5384 },176	{ .temp_c	= 105, .ohm	= 4594 },177	{ .temp_c	= 110, .ohm	= 3934 },178	{ .temp_c	= 115, .ohm	= 3380 },179	{ .temp_c	= 120, .ohm	= 2916 },180	{ .temp_c	= 125, .ohm	= 2522 },181};182 183static const struct ntc_compensation ncpXXxh103[] = {184	{ .temp_c	= -40, .ohm	= 247565 },185	{ .temp_c	= -35, .ohm	= 181742 },186	{ .temp_c	= -30, .ohm	= 135128 },187	{ .temp_c	= -25, .ohm	= 101678 },188	{ .temp_c	= -20, .ohm	= 77373 },189	{ .temp_c	= -15, .ohm	= 59504 },190	{ .temp_c	= -10, .ohm	= 46222 },191	{ .temp_c	= -5, .ohm	= 36244 },192	{ .temp_c	= 0, .ohm	= 28674 },193	{ .temp_c	= 5, .ohm	= 22878 },194	{ .temp_c	= 10, .ohm	= 18399 },195	{ .temp_c	= 15, .ohm	= 14910 },196	{ .temp_c	= 20, .ohm	= 12169 },197	{ .temp_c	= 25, .ohm	= 10000 },198	{ .temp_c	= 30, .ohm	= 8271 },199	{ .temp_c	= 35, .ohm	= 6883 },200	{ .temp_c	= 40, .ohm	= 5762 },201	{ .temp_c	= 45, .ohm	= 4851 },202	{ .temp_c	= 50, .ohm	= 4105 },203	{ .temp_c	= 55, .ohm	= 3492 },204	{ .temp_c	= 60, .ohm	= 2985 },205	{ .temp_c	= 65, .ohm	= 2563 },206	{ .temp_c	= 70, .ohm	= 2211 },207	{ .temp_c	= 75, .ohm	= 1915 },208	{ .temp_c	= 80, .ohm	= 1666 },209	{ .temp_c	= 85, .ohm	= 1454 },210	{ .temp_c	= 90, .ohm	= 1275 },211	{ .temp_c	= 95, .ohm	= 1121 },212	{ .temp_c	= 100, .ohm	= 990 },213	{ .temp_c	= 105, .ohm	= 876 },214	{ .temp_c	= 110, .ohm	= 779 },215	{ .temp_c	= 115, .ohm	= 694 },216	{ .temp_c	= 120, .ohm	= 620 },217	{ .temp_c	= 125, .ohm	= 556 },218};219 220/*221 * The following compensation tables are from the specifications in EPCOS NTC222 * Thermistors Datasheets223 */224static const struct ntc_compensation b57330v2103[] = {225	{ .temp_c	= -40, .ohm	= 190030 },226	{ .temp_c	= -35, .ohm	= 145360 },227	{ .temp_c	= -30, .ohm	= 112060 },228	{ .temp_c	= -25, .ohm	= 87041 },229	{ .temp_c	= -20, .ohm	= 68104 },230	{ .temp_c	= -15, .ohm	= 53665 },231	{ .temp_c	= -10, .ohm	= 42576 },232	{ .temp_c	= -5, .ohm	= 34001 },233	{ .temp_c	= 0, .ohm	= 27326 },234	{ .temp_c	= 5, .ohm	= 22096 },235	{ .temp_c	= 10, .ohm	= 17973 },236	{ .temp_c	= 15, .ohm	= 14703 },237	{ .temp_c	= 20, .ohm	= 12090 },238	{ .temp_c	= 25, .ohm	= 10000 },239	{ .temp_c	= 30, .ohm	= 8311 },240	{ .temp_c	= 35, .ohm	= 6941 },241	{ .temp_c	= 40, .ohm	= 5825 },242	{ .temp_c	= 45, .ohm	= 4911 },243	{ .temp_c	= 50, .ohm	= 4158 },244	{ .temp_c	= 55, .ohm	= 3536 },245	{ .temp_c	= 60, .ohm	= 3019 },246	{ .temp_c	= 65, .ohm	= 2588 },247	{ .temp_c	= 70, .ohm	= 2227 },248	{ .temp_c	= 75, .ohm	= 1924 },249	{ .temp_c	= 80, .ohm	= 1668 },250	{ .temp_c	= 85, .ohm	= 1451 },251	{ .temp_c	= 90, .ohm	= 1266 },252	{ .temp_c	= 95, .ohm	= 1108 },253	{ .temp_c	= 100, .ohm	= 973 },254	{ .temp_c	= 105, .ohm	= 857 },255	{ .temp_c	= 110, .ohm	= 757 },256	{ .temp_c	= 115, .ohm	= 671 },257	{ .temp_c	= 120, .ohm	= 596 },258	{ .temp_c	= 125, .ohm	= 531 },259};260 261static const struct ntc_compensation b57891s0103[] = {262	{ .temp_c	= -55.0, .ohm	= 878900 },263	{ .temp_c	= -50.0, .ohm	= 617590 },264	{ .temp_c	= -45.0, .ohm	= 439340 },265	{ .temp_c	= -40.0, .ohm	= 316180 },266	{ .temp_c	= -35.0, .ohm	= 230060 },267	{ .temp_c	= -30.0, .ohm	= 169150 },268	{ .temp_c	= -25.0, .ohm	= 125550 },269	{ .temp_c	= -20.0, .ohm	= 94143 },270	{ .temp_c	= -15.0, .ohm	= 71172 },271	{ .temp_c	= -10.0, .ohm	= 54308 },272	{ .temp_c	= -5.0, .ohm	= 41505 },273	{ .temp_c	= 0.0, .ohm	= 32014 },274	{ .temp_c	= 5.0, .ohm	= 25011 },275	{ .temp_c	= 10.0, .ohm	= 19691 },276	{ .temp_c	= 15.0, .ohm	= 15618 },277	{ .temp_c	= 20.0, .ohm	= 12474 },278	{ .temp_c	= 25.0, .ohm	= 10000 },279	{ .temp_c	= 30.0, .ohm	= 8080 },280	{ .temp_c	= 35.0, .ohm	= 6569 },281	{ .temp_c	= 40.0, .ohm	= 5372 },282	{ .temp_c	= 45.0, .ohm	= 4424 },283	{ .temp_c	= 50.0, .ohm	= 3661 },284	{ .temp_c	= 55.0, .ohm	= 3039 },285	{ .temp_c	= 60.0, .ohm	= 2536 },286	{ .temp_c	= 65.0, .ohm	= 2128 },287	{ .temp_c	= 70.0, .ohm	= 1794 },288	{ .temp_c	= 75.0, .ohm	= 1518 },289	{ .temp_c	= 80.0, .ohm	= 1290 },290	{ .temp_c	= 85.0, .ohm	= 1100 },291	{ .temp_c	= 90.0, .ohm	= 942 },292	{ .temp_c	= 95.0, .ohm	= 809 },293	{ .temp_c	= 100.0, .ohm	= 697 },294	{ .temp_c	= 105.0, .ohm	= 604 },295	{ .temp_c	= 110.0, .ohm	= 525 },296	{ .temp_c	= 115.0, .ohm	= 457 },297	{ .temp_c	= 120.0, .ohm	= 400 },298	{ .temp_c	= 125.0, .ohm	= 351 },299	{ .temp_c	= 130.0, .ohm	= 308 },300	{ .temp_c	= 135.0, .ohm	= 272 },301	{ .temp_c	= 140.0, .ohm	= 240 },302	{ .temp_c	= 145.0, .ohm	= 213 },303	{ .temp_c	= 150.0, .ohm	= 189 },304	{ .temp_c	= 155.0, .ohm	= 168 },305};306 307struct ntc_type {308	const struct ntc_compensation *comp;309	int n_comp;310};311 312#define NTC_TYPE(ntc, compensation) \313[(ntc)] = { .comp = (compensation), .n_comp = ARRAY_SIZE(compensation) }314 315static const struct ntc_type ntc_type[] = {316	NTC_TYPE(TYPE_B57330V2103, b57330v2103),317	NTC_TYPE(TYPE_B57891S0103, b57891s0103),318	NTC_TYPE(TYPE_NCPXXWB473,  ncpXXwb473),319	NTC_TYPE(TYPE_NCPXXWF104,  ncpXXwf104),320	NTC_TYPE(TYPE_NCPXXWL333,  ncpXXwl333),321	NTC_TYPE(TYPE_NCPXXXH103,  ncpXXxh103),322};323 324/*325 * pullup_uV, pullup_ohm, pulldown_ohm, and connect are required.326 *327 * How to setup pullup_ohm, pulldown_ohm, and connect is328 * described at Documentation/hwmon/ntc_thermistor.rst329 *330 * pullup/down_ohm: 0 for infinite / not-connected331 *332 * chan: iio_channel pointer to communicate with the ADC which the333 * thermistor is using for conversion of the analog values.334 */335struct ntc_data {336	const struct ntc_compensation *comp;337	int n_comp;338	unsigned int pullup_uv;339	unsigned int pullup_ohm;340	unsigned int pulldown_ohm;341	enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;342	struct iio_channel *chan;343};344 345static int ntc_adc_iio_read(struct ntc_data *data)346{347	struct iio_channel *channel = data->chan;348	int uv, ret;349 350	ret = iio_read_channel_processed_scale(channel, &uv, 1000);351	if (ret < 0) {352		int raw;353 354		/*355		 * This fallback uses a raw read and then356		 * assumes the ADC is 12 bits, scaling with357		 * a factor 1000 to get to microvolts.358		 */359		ret = iio_read_channel_raw(channel, &raw);360		if (ret < 0) {361			pr_err("read channel() error: %d\n", ret);362			return ret;363		}364		ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);365		if (ret < 0) {366			/* Assume 12 bit ADC with vref at pullup_uv */367			uv = (data->pullup_uv * (s64)raw) >> 12;368		}369	}370 371	return uv;372}373 374static inline u64 div64_u64_safe(u64 dividend, u64 divisor)375{376	if (divisor == 0 && dividend == 0)377		return 0;378	if (divisor == 0)379		return UINT_MAX;380	return div64_u64(dividend, divisor);381}382 383static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)384{385	u32 puv = data->pullup_uv;386	u64 n, puo, pdo;387	puo = data->pullup_ohm;388	pdo = data->pulldown_ohm;389 390	if (uv == 0)391		return (data->connect == NTC_CONNECTED_POSITIVE) ?392			INT_MAX : 0;393	if (uv >= puv)394		return (data->connect == NTC_CONNECTED_POSITIVE) ?395			0 : INT_MAX;396 397	if (data->connect == NTC_CONNECTED_POSITIVE && puo == 0)398		n = div_u64(pdo * (puv - uv), uv);399	else if (data->connect == NTC_CONNECTED_GROUND && pdo == 0)400		n = div_u64(puo * uv, puv - uv);401	else if (data->connect == NTC_CONNECTED_POSITIVE)402		n = div64_u64_safe(pdo * puo * (puv - uv),403				puo * uv - pdo * (puv - uv));404	else405		n = div64_u64_safe(pdo * puo * uv, pdo * (puv - uv) - puo * uv);406 407	if (n > INT_MAX)408		n = INT_MAX;409	return n;410}411 412static void lookup_comp(struct ntc_data *data, unsigned int ohm,413			int *i_low, int *i_high)414{415	int start, end, mid;416 417	/*418	 * Handle special cases: Resistance is higher than or equal to419	 * resistance in first table entry, or resistance is lower or equal420	 * to resistance in last table entry.421	 * In these cases, return i_low == i_high, either pointing to the422	 * beginning or to the end of the table depending on the condition.423	 */424	if (ohm >= data->comp[0].ohm) {425		*i_low = 0;426		*i_high = 0;427		return;428	}429	if (ohm <= data->comp[data->n_comp - 1].ohm) {430		*i_low = data->n_comp - 1;431		*i_high = data->n_comp - 1;432		return;433	}434 435	/* Do a binary search on compensation table */436	start = 0;437	end = data->n_comp;438	while (start < end) {439		mid = start + (end - start) / 2;440		/*441		 * start <= mid < end442		 * data->comp[start].ohm > ohm >= data->comp[end].ohm443		 *444		 * We could check for "ohm == data->comp[mid].ohm" here, but445		 * that is a quite unlikely condition, and we would have to446		 * check again after updating start. Check it at the end instead447		 * for simplicity.448		 */449		if (ohm >= data->comp[mid].ohm) {450			end = mid;451		} else {452			start = mid + 1;453			/*454			 * ohm >= data->comp[start].ohm might be true here,455			 * since we set start to mid + 1. In that case, we are456			 * done. We could keep going, but the condition is quite457			 * likely to occur, so it is worth checking for it.458			 */459			if (ohm >= data->comp[start].ohm)460				end = start;461		}462		/*463		 * start <= end464		 * data->comp[start].ohm >= ohm >= data->comp[end].ohm465		 */466	}467	/*468	 * start == end469	 * ohm >= data->comp[end].ohm470	 */471	*i_low = end;472	if (ohm == data->comp[end].ohm)473		*i_high = end;474	else475		*i_high = end - 1;476}477 478static int get_temp_mc(struct ntc_data *data, unsigned int ohm)479{480	int low, high;481	int temp;482 483	lookup_comp(data, ohm, &low, &high);484	/*485	 * First multiplying the table temperatures with 1000 to get to486	 * millicentigrades (which is what we want) and then interpolating487	 * will give the best precision.488	 */489	temp = fixp_linear_interpolate(data->comp[low].ohm,490				       data->comp[low].temp_c * 1000,491				       data->comp[high].ohm,492				       data->comp[high].temp_c * 1000,493				       ohm);494	return temp;495}496 497static int ntc_thermistor_get_ohm(struct ntc_data *data)498{499	int read_uv;500 501	read_uv = ntc_adc_iio_read(data);502	if (read_uv < 0)503		return read_uv;504	return get_ohm_of_thermistor(data, read_uv);505}506 507static int ntc_read(struct device *dev, enum hwmon_sensor_types type,508		    u32 attr, int channel, long *val)509{510	struct ntc_data *data = dev_get_drvdata(dev);511	int ohm;512 513	switch (type) {514	case hwmon_temp:515		switch (attr) {516		case hwmon_temp_input:517			ohm = ntc_thermistor_get_ohm(data);518			if (ohm < 0)519				return ohm;520			*val = get_temp_mc(data, ohm);521			return 0;522		case hwmon_temp_type:523			*val = 4;524			return 0;525		default:526			break;527		}528		break;529	default:530		break;531	}532	return -EINVAL;533}534 535static umode_t ntc_is_visible(const void *data, enum hwmon_sensor_types type,536			      u32 attr, int channel)537{538	if (type == hwmon_temp) {539		switch (attr) {540		case hwmon_temp_input:541		case hwmon_temp_type:542			return 0444;543		default:544			break;545		}546	}547	return 0;548}549 550static const struct hwmon_channel_info * const ntc_info[] = {551	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),552	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_TYPE),553	NULL554};555 556static const struct hwmon_ops ntc_hwmon_ops = {557	.is_visible = ntc_is_visible,558	.read = ntc_read,559};560 561static const struct hwmon_chip_info ntc_chip_info = {562	.ops = &ntc_hwmon_ops,563	.info = ntc_info,564};565 566static int ntc_thermistor_parse_props(struct device *dev,567				      struct ntc_data *data)568{569	struct iio_channel *chan;570	enum iio_chan_type type;571	int ret;572 573	chan = devm_iio_channel_get(dev, NULL);574	if (IS_ERR(chan))575		return PTR_ERR(chan);576 577	ret = iio_get_channel_type(chan, &type);578	if (ret < 0)579		return ret;580 581	if (type != IIO_VOLTAGE)582		return -EINVAL;583 584	ret = device_property_read_u32(dev, "pullup-uv", &data->pullup_uv);585	if (ret)586		return dev_err_probe(dev,  ret, "pullup-uv not specified\n");587 588	ret = device_property_read_u32(dev, "pullup-ohm", &data->pullup_ohm);589	if (ret)590		return dev_err_probe(dev,  ret, "pullup-ohm not specified\n");591 592	ret = device_property_read_u32(dev, "pulldown-ohm", &data->pulldown_ohm);593	if (ret)594		return dev_err_probe(dev,  ret, "pulldown-ohm not specified\n");595 596	if (device_property_read_bool(dev, "connected-positive"))597		data->connect = NTC_CONNECTED_POSITIVE;598	else /* status change should be possible if not always on. */599		data->connect = NTC_CONNECTED_GROUND;600 601	data->chan = chan;602 603	return 0;604}605 606static int ntc_thermistor_probe(struct platform_device *pdev)607{608	struct device *dev = &pdev->dev;609	const struct platform_device_id *pdev_id;610	struct device *hwmon_dev;611	struct ntc_data *data;612	int ret;613 614	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);615	if (!data)616		return -ENOMEM;617 618	ret = ntc_thermistor_parse_props(dev, data);619	if (ret)620		return ret;621 622	if (data->pullup_uv == 0 ||623	    (data->pullup_ohm == 0 && data->connect ==624	     NTC_CONNECTED_GROUND) ||625	    (data->pulldown_ohm == 0 && data->connect ==626	     NTC_CONNECTED_POSITIVE) ||627	    (data->connect != NTC_CONNECTED_POSITIVE &&628	     data->connect != NTC_CONNECTED_GROUND)) {629		dev_err(dev, "Required data to use NTC driver not supplied.\n");630		return -EINVAL;631	}632 633	pdev_id = device_get_match_data(dev);634 635	if (pdev_id->driver_data >= ARRAY_SIZE(ntc_type)) {636		dev_err(dev, "Unknown device type: %lu(%s)\n",637				pdev_id->driver_data, pdev_id->name);638		return -EINVAL;639	}640 641	data->comp   = ntc_type[pdev_id->driver_data].comp;642	data->n_comp = ntc_type[pdev_id->driver_data].n_comp;643 644	hwmon_dev = devm_hwmon_device_register_with_info(dev, pdev_id->name,645							 data, &ntc_chip_info,646							 NULL);647	if (IS_ERR(hwmon_dev)) {648		dev_err(dev, "unable to register as hwmon device.\n");649		return PTR_ERR(hwmon_dev);650	}651 652	dev_info(dev, "Thermistor type: %s successfully probed.\n",653		 pdev_id->name);654 655	return 0;656}657 658static const struct of_device_id ntc_match[] = {659	{ .compatible = "epcos,b57330v2103",660		.data = &ntc_thermistor_id[NTC_B57330V2103]},661	{ .compatible = "epcos,b57891s0103",662		.data = &ntc_thermistor_id[NTC_B57891S0103] },663	{ .compatible = "murata,ncp03wb473",664		.data = &ntc_thermistor_id[NTC_NCP03WB473] },665	{ .compatible = "murata,ncp03wf104",666		.data = &ntc_thermistor_id[NTC_NCP03WF104] },667	{ .compatible = "murata,ncp15wb473",668		.data = &ntc_thermistor_id[NTC_NCP15WB473] },669	{ .compatible = "murata,ncp15wl333",670		.data = &ntc_thermistor_id[NTC_NCP15WL333] },671	{ .compatible = "murata,ncp15xh103",672		.data = &ntc_thermistor_id[NTC_NCP15XH103] },673	{ .compatible = "murata,ncp18wb473",674		.data = &ntc_thermistor_id[NTC_NCP18WB473] },675	{ .compatible = "murata,ncp21wb473",676		.data = &ntc_thermistor_id[NTC_NCP21WB473] },677	{ .compatible = "samsung,1404-001221",678		.data = &ntc_thermistor_id[NTC_SSG1404001221] },679 680	/* Usage of vendor name "ntc" is deprecated */681	{ .compatible = "ntc,ncp03wb473",682		.data = &ntc_thermistor_id[NTC_NCP03WB473] },683	{ .compatible = "ntc,ncp15wb473",684		.data = &ntc_thermistor_id[NTC_NCP15WB473] },685	{ .compatible = "ntc,ncp15wl333",686		.data = &ntc_thermistor_id[NTC_NCP15WL333] },687	{ .compatible = "ntc,ncp18wb473",688		.data = &ntc_thermistor_id[NTC_NCP18WB473] },689	{ .compatible = "ntc,ncp21wb473",690		.data = &ntc_thermistor_id[NTC_NCP21WB473] },691	{ },692};693MODULE_DEVICE_TABLE(of, ntc_match);694 695static struct platform_driver ntc_thermistor_driver = {696	.driver = {697		.name = "ntc-thermistor",698		.of_match_table = ntc_match,699	},700	.probe = ntc_thermistor_probe,701	.id_table = ntc_thermistor_id,702};703 704module_platform_driver(ntc_thermistor_driver);705 706MODULE_DESCRIPTION("NTC Thermistor Driver");707MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");708MODULE_LICENSE("GPL");709MODULE_ALIAS("platform:ntc-thermistor");710