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))
42 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
79 #define JZ_ADC_IRQ_AUX BIT(0)
116 mutex_lock(&adc->lock); in ingenic_adc_set_adcmd()
119 readl(adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
121 if (mask & 0x3) { in ingenic_adc_set_adcmd()
126 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
132 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
135 if (mask & 0xc) { in ingenic_adc_set_adcmd()
140 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
146 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
149 if (mask & 0x30) { in ingenic_adc_set_adcmd()
153 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
158 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
162 writel(0, adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
164 mutex_unlock(&adc->lock); in ingenic_adc_set_adcmd()
173 mutex_lock(&adc->lock); in ingenic_adc_set_config()
175 cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask; in ingenic_adc_set_config()
177 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_set_config()
179 mutex_unlock(&adc->lock); in ingenic_adc_set_config()
188 val = readb(adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
195 writeb(val, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_enable_unlocked()
202 mutex_lock(&adc->lock); in ingenic_adc_enable()
204 mutex_unlock(&adc->lock); in ingenic_adc_enable()
219 mutex_lock(&adc->lock); in ingenic_adc_capture()
220 cfg = readl(adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
221 writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
224 ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val, in ingenic_adc_capture()
229 writel(cfg, adc->base + JZ_ADC_REG_CFG); in ingenic_adc_capture()
230 mutex_unlock(&adc->lock); in ingenic_adc_capture()
242 struct device *dev = iio_dev->dev.parent; in ingenic_adc_write_raw()
247 switch (chan->channel) { in ingenic_adc_write_raw()
249 if (!adc->soc_data->battery_vref_mode) in ingenic_adc_write_raw()
250 return -EINVAL; in ingenic_adc_write_raw()
252 ret = clk_enable(adc->clk); in ingenic_adc_write_raw()
262 0); in ingenic_adc_write_raw()
263 adc->low_vref_mode = false; in ingenic_adc_write_raw()
268 adc->low_vref_mode = true; in ingenic_adc_write_raw()
271 clk_disable(adc->clk); in ingenic_adc_write_raw()
273 return 0; in ingenic_adc_write_raw()
275 return -EINVAL; in ingenic_adc_write_raw()
278 return -EINVAL; in ingenic_adc_write_raw()
283 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
292 0, 1, (1 << JZ_ADC_BATTERY_LOW_VREF_BITS) - 1,
305 0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
318 parent_clk = clk_get_parent(adc->clk); in jz4725b_adc_init_clk_div()
321 return -ENODEV; in jz4725b_adc_init_clk_div()
335 return -EINVAL; in jz4725b_adc_init_clk_div()
341 writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4725b_adc_init_clk_div()
342 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4725b_adc_init_clk_div()
343 adc->base + JZ_ADC_REG_ADCLK); in jz4725b_adc_init_clk_div()
345 return 0; in jz4725b_adc_init_clk_div()
354 parent_clk = clk_get_parent(adc->clk); in jz4770_adc_init_clk_div()
357 return -ENODEV; in jz4770_adc_init_clk_div()
370 return -EINVAL; in jz4770_adc_init_clk_div()
378 writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) | in jz4770_adc_init_clk_div()
379 ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) | in jz4770_adc_init_clk_div()
380 (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, in jz4770_adc_init_clk_div()
381 adc->base + JZ_ADC_REG_ADCLK); in jz4770_adc_init_clk_div()
383 return 0; in jz4770_adc_init_clk_div()
392 .indexed = 1,
394 .scan_index = -1,
403 .indexed = 1,
405 .scan_index = -1,
415 .indexed = 1,
417 .scan_index = -1,
424 .indexed = 1,
426 .scan_index = -1,
433 .indexed = 1,
435 .scan_index = -1,
444 .indexed = 1,
446 .scan_index = -1,
453 .indexed = 1,
455 .scan_index = 0,
464 .indexed = 1,
475 .indexed = 1,
486 .indexed = 1,
497 .indexed = 1,
508 .indexed = 1,
522 .indexed = 1,
524 .scan_index = -1,
533 .indexed = 1,
535 .scan_index = -1,
542 .indexed = 1,
544 .scan_index = -1,
616 *length = adc->soc_data->battery_raw_avail_size; in ingenic_adc_read_avail()
617 *vals = adc->soc_data->battery_raw_avail; in ingenic_adc_read_avail()
621 *length = adc->soc_data->battery_scale_avail_size; in ingenic_adc_read_avail()
622 *vals = adc->soc_data->battery_scale_avail; in ingenic_adc_read_avail()
625 return -EINVAL; in ingenic_adc_read_avail()
633 int cmd, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); in ingenic_adc_read_chan_info_raw()
636 ret = clk_enable(adc->clk); in ingenic_adc_read_chan_info_raw()
638 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_read_chan_info_raw()
644 mutex_lock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
645 if (adc->soc_data->has_aux_md && engine == 0) { in ingenic_adc_read_chan_info_raw()
646 switch (chan->channel) { in ingenic_adc_read_chan_info_raw()
648 cmd = 0; in ingenic_adc_read_chan_info_raw()
665 switch (chan->channel) { in ingenic_adc_read_chan_info_raw()
669 *val = readw(adc->base + JZ_ADC_REG_ADSDAT); in ingenic_adc_read_chan_info_raw()
672 *val = readw(adc->base + JZ_ADC_REG_ADBDAT); in ingenic_adc_read_chan_info_raw()
678 mutex_unlock(&adc->aux_lock); in ingenic_adc_read_chan_info_raw()
679 clk_disable(adc->clk); in ingenic_adc_read_chan_info_raw()
696 switch (chan->channel) { in ingenic_adc_read_raw()
704 if (adc->low_vref_mode) { in ingenic_adc_read_raw()
708 *val = adc->soc_data->battery_high_vref; in ingenic_adc_read_raw()
709 *val2 = adc->soc_data->battery_high_vref_bits; in ingenic_adc_read_raw()
716 return -EINVAL; in ingenic_adc_read_raw()
725 if (!iiospec->args_count) in ingenic_adc_of_xlate()
726 return -EINVAL; in ingenic_adc_of_xlate()
728 for (i = 0; i < iio_dev->num_channels; ++i) in ingenic_adc_of_xlate()
729 if (iio_dev->channels[i].channel == iiospec->args[0]) in ingenic_adc_of_xlate()
732 return -EINVAL; in ingenic_adc_of_xlate()
752 ret = clk_enable(adc->clk); in ingenic_adc_buffer_enable()
754 dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", in ingenic_adc_buffer_enable()
765 writew(80, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_enable()
766 writew(2, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_enable()
767 writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_enable()
768 writel(0, adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_buffer_enable()
772 ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]); in ingenic_adc_buffer_enable()
776 return 0; in ingenic_adc_buffer_enable()
785 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0); in ingenic_adc_buffer_disable()
787 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_buffer_disable()
788 writeb(0xff, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_buffer_disable()
789 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0); in ingenic_adc_buffer_disable()
790 writew(0, adc->base + JZ_ADC_REG_ADSAME); in ingenic_adc_buffer_disable()
791 writew(0, adc->base + JZ_ADC_REG_ADWAIT); in ingenic_adc_buffer_disable()
792 clk_disable(adc->clk); in ingenic_adc_buffer_disable()
794 return 0; in ingenic_adc_buffer_disable()
806 unsigned long mask = iio_dev->active_scan_mask[0]; in ingenic_adc_irq()
810 for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) { in ingenic_adc_irq()
811 if (mask & 0x3) in ingenic_adc_irq()
812 tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); in ingenic_adc_irq()
814 tdat[i] = 0; in ingenic_adc_irq()
818 writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS); in ingenic_adc_irq()
825 struct device *dev = &pdev->dev; in ingenic_adc_probe()
833 return -EINVAL; in ingenic_adc_probe()
837 return -ENOMEM; in ingenic_adc_probe()
840 mutex_init(&adc->lock); in ingenic_adc_probe()
841 mutex_init(&adc->aux_lock); in ingenic_adc_probe()
842 adc->soc_data = soc_data; in ingenic_adc_probe()
844 irq = platform_get_irq(pdev, 0); in ingenic_adc_probe()
845 if (irq < 0) in ingenic_adc_probe()
848 ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0, in ingenic_adc_probe()
850 if (ret < 0) { in ingenic_adc_probe()
855 adc->base = devm_platform_ioremap_resource(pdev, 0); in ingenic_adc_probe()
856 if (IS_ERR(adc->base)) in ingenic_adc_probe()
857 return PTR_ERR(adc->base); in ingenic_adc_probe()
859 adc->clk = devm_clk_get(dev, "adc"); in ingenic_adc_probe()
860 if (IS_ERR(adc->clk)) { in ingenic_adc_probe()
862 return PTR_ERR(adc->clk); in ingenic_adc_probe()
865 ret = clk_prepare_enable(adc->clk); in ingenic_adc_probe()
872 if (soc_data->init_clk_div) { in ingenic_adc_probe()
873 ret = soc_data->init_clk_div(dev, adc); in ingenic_adc_probe()
875 clk_disable_unprepare(adc->clk); in ingenic_adc_probe()
881 writeb(0x00, adc->base + JZ_ADC_REG_ENABLE); in ingenic_adc_probe()
882 writeb(0xff, adc->base + JZ_ADC_REG_CTRL); in ingenic_adc_probe()
885 if (device_property_present(dev, "ingenic,use-internal-divider")) in ingenic_adc_probe()
889 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_VBAT_SEL, 0); in ingenic_adc_probe()
892 clk_disable(adc->clk); in ingenic_adc_probe()
894 ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk); in ingenic_adc_probe()
900 iio_dev->name = "jz-adc"; in ingenic_adc_probe()
901 iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; in ingenic_adc_probe()
902 iio_dev->setup_ops = &ingenic_buffer_setup_ops; in ingenic_adc_probe()
903 iio_dev->channels = soc_data->channels; in ingenic_adc_probe()
904 iio_dev->num_channels = soc_data->num_channels; in ingenic_adc_probe()
905 iio_dev->info = &ingenic_adc_info; in ingenic_adc_probe()
915 { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
916 { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
917 { .compatible = "ingenic,jz4760-adc", .data = &jz4760_adc_soc_data, },
918 { .compatible = "ingenic,jz4760b-adc", .data = &jz4760_adc_soc_data, },
919 { .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
926 .name = "ingenic-adc",