0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011 #include <linux/math64.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/property.h>
0015 #include <linux/err.h>
0016 #include <linux/fixp-arith.h>
0017 #include <linux/iio/consumer.h>
0018 #include <linux/hwmon.h>
0019
0020 enum ntc_thermistor_type {
0021 TYPE_B57330V2103,
0022 TYPE_B57891S0103,
0023 TYPE_NCPXXWB473,
0024 TYPE_NCPXXWF104,
0025 TYPE_NCPXXWL333,
0026 TYPE_NCPXXXH103,
0027 };
0028
0029 struct ntc_compensation {
0030 int temp_c;
0031 unsigned int ohm;
0032 };
0033
0034
0035
0036
0037
0038 enum {
0039 NTC_B57330V2103,
0040 NTC_B57891S0103,
0041 NTC_NCP03WB473,
0042 NTC_NCP03WF104,
0043 NTC_NCP15WB473,
0044 NTC_NCP15WL333,
0045 NTC_NCP15XH103,
0046 NTC_NCP18WB473,
0047 NTC_NCP21WB473,
0048 NTC_SSG1404001221,
0049 NTC_LAST,
0050 };
0051
0052 static const struct platform_device_id ntc_thermistor_id[] = {
0053 [NTC_B57330V2103] = { "b57330v2103", TYPE_B57330V2103 },
0054 [NTC_B57891S0103] = { "b57891s0103", TYPE_B57891S0103 },
0055 [NTC_NCP03WB473] = { "ncp03wb473", TYPE_NCPXXWB473 },
0056 [NTC_NCP03WF104] = { "ncp03wf104", TYPE_NCPXXWF104 },
0057 [NTC_NCP15WB473] = { "ncp15wb473", TYPE_NCPXXWB473 },
0058 [NTC_NCP15WL333] = { "ncp15wl333", TYPE_NCPXXWL333 },
0059 [NTC_NCP15XH103] = { "ncp15xh103", TYPE_NCPXXXH103 },
0060 [NTC_NCP18WB473] = { "ncp18wb473", TYPE_NCPXXWB473 },
0061 [NTC_NCP21WB473] = { "ncp21wb473", TYPE_NCPXXWB473 },
0062 [NTC_SSG1404001221] = { "ssg1404_001221", TYPE_NCPXXWB473 },
0063 [NTC_LAST] = { },
0064 };
0065
0066
0067
0068
0069
0070
0071
0072 static const struct ntc_compensation ncpXXwb473[] = {
0073 { .temp_c = -40, .ohm = 1747920 },
0074 { .temp_c = -35, .ohm = 1245428 },
0075 { .temp_c = -30, .ohm = 898485 },
0076 { .temp_c = -25, .ohm = 655802 },
0077 { .temp_c = -20, .ohm = 483954 },
0078 { .temp_c = -15, .ohm = 360850 },
0079 { .temp_c = -10, .ohm = 271697 },
0080 { .temp_c = -5, .ohm = 206463 },
0081 { .temp_c = 0, .ohm = 158214 },
0082 { .temp_c = 5, .ohm = 122259 },
0083 { .temp_c = 10, .ohm = 95227 },
0084 { .temp_c = 15, .ohm = 74730 },
0085 { .temp_c = 20, .ohm = 59065 },
0086 { .temp_c = 25, .ohm = 47000 },
0087 { .temp_c = 30, .ohm = 37643 },
0088 { .temp_c = 35, .ohm = 30334 },
0089 { .temp_c = 40, .ohm = 24591 },
0090 { .temp_c = 45, .ohm = 20048 },
0091 { .temp_c = 50, .ohm = 16433 },
0092 { .temp_c = 55, .ohm = 13539 },
0093 { .temp_c = 60, .ohm = 11209 },
0094 { .temp_c = 65, .ohm = 9328 },
0095 { .temp_c = 70, .ohm = 7798 },
0096 { .temp_c = 75, .ohm = 6544 },
0097 { .temp_c = 80, .ohm = 5518 },
0098 { .temp_c = 85, .ohm = 4674 },
0099 { .temp_c = 90, .ohm = 3972 },
0100 { .temp_c = 95, .ohm = 3388 },
0101 { .temp_c = 100, .ohm = 2902 },
0102 { .temp_c = 105, .ohm = 2494 },
0103 { .temp_c = 110, .ohm = 2150 },
0104 { .temp_c = 115, .ohm = 1860 },
0105 { .temp_c = 120, .ohm = 1615 },
0106 { .temp_c = 125, .ohm = 1406 },
0107 };
0108 static const struct ntc_compensation ncpXXwl333[] = {
0109 { .temp_c = -40, .ohm = 1610154 },
0110 { .temp_c = -35, .ohm = 1130850 },
0111 { .temp_c = -30, .ohm = 802609 },
0112 { .temp_c = -25, .ohm = 575385 },
0113 { .temp_c = -20, .ohm = 416464 },
0114 { .temp_c = -15, .ohm = 304219 },
0115 { .temp_c = -10, .ohm = 224193 },
0116 { .temp_c = -5, .ohm = 166623 },
0117 { .temp_c = 0, .ohm = 124850 },
0118 { .temp_c = 5, .ohm = 94287 },
0119 { .temp_c = 10, .ohm = 71747 },
0120 { .temp_c = 15, .ohm = 54996 },
0121 { .temp_c = 20, .ohm = 42455 },
0122 { .temp_c = 25, .ohm = 33000 },
0123 { .temp_c = 30, .ohm = 25822 },
0124 { .temp_c = 35, .ohm = 20335 },
0125 { .temp_c = 40, .ohm = 16115 },
0126 { .temp_c = 45, .ohm = 12849 },
0127 { .temp_c = 50, .ohm = 10306 },
0128 { .temp_c = 55, .ohm = 8314 },
0129 { .temp_c = 60, .ohm = 6746 },
0130 { .temp_c = 65, .ohm = 5503 },
0131 { .temp_c = 70, .ohm = 4513 },
0132 { .temp_c = 75, .ohm = 3721 },
0133 { .temp_c = 80, .ohm = 3084 },
0134 { .temp_c = 85, .ohm = 2569 },
0135 { .temp_c = 90, .ohm = 2151 },
0136 { .temp_c = 95, .ohm = 1809 },
0137 { .temp_c = 100, .ohm = 1529 },
0138 { .temp_c = 105, .ohm = 1299 },
0139 { .temp_c = 110, .ohm = 1108 },
0140 { .temp_c = 115, .ohm = 949 },
0141 { .temp_c = 120, .ohm = 817 },
0142 { .temp_c = 125, .ohm = 707 },
0143 };
0144
0145 static const struct ntc_compensation ncpXXwf104[] = {
0146 { .temp_c = -40, .ohm = 4397119 },
0147 { .temp_c = -35, .ohm = 3088599 },
0148 { .temp_c = -30, .ohm = 2197225 },
0149 { .temp_c = -25, .ohm = 1581881 },
0150 { .temp_c = -20, .ohm = 1151037 },
0151 { .temp_c = -15, .ohm = 846579 },
0152 { .temp_c = -10, .ohm = 628988 },
0153 { .temp_c = -5, .ohm = 471632 },
0154 { .temp_c = 0, .ohm = 357012 },
0155 { .temp_c = 5, .ohm = 272500 },
0156 { .temp_c = 10, .ohm = 209710 },
0157 { .temp_c = 15, .ohm = 162651 },
0158 { .temp_c = 20, .ohm = 127080 },
0159 { .temp_c = 25, .ohm = 100000 },
0160 { .temp_c = 30, .ohm = 79222 },
0161 { .temp_c = 35, .ohm = 63167 },
0162 { .temp_c = 40, .ohm = 50677 },
0163 { .temp_c = 45, .ohm = 40904 },
0164 { .temp_c = 50, .ohm = 33195 },
0165 { .temp_c = 55, .ohm = 27091 },
0166 { .temp_c = 60, .ohm = 22224 },
0167 { .temp_c = 65, .ohm = 18323 },
0168 { .temp_c = 70, .ohm = 15184 },
0169 { .temp_c = 75, .ohm = 12635 },
0170 { .temp_c = 80, .ohm = 10566 },
0171 { .temp_c = 85, .ohm = 8873 },
0172 { .temp_c = 90, .ohm = 7481 },
0173 { .temp_c = 95, .ohm = 6337 },
0174 { .temp_c = 100, .ohm = 5384 },
0175 { .temp_c = 105, .ohm = 4594 },
0176 { .temp_c = 110, .ohm = 3934 },
0177 { .temp_c = 115, .ohm = 3380 },
0178 { .temp_c = 120, .ohm = 2916 },
0179 { .temp_c = 125, .ohm = 2522 },
0180 };
0181
0182 static const struct ntc_compensation ncpXXxh103[] = {
0183 { .temp_c = -40, .ohm = 247565 },
0184 { .temp_c = -35, .ohm = 181742 },
0185 { .temp_c = -30, .ohm = 135128 },
0186 { .temp_c = -25, .ohm = 101678 },
0187 { .temp_c = -20, .ohm = 77373 },
0188 { .temp_c = -15, .ohm = 59504 },
0189 { .temp_c = -10, .ohm = 46222 },
0190 { .temp_c = -5, .ohm = 36244 },
0191 { .temp_c = 0, .ohm = 28674 },
0192 { .temp_c = 5, .ohm = 22878 },
0193 { .temp_c = 10, .ohm = 18399 },
0194 { .temp_c = 15, .ohm = 14910 },
0195 { .temp_c = 20, .ohm = 12169 },
0196 { .temp_c = 25, .ohm = 10000 },
0197 { .temp_c = 30, .ohm = 8271 },
0198 { .temp_c = 35, .ohm = 6883 },
0199 { .temp_c = 40, .ohm = 5762 },
0200 { .temp_c = 45, .ohm = 4851 },
0201 { .temp_c = 50, .ohm = 4105 },
0202 { .temp_c = 55, .ohm = 3492 },
0203 { .temp_c = 60, .ohm = 2985 },
0204 { .temp_c = 65, .ohm = 2563 },
0205 { .temp_c = 70, .ohm = 2211 },
0206 { .temp_c = 75, .ohm = 1915 },
0207 { .temp_c = 80, .ohm = 1666 },
0208 { .temp_c = 85, .ohm = 1454 },
0209 { .temp_c = 90, .ohm = 1275 },
0210 { .temp_c = 95, .ohm = 1121 },
0211 { .temp_c = 100, .ohm = 990 },
0212 { .temp_c = 105, .ohm = 876 },
0213 { .temp_c = 110, .ohm = 779 },
0214 { .temp_c = 115, .ohm = 694 },
0215 { .temp_c = 120, .ohm = 620 },
0216 { .temp_c = 125, .ohm = 556 },
0217 };
0218
0219
0220
0221
0222
0223 static const struct ntc_compensation b57330v2103[] = {
0224 { .temp_c = -40, .ohm = 190030 },
0225 { .temp_c = -35, .ohm = 145360 },
0226 { .temp_c = -30, .ohm = 112060 },
0227 { .temp_c = -25, .ohm = 87041 },
0228 { .temp_c = -20, .ohm = 68104 },
0229 { .temp_c = -15, .ohm = 53665 },
0230 { .temp_c = -10, .ohm = 42576 },
0231 { .temp_c = -5, .ohm = 34001 },
0232 { .temp_c = 0, .ohm = 27326 },
0233 { .temp_c = 5, .ohm = 22096 },
0234 { .temp_c = 10, .ohm = 17973 },
0235 { .temp_c = 15, .ohm = 14703 },
0236 { .temp_c = 20, .ohm = 12090 },
0237 { .temp_c = 25, .ohm = 10000 },
0238 { .temp_c = 30, .ohm = 8311 },
0239 { .temp_c = 35, .ohm = 6941 },
0240 { .temp_c = 40, .ohm = 5825 },
0241 { .temp_c = 45, .ohm = 4911 },
0242 { .temp_c = 50, .ohm = 4158 },
0243 { .temp_c = 55, .ohm = 3536 },
0244 { .temp_c = 60, .ohm = 3019 },
0245 { .temp_c = 65, .ohm = 2588 },
0246 { .temp_c = 70, .ohm = 2227 },
0247 { .temp_c = 75, .ohm = 1924 },
0248 { .temp_c = 80, .ohm = 1668 },
0249 { .temp_c = 85, .ohm = 1451 },
0250 { .temp_c = 90, .ohm = 1266 },
0251 { .temp_c = 95, .ohm = 1108 },
0252 { .temp_c = 100, .ohm = 973 },
0253 { .temp_c = 105, .ohm = 857 },
0254 { .temp_c = 110, .ohm = 757 },
0255 { .temp_c = 115, .ohm = 671 },
0256 { .temp_c = 120, .ohm = 596 },
0257 { .temp_c = 125, .ohm = 531 },
0258 };
0259
0260 static const struct ntc_compensation b57891s0103[] = {
0261 { .temp_c = -55.0, .ohm = 878900 },
0262 { .temp_c = -50.0, .ohm = 617590 },
0263 { .temp_c = -45.0, .ohm = 439340 },
0264 { .temp_c = -40.0, .ohm = 316180 },
0265 { .temp_c = -35.0, .ohm = 230060 },
0266 { .temp_c = -30.0, .ohm = 169150 },
0267 { .temp_c = -25.0, .ohm = 125550 },
0268 { .temp_c = -20.0, .ohm = 94143 },
0269 { .temp_c = -15.0, .ohm = 71172 },
0270 { .temp_c = -10.0, .ohm = 54308 },
0271 { .temp_c = -5.0, .ohm = 41505 },
0272 { .temp_c = 0.0, .ohm = 32014 },
0273 { .temp_c = 5.0, .ohm = 25011 },
0274 { .temp_c = 10.0, .ohm = 19691 },
0275 { .temp_c = 15.0, .ohm = 15618 },
0276 { .temp_c = 20.0, .ohm = 12474 },
0277 { .temp_c = 25.0, .ohm = 10000 },
0278 { .temp_c = 30.0, .ohm = 8080 },
0279 { .temp_c = 35.0, .ohm = 6569 },
0280 { .temp_c = 40.0, .ohm = 5372 },
0281 { .temp_c = 45.0, .ohm = 4424 },
0282 { .temp_c = 50.0, .ohm = 3661 },
0283 { .temp_c = 55.0, .ohm = 3039 },
0284 { .temp_c = 60.0, .ohm = 2536 },
0285 { .temp_c = 65.0, .ohm = 2128 },
0286 { .temp_c = 70.0, .ohm = 1794 },
0287 { .temp_c = 75.0, .ohm = 1518 },
0288 { .temp_c = 80.0, .ohm = 1290 },
0289 { .temp_c = 85.0, .ohm = 1100 },
0290 { .temp_c = 90.0, .ohm = 942 },
0291 { .temp_c = 95.0, .ohm = 809 },
0292 { .temp_c = 100.0, .ohm = 697 },
0293 { .temp_c = 105.0, .ohm = 604 },
0294 { .temp_c = 110.0, .ohm = 525 },
0295 { .temp_c = 115.0, .ohm = 457 },
0296 { .temp_c = 120.0, .ohm = 400 },
0297 { .temp_c = 125.0, .ohm = 351 },
0298 { .temp_c = 130.0, .ohm = 308 },
0299 { .temp_c = 135.0, .ohm = 272 },
0300 { .temp_c = 140.0, .ohm = 240 },
0301 { .temp_c = 145.0, .ohm = 213 },
0302 { .temp_c = 150.0, .ohm = 189 },
0303 { .temp_c = 155.0, .ohm = 168 },
0304 };
0305
0306 struct ntc_type {
0307 const struct ntc_compensation *comp;
0308 int n_comp;
0309 };
0310
0311 #define NTC_TYPE(ntc, compensation) \
0312 [(ntc)] = { .comp = (compensation), .n_comp = ARRAY_SIZE(compensation) }
0313
0314 static const struct ntc_type ntc_type[] = {
0315 NTC_TYPE(TYPE_B57330V2103, b57330v2103),
0316 NTC_TYPE(TYPE_B57891S0103, b57891s0103),
0317 NTC_TYPE(TYPE_NCPXXWB473, ncpXXwb473),
0318 NTC_TYPE(TYPE_NCPXXWF104, ncpXXwf104),
0319 NTC_TYPE(TYPE_NCPXXWL333, ncpXXwl333),
0320 NTC_TYPE(TYPE_NCPXXXH103, ncpXXxh103),
0321 };
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334 struct ntc_data {
0335 const struct ntc_compensation *comp;
0336 int n_comp;
0337 unsigned int pullup_uv;
0338 unsigned int pullup_ohm;
0339 unsigned int pulldown_ohm;
0340 enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
0341 struct iio_channel *chan;
0342 };
0343
0344 static int ntc_adc_iio_read(struct ntc_data *data)
0345 {
0346 struct iio_channel *channel = data->chan;
0347 int uv, ret;
0348
0349 ret = iio_read_channel_processed_scale(channel, &uv, 1000);
0350 if (ret < 0) {
0351 int raw;
0352
0353
0354
0355
0356
0357
0358 ret = iio_read_channel_raw(channel, &raw);
0359 if (ret < 0) {
0360 pr_err("read channel() error: %d\n", ret);
0361 return ret;
0362 }
0363 ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
0364 if (ret < 0) {
0365
0366 uv = (data->pullup_uv * (s64)raw) >> 12;
0367 }
0368 }
0369
0370 return uv;
0371 }
0372
0373 static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
0374 {
0375 if (divisor == 0 && dividend == 0)
0376 return 0;
0377 if (divisor == 0)
0378 return UINT_MAX;
0379 return div64_u64(dividend, divisor);
0380 }
0381
0382 static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)
0383 {
0384 u32 puv = data->pullup_uv;
0385 u64 n, puo, pdo;
0386 puo = data->pullup_ohm;
0387 pdo = data->pulldown_ohm;
0388
0389 if (uv == 0)
0390 return (data->connect == NTC_CONNECTED_POSITIVE) ?
0391 INT_MAX : 0;
0392 if (uv >= puv)
0393 return (data->connect == NTC_CONNECTED_POSITIVE) ?
0394 0 : INT_MAX;
0395
0396 if (data->connect == NTC_CONNECTED_POSITIVE && puo == 0)
0397 n = div_u64(pdo * (puv - uv), uv);
0398 else if (data->connect == NTC_CONNECTED_GROUND && pdo == 0)
0399 n = div_u64(puo * uv, puv - uv);
0400 else if (data->connect == NTC_CONNECTED_POSITIVE)
0401 n = div64_u64_safe(pdo * puo * (puv - uv),
0402 puo * uv - pdo * (puv - uv));
0403 else
0404 n = div64_u64_safe(pdo * puo * uv, pdo * (puv - uv) - puo * uv);
0405
0406 if (n > INT_MAX)
0407 n = INT_MAX;
0408 return n;
0409 }
0410
0411 static void lookup_comp(struct ntc_data *data, unsigned int ohm,
0412 int *i_low, int *i_high)
0413 {
0414 int start, end, mid;
0415
0416
0417
0418
0419
0420
0421
0422
0423 if (ohm >= data->comp[0].ohm) {
0424 *i_low = 0;
0425 *i_high = 0;
0426 return;
0427 }
0428 if (ohm <= data->comp[data->n_comp - 1].ohm) {
0429 *i_low = data->n_comp - 1;
0430 *i_high = data->n_comp - 1;
0431 return;
0432 }
0433
0434
0435 start = 0;
0436 end = data->n_comp;
0437 while (start < end) {
0438 mid = start + (end - start) / 2;
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 if (ohm >= data->comp[mid].ohm) {
0449 end = mid;
0450 } else {
0451 start = mid + 1;
0452
0453
0454
0455
0456
0457
0458 if (ohm >= data->comp[start].ohm)
0459 end = start;
0460 }
0461
0462
0463
0464
0465 }
0466
0467
0468
0469
0470 *i_low = end;
0471 if (ohm == data->comp[end].ohm)
0472 *i_high = end;
0473 else
0474 *i_high = end - 1;
0475 }
0476
0477 static int get_temp_mc(struct ntc_data *data, unsigned int ohm)
0478 {
0479 int low, high;
0480 int temp;
0481
0482 lookup_comp(data, ohm, &low, &high);
0483
0484
0485
0486
0487
0488 temp = fixp_linear_interpolate(data->comp[low].ohm,
0489 data->comp[low].temp_c * 1000,
0490 data->comp[high].ohm,
0491 data->comp[high].temp_c * 1000,
0492 ohm);
0493 return temp;
0494 }
0495
0496 static int ntc_thermistor_get_ohm(struct ntc_data *data)
0497 {
0498 int read_uv;
0499
0500 read_uv = ntc_adc_iio_read(data);
0501 if (read_uv < 0)
0502 return read_uv;
0503 return get_ohm_of_thermistor(data, read_uv);
0504 }
0505
0506 static int ntc_read(struct device *dev, enum hwmon_sensor_types type,
0507 u32 attr, int channel, long *val)
0508 {
0509 struct ntc_data *data = dev_get_drvdata(dev);
0510 int ohm;
0511
0512 switch (type) {
0513 case hwmon_temp:
0514 switch (attr) {
0515 case hwmon_temp_input:
0516 ohm = ntc_thermistor_get_ohm(data);
0517 if (ohm < 0)
0518 return ohm;
0519 *val = get_temp_mc(data, ohm);
0520 return 0;
0521 case hwmon_temp_type:
0522 *val = 4;
0523 return 0;
0524 default:
0525 break;
0526 }
0527 break;
0528 default:
0529 break;
0530 }
0531 return -EINVAL;
0532 }
0533
0534 static umode_t ntc_is_visible(const void *data, enum hwmon_sensor_types type,
0535 u32 attr, int channel)
0536 {
0537 if (type == hwmon_temp) {
0538 switch (attr) {
0539 case hwmon_temp_input:
0540 case hwmon_temp_type:
0541 return 0444;
0542 default:
0543 break;
0544 }
0545 }
0546 return 0;
0547 }
0548
0549 static const struct hwmon_channel_info *ntc_info[] = {
0550 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
0551 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_TYPE),
0552 NULL
0553 };
0554
0555 static const struct hwmon_ops ntc_hwmon_ops = {
0556 .is_visible = ntc_is_visible,
0557 .read = ntc_read,
0558 };
0559
0560 static const struct hwmon_chip_info ntc_chip_info = {
0561 .ops = &ntc_hwmon_ops,
0562 .info = ntc_info,
0563 };
0564
0565 static int ntc_thermistor_parse_props(struct device *dev,
0566 struct ntc_data *data)
0567 {
0568 struct iio_channel *chan;
0569 enum iio_chan_type type;
0570 int ret;
0571
0572 chan = devm_iio_channel_get(dev, NULL);
0573 if (IS_ERR(chan))
0574 return PTR_ERR(chan);
0575
0576 ret = iio_get_channel_type(chan, &type);
0577 if (ret < 0)
0578 return ret;
0579
0580 if (type != IIO_VOLTAGE)
0581 return -EINVAL;
0582
0583 ret = device_property_read_u32(dev, "pullup-uv", &data->pullup_uv);
0584 if (ret)
0585 return dev_err_probe(dev, ret, "pullup-uv not specified\n");
0586
0587 ret = device_property_read_u32(dev, "pullup-ohm", &data->pullup_ohm);
0588 if (ret)
0589 return dev_err_probe(dev, ret, "pullup-ohm not specified\n");
0590
0591 ret = device_property_read_u32(dev, "pulldown-ohm", &data->pulldown_ohm);
0592 if (ret)
0593 return dev_err_probe(dev, ret, "pulldown-ohm not specified\n");
0594
0595 if (device_property_read_bool(dev, "connected-positive"))
0596 data->connect = NTC_CONNECTED_POSITIVE;
0597 else
0598 data->connect = NTC_CONNECTED_GROUND;
0599
0600 data->chan = chan;
0601
0602 return 0;
0603 }
0604
0605 static int ntc_thermistor_probe(struct platform_device *pdev)
0606 {
0607 struct device *dev = &pdev->dev;
0608 const struct platform_device_id *pdev_id;
0609 struct device *hwmon_dev;
0610 struct ntc_data *data;
0611 int ret;
0612
0613 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0614 if (!data)
0615 return -ENOMEM;
0616
0617 ret = ntc_thermistor_parse_props(dev, data);
0618 if (ret)
0619 return ret;
0620
0621 if (data->pullup_uv == 0 ||
0622 (data->pullup_ohm == 0 && data->connect ==
0623 NTC_CONNECTED_GROUND) ||
0624 (data->pulldown_ohm == 0 && data->connect ==
0625 NTC_CONNECTED_POSITIVE) ||
0626 (data->connect != NTC_CONNECTED_POSITIVE &&
0627 data->connect != NTC_CONNECTED_GROUND)) {
0628 dev_err(dev, "Required data to use NTC driver not supplied.\n");
0629 return -EINVAL;
0630 }
0631
0632 pdev_id = device_get_match_data(dev);
0633
0634 if (pdev_id->driver_data >= ARRAY_SIZE(ntc_type)) {
0635 dev_err(dev, "Unknown device type: %lu(%s)\n",
0636 pdev_id->driver_data, pdev_id->name);
0637 return -EINVAL;
0638 }
0639
0640 data->comp = ntc_type[pdev_id->driver_data].comp;
0641 data->n_comp = ntc_type[pdev_id->driver_data].n_comp;
0642
0643 hwmon_dev = devm_hwmon_device_register_with_info(dev, pdev_id->name,
0644 data, &ntc_chip_info,
0645 NULL);
0646 if (IS_ERR(hwmon_dev)) {
0647 dev_err(dev, "unable to register as hwmon device.\n");
0648 return PTR_ERR(hwmon_dev);
0649 }
0650
0651 dev_info(dev, "Thermistor type: %s successfully probed.\n",
0652 pdev_id->name);
0653
0654 return 0;
0655 }
0656
0657 static const struct of_device_id ntc_match[] = {
0658 { .compatible = "epcos,b57330v2103",
0659 .data = &ntc_thermistor_id[NTC_B57330V2103]},
0660 { .compatible = "epcos,b57891s0103",
0661 .data = &ntc_thermistor_id[NTC_B57891S0103] },
0662 { .compatible = "murata,ncp03wb473",
0663 .data = &ntc_thermistor_id[NTC_NCP03WB473] },
0664 { .compatible = "murata,ncp03wf104",
0665 .data = &ntc_thermistor_id[NTC_NCP03WF104] },
0666 { .compatible = "murata,ncp15wb473",
0667 .data = &ntc_thermistor_id[NTC_NCP15WB473] },
0668 { .compatible = "murata,ncp15wl333",
0669 .data = &ntc_thermistor_id[NTC_NCP15WL333] },
0670 { .compatible = "murata,ncp15xh103",
0671 .data = &ntc_thermistor_id[NTC_NCP15XH103] },
0672 { .compatible = "murata,ncp18wb473",
0673 .data = &ntc_thermistor_id[NTC_NCP18WB473] },
0674 { .compatible = "murata,ncp21wb473",
0675 .data = &ntc_thermistor_id[NTC_NCP21WB473] },
0676 { .compatible = "samsung,1404-001221",
0677 .data = &ntc_thermistor_id[NTC_SSG1404001221] },
0678
0679
0680 { .compatible = "ntc,ncp03wb473",
0681 .data = &ntc_thermistor_id[NTC_NCP03WB473] },
0682 { .compatible = "ntc,ncp15wb473",
0683 .data = &ntc_thermistor_id[NTC_NCP15WB473] },
0684 { .compatible = "ntc,ncp15wl333",
0685 .data = &ntc_thermistor_id[NTC_NCP15WL333] },
0686 { .compatible = "ntc,ncp18wb473",
0687 .data = &ntc_thermistor_id[NTC_NCP18WB473] },
0688 { .compatible = "ntc,ncp21wb473",
0689 .data = &ntc_thermistor_id[NTC_NCP21WB473] },
0690 { },
0691 };
0692 MODULE_DEVICE_TABLE(of, ntc_match);
0693
0694 static struct platform_driver ntc_thermistor_driver = {
0695 .driver = {
0696 .name = "ntc-thermistor",
0697 .of_match_table = ntc_match,
0698 },
0699 .probe = ntc_thermistor_probe,
0700 .id_table = ntc_thermistor_id,
0701 };
0702
0703 module_platform_driver(ntc_thermistor_driver);
0704
0705 MODULE_DESCRIPTION("NTC Thermistor Driver");
0706 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
0707 MODULE_LICENSE("GPL");
0708 MODULE_ALIAS("platform:ntc-thermistor");