1 /* $Id: imx31lk_pcic.c,v 1.3 2008/06/30 00:49:31 perry Exp $ */
2 /* $NetBSD: imx31lk_pcic.c,v 1.2 2008/04/27 18:58:46 matt Exp $ */
3 /* $OpenBSD: pxapcic.c,v 1.1 2005/07/01 23:51:55 uwe Exp $ */
6 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/cdefs.h>
22 __KERNEL_RCSID(0, "$Id: imx31lk_pcic.c,v 1.3 2008/06/30 00:49:31 perry Exp $");
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/device.h>
28 #include <machine/intr.h>
29 #include <machine/bus.h>
34 #include <arch/arm/imx/imx_emifs.h>
35 #include <arch/arm/imx/imx_gpio.h>
37 #include <arch/arm/imx/imx31var.h>
38 #include <arch/arm/imx/imx_pcic.h>
41 static int imx31lk_pcic_match(struct device
*, struct cfdata
*, void *);
42 static void imx31lk_pcic_attach(struct device
*, struct device
*, void *);
44 CFATTACH_DECL(imx31lk_pcic
, sizeof(struct imx_pcic_softc
),
45 imx31lk_pcic_match
, imx31lk_pcic_attach
, NULL
, NULL
);
47 static void imx31lk_pcic_socket_setup(struct imx_pcic_socket
*);
48 static u_int
imx31lk_pcic_read(struct imx_pcic_socket
*, int);
49 static void imx31lk_pcic_write(struct imx_pcic_socket
*, int, u_int
);
50 static void imx31lk_pcic_set_power(struct imx_pcic_socket
*, int);
51 static void imx31lk_pcic_clear_intr(struct imx_pcic_socket
*);
52 static void *imx31lk_pcic_intr_establish(struct imx_pcic_socket
*, int,
53 int (*)(void *), void *);
54 static void imx31lk_pcic_intr_disestablish(struct imx_pcic_socket
*, void *);
56 struct imx_pcic_tag imx31lk_pcic_functions
= {
59 imx31lk_pcic_set_power
,
60 imx31lk_pcic_clear_intr
,
61 imx31lk_pcic_intr_establish
,
62 imx31lk_pcic_intr_disestablish
66 imx31lk_pcic_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
73 imx31lk_pcic_attach(struct device
*parent
, struct device
*self
, void *aux
)
75 struct imx_pcic_softc
*sc
= (struct imx_pcic_softc
*)self
;
76 struct aips_attach_args
* const aipsa
= aux
;
79 printf("imx_iot %p\n", aipsa
->aipsa_memt
);
80 printf("imx_addr %lx\n", aipsa
->aipsa_addr
);
81 printf("imx_size %lx\n", aipsa
->aipsa_size
);
82 printf("imx_intr %d\n", aipsa
->aipsa_intr
);
84 sc
->sc_pa
= aipsa
->aipsa_addr
;
85 sc
->sc_iot
= aipsa
->aipsa_memt
;
89 sc
->sc_irqpin
[0] = aa
->emifs_intr
; /* XXX */
90 sc
->sc_irqcfpin
[0] = -1; /* XXX */
93 sc
->sc_flags
|= PPF_REVERSE_ORDER
;
95 imx_pcic_attach_common(sc
, &imx31lk_pcic_socket_setup
);
99 imx31lk_pcic_socket_setup(struct imx_pcic_socket
*so
)
101 struct imx_pcic_softc
*sc
;
103 bus_size_t size
= 0x2000; /* XXX */
105 bus_space_handle_t imx31lkh
;
112 panic("%s: CF slot %d not supported", sc
->sc_dev
.dv_xname
, so
->socket
);
116 error
= bus_space_map(iot
, trunc_page(pa
), round_page(size
),
119 panic("%s: failed to map memory %x for imx31lk",
120 sc
->sc_dev
.dv_xname
, (uint32_t)pa
);
122 imx31lkh
+= pa
- trunc_page(pa
);
129 so
->power_capability
= PXAPCIC_POWER_3V
;
131 so
->power_capability
|= PXAPCIC_POWER_5V
;
134 so
->pcictag_cookie
= (void *)imx31lkh
;
135 so
->pcictag
= &imx31lk_pcic_functions
;
139 imx31lk_pcic_read(struct imx_pcic_socket
*so
, int reg
)
142 bus_space_tag_t iot
= so
->sc
->sc_iot
;
143 bus_space_handle_t ioh
= (bus_space_handle_t
)so
->pcictag_cookie
;
146 csr
= bus_space_read_2(iot
, ioh
, SCOOP_CSR
);
149 case PXAPCIC_CARD_STATUS
:
150 if (csr
& SCP_CSR_MISSING
)
151 return (PXAPCIC_CARD_INVALID
);
153 return (PXAPCIC_CARD_VALID
);
155 case PXAPCIC_CARD_READY
:
156 return ((bus_space_read_2(iot
, ioh
, SCOOP_CSR
) &
157 SCP_CSR_READY
) != 0);
160 panic("imx31lk_pcic_read: bogus register");
164 panic("imx31lk_pcic_read");
169 imx31lk_pcic_write(struct imx_pcic_socket
*so
, int reg
, u_int val
)
172 bus_space_tag_t iot
= so
->sc
->sc_iot
;
173 bus_space_handle_t ioh
= (bus_space_handle_t
)so
->pcictag_cookie
;
180 case PXAPCIC_CARD_POWER
:
181 newval
= bus_space_read_2(iot
, ioh
, SCOOP_CPR
);
182 newval
&= ~(SCP_CPR_PWR
| SCP_CPR_3V
| SCP_CPR_5V
);
184 if (val
== PXAPCIC_POWER_3V
)
185 newval
|= (SCP_CPR_PWR
| SCP_CPR_3V
);
186 else if (val
== PXAPCIC_POWER_5V
)
187 newval
|= (SCP_CPR_PWR
| SCP_CPR_5V
);
189 bus_space_write_2(iot
, ioh
, SCOOP_CPR
, newval
);
192 case PXAPCIC_CARD_RESET
:
193 bus_space_write_2(iot
, ioh
, SCOOP_CCR
,
194 val
? SCP_CCR_RESET
: 0);
198 panic("imx31lk_pcic_write: bogus register");
203 panic("imx31lk_pcic_write");
208 imx31lk_pcic_set_power(struct imx_pcic_socket
*so
, int pwr
)
211 bus_space_tag_t iot
= so
->sc
->sc_iot
;
212 bus_space_handle_t ioh
= (bus_space_handle_t
)so
->pcictag_cookie
;
219 case PXAPCIC_POWER_OFF
:
221 /* XXX does this disable power to both sockets? */
222 reg
= bus_space_read_2(iot
, ioh
, SCOOP_GPWR
);
223 bus_space_write_2(iot
, ioh
, SCOOP_GPWR
,
224 reg
& ~(1 << SCOOP0_CF_POWER_C3000
));
228 case PXAPCIC_POWER_3V
:
229 case PXAPCIC_POWER_5V
:
231 if (so
->socket
== 0) {
232 reg
= bus_space_read_2(iot
, ioh
, SCOOP_GPWR
);
233 bus_space_write_2(iot
, ioh
, SCOOP_GPWR
,
234 reg
| (1 << SCOOP0_CF_POWER_C3000
));
240 panic("imx31lk_pcic_set_power: bogus power state");
245 panic("imx31lk_pcic_set_power");
250 imx31lk_pcic_clear_intr(struct imx_pcic_socket
*so
)
253 bus_space_tag_t iot
= so
->sc
->sc_iot
;
254 bus_space_handle_t ioh
= (bus_space_handle_t
)so
->pcictag_cookie
;
256 bus_space_write_2(iot
, ioh
, SCOOP_IRM
, 0x00ff);
257 bus_space_write_2(iot
, ioh
, SCOOP_ISR
, 0x0000);
258 bus_space_write_2(iot
, ioh
, SCOOP_IRM
, 0x0000);
260 panic("imx31lk_pcic_clear_intr");
265 imx31lk_pcic_intr_establish(struct imx_pcic_socket
*so
, int ipl
,
266 int (*func
)(void *), void *arg
)
269 printf("%s: irqpin %d\n", __func__
, so
->irqpin
);
270 return (imx_gpio_intr_establish(so
->irqpin
, IST_EDGE_FALLING
,
271 ipl
, "pcic", func
, arg
));
278 imx31lk_pcic_intr_disestablish(struct imx_pcic_socket
*so
, void *ih
)
282 imx_gpio_intr_disestablish(ih
);