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>
24 #define JZ_ADC_REG_ENABLE 0x00
25 #define JZ_ADC_REG_CFG 0x04
26 #define JZ_ADC_REG_CTRL 0x08
27 #define JZ_ADC_REG_STATUS 0x0c
28 #define JZ_ADC_REG_ADSAME 0x10
29 #define JZ_ADC_REG_ADWAIT 0x14
30 #define JZ_ADC_REG_ADTCH 0x18
31 #define JZ_ADC_REG_ADBDAT 0x1c
32 #define JZ_ADC_REG_ADSDAT 0x20
33 #define JZ_ADC_REG_ADCMD 0x24
34 #define JZ_ADC_REG_ADCLK 0x28
37 #define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1))
44 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
81 #define JZ_ADC_IRQ_AUX BIT(0)
118 mutex_lock(&adc->lock); in ingenic_adc_set_adcmd()
121 readl(adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
123 if (mask & 0x3) { in ingenic_adc_set_adcmd()
128 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
134 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
137 if (mask & 0xc) { in ingenic_adc_set_adcmd()
142 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
148 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
151 if (mask & 0x30) { in ingenic_adc_set_adcmd()
155 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
160 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
164 writel(0, adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
166 mutex_unlock(&adc->lock); in ingenic_adc_set_adcmd()
175 mutex_lock(&adc->lock); in ingenic_adc_set_config()
177 cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask; in ingenic_adc_set_config()
179 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_set_config()
181 mutex_unlock(&adc->lock); in ingenic_adc_set_config()
190 val = readb(adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
197 writeb(val, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
204 mutex_lock(&adc->lock); in ingenic_adc_enable()
206 mutex_unlock(&adc->lock); in ingenic_adc_enable()
221 mutex_lock(&adc->lock); in ingenic_adc_capture()
222 cfg = readl(adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
223 writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
226 ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val, in ingenic_adc_capture()
231 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
232 mutex_unlock(&adc->lock); in ingenic_adc_capture()
244 struct device *dev = iio_dev->dev.parent; in ingenic_adc_write_raw()
249 switch (chan->channel) { in ingenic_adc_write_raw()
251 if (!adc->soc_data->battery_vref_mode) in ingenic_adc_write_raw()
252 return -EINVAL; in ingenic_adc_write_raw()
254 ret = clk_enable(adc->clk); in ingenic_adc_write_raw()
264 0); in ingenic_adc_write_raw()
265 adc->low_vref_mode = false; in ingenic_adc_write_raw()
270 adc->low_vref_mode = true; in ingenic_adc_write_raw()
273 clk_disable(adc->clk); in ingenic_adc_write_raw()
275 return 0; in ingenic_adc_write_raw()
277 return -EINVAL; in ingenic_adc_write_raw()
280 return -EINVAL; in ingenic_adc_write_raw()
285 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
294 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
307 0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
320 parent_clk = clk_get_parent(adc->clk); in jz4725b_adc_init_clk_div()
323 return -ENODEV; in jz4725b_adc_init_clk_div()
337 return -EINVAL; in jz4725b_adc_init_clk_div()
343 writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4725b_adc_init_clk_div()
344 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4725b_adc_init_clk_div()
345 adc->base + JZ_ADC_REG_ADCLK); in jz4725b_adc_init_clk_div()
347 return 0; in jz4725b_adc_init_clk_div()
356 parent_clk = clk_get_parent(adc->clk); in jz4770_adc_init_clk_div()
359 return -ENODEV; in jz4770_adc_init_clk_div()
372 return -EINVAL; in jz4770_adc_init_clk_div()
380 writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) | in jz4770_adc_init_clk_div()
381 ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4770_adc_init_clk_div()
382 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4770_adc_init_clk_div()
383 adc->base + JZ_ADC_REG_ADCLK); in jz4770_adc_init_clk_div()
385 return 0; in jz4770_adc_init_clk_div()
394 .indexed = 1,
396 .scan_index = -1,
405 .indexed = 1,
407 .scan_index = -1,
417 .indexed = 1,
419 .scan_index = -1,
426 .indexed = 1,
428 .scan_index = -1,
435 .indexed = 1,
437 .scan_index = -1,
446 .indexed = 1,
448 .scan_index = -1,
455 .indexed = 1,
457 .scan_index = 0,
466 .indexed = 1,
477 .indexed = 1,
488 .indexed = 1,
499 .indexed = 1,
510 .indexed = 1,
524 .indexed = 1,
526 .scan_index = -1,
535 .indexed = 1,
537 .scan_index = -1,
544 .indexed = 1,
546 .scan_index = -1,
618 *length = adc->soc_data->battery_raw_avail_size; in ingenic_adc_read_avail()
619 *vals = adc->soc_data->battery_raw_avail; in ingenic_adc_read_avail()
623 *length = adc->soc_data->battery_scale_avail_size; in ingenic_adc_read_avail()
624 *vals = adc->soc_data->battery_scale_avail; in ingenic_adc_read_avail()
627 return -EINVAL; in ingenic_adc_read_avail()
635 int cmd, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); in ingenic_adc_read_chan_info_raw()
638 ret = clk_enable(adc->clk); in ingenic_adc_read_chan_info_raw()
640 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_read_chan_info_raw()
646 mutex_lock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
647 if (adc->soc_data->has_aux_md && engine == 0) { in ingenic_adc_read_chan_info_raw()
648 switch (chan->channel) { in ingenic_adc_read_chan_info_raw()
650 cmd = 0; in ingenic_adc_read_chan_info_raw()
667 switch (chan->channel) { in ingenic_adc_read_chan_info_raw()
671 *val = readw(adc->base + JZ_ADC_REG_ADSDAT); in ingenic_adc_read_chan_info_raw()
674 *val = readw(adc->base + JZ_ADC_REG_ADBDAT); in ingenic_adc_read_chan_info_raw()
680 mutex_unlock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
681 clk_disable(adc->clk); in ingenic_adc_read_chan_info_raw()
698 switch (chan->channel) { in ingenic_adc_read_raw()
706 if (adc->low_vref_mode) { in ingenic_adc_read_raw()
710 *val = adc->soc_data->battery_high_vref; in ingenic_adc_read_raw()
711 *val2 = adc->soc_data->battery_high_vref_bits; in ingenic_adc_read_raw()
718 return -EINVAL; in ingenic_adc_read_raw()
727 if (!iiospec->nargs) in ingenic_adc_fwnode_xlate()
728 return -EINVAL; in ingenic_adc_fwnode_xlate()
730 for (i = 0; i < iio_dev->num_channels; ++i) in ingenic_adc_fwnode_xlate()
731 if (iio_dev->channels[i].channel == iiospec->args[0]) in ingenic_adc_fwnode_xlate()
734 return -EINVAL; in ingenic_adc_fwnode_xlate()
749 ret = clk_enable(adc->clk); in ingenic_adc_buffer_enable()
751 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_buffer_enable()
762 writew(80, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_enable()
763 writew(2, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_enable()
764 writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_enable()
765 writel(0, adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_buffer_enable()
769 ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]); in ingenic_adc_buffer_enable()
773 return 0; in ingenic_adc_buffer_enable()
782 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0); in ingenic_adc_buffer_disable()
784 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_disable()
785 writeb(0xff, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_buffer_disable()
786 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0); in ingenic_adc_buffer_disable()
787 writew(0, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_disable()
788 writew(0, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_disable()
789 clk_disable(adc->clk); in ingenic_adc_buffer_disable()
791 return 0; in ingenic_adc_buffer_disable()
803 unsigned long mask = iio_dev->active_scan_mask[0]; in ingenic_adc_irq()
807 for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) { in ingenic_adc_irq()
808 if (mask & 0x3) in ingenic_adc_irq()
809 tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_irq()
811 tdat[i] = 0; in ingenic_adc_irq()
815 writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_irq()
822 struct device *dev = &pdev->dev; in ingenic_adc_probe()
830 return -EINVAL; in ingenic_adc_probe()
834 return -ENOMEM; in ingenic_adc_probe()
837 mutex_init(&adc->lock); in ingenic_adc_probe()
838 mutex_init(&adc->aux_lock); in ingenic_adc_probe()
839 adc->soc_data = soc_data; in ingenic_adc_probe()
841 irq = platform_get_irq(pdev, 0); in ingenic_adc_probe()
842 if (irq < 0) in ingenic_adc_probe()
845 ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0, in ingenic_adc_probe()
847 if (ret < 0) { in ingenic_adc_probe()
852 adc->base = devm_platform_ioremap_resource(pdev, 0); in ingenic_adc_probe()
853 if (IS_ERR(adc->base)) in ingenic_adc_probe()
854 return PTR_ERR(adc->base); in ingenic_adc_probe()
856 adc->clk = devm_clk_get_prepared(dev, "adc"); in ingenic_adc_probe()
857 if (IS_ERR(adc->clk)) { in ingenic_adc_probe()
859 return PTR_ERR(adc->clk); in ingenic_adc_probe()
862 ret = clk_enable(adc->clk); in ingenic_adc_probe()
869 if (soc_data->init_clk_div) { in ingenic_adc_probe()
870 ret = soc_data->init_clk_div(dev, adc); in ingenic_adc_probe()
872 clk_disable_unprepare(adc->clk); in ingenic_adc_probe()
878 writeb(0x00, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_probe()
879 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_probe()
882 if (device_property_present(dev, "ingenic,use-internal-divider")) in ingenic_adc_probe()
886 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_VBAT_SEL, 0); in ingenic_adc_probe()
889 clk_disable(adc->clk); in ingenic_adc_probe()
891 iio_dev->name = "jz-adc"; in ingenic_adc_probe()
892 iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in ingenic_adc_probe()
893 iio_dev->setup_ops = &ingenic_buffer_setup_ops; in ingenic_adc_probe()
894 iio_dev->channels = soc_data->channels; in ingenic_adc_probe()
895 iio_dev->num_channels = soc_data->num_channels; in ingenic_adc_probe()
896 iio_dev->info = &ingenic_adc_info; in ingenic_adc_probe()
906 { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
907 { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
908 { .compatible = "ingenic,jz4760-adc", .data = &jz4760_adc_soc_data, },
909 { .compatible = "ingenic,jz4760b-adc", .data = &jz4760_adc_soc_data, },
910 { .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
917 .name = "ingenic-adc",