Annotation of sys/arch/zaurus/dev/zaurus_ssp.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: zaurus_ssp.c,v 1.6 2005/04/08 21:58:49 uwe Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/device.h>
22:
23: #include <machine/bus.h>
24:
25: #include <arm/xscale/pxa2x0reg.h>
26: #include <arm/xscale/pxa2x0var.h>
27: #include <arm/xscale/pxa2x0_gpio.h>
28:
29: #include <zaurus/dev/zaurus_sspvar.h>
30:
31: #define GPIO_ADS7846_CS_C3000 14 /* SSP SFRM */
32: #define GPIO_MAX1111_CS_C3000 20
33: #define GPIO_TG_CS_C3000 53
34:
35: #define SSCR0_ADS7846_C3000 0x06ab
36: #define SSCR0_LZ9JG18 0x01ab
37: #define SSCR0_MAX1111 0x0387
38:
39: struct zssp_softc {
40: struct device sc_dev;
41: bus_space_tag_t sc_iot;
42: bus_space_handle_t sc_ioh;
43: };
44:
45: int zssp_match(struct device *, void *, void *);
46: void zssp_attach(struct device *, struct device *, void *);
47: void zssp_init(void);
48: void zssp_powerhook(int, void *);
49:
50: int zssp_read_max1111(u_int32_t);
51: u_int32_t zssp_read_ads7846(u_int32_t);
52: void zssp_write_lz9jg18(u_int32_t);
53:
54: struct cfattach zssp_ca = {
55: sizeof (struct zssp_softc), zssp_match, zssp_attach
56: };
57:
58: struct cfdriver zssp_cd = {
59: NULL, "zssp", DV_DULL
60: };
61:
62: int
63: zssp_match(struct device *parent, void *match, void *aux)
64: {
65: return 1;
66: }
67:
68: void
69: zssp_attach(struct device *parent, struct device *self, void *aux)
70: {
71: struct zssp_softc *sc = (struct zssp_softc *)self;
72:
73: sc->sc_iot = &pxa2x0_bs_tag;
74: if (bus_space_map(sc->sc_iot, PXA2X0_SSP1_BASE, PXA2X0_SSP_SIZE,
75: 0, &sc->sc_ioh)) {
76: printf(": can't map bus space\n");
77: return;
78: }
79:
80: printf("\n");
81:
82: if (powerhook_establish(zssp_powerhook, sc) == NULL)
83: printf("%s: can't establish power hook\n",
84: sc->sc_dev.dv_xname);
85:
86: zssp_init();
87: }
88:
89: /*
90: * Initialize the dedicated SSP unit and disable all chip selects.
91: * This function is called with interrupts disabled.
92: */
93: void
94: zssp_init(void)
95: {
96: struct zssp_softc *sc;
97:
98: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
99: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
100:
101: pxa2x0_clkman_config(CKEN_SSP, 1);
102:
103: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_LZ9JG18);
104: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR1, 0);
105:
106: pxa2x0_gpio_set_function(GPIO_ADS7846_CS_C3000, GPIO_OUT|GPIO_SET);
107: pxa2x0_gpio_set_function(GPIO_MAX1111_CS_C3000, GPIO_OUT|GPIO_SET);
108: pxa2x0_gpio_set_function(GPIO_TG_CS_C3000, GPIO_OUT|GPIO_SET);
109: }
110:
111: void
112: zssp_powerhook(int why, void *arg)
113: {
114: int s;
115:
116: if (why == PWR_RESUME) {
117: s = splhigh();
118: zssp_init();
119: splx(s);
120: }
121: }
122:
123: /*
124: * Transmit a single data word to one of the ICs, keep the chip selected
125: * afterwards, and don't wait for data to be returned in SSDR. Interrupts
126: * must be held off until zssp_ic_stop() gets called.
127: */
128: void
129: zssp_ic_start(int ic, u_int32_t data)
130: {
131: struct zssp_softc *sc;
132:
133: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
134: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
135:
136: /* disable other ICs */
137: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
138: if (ic != ZSSP_IC_ADS7846)
139: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
140: if (ic != ZSSP_IC_LZ9JG18)
141: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
142: if (ic != ZSSP_IC_MAX1111)
143: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
144:
145: /* activate the chosen one */
146: switch (ic) {
147: case ZSSP_IC_ADS7846:
148: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
149: SSCR0_ADS7846_C3000);
150: pxa2x0_gpio_clear_bit(GPIO_ADS7846_CS_C3000);
151: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, data);
152: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
153: & SSSR_TNF) != SSSR_TNF)
154: /* poll */;
155: break;
156: case ZSSP_IC_LZ9JG18:
157: pxa2x0_gpio_clear_bit(GPIO_TG_CS_C3000);
158: break;
159: case ZSSP_IC_MAX1111:
160: pxa2x0_gpio_clear_bit(GPIO_MAX1111_CS_C3000);
161: break;
162: }
163: }
164:
165: /*
166: * Read the last value from SSDR and deactivate all chip-selects.
167: */
168: u_int32_t
169: zssp_ic_stop(int ic)
170: {
171: struct zssp_softc *sc;
172: u_int32_t rv;
173:
174: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
175: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
176:
177: switch (ic) {
178: case ZSSP_IC_ADS7846:
179: /* read result of last command */
180: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
181: & SSSR_RNE) != SSSR_RNE)
182: /* poll */;
183: rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
184: break;
185: case ZSSP_IC_LZ9JG18:
186: case ZSSP_IC_MAX1111:
187: /* last value received is irrelevant or undefined */
188: default:
189: rv = 0;
190: break;
191: }
192:
193: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
194: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
195: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
196:
197: return (rv);
198: }
199:
200: /*
201: * Activate one of the chip-select lines, transmit one word value in
202: * each direction, and deactivate the chip-select again.
203: */
204: u_int32_t
205: zssp_ic_send(int ic, u_int32_t data)
206: {
207:
208: switch (ic) {
209: case ZSSP_IC_MAX1111:
210: return (zssp_read_max1111(data));
211: case ZSSP_IC_ADS7846:
212: return (zssp_read_ads7846(data));
213: case ZSSP_IC_LZ9JG18:
214: zssp_write_lz9jg18(data);
215: return 0;
216: default:
217: printf("zssp_ic_send: invalid IC %d\n", ic);
218: return 0;
219: }
220: }
221:
222: int
223: zssp_read_max1111(u_int32_t cmd)
224: {
225: struct zssp_softc *sc;
226: int voltage[2];
227: int i;
228: int s;
229:
230: KASSERT(zssp_cd.cd_ndevs > 0 && zssp_cd.cd_devs[0] != NULL);
231: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
232:
233: s = splhigh();
234:
235: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
236: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_MAX1111);
237:
238: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
239: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
240: pxa2x0_gpio_clear_bit(GPIO_MAX1111_CS_C3000);
241:
242: delay(1);
243:
244: /* Send the command word and read a dummy word back. */
245: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
246: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
247: & SSSR_TNF) != SSSR_TNF)
248: /* poll */;
249: /* XXX is this delay necessary? */
250: delay(1);
251: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
252: & SSSR_RNE) != SSSR_RNE)
253: /* poll */;
254: i = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
255:
256: for (i = 0; i < 2; i++) {
257: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, 0);
258: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
259: & SSSR_TNF) != SSSR_TNF)
260: /* poll */;
261: /* XXX again, is this delay necessary? */
262: delay(1);
263: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
264: & SSSR_RNE) != SSSR_RNE)
265: /* poll */;
266: voltage[i] = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
267: SSP_SSDR);
268: }
269:
270: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
271: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
272: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
273:
274: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
275:
276: /* XXX no idea what this means, but it's what Linux would do. */
277: if ((voltage[0] & 0xc0) != 0 || (voltage[1] & 0x3f) != 0)
278: voltage[0] = -1;
279: else
280: voltage[0] = ((voltage[0] << 2) & 0xfc) |
281: ((voltage[1] >> 6) & 0x03);
282:
283: splx(s);
284: return voltage[0];
285: }
286:
287: /* XXX - only does CS_ADS7846 */
288: u_int32_t
289: zssp_read_ads7846(u_int32_t cmd)
290: {
291: struct zssp_softc *sc;
292:
293: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
294: unsigned int cr0;
295: int s;
296: u_int32_t val;
297:
298: if (zssp_cd.cd_ndevs < 1 || zssp_cd.cd_devs[0] == NULL) {
299: printf("zssp_read_ads7846: not configured\n");
300: return 0;
301: }
302: sc = (struct zssp_softc *)zssp_cd.cd_devs[0];
303:
304: s = splhigh();
305: if (1) {
306: cr0 = SSCR0_ADS7846_C3000;
307: } else {
308: cr0 = 0x00ab;
309: }
310: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
311: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, cr0);
312:
313: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
314: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
315: pxa2x0_gpio_clear_bit(GPIO_ADS7846_CS_C3000);
316:
317: bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
318:
319: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
320: & SSSR_TNF) != SSSR_TNF)
321: /* poll */;
322:
323: delay(1);
324:
325: while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
326: & SSSR_RNE) != SSSR_RNE)
327: /* poll */;
328:
329: val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
330:
331: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000); /* deselect */
332:
333: splx(s);
334:
335: return val;
336: }
337:
338: void
339: zssp_write_lz9jg18(u_int32_t data)
340: {
341: int s;
342: int sclk_pin, sclk_fn;
343: int sfrm_pin, sfrm_fn;
344: int txd_pin, txd_fn;
345: int rxd_pin, rxd_fn;
346: int i;
347:
348: /* XXX this creates a DAC command from a backlight duty value. */
349: data = 0x40 | (data & 0x1f);
350:
351: if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) {
352: /* C3000 */
353: sclk_pin = 19;
354: sfrm_pin = 14;
355: txd_pin = 87;
356: rxd_pin = 86;
357: } else {
358: sclk_pin = 23;
359: sfrm_pin = 24;
360: txd_pin = 25;
361: rxd_pin = 26;
362: }
363:
364: s = splhigh();
365:
366: sclk_fn = pxa2x0_gpio_get_function(sclk_pin);
367: sfrm_fn = pxa2x0_gpio_get_function(sfrm_pin);
368: txd_fn = pxa2x0_gpio_get_function(txd_pin);
369: rxd_fn = pxa2x0_gpio_get_function(rxd_pin);
370:
371: pxa2x0_gpio_set_function(sfrm_pin, GPIO_OUT | GPIO_SET);
372: pxa2x0_gpio_set_function(sclk_pin, GPIO_OUT | GPIO_CLR);
373: pxa2x0_gpio_set_function(txd_pin, GPIO_OUT | GPIO_CLR);
374: pxa2x0_gpio_set_function(rxd_pin, GPIO_IN);
375:
376: pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000);
377: pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000);
378: pxa2x0_gpio_clear_bit(GPIO_TG_CS_C3000);
379:
380: delay(10);
381:
382: for (i = 0; i < 8; i++) {
383: if (data & 0x80)
384: pxa2x0_gpio_set_bit(txd_pin);
385: else
386: pxa2x0_gpio_clear_bit(txd_pin);
387: delay(10);
388: pxa2x0_gpio_set_bit(sclk_pin);
389: delay(10);
390: pxa2x0_gpio_clear_bit(sclk_pin);
391: delay(10);
392: data <<= 1;
393: }
394:
395: pxa2x0_gpio_clear_bit(txd_pin);
396: pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000);
397:
398: pxa2x0_gpio_set_function(sclk_pin, sclk_fn);
399: pxa2x0_gpio_set_function(sfrm_pin, sfrm_fn);
400: pxa2x0_gpio_set_function(txd_pin, txd_fn);
401: pxa2x0_gpio_set_function(rxd_pin, rxd_fn);
402:
403: splx(s);
404: }
CVSweb