Lines Matching +full:12 +full:bit +full:- +full:clk +full:- +full:divider
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>
10 #include <linux/clk.h>
34 #define JZ_ADC_REG_ENABLE_PD BIT(7)
35 #define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1))
36 #define JZ_ADC_REG_CFG_BAT_MD BIT(4)
39 #define JZ_ADC_REG_CFG_CMD_SEL BIT(22)
40 #define JZ_ADC_REG_CFG_TOUCH_OPS_MASK (BIT(31) | GENMASK(23, 10))
46 #define JZ_ADC_REG_ADCMD_YNADC BIT(7)
47 #define JZ_ADC_REG_ADCMD_YPADC BIT(8)
48 #define JZ_ADC_REG_ADCMD_XNADC BIT(9)
49 #define JZ_ADC_REG_ADCMD_XPADC BIT(10)
50 #define JZ_ADC_REG_ADCMD_VREFPYP BIT(11)
51 #define JZ_ADC_REG_ADCMD_VREFPXP BIT(12)
52 #define JZ_ADC_REG_ADCMD_VREFPXN BIT(13)
53 #define JZ_ADC_REG_ADCMD_VREFPAUX BIT(14)
54 #define JZ_ADC_REG_ADCMD_VREFPVDD33 BIT(15)
55 #define JZ_ADC_REG_ADCMD_VREFNYN BIT(16)
56 #define JZ_ADC_REG_ADCMD_VREFNXP BIT(17)
57 #define JZ_ADC_REG_ADCMD_VREFNXN BIT(18)
58 #define JZ_ADC_REG_ADCMD_VREFAUX BIT(19)
59 #define JZ_ADC_REG_ADCMD_YNGRU BIT(20)
60 #define JZ_ADC_REG_ADCMD_XNGRU BIT(21)
61 #define JZ_ADC_REG_ADCMD_XPGRU BIT(22)
62 #define JZ_ADC_REG_ADCMD_YPSUP BIT(23)
63 #define JZ_ADC_REG_ADCMD_XNSUP BIT(24)
64 #define JZ_ADC_REG_ADCMD_XPSUP BIT(25)
67 #define JZ_ADC_AUX_VREF_BITS 12
69 #define JZ_ADC_BATTERY_LOW_VREF_BITS 12
73 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
75 #define JZ4770_ADC_BATTERY_VREF_BITS 12
77 #define JZ_ADC_IRQ_AUX BIT(0)
78 #define JZ_ADC_IRQ_BATTERY BIT(1)
79 #define JZ_ADC_IRQ_TOUCH BIT(2)
80 #define JZ_ADC_IRQ_PEN_DOWN BIT(3)
81 #define JZ_ADC_IRQ_PEN_UP BIT(4)
82 #define JZ_ADC_IRQ_PEN_DOWN_SLEEP BIT(5)
83 #define JZ_ADC_IRQ_SLEEP BIT(7)
103 struct clk *clk; member
114 mutex_lock(&adc->lock); in ingenic_adc_set_adcmd()
117 readl(adc->base + JZ_ADC_REG_ADCMD); 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()
138 adc->base + JZ_ADC_REG_ADCMD); in ingenic_adc_set_adcmd()
144 adc->base + JZ_ADC_REG_ADCMD); 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()
189 val |= BIT(engine); in ingenic_adc_enable_unlocked()
191 val &= ~BIT(engine); 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()
223 !(val & BIT(engine)), 250, 1000); 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()
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()
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,
308 struct clk *parent_clk; in jz4725b_adc_init_clk_div()
312 parent_clk = clk_get_parent(adc->clk); in jz4725b_adc_init_clk_div()
315 return -ENODEV; in jz4725b_adc_init_clk_div()
322 * In practice we typically get 6 MHz, half of the 12 MHz EXT clock. in jz4725b_adc_init_clk_div()
328 dev_err(dev, "No valid divider for ADC main clock\n"); in jz4725b_adc_init_clk_div()
329 return -EINVAL; in jz4725b_adc_init_clk_div()
332 /* We also need a divider that produces a 10us clock. */ 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()
344 struct clk *parent_clk; in jz4770_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()
363 dev_err(dev, "No valid divider for ADC main clock\n"); in jz4770_adc_init_clk_div()
364 return -EINVAL; in jz4770_adc_init_clk_div()
367 /* We also need a divider that produces a 10us clock. */ 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()
384 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
385 BIT(IIO_CHAN_INFO_SCALE),
388 .scan_index = -1,
393 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
394 BIT(IIO_CHAN_INFO_SCALE),
395 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
396 BIT(IIO_CHAN_INFO_SCALE),
399 .scan_index = -1,
411 .realbits = 12,
422 .realbits = 12,
433 .realbits = 12,
444 .realbits = 12,
455 .realbits = 12,
466 .realbits = 12,
473 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
474 BIT(IIO_CHAN_INFO_SCALE),
477 .scan_index = -1,
482 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
483 BIT(IIO_CHAN_INFO_SCALE),
484 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
485 BIT(IIO_CHAN_INFO_SCALE),
488 .scan_index = -1,
493 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
494 BIT(IIO_CHAN_INFO_SCALE),
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() local
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()
586 ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit); 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()
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()
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()
732 unsigned long mask = iio_dev->active_scan_mask[0]; in ingenic_adc_irq()
738 tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); 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()
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",