Lines Matching +full:0 +full:- +full:indexed
1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2019 Artur Rojek <contact@artur-rojek.eu>
6 * based on drivers/mfd/jz4740-adc.c
9 #include <dt-bindings/iio/adc/ingenic,adc.h>
22 #define JZ_ADC_REG_ENABLE 0x00
23 #define JZ_ADC_REG_CFG 0x04
24 #define JZ_ADC_REG_CTRL 0x08
25 #define JZ_ADC_REG_STATUS 0x0c
26 #define JZ_ADC_REG_ADSAME 0x10
27 #define JZ_ADC_REG_ADWAIT 0x14
28 #define JZ_ADC_REG_ADTCH 0x18
29 #define JZ_ADC_REG_ADBDAT 0x1c
30 #define JZ_ADC_REG_ADSDAT 0x20
31 #define JZ_ADC_REG_ADCMD 0x24
32 #define JZ_ADC_REG_ADCLK 0x28
35 #define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1))
41 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
77 #define JZ_ADC_IRQ_AUX BIT(0)
114 mutex_lock(&adc->lock); in ingenic_adc_set_adcmd()
117 readl(adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
119 if (mask & 0x3) { in ingenic_adc_set_adcmd()
124 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
130 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
133 if (mask & 0xc) { in ingenic_adc_set_adcmd()
138 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
144 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
147 if (mask & 0x30) { in ingenic_adc_set_adcmd()
151 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
156 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
160 writel(0, adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
162 mutex_unlock(&adc->lock); in ingenic_adc_set_adcmd()
171 mutex_lock(&adc->lock); in ingenic_adc_set_config()
173 cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask; in ingenic_adc_set_config()
175 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_set_config()
177 mutex_unlock(&adc->lock); in ingenic_adc_set_config()
186 val = readb(adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
193 writeb(val, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
200 mutex_lock(&adc->lock); in ingenic_adc_enable()
202 mutex_unlock(&adc->lock); in ingenic_adc_enable()
217 mutex_lock(&adc->lock); in ingenic_adc_capture()
218 cfg = readl(adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
219 writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
222 ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val, in ingenic_adc_capture()
227 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
228 mutex_unlock(&adc->lock); in ingenic_adc_capture()
240 struct device *dev = iio_dev->dev.parent; in ingenic_adc_write_raw()
245 switch (chan->channel) { in ingenic_adc_write_raw()
247 if (!adc->soc_data->battery_vref_mode) in ingenic_adc_write_raw()
248 return -EINVAL; in ingenic_adc_write_raw()
250 ret = clk_enable(adc->clk); in ingenic_adc_write_raw()
260 0); in ingenic_adc_write_raw()
261 adc->low_vref_mode = false; in ingenic_adc_write_raw()
266 adc->low_vref_mode = true; in ingenic_adc_write_raw()
269 clk_disable(adc->clk); in ingenic_adc_write_raw()
271 return 0; in ingenic_adc_write_raw()
273 return -EINVAL; in ingenic_adc_write_raw()
276 return -EINVAL; in ingenic_adc_write_raw()
281 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
290 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
299 0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
312 parent_clk = clk_get_parent(adc->clk); in jz4725b_adc_init_clk_div()
315 return -ENODEV; in jz4725b_adc_init_clk_div()
329 return -EINVAL; in jz4725b_adc_init_clk_div()
335 writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4725b_adc_init_clk_div()
336 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4725b_adc_init_clk_div()
337 adc->base + JZ_ADC_REG_ADCLK); in jz4725b_adc_init_clk_div()
339 return 0; in jz4725b_adc_init_clk_div()
348 parent_clk = clk_get_parent(adc->clk); in jz4770_adc_init_clk_div()
351 return -ENODEV; in jz4770_adc_init_clk_div()
364 return -EINVAL; in jz4770_adc_init_clk_div()
372 writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) | in jz4770_adc_init_clk_div()
373 ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4770_adc_init_clk_div()
374 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4770_adc_init_clk_div()
375 adc->base + JZ_ADC_REG_ADCLK); in jz4770_adc_init_clk_div()
377 return 0; in jz4770_adc_init_clk_div()
386 .indexed = 1,
388 .scan_index = -1,
397 .indexed = 1,
399 .scan_index = -1,
406 .indexed = 1,
408 .scan_index = 0,
417 .indexed = 1,
428 .indexed = 1,
439 .indexed = 1,
450 .indexed = 1,
461 .indexed = 1,
475 .indexed = 1,
477 .scan_index = -1,
486 .indexed = 1,
488 .scan_index = -1,
495 .indexed = 1,
497 .scan_index = -1,
555 *length = adc->soc_data->battery_raw_avail_size; in ingenic_adc_read_avail()
556 *vals = adc->soc_data->battery_raw_avail; in ingenic_adc_read_avail()
560 *length = adc->soc_data->battery_scale_avail_size; in ingenic_adc_read_avail()
561 *vals = adc->soc_data->battery_scale_avail; in ingenic_adc_read_avail()
564 return -EINVAL; in ingenic_adc_read_avail()
572 int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); in ingenic_adc_read_chan_info_raw()
575 ret = clk_enable(adc->clk); in ingenic_adc_read_chan_info_raw()
577 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_read_chan_info_raw()
583 mutex_lock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
584 if (adc->soc_data->has_aux2 && engine == 0) { in ingenic_adc_read_chan_info_raw()
585 bit = BIT(chan->channel == INGENIC_ADC_AUX2); in ingenic_adc_read_chan_info_raw()
593 switch (chan->channel) { in ingenic_adc_read_chan_info_raw()
596 *val = readw(adc->base + JZ_ADC_REG_ADSDAT); in ingenic_adc_read_chan_info_raw()
599 *val = readw(adc->base + JZ_ADC_REG_ADBDAT); in ingenic_adc_read_chan_info_raw()
605 mutex_unlock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
606 clk_disable(adc->clk); in ingenic_adc_read_chan_info_raw()
623 switch (chan->channel) { in ingenic_adc_read_raw()
630 if (adc->low_vref_mode) { in ingenic_adc_read_raw()
634 *val = adc->soc_data->battery_high_vref; in ingenic_adc_read_raw()
635 *val2 = adc->soc_data->battery_high_vref_bits; in ingenic_adc_read_raw()
642 return -EINVAL; in ingenic_adc_read_raw()
651 if (!iiospec->args_count) in ingenic_adc_of_xlate()
652 return -EINVAL; in ingenic_adc_of_xlate()
654 for (i = 0; i < iio_dev->num_channels; ++i) in ingenic_adc_of_xlate()
655 if (iio_dev->channels[i].channel == iiospec->args[0]) in ingenic_adc_of_xlate()
658 return -EINVAL; in ingenic_adc_of_xlate()
678 ret = clk_enable(adc->clk); in ingenic_adc_buffer_enable()
680 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_buffer_enable()
691 writew(80, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_enable()
692 writew(2, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_enable()
693 writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_enable()
694 writel(0, adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_buffer_enable()
698 ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]); in ingenic_adc_buffer_enable()
702 return 0; in ingenic_adc_buffer_enable()
711 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0); in ingenic_adc_buffer_disable()
713 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_disable()
714 writeb(0xff, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_buffer_disable()
715 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0); in ingenic_adc_buffer_disable()
716 writew(0, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_disable()
717 writew(0, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_disable()
718 clk_disable(adc->clk); in ingenic_adc_buffer_disable()
720 return 0; in ingenic_adc_buffer_disable()
732 unsigned long mask = iio_dev->active_scan_mask[0]; in ingenic_adc_irq()
736 for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) { in ingenic_adc_irq()
737 if (mask & 0x3) in ingenic_adc_irq()
738 tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_irq()
740 tdat[i] = 0; in ingenic_adc_irq()
744 writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_irq()
751 struct device *dev = &pdev->dev; in ingenic_adc_probe()
759 return -EINVAL; in ingenic_adc_probe()
763 return -ENOMEM; in ingenic_adc_probe()
766 mutex_init(&adc->lock); in ingenic_adc_probe()
767 mutex_init(&adc->aux_lock); in ingenic_adc_probe()
768 adc->soc_data = soc_data; in ingenic_adc_probe()
770 irq = platform_get_irq(pdev, 0); in ingenic_adc_probe()
771 if (irq < 0) in ingenic_adc_probe()
774 ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0, in ingenic_adc_probe()
776 if (ret < 0) { in ingenic_adc_probe()
781 adc->base = devm_platform_ioremap_resource(pdev, 0); in ingenic_adc_probe()
782 if (IS_ERR(adc->base)) in ingenic_adc_probe()
783 return PTR_ERR(adc->base); in ingenic_adc_probe()
785 adc->clk = devm_clk_get(dev, "adc"); in ingenic_adc_probe()
786 if (IS_ERR(adc->clk)) { in ingenic_adc_probe()
788 return PTR_ERR(adc->clk); in ingenic_adc_probe()
791 ret = clk_prepare_enable(adc->clk); in ingenic_adc_probe()
798 if (soc_data->init_clk_div) { in ingenic_adc_probe()
799 ret = soc_data->init_clk_div(dev, adc); in ingenic_adc_probe()
801 clk_disable_unprepare(adc->clk); in ingenic_adc_probe()
807 writeb(0x00, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_probe()
808 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_probe()
810 clk_disable(adc->clk); in ingenic_adc_probe()
812 ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk); in ingenic_adc_probe()
818 iio_dev->name = "jz-adc"; in ingenic_adc_probe()
819 iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in ingenic_adc_probe()
820 iio_dev->setup_ops = &ingenic_buffer_setup_ops; in ingenic_adc_probe()
821 iio_dev->channels = soc_data->channels; in ingenic_adc_probe()
822 iio_dev->num_channels = soc_data->num_channels; in ingenic_adc_probe()
823 iio_dev->info = &ingenic_adc_info; in ingenic_adc_probe()
833 { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
834 { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
835 { .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
842 .name = "ingenic-adc",