Blame view

drivers/mfd/ti_am335x_tscadc.c 9.7 KB
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   * TI Touch Screen / ADC MFD driver
   *
   * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation version 2.
   *
   * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   * kind, whether express or implied; without even the implied warranty
   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   */
  
  #include <linux/module.h>
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
17
18
19
20
21
22
23
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/io.h>
  #include <linux/clk.h>
  #include <linux/regmap.h>
  #include <linux/mfd/core.h>
  #include <linux/pm_runtime.h>
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
24
25
  #include <linux/of.h>
  #include <linux/of_device.h>
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
26
  #include <linux/sched.h>
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  
  #include <linux/mfd/ti_am335x_tscadc.h>
  
  static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
  {
  	unsigned int val;
  
  	regmap_read(tsadc->regmap_tscadc, reg, &val);
  	return val;
  }
  
  static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg,
  					unsigned int val)
  {
  	regmap_write(tsadc->regmap_tscadc, reg, val);
  }
  
  static const struct regmap_config tscadc_regmap_config = {
  	.name = "ti_tscadc",
  	.reg_bits = 32,
  	.reg_stride = 4,
  	.val_bits = 32,
  };
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
50
  void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
abeccee40   Patil, Rachna   input: ti_am33x_t...
51
  {
317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
52
53
54
  	unsigned long flags;
  
  	spin_lock_irqsave(&tsadc->reg_lock, flags);
6ac734d22   Vignesh R   mfd: ti_am335x_ts...
55
  	tsadc->reg_se_cache |= val;
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
56
57
58
  	if (tsadc->adc_waiting)
  		wake_up(&tsadc->reg_se_wait);
  	else if (!tsadc->adc_in_use)
6a71f38dd   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
59
  		tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
60

317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
61
  	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
abeccee40   Patil, Rachna   input: ti_am33x_t...
62
  }
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
63
  EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
  {
  	DEFINE_WAIT(wait);
  	u32 reg;
  
  	/*
  	 * disable TSC steps so it does not run while the ADC is using it. If
  	 * write 0 while it is running (it just started or was already running)
  	 * then it completes all steps that were enabled and stops then.
  	 */
  	tscadc_writel(tsadc, REG_SE, 0);
  	reg = tscadc_readl(tsadc, REG_ADCFSM);
  	if (reg & SEQ_STATUS) {
  		tsadc->adc_waiting = true;
  		prepare_to_wait(&tsadc->reg_se_wait, &wait,
  				TASK_UNINTERRUPTIBLE);
  		spin_unlock_irq(&tsadc->reg_lock);
  
  		schedule();
  
  		spin_lock_irq(&tsadc->reg_lock);
  		finish_wait(&tsadc->reg_se_wait, &wait);
  
  		reg = tscadc_readl(tsadc, REG_ADCFSM);
  		WARN_ON(reg & SEQ_STATUS);
  		tsadc->adc_waiting = false;
  	}
  	tsadc->adc_in_use = true;
  }
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
93
94
  void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
  {
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
95
  	spin_lock_irq(&tsadc->reg_lock);
6ac734d22   Vignesh R   mfd: ti_am335x_ts...
96
  	tsadc->reg_se_cache |= val;
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
97
98
99
100
101
102
103
104
105
  	am335x_tscadc_need_adc(tsadc);
  
  	tscadc_writel(tsadc, REG_SE, val);
  	spin_unlock_irq(&tsadc->reg_lock);
  }
  EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
  
  void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
  {
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
106
107
108
  	unsigned long flags;
  
  	spin_lock_irqsave(&tsadc->reg_lock, flags);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
109
110
  	tsadc->adc_in_use = false;
  	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
111
112
  	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
  }
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
113
  EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
abeccee40   Patil, Rachna   input: ti_am33x_t...
114
115
116
  
  void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
  {
317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
117
118
119
  	unsigned long flags;
  
  	spin_lock_irqsave(&tsadc->reg_lock, flags);
abeccee40   Patil, Rachna   input: ti_am33x_t...
120
  	tsadc->reg_se_cache &= ~val;
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
121
  	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
122
  	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
abeccee40   Patil, Rachna   input: ti_am33x_t...
123
124
  }
  EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
125
126
127
128
129
130
131
132
133
  static void tscadc_idle_config(struct ti_tscadc_dev *config)
  {
  	unsigned int idleconfig;
  
  	idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
  			STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
  
  	tscadc_writel(config, REG_IDLECONFIG, idleconfig);
  }
612b95cd7   Greg Kroah-Hartman   Drivers: mfd: rem...
134
  static	int ti_tscadc_probe(struct platform_device *pdev)
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
135
136
137
138
  {
  	struct ti_tscadc_dev	*tscadc;
  	struct resource		*res;
  	struct clk		*clk;
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
139
  	struct device_node	*node = pdev->dev.of_node;
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
140
  	struct mfd_cell		*cell;
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
141
142
143
  	struct property         *prop;
  	const __be32            *cur;
  	u32			val;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
144
  	int			err, ctrl;
e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
145
  	int			clock_rate;
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
146
  	int			tsc_wires = 0, adc_channels = 0, total_channels;
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
147
  	int			readouts = 0;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
148

9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
149
150
151
  	if (!pdev->dev.of_node) {
  		dev_err(&pdev->dev, "Could not find valid DT data.
  ");
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
152
153
  		return -EINVAL;
  	}
9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
154
155
  	node = of_get_child_by_name(pdev->dev.of_node, "tsc");
  	of_property_read_u32(node, "ti,wires", &tsc_wires);
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
156
  	of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
157

9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
158
  	node = of_get_child_by_name(pdev->dev.of_node, "adc");
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
159
160
161
162
163
164
165
166
167
  	of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
  		adc_channels++;
  		if (val > 7) {
  			dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)
  ",
  					val);
  			return -EINVAL;
  		}
  	}
5e53a69b4   Patil, Rachna   IIO : ADC: tiadc:...
168
  	total_channels = tsc_wires + adc_channels;
5e53a69b4   Patil, Rachna   IIO : ADC: tiadc:...
169
170
171
172
173
  	if (total_channels > 8) {
  		dev_err(&pdev->dev, "Number of i/p channels more than 8
  ");
  		return -EINVAL;
  	}
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
174
175
176
177
178
  	if (total_channels == 0) {
  		dev_err(&pdev->dev, "Need atleast one channel.
  ");
  		return -EINVAL;
  	}
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
179

18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
180
181
182
183
184
  	if (readouts * 2 + 2 + adc_channels > 16) {
  		dev_err(&pdev->dev, "Too many step configurations requested
  ");
  		return -EINVAL;
  	}
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
185
186
187
188
189
190
191
192
193
  	/* Allocate memory for device */
  	tscadc = devm_kzalloc(&pdev->dev,
  			sizeof(struct ti_tscadc_dev), GFP_KERNEL);
  	if (!tscadc) {
  		dev_err(&pdev->dev, "failed to allocate memory.
  ");
  		return -ENOMEM;
  	}
  	tscadc->dev = &pdev->dev;
3c39c9c6e   Patil, Rachna   MFD: ti_am335x_ts...
194
195
196
197
198
199
200
201
  
  	err = platform_get_irq(pdev, 0);
  	if (err < 0) {
  		dev_err(&pdev->dev, "no irq ID is specified.
  ");
  		goto ret;
  	} else
  		tscadc->irq = err;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
202

924ff918a   Jingoo Han   mfd: ti_am335x_ts...
203
204
205
206
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
  	if (IS_ERR(tscadc->tscadc_base))
  		return PTR_ERR(tscadc->tscadc_base);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
207
208
209
210
211
212
213
  
  	tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
  			tscadc->tscadc_base, &tscadc_regmap_config);
  	if (IS_ERR(tscadc->regmap_tscadc)) {
  		dev_err(&pdev->dev, "regmap init failed
  ");
  		err = PTR_ERR(tscadc->regmap_tscadc);
3c39c9c6e   Patil, Rachna   MFD: ti_am335x_ts...
214
  		goto ret;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
215
  	}
abeccee40   Patil, Rachna   input: ti_am33x_t...
216
  	spin_lock_init(&tscadc->reg_lock);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
217
  	init_waitqueue_head(&tscadc->reg_se_wait);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  	pm_runtime_enable(&pdev->dev);
  	pm_runtime_get_sync(&pdev->dev);
  
  	/*
  	 * The TSC_ADC_Subsystem has 2 clock domains
  	 * OCP_CLK and ADC_CLK.
  	 * The ADC clock is expected to run at target of 3MHz,
  	 * and expected to capture 12-bit data at a rate of 200 KSPS.
  	 * The TSC_ADC_SS controller design assumes the OCP clock is
  	 * at least 6x faster than the ADC clock.
  	 */
  	clk = clk_get(&pdev->dev, "adc_tsc_fck");
  	if (IS_ERR(clk)) {
  		dev_err(&pdev->dev, "failed to get TSC fck
  ");
  		err = PTR_ERR(clk);
  		goto err_disable_clk;
  	}
  	clock_rate = clk_get_rate(clk);
  	clk_put(clk);
e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
238
  	tscadc->clk_div = clock_rate / ADC_CLK;
efe3126af   Patil, Rachna   MFD: ti_tscadc: A...
239

01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
240
  	/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
241
242
  	tscadc->clk_div--;
  	tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
243
244
  
  	/* Set the control register bits */
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
245
  	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
246
247
248
  	tscadc_writel(tscadc, REG_CTRL, ctrl);
  
  	/* Set register bits for Idle Config Mode */
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
249
250
251
252
253
254
  	if (tsc_wires > 0) {
  		tscadc->tsc_wires = tsc_wires;
  		if (tsc_wires == 5)
  			ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
  		else
  			ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
255
  		tscadc_idle_config(tscadc);
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
256
  	}
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
257
258
  
  	/* Enable the TSC module enable bit */
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
259
260
  	ctrl |= CNTRLREG_TSCSSENB;
  	tscadc_writel(tscadc, REG_CTRL, ctrl);
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
261
262
263
  	tscadc->used_cells = 0;
  	tscadc->tsc_cell = -1;
  	tscadc->adc_cell = -1;
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
264
  	/* TSC Cell */
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
265
266
267
  	if (tsc_wires > 0) {
  		tscadc->tsc_cell = tscadc->used_cells;
  		cell = &tscadc->cells[tscadc->used_cells++];
5f184e63c   Sebastian Andrzej Siewior   mfd: input: ti_am...
268
  		cell->name = "TI-am335x-tsc";
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
269
270
271
272
  		cell->of_compatible = "ti,am3359-tsc";
  		cell->platform_data = &tscadc;
  		cell->pdata_size = sizeof(tscadc);
  	}
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
273

5e53a69b4   Patil, Rachna   IIO : ADC: tiadc:...
274
  	/* ADC Cell */
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
275
276
277
  	if (adc_channels > 0) {
  		tscadc->adc_cell = tscadc->used_cells;
  		cell = &tscadc->cells[tscadc->used_cells++];
9f99928fe   Sebastian Andrzej Siewior   mfd: iio: ti_am33...
278
  		cell->name = "TI-am335x-adc";
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
279
280
281
282
  		cell->of_compatible = "ti,am3359-adc";
  		cell->platform_data = &tscadc;
  		cell->pdata_size = sizeof(tscadc);
  	}
5e53a69b4   Patil, Rachna   IIO : ADC: tiadc:...
283

01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
284
  	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
285
  			tscadc->used_cells, NULL, 0, NULL);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
286
287
288
289
290
  	if (err < 0)
  		goto err_disable_clk;
  
  	device_init_wakeup(&pdev->dev, true);
  	platform_set_drvdata(pdev, tscadc);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
291
292
293
294
295
  	return 0;
  
  err_disable_clk:
  	pm_runtime_put_sync(&pdev->dev);
  	pm_runtime_disable(&pdev->dev);
3c39c9c6e   Patil, Rachna   MFD: ti_am335x_ts...
296
  ret:
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
297
298
  	return err;
  }
612b95cd7   Greg Kroah-Hartman   Drivers: mfd: rem...
299
  static int ti_tscadc_remove(struct platform_device *pdev)
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  {
  	struct ti_tscadc_dev	*tscadc = platform_get_drvdata(pdev);
  
  	tscadc_writel(tscadc, REG_SE, 0x00);
  
  	pm_runtime_put_sync(&pdev->dev);
  	pm_runtime_disable(&pdev->dev);
  
  	mfd_remove_devices(tscadc->dev);
  
  	return 0;
  }
  
  #ifdef CONFIG_PM
  static int tscadc_suspend(struct device *dev)
  {
  	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
  
  	tscadc_writel(tscadc_dev, REG_SE, 0x00);
  	pm_runtime_put_sync(dev);
  
  	return 0;
  }
  
  static int tscadc_resume(struct device *dev)
  {
  	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
327
  	u32 ctrl;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
328
329
330
331
  
  	pm_runtime_get_sync(dev);
  
  	/* context restore */
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
332
  	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
333
  	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
334

f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
335
336
337
338
339
  	if (tscadc_dev->tsc_cell != -1) {
  		if (tscadc_dev->tsc_wires == 5)
  			ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
  		else
  			ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
340
  		tscadc_idle_config(tscadc_dev);
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
341
342
343
  	}
  	ctrl |= CNTRLREG_TSCSSENB;
  	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
344

e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
345
  	tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
346
347
348
349
350
351
352
353
354
355
356
  	return 0;
  }
  
  static const struct dev_pm_ops tscadc_pm_ops = {
  	.suspend = tscadc_suspend,
  	.resume = tscadc_resume,
  };
  #define TSCADC_PM_OPS (&tscadc_pm_ops)
  #else
  #define TSCADC_PM_OPS NULL
  #endif
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
357
358
359
360
361
  static const struct of_device_id ti_tscadc_dt_ids[] = {
  	{ .compatible = "ti,am3359-tscadc", },
  	{ }
  };
  MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
362
363
  static struct platform_driver ti_tscadc_driver = {
  	.driver = {
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
364
  		.name   = "ti_am3359-tscadc",
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
365
  		.pm	= TSCADC_PM_OPS,
131221bc5   Sachin Kamat   mfd: ti_am335x_ts...
366
  		.of_match_table = ti_tscadc_dt_ids,
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
367
368
  	},
  	.probe	= ti_tscadc_probe,
612b95cd7   Greg Kroah-Hartman   Drivers: mfd: rem...
369
  	.remove	= ti_tscadc_remove,
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
370
371
372
373
374
375
376
377
  
  };
  
  module_platform_driver(ti_tscadc_driver);
  
  MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
  MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
  MODULE_LICENSE("GPL");