Annotation of sys/arch/zaurus/dev/scoop_pcic.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: scoop_pcic.c,v 1.1 2005/07/01 23:51:55 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 <uvm/uvm.h>
22:
23: #include <arch/arm/xscale/pxa2x0var.h>
24: #include <arch/arm/xscale/pxapcicvar.h>
25:
26: #include <machine/zaurus_reg.h>
27: #include <machine/zaurus_var.h>
28:
29: #include <zaurus/dev/zaurus_scoopreg.h>
30:
31: int scoop_pcic_match(struct device *, void *, void *);
32: void scoop_pcic_attach(struct device *, struct device *, void *);
33: void scoop_pcic_socket_setup(struct pxapcic_socket *);
34:
35: struct cfattach pxapcic_scoop_ca = {
36: sizeof(struct pxapcic_softc), scoop_pcic_match,
37: scoop_pcic_attach
38: };
39:
40: u_int scoop_pcic_read(struct pxapcic_socket *, int);
41: void scoop_pcic_write(struct pxapcic_socket *, int, u_int);
42: void scoop_pcic_set_power(struct pxapcic_socket *, int);
43: void scoop_pcic_clear_intr(struct pxapcic_socket *);
44:
45: struct pxapcic_tag scoop_pcic_functions = {
46: scoop_pcic_read,
47: scoop_pcic_write,
48: scoop_pcic_set_power,
49: scoop_pcic_clear_intr,
50: 0, /* intr_establish */
51: 0, /* intr_disestablish */
52: 0 /* intr_string */
53: };
54:
55: int
56: scoop_pcic_match(struct device *parent, void *cf, void *aux)
57: {
58: return (ZAURUS_ISC860 || ZAURUS_ISC3000);
59: }
60:
61: void
62: scoop_pcic_attach(struct device *parent, struct device *self, void *aux)
63: {
64: struct pxapcic_softc *sc = (struct pxapcic_softc *)self;
65: struct pxaip_attach_args *pxa = aux;
66:
67: sc->sc_iot = pxa->pxa_iot;
68:
69: if (ZAURUS_ISC860) {
70: sc->sc_nslots = 1;
71: sc->sc_irqpin[0] = C860_CF0_IRQ;
72: sc->sc_irqcfpin[0] = C860_CF0_IRQ_PIN;
73: } else if (ZAURUS_ISC3000) {
74: sc->sc_nslots = 2;
75: sc->sc_irqpin[0] = C3000_CF0_IRQ;
76: sc->sc_irqcfpin[0] = C3000_CF0_IRQ_PIN;
77: sc->sc_irqpin[1] = C3000_CF1_IRQ;
78: sc->sc_irqcfpin[1] = C3000_CF1_IRQ_PIN;
79: }
80:
81: pxapcic_attach(sc, &scoop_pcic_socket_setup);
82: }
83:
84: void
85: scoop_pcic_socket_setup(struct pxapcic_socket *so)
86: {
87: struct pxapcic_softc *sc;
88: bus_addr_t pa;
89: bus_size_t size = SCOOP_SIZE;
90: bus_space_tag_t iot;
91: bus_space_handle_t scooph;
92: int error;
93:
94: sc = so->sc;
95: iot = sc->sc_iot;
96:
97: if (so->socket == 0)
98: pa = C3000_SCOOP0_BASE;
99: else if (so->socket == 1)
100: pa = C3000_SCOOP1_BASE;
101: else
102: panic("%s: invalid CF slot %d", sc->sc_dev.dv_xname,
103: so->socket);
104: error = bus_space_map(iot, trunc_page(pa), round_page(size),
105: 0, &scooph);
106: if (error)
107: panic("%s: failed to map memory %x for scoop",
108: sc->sc_dev.dv_xname, pa);
109: scooph += pa - trunc_page(pa);
110:
111: bus_space_write_2(iot, scooph, SCOOP_IMR,
112: SCP_IMR_UNKN0 | SCP_IMR_UNKN1);
113:
114: /* setup */
115: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0100);
116: bus_space_write_2(iot, scooph, SCOOP_CDR, 0x0000);
117: bus_space_write_2(iot, scooph, SCOOP_CPR, 0x0000);
118: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x0000);
119: bus_space_write_2(iot, scooph, SCOOP_IRM, 0x00ff);
120: bus_space_write_2(iot, scooph, SCOOP_ISR, 0x0000);
121: bus_space_write_2(iot, scooph, SCOOP_IRM, 0x0000);
122:
123: /* C3000 */
124: if (so->socket == 1) {
125: bus_space_write_2(iot, scooph, SCOOP_CPR, 0x80c1);
126: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00c4);
127: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
128: } else {
129: bus_space_write_2(iot, scooph, SCOOP_CPR,
130: SCP_CPR_PWR|SCP_CPR_5V);
131: }
132:
133: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00ce);
134: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
135:
136: /* C3000 */
137: so->power_capability = PXAPCIC_POWER_3V;
138: if (so->socket == 0)
139: so->power_capability |= PXAPCIC_POWER_5V;
140:
141: so->pcictag_cookie = (void *)scooph;
142: so->pcictag = &scoop_pcic_functions;
143: }
144:
145: u_int
146: scoop_pcic_read(struct pxapcic_socket *so, int reg)
147: {
148: bus_space_tag_t iot = so->sc->sc_iot;
149: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
150: u_int16_t csr;
151:
152: csr = bus_space_read_2(iot, ioh, SCOOP_CSR);
153:
154: switch (reg) {
155: case PXAPCIC_CARD_STATUS:
156: if (csr & SCP_CSR_MISSING)
157: return (PXAPCIC_CARD_INVALID);
158: else
159: return (PXAPCIC_CARD_VALID);
160:
161: case PXAPCIC_CARD_READY:
162: return ((bus_space_read_2(iot, ioh, SCOOP_CSR) &
163: SCP_CSR_READY) != 0);
164:
165: default:
166: panic("scoop_pcic_read: bogus register");
167: }
168: }
169:
170: void
171: scoop_pcic_write(struct pxapcic_socket *so, int reg, u_int val)
172: {
173: bus_space_tag_t iot = so->sc->sc_iot;
174: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
175: u_int16_t newval;
176: int s;
177:
178: s = splhigh();
179:
180: switch (reg) {
181: case PXAPCIC_CARD_POWER:
182: newval = bus_space_read_2(iot, ioh, SCOOP_CPR);
183: newval &= ~(SCP_CPR_PWR | SCP_CPR_3V | SCP_CPR_5V);
184:
185: if (val == PXAPCIC_POWER_3V)
186: newval |= (SCP_CPR_PWR | SCP_CPR_3V);
187: else if (val == PXAPCIC_POWER_5V)
188: newval |= (SCP_CPR_PWR | SCP_CPR_5V);
189:
190: bus_space_write_2(iot, ioh, SCOOP_CPR, newval);
191: break;
192:
193: case PXAPCIC_CARD_RESET:
194: bus_space_write_2(iot, ioh, SCOOP_CCR,
195: val ? SCP_CCR_RESET : 0);
196: break;
197:
198: default:
199: panic("scoop_pcic_write: bogus register");
200: }
201:
202: splx(s);
203: }
204:
205: void
206: scoop_pcic_set_power(struct pxapcic_socket *so, int pwr)
207: {
208: bus_space_tag_t iot = so->sc->sc_iot;
209: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
210: u_int16_t reg;
211: int s;
212:
213: s = splhigh();
214:
215: switch (pwr) {
216: case PXAPCIC_POWER_OFF:
217: #if 0
218: /* XXX does this disable power to both sockets? */
219: reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
220: bus_space_write_2(iot, ioh, SCOOP_GPWR,
221: reg & ~(1 << SCOOP0_CF_POWER_C3000));
222: #endif
223: break;
224:
225: case PXAPCIC_POWER_3V:
226: case PXAPCIC_POWER_5V:
227: /* XXX */
228: if (so->socket == 0) {
229: reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
230: bus_space_write_2(iot, ioh, SCOOP_GPWR,
231: reg | (1 << SCOOP0_CF_POWER_C3000));
232: }
233: break;
234:
235: default:
236: splx(s);
237: panic("scoop_pcic_set_power: bogus power state");
238: }
239:
240: splx(s);
241: }
242:
243: void
244: scoop_pcic_clear_intr(struct pxapcic_socket *so)
245: {
246: bus_space_tag_t iot = so->sc->sc_iot;
247: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
248:
249: bus_space_write_2(iot, ioh, SCOOP_IRM, 0x00ff);
250: bus_space_write_2(iot, ioh, SCOOP_ISR, 0x0000);
251: bus_space_write_2(iot, ioh, SCOOP_IRM, 0x0000);
252: }
CVSweb