.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Amlogic Meson Successive Approximation Register (SAR) A/D Converter |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * You should have received a copy of the GNU General Public License |
---|
11 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
12 | 6 | */ |
---|
13 | 7 | |
---|
14 | 8 | #include <linux/bitfield.h> |
---|
.. | .. |
---|
18 | 12 | #include <linux/io.h> |
---|
19 | 13 | #include <linux/iio/iio.h> |
---|
20 | 14 | #include <linux/module.h> |
---|
| 15 | +#include <linux/nvmem-consumer.h> |
---|
21 | 16 | #include <linux/interrupt.h> |
---|
22 | 17 | #include <linux/of.h> |
---|
23 | 18 | #include <linux/of_irq.h> |
---|
.. | .. |
---|
25 | 20 | #include <linux/platform_device.h> |
---|
26 | 21 | #include <linux/regmap.h> |
---|
27 | 22 | #include <linux/regulator/consumer.h> |
---|
| 23 | +#include <linux/mfd/syscon.h> |
---|
28 | 24 | |
---|
29 | 25 | #define MESON_SAR_ADC_REG0 0x00 |
---|
30 | 26 | #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) |
---|
.. | .. |
---|
75 | 71 | #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) |
---|
76 | 72 | #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) |
---|
77 | 73 | #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 |
---|
78 | | - #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 |
---|
| 74 | + #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6 |
---|
79 | 75 | #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) |
---|
80 | 76 | #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) |
---|
81 | 77 | |
---|
.. | .. |
---|
148 | 144 | #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) |
---|
149 | 145 | #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) |
---|
150 | 146 | #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) |
---|
151 | | - #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11 |
---|
152 | 147 | #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) |
---|
153 | 148 | #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) |
---|
154 | 149 | #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) |
---|
.. | .. |
---|
166 | 161 | |
---|
167 | 162 | #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 |
---|
168 | 163 | #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ |
---|
| 164 | +#define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6 |
---|
| 165 | +#define MESON_SAR_ADC_TEMP_OFFSET 27 |
---|
| 166 | + |
---|
| 167 | +/* temperature sensor calibration information in eFuse */ |
---|
| 168 | +#define MESON_SAR_ADC_EFUSE_BYTES 4 |
---|
| 169 | +#define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) |
---|
| 170 | +#define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) |
---|
| 171 | + |
---|
| 172 | +#define MESON_HHI_DPLL_TOP_0 0x318 |
---|
| 173 | +#define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9) |
---|
| 174 | + |
---|
169 | 175 | /* for use with IIO_VAL_INT_PLUS_MICRO */ |
---|
170 | 176 | #define MILLION 1000000 |
---|
171 | 177 | |
---|
.. | .. |
---|
173 | 179 | .type = IIO_VOLTAGE, \ |
---|
174 | 180 | .indexed = 1, \ |
---|
175 | 181 | .channel = _chan, \ |
---|
| 182 | + .address = _chan, \ |
---|
176 | 183 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
---|
177 | 184 | BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ |
---|
178 | | - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
---|
179 | | - BIT(IIO_CHAN_INFO_CALIBBIAS) | \ |
---|
| 185 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
---|
| 186 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ |
---|
180 | 187 | BIT(IIO_CHAN_INFO_CALIBSCALE), \ |
---|
181 | 188 | .datasheet_name = "SAR_ADC_CH"#_chan, \ |
---|
182 | 189 | } |
---|
183 | 190 | |
---|
184 | | -/* |
---|
185 | | - * TODO: the hardware supports IIO_TEMP for channel 6 as well which is |
---|
186 | | - * currently not supported by this driver. |
---|
187 | | - */ |
---|
| 191 | +#define MESON_SAR_ADC_TEMP_CHAN(_chan) { \ |
---|
| 192 | + .type = IIO_TEMP, \ |
---|
| 193 | + .channel = _chan, \ |
---|
| 194 | + .address = MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL, \ |
---|
| 195 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
---|
| 196 | + BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ |
---|
| 197 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \ |
---|
| 198 | + BIT(IIO_CHAN_INFO_SCALE), \ |
---|
| 199 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ |
---|
| 200 | + BIT(IIO_CHAN_INFO_CALIBSCALE), \ |
---|
| 201 | + .datasheet_name = "TEMP_SENSOR", \ |
---|
| 202 | +} |
---|
| 203 | + |
---|
188 | 204 | static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { |
---|
189 | 205 | MESON_SAR_ADC_CHAN(0), |
---|
190 | 206 | MESON_SAR_ADC_CHAN(1), |
---|
.. | .. |
---|
195 | 211 | MESON_SAR_ADC_CHAN(6), |
---|
196 | 212 | MESON_SAR_ADC_CHAN(7), |
---|
197 | 213 | IIO_CHAN_SOFT_TIMESTAMP(8), |
---|
| 214 | +}; |
---|
| 215 | + |
---|
| 216 | +static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = { |
---|
| 217 | + MESON_SAR_ADC_CHAN(0), |
---|
| 218 | + MESON_SAR_ADC_CHAN(1), |
---|
| 219 | + MESON_SAR_ADC_CHAN(2), |
---|
| 220 | + MESON_SAR_ADC_CHAN(3), |
---|
| 221 | + MESON_SAR_ADC_CHAN(4), |
---|
| 222 | + MESON_SAR_ADC_CHAN(5), |
---|
| 223 | + MESON_SAR_ADC_CHAN(6), |
---|
| 224 | + MESON_SAR_ADC_CHAN(7), |
---|
| 225 | + MESON_SAR_ADC_TEMP_CHAN(8), |
---|
| 226 | + IIO_CHAN_SOFT_TIMESTAMP(9), |
---|
198 | 227 | }; |
---|
199 | 228 | |
---|
200 | 229 | enum meson_sar_adc_avg_mode { |
---|
.. | .. |
---|
225 | 254 | u32 bandgap_reg; |
---|
226 | 255 | unsigned int resolution; |
---|
227 | 256 | const struct regmap_config *regmap_config; |
---|
| 257 | + u8 temperature_trimming_bits; |
---|
| 258 | + unsigned int temperature_multiplier; |
---|
| 259 | + unsigned int temperature_divider; |
---|
228 | 260 | }; |
---|
229 | 261 | |
---|
230 | 262 | struct meson_sar_adc_data { |
---|
.. | .. |
---|
235 | 267 | struct meson_sar_adc_priv { |
---|
236 | 268 | struct regmap *regmap; |
---|
237 | 269 | struct regulator *vref; |
---|
238 | | - const struct meson_sar_adc_data *data; |
---|
| 270 | + const struct meson_sar_adc_param *param; |
---|
239 | 271 | struct clk *clkin; |
---|
240 | 272 | struct clk *core_clk; |
---|
241 | 273 | struct clk *adc_sel_clk; |
---|
.. | .. |
---|
246 | 278 | struct completion done; |
---|
247 | 279 | int calibbias; |
---|
248 | 280 | int calibscale; |
---|
| 281 | + struct regmap *tsc_regmap; |
---|
| 282 | + bool temperature_sensor_calibrated; |
---|
| 283 | + u8 temperature_sensor_coefficient; |
---|
| 284 | + u16 temperature_sensor_adc_val; |
---|
249 | 285 | }; |
---|
250 | 286 | |
---|
251 | 287 | static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { |
---|
.. | .. |
---|
280 | 316 | /* use val_calib = scale * val_raw + offset calibration function */ |
---|
281 | 317 | tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; |
---|
282 | 318 | |
---|
283 | | - return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1); |
---|
| 319 | + return clamp(tmp, 0, (1 << priv->param->resolution) - 1); |
---|
284 | 320 | } |
---|
285 | 321 | |
---|
286 | 322 | static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) |
---|
.. | .. |
---|
324 | 360 | |
---|
325 | 361 | regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); |
---|
326 | 362 | fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); |
---|
327 | | - if (fifo_chan != chan->channel) { |
---|
| 363 | + if (fifo_chan != chan->address) { |
---|
328 | 364 | dev_err(&indio_dev->dev, |
---|
329 | | - "ADC FIFO entry belongs to channel %d instead of %d\n", |
---|
330 | | - fifo_chan, chan->channel); |
---|
| 365 | + "ADC FIFO entry belongs to channel %d instead of %lu\n", |
---|
| 366 | + fifo_chan, chan->address); |
---|
331 | 367 | return -EINVAL; |
---|
332 | 368 | } |
---|
333 | 369 | |
---|
334 | 370 | fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); |
---|
335 | | - fifo_val &= GENMASK(priv->data->param->resolution - 1, 0); |
---|
| 371 | + fifo_val &= GENMASK(priv->param->resolution - 1, 0); |
---|
336 | 372 | *val = meson_sar_adc_calib_val(indio_dev, fifo_val); |
---|
337 | 373 | |
---|
338 | 374 | return 0; |
---|
.. | .. |
---|
344 | 380 | enum meson_sar_adc_num_samples samples) |
---|
345 | 381 | { |
---|
346 | 382 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
347 | | - int val, channel = chan->channel; |
---|
| 383 | + int val, address = chan->address; |
---|
348 | 384 | |
---|
349 | | - val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel); |
---|
| 385 | + val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); |
---|
350 | 386 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, |
---|
351 | | - MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel), |
---|
| 387 | + MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), |
---|
352 | 388 | val); |
---|
353 | 389 | |
---|
354 | | - val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel); |
---|
| 390 | + val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); |
---|
355 | 391 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, |
---|
356 | | - MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val); |
---|
| 392 | + MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); |
---|
357 | 393 | } |
---|
358 | 394 | |
---|
359 | 395 | static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, |
---|
.. | .. |
---|
373 | 409 | |
---|
374 | 410 | /* map channel index 0 to the channel which we want to read */ |
---|
375 | 411 | regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), |
---|
376 | | - chan->channel); |
---|
| 412 | + chan->address); |
---|
377 | 413 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, |
---|
378 | 414 | MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); |
---|
379 | 415 | |
---|
380 | 416 | regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, |
---|
381 | | - chan->channel); |
---|
| 417 | + chan->address); |
---|
382 | 418 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, |
---|
383 | 419 | MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, |
---|
384 | 420 | regval); |
---|
385 | 421 | |
---|
386 | 422 | regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, |
---|
387 | | - chan->channel); |
---|
| 423 | + chan->address); |
---|
388 | 424 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, |
---|
389 | 425 | MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, |
---|
390 | 426 | regval); |
---|
391 | 427 | |
---|
392 | | - if (chan->channel == 6) |
---|
393 | | - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
394 | | - MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0); |
---|
| 428 | + if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) { |
---|
| 429 | + if (chan->type == IIO_TEMP) |
---|
| 430 | + regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL; |
---|
| 431 | + else |
---|
| 432 | + regval = 0; |
---|
| 433 | + |
---|
| 434 | + regmap_update_bits(priv->regmap, |
---|
| 435 | + MESON_SAR_ADC_DELTA_10, |
---|
| 436 | + MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval); |
---|
| 437 | + } |
---|
395 | 438 | } |
---|
396 | 439 | |
---|
397 | 440 | static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, |
---|
.. | .. |
---|
451 | 494 | |
---|
452 | 495 | mutex_lock(&indio_dev->mlock); |
---|
453 | 496 | |
---|
454 | | - if (priv->data->param->has_bl30_integration) { |
---|
| 497 | + if (priv->param->has_bl30_integration) { |
---|
455 | 498 | /* prevent BL30 from using the SAR ADC while we are using it */ |
---|
456 | 499 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, |
---|
457 | 500 | MESON_SAR_ADC_DELAY_KERNEL_BUSY, |
---|
.. | .. |
---|
479 | 522 | { |
---|
480 | 523 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
481 | 524 | |
---|
482 | | - if (priv->data->param->has_bl30_integration) |
---|
| 525 | + if (priv->param->has_bl30_integration) |
---|
483 | 526 | /* allow BL30 to use the SAR ADC again */ |
---|
484 | 527 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, |
---|
485 | 528 | MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); |
---|
.. | .. |
---|
506 | 549 | enum meson_sar_adc_num_samples avg_samples, |
---|
507 | 550 | int *val) |
---|
508 | 551 | { |
---|
| 552 | + struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
509 | 553 | int ret; |
---|
| 554 | + |
---|
| 555 | + if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) |
---|
| 556 | + return -ENOTSUPP; |
---|
510 | 557 | |
---|
511 | 558 | ret = meson_sar_adc_lock(indio_dev); |
---|
512 | 559 | if (ret) |
---|
.. | .. |
---|
527 | 574 | |
---|
528 | 575 | if (ret) { |
---|
529 | 576 | dev_warn(indio_dev->dev.parent, |
---|
530 | | - "failed to read sample for channel %d: %d\n", |
---|
531 | | - chan->channel, ret); |
---|
| 577 | + "failed to read sample for channel %lu: %d\n", |
---|
| 578 | + chan->address, ret); |
---|
532 | 579 | return ret; |
---|
533 | 580 | } |
---|
534 | 581 | |
---|
.. | .. |
---|
555 | 602 | break; |
---|
556 | 603 | |
---|
557 | 604 | case IIO_CHAN_INFO_SCALE: |
---|
558 | | - ret = regulator_get_voltage(priv->vref); |
---|
559 | | - if (ret < 0) { |
---|
560 | | - dev_err(indio_dev->dev.parent, |
---|
561 | | - "failed to get vref voltage: %d\n", ret); |
---|
562 | | - return ret; |
---|
563 | | - } |
---|
| 605 | + if (chan->type == IIO_VOLTAGE) { |
---|
| 606 | + ret = regulator_get_voltage(priv->vref); |
---|
| 607 | + if (ret < 0) { |
---|
| 608 | + dev_err(indio_dev->dev.parent, |
---|
| 609 | + "failed to get vref voltage: %d\n", |
---|
| 610 | + ret); |
---|
| 611 | + return ret; |
---|
| 612 | + } |
---|
564 | 613 | |
---|
565 | | - *val = ret / 1000; |
---|
566 | | - *val2 = priv->data->param->resolution; |
---|
567 | | - return IIO_VAL_FRACTIONAL_LOG2; |
---|
| 614 | + *val = ret / 1000; |
---|
| 615 | + *val2 = priv->param->resolution; |
---|
| 616 | + return IIO_VAL_FRACTIONAL_LOG2; |
---|
| 617 | + } else if (chan->type == IIO_TEMP) { |
---|
| 618 | + /* SoC specific multiplier and divider */ |
---|
| 619 | + *val = priv->param->temperature_multiplier; |
---|
| 620 | + *val2 = priv->param->temperature_divider; |
---|
| 621 | + |
---|
| 622 | + /* celsius to millicelsius */ |
---|
| 623 | + *val *= 1000; |
---|
| 624 | + |
---|
| 625 | + return IIO_VAL_FRACTIONAL; |
---|
| 626 | + } else { |
---|
| 627 | + return -EINVAL; |
---|
| 628 | + } |
---|
568 | 629 | |
---|
569 | 630 | case IIO_CHAN_INFO_CALIBBIAS: |
---|
570 | 631 | *val = priv->calibbias; |
---|
.. | .. |
---|
574 | 635 | *val = priv->calibscale / MILLION; |
---|
575 | 636 | *val2 = priv->calibscale % MILLION; |
---|
576 | 637 | return IIO_VAL_INT_PLUS_MICRO; |
---|
| 638 | + |
---|
| 639 | + case IIO_CHAN_INFO_OFFSET: |
---|
| 640 | + *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET * |
---|
| 641 | + priv->param->temperature_divider, |
---|
| 642 | + priv->param->temperature_multiplier); |
---|
| 643 | + *val -= priv->temperature_sensor_adc_val; |
---|
| 644 | + return IIO_VAL_INT; |
---|
577 | 645 | |
---|
578 | 646 | default: |
---|
579 | 647 | return -EINVAL; |
---|
.. | .. |
---|
631 | 699 | return 0; |
---|
632 | 700 | } |
---|
633 | 701 | |
---|
| 702 | +static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) |
---|
| 703 | +{ |
---|
| 704 | + struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
| 705 | + u8 *buf, trimming_bits, trimming_mask, upper_adc_val; |
---|
| 706 | + struct nvmem_cell *temperature_calib; |
---|
| 707 | + size_t read_len; |
---|
| 708 | + int ret; |
---|
| 709 | + |
---|
| 710 | + temperature_calib = devm_nvmem_cell_get(indio_dev->dev.parent, |
---|
| 711 | + "temperature_calib"); |
---|
| 712 | + if (IS_ERR(temperature_calib)) { |
---|
| 713 | + ret = PTR_ERR(temperature_calib); |
---|
| 714 | + |
---|
| 715 | + /* |
---|
| 716 | + * leave the temperature sensor disabled if no calibration data |
---|
| 717 | + * was passed via nvmem-cells. |
---|
| 718 | + */ |
---|
| 719 | + if (ret == -ENODEV) |
---|
| 720 | + return 0; |
---|
| 721 | + |
---|
| 722 | + return dev_err_probe(indio_dev->dev.parent, ret, |
---|
| 723 | + "failed to get temperature_calib cell\n"); |
---|
| 724 | + } |
---|
| 725 | + |
---|
| 726 | + priv->tsc_regmap = |
---|
| 727 | + syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node, |
---|
| 728 | + "amlogic,hhi-sysctrl"); |
---|
| 729 | + if (IS_ERR(priv->tsc_regmap)) { |
---|
| 730 | + dev_err(indio_dev->dev.parent, |
---|
| 731 | + "failed to get amlogic,hhi-sysctrl regmap\n"); |
---|
| 732 | + return PTR_ERR(priv->tsc_regmap); |
---|
| 733 | + } |
---|
| 734 | + |
---|
| 735 | + read_len = MESON_SAR_ADC_EFUSE_BYTES; |
---|
| 736 | + buf = nvmem_cell_read(temperature_calib, &read_len); |
---|
| 737 | + if (IS_ERR(buf)) { |
---|
| 738 | + dev_err(indio_dev->dev.parent, |
---|
| 739 | + "failed to read temperature_calib cell\n"); |
---|
| 740 | + return PTR_ERR(buf); |
---|
| 741 | + } else if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { |
---|
| 742 | + kfree(buf); |
---|
| 743 | + dev_err(indio_dev->dev.parent, |
---|
| 744 | + "invalid read size of temperature_calib cell\n"); |
---|
| 745 | + return -EINVAL; |
---|
| 746 | + } |
---|
| 747 | + |
---|
| 748 | + trimming_bits = priv->param->temperature_trimming_bits; |
---|
| 749 | + trimming_mask = BIT(trimming_bits) - 1; |
---|
| 750 | + |
---|
| 751 | + priv->temperature_sensor_calibrated = |
---|
| 752 | + buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED; |
---|
| 753 | + priv->temperature_sensor_coefficient = buf[2] & trimming_mask; |
---|
| 754 | + |
---|
| 755 | + upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL, |
---|
| 756 | + buf[3]); |
---|
| 757 | + |
---|
| 758 | + priv->temperature_sensor_adc_val = buf[2]; |
---|
| 759 | + priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE; |
---|
| 760 | + priv->temperature_sensor_adc_val >>= trimming_bits; |
---|
| 761 | + |
---|
| 762 | + kfree(buf); |
---|
| 763 | + |
---|
| 764 | + return 0; |
---|
| 765 | +} |
---|
| 766 | + |
---|
634 | 767 | static int meson_sar_adc_init(struct iio_dev *indio_dev) |
---|
635 | 768 | { |
---|
636 | 769 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
.. | .. |
---|
642 | 775 | */ |
---|
643 | 776 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); |
---|
644 | 777 | |
---|
645 | | - if (priv->data->param->has_bl30_integration) { |
---|
| 778 | + if (priv->param->has_bl30_integration) { |
---|
646 | 779 | /* |
---|
647 | 780 | * leave sampling delay and the input clocks as configured by |
---|
648 | 781 | * BL30 to make sure BL30 gets the values it expects when |
---|
.. | .. |
---|
655 | 788 | |
---|
656 | 789 | meson_sar_adc_stop_sample_engine(indio_dev); |
---|
657 | 790 | |
---|
658 | | - /* update the channel 6 MUX to select the temperature sensor */ |
---|
| 791 | + /* |
---|
| 792 | + * disable this bit as seems to be only relevant for Meson6 (based |
---|
| 793 | + * on the vendor driver), which we don't support at the moment. |
---|
| 794 | + */ |
---|
659 | 795 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
---|
660 | | - MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, |
---|
661 | | - MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL); |
---|
| 796 | + MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); |
---|
662 | 797 | |
---|
663 | 798 | /* disable all channels by default */ |
---|
664 | 799 | regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); |
---|
.. | .. |
---|
715 | 850 | regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; |
---|
716 | 851 | regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); |
---|
717 | 852 | |
---|
| 853 | + if (priv->temperature_sensor_calibrated) { |
---|
| 854 | + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
| 855 | + MESON_SAR_ADC_DELTA_10_TS_REVE1, |
---|
| 856 | + MESON_SAR_ADC_DELTA_10_TS_REVE1); |
---|
| 857 | + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
| 858 | + MESON_SAR_ADC_DELTA_10_TS_REVE0, |
---|
| 859 | + MESON_SAR_ADC_DELTA_10_TS_REVE0); |
---|
| 860 | + |
---|
| 861 | + /* |
---|
| 862 | + * set bits [3:0] of the TSC (temperature sensor coefficient) |
---|
| 863 | + * to get the correct values when reading the temperature. |
---|
| 864 | + */ |
---|
| 865 | + regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK, |
---|
| 866 | + priv->temperature_sensor_coefficient); |
---|
| 867 | + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
| 868 | + MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); |
---|
| 869 | + |
---|
| 870 | + if (priv->param->temperature_trimming_bits == 5) { |
---|
| 871 | + if (priv->temperature_sensor_coefficient & BIT(4)) |
---|
| 872 | + regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4; |
---|
| 873 | + else |
---|
| 874 | + regval = 0; |
---|
| 875 | + |
---|
| 876 | + /* |
---|
| 877 | + * bit [4] (the 5th bit when starting to count at 1) |
---|
| 878 | + * of the TSC is located in the HHI register area. |
---|
| 879 | + */ |
---|
| 880 | + regmap_update_bits(priv->tsc_regmap, |
---|
| 881 | + MESON_HHI_DPLL_TOP_0, |
---|
| 882 | + MESON_HHI_DPLL_TOP_0_TSC_BIT4, |
---|
| 883 | + regval); |
---|
| 884 | + } |
---|
| 885 | + } else { |
---|
| 886 | + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
| 887 | + MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); |
---|
| 888 | + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, |
---|
| 889 | + MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); |
---|
| 890 | + } |
---|
| 891 | + |
---|
718 | 892 | ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); |
---|
719 | 893 | if (ret) { |
---|
720 | 894 | dev_err(indio_dev->dev.parent, |
---|
.. | .. |
---|
722 | 896 | return ret; |
---|
723 | 897 | } |
---|
724 | 898 | |
---|
725 | | - ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate); |
---|
| 899 | + ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); |
---|
726 | 900 | if (ret) { |
---|
727 | 901 | dev_err(indio_dev->dev.parent, |
---|
728 | 902 | "failed to set adc clock rate\n"); |
---|
.. | .. |
---|
735 | 909 | static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) |
---|
736 | 910 | { |
---|
737 | 911 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); |
---|
738 | | - const struct meson_sar_adc_param *param = priv->data->param; |
---|
| 912 | + const struct meson_sar_adc_param *param = priv->param; |
---|
739 | 913 | u32 enable_mask; |
---|
740 | 914 | |
---|
741 | 915 | if (param->bandgap_reg == MESON_SAR_ADC_REG11) |
---|
.. | .. |
---|
855 | 1029 | int ret, nominal0, nominal1, value0, value1; |
---|
856 | 1030 | |
---|
857 | 1031 | /* use points 25% and 75% for calibration */ |
---|
858 | | - nominal0 = (1 << priv->data->param->resolution) / 4; |
---|
859 | | - nominal1 = (1 << priv->data->param->resolution) * 3 / 4; |
---|
| 1032 | + nominal0 = (1 << priv->param->resolution) / 4; |
---|
| 1033 | + nominal1 = (1 << priv->param->resolution) * 3 / 4; |
---|
860 | 1034 | |
---|
861 | 1035 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); |
---|
862 | 1036 | usleep_range(10, 20); |
---|
863 | 1037 | ret = meson_sar_adc_get_sample(indio_dev, |
---|
864 | | - &meson_sar_adc_iio_channels[7], |
---|
| 1038 | + &indio_dev->channels[7], |
---|
865 | 1039 | MEAN_AVERAGING, EIGHT_SAMPLES, &value0); |
---|
866 | 1040 | if (ret < 0) |
---|
867 | 1041 | goto out; |
---|
.. | .. |
---|
869 | 1043 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); |
---|
870 | 1044 | usleep_range(10, 20); |
---|
871 | 1045 | ret = meson_sar_adc_get_sample(indio_dev, |
---|
872 | | - &meson_sar_adc_iio_channels[7], |
---|
| 1046 | + &indio_dev->channels[7], |
---|
873 | 1047 | MEAN_AVERAGING, EIGHT_SAMPLES, &value1); |
---|
874 | 1048 | if (ret < 0) |
---|
875 | 1049 | goto out; |
---|
.. | .. |
---|
900 | 1074 | .bandgap_reg = MESON_SAR_ADC_DELTA_10, |
---|
901 | 1075 | .regmap_config = &meson_sar_adc_regmap_config_meson8, |
---|
902 | 1076 | .resolution = 10, |
---|
| 1077 | + .temperature_trimming_bits = 4, |
---|
| 1078 | + .temperature_multiplier = 18 * 10000, |
---|
| 1079 | + .temperature_divider = 1024 * 10 * 85, |
---|
| 1080 | +}; |
---|
| 1081 | + |
---|
| 1082 | +static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { |
---|
| 1083 | + .has_bl30_integration = false, |
---|
| 1084 | + .clock_rate = 1150000, |
---|
| 1085 | + .bandgap_reg = MESON_SAR_ADC_DELTA_10, |
---|
| 1086 | + .regmap_config = &meson_sar_adc_regmap_config_meson8, |
---|
| 1087 | + .resolution = 10, |
---|
| 1088 | + .temperature_trimming_bits = 5, |
---|
| 1089 | + .temperature_multiplier = 10, |
---|
| 1090 | + .temperature_divider = 32, |
---|
903 | 1091 | }; |
---|
904 | 1092 | |
---|
905 | 1093 | static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { |
---|
.. | .. |
---|
924 | 1112 | }; |
---|
925 | 1113 | |
---|
926 | 1114 | static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { |
---|
927 | | - .param = &meson_sar_adc_meson8_param, |
---|
| 1115 | + .param = &meson_sar_adc_meson8b_param, |
---|
928 | 1116 | .name = "meson-meson8b-saradc", |
---|
929 | 1117 | }; |
---|
930 | 1118 | |
---|
931 | 1119 | static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = { |
---|
932 | | - .param = &meson_sar_adc_meson8_param, |
---|
| 1120 | + .param = &meson_sar_adc_meson8b_param, |
---|
933 | 1121 | .name = "meson-meson8m2-saradc", |
---|
934 | 1122 | }; |
---|
935 | 1123 | |
---|
.. | .. |
---|
953 | 1141 | .name = "meson-axg-saradc", |
---|
954 | 1142 | }; |
---|
955 | 1143 | |
---|
| 1144 | +static const struct meson_sar_adc_data meson_sar_adc_g12a_data = { |
---|
| 1145 | + .param = &meson_sar_adc_gxl_param, |
---|
| 1146 | + .name = "meson-g12a-saradc", |
---|
| 1147 | +}; |
---|
| 1148 | + |
---|
956 | 1149 | static const struct of_device_id meson_sar_adc_of_match[] = { |
---|
957 | 1150 | { |
---|
958 | 1151 | .compatible = "amlogic,meson8-saradc", |
---|
959 | 1152 | .data = &meson_sar_adc_meson8_data, |
---|
960 | | - }, |
---|
961 | | - { |
---|
| 1153 | + }, { |
---|
962 | 1154 | .compatible = "amlogic,meson8b-saradc", |
---|
963 | 1155 | .data = &meson_sar_adc_meson8b_data, |
---|
964 | | - }, |
---|
965 | | - { |
---|
| 1156 | + }, { |
---|
966 | 1157 | .compatible = "amlogic,meson8m2-saradc", |
---|
967 | 1158 | .data = &meson_sar_adc_meson8m2_data, |
---|
968 | | - }, |
---|
969 | | - { |
---|
| 1159 | + }, { |
---|
970 | 1160 | .compatible = "amlogic,meson-gxbb-saradc", |
---|
971 | 1161 | .data = &meson_sar_adc_gxbb_data, |
---|
972 | 1162 | }, { |
---|
.. | .. |
---|
978 | 1168 | }, { |
---|
979 | 1169 | .compatible = "amlogic,meson-axg-saradc", |
---|
980 | 1170 | .data = &meson_sar_adc_axg_data, |
---|
| 1171 | + }, { |
---|
| 1172 | + .compatible = "amlogic,meson-g12a-saradc", |
---|
| 1173 | + .data = &meson_sar_adc_g12a_data, |
---|
981 | 1174 | }, |
---|
982 | | - {}, |
---|
| 1175 | + { /* sentinel */ } |
---|
983 | 1176 | }; |
---|
984 | 1177 | MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); |
---|
985 | 1178 | |
---|
986 | 1179 | static int meson_sar_adc_probe(struct platform_device *pdev) |
---|
987 | 1180 | { |
---|
| 1181 | + const struct meson_sar_adc_data *match_data; |
---|
988 | 1182 | struct meson_sar_adc_priv *priv; |
---|
989 | 1183 | struct iio_dev *indio_dev; |
---|
990 | | - struct resource *res; |
---|
991 | 1184 | void __iomem *base; |
---|
992 | | - const struct of_device_id *match; |
---|
993 | 1185 | int irq, ret; |
---|
994 | 1186 | |
---|
995 | 1187 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); |
---|
.. | .. |
---|
1001 | 1193 | priv = iio_priv(indio_dev); |
---|
1002 | 1194 | init_completion(&priv->done); |
---|
1003 | 1195 | |
---|
1004 | | - match = of_match_device(meson_sar_adc_of_match, &pdev->dev); |
---|
1005 | | - if (!match) { |
---|
1006 | | - dev_err(&pdev->dev, "failed to match device\n"); |
---|
| 1196 | + match_data = of_device_get_match_data(&pdev->dev); |
---|
| 1197 | + if (!match_data) { |
---|
| 1198 | + dev_err(&pdev->dev, "failed to get match data\n"); |
---|
1007 | 1199 | return -ENODEV; |
---|
1008 | 1200 | } |
---|
1009 | 1201 | |
---|
1010 | | - priv->data = match->data; |
---|
| 1202 | + priv->param = match_data->param; |
---|
1011 | 1203 | |
---|
1012 | | - indio_dev->name = priv->data->name; |
---|
1013 | | - indio_dev->dev.parent = &pdev->dev; |
---|
1014 | | - indio_dev->dev.of_node = pdev->dev.of_node; |
---|
| 1204 | + indio_dev->name = match_data->name; |
---|
1015 | 1205 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
1016 | 1206 | indio_dev->info = &meson_sar_adc_iio_info; |
---|
1017 | 1207 | |
---|
1018 | | - indio_dev->channels = meson_sar_adc_iio_channels; |
---|
1019 | | - indio_dev->num_channels = ARRAY_SIZE(meson_sar_adc_iio_channels); |
---|
1020 | | - |
---|
1021 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1022 | | - base = devm_ioremap_resource(&pdev->dev, res); |
---|
| 1208 | + base = devm_platform_ioremap_resource(pdev, 0); |
---|
1023 | 1209 | if (IS_ERR(base)) |
---|
1024 | 1210 | return PTR_ERR(base); |
---|
1025 | 1211 | |
---|
1026 | 1212 | priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
---|
1027 | | - priv->data->param->regmap_config); |
---|
| 1213 | + priv->param->regmap_config); |
---|
1028 | 1214 | if (IS_ERR(priv->regmap)) |
---|
1029 | 1215 | return PTR_ERR(priv->regmap); |
---|
1030 | 1216 | |
---|
.. | .. |
---|
1084 | 1270 | |
---|
1085 | 1271 | priv->calibscale = MILLION; |
---|
1086 | 1272 | |
---|
| 1273 | + if (priv->param->temperature_trimming_bits) { |
---|
| 1274 | + ret = meson_sar_adc_temp_sensor_init(indio_dev); |
---|
| 1275 | + if (ret) |
---|
| 1276 | + return ret; |
---|
| 1277 | + } |
---|
| 1278 | + |
---|
| 1279 | + if (priv->temperature_sensor_calibrated) { |
---|
| 1280 | + indio_dev->channels = meson_sar_adc_and_temp_iio_channels; |
---|
| 1281 | + indio_dev->num_channels = |
---|
| 1282 | + ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels); |
---|
| 1283 | + } else { |
---|
| 1284 | + indio_dev->channels = meson_sar_adc_iio_channels; |
---|
| 1285 | + indio_dev->num_channels = |
---|
| 1286 | + ARRAY_SIZE(meson_sar_adc_iio_channels); |
---|
| 1287 | + } |
---|
| 1288 | + |
---|
1087 | 1289 | ret = meson_sar_adc_init(indio_dev); |
---|
1088 | 1290 | if (ret) |
---|
1089 | 1291 | goto err; |
---|