Lines Matching +full:adc +full:- +full:clk

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * exynos_adc.c - Support for ADC in EXYNOS SoCs
5 * 8 ~ 10 channel, 10/12-bit ADC
19 #include <linux/clk.h>
34 #include <linux/platform_data/touchscreen-s3c2410.h>
47 /* S3C2410 ADC registers definitions */
64 /* Bit definitions for S3C2410 ADC */
127 struct clk *clk; member
128 struct clk *sclk;
148 * a wait-callback is used to wait for the conversion result,
171 if (info->data->needs_sclk) in exynos_adc_unprepare_clk()
172 clk_unprepare(info->sclk); in exynos_adc_unprepare_clk()
173 clk_unprepare(info->clk); in exynos_adc_unprepare_clk()
180 ret = clk_prepare(info->clk); in exynos_adc_prepare_clk()
182 dev_err(info->dev, "failed preparing adc clock: %d\n", ret); in exynos_adc_prepare_clk()
186 if (info->data->needs_sclk) { in exynos_adc_prepare_clk()
187 ret = clk_prepare(info->sclk); in exynos_adc_prepare_clk()
189 clk_unprepare(info->clk); in exynos_adc_prepare_clk()
190 dev_err(info->dev, in exynos_adc_prepare_clk()
201 if (info->data->needs_sclk) in exynos_adc_disable_clk()
202 clk_disable(info->sclk); in exynos_adc_disable_clk()
203 clk_disable(info->clk); in exynos_adc_disable_clk()
210 ret = clk_enable(info->clk); in exynos_adc_enable_clk()
212 dev_err(info->dev, "failed enabling adc clock: %d\n", ret); in exynos_adc_enable_clk()
216 if (info->data->needs_sclk) { in exynos_adc_enable_clk()
217 ret = clk_enable(info->sclk); in exynos_adc_enable_clk()
219 clk_disable(info->clk); in exynos_adc_enable_clk()
220 dev_err(info->dev, in exynos_adc_enable_clk()
233 if (info->data->needs_adc_phy) in exynos_adc_v1_init_hw()
234 regmap_write(info->pmu_map, info->data->phy_offset, 1); in exynos_adc_v1_init_hw()
239 /* Enable 12-bit ADC resolution */ in exynos_adc_v1_init_hw()
241 writel(con1, ADC_V1_CON(info->regs)); in exynos_adc_v1_init_hw()
244 writel(info->delay, ADC_V1_DLY(info->regs)); in exynos_adc_v1_init_hw()
251 if (info->data->needs_adc_phy) in exynos_adc_v1_exit_hw()
252 regmap_write(info->pmu_map, info->data->phy_offset, 0); in exynos_adc_v1_exit_hw()
254 con = readl(ADC_V1_CON(info->regs)); in exynos_adc_v1_exit_hw()
256 writel(con, ADC_V1_CON(info->regs)); in exynos_adc_v1_exit_hw()
261 writel(1, ADC_V1_INTCLR(info->regs)); in exynos_adc_v1_clear_irq()
269 writel(addr, ADC_V1_MUX(info->regs)); in exynos_adc_v1_start_conv()
271 con1 = readl(ADC_V1_CON(info->regs)); in exynos_adc_v1_start_conv()
272 writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); in exynos_adc_v1_start_conv()
278 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
290 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
302 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
315 /* Enable 12 bit ADC resolution */ in exynos_adc_s3c2416_start_conv()
316 con1 = readl(ADC_V1_CON(info->regs)); in exynos_adc_s3c2416_start_conv()
318 writel(con1, ADC_V1_CON(info->regs)); in exynos_adc_s3c2416_start_conv()
321 writel(addr, ADC_S3C2410_MUX(info->regs)); in exynos_adc_s3c2416_start_conv()
323 con1 = readl(ADC_V1_CON(info->regs)); in exynos_adc_s3c2416_start_conv()
324 writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); in exynos_adc_s3c2416_start_conv()
329 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
342 writel(addr, ADC_S3C2410_MUX(info->regs)); in exynos_adc_s3c2443_start_conv()
344 con1 = readl(ADC_V1_CON(info->regs)); in exynos_adc_s3c2443_start_conv()
345 writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); in exynos_adc_s3c2443_start_conv()
350 .mask = ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */
362 con1 = readl(ADC_V1_CON(info->regs)); in exynos_adc_s3c64xx_start_conv()
365 writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); in exynos_adc_s3c64xx_start_conv()
370 .mask = ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */
379 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
391 if (info->data->needs_adc_phy) in exynos_adc_v2_init_hw()
392 regmap_write(info->pmu_map, info->data->phy_offset, 1); in exynos_adc_v2_init_hw()
395 writel(con1, ADC_V2_CON1(info->regs)); in exynos_adc_v2_init_hw()
399 writel(con2, ADC_V2_CON2(info->regs)); in exynos_adc_v2_init_hw()
402 writel(1, ADC_V2_INT_EN(info->regs)); in exynos_adc_v2_init_hw()
409 if (info->data->needs_adc_phy) in exynos_adc_v2_exit_hw()
410 regmap_write(info->pmu_map, info->data->phy_offset, 0); in exynos_adc_v2_exit_hw()
412 con = readl(ADC_V2_CON1(info->regs)); in exynos_adc_v2_exit_hw()
414 writel(con, ADC_V2_CON1(info->regs)); in exynos_adc_v2_exit_hw()
419 writel(1, ADC_V2_INT_ST(info->regs)); in exynos_adc_v2_clear_irq()
427 con2 = readl(ADC_V2_CON2(info->regs)); in exynos_adc_v2_start_conv()
430 writel(con2, ADC_V2_CON2(info->regs)); in exynos_adc_v2_start_conv()
432 con1 = readl(ADC_V2_CON1(info->regs)); in exynos_adc_v2_start_conv()
433 writel(con1 | ADC_CON_EN_START, ADC_V2_CON1(info->regs)); in exynos_adc_v2_start_conv()
438 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
450 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
466 writel(con1, ADC_V2_CON1(info->regs)); in exynos_adc_exynos7_init_hw()
468 con2 = readl(ADC_V2_CON2(info->regs)); in exynos_adc_exynos7_init_hw()
471 writel(con2, ADC_V2_CON2(info->regs)); in exynos_adc_exynos7_init_hw()
474 writel(1, ADC_V2_INT_EN(info->regs)); in exynos_adc_exynos7_init_hw()
479 .mask = ADC_DATX_MASK, /* 12 bit ADC resolution */
489 .compatible = "samsung,s3c2410-adc",
492 .compatible = "samsung,s3c2416-adc",
495 .compatible = "samsung,s3c2440-adc",
498 .compatible = "samsung,s3c2443-adc",
501 .compatible = "samsung,s3c6410-adc",
504 .compatible = "samsung,s5pv210-adc",
507 .compatible = "samsung,exynos4212-adc",
510 .compatible = "samsung,exynos-adc-v1",
513 .compatible = "samsung,exynos-adc-v2",
516 .compatible = "samsung,exynos3250-adc",
519 .compatible = "samsung,exynos7-adc",
530 match = of_match_node(exynos_adc_match, pdev->dev.of_node); in exynos_adc_get_data()
531 return (struct exynos_adc_data *)match->data; in exynos_adc_get_data()
545 ret = regulator_get_voltage(info->vdd); in exynos_read_raw()
551 *val2 = info->data->mask; in exynos_read_raw()
555 return -EINVAL; in exynos_read_raw()
558 mutex_lock(&info->lock); in exynos_read_raw()
559 reinit_completion(&info->completion); in exynos_read_raw()
562 if (info->data->start_conv) in exynos_read_raw()
563 info->data->start_conv(info, chan->address); in exynos_read_raw()
565 time_left = wait_for_completion_timeout(&info->completion, in exynos_read_raw()
568 dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); in exynos_read_raw()
569 if (info->data->init_hw) in exynos_read_raw()
570 info->data->init_hw(info); in exynos_read_raw()
571 ret = -ETIMEDOUT; in exynos_read_raw()
573 *val = info->value; in exynos_read_raw()
578 mutex_unlock(&info->lock); in exynos_read_raw()
589 mutex_lock(&info->lock); in exynos_read_s3c64xx_ts()
590 info->read_ts = true; in exynos_read_s3c64xx_ts()
592 reinit_completion(&info->completion); in exynos_read_s3c64xx_ts()
595 ADC_V1_TSC(info->regs)); in exynos_read_s3c64xx_ts()
598 info->data->start_conv(info, ADC_S3C2410_MUX_TS); in exynos_read_s3c64xx_ts()
600 time_left = wait_for_completion_timeout(&info->completion, in exynos_read_s3c64xx_ts()
603 dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); in exynos_read_s3c64xx_ts()
604 if (info->data->init_hw) in exynos_read_s3c64xx_ts()
605 info->data->init_hw(info); in exynos_read_s3c64xx_ts()
606 ret = -ETIMEDOUT; in exynos_read_s3c64xx_ts()
608 *x = info->ts_x; in exynos_read_s3c64xx_ts()
609 *y = info->ts_y; in exynos_read_s3c64xx_ts()
613 info->read_ts = false; in exynos_read_s3c64xx_ts()
614 mutex_unlock(&info->lock); in exynos_read_s3c64xx_ts()
622 u32 mask = info->data->mask; in exynos_adc_isr()
625 if (info->read_ts) { in exynos_adc_isr()
626 info->ts_x = readl(ADC_V1_DATX(info->regs)); in exynos_adc_isr()
627 info->ts_y = readl(ADC_V1_DATY(info->regs)); in exynos_adc_isr()
628 writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs)); in exynos_adc_isr()
630 info->value = readl(ADC_V1_DATX(info->regs)) & mask; in exynos_adc_isr()
634 if (info->data->clear_irq) in exynos_adc_isr()
635 info->data->clear_irq(info); in exynos_adc_isr()
637 complete(&info->completion); in exynos_adc_isr()
652 struct iio_dev *dev = dev_get_drvdata(info->dev); in exynos_ts_isr()
657 while (READ_ONCE(info->ts_enabled)) { in exynos_ts_isr()
659 if (ret == -ETIMEDOUT) in exynos_ts_isr()
664 input_report_key(info->input, BTN_TOUCH, 0); in exynos_ts_isr()
665 input_sync(info->input); in exynos_ts_isr()
669 input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK); in exynos_ts_isr()
670 input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK); in exynos_ts_isr()
671 input_report_key(info->input, BTN_TOUCH, 1); in exynos_ts_isr()
672 input_sync(info->input); in exynos_ts_isr()
677 writel(0, ADC_V1_CLRINTPNDNUP(info->regs)); in exynos_ts_isr()
689 return -EINVAL; in exynos_adc_reg_access()
691 *readval = readl(info->regs + reg); in exynos_adc_reg_access()
737 WRITE_ONCE(info->ts_enabled, true); in exynos_adc_ts_open()
738 enable_irq(info->tsirq); in exynos_adc_ts_open()
747 WRITE_ONCE(info->ts_enabled, false); in exynos_adc_ts_close()
748 disable_irq(info->tsirq); in exynos_adc_ts_close()
755 if (info->tsirq <= 0) in exynos_adc_ts_init()
756 return -ENODEV; in exynos_adc_ts_init()
758 info->input = input_allocate_device(); in exynos_adc_ts_init()
759 if (!info->input) in exynos_adc_ts_init()
760 return -ENOMEM; in exynos_adc_ts_init()
762 info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); in exynos_adc_ts_init()
763 info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); in exynos_adc_ts_init()
765 input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0); in exynos_adc_ts_init()
766 input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0); in exynos_adc_ts_init()
768 info->input->name = "S3C24xx TouchScreen"; in exynos_adc_ts_init()
769 info->input->id.bustype = BUS_HOST; in exynos_adc_ts_init()
770 info->input->open = exynos_adc_ts_open; in exynos_adc_ts_init()
771 info->input->close = exynos_adc_ts_close; in exynos_adc_ts_init()
773 input_set_drvdata(info->input, info); in exynos_adc_ts_init()
775 ret = input_register_device(info->input); in exynos_adc_ts_init()
777 input_free_device(info->input); in exynos_adc_ts_init()
781 ret = request_threaded_irq(info->tsirq, NULL, exynos_ts_isr, in exynos_adc_ts_init()
785 input_unregister_device(info->input); in exynos_adc_ts_init()
793 struct device_node *np = pdev->dev.of_node; in exynos_adc_probe()
794 struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); in exynos_adc_probe()
800 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc)); in exynos_adc_probe()
802 dev_err(&pdev->dev, "failed allocating iio device\n"); in exynos_adc_probe()
803 return -ENOMEM; in exynos_adc_probe()
808 info->data = exynos_adc_get_data(pdev); in exynos_adc_probe()
809 if (!info->data) { in exynos_adc_probe()
810 dev_err(&pdev->dev, "failed getting exynos_adc_data\n"); in exynos_adc_probe()
811 return -EINVAL; in exynos_adc_probe()
814 info->regs = devm_platform_ioremap_resource(pdev, 0); in exynos_adc_probe()
815 if (IS_ERR(info->regs)) in exynos_adc_probe()
816 return PTR_ERR(info->regs); in exynos_adc_probe()
819 if (info->data->needs_adc_phy) { in exynos_adc_probe()
820 info->pmu_map = syscon_regmap_lookup_by_phandle( in exynos_adc_probe()
821 pdev->dev.of_node, in exynos_adc_probe()
822 "samsung,syscon-phandle"); in exynos_adc_probe()
823 if (IS_ERR(info->pmu_map)) { in exynos_adc_probe()
824 dev_err(&pdev->dev, "syscon regmap lookup failed.\n"); in exynos_adc_probe()
825 return PTR_ERR(info->pmu_map); in exynos_adc_probe()
831 has_ts = of_property_read_bool(pdev->dev.of_node, in exynos_adc_probe()
832 "has-touchscreen") || pdata; in exynos_adc_probe()
838 info->irq = irq; in exynos_adc_probe()
842 if (irq == -EPROBE_DEFER) in exynos_adc_probe()
845 info->tsirq = irq; in exynos_adc_probe()
847 info->tsirq = -1; in exynos_adc_probe()
850 info->dev = &pdev->dev; in exynos_adc_probe()
852 init_completion(&info->completion); in exynos_adc_probe()
854 info->clk = devm_clk_get(&pdev->dev, "adc"); in exynos_adc_probe()
855 if (IS_ERR(info->clk)) { in exynos_adc_probe()
856 dev_err(&pdev->dev, "failed getting clock, err = %ld\n", in exynos_adc_probe()
857 PTR_ERR(info->clk)); in exynos_adc_probe()
858 return PTR_ERR(info->clk); in exynos_adc_probe()
861 if (info->data->needs_sclk) { in exynos_adc_probe()
862 info->sclk = devm_clk_get(&pdev->dev, "sclk"); in exynos_adc_probe()
863 if (IS_ERR(info->sclk)) { in exynos_adc_probe()
864 dev_err(&pdev->dev, in exynos_adc_probe()
866 PTR_ERR(info->sclk)); in exynos_adc_probe()
867 return PTR_ERR(info->sclk); in exynos_adc_probe()
871 info->vdd = devm_regulator_get(&pdev->dev, "vdd"); in exynos_adc_probe()
872 if (IS_ERR(info->vdd)) in exynos_adc_probe()
873 return dev_err_probe(&pdev->dev, PTR_ERR(info->vdd), in exynos_adc_probe()
876 ret = regulator_enable(info->vdd); in exynos_adc_probe()
890 indio_dev->name = dev_name(&pdev->dev); in exynos_adc_probe()
891 indio_dev->info = &exynos_adc_iio_info; in exynos_adc_probe()
892 indio_dev->modes = INDIO_DIRECT_MODE; in exynos_adc_probe()
893 indio_dev->channels = exynos_adc_iio_channels; in exynos_adc_probe()
894 indio_dev->num_channels = info->data->num_channels; in exynos_adc_probe()
896 mutex_init(&info->lock); in exynos_adc_probe()
898 ret = request_irq(info->irq, exynos_adc_isr, in exynos_adc_probe()
899 0, dev_name(&pdev->dev), info); in exynos_adc_probe()
901 dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", in exynos_adc_probe()
902 info->irq); in exynos_adc_probe()
910 if (info->data->init_hw) in exynos_adc_probe()
911 info->data->init_hw(info); in exynos_adc_probe()
914 info->delay = pdata->delay; in exynos_adc_probe()
916 info->delay = 10000; in exynos_adc_probe()
923 ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); in exynos_adc_probe()
925 dev_err(&pdev->dev, "failed adding child nodes\n"); in exynos_adc_probe()
932 device_for_each_child(&indio_dev->dev, NULL, in exynos_adc_probe()
935 input_unregister_device(info->input); in exynos_adc_probe()
936 free_irq(info->tsirq, info); in exynos_adc_probe()
941 free_irq(info->irq, info); in exynos_adc_probe()
943 if (info->data->exit_hw) in exynos_adc_probe()
944 info->data->exit_hw(info); in exynos_adc_probe()
949 regulator_disable(info->vdd); in exynos_adc_probe()
958 if (IS_REACHABLE(CONFIG_INPUT) && info->input) { in exynos_adc_remove()
959 free_irq(info->tsirq, info); in exynos_adc_remove()
960 input_unregister_device(info->input); in exynos_adc_remove()
962 device_for_each_child(&indio_dev->dev, NULL, in exynos_adc_remove()
965 free_irq(info->irq, info); in exynos_adc_remove()
966 if (info->data->exit_hw) in exynos_adc_remove()
967 info->data->exit_hw(info); in exynos_adc_remove()
970 regulator_disable(info->vdd); in exynos_adc_remove()
978 if (info->data->exit_hw) in exynos_adc_suspend()
979 info->data->exit_hw(info); in exynos_adc_suspend()
981 regulator_disable(info->vdd); in exynos_adc_suspend()
992 ret = regulator_enable(info->vdd); in exynos_adc_resume()
1000 if (info->data->init_hw) in exynos_adc_resume()
1001 info->data->init_hw(info); in exynos_adc_resume()
1013 .name = "exynos-adc",
1022 MODULE_DESCRIPTION("Samsung EXYNOS5 ADC driver");