Deleted Added
full compact
fhc.c (146995) fhc.c (152684)
1/*-
2 * Copyright (c) 2003 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/sparc64/fhc/fhc.c 146995 2005-06-05 10:16:27Z marius $");
28__FBSDID("$FreeBSD: head/sys/sparc64/fhc/fhc.c 152684 2005-11-22 16:39:44Z marius $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/malloc.h>
35#include <sys/pcpu.h>
36
37#include <dev/led/led.h>
38#include <dev/ofw/ofw_bus.h>
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/malloc.h>
35#include <sys/pcpu.h>
36
37#include <dev/led/led.h>
38#include <dev/ofw/ofw_bus.h>
39#include <dev/ofw/ofw_bus_subr.h>
39#include <dev/ofw/openfirm.h>
40
41#include <machine/bus.h>
42#include <machine/bus_common.h>
43#include <machine/resource.h>
44
45#include <sys/rman.h>
46
47#include <sparc64/fhc/fhcreg.h>
48#include <sparc64/fhc/fhcvar.h>
49#include <sparc64/sbus/ofw_sbus.h>
50
51struct fhc_clr {
52 driver_intr_t *fc_func;
53 void *fc_arg;
54 void *fc_cookie;
55 bus_space_tag_t fc_bt;
56 bus_space_handle_t fc_bh;
57};
58
59struct fhc_devinfo {
40#include <dev/ofw/openfirm.h>
41
42#include <machine/bus.h>
43#include <machine/bus_common.h>
44#include <machine/resource.h>
45
46#include <sys/rman.h>
47
48#include <sparc64/fhc/fhcreg.h>
49#include <sparc64/fhc/fhcvar.h>
50#include <sparc64/sbus/ofw_sbus.h>
51
52struct fhc_clr {
53 driver_intr_t *fc_func;
54 void *fc_arg;
55 void *fc_cookie;
56 bus_space_tag_t fc_bt;
57 bus_space_handle_t fc_bh;
58};
59
60struct fhc_devinfo {
60 char *fdi_compat;
61 char *fdi_model;
62 char *fdi_name;
63 char *fdi_type;
64 phandle_t fdi_node;
61 struct ofw_bus_devinfo fdi_obdinfo;
65 struct resource_list fdi_rl;
66};
67
68static void fhc_intr_stub(void *);
69static void fhc_led_func(void *, int);
62 struct resource_list fdi_rl;
63};
64
65static void fhc_intr_stub(void *);
66static void fhc_led_func(void *, int);
67static int fhc_print_res(struct fhc_devinfo *);
70
71int
72fhc_probe(device_t dev)
73{
74
75 return (0);
76}
77
78int
79fhc_attach(device_t dev)
80{
81 char ledname[sizeof("boardXX")];
82 struct fhc_devinfo *fdi;
83 struct sbus_regs *reg;
84 struct fhc_softc *sc;
85 phandle_t child;
86 phandle_t node;
68
69int
70fhc_probe(device_t dev)
71{
72
73 return (0);
74}
75
76int
77fhc_attach(device_t dev)
78{
79 char ledname[sizeof("boardXX")];
80 struct fhc_devinfo *fdi;
81 struct sbus_regs *reg;
82 struct fhc_softc *sc;
83 phandle_t child;
84 phandle_t node;
87 bus_addr_t size;
88 bus_addr_t off;
89 device_t cdev;
90 uint32_t ctrl;
91 uint32_t *intr;
92 uint32_t iv;
93 char *name;
94 int nintr;
95 int nreg;
96 int i;
97
98 sc = device_get_softc(dev);
99 node = sc->sc_node;
100
101 device_printf(dev, "board %d, ", sc->sc_board);
102 if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) {
103 printf("model %s\n", name);
104 free(name, M_OFWPROP);
105 } else
106 printf("model unknown\n");
107
108 for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
109 bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0);
110 bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR);
111 }
112
113 sc->sc_ign = sc->sc_board << 1;
114 bus_space_write_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0,
115 sc->sc_ign);
116 sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN],
117 sc->sc_bh[FHC_IGN], 0x0);
118
119 ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
120 sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
121 if ((sc->sc_flags & FHC_CENTRAL) == 0)
122 ctrl |= FHC_CTRL_IXIST;
123 ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
124 bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
125 FHC_CTRL, ctrl);
126 bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
127 FHC_CTRL);
128
129 sc->sc_nrange = OF_getprop_alloc(node, "ranges",
130 sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
131 if (sc->sc_nrange == -1) {
132 device_printf(dev, "can't get ranges\n");
133 return (ENXIO);
134 }
135
136 if ((sc->sc_flags & FHC_CENTRAL) == 0) {
137 snprintf(ledname, sizeof(ledname), "board%d", sc->sc_board);
138 sc->sc_led_dev = led_create(fhc_led_func, sc, ledname);
139 }
140
141 for (child = OF_child(node); child != 0; child = OF_peer(child)) {
85 device_t cdev;
86 uint32_t ctrl;
87 uint32_t *intr;
88 uint32_t iv;
89 char *name;
90 int nintr;
91 int nreg;
92 int i;
93
94 sc = device_get_softc(dev);
95 node = sc->sc_node;
96
97 device_printf(dev, "board %d, ", sc->sc_board);
98 if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) {
99 printf("model %s\n", name);
100 free(name, M_OFWPROP);
101 } else
102 printf("model unknown\n");
103
104 for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
105 bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0);
106 bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR);
107 }
108
109 sc->sc_ign = sc->sc_board << 1;
110 bus_space_write_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0,
111 sc->sc_ign);
112 sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN],
113 sc->sc_bh[FHC_IGN], 0x0);
114
115 ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
116 sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
117 if ((sc->sc_flags & FHC_CENTRAL) == 0)
118 ctrl |= FHC_CTRL_IXIST;
119 ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
120 bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
121 FHC_CTRL, ctrl);
122 bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
123 FHC_CTRL);
124
125 sc->sc_nrange = OF_getprop_alloc(node, "ranges",
126 sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
127 if (sc->sc_nrange == -1) {
128 device_printf(dev, "can't get ranges\n");
129 return (ENXIO);
130 }
131
132 if ((sc->sc_flags & FHC_CENTRAL) == 0) {
133 snprintf(ledname, sizeof(ledname), "board%d", sc->sc_board);
134 sc->sc_led_dev = led_create(fhc_led_func, sc, ledname);
135 }
136
137 for (child = OF_child(node); child != 0; child = OF_peer(child)) {
142 if ((OF_getprop_alloc(child, "name", 1, (void **)&name)) == -1)
138 fdi = malloc(sizeof(*fdi), M_DEVBUF, M_WAITOK | M_ZERO);
139 if (ofw_bus_gen_setup_devinfo(&fdi->fdi_obdinfo, child) != 0) {
140 free(fdi, M_DEVBUF);
143 continue;
141 continue;
144 cdev = device_add_child(dev, NULL, -1);
145 if (cdev != NULL) {
146 fdi = malloc(sizeof(*fdi), M_DEVBUF, M_WAITOK | M_ZERO);
147 if (fdi == NULL)
148 continue;
149 fdi->fdi_name = name;
150 fdi->fdi_node = child;
151 OF_getprop_alloc(child, "compatible", 1,
152 (void **)&fdi->fdi_compat);
153 OF_getprop_alloc(child, "device_type", 1,
154 (void **)&fdi->fdi_type);
155 OF_getprop_alloc(child, "model", 1,
156 (void **)&fdi->fdi_model);
157 resource_list_init(&fdi->fdi_rl);
158 nreg = OF_getprop_alloc(child, "reg", sizeof(*reg),
159 (void **)&reg);
160 if (nreg != -1) {
161 for (i = 0; i < nreg; i++) {
162 off = reg[i].sbr_offset;
163 size = reg[i].sbr_size;
164 resource_list_add(&fdi->fdi_rl,
165 SYS_RES_MEMORY, i, off, off + size,
166 size);
167 }
168 free(reg, M_OFWPROP);
142 }
143 nreg = OF_getprop_alloc(child, "reg", sizeof(*reg),
144 (void **)&reg);
145 if (nreg == -1) {
146 device_printf(dev, "<%s>: incomplete\n",
147 fdi->fdi_obdinfo.obd_name);
148 ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo);
149 free(fdi, M_DEVBUF);
150 continue;
151 }
152 resource_list_init(&fdi->fdi_rl);
153 for (i = 0; i < nreg; i++)
154 resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, i,
155 reg[i].sbr_offset, reg[i].sbr_offset +
156 reg[i].sbr_size, reg[i].sbr_size);
157 free(reg, M_OFWPROP);
158 nintr = OF_getprop_alloc(child, "interrupts", sizeof(*intr),
159 (void **)&intr);
160 if (nintr != -1) {
161 for (i = 0; i < nintr; i++) {
162 iv = INTINO(intr[i]) |
163 (sc->sc_ign << INTMAP_IGN_SHIFT);
164 resource_list_add(&fdi->fdi_rl, SYS_RES_IRQ, i,
165 iv, iv, 1);
169 }
166 }
170 nintr = OF_getprop_alloc(child, "interrupts",
171 sizeof(*intr), (void **)&intr);
172 if (nintr != -1) {
173 for (i = 0; i < nintr; i++) {
174 iv = INTINO(intr[i]) |
175 (sc->sc_ign << INTMAP_IGN_SHIFT);
176 resource_list_add(&fdi->fdi_rl,
177 SYS_RES_IRQ, i, iv, iv, 1);
178 }
179 free(intr, M_OFWPROP);
180 }
181 device_set_ivars(cdev, fdi);
182 } else
183 free(name, M_OFWPROP);
167 free(intr, M_OFWPROP);
168 }
169 cdev = device_add_child(dev, NULL, -1);
170 if (cdev == NULL) {
171 device_printf(dev, "<%s>: device_add_child failed\n",
172 fdi->fdi_obdinfo.obd_name);
173 resource_list_free(&fdi->fdi_rl);
174 ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo);
175 free(fdi, M_DEVBUF);
176 continue;
177 }
178 device_set_ivars(cdev, fdi);
184 }
185
186 return (bus_generic_attach(dev));
187}
188
189int
190fhc_print_child(device_t dev, device_t child)
191{
179 }
180
181 return (bus_generic_attach(dev));
182}
183
184int
185fhc_print_child(device_t dev, device_t child)
186{
192 struct fhc_devinfo *fdi;
193 int rv;
194
187 int rv;
188
195 fdi = device_get_ivars(child);
196 rv = bus_print_child_header(dev, child);
189 rv = bus_print_child_header(dev, child);
197 rv += resource_list_print_type(&fdi->fdi_rl, "mem",
198 SYS_RES_MEMORY, "%#lx");
199 rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%ld");
190 rv += fhc_print_res(device_get_ivars(child));
200 rv += bus_print_child_footer(dev, child);
201 return (rv);
202}
203
204void
205fhc_probe_nomatch(device_t dev, device_t child)
206{
191 rv += bus_print_child_footer(dev, child);
192 return (rv);
193}
194
195void
196fhc_probe_nomatch(device_t dev, device_t child)
197{
207 struct fhc_devinfo *fdi;
198 const char *type;
208
199
209 fdi = device_get_ivars(child);
210 device_printf(dev, "<%s>", fdi->fdi_name);
211 resource_list_print_type(&fdi->fdi_rl, "mem", SYS_RES_MEMORY, "%#lx");
212 resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%ld");
200 device_printf(dev, "<%s>", ofw_bus_get_name(child));
201 fhc_print_res(device_get_ivars(child));
202 type = ofw_bus_get_type(child);
213 printf(" type %s (no driver attached)\n",
203 printf(" type %s (no driver attached)\n",
214 fdi->fdi_type != NULL ? fdi->fdi_type : "unknown");
204 type != NULL ? type : "unknown");
215}
216
217int
218fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
219 driver_intr_t *func, void *arg, void **cookiep)
220{
221 struct fhc_softc *sc;
222 struct fhc_clr *fc;
223 bus_space_tag_t bt;
224 bus_space_handle_t bh;
225 int error;
226 int i;
227 long vec;
228 uint32_t inr;
229
230 sc = device_get_softc(bus);
231 vec = rman_get_start(r);
232
233 bt = NULL;
234 bh = 0;
235 inr = 0;
236 for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
237 if (INTINO(bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i],
238 FHC_IMAP)) == INTINO(vec)){
239 bt = sc->sc_bt[i];
240 bh = sc->sc_bh[i];
241 inr = INTINO(vec) | (sc->sc_ign << INTMAP_IGN_SHIFT);
242 break;
243 }
244 }
245 if (inr == 0)
246 return (0);
247
248 fc = malloc(sizeof(*fc), M_DEVBUF, M_WAITOK | M_ZERO);
249 if (fc == NULL)
250 return (0);
251 fc->fc_func = func;
252 fc->fc_arg = arg;
253 fc->fc_bt = bt;
254 fc->fc_bh = bh;
255
256 bus_space_write_4(bt, bh, FHC_IMAP, inr);
257 bus_space_read_4(bt, bh, FHC_IMAP);
258
259 error = bus_generic_setup_intr(bus, child, r, flags, fhc_intr_stub,
260 fc, cookiep);
261 if (error != 0) {
262 free(fc, M_DEVBUF);
263 return (error);
264 }
265 fc->fc_cookie = *cookiep;
266 *cookiep = fc;
267
268 bus_space_write_4(bt, bh, FHC_ICLR, 0x0);
269 bus_space_write_4(bt, bh, FHC_IMAP, INTMAP_ENABLE(inr, PCPU_GET(mid)));
270 bus_space_read_4(bt, bh, FHC_IMAP);
271
272 return (error);
273}
274
275int
276fhc_teardown_intr(device_t bus, device_t child, struct resource *r,
277 void *cookie)
278{
279 struct fhc_clr *fc;
280 int error;
281
282 fc = cookie;
283 error = bus_generic_teardown_intr(bus, child, r, fc->fc_cookie);
284 if (error != 0)
285 free(fc, M_DEVBUF);
286 return (error);
287}
288
289static void
290fhc_intr_stub(void *arg)
291{
292 struct fhc_clr *fc = arg;
293
294 fc->fc_func(fc->fc_arg);
295
296 bus_space_write_4(fc->fc_bt, fc->fc_bh, FHC_ICLR, 0x0);
297 bus_space_read_4(fc->fc_bt, fc->fc_bh, FHC_ICLR);
298}
299
300struct resource *
301fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
302 u_long start, u_long end, u_long count, u_int flags)
303{
304 struct resource_list *rl;
305 struct resource_list_entry *rle;
306 struct fhc_softc *sc;
307 struct resource *res;
308 bus_addr_t coffset;
309 bus_addr_t cend;
310 bus_addr_t phys;
311 int isdefault;
312 int passthrough;
313 int i;
314
315 isdefault = (start == 0UL && end == ~0UL);
316 passthrough = (device_get_parent(child) != bus);
317 res = NULL;
318 rle = NULL;
319 rl = BUS_GET_RESOURCE_LIST(bus, child);
320 sc = device_get_softc(bus);
321 rle = resource_list_find(rl, type, *rid);
322 switch (type) {
323 case SYS_RES_IRQ:
324 return (resource_list_alloc(rl, bus, child, type, rid, start,
325 end, count, flags));
326 case SYS_RES_MEMORY:
327 if (!passthrough) {
328 if (rle == NULL)
329 return (NULL);
330 if (rle->res != NULL)
331 panic("%s: resource entry is busy", __func__);
332 if (isdefault) {
333 start = rle->start;
334 count = ulmax(count, rle->count);
335 end = ulmax(rle->end, start + count - 1);
336 }
337 }
338 for (i = 0; i < sc->sc_nrange; i++) {
339 coffset = sc->sc_ranges[i].coffset;
340 cend = coffset + sc->sc_ranges[i].size - 1;
341 if (start >= coffset && end <= cend) {
342 start -= coffset;
343 end -= coffset;
344 phys = sc->sc_ranges[i].poffset |
345 ((bus_addr_t)sc->sc_ranges[i].pspace << 32);
346 res = bus_generic_alloc_resource(bus, child,
347 type, rid, phys + start, phys + end,
348 count, flags);
349 if (!passthrough)
350 rle->res = res;
351 break;
352 }
353 }
354 break;
355 }
356 return (res);
357}
358
359struct resource_list *
360fhc_get_resource_list(device_t bus, device_t child)
361{
362 struct fhc_devinfo *fdi;
363
364 fdi = device_get_ivars(child);
365 return (&fdi->fdi_rl);
366}
367
205}
206
207int
208fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
209 driver_intr_t *func, void *arg, void **cookiep)
210{
211 struct fhc_softc *sc;
212 struct fhc_clr *fc;
213 bus_space_tag_t bt;
214 bus_space_handle_t bh;
215 int error;
216 int i;
217 long vec;
218 uint32_t inr;
219
220 sc = device_get_softc(bus);
221 vec = rman_get_start(r);
222
223 bt = NULL;
224 bh = 0;
225 inr = 0;
226 for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
227 if (INTINO(bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i],
228 FHC_IMAP)) == INTINO(vec)){
229 bt = sc->sc_bt[i];
230 bh = sc->sc_bh[i];
231 inr = INTINO(vec) | (sc->sc_ign << INTMAP_IGN_SHIFT);
232 break;
233 }
234 }
235 if (inr == 0)
236 return (0);
237
238 fc = malloc(sizeof(*fc), M_DEVBUF, M_WAITOK | M_ZERO);
239 if (fc == NULL)
240 return (0);
241 fc->fc_func = func;
242 fc->fc_arg = arg;
243 fc->fc_bt = bt;
244 fc->fc_bh = bh;
245
246 bus_space_write_4(bt, bh, FHC_IMAP, inr);
247 bus_space_read_4(bt, bh, FHC_IMAP);
248
249 error = bus_generic_setup_intr(bus, child, r, flags, fhc_intr_stub,
250 fc, cookiep);
251 if (error != 0) {
252 free(fc, M_DEVBUF);
253 return (error);
254 }
255 fc->fc_cookie = *cookiep;
256 *cookiep = fc;
257
258 bus_space_write_4(bt, bh, FHC_ICLR, 0x0);
259 bus_space_write_4(bt, bh, FHC_IMAP, INTMAP_ENABLE(inr, PCPU_GET(mid)));
260 bus_space_read_4(bt, bh, FHC_IMAP);
261
262 return (error);
263}
264
265int
266fhc_teardown_intr(device_t bus, device_t child, struct resource *r,
267 void *cookie)
268{
269 struct fhc_clr *fc;
270 int error;
271
272 fc = cookie;
273 error = bus_generic_teardown_intr(bus, child, r, fc->fc_cookie);
274 if (error != 0)
275 free(fc, M_DEVBUF);
276 return (error);
277}
278
279static void
280fhc_intr_stub(void *arg)
281{
282 struct fhc_clr *fc = arg;
283
284 fc->fc_func(fc->fc_arg);
285
286 bus_space_write_4(fc->fc_bt, fc->fc_bh, FHC_ICLR, 0x0);
287 bus_space_read_4(fc->fc_bt, fc->fc_bh, FHC_ICLR);
288}
289
290struct resource *
291fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
292 u_long start, u_long end, u_long count, u_int flags)
293{
294 struct resource_list *rl;
295 struct resource_list_entry *rle;
296 struct fhc_softc *sc;
297 struct resource *res;
298 bus_addr_t coffset;
299 bus_addr_t cend;
300 bus_addr_t phys;
301 int isdefault;
302 int passthrough;
303 int i;
304
305 isdefault = (start == 0UL && end == ~0UL);
306 passthrough = (device_get_parent(child) != bus);
307 res = NULL;
308 rle = NULL;
309 rl = BUS_GET_RESOURCE_LIST(bus, child);
310 sc = device_get_softc(bus);
311 rle = resource_list_find(rl, type, *rid);
312 switch (type) {
313 case SYS_RES_IRQ:
314 return (resource_list_alloc(rl, bus, child, type, rid, start,
315 end, count, flags));
316 case SYS_RES_MEMORY:
317 if (!passthrough) {
318 if (rle == NULL)
319 return (NULL);
320 if (rle->res != NULL)
321 panic("%s: resource entry is busy", __func__);
322 if (isdefault) {
323 start = rle->start;
324 count = ulmax(count, rle->count);
325 end = ulmax(rle->end, start + count - 1);
326 }
327 }
328 for (i = 0; i < sc->sc_nrange; i++) {
329 coffset = sc->sc_ranges[i].coffset;
330 cend = coffset + sc->sc_ranges[i].size - 1;
331 if (start >= coffset && end <= cend) {
332 start -= coffset;
333 end -= coffset;
334 phys = sc->sc_ranges[i].poffset |
335 ((bus_addr_t)sc->sc_ranges[i].pspace << 32);
336 res = bus_generic_alloc_resource(bus, child,
337 type, rid, phys + start, phys + end,
338 count, flags);
339 if (!passthrough)
340 rle->res = res;
341 break;
342 }
343 }
344 break;
345 }
346 return (res);
347}
348
349struct resource_list *
350fhc_get_resource_list(device_t bus, device_t child)
351{
352 struct fhc_devinfo *fdi;
353
354 fdi = device_get_ivars(child);
355 return (&fdi->fdi_rl);
356}
357
358const struct ofw_bus_devinfo *
359fhc_get_devinfo(device_t bus, device_t child)
360{
361 struct fhc_devinfo *fdi;
362
363 fdi = device_get_ivars(child);
364 return (&fdi->fdi_obdinfo);
365}
366
368static void
369fhc_led_func(void *arg, int onoff)
370{
371 struct fhc_softc *sc;
372 uint32_t ctrl;
373
374 sc = (struct fhc_softc *)arg;
375
376 ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
377 sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
378 if (onoff)
379 ctrl |= FHC_CTRL_RLED;
380 else
381 ctrl &= ~FHC_CTRL_RLED;
382 ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
383 bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
384 FHC_CTRL, ctrl);
385 bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
386 FHC_CTRL);
387}
388
367static void
368fhc_led_func(void *arg, int onoff)
369{
370 struct fhc_softc *sc;
371 uint32_t ctrl;
372
373 sc = (struct fhc_softc *)arg;
374
375 ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
376 sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
377 if (onoff)
378 ctrl |= FHC_CTRL_RLED;
379 else
380 ctrl &= ~FHC_CTRL_RLED;
381 ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
382 bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
383 FHC_CTRL, ctrl);
384 bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
385 FHC_CTRL);
386}
387
389const char *
390fhc_get_compat(device_t bus, device_t dev)
391{
392 struct fhc_devinfo *dinfo;
393
394 dinfo = device_get_ivars(dev);
395 return (dinfo->fdi_compat);
396}
397
398const char *
399fhc_get_model(device_t bus, device_t dev)
388static int
389fhc_print_res(struct fhc_devinfo *fdi)
400{
390{
401 struct fhc_devinfo *dinfo;
391 int rv;
402
392
403 dinfo = device_get_ivars(dev);
404 return (dinfo->fdi_model);
393 rv = 0;
394 rv += resource_list_print_type(&fdi->fdi_rl, "mem", SYS_RES_MEMORY,
395 "%#lx");
396 rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%ld");
397 return (rv);
405}
398}
406
407const char *
408fhc_get_name(device_t bus, device_t dev)
409{
410 struct fhc_devinfo *dinfo;
411
412 dinfo = device_get_ivars(dev);
413 return (dinfo->fdi_name);
414}
415
416phandle_t
417fhc_get_node(device_t bus, device_t dev)
418{
419 struct fhc_devinfo *dinfo;
420
421 dinfo = device_get_ivars(dev);
422 return (dinfo->fdi_node);
423}
424
425const char *
426fhc_get_type(device_t bus, device_t dev)
427{
428 struct fhc_devinfo *dinfo;
429
430 dinfo = device_get_ivars(dev);
431 return (dinfo->fdi_type);
432}