1 #include "opt_gemini.h"
2 #if !defined(GEMINI_MASTER) && !defined(GEMINI_SLAVE)
3 # error IPI needs GEMINI_MASTER or GEMINI_SLAVE
10 __KERNEL_RCSID(0, "$NetBSD: gemini_ipi.c,v 1.4 2008/12/06 05:22:39 cliff Exp $");
12 #include <sys/param.h>
13 #include <sys/systm.h>
14 #include <sys/device.h>
16 #include <sys/malloc.h>
17 #include <arch/arm/gemini/gemini_obiovar.h>
18 #include <arch/arm/gemini/gemini_ipivar.h>
19 #include <arch/arm/gemini/gemini_reg.h>
21 static int gemini_ipi_match(struct device
*, struct cfdata
*, void *);
22 static void gemini_ipi_attach(struct device
*, struct device
*, void *);
23 static int gemini_ipiintr(void *);
25 CFATTACH_DECL_NEW(geminiipi
, sizeof(struct gemini_ipi_softc
),
26 gemini_ipi_match
, gemini_ipi_attach
, NULL
, NULL
);
28 static gemini_ipi_softc_t
*gemini_ipi_sc
;
32 gemini_ipi_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
34 struct obio_attach_args
*obio
= aux
;
36 if (obio
->obio_intr
== LPCCF_INTR_DEFAULT
)
37 panic("ipi must specify intr in config.");
43 gemini_ipi_attach(struct device
*parent
, struct device
*self
, void *aux
)
45 gemini_ipi_softc_t
*sc
= device_private(self
);
46 struct obio_attach_args
*obio
= aux
;
48 bus_space_handle_t ioh
;
54 addr
= GEMINI_GLOBAL_BASE
;
55 size
= 4096; /* XXX */
57 if (bus_space_map(iot
, addr
, size
, 0, &ioh
))
58 panic("%s: Cannot map registers", device_xname(self
));
61 * NOTE: we are using IPL_NET, not IPL_HIGH use of IPI on this system
62 * is (mainly) networking keep simple (for now) and force all IPIs
63 * to same level so splnet() can block them as any other NIC.
66 ih
= intr_establish(obio
->obio_intr
, IPL_NET
, IST_LEVEL_HIGH
,
69 ih
= intr_establish(obio
->obio_intr
, IPL_NET
, IST_EDGE_RISING
,
73 panic("%s: Cannot establish interrupt %d\n",
74 device_xname(self
), obio
->obio_intr
);
76 SIMPLEQ_INIT(&sc
->sc_intrq
);
82 sc
->sc_intr
= obio
->obio_intr
;
91 config_found(self
, __UNCONST("geminiipm"), NULL
);
96 gemini_ipi_intrq_empty(gemini_ipi_softc_t
*sc
)
98 return SIMPLEQ_EMPTY(&sc
->sc_intrq
);
102 gemini_ipi_intrq_insert(gemini_ipi_softc_t
*sc
, int (*func
)(void *), void *arg
)
104 gemini_ipi_intrq_t
*iqp
;
106 iqp
= malloc(sizeof(*iqp
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
108 printf("gemini_ipi_intrq_insert: malloc failed\n");
114 SIMPLEQ_INSERT_TAIL(&sc
->sc_intrq
, iqp
, iq_q
);
120 gemini_ipi_intrq_remove(gemini_ipi_softc_t
*sc
, void *cookie
)
122 gemini_ipi_intrq_t
*iqp
;
124 SIMPLEQ_FOREACH(iqp
, &sc
->sc_intrq
, iq_q
) {
125 if ((void *)iqp
== cookie
) {
126 SIMPLEQ_REMOVE(&sc
->sc_intrq
,
127 iqp
, gemini_ipi_intrq
, iq_q
);
135 gemini_ipi_intrq_dispatch(gemini_ipi_softc_t
*sc
)
137 gemini_ipi_intrq_t
*iqp
;
140 SIMPLEQ_FOREACH(iqp
, &sc
->sc_intrq
, iq_q
)
141 rv
|= (*iqp
->iq_func
)(iqp
->iq_arg
);
148 ipi_intr_establish(int (*func
)(void *), void *arg
)
150 gemini_ipi_softc_t
*sc
= gemini_ipi_sc
;
156 ih
= gemini_ipi_intrq_insert(sc
, func
, arg
);
159 panic("%s: gemini_ipi_intrq_insert failed",
160 device_xname(&sc
->sc_dev
));
167 ipi_intr_disestablish(void *ih
)
169 gemini_ipi_softc_t
*sc
= gemini_ipi_sc
;
172 panic("%s: NULL gemini_ipi_sc", device_xname(&sc
->sc_dev
));
174 gemini_ipi_intrq_remove(sc
, ih
);
180 gemini_ipi_softc_t
*sc
= gemini_ipi_sc
;
188 #if defined(GEMINI_MASTER)
189 off
= GEMINI_GLOBAL_CPU0
;
190 bit
= GLOBAL_CPU0_IPICPU1
;
191 #elif defined(GEMINI_SLAVE)
192 off
= GEMINI_GLOBAL_CPU1
;
193 bit
= GLOBAL_CPU1_IPICPU0
;
196 r
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, off
);
198 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, off
, r
);
204 ipi_ack(gemini_ipi_softc_t
*sc
)
210 #if defined(GEMINI_MASTER)
211 off
= GEMINI_GLOBAL_CPU1
;
212 bit
= GLOBAL_CPU1_IPICPU0
;
213 #elif defined(GEMINI_SLAVE)
214 off
= GEMINI_GLOBAL_CPU0
;
215 bit
= GLOBAL_CPU0_IPICPU1
;
218 r
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, off
);
220 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, off
, r
);
224 gemini_ipiintr(void *arg
)
226 gemini_ipi_softc_t
*sc
= arg
;
234 rv
= gemini_ipi_intrq_dispatch(sc
);