Blame view

drivers/mfd/ti_am335x_tscadc.c 9.53 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
  static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
  {
  	DEFINE_WAIT(wait);
  	u32 reg;
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
68
69
70
71
72
73
74
75
76
77
78
  	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);
b10848e6f   Vignesh R   mfd: ti_am335x_ts...
79
80
81
82
  		/*
  		 * Sequencer should either be idle or
  		 * busy applying the charge step.
  		 */
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
83
  		reg = tscadc_readl(tsadc, REG_ADCFSM);
b10848e6f   Vignesh R   mfd: ti_am335x_ts...
84
  		WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP));
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
85
86
87
88
  		tsadc->adc_waiting = false;
  	}
  	tsadc->adc_in_use = true;
  }
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
89
90
  void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
  {
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
91
92
93
94
95
96
97
98
99
100
  	spin_lock_irq(&tsadc->reg_lock);
  	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...
101
102
103
  	unsigned long flags;
  
  	spin_lock_irqsave(&tsadc->reg_lock, flags);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
104
105
  	tsadc->adc_in_use = false;
  	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
7e170c6e4   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
106
107
  	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
  }
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
108
  EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
abeccee40   Patil, Rachna   input: ti_am33x_t...
109
110
111
  
  void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
  {
317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
112
113
114
  	unsigned long flags;
  
  	spin_lock_irqsave(&tsadc->reg_lock, flags);
abeccee40   Patil, Rachna   input: ti_am33x_t...
115
  	tsadc->reg_se_cache &= ~val;
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
116
  	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
317b20999   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
117
  	spin_unlock_irqrestore(&tsadc->reg_lock, flags);
abeccee40   Patil, Rachna   input: ti_am33x_t...
118
119
  }
  EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
120
121
122
123
124
125
126
127
128
  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...
129
  static	int ti_tscadc_probe(struct platform_device *pdev)
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
130
131
132
133
  {
  	struct ti_tscadc_dev	*tscadc;
  	struct resource		*res;
  	struct clk		*clk;
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
134
  	struct device_node	*node = pdev->dev.of_node;
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
135
  	struct mfd_cell		*cell;
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
136
137
138
  	struct property         *prop;
  	const __be32            *cur;
  	u32			val;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
139
  	int			err, ctrl;
e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
140
  	int			clock_rate;
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
141
  	int			tsc_wires = 0, adc_channels = 0, total_channels;
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
142
  	int			readouts = 0;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
143

9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
144
145
146
  	if (!pdev->dev.of_node) {
  		dev_err(&pdev->dev, "Could not find valid DT data.
  ");
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
147
148
  		return -EINVAL;
  	}
9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
149
150
  	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...
151
  	of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
152

9e5775f31   Sebastian Andrzej Siewior   mfd: ti_am335x_ts...
153
  	node = of_get_child_by_name(pdev->dev.of_node, "adc");
18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
154
155
156
157
158
159
160
161
162
  	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:...
163
  	total_channels = tsc_wires + adc_channels;
5e53a69b4   Patil, Rachna   IIO : ADC: tiadc:...
164
165
166
167
168
  	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...
169
170
171
172
173
  	if (total_channels == 0) {
  		dev_err(&pdev->dev, "Need atleast one channel.
  ");
  		return -EINVAL;
  	}
2b99bafab   Patil, Rachna   input: TSC: ti_ts...
174

18926edeb   Sebastian Andrzej Siewior   iio: ti_am335x_ad...
175
176
177
178
179
  	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...
180
181
182
183
184
185
186
187
188
  	/* 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...
189
190
191
192
193
194
195
196
  
  	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...
197

924ff918a   Jingoo Han   mfd: ti_am335x_ts...
198
199
200
201
  	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...
202
203
204
205
206
207
208
  
  	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...
209
  		goto ret;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
210
  	}
abeccee40   Patil, Rachna   input: ti_am33x_t...
211
  	spin_lock_init(&tscadc->reg_lock);
7ca6740cd   Sebastian Andrzej Siewior   mfd: input: iio: ...
212
  	init_waitqueue_head(&tscadc->reg_se_wait);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	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...
233
  	tscadc->clk_div = clock_rate / ADC_CLK;
efe3126af   Patil, Rachna   MFD: ti_tscadc: A...
234

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

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

01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
279
  	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
24d5c82f8   Pantelis Antoniou   mfd: ti_tscadc: d...
280
  			tscadc->used_cells, NULL, 0, NULL);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
281
282
283
284
285
  	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...
286
287
288
289
290
  	return 0;
  
  err_disable_clk:
  	pm_runtime_put_sync(&pdev->dev);
  	pm_runtime_disable(&pdev->dev);
3c39c9c6e   Patil, Rachna   MFD: ti_am335x_ts...
291
  ret:
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
292
293
  	return err;
  }
612b95cd7   Greg Kroah-Hartman   Drivers: mfd: rem...
294
  static int ti_tscadc_remove(struct platform_device *pdev)
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  {
  	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...
322
  	u32 ctrl;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
323
324
325
326
  
  	pm_runtime_get_sync(dev);
  
  	/* context restore */
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
327
  	ctrl = CNTRLREG_STEPCONFIGWRT |	CNTRLREG_STEPID;
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
328
  	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
b5f8b7632   Patil, Rachna   MFD: ti_tscadc: D...
329

f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
330
331
332
333
334
  	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...
335
  		tscadc_idle_config(tscadc_dev);
f0933a60d   Jeff Lance   mfd: ti_am335x_ts...
336
337
338
  	}
  	ctrl |= CNTRLREG_TSCSSENB;
  	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
339

e90f87541   Matthias Kaehlcke   mfd: ti_am335x_ts...
340
  	tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div);
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
341
342
343
344
345
346
347
348
349
350
351
  	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...
352
353
354
355
356
  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...
357
358
  static struct platform_driver ti_tscadc_driver = {
  	.driver = {
a6543a1cb   Patil, Rachna   mfd: ti_am335x_ts...
359
  		.name   = "ti_am3359-tscadc",
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
360
  		.pm	= TSCADC_PM_OPS,
131221bc5   Sachin Kamat   mfd: ti_am335x_ts...
361
  		.of_match_table = ti_tscadc_dt_ids,
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
362
363
  	},
  	.probe	= ti_tscadc_probe,
612b95cd7   Greg Kroah-Hartman   Drivers: mfd: rem...
364
  	.remove	= ti_tscadc_remove,
01636eb97   Patil, Rachna   mfd: ti_tscadc: A...
365
366
367
368
369
370
371
372
  
  };
  
  module_platform_driver(ti_tscadc_driver);
  
  MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
  MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
  MODULE_LICENSE("GPL");