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 **)®); 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 **)®); 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}
| |
| |