Lines Matching +full:rzg2l +full:- +full:adc

1 // SPDX-License-Identifier: GPL-2.0
7 * Author: Lad Prabhakar <prabhakar.mahadev-[email protected]>
25 #define DRIVER_NAME "rzg2l-adc"
59 * struct rzg2l_adc_hw_params - ADC hardware specific parameters
60 * @default_adsmp: default ADC sampling period (see ADM3 register); index 0 is
62 * @adsmp_mask: ADC sampling period mask (see ADM3 register)
64 * @default_adcmp: default ADC cmp (see ADM3 register)
95 * struct rzg2l_adc_channel - ADC channel descriptor
96 * @name: ADC channel name
97 * @type: ADC channel type
116 static unsigned int rzg2l_adc_readl(struct rzg2l_adc *adc, u32 reg) in rzg2l_adc_readl() argument
118 return readl(adc->base + reg); in rzg2l_adc_readl()
121 static void rzg2l_adc_writel(struct rzg2l_adc *adc, unsigned int reg, u32 val) in rzg2l_adc_writel() argument
123 writel(val, adc->base + reg); in rzg2l_adc_writel()
126 static void rzg2l_adc_pwr(struct rzg2l_adc *adc, bool on) in rzg2l_adc_pwr() argument
130 reg = rzg2l_adc_readl(adc, RZG2L_ADM(0)); in rzg2l_adc_pwr()
135 rzg2l_adc_writel(adc, RZG2L_ADM(0), reg); in rzg2l_adc_pwr()
139 static void rzg2l_adc_start_stop(struct rzg2l_adc *adc, bool start) in rzg2l_adc_start_stop() argument
144 reg = rzg2l_adc_readl(adc, RZG2L_ADM(0)); in rzg2l_adc_start_stop()
149 rzg2l_adc_writel(adc, RZG2L_ADM(0), reg); in rzg2l_adc_start_stop()
155 200, 1000, true, adc, RZG2L_ADM(0)); in rzg2l_adc_start_stop()
157 pr_err("%s stopping ADC timed out\n", __func__); in rzg2l_adc_start_stop()
160 static void rzg2l_set_trigger(struct rzg2l_adc *adc) in rzg2l_set_trigger() argument
166 * EGA[13:12] - Set 00 to indicate hardware trigger is invalid in rzg2l_set_trigger()
167 * BS[4] - Enable 1-buffer mode in rzg2l_set_trigger()
168 * MS[1] - Enable Select mode in rzg2l_set_trigger()
169 * TRG[0] - Enable software trigger mode in rzg2l_set_trigger()
171 reg = rzg2l_adc_readl(adc, RZG2L_ADM(1)); in rzg2l_set_trigger()
176 rzg2l_adc_writel(adc, RZG2L_ADM(1), reg); in rzg2l_set_trigger()
187 static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch) in rzg2l_adc_conversion_setup() argument
189 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; in rzg2l_adc_conversion_setup()
193 if (rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_ADBSY) in rzg2l_adc_conversion_setup()
194 return -EBUSY; in rzg2l_adc_conversion_setup()
196 rzg2l_set_trigger(adc); in rzg2l_adc_conversion_setup()
199 reg = rzg2l_adc_readl(adc, RZG2L_ADM(2)); in rzg2l_adc_conversion_setup()
200 reg &= ~GENMASK(hw_params->num_channels - 1, 0); in rzg2l_adc_conversion_setup()
202 rzg2l_adc_writel(adc, RZG2L_ADM(2), reg); in rzg2l_adc_conversion_setup()
204 reg = rzg2l_adc_readl(adc, RZG2L_ADM(3)); in rzg2l_adc_conversion_setup()
205 reg &= ~hw_params->adsmp_mask; in rzg2l_adc_conversion_setup()
206 reg |= hw_params->default_adsmp[index]; in rzg2l_adc_conversion_setup()
207 rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); in rzg2l_adc_conversion_setup()
211 * INTS[31] - Select pulse signal in rzg2l_adc_conversion_setup()
212 * CSEEN[16] - Enable channel select error interrupt in rzg2l_adc_conversion_setup()
213 * INTEN[7:0] - Select channel interrupt in rzg2l_adc_conversion_setup()
215 reg = rzg2l_adc_readl(adc, RZG2L_ADINT); in rzg2l_adc_conversion_setup()
217 reg &= ~hw_params->adint_inten_mask; in rzg2l_adc_conversion_setup()
219 rzg2l_adc_writel(adc, RZG2L_ADINT, reg); in rzg2l_adc_conversion_setup()
224 static int rzg2l_adc_conversion(struct iio_dev *indio_dev, struct rzg2l_adc *adc, u8 ch) in rzg2l_adc_conversion() argument
226 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; in rzg2l_adc_conversion()
227 struct device *dev = indio_dev->dev.parent; in rzg2l_adc_conversion()
234 ret = rzg2l_adc_conversion_setup(adc, ch); in rzg2l_adc_conversion()
238 reinit_completion(&adc->completion); in rzg2l_adc_conversion()
240 rzg2l_adc_start_stop(adc, true); in rzg2l_adc_conversion()
242 if (!wait_for_completion_timeout(&adc->completion, RZG2L_ADC_TIMEOUT)) { in rzg2l_adc_conversion()
243 rzg2l_adc_writel(adc, RZG2L_ADINT, in rzg2l_adc_conversion()
244 rzg2l_adc_readl(adc, RZG2L_ADINT) & ~hw_params->adint_inten_mask); in rzg2l_adc_conversion()
245 ret = -ETIMEDOUT; in rzg2l_adc_conversion()
248 rzg2l_adc_start_stop(adc, false); in rzg2l_adc_conversion()
260 struct rzg2l_adc *adc = iio_priv(indio_dev); in rzg2l_adc_read_raw() local
265 if (chan->type != IIO_VOLTAGE && chan->type != IIO_TEMP) in rzg2l_adc_read_raw()
266 return -EINVAL; in rzg2l_adc_read_raw()
268 guard(mutex)(&adc->lock); in rzg2l_adc_read_raw()
270 ret = rzg2l_adc_conversion(indio_dev, adc, chan->channel); in rzg2l_adc_read_raw()
274 *val = adc->last_val[chan->channel]; in rzg2l_adc_read_raw()
280 return -EINVAL; in rzg2l_adc_read_raw()
288 return sysfs_emit(label, "%s\n", rzg2l_adc_channels[chan->channel].name); in rzg2l_adc_read_label()
298 struct rzg2l_adc *adc = dev_id; in rzg2l_adc_isr() local
299 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; in rzg2l_adc_isr()
304 reg = rzg2l_adc_readl(adc, RZG2L_ADSTS); in rzg2l_adc_isr()
308 rzg2l_adc_writel(adc, RZG2L_ADSTS, reg); in rzg2l_adc_isr()
312 intst = reg & GENMASK(hw_params->num_channels - 1, 0); in rzg2l_adc_isr()
316 for_each_set_bit(ch, &intst, hw_params->num_channels) in rzg2l_adc_isr()
317 adc->last_val[ch] = rzg2l_adc_readl(adc, RZG2L_ADCR(ch)) & RZG2L_ADCR_AD_MASK; in rzg2l_adc_isr()
320 rzg2l_adc_writel(adc, RZG2L_ADSTS, reg); in rzg2l_adc_isr()
322 complete(&adc->completion); in rzg2l_adc_isr()
327 static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc) in rzg2l_adc_parse_properties() argument
329 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; in rzg2l_adc_parse_properties()
337 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); in rzg2l_adc_parse_properties()
339 return -ENOMEM; in rzg2l_adc_parse_properties()
341 num_channels = device_get_child_node_count(&pdev->dev); in rzg2l_adc_parse_properties()
343 return dev_err_probe(&pdev->dev, -ENODEV, "no channel children\n"); in rzg2l_adc_parse_properties()
345 if (num_channels > hw_params->num_channels) in rzg2l_adc_parse_properties()
346 return dev_err_probe(&pdev->dev, -EINVAL, in rzg2l_adc_parse_properties()
349 chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array), in rzg2l_adc_parse_properties()
352 return -ENOMEM; in rzg2l_adc_parse_properties()
355 device_for_each_child_node_scoped(&pdev->dev, fwnode) { in rzg2l_adc_parse_properties()
360 if (channel >= hw_params->num_channels) in rzg2l_adc_parse_properties()
361 return -EINVAL; in rzg2l_adc_parse_properties()
371 data->num_channels = num_channels; in rzg2l_adc_parse_properties()
372 data->channels = chan_array; in rzg2l_adc_parse_properties()
373 adc->data = data; in rzg2l_adc_parse_properties()
378 static int rzg2l_adc_hw_init(struct device *dev, struct rzg2l_adc *adc) in rzg2l_adc_hw_init() argument
380 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; in rzg2l_adc_hw_init()
389 reg = rzg2l_adc_readl(adc, RZG2L_ADM(0)); in rzg2l_adc_hw_init()
391 rzg2l_adc_writel(adc, RZG2L_ADM(0), reg); in rzg2l_adc_hw_init()
394 200, 1000, false, adc, RZG2L_ADM(0)); in rzg2l_adc_hw_init()
398 if (hw_params->adivc) { in rzg2l_adc_hw_init()
400 reg = rzg2l_adc_readl(adc, RZG2L_ADIVC); in rzg2l_adc_hw_init()
403 rzg2l_adc_writel(adc, RZG2L_ADIVC, reg); in rzg2l_adc_hw_init()
408 * ADIL[31:24] - Should be always set to 0 in rzg2l_adc_hw_init()
409 * ADCMP[23:16] - Should be always set to 0xe in rzg2l_adc_hw_init()
410 * ADSMP[15:0] - Set default (0x578) sampling period in rzg2l_adc_hw_init()
412 reg = rzg2l_adc_readl(adc, RZG2L_ADM(3)); in rzg2l_adc_hw_init()
415 reg &= ~hw_params->adsmp_mask; in rzg2l_adc_hw_init()
416 reg |= FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, hw_params->default_adcmp) | in rzg2l_adc_hw_init()
417 hw_params->default_adsmp[0]; in rzg2l_adc_hw_init()
419 rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); in rzg2l_adc_hw_init()
429 struct device *dev = &pdev->dev; in rzg2l_adc_probe()
431 struct rzg2l_adc *adc; in rzg2l_adc_probe() local
435 indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); in rzg2l_adc_probe()
437 return -ENOMEM; in rzg2l_adc_probe()
439 adc = iio_priv(indio_dev); in rzg2l_adc_probe()
441 adc->hw_params = device_get_match_data(dev); in rzg2l_adc_probe()
442 if (!adc->hw_params || adc->hw_params->num_channels > RZG2L_ADC_MAX_CHANNELS) in rzg2l_adc_probe()
443 return -EINVAL; in rzg2l_adc_probe()
445 ret = rzg2l_adc_parse_properties(pdev, adc); in rzg2l_adc_probe()
449 mutex_init(&adc->lock); in rzg2l_adc_probe()
451 adc->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_adc_probe()
452 if (IS_ERR(adc->base)) in rzg2l_adc_probe()
453 return PTR_ERR(adc->base); in rzg2l_adc_probe()
455 adc->adrstn = devm_reset_control_get_exclusive_deasserted(dev, "adrst-n"); in rzg2l_adc_probe()
456 if (IS_ERR(adc->adrstn)) in rzg2l_adc_probe()
457 return dev_err_probe(dev, PTR_ERR(adc->adrstn), in rzg2l_adc_probe()
458 "failed to get/deassert adrst-n\n"); in rzg2l_adc_probe()
460 adc->presetn = devm_reset_control_get_exclusive_deasserted(dev, "presetn"); in rzg2l_adc_probe()
461 if (IS_ERR(adc->presetn)) in rzg2l_adc_probe()
462 return dev_err_probe(dev, PTR_ERR(adc->presetn), in rzg2l_adc_probe()
473 ret = rzg2l_adc_hw_init(dev, adc); in rzg2l_adc_probe()
475 return dev_err_probe(&pdev->dev, ret, in rzg2l_adc_probe()
476 "failed to initialize ADC HW\n"); in rzg2l_adc_probe()
483 0, dev_name(dev), adc); in rzg2l_adc_probe()
487 init_completion(&adc->completion); in rzg2l_adc_probe()
489 indio_dev->name = DRIVER_NAME; in rzg2l_adc_probe()
490 indio_dev->info = &rzg2l_adc_iio_info; in rzg2l_adc_probe()
491 indio_dev->modes = INDIO_DIRECT_MODE; in rzg2l_adc_probe()
492 indio_dev->channels = adc->data->channels; in rzg2l_adc_probe()
493 indio_dev->num_channels = adc->data->num_channels; in rzg2l_adc_probe()
516 { .compatible = "renesas,r9a08g045-adc", .data = &rzg3s_hw_params },
517 { .compatible = "renesas,rzg2l-adc", .data = &rzg2l_hw_params },
525 struct rzg2l_adc *adc = iio_priv(indio_dev); in rzg2l_adc_pm_runtime_suspend() local
527 rzg2l_adc_pwr(adc, false); in rzg2l_adc_pm_runtime_suspend()
535 struct rzg2l_adc *adc = iio_priv(indio_dev); in rzg2l_adc_pm_runtime_resume() local
537 rzg2l_adc_pwr(adc, true); in rzg2l_adc_pm_runtime_resume()
545 struct rzg2l_adc *adc = iio_priv(indio_dev); in rzg2l_adc_suspend() local
547 { .rstc = adc->presetn }, in rzg2l_adc_suspend()
548 { .rstc = adc->adrstn }, in rzg2l_adc_suspend()
553 adc->was_rpm_active = false; in rzg2l_adc_suspend()
558 adc->was_rpm_active = true; in rzg2l_adc_suspend()
568 if (adc->was_rpm_active) in rzg2l_adc_suspend()
577 struct rzg2l_adc *adc = iio_priv(indio_dev); in rzg2l_adc_resume() local
579 { .rstc = adc->adrstn }, in rzg2l_adc_resume()
580 { .rstc = adc->presetn }, in rzg2l_adc_resume()
588 if (adc->was_rpm_active) { in rzg2l_adc_resume()
594 ret = rzg2l_adc_hw_init(dev, adc); in rzg2l_adc_resume()
601 if (adc->was_rpm_active) { in rzg2l_adc_resume()
626 MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-[email protected]>");
627 MODULE_DESCRIPTION("Renesas RZ/G2L ADC driver");