wzero3_ssp.c revision 1.4 1 /* $NetBSD: wzero3_ssp.c,v 1.4 2010/05/30 10:00:27 nonaka Exp $ */
2
3 /*
4 * Copyright (c) 2010 NONAKA Kimihiro <nonaka (at) netbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.4 2010/05/30 10:00:27 nonaka Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/mutex.h>
36 #include <sys/pmf.h>
37 #include <sys/bus.h>
38
39 #include <machine/bootinfo.h>
40 #include <machine/platid.h>
41 #include <machine/platid_mask.h>
42
43 #include <arm/xscale/pxa2x0reg.h>
44 #include <arm/xscale/pxa2x0var.h>
45 #include <arm/xscale/pxa2x0_gpio.h>
46
47 #include <hpcarm/dev/wzero3_reg.h>
48 #include <hpcarm/dev/wzero3_sspvar.h>
49
50 #define WS003SH_SSCR0_MAX1233 0x0000048f /* 16bit/SPI/div by 5 */
51 #define WS007SH_SSCR0_ADS7846 0x000006ab /* 12bit/Microwire/div by 7 */
52 #define WS011SH_SSCR0_AK4184_TP 0x0010068f /* 32bit/SPI/div by 7 */
53 #define WS011SH_SSCR0_AK4184_KEYPAD 0x0000068f /* 16bit/SPI/div by 7 */
54
55 struct wzero3ssp_model;
56 struct wzero3ssp_softc {
57 device_t sc_dev;
58 bus_space_tag_t sc_iot;
59 bus_space_handle_t sc_ioh;
60 kmutex_t sc_mtx;
61 const struct wzero3ssp_model *sc_model;
62 };
63
64 static int wzero3ssp_match(device_t, cfdata_t, void *);
65 static void wzero3ssp_attach(device_t, device_t, void *);
66
67 CFATTACH_DECL_NEW(wzero3ssp, sizeof(struct wzero3ssp_softc),
68 wzero3ssp_match, wzero3ssp_attach, NULL, NULL);
69
70 static void wzero3ssp_init(struct wzero3ssp_softc *);
71 static bool wzero3ssp_resume(device_t dv, const pmf_qual_t *);
72 static uint32_t wzero3ssp_read_ads7846(struct wzero3ssp_softc *, uint32_t);
73 static uint32_t wzero3ssp_read_max1233(struct wzero3ssp_softc *, uint32_t,
74 uint32_t);
75 static uint32_t wzero3ssp_read_ak4184_tp(struct wzero3ssp_softc *, uint32_t);
76 static uint16_t wzero3ssp_read_ak4184_keypad(struct wzero3ssp_softc *, uint32_t,
77 uint32_t);
78
79 static struct wzero3ssp_softc *wzero3ssp_sc;
80
81 static const struct wzero3ssp_model {
82 platid_mask_t *platid;
83 u_long sspaddr;
84 } wzero3ssp_table[] = {
85 /* WS003SH */
86 {
87 &platid_mask_MACH_SHARP_WZERO3_WS003SH,
88 PXA2X0_SSP2_BASE,
89 },
90 /* WS004SH */
91 {
92 &platid_mask_MACH_SHARP_WZERO3_WS004SH,
93 PXA2X0_SSP2_BASE,
94 },
95 /* WS007SH */
96 {
97 &platid_mask_MACH_SHARP_WZERO3_WS007SH,
98 PXA2X0_SSP1_BASE,
99 },
100 /* WS011SH */
101 {
102 &platid_mask_MACH_SHARP_WZERO3_WS011SH,
103 PXA2X0_SSP1_BASE,
104 },
105 #if 0
106 /* WS0020H */
107 {
108 &platid_mask_MACH_SHARP_WZERO3_WS020SH,
109 PXA2X0_SSP1_BASE,
110 },
111 #endif
112 {
113 NULL, 0,
114 },
115 };
116
117 static const struct wzero3ssp_model *
118 wzero3ssp_lookup(void)
119 {
120 const struct wzero3ssp_model *model;
121
122 for (model = wzero3ssp_table; model->platid != NULL; model++) {
123 if (platid_match(&platid, model->platid)) {
124 return model;
125 }
126 }
127 return NULL;
128 }
129
130 static int
131 wzero3ssp_match(device_t parent, cfdata_t cf, void *aux)
132 {
133
134 if (strcmp(cf->cf_name, "wzero3ssp") != 0)
135 return 0;
136 if (wzero3ssp_lookup() == NULL)
137 return 0;
138 if (wzero3ssp_sc != NULL)
139 return 0;
140 return 1;
141 }
142
143 static void
144 wzero3ssp_attach(device_t parent, device_t self, void *aux)
145 {
146 struct wzero3ssp_softc *sc = device_private(self);
147
148 sc->sc_dev = self;
149 wzero3ssp_sc = sc;
150
151 aprint_normal("\n");
152 aprint_naive("\n");
153
154 sc->sc_model = wzero3ssp_lookup();
155 if (sc->sc_model == NULL) {
156 aprint_error_dev(self, "unknown model\n");
157 return;
158 }
159
160 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_TTY);
161
162 sc->sc_iot = &pxa2x0_bs_tag;
163 if (bus_space_map(sc->sc_iot, sc->sc_model->sspaddr, PXA2X0_SSP_SIZE, 0,
164 &sc->sc_ioh)) {
165 aprint_error_dev(sc->sc_dev, "can't map bus space\n");
166 return;
167 }
168
169 if (!pmf_device_register(sc->sc_dev, NULL, wzero3ssp_resume))
170 aprint_error_dev(sc->sc_dev,
171 "couldn't establish power handler\n");
172
173 wzero3ssp_init(sc);
174 }
175
176 /*
177 * Initialize the dedicated SSP unit and disable all chip selects.
178 * This function is called with interrupts disabled.
179 */
180 static void
181 wzero3ssp_init(struct wzero3ssp_softc *sc)
182 {
183
184 if (sc->sc_model->sspaddr == PXA2X0_SSP1_BASE)
185 pxa2x0_clkman_config(CKEN_SSP2, 1);
186 else if (sc->sc_model->sspaddr == PXA2X0_SSP2_BASE)
187 pxa2x0_clkman_config(CKEN_SSP3, 1);
188
189 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
190 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR1, 0);
191
192 /* XXX */
193 if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS003SH)
194 || platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS004SH)) {
195 pxa2x0_gpio_set_function(39/*GPIO_WS003SH_XXX*/,
196 GPIO_OUT|GPIO_SET);
197 pxa2x0_gpio_set_function(GPIO_WS003SH_MAX1233_CS,
198 GPIO_OUT|GPIO_SET);
199 }
200 if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS007SH)) {
201 pxa2x0_gpio_set_function(GPIO_WS007SH_ADS7846_CS,
202 GPIO_OUT|GPIO_SET);
203 }
204 if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) {
205 pxa2x0_gpio_set_function(GPIO_WS011SH_AK4184_CS,
206 GPIO_OUT|GPIO_SET);
207 }
208 }
209
210 static bool
211 wzero3ssp_resume(device_t dv, const pmf_qual_t *qual)
212 {
213 struct wzero3ssp_softc *sc = device_private(dv);
214
215 mutex_enter(&sc->sc_mtx);
216 wzero3ssp_init(sc);
217 mutex_exit(&sc->sc_mtx);
218
219 return true;
220 }
221
222 /*
223 * Transmit a single data word to one of the ICs, keep the chip selected
224 * afterwards, and don't wait for data to be returned in SSDR. Interrupts
225 * must be held off until wzero3ssp_ic_stop() gets called.
226 */
227 void
228 wzero3ssp_ic_start(int ic, uint32_t cmd)
229 {
230 struct wzero3ssp_softc *sc;
231
232 KASSERT(wzero3ssp_sc != NULL);
233 sc = wzero3ssp_sc;
234
235 mutex_enter(&sc->sc_mtx);
236
237 /* disable other ICs */
238 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
239 if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS007SH)) {
240 if (ic != WZERO3_SSP_IC_ADS7846)
241 pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
242 }
243 if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) {
244 if (ic != WZERO3_SSP_IC_AK4184_TP
245 && ic != WZERO3_SSP_IC_AK4184_KEYPAD)
246 pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
247 }
248
249 /* activate the chosen one */
250 switch (ic) {
251 case WZERO3_SSP_IC_ADS7846:
252 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
253 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
254 WS007SH_SSCR0_ADS7846);
255 pxa2x0_gpio_clear_bit(GPIO_WS007SH_ADS7846_CS);
256 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
257 while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
258 & SSSR_TNF) != SSSR_TNF)
259 continue; /* poll */
260 break;
261 case WZERO3_SSP_IC_AK4184_TP:
262 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
263 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
264 WS011SH_SSCR0_AK4184_TP);
265 pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS);
266 (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
267 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
268 & SSSR_TNF))
269 continue; /* poll */
270 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd << 16);
271 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
272 & SSSR_BUSY)
273 continue; /* poll */
274 break;
275 case WZERO3_SSP_IC_MAX1233:
276 case WZERO3_SSP_IC_AK4184_KEYPAD:
277 case WZERO3_SSP_IC_NUM:
278 default:
279 break;
280 }
281 }
282
283 /*
284 * Read the last value from SSDR and deactivate all chip-selects.
285 */
286 uint32_t
287 wzero3ssp_ic_stop(int ic)
288 {
289 struct wzero3ssp_softc *sc;
290 uint32_t rv;
291
292 KASSERT(wzero3ssp_sc != NULL);
293 sc = wzero3ssp_sc;
294
295 switch (ic) {
296 case WZERO3_SSP_IC_ADS7846:
297 /* read result of last command */
298 while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
299 & SSSR_RNE) != SSSR_RNE)
300 continue; /* poll */
301 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
302 pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
303 break;
304 case WZERO3_SSP_IC_AK4184_TP:
305 /* read result of last command */
306 while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
307 & SSSR_RNE) != SSSR_RNE)
308 continue; /* poll */
309 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
310 pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
311 break;
312 case WZERO3_SSP_IC_MAX1233:
313 case WZERO3_SSP_IC_AK4184_KEYPAD:
314 case WZERO3_SSP_IC_NUM:
315 default:
316 rv = 0;
317 break;
318 }
319
320 mutex_exit(&sc->sc_mtx);
321
322 return rv;
323 }
324
325 /*
326 * Activate one of the chip-select lines, transmit one word value in
327 * each direction, and deactivate the chip-select again.
328 */
329 uint32_t
330 wzero3ssp_ic_send(int ic, uint32_t data, uint32_t data2)
331 {
332 struct wzero3ssp_softc *sc;
333
334 if (wzero3ssp_sc == NULL) {
335 aprint_error("%s: not configured\n", __func__);
336 return 0;
337 }
338 sc = wzero3ssp_sc;
339
340 switch (ic) {
341 case WZERO3_SSP_IC_ADS7846:
342 return wzero3ssp_read_ads7846(sc, data);
343 case WZERO3_SSP_IC_MAX1233:
344 return wzero3ssp_read_max1233(sc, data, data2);
345 case WZERO3_SSP_IC_AK4184_TP:
346 return wzero3ssp_read_ak4184_tp(sc, data);
347 case WZERO3_SSP_IC_AK4184_KEYPAD:
348 return wzero3ssp_read_ak4184_keypad(sc, data, data2);
349 case WZERO3_SSP_IC_NUM:
350 default:
351 aprint_error("%s: invalid IC %d\n", __func__, ic);
352 return 0;
353 }
354 }
355
356 static uint32_t
357 wzero3ssp_read_ads7846(struct wzero3ssp_softc *sc, uint32_t cmd)
358 {
359 uint32_t rv;
360
361 mutex_enter(&sc->sc_mtx);
362
363 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
364 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
365 WS007SH_SSCR0_ADS7846);
366
367 pxa2x0_gpio_clear_bit(GPIO_WS007SH_ADS7846_CS);
368
369 /* send cmd */
370 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
371 continue; /* poll */
372 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
373 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
374 continue; /* poll */
375
376 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
377 continue; /* poll */
378 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
379
380 pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
381
382 mutex_exit(&sc->sc_mtx);
383
384 return rv;
385 }
386
387 static uint32_t
388 wzero3ssp_read_max1233(struct wzero3ssp_softc *sc, uint32_t cmd, uint32_t data)
389 {
390 uint32_t rv;
391
392 mutex_enter(&sc->sc_mtx);
393
394 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
395 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
396 WS003SH_SSCR0_MAX1233);
397
398 pxa2x0_gpio_set_bit(39/*GPIO_WS003SH_XXX*/);
399 pxa2x0_gpio_clear_bit(GPIO_WS003SH_MAX1233_CS);
400
401 /* send cmd */
402 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
403 continue; /* poll */
404 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
405 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
406 continue; /* poll */
407 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
408 continue; /* poll */
409 (void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
410
411 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
412 continue; /* poll */
413 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, data);
414 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
415 continue; /* poll */
416 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
417 continue; /* poll */
418 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
419
420 pxa2x0_gpio_set_bit(GPIO_WS003SH_MAX1233_CS);
421
422 mutex_exit(&sc->sc_mtx);
423
424 return rv;
425 }
426
427 static uint32_t
428 wzero3ssp_read_ak4184_tp(struct wzero3ssp_softc *sc, uint32_t cmd)
429 {
430 uint32_t rv;
431
432 mutex_enter(&sc->sc_mtx);
433
434 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
435 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
436 WS011SH_SSCR0_AK4184_TP);
437
438 pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS);
439
440 /* clear rx fifo */
441 (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
442
443 /* send cmd */
444 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
445 continue; /* poll */
446 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd << 16);
447 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
448 continue; /* poll */
449
450 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
451 continue; /* poll */
452 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
453
454 pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
455
456 mutex_exit(&sc->sc_mtx);
457
458 return rv;
459 }
460
461 static uint16_t
462 wzero3ssp_read_ak4184_keypad(struct wzero3ssp_softc *sc, uint32_t cmd,
463 uint32_t data)
464 {
465 uint16_t rv;
466
467 mutex_enter(&sc->sc_mtx);
468
469 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
470 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
471 WS011SH_SSCR0_AK4184_KEYPAD);
472
473 pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS);
474
475 /* clear rx fifo */
476 (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
477
478 /* send cmd */
479 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
480 continue; /* poll */
481 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR, (uint16_t)cmd);
482 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
483 continue; /* poll */
484 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
485 continue; /* poll */
486 (void) bus_space_read_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
487
488 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
489 continue; /* poll */
490 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR, (uint16_t)data);
491 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
492 continue; /* poll */
493 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
494 continue; /* poll */
495 rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
496
497 pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
498
499 mutex_exit(&sc->sc_mtx);
500
501 return rv;
502 }
503