101636eb9SPatil, Rachna /*
201636eb9SPatil, Rachna  * TI Touch Screen / ADC MFD driver
301636eb9SPatil, Rachna  *
401636eb9SPatil, Rachna  * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
501636eb9SPatil, Rachna  *
601636eb9SPatil, Rachna  * This program is free software; you can redistribute it and/or
701636eb9SPatil, Rachna  * modify it under the terms of the GNU General Public License as
801636eb9SPatil, Rachna  * published by the Free Software Foundation version 2.
901636eb9SPatil, Rachna  *
1001636eb9SPatil, Rachna  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
1101636eb9SPatil, Rachna  * kind, whether express or implied; without even the implied warranty
1201636eb9SPatil, Rachna  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1301636eb9SPatil, Rachna  * GNU General Public License for more details.
1401636eb9SPatil, Rachna  */
1501636eb9SPatil, Rachna 
1601636eb9SPatil, Rachna #include <linux/module.h>
1701636eb9SPatil, Rachna #include <linux/slab.h>
1801636eb9SPatil, Rachna #include <linux/err.h>
1901636eb9SPatil, Rachna #include <linux/io.h>
2001636eb9SPatil, Rachna #include <linux/clk.h>
2101636eb9SPatil, Rachna #include <linux/regmap.h>
2201636eb9SPatil, Rachna #include <linux/mfd/core.h>
2301636eb9SPatil, Rachna #include <linux/pm_runtime.h>
24a6543a1cSPatil, Rachna #include <linux/of.h>
25a6543a1cSPatil, Rachna #include <linux/of_device.h>
267ca6740cSSebastian Andrzej Siewior #include <linux/sched.h>
2701636eb9SPatil, Rachna 
2801636eb9SPatil, Rachna #include <linux/mfd/ti_am335x_tscadc.h>
2901636eb9SPatil, Rachna 
3001636eb9SPatil, Rachna static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
3101636eb9SPatil, Rachna {
3201636eb9SPatil, Rachna 	unsigned int val;
3301636eb9SPatil, Rachna 
3401636eb9SPatil, Rachna 	regmap_read(tsadc->regmap_tscadc, reg, &val);
3501636eb9SPatil, Rachna 	return val;
3601636eb9SPatil, Rachna }
3701636eb9SPatil, Rachna 
3801636eb9SPatil, Rachna static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg,
3901636eb9SPatil, Rachna 					unsigned int val)
4001636eb9SPatil, Rachna {
4101636eb9SPatil, Rachna 	regmap_write(tsadc->regmap_tscadc, reg, val);
4201636eb9SPatil, Rachna }
4301636eb9SPatil, Rachna 
4401636eb9SPatil, Rachna static const struct regmap_config tscadc_regmap_config = {
4501636eb9SPatil, Rachna 	.name = "ti_tscadc",
4601636eb9SPatil, Rachna 	.reg_bits = 32,
4701636eb9SPatil, Rachna 	.reg_stride = 4,
4801636eb9SPatil, Rachna 	.val_bits = 32,
4901636eb9SPatil, Rachna };
5001636eb9SPatil, Rachna 
517e170c6eSSebastian Andrzej Siewior void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
52abeccee4SPatil, Rachna {
53317b2099SSebastian Andrzej Siewior 	unsigned long flags;
54317b2099SSebastian Andrzej Siewior 
55317b2099SSebastian Andrzej Siewior 	spin_lock_irqsave(&tsadc->reg_lock, flags);
567ca6740cSSebastian Andrzej Siewior 	tsadc->reg_se_cache = val;
577ca6740cSSebastian Andrzej Siewior 	if (tsadc->adc_waiting)
587ca6740cSSebastian Andrzej Siewior 		wake_up(&tsadc->reg_se_wait);
597ca6740cSSebastian Andrzej Siewior 	else if (!tsadc->adc_in_use)
607ca6740cSSebastian Andrzej Siewior 		tscadc_writel(tsadc, REG_SE, val);
617ca6740cSSebastian Andrzej Siewior 
62317b2099SSebastian Andrzej Siewior 	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
63abeccee4SPatil, Rachna }
647e170c6eSSebastian Andrzej Siewior EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
657e170c6eSSebastian Andrzej Siewior 
667ca6740cSSebastian Andrzej Siewior static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
677ca6740cSSebastian Andrzej Siewior {
687ca6740cSSebastian Andrzej Siewior 	DEFINE_WAIT(wait);
697ca6740cSSebastian Andrzej Siewior 	u32 reg;
707ca6740cSSebastian Andrzej Siewior 
717ca6740cSSebastian Andrzej Siewior 	/*
727ca6740cSSebastian Andrzej Siewior 	 * disable TSC steps so it does not run while the ADC is using it. If
737ca6740cSSebastian Andrzej Siewior 	 * write 0 while it is running (it just started or was already running)
747ca6740cSSebastian Andrzej Siewior 	 * then it completes all steps that were enabled and stops then.
757ca6740cSSebastian Andrzej Siewior 	 */
767ca6740cSSebastian Andrzej Siewior 	tscadc_writel(tsadc, REG_SE, 0);
777ca6740cSSebastian Andrzej Siewior 	reg = tscadc_readl(tsadc, REG_ADCFSM);
787ca6740cSSebastian Andrzej Siewior 	if (reg & SEQ_STATUS) {
797ca6740cSSebastian Andrzej Siewior 		tsadc->adc_waiting = true;
807ca6740cSSebastian Andrzej Siewior 		prepare_to_wait(&tsadc->reg_se_wait, &wait,
817ca6740cSSebastian Andrzej Siewior 				TASK_UNINTERRUPTIBLE);
827ca6740cSSebastian Andrzej Siewior 		spin_unlock_irq(&tsadc->reg_lock);
837ca6740cSSebastian Andrzej Siewior 
847ca6740cSSebastian Andrzej Siewior 		schedule();
857ca6740cSSebastian Andrzej Siewior 
867ca6740cSSebastian Andrzej Siewior 		spin_lock_irq(&tsadc->reg_lock);
877ca6740cSSebastian Andrzej Siewior 		finish_wait(&tsadc->reg_se_wait, &wait);
887ca6740cSSebastian Andrzej Siewior 
897ca6740cSSebastian Andrzej Siewior 		reg = tscadc_readl(tsadc, REG_ADCFSM);
907ca6740cSSebastian Andrzej Siewior 		WARN_ON(reg & SEQ_STATUS);
917ca6740cSSebastian Andrzej Siewior 		tsadc->adc_waiting = false;
927ca6740cSSebastian Andrzej Siewior 	}
937ca6740cSSebastian Andrzej Siewior 	tsadc->adc_in_use = true;
947ca6740cSSebastian Andrzej Siewior }
957ca6740cSSebastian Andrzej Siewior 
967e170c6eSSebastian Andrzej Siewior void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
977e170c6eSSebastian Andrzej Siewior {
987ca6740cSSebastian Andrzej Siewior 	spin_lock_irq(&tsadc->reg_lock);
997ca6740cSSebastian Andrzej Siewior 	am335x_tscadc_need_adc(tsadc);
1007ca6740cSSebastian Andrzej Siewior 
1017ca6740cSSebastian Andrzej Siewior 	tscadc_writel(tsadc, REG_SE, val);
1027ca6740cSSebastian Andrzej Siewior 	spin_unlock_irq(&tsadc->reg_lock);
1037ca6740cSSebastian Andrzej Siewior }
1047ca6740cSSebastian Andrzej Siewior EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
1057ca6740cSSebastian Andrzej Siewior 
1067ca6740cSSebastian Andrzej Siewior void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
1077ca6740cSSebastian Andrzej Siewior {
1087e170c6eSSebastian Andrzej Siewior 	unsigned long flags;
1097e170c6eSSebastian Andrzej Siewior 
1107e170c6eSSebastian Andrzej Siewior 	spin_lock_irqsave(&tsadc->reg_lock, flags);
1117ca6740cSSebastian Andrzej Siewior 	tsadc->adc_in_use = false;
1127ca6740cSSebastian Andrzej Siewior 	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
1137e170c6eSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
1147e170c6eSSebastian Andrzej Siewior }
1157ca6740cSSebastian Andrzej Siewior EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
116abeccee4SPatil, Rachna 
117abeccee4SPatil, Rachna void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
118abeccee4SPatil, Rachna {
119317b2099SSebastian Andrzej Siewior 	unsigned long flags;
120317b2099SSebastian Andrzej Siewior 
121317b2099SSebastian Andrzej Siewior 	spin_lock_irqsave(&tsadc->reg_lock, flags);
122abeccee4SPatil, Rachna 	tsadc->reg_se_cache &= ~val;
1237ca6740cSSebastian Andrzej Siewior 	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
124317b2099SSebastian Andrzej Siewior 	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
125abeccee4SPatil, Rachna }
126abeccee4SPatil, Rachna EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
127abeccee4SPatil, Rachna 
12801636eb9SPatil, Rachna static void tscadc_idle_config(struct ti_tscadc_dev *config)
12901636eb9SPatil, Rachna {
13001636eb9SPatil, Rachna 	unsigned int idleconfig;
13101636eb9SPatil, Rachna 
13201636eb9SPatil, Rachna 	idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
13301636eb9SPatil, Rachna 			STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
13401636eb9SPatil, Rachna 
13501636eb9SPatil, Rachna 	tscadc_writel(config, REG_IDLECONFIG, idleconfig);
13601636eb9SPatil, Rachna }
13701636eb9SPatil, Rachna 
138612b95cdSGreg Kroah-Hartman static	int ti_tscadc_probe(struct platform_device *pdev)
13901636eb9SPatil, Rachna {
14001636eb9SPatil, Rachna 	struct ti_tscadc_dev	*tscadc;
14101636eb9SPatil, Rachna 	struct resource		*res;
14201636eb9SPatil, Rachna 	struct clk		*clk;
143a6543a1cSPatil, Rachna 	struct device_node	*node = pdev->dev.of_node;
1442b99bafaSPatil, Rachna 	struct mfd_cell		*cell;
14518926edeSSebastian Andrzej Siewior 	struct property         *prop;
14618926edeSSebastian Andrzej Siewior 	const __be32            *cur;
14718926edeSSebastian Andrzej Siewior 	u32			val;
14801636eb9SPatil, Rachna 	int			err, ctrl;
149e90f8754SMatthias Kaehlcke 	int			clock_rate;
150a6543a1cSPatil, Rachna 	int			tsc_wires = 0, adc_channels = 0, total_channels;
15118926edeSSebastian Andrzej Siewior 	int			readouts = 0;
15201636eb9SPatil, Rachna 
1539e5775f3SSebastian Andrzej Siewior 	if (!pdev->dev.of_node) {
1549e5775f3SSebastian Andrzej Siewior 		dev_err(&pdev->dev, "Could not find valid DT data.\n");
15501636eb9SPatil, Rachna 		return -EINVAL;
15601636eb9SPatil, Rachna 	}
15701636eb9SPatil, Rachna 
158a6543a1cSPatil, Rachna 	node = of_get_child_by_name(pdev->dev.of_node, "tsc");
159a6543a1cSPatil, Rachna 	of_property_read_u32(node, "ti,wires", &tsc_wires);
16018926edeSSebastian Andrzej Siewior 	of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
1615e53a69bSPatil, Rachna 
162a6543a1cSPatil, Rachna 	node = of_get_child_by_name(pdev->dev.of_node, "adc");
16318926edeSSebastian Andrzej Siewior 	of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
16418926edeSSebastian Andrzej Siewior 		adc_channels++;
16518926edeSSebastian Andrzej Siewior 		if (val > 7) {
16618926edeSSebastian Andrzej Siewior 			dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
16718926edeSSebastian Andrzej Siewior 					val);
16818926edeSSebastian Andrzej Siewior 			return -EINVAL;
16918926edeSSebastian Andrzej Siewior 		}
17018926edeSSebastian Andrzej Siewior 	}
1715e53a69bSPatil, Rachna 	total_channels = tsc_wires + adc_channels;
1725e53a69bSPatil, Rachna 	if (total_channels > 8) {
1735e53a69bSPatil, Rachna 		dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
1745e53a69bSPatil, Rachna 		return -EINVAL;
1755e53a69bSPatil, Rachna 	}
17624d5c82fSPantelis Antoniou 	if (total_channels == 0) {
17724d5c82fSPantelis Antoniou 		dev_err(&pdev->dev, "Need atleast one channel.\n");
17824d5c82fSPantelis Antoniou 		return -EINVAL;
17924d5c82fSPantelis Antoniou 	}
1802b99bafaSPatil, Rachna 
18118926edeSSebastian Andrzej Siewior 	if (readouts * 2 + 2 + adc_channels > 16) {
18218926edeSSebastian Andrzej Siewior 		dev_err(&pdev->dev, "Too many step configurations requested\n");
18318926edeSSebastian Andrzej Siewior 		return -EINVAL;
18418926edeSSebastian Andrzej Siewior 	}
18518926edeSSebastian Andrzej Siewior 
18601636eb9SPatil, Rachna 	/* Allocate memory for device */
18701636eb9SPatil, Rachna 	tscadc = devm_kzalloc(&pdev->dev,
18801636eb9SPatil, Rachna 			sizeof(struct ti_tscadc_dev), GFP_KERNEL);
18901636eb9SPatil, Rachna 	if (!tscadc) {
19001636eb9SPatil, Rachna 		dev_err(&pdev->dev, "failed to allocate memory.\n");
19101636eb9SPatil, Rachna 		return -ENOMEM;
19201636eb9SPatil, Rachna 	}
19301636eb9SPatil, Rachna 	tscadc->dev = &pdev->dev;
1943c39c9c6SPatil, Rachna 
1953c39c9c6SPatil, Rachna 	err = platform_get_irq(pdev, 0);
1963c39c9c6SPatil, Rachna 	if (err < 0) {
1973c39c9c6SPatil, Rachna 		dev_err(&pdev->dev, "no irq ID is specified.\n");
1983c39c9c6SPatil, Rachna 		goto ret;
1993c39c9c6SPatil, Rachna 	} else
2003c39c9c6SPatil, Rachna 		tscadc->irq = err;
20101636eb9SPatil, Rachna 
202924ff918SJingoo Han 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203924ff918SJingoo Han 	tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
204924ff918SJingoo Han 	if (IS_ERR(tscadc->tscadc_base))
205924ff918SJingoo Han 		return PTR_ERR(tscadc->tscadc_base);
20601636eb9SPatil, Rachna 
20701636eb9SPatil, Rachna 	tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
20801636eb9SPatil, Rachna 			tscadc->tscadc_base, &tscadc_regmap_config);
20901636eb9SPatil, Rachna 	if (IS_ERR(tscadc->regmap_tscadc)) {
21001636eb9SPatil, Rachna 		dev_err(&pdev->dev, "regmap init failed\n");
21101636eb9SPatil, Rachna 		err = PTR_ERR(tscadc->regmap_tscadc);
2123c39c9c6SPatil, Rachna 		goto ret;
21301636eb9SPatil, Rachna 	}
21401636eb9SPatil, Rachna 
215abeccee4SPatil, Rachna 	spin_lock_init(&tscadc->reg_lock);
2167ca6740cSSebastian Andrzej Siewior 	init_waitqueue_head(&tscadc->reg_se_wait);
2177ca6740cSSebastian Andrzej Siewior 
21801636eb9SPatil, Rachna 	pm_runtime_enable(&pdev->dev);
21901636eb9SPatil, Rachna 	pm_runtime_get_sync(&pdev->dev);
22001636eb9SPatil, Rachna 
22101636eb9SPatil, Rachna 	/*
22201636eb9SPatil, Rachna 	 * The TSC_ADC_Subsystem has 2 clock domains
22301636eb9SPatil, Rachna 	 * OCP_CLK and ADC_CLK.
22401636eb9SPatil, Rachna 	 * The ADC clock is expected to run at target of 3MHz,
22501636eb9SPatil, Rachna 	 * and expected to capture 12-bit data at a rate of 200 KSPS.
22601636eb9SPatil, Rachna 	 * The TSC_ADC_SS controller design assumes the OCP clock is
22701636eb9SPatil, Rachna 	 * at least 6x faster than the ADC clock.
22801636eb9SPatil, Rachna 	 */
22901636eb9SPatil, Rachna 	clk = clk_get(&pdev->dev, "adc_tsc_fck");
23001636eb9SPatil, Rachna 	if (IS_ERR(clk)) {
23101636eb9SPatil, Rachna 		dev_err(&pdev->dev, "failed to get TSC fck\n");
23201636eb9SPatil, Rachna 		err = PTR_ERR(clk);
23301636eb9SPatil, Rachna 		goto err_disable_clk;
23401636eb9SPatil, Rachna 	}
23501636eb9SPatil, Rachna 	clock_rate = clk_get_rate(clk);
23601636eb9SPatil, Rachna 	clk_put(clk);
237e90f8754SMatthias Kaehlcke 	tscadc->clk_div = clock_rate / ADC_CLK;
238efe3126aSPatil, Rachna 
23901636eb9SPatil, Rachna 	/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
240e90f8754SMatthias Kaehlcke 	tscadc->clk_div--;
241e90f8754SMatthias Kaehlcke 	tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div);
24201636eb9SPatil, Rachna 
24301636eb9SPatil, Rachna 	/* Set the control register bits */
24401636eb9SPatil, Rachna 	ctrl = CNTRLREG_STEPCONFIGWRT |
245b5f8b763SPatil, Rachna 			CNTRLREG_STEPID;
246b5f8b763SPatil, Rachna 	if (tsc_wires > 0)
247b5f8b763SPatil, Rachna 		ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
24801636eb9SPatil, Rachna 	tscadc_writel(tscadc, REG_CTRL, ctrl);
24901636eb9SPatil, Rachna 
25001636eb9SPatil, Rachna 	/* Set register bits for Idle Config Mode */
251b5f8b763SPatil, Rachna 	if (tsc_wires > 0)
25201636eb9SPatil, Rachna 		tscadc_idle_config(tscadc);
25301636eb9SPatil, Rachna 
25401636eb9SPatil, Rachna 	/* Enable the TSC module enable bit */
25501636eb9SPatil, Rachna 	ctrl = tscadc_readl(tscadc, REG_CTRL);
25601636eb9SPatil, Rachna 	ctrl |= CNTRLREG_TSCSSENB;
25701636eb9SPatil, Rachna 	tscadc_writel(tscadc, REG_CTRL, ctrl);
25801636eb9SPatil, Rachna 
25924d5c82fSPantelis Antoniou 	tscadc->used_cells = 0;
26024d5c82fSPantelis Antoniou 	tscadc->tsc_cell = -1;
26124d5c82fSPantelis Antoniou 	tscadc->adc_cell = -1;
26224d5c82fSPantelis Antoniou 
2632b99bafaSPatil, Rachna 	/* TSC Cell */
26424d5c82fSPantelis Antoniou 	if (tsc_wires > 0) {
26524d5c82fSPantelis Antoniou 		tscadc->tsc_cell = tscadc->used_cells;
26624d5c82fSPantelis Antoniou 		cell = &tscadc->cells[tscadc->used_cells++];
2675f184e63SSebastian Andrzej Siewior 		cell->name = "TI-am335x-tsc";
2680396310bSPatil, Rachna 		cell->of_compatible = "ti,am3359-tsc";
269a9bce1b0SSebastian Andrzej Siewior 		cell->platform_data = &tscadc;
270a9bce1b0SSebastian Andrzej Siewior 		cell->pdata_size = sizeof(tscadc);
27124d5c82fSPantelis Antoniou 	}
2722b99bafaSPatil, Rachna 
2735e53a69bSPatil, Rachna 	/* ADC Cell */
27424d5c82fSPantelis Antoniou 	if (adc_channels > 0) {
27524d5c82fSPantelis Antoniou 		tscadc->adc_cell = tscadc->used_cells;
27624d5c82fSPantelis Antoniou 		cell = &tscadc->cells[tscadc->used_cells++];
2779f99928fSSebastian Andrzej Siewior 		cell->name = "TI-am335x-adc";
2786f39ac4eSPatil, Rachna 		cell->of_compatible = "ti,am3359-adc";
279a9bce1b0SSebastian Andrzej Siewior 		cell->platform_data = &tscadc;
280a9bce1b0SSebastian Andrzej Siewior 		cell->pdata_size = sizeof(tscadc);
28124d5c82fSPantelis Antoniou 	}
2825e53a69bSPatil, Rachna 
28301636eb9SPatil, Rachna 	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
28424d5c82fSPantelis Antoniou 			tscadc->used_cells, NULL, 0, NULL);
28501636eb9SPatil, Rachna 	if (err < 0)
28601636eb9SPatil, Rachna 		goto err_disable_clk;
28701636eb9SPatil, Rachna 
28801636eb9SPatil, Rachna 	device_init_wakeup(&pdev->dev, true);
28901636eb9SPatil, Rachna 	platform_set_drvdata(pdev, tscadc);
29001636eb9SPatil, Rachna 	return 0;
29101636eb9SPatil, Rachna 
29201636eb9SPatil, Rachna err_disable_clk:
29301636eb9SPatil, Rachna 	pm_runtime_put_sync(&pdev->dev);
29401636eb9SPatil, Rachna 	pm_runtime_disable(&pdev->dev);
2953c39c9c6SPatil, Rachna ret:
29601636eb9SPatil, Rachna 	return err;
29701636eb9SPatil, Rachna }
29801636eb9SPatil, Rachna 
299612b95cdSGreg Kroah-Hartman static int ti_tscadc_remove(struct platform_device *pdev)
30001636eb9SPatil, Rachna {
30101636eb9SPatil, Rachna 	struct ti_tscadc_dev	*tscadc = platform_get_drvdata(pdev);
30201636eb9SPatil, Rachna 
30301636eb9SPatil, Rachna 	tscadc_writel(tscadc, REG_SE, 0x00);
30401636eb9SPatil, Rachna 
30501636eb9SPatil, Rachna 	pm_runtime_put_sync(&pdev->dev);
30601636eb9SPatil, Rachna 	pm_runtime_disable(&pdev->dev);
30701636eb9SPatil, Rachna 
30801636eb9SPatil, Rachna 	mfd_remove_devices(tscadc->dev);
30901636eb9SPatil, Rachna 
31001636eb9SPatil, Rachna 	return 0;
31101636eb9SPatil, Rachna }
31201636eb9SPatil, Rachna 
31301636eb9SPatil, Rachna #ifdef CONFIG_PM
31401636eb9SPatil, Rachna static int tscadc_suspend(struct device *dev)
31501636eb9SPatil, Rachna {
31601636eb9SPatil, Rachna 	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
31701636eb9SPatil, Rachna 
31801636eb9SPatil, Rachna 	tscadc_writel(tscadc_dev, REG_SE, 0x00);
31901636eb9SPatil, Rachna 	pm_runtime_put_sync(dev);
32001636eb9SPatil, Rachna 
32101636eb9SPatil, Rachna 	return 0;
32201636eb9SPatil, Rachna }
32301636eb9SPatil, Rachna 
32401636eb9SPatil, Rachna static int tscadc_resume(struct device *dev)
32501636eb9SPatil, Rachna {
32601636eb9SPatil, Rachna 	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
32701636eb9SPatil, Rachna 	unsigned int restore, ctrl;
32801636eb9SPatil, Rachna 
32901636eb9SPatil, Rachna 	pm_runtime_get_sync(dev);
33001636eb9SPatil, Rachna 
33101636eb9SPatil, Rachna 	/* context restore */
332b5f8b763SPatil, Rachna 	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
333b5f8b763SPatil, Rachna 	if (tscadc_dev->tsc_cell != -1)
334b5f8b763SPatil, Rachna 		ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
33501636eb9SPatil, Rachna 	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
336b5f8b763SPatil, Rachna 
337b5f8b763SPatil, Rachna 	if (tscadc_dev->tsc_cell != -1)
33801636eb9SPatil, Rachna 		tscadc_idle_config(tscadc_dev);
33901636eb9SPatil, Rachna 	restore = tscadc_readl(tscadc_dev, REG_CTRL);
34001636eb9SPatil, Rachna 	tscadc_writel(tscadc_dev, REG_CTRL,
34101636eb9SPatil, Rachna 			(restore | CNTRLREG_TSCSSENB));
34201636eb9SPatil, Rachna 
343e90f8754SMatthias Kaehlcke 	tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div);
344e90f8754SMatthias Kaehlcke 
34501636eb9SPatil, Rachna 	return 0;
34601636eb9SPatil, Rachna }
34701636eb9SPatil, Rachna 
34801636eb9SPatil, Rachna static const struct dev_pm_ops tscadc_pm_ops = {
34901636eb9SPatil, Rachna 	.suspend = tscadc_suspend,
35001636eb9SPatil, Rachna 	.resume = tscadc_resume,
35101636eb9SPatil, Rachna };
35201636eb9SPatil, Rachna #define TSCADC_PM_OPS (&tscadc_pm_ops)
35301636eb9SPatil, Rachna #else
35401636eb9SPatil, Rachna #define TSCADC_PM_OPS NULL
35501636eb9SPatil, Rachna #endif
35601636eb9SPatil, Rachna 
357a6543a1cSPatil, Rachna static const struct of_device_id ti_tscadc_dt_ids[] = {
358a6543a1cSPatil, Rachna 	{ .compatible = "ti,am3359-tscadc", },
359a6543a1cSPatil, Rachna 	{ }
360a6543a1cSPatil, Rachna };
361a6543a1cSPatil, Rachna MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
362a6543a1cSPatil, Rachna 
36301636eb9SPatil, Rachna static struct platform_driver ti_tscadc_driver = {
36401636eb9SPatil, Rachna 	.driver = {
365a6543a1cSPatil, Rachna 		.name   = "ti_am3359-tscadc",
36601636eb9SPatil, Rachna 		.owner	= THIS_MODULE,
36701636eb9SPatil, Rachna 		.pm	= TSCADC_PM_OPS,
368131221bcSSachin Kamat 		.of_match_table = ti_tscadc_dt_ids,
36901636eb9SPatil, Rachna 	},
37001636eb9SPatil, Rachna 	.probe	= ti_tscadc_probe,
371612b95cdSGreg Kroah-Hartman 	.remove	= ti_tscadc_remove,
37201636eb9SPatil, Rachna 
37301636eb9SPatil, Rachna };
37401636eb9SPatil, Rachna 
37501636eb9SPatil, Rachna module_platform_driver(ti_tscadc_driver);
37601636eb9SPatil, Rachna 
37701636eb9SPatil, Rachna MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
37801636eb9SPatil, Rachna MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
37901636eb9SPatil, Rachna MODULE_LICENSE("GPL");
380