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