nexus.c (282480) | nexus.c (284273) |
---|---|
1/*- 2 * Copyright 1998 Massachusetts Institute of Technology 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose and without fee is hereby 6 * granted, provided that both the above copyright notice and this 7 * permission notice appear in all copies, that both the above 8 * copyright notice and this permission notice appear in all --- 26 unchanged lines hidden (view full) --- 35 * resources which are common to all of them. In particular, 36 * this code implements the core resource managers for interrupt 37 * requests, DMA requests (which rightfully should be a part of the 38 * ISA code but it's easier to do it here for now), I/O port addresses, 39 * and I/O memory address space. 40 */ 41 42#include <sys/cdefs.h> | 1/*- 2 * Copyright 1998 Massachusetts Institute of Technology 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose and without fee is hereby 6 * granted, provided that both the above copyright notice and this 7 * permission notice appear in all copies, that both the above 8 * copyright notice and this permission notice appear in all --- 26 unchanged lines hidden (view full) --- 35 * resources which are common to all of them. In particular, 36 * this code implements the core resource managers for interrupt 37 * requests, DMA requests (which rightfully should be a part of the 38 * ISA code but it's easier to do it here for now), I/O port addresses, 39 * and I/O memory address space. 40 */ 41 42#include <sys/cdefs.h> |
43__FBSDID("$FreeBSD: head/sys/arm64/arm64/nexus.c 282480 2015-05-05 11:13:16Z andrew $"); | 43__FBSDID("$FreeBSD: head/sys/arm64/arm64/nexus.c 284273 2015-06-11 15:45:33Z andrew $"); |
44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/malloc.h> 50#include <sys/module.h> 51#include <machine/bus.h> 52#include <sys/rman.h> 53#include <sys/interrupt.h> 54 55#include <machine/vmparam.h> 56#include <machine/pcb.h> 57#include <vm/vm.h> 58#include <vm/pmap.h> 59 60#include <machine/resource.h> 61#include <machine/intr.h> 62 | 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/malloc.h> 50#include <sys/module.h> 51#include <machine/bus.h> 52#include <sys/rman.h> 53#include <sys/interrupt.h> 54 55#include <machine/vmparam.h> 56#include <machine/pcb.h> 57#include <vm/vm.h> 58#include <vm/pmap.h> 59 60#include <machine/resource.h> 61#include <machine/intr.h> 62 |
63#include "opt_acpi.h" |
|
63#include "opt_platform.h" 64 65#ifdef FDT 66#include <dev/fdt/fdt_common.h> 67#include "ofw_bus_if.h" 68#endif | 64#include "opt_platform.h" 65 66#ifdef FDT 67#include <dev/fdt/fdt_common.h> 68#include "ofw_bus_if.h" 69#endif |
70#ifdef DEV_ACPI 71#include <contrib/dev/acpica/include/acpi.h> 72#include <dev/acpica/acpivar.h> 73#endif |
|
69 70extern struct bus_space memmap_bus; 71 72static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); 73 74struct nexus_device { 75 struct resource_list nx_resources; 76}; 77 78#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) 79 80static struct rman mem_rman; | 74 75extern struct bus_space memmap_bus; 76 77static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); 78 79struct nexus_device { 80 struct resource_list nx_resources; 81}; 82 83#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) 84 85static struct rman mem_rman; |
86static struct rman irq_rman; |
|
81 | 87 |
82static int nexus_probe(device_t); | |
83static int nexus_attach(device_t); | 88static int nexus_attach(device_t); |
89 90#ifdef FDT 91static device_probe_t nexus_fdt_probe; 92static device_attach_t nexus_fdt_attach; 93#endif 94#ifdef DEV_ACPI 95static device_probe_t nexus_acpi_probe; 96static device_attach_t nexus_acpi_attach; 97#endif 98 |
|
84static int nexus_print_child(device_t, device_t); 85static device_t nexus_add_child(device_t, u_int, const char *, int); 86static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, 87 u_long, u_long, u_long, u_int); 88static int nexus_activate_resource(device_t, device_t, int, int, 89 struct resource *); 90static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 91 enum intr_polarity pol); | 99static int nexus_print_child(device_t, device_t); 100static device_t nexus_add_child(device_t, u_int, const char *, int); 101static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, 102 u_long, u_long, u_long, u_int); 103static int nexus_activate_resource(device_t, device_t, int, int, 104 struct resource *); 105static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 106 enum intr_polarity pol); |
107static struct resource_list *nexus_get_reslist(device_t, device_t); 108static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); |
|
92static int nexus_deactivate_resource(device_t, device_t, int, int, 93 struct resource *); 94 95static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, 96 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); 97static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); 98 99#ifdef FDT 100static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, 101 int icells, pcell_t *intr); 102#endif 103 104static device_method_t nexus_methods[] = { | 109static int nexus_deactivate_resource(device_t, device_t, int, int, 110 struct resource *); 111 112static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, 113 int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); 114static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); 115 116#ifdef FDT 117static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, 118 int icells, pcell_t *intr); 119#endif 120 121static device_method_t nexus_methods[] = { |
105 /* Device interface */ 106 DEVMETHOD(device_probe, nexus_probe), 107 DEVMETHOD(device_attach, nexus_attach), | |
108 /* Bus interface */ 109 DEVMETHOD(bus_print_child, nexus_print_child), 110 DEVMETHOD(bus_add_child, nexus_add_child), 111 DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), 112 DEVMETHOD(bus_activate_resource, nexus_activate_resource), 113 DEVMETHOD(bus_config_intr, nexus_config_intr), | 122 /* Bus interface */ 123 DEVMETHOD(bus_print_child, nexus_print_child), 124 DEVMETHOD(bus_add_child, nexus_add_child), 125 DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), 126 DEVMETHOD(bus_activate_resource, nexus_activate_resource), 127 DEVMETHOD(bus_config_intr, nexus_config_intr), |
128 DEVMETHOD(bus_get_resource_list, nexus_get_reslist), 129 DEVMETHOD(bus_set_resource, nexus_set_resource), |
|
114 DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), 115 DEVMETHOD(bus_setup_intr, nexus_setup_intr), 116 DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), | 130 DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), 131 DEVMETHOD(bus_setup_intr, nexus_setup_intr), 132 DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), |
117#ifdef FDT 118 DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), 119#endif | 133 |
120 { 0, 0 } 121}; 122 123static devclass_t nexus_devclass; 124static driver_t nexus_driver = { 125 "nexus", 126 nexus_methods, 127 1 /* no softc */ 128}; 129DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); 130 131static int | 134 { 0, 0 } 135}; 136 137static devclass_t nexus_devclass; 138static driver_t nexus_driver = { 139 "nexus", 140 nexus_methods, 141 1 /* no softc */ 142}; 143DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); 144 145static int |
132nexus_probe(device_t dev) 133{ 134 135 device_quiet(dev); /* suppress attach message for neatness */ 136 137 return (BUS_PROBE_DEFAULT); 138} 139 140static int | |
141nexus_attach(device_t dev) 142{ 143 144 mem_rman.rm_start = 0; 145 mem_rman.rm_end = ~0ul; 146 mem_rman.rm_type = RMAN_ARRAY; 147 mem_rman.rm_descr = "I/O memory addresses"; 148 if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) | 146nexus_attach(device_t dev) 147{ 148 149 mem_rman.rm_start = 0; 150 mem_rman.rm_end = ~0ul; 151 mem_rman.rm_type = RMAN_ARRAY; 152 mem_rman.rm_descr = "I/O memory addresses"; 153 if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) |
149 panic("nexus_probe mem_rman"); | 154 panic("nexus_attach mem_rman"); 155 irq_rman.rm_start = 0; 156 irq_rman.rm_end = ~0ul; 157 irq_rman.rm_type = RMAN_ARRAY; 158 irq_rman.rm_descr = "Interrupts"; 159 if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0)) 160 panic("nexus_attach irq_rman"); |
150 | 161 |
151 /* Add the ofwbus device */ 152 /* ARM64TODO: Alternatively add acpi */ 153 nexus_add_child(dev, 10, "ofwbus", 0); 154 155 /* 156 * First, deal with the children we know about already 157 */ | |
158 bus_generic_probe(dev); 159 bus_generic_attach(dev); 160 161 return (0); 162} 163 164static int 165nexus_print_child(device_t bus, device_t child) --- 30 unchanged lines hidden (view full) --- 196 * Allocate a resource on behalf of child. NB: child is usually going to be a 197 * child of one of our descendants, not a direct child of nexus0. 198 * (Exceptions include footbridge.) 199 */ 200static struct resource * 201nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, 202 u_long start, u_long end, u_long count, u_int flags) 203{ | 162 bus_generic_probe(dev); 163 bus_generic_attach(dev); 164 165 return (0); 166} 167 168static int 169nexus_print_child(device_t bus, device_t child) --- 30 unchanged lines hidden (view full) --- 200 * Allocate a resource on behalf of child. NB: child is usually going to be a 201 * child of one of our descendants, not a direct child of nexus0. 202 * (Exceptions include footbridge.) 203 */ 204static struct resource * 205nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, 206 u_long start, u_long end, u_long count, u_int flags) 207{ |
208 struct nexus_device *ndev = DEVTONX(child); |
|
204 struct resource *rv; | 209 struct resource *rv; |
210 struct resource_list_entry *rle; |
|
205 struct rman *rm; 206 int needactivate = flags & RF_ACTIVE; 207 | 211 struct rman *rm; 212 int needactivate = flags & RF_ACTIVE; 213 |
214 /* 215 * If this is an allocation of the "default" range for a given 216 * RID, and we know what the resources for this device are 217 * (ie. they aren't maintained by a child bus), then work out 218 * the start/end values. 219 */ 220 if ((start == 0UL) && (end == ~0UL) && (count == 1)) { 221 if (device_get_parent(child) != bus || ndev == NULL) 222 return(NULL); 223 rle = resource_list_find(&ndev->nx_resources, type, *rid); 224 if (rle == NULL) 225 return(NULL); 226 start = rle->start; 227 end = rle->end; 228 count = rle->count; 229 } 230 |
|
208 switch (type) { | 231 switch (type) { |
232 case SYS_RES_IRQ: 233 rm = &irq_rman; 234 break; 235 |
|
209 case SYS_RES_MEMORY: 210 case SYS_RES_IOPORT: 211 rm = &mem_rman; 212 break; 213 214 default: 215 return (NULL); 216 } --- 75 unchanged lines hidden (view full) --- 292 } 293 rman_set_bustag(r, &memmap_bus); 294 rman_set_virtual(r, (void *)vaddr); 295 rman_set_bushandle(r, vaddr); 296 } 297 return (0); 298} 299 | 236 case SYS_RES_MEMORY: 237 case SYS_RES_IOPORT: 238 rm = &mem_rman; 239 break; 240 241 default: 242 return (NULL); 243 } --- 75 unchanged lines hidden (view full) --- 319 } 320 rman_set_bustag(r, &memmap_bus); 321 rman_set_virtual(r, (void *)vaddr); 322 rman_set_bushandle(r, vaddr); 323 } 324 return (0); 325} 326 |
327static struct resource_list * 328nexus_get_reslist(device_t dev, device_t child) 329{ 330 struct nexus_device *ndev = DEVTONX(child); 331 332 return (&ndev->nx_resources); 333} 334 |
|
300static int | 335static int |
336nexus_set_resource(device_t dev, device_t child, int type, int rid, 337 u_long start, u_long count) 338{ 339 struct nexus_device *ndev = DEVTONX(child); 340 struct resource_list *rl = &ndev->nx_resources; 341 342 /* XXX this should return a success/failure indicator */ 343 resource_list_add(rl, type, rid, start, start + count - 1, count); 344 345 return(0); 346} 347 348 349static int |
|
301nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, 302 struct resource *r) 303{ 304 bus_size_t psize; 305 bus_space_handle_t vaddr; 306 307 psize = (bus_size_t)rman_get_size(r); 308 vaddr = rman_get_bushandle(r); 309 310 if (vaddr != 0) { 311 bus_space_unmap(&memmap_bus, vaddr, psize); 312 rman_set_virtual(r, NULL); 313 rman_set_bushandle(r, 0); 314 } 315 316 return (rman_deactivate_resource(r)); 317} 318 319#ifdef FDT | 350nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, 351 struct resource *r) 352{ 353 bus_size_t psize; 354 bus_space_handle_t vaddr; 355 356 psize = (bus_size_t)rman_get_size(r); 357 vaddr = rman_get_bushandle(r); 358 359 if (vaddr != 0) { 360 bus_space_unmap(&memmap_bus, vaddr, psize); 361 rman_set_virtual(r, NULL); 362 rman_set_bushandle(r, 0); 363 } 364 365 return (rman_deactivate_resource(r)); 366} 367 368#ifdef FDT |
369static device_method_t nexus_fdt_methods[] = { 370 /* Device interface */ 371 DEVMETHOD(device_probe, nexus_fdt_probe), 372 DEVMETHOD(device_attach, nexus_fdt_attach), 373 374 /* OFW interface */ 375 DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), 376}; 377 378#define nexus_baseclasses nexus_fdt_baseclasses 379DEFINE_CLASS_1(nexus, nexus_fdt_driver, nexus_fdt_methods, 1, nexus_driver); 380#undef nexus_baseclasses 381static devclass_t nexus_fdt_devclass; 382 383DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass, 0, 0); 384 |
|
320static int | 385static int |
386nexus_fdt_probe(device_t dev) 387{ 388 389 if (OF_peer(0) == 0) 390 return (ENXIO); 391 392 device_quiet(dev); 393 return (BUS_PROBE_DEFAULT); 394} 395 396static int 397nexus_fdt_attach(device_t dev) 398{ 399 400 nexus_add_child(dev, 10, "ofwbus", 0); 401 return (nexus_attach(dev)); 402} 403 404static int |
|
321nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, 322 pcell_t *intr) 323{ 324 int irq; 325 326 if (icells == 3) { 327 irq = intr[1]; 328 if (intr[0] == 0) 329 irq += 32; /* SPI */ 330 else 331 irq += 16; /* PPI */ 332 } else 333 irq = intr[0]; 334 335 return (irq); 336} 337#endif 338 | 405nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, 406 pcell_t *intr) 407{ 408 int irq; 409 410 if (icells == 3) { 411 irq = intr[1]; 412 if (intr[0] == 0) 413 irq += 32; /* SPI */ 414 else 415 irq += 16; /* PPI */ 416 } else 417 irq = intr[0]; 418 419 return (irq); 420} 421#endif 422 |
423#ifdef DEV_ACPI 424static device_method_t nexus_acpi_methods[] = { 425 /* Device interface */ 426 DEVMETHOD(device_probe, nexus_acpi_probe), 427 DEVMETHOD(device_attach, nexus_acpi_attach), 428}; 429 430#define nexus_baseclasses nexus_acpi_baseclasses 431DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, 432 nexus_driver); 433#undef nexus_baseclasses 434static devclass_t nexus_acpi_devclass; 435 436DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_acpi_devclass, 0, 0); 437 438static int 439nexus_acpi_probe(device_t dev) 440{ 441 442 if (acpi_identify() != 0) 443 return (ENXIO); 444 445 device_quiet(dev); 446 return (BUS_PROBE_LOW_PRIORITY); 447} 448 449static int 450nexus_acpi_attach(device_t dev) 451{ 452 453 nexus_add_child(dev, 10, "acpi", 0); 454 return (nexus_attach(dev)); 455} 456#endif |
|