diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-13 06:14:59 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-13 06:14:59 -0400 |
commit | d8c5d658f425bd25bbfb137f2617f59ed4fdee7d (patch) | |
tree | ba1607f9cc0fb8c3ac246a78490d3e5b8438f44e /drivers/input | |
parent | a1ace0aac5a83b859c2ddeb5dfb032b9b6dcd9cf (diff) | |
parent | 1460c152c53335b5403045d056502eda1204c33a (diff) |
Merge tag 'am335x_tsc-adc' of git://breakpoint.cc/bigeasy/linux
A complete refurbished series inclunding:
- DT support for the MFD, TSC and ADC driver & platform device support,
which has no users, has been killed.
- iio_map from last series is gone and replaced by proper nodes in the
device tree.
- suspend fixes which means correct data structs are taken and no
interrupt storm
- fifo split which should problem with TSC & ADC beeing used at the same
time
- The ADC channels are now checked before blindly applied. That means the
touch part reads X, Y and Z coordinates and does not mix them up. Same
goes for the IIO ADC driver.
- The IIO ADC driver now creates files named in_voltageX_raw where X
represents the ADC line instead of a number starting at 0. A read from
this file can return -EBUSY in case touch is busy and the ADC didn't
collect a value.
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/ti_am335x_tsc.c | 288 |
1 files changed, 203 insertions, 85 deletions
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87827a4..0e9f02aeae6b 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
@@ -24,8 +24,9 @@ | |||
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/input/ti_am335x_tsc.h> | ||
28 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_device.h> | ||
29 | 30 | ||
30 | #include <linux/mfd/ti_am335x_tscadc.h> | 31 | #include <linux/mfd/ti_am335x_tscadc.h> |
31 | 32 | ||
@@ -33,6 +34,13 @@ | |||
33 | #define SEQ_SETTLE 275 | 34 | #define SEQ_SETTLE 275 |
34 | #define MAX_12BIT ((1 << 12) - 1) | 35 | #define MAX_12BIT ((1 << 12) - 1) |
35 | 36 | ||
37 | static const int config_pins[] = { | ||
38 | STEPCONFIG_XPP, | ||
39 | STEPCONFIG_XNN, | ||
40 | STEPCONFIG_YPP, | ||
41 | STEPCONFIG_YNN, | ||
42 | }; | ||
43 | |||
36 | struct titsc { | 44 | struct titsc { |
37 | struct input_dev *input; | 45 | struct input_dev *input; |
38 | struct ti_tscadc_dev *mfd_tscadc; | 46 | struct ti_tscadc_dev *mfd_tscadc; |
@@ -40,7 +48,10 @@ struct titsc { | |||
40 | unsigned int wires; | 48 | unsigned int wires; |
41 | unsigned int x_plate_resistance; | 49 | unsigned int x_plate_resistance; |
42 | bool pen_down; | 50 | bool pen_down; |
43 | int steps_to_configure; | 51 | int coordinate_readouts; |
52 | u32 config_inp[4]; | ||
53 | u32 bit_xp, bit_xn, bit_yp, bit_yn; | ||
54 | u32 inp_xp, inp_xn, inp_yp, inp_yn; | ||
44 | }; | 55 | }; |
45 | 56 | ||
46 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) | 57 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) |
@@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, | |||
54 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); | 65 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); |
55 | } | 66 | } |
56 | 67 | ||
68 | static int titsc_config_wires(struct titsc *ts_dev) | ||
69 | { | ||
70 | u32 analog_line[4]; | ||
71 | u32 wire_order[4]; | ||
72 | int i, bit_cfg; | ||
73 | |||
74 | for (i = 0; i < 4; i++) { | ||
75 | /* | ||
76 | * Get the order in which TSC wires are attached | ||
77 | * w.r.t. each of the analog input lines on the EVM. | ||
78 | */ | ||
79 | analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; | ||
80 | wire_order[i] = ts_dev->config_inp[i] & 0x0F; | ||
81 | if (WARN_ON(analog_line[i] > 7)) | ||
82 | return -EINVAL; | ||
83 | if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | for (i = 0; i < 4; i++) { | ||
88 | int an_line; | ||
89 | int wi_order; | ||
90 | |||
91 | an_line = analog_line[i]; | ||
92 | wi_order = wire_order[i]; | ||
93 | bit_cfg = config_pins[wi_order]; | ||
94 | if (bit_cfg == 0) | ||
95 | return -EINVAL; | ||
96 | switch (wi_order) { | ||
97 | case 0: | ||
98 | ts_dev->bit_xp = bit_cfg; | ||
99 | ts_dev->inp_xp = an_line; | ||
100 | break; | ||
101 | |||
102 | case 1: | ||
103 | ts_dev->bit_xn = bit_cfg; | ||
104 | ts_dev->inp_xn = an_line; | ||
105 | break; | ||
106 | |||
107 | case 2: | ||
108 | ts_dev->bit_yp = bit_cfg; | ||
109 | ts_dev->inp_yp = an_line; | ||
110 | break; | ||
111 | case 3: | ||
112 | ts_dev->bit_yn = bit_cfg; | ||
113 | ts_dev->inp_yn = an_line; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
119 | |||
57 | static void titsc_step_config(struct titsc *ts_dev) | 120 | static void titsc_step_config(struct titsc *ts_dev) |
58 | { | 121 | { |
59 | unsigned int config; | 122 | unsigned int config; |
60 | int i, total_steps; | 123 | int i; |
61 | 124 | int end_step; | |
62 | /* Configure the Step registers */ | 125 | u32 stepenable; |
63 | total_steps = 2 * ts_dev->steps_to_configure; | ||
64 | 126 | ||
65 | config = STEPCONFIG_MODE_HWSYNC | | 127 | config = STEPCONFIG_MODE_HWSYNC | |
66 | STEPCONFIG_AVG_16 | STEPCONFIG_XPP; | 128 | STEPCONFIG_AVG_16 | ts_dev->bit_xp; |
67 | switch (ts_dev->wires) { | 129 | switch (ts_dev->wires) { |
68 | case 4: | 130 | case 4: |
69 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | 131 | config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; |
70 | break; | 132 | break; |
71 | case 5: | 133 | case 5: |
72 | config |= STEPCONFIG_YNN | | 134 | config |= ts_dev->bit_yn | |
73 | STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | | 135 | STEPCONFIG_INP_AN4 | ts_dev->bit_xn | |
74 | STEPCONFIG_YPP; | 136 | ts_dev->bit_yp; |
75 | break; | 137 | break; |
76 | case 8: | 138 | case 8: |
77 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | 139 | config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; |
78 | break; | 140 | break; |
79 | } | 141 | } |
80 | 142 | ||
81 | for (i = 1; i <= ts_dev->steps_to_configure; i++) { | 143 | /* 1 … coordinate_readouts is for X */ |
144 | end_step = ts_dev->coordinate_readouts; | ||
145 | for (i = 0; i < end_step; i++) { | ||
82 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | 146 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); |
83 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | 147 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); |
84 | } | 148 | } |
85 | 149 | ||
86 | config = 0; | 150 | config = 0; |
87 | config = STEPCONFIG_MODE_HWSYNC | | 151 | config = STEPCONFIG_MODE_HWSYNC | |
88 | STEPCONFIG_AVG_16 | STEPCONFIG_YNN | | 152 | STEPCONFIG_AVG_16 | ts_dev->bit_yn | |
89 | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; | 153 | STEPCONFIG_INM_ADCREFM; |
90 | switch (ts_dev->wires) { | 154 | switch (ts_dev->wires) { |
91 | case 4: | 155 | case 4: |
92 | config |= STEPCONFIG_YPP; | 156 | config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); |
93 | break; | 157 | break; |
94 | case 5: | 158 | case 5: |
95 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | | 159 | config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | |
96 | STEPCONFIG_XNP | STEPCONFIG_YPN; | 160 | ts_dev->bit_xn | ts_dev->bit_yp; |
97 | break; | 161 | break; |
98 | case 8: | 162 | case 8: |
99 | config |= STEPCONFIG_YPP; | 163 | config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); |
100 | break; | 164 | break; |
101 | } | 165 | } |
102 | 166 | ||
103 | for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { | 167 | /* coordinate_readouts … coordinate_readouts * 2 is for Y */ |
168 | end_step = ts_dev->coordinate_readouts * 2; | ||
169 | for (i = ts_dev->coordinate_readouts; i < end_step; i++) { | ||
104 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | 170 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); |
105 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | 171 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); |
106 | } | 172 | } |
107 | 173 | ||
108 | config = 0; | ||
109 | /* Charge step configuration */ | 174 | /* Charge step configuration */ |
110 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | 175 | config = ts_dev->bit_xp | ts_dev->bit_yn | |
111 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | | 176 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | |
112 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; | 177 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); |
113 | 178 | ||
114 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); | 179 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); |
115 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); | 180 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); |
116 | 181 | ||
117 | config = 0; | 182 | /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */ |
118 | /* Configure to calculate pressure */ | ||
119 | config = STEPCONFIG_MODE_HWSYNC | | 183 | config = STEPCONFIG_MODE_HWSYNC | |
120 | STEPCONFIG_AVG_16 | STEPCONFIG_YPP | | 184 | STEPCONFIG_AVG_16 | ts_dev->bit_yp | |
121 | STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; | 185 | ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | |
122 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); | 186 | STEPCONFIG_INP(ts_dev->inp_xp); |
123 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), | 187 | titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); |
188 | titsc_writel(ts_dev, REG_STEPDELAY(end_step), | ||
124 | STEPCONFIG_OPENDLY); | 189 | STEPCONFIG_OPENDLY); |
125 | 190 | ||
126 | config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; | 191 | end_step++; |
127 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); | 192 | config |= STEPCONFIG_INP(ts_dev->inp_yn); |
128 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), | 193 | titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); |
194 | titsc_writel(ts_dev, REG_STEPDELAY(end_step), | ||
129 | STEPCONFIG_OPENDLY); | 195 | STEPCONFIG_OPENDLY); |
130 | 196 | ||
131 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | 197 | /* The steps1 … end and bit 0 for TS_Charge */ |
198 | stepenable = (1 << (end_step + 2)) - 1; | ||
199 | am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); | ||
132 | } | 200 | } |
133 | 201 | ||
134 | static void titsc_read_coordinates(struct titsc *ts_dev, | 202 | static void titsc_read_coordinates(struct titsc *ts_dev, |
135 | unsigned int *x, unsigned int *y) | 203 | u32 *x, u32 *y, u32 *z1, u32 *z2) |
136 | { | 204 | { |
137 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); | 205 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); |
138 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | 206 | unsigned int prev_val_x = ~0, prev_val_y = ~0; |
139 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | 207 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; |
140 | unsigned int read, diff; | 208 | unsigned int read, diff; |
141 | unsigned int i, channel; | 209 | unsigned int i, channel; |
210 | unsigned int creads = ts_dev->coordinate_readouts; | ||
142 | 211 | ||
212 | *z1 = *z2 = 0; | ||
213 | if (fifocount % (creads * 2 + 2)) | ||
214 | fifocount -= fifocount % (creads * 2 + 2); | ||
143 | /* | 215 | /* |
144 | * Delta filter is used to remove large variations in sampled | 216 | * Delta filter is used to remove large variations in sampled |
145 | * values from ADC. The filter tries to predict where the next | 217 | * values from ADC. The filter tries to predict where the next |
@@ -148,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev, | |||
148 | * algorithm compares the difference with that of a present value, | 220 | * algorithm compares the difference with that of a present value, |
149 | * if true the value is reported to the sub system. | 221 | * if true the value is reported to the sub system. |
150 | */ | 222 | */ |
151 | for (i = 0; i < fifocount - 1; i++) { | 223 | for (i = 0; i < fifocount; i++) { |
152 | read = titsc_readl(ts_dev, REG_FIFO0); | 224 | read = titsc_readl(ts_dev, REG_FIFO0); |
153 | channel = read & 0xf0000; | 225 | |
154 | channel = channel >> 0x10; | 226 | channel = (read & 0xf0000) >> 16; |
155 | if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { | 227 | read &= 0xfff; |
156 | read &= 0xfff; | 228 | if (channel < creads) { |
157 | diff = abs(read - prev_val_x); | 229 | diff = abs(read - prev_val_x); |
158 | if (diff < prev_diff_x) { | 230 | if (diff < prev_diff_x) { |
159 | prev_diff_x = diff; | 231 | prev_diff_x = diff; |
160 | *x = read; | 232 | *x = read; |
161 | } | 233 | } |
162 | prev_val_x = read; | 234 | prev_val_x = read; |
163 | } | ||
164 | 235 | ||
165 | read = titsc_readl(ts_dev, REG_FIFO1); | 236 | } else if (channel < creads * 2) { |
166 | channel = read & 0xf0000; | ||
167 | channel = channel >> 0x10; | ||
168 | if ((channel >= ts_dev->steps_to_configure) && | ||
169 | (channel < (2 * ts_dev->steps_to_configure - 1))) { | ||
170 | read &= 0xfff; | ||
171 | diff = abs(read - prev_val_y); | 237 | diff = abs(read - prev_val_y); |
172 | if (diff < prev_diff_y) { | 238 | if (diff < prev_diff_y) { |
173 | prev_diff_y = diff; | 239 | prev_diff_y = diff; |
174 | *y = read; | 240 | *y = read; |
175 | } | 241 | } |
176 | prev_val_y = read; | 242 | prev_val_y = read; |
243 | |||
244 | } else if (channel < creads * 2 + 1) { | ||
245 | *z1 = read; | ||
246 | |||
247 | } else if (channel < creads * 2 + 2) { | ||
248 | *z2 = read; | ||
177 | } | 249 | } |
178 | } | 250 | } |
179 | } | 251 | } |
@@ -186,23 +258,11 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
186 | unsigned int x = 0, y = 0; | 258 | unsigned int x = 0, y = 0; |
187 | unsigned int z1, z2, z; | 259 | unsigned int z1, z2, z; |
188 | unsigned int fsm; | 260 | unsigned int fsm; |
189 | unsigned int fifo1count, fifo0count; | ||
190 | int i; | ||
191 | 261 | ||
192 | status = titsc_readl(ts_dev, REG_IRQSTATUS); | 262 | status = titsc_readl(ts_dev, REG_IRQSTATUS); |
193 | if (status & IRQENB_FIFO0THRES) { | 263 | if (status & IRQENB_FIFO0THRES) { |
194 | titsc_read_coordinates(ts_dev, &x, &y); | ||
195 | 264 | ||
196 | z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; | 265 | titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2); |
197 | z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
198 | |||
199 | fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); | ||
200 | for (i = 0; i < fifo1count; i++) | ||
201 | titsc_readl(ts_dev, REG_FIFO1); | ||
202 | |||
203 | fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
204 | for (i = 0; i < fifo0count; i++) | ||
205 | titsc_readl(ts_dev, REG_FIFO0); | ||
206 | 266 | ||
207 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | 267 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { |
208 | /* | 268 | /* |
@@ -210,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
210 | * Resistance(touch) = x plate resistance * | 270 | * Resistance(touch) = x plate resistance * |
211 | * x postion/4096 * ((z2 / z1) - 1) | 271 | * x postion/4096 * ((z2 / z1) - 1) |
212 | */ | 272 | */ |
213 | z = z2 - z1; | 273 | z = z1 - z2; |
214 | z *= x; | 274 | z *= x; |
215 | z *= ts_dev->x_plate_resistance; | 275 | z *= ts_dev->x_plate_resistance; |
216 | z /= z1; | 276 | z /= z2; |
217 | z = (z + 2047) >> 12; | 277 | z = (z + 2047) >> 12; |
218 | 278 | ||
219 | if (z <= MAX_12BIT) { | 279 | if (z <= MAX_12BIT) { |
@@ -248,10 +308,53 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
248 | irqclr |= IRQENB_PENUP; | 308 | irqclr |= IRQENB_PENUP; |
249 | } | 309 | } |
250 | 310 | ||
251 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | 311 | if (status & IRQENB_HW_PEN) { |
312 | |||
313 | titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); | ||
314 | titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); | ||
315 | } | ||
252 | 316 | ||
253 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | 317 | if (irqclr) { |
254 | return IRQ_HANDLED; | 318 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); |
319 | am335x_tsc_se_update(ts_dev->mfd_tscadc); | ||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | return IRQ_NONE; | ||
323 | } | ||
324 | |||
325 | static int titsc_parse_dt(struct platform_device *pdev, | ||
326 | struct titsc *ts_dev) | ||
327 | { | ||
328 | struct device_node *node = pdev->dev.of_node; | ||
329 | int err; | ||
330 | |||
331 | if (!node) | ||
332 | return -EINVAL; | ||
333 | |||
334 | err = of_property_read_u32(node, "ti,wires", &ts_dev->wires); | ||
335 | if (err < 0) | ||
336 | return err; | ||
337 | switch (ts_dev->wires) { | ||
338 | case 4: | ||
339 | case 5: | ||
340 | case 8: | ||
341 | break; | ||
342 | default: | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | |||
346 | err = of_property_read_u32(node, "ti,x-plate-resistance", | ||
347 | &ts_dev->x_plate_resistance); | ||
348 | if (err < 0) | ||
349 | return err; | ||
350 | |||
351 | err = of_property_read_u32(node, "ti,coordiante-readouts", | ||
352 | &ts_dev->coordinate_readouts); | ||
353 | if (err < 0) | ||
354 | return err; | ||
355 | |||
356 | return of_property_read_u32_array(node, "ti,wire-config", | ||
357 | ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); | ||
255 | } | 358 | } |
256 | 359 | ||
257 | /* | 360 | /* |
@@ -262,17 +365,9 @@ static int titsc_probe(struct platform_device *pdev) | |||
262 | { | 365 | { |
263 | struct titsc *ts_dev; | 366 | struct titsc *ts_dev; |
264 | struct input_dev *input_dev; | 367 | struct input_dev *input_dev; |
265 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | 368 | struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); |
266 | struct mfd_tscadc_board *pdata; | ||
267 | int err; | 369 | int err; |
268 | 370 | ||
269 | pdata = tscadc_dev->dev->platform_data; | ||
270 | |||
271 | if (!pdata) { | ||
272 | dev_err(&pdev->dev, "Could not find platform data\n"); | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | /* Allocate memory for device */ | 371 | /* Allocate memory for device */ |
277 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); | 372 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); |
278 | input_dev = input_allocate_device(); | 373 | input_dev = input_allocate_device(); |
@@ -286,9 +381,12 @@ static int titsc_probe(struct platform_device *pdev) | |||
286 | ts_dev->mfd_tscadc = tscadc_dev; | 381 | ts_dev->mfd_tscadc = tscadc_dev; |
287 | ts_dev->input = input_dev; | 382 | ts_dev->input = input_dev; |
288 | ts_dev->irq = tscadc_dev->irq; | 383 | ts_dev->irq = tscadc_dev->irq; |
289 | ts_dev->wires = pdata->tsc_init->wires; | 384 | |
290 | ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; | 385 | err = titsc_parse_dt(pdev, ts_dev); |
291 | ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; | 386 | if (err) { |
387 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); | ||
388 | goto err_free_mem; | ||
389 | } | ||
292 | 390 | ||
293 | err = request_irq(ts_dev->irq, titsc_irq, | 391 | err = request_irq(ts_dev->irq, titsc_irq, |
294 | 0, pdev->dev.driver->name, ts_dev); | 392 | 0, pdev->dev.driver->name, ts_dev); |
@@ -298,8 +396,14 @@ static int titsc_probe(struct platform_device *pdev) | |||
298 | } | 396 | } |
299 | 397 | ||
300 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); | 398 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); |
399 | err = titsc_config_wires(ts_dev); | ||
400 | if (err) { | ||
401 | dev_err(&pdev->dev, "wrong i/p wire configuration\n"); | ||
402 | goto err_free_irq; | ||
403 | } | ||
301 | titsc_step_config(ts_dev); | 404 | titsc_step_config(ts_dev); |
302 | titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); | 405 | titsc_writel(ts_dev, REG_FIFO0THR, |
406 | ts_dev->coordinate_readouts * 2 + 2 - 1); | ||
303 | 407 | ||
304 | input_dev->name = "ti-tsc"; | 408 | input_dev->name = "ti-tsc"; |
305 | input_dev->dev.parent = &pdev->dev; | 409 | input_dev->dev.parent = &pdev->dev; |
@@ -329,11 +433,16 @@ err_free_mem: | |||
329 | 433 | ||
330 | static int titsc_remove(struct platform_device *pdev) | 434 | static int titsc_remove(struct platform_device *pdev) |
331 | { | 435 | { |
332 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | 436 | struct titsc *ts_dev = platform_get_drvdata(pdev); |
333 | struct titsc *ts_dev = tscadc_dev->tsc; | 437 | u32 steps; |
334 | 438 | ||
335 | free_irq(ts_dev->irq, ts_dev); | 439 | free_irq(ts_dev->irq, ts_dev); |
336 | 440 | ||
441 | /* total steps followed by the enable mask */ | ||
442 | steps = 2 * ts_dev->coordinate_readouts + 2; | ||
443 | steps = (1 << steps) - 1; | ||
444 | am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); | ||
445 | |||
337 | input_unregister_device(ts_dev->input); | 446 | input_unregister_device(ts_dev->input); |
338 | 447 | ||
339 | platform_set_drvdata(pdev, NULL); | 448 | platform_set_drvdata(pdev, NULL); |
@@ -344,10 +453,11 @@ static int titsc_remove(struct platform_device *pdev) | |||
344 | #ifdef CONFIG_PM | 453 | #ifdef CONFIG_PM |
345 | static int titsc_suspend(struct device *dev) | 454 | static int titsc_suspend(struct device *dev) |
346 | { | 455 | { |
347 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | 456 | struct titsc *ts_dev = dev_get_drvdata(dev); |
348 | struct titsc *ts_dev = tscadc_dev->tsc; | 457 | struct ti_tscadc_dev *tscadc_dev; |
349 | unsigned int idle; | 458 | unsigned int idle; |
350 | 459 | ||
460 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); | ||
351 | if (device_may_wakeup(tscadc_dev->dev)) { | 461 | if (device_may_wakeup(tscadc_dev->dev)) { |
352 | idle = titsc_readl(ts_dev, REG_IRQENABLE); | 462 | idle = titsc_readl(ts_dev, REG_IRQENABLE); |
353 | titsc_writel(ts_dev, REG_IRQENABLE, | 463 | titsc_writel(ts_dev, REG_IRQENABLE, |
@@ -359,9 +469,10 @@ static int titsc_suspend(struct device *dev) | |||
359 | 469 | ||
360 | static int titsc_resume(struct device *dev) | 470 | static int titsc_resume(struct device *dev) |
361 | { | 471 | { |
362 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | 472 | struct titsc *ts_dev = dev_get_drvdata(dev); |
363 | struct titsc *ts_dev = tscadc_dev->tsc; | 473 | struct ti_tscadc_dev *tscadc_dev; |
364 | 474 | ||
475 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); | ||
365 | if (device_may_wakeup(tscadc_dev->dev)) { | 476 | if (device_may_wakeup(tscadc_dev->dev)) { |
366 | titsc_writel(ts_dev, REG_IRQWAKEUP, | 477 | titsc_writel(ts_dev, REG_IRQWAKEUP, |
367 | 0x00); | 478 | 0x00); |
@@ -369,7 +480,7 @@ static int titsc_resume(struct device *dev) | |||
369 | } | 480 | } |
370 | titsc_step_config(ts_dev); | 481 | titsc_step_config(ts_dev); |
371 | titsc_writel(ts_dev, REG_FIFO0THR, | 482 | titsc_writel(ts_dev, REG_FIFO0THR, |
372 | ts_dev->steps_to_configure); | 483 | ts_dev->coordinate_readouts * 2 + 2 - 1); |
373 | return 0; | 484 | return 0; |
374 | } | 485 | } |
375 | 486 | ||
@@ -382,13 +493,20 @@ static const struct dev_pm_ops titsc_pm_ops = { | |||
382 | #define TITSC_PM_OPS NULL | 493 | #define TITSC_PM_OPS NULL |
383 | #endif | 494 | #endif |
384 | 495 | ||
496 | static const struct of_device_id ti_tsc_dt_ids[] = { | ||
497 | { .compatible = "ti,am3359-tsc", }, | ||
498 | { } | ||
499 | }; | ||
500 | MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); | ||
501 | |||
385 | static struct platform_driver ti_tsc_driver = { | 502 | static struct platform_driver ti_tsc_driver = { |
386 | .probe = titsc_probe, | 503 | .probe = titsc_probe, |
387 | .remove = titsc_remove, | 504 | .remove = titsc_remove, |
388 | .driver = { | 505 | .driver = { |
389 | .name = "tsc", | 506 | .name = "TI-am335x-tsc", |
390 | .owner = THIS_MODULE, | 507 | .owner = THIS_MODULE, |
391 | .pm = TITSC_PM_OPS, | 508 | .pm = TITSC_PM_OPS, |
509 | .of_match_table = of_match_ptr(ti_tsc_dt_ids), | ||
392 | }, | 510 | }, |
393 | }; | 511 | }; |
394 | module_platform_driver(ti_tsc_driver); | 512 | module_platform_driver(ti_tsc_driver); |