1/*-
| 1/*-
|
| 2 * Copyright (c) 2015-2016 Landon Fuller <landon@freebsd.org>
|
2 * Copyright (c) 2007 Bruce M. Simpson. 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>
| 3 * Copyright (c) 2007 Bruce M. Simpson. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h>
|
28__FBSDID("$FreeBSD: head/sys/dev/bhnd/siba/siba_nexus.c 296077 2016-02-26 03:34:08Z adrian $");
| 29__FBSDID("$FreeBSD: head/sys/dev/bhnd/siba/siba_nexus.c 301410 2016-06-04 19:53:47Z landonf $");
|
29 30#include <sys/param.h>
| 30 31#include <sys/param.h>
|
31#include <sys/systm.h> 32#include <sys/bus.h>
| |
33#include <sys/kernel.h>
| 32#include <sys/kernel.h>
|
| 33#include <sys/bus.h>
|
34#include <sys/module.h>
| 34#include <sys/module.h>
|
35#include <sys/rman.h> 36#include <sys/malloc.h>
| |
37 38#include <machine/bus.h>
| 35 36#include <machine/bus.h>
|
| 37#include <sys/rman.h> 38#include <machine/resource.h>
|
39 40#include <dev/bhnd/bhnd_ids.h>
| 39 40#include <dev/bhnd/bhnd_ids.h>
|
41#include <dev/bhnd/cores/bhnd_chipcreg.h>
| 41#include <dev/bhnd/bhnd_nexusvar.h> 42#include <dev/bhnd/cores/chipc/chipcreg.h>
|
42
| 43
|
43#include "sibareg.h"
| |
44#include "sibavar.h" 45 46/* 47 * Supports siba(4) attachment to a MIPS nexus bus. 48 *
| 44#include "sibavar.h" 45 46/* 47 * Supports siba(4) attachment to a MIPS nexus bus. 48 *
|
49 * This driver is a direct port of Bruce M. Simpson' original siba(4) to the 50 * bhnd(4) bus infrastructure.
| 49 * Derived from Bruce M. Simpson' original siba(4) driver.
|
51 */ 52
| 50 */ 51
|
53/* 54 * TODO: De-mipsify this code. 55 * TODO: cpu clock calculation. -> move to siba_cc instance 56 * TODO: Hardwire IRQs for attached cores on siba at probe time. 57 * TODO: Support detach. 58 * TODO: Power management. 59 * TODO: code cleanup. 60 * TODO: Support deployments of siba other than as a system bus. 61 */ 62 63#ifndef MIPS_MEM_RID 64#define MIPS_MEM_RID 0x20 65#endif 66 67extern int rman_debug; 68 69static struct rman mem_rman; /* XXX move to softc */ 70 71static int siba_debug = 1; 72static const char descfmt[] = "Sonics SiliconBackplane rev %s"; 73#define SIBA_DEVDESCLEN sizeof(descfmt) + 8 74 75static int siba_nexus_activate_resource(device_t, device_t, int, int, 76 struct resource *); 77static struct resource * 78 siba_nexus_alloc_resource(device_t, device_t, int, int *, 79 rman_res_t, rman_res_t, rman_res_t, u_int); 80static int siba_nexus_attach(device_t); 81#ifdef notyet 82static uint8_t siba_nexus_getirq(uint16_t); 83#endif 84static int siba_nexus_probe(device_t); 85
| |
86struct siba_nexus_softc { 87 struct siba_softc parent_sc;
| 52struct siba_nexus_softc { 53 struct siba_softc parent_sc;
|
88 89 device_t siba_dev; /* Device ID */
| |
90 struct bhnd_chipid siba_cid;
| 54 struct bhnd_chipid siba_cid;
|
91 struct resource *siba_mem_res; 92 bus_space_tag_t siba_mem_bt; 93 bus_space_handle_t siba_mem_bh; 94 bus_addr_t siba_maddr; 95 bus_size_t siba_msize;
| |
96}; 97
| 55}; 56
|
98// TODO - depends on bhnd(4) IRQ support 99#ifdef notyet 100/* 101 * On the Sentry5, the system bus IRQs are the same as the 102 * MIPS IRQs. Particular cores are hardwired to certain IRQ lines. 103 */ 104static uint8_t 105siba_nexus_getirq(uint16_t devid) 106{ 107 uint8_t irq; 108 109 switch (devid) { 110 case BHND_COREID_CC: 111 irq = 0; 112 break; 113 case BHND_COREID_ENET: 114 irq = 1; 115 break; 116 case BHND_COREID_IPSEC: 117 irq = 2; 118 break; 119 case BHND_COREID_USB: 120 irq = 3; 121 break; 122 case BHND_COREID_PCI: 123 irq = 4; 124 break; 125#if 0 126 /* 127 * 5 is reserved for the MIPS on-chip timer interrupt; 128 * it is hard-wired by the tick driver. 129 */ 130 case BHND_COREID_MIPS: 131 case BHND_COREID_MIPS33: 132 irq = 5; 133 break; 134#endif 135 default: 136 irq = 0xFF; /* this core does not need an irq */ 137 break; 138 } 139 140 return (irq); 141} 142#endif 143
| |
144static int 145siba_nexus_probe(device_t dev) 146{
| 57static int 58siba_nexus_probe(device_t dev) 59{
|
147 struct siba_nexus_softc *sc = device_get_softc(dev); 148 struct bhnd_core_info cc; 149 uint32_t idhi, idlo; 150 int error, rid;
| 60 struct siba_nexus_softc *sc; 61 int error;
|
151
| 62
|
152 sc->siba_dev = dev;
| 63 sc = device_get_softc(dev);
|
153
| 64
|
154 //rman_debug = 1; /* XXX */
| 65 /* Read the ChipCommon info using the hints the kernel 66 * was compiled with. */ 67 if ((error = bhnd_nexus_read_chipid(dev, &sc->siba_cid))) 68 return (error);
|
155
| 69
|
156 /* 157 * Read the ChipCommon info using the hints the kernel 158 * was compiled with. 159 */ 160 rid = MIPS_MEM_RID; 161 sc->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 162 RF_ACTIVE); 163 if (sc->siba_mem_res == NULL) { 164 device_printf(dev, "unable to allocate probe aperture\n");
| 70 if (sc->siba_cid.chip_type != BHND_CHIPTYPE_SIBA)
|
165 return (ENXIO);
| 71 return (ENXIO);
|
166 } 167 sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res); 168 sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res); 169 sc->siba_maddr = rman_get_start(sc->siba_mem_res); 170 sc->siba_msize = rman_get_size(sc->siba_mem_res);
| |
171
| 72
|
172 if (siba_debug) { 173 device_printf(dev, "start %08x len %08x\n", 174 sc->siba_maddr, sc->siba_msize);
| 73 if ((error = siba_probe(dev)) > 0) { 74 device_printf(dev, "error %d in probe\n", error); 75 return (error);
|
175 } 176
| 76 } 77
|
177 idlo = bus_read_4(sc->siba_mem_res, SIBA_IDLOW); 178 idhi = bus_read_4(sc->siba_mem_res, SIBA_IDHIGH); 179 cc = siba_parse_core_info(idhi, 0, 0); 180 181 if (siba_debug) { 182 device_printf(dev, "idhi = %08x\n", idhi); 183 device_printf(dev, " chipcore id = %08x\n", cc.device); 184 } 185 186 /* 187 * For now, check that the first core is the ChipCommon core. 188 */ 189 if (bhnd_core_class(&cc) != BHND_DEVCLASS_CC) { 190 if (siba_debug) 191 device_printf(dev, "first core is not ChipCommon\n"); 192 return (ENXIO); 193 } 194 195 /* 196 * Determine backplane revision and set description string. 197 */ 198 uint32_t rev; 199 char *revp; 200 char descbuf[SIBA_DEVDESCLEN]; 201 202 rev = SIBA_REG_GET(idlo, IDL_SBREV); 203 revp = "unknown"; 204 if (rev == SIBA_IDL_SBREV_2_2) 205 revp = "2.2"; 206 else if (rev == SIBA_IDL_SBREV_2_3) 207 revp = "2.3"; 208 209 (void)snprintf(descbuf, sizeof(descbuf), descfmt, revp); 210 device_set_desc_copy(dev, descbuf); 211 212 /* 213 * Determine how many cores are present on this siba bus, so 214 * that we may map them all. 215 */ 216 uint32_t ccidreg; 217 218 ccidreg = bus_read_4(sc->siba_mem_res, CHIPC_ID); 219 sc->siba_cid = bhnd_parse_chipid(ccidreg, sc->siba_maddr); 220 if (siba_debug) { 221 device_printf(dev, "ccid = %08x, cc_id = %04x, cc_rev = %04x\n", 222 ccidreg, sc->siba_cid.chip_id, sc->siba_cid.chip_rev); 223 } 224 225 if (sc->siba_cid.ncores == 0) 226 sc->siba_cid.ncores = siba_get_ncores(&sc->siba_cid); 227 228 if (siba_debug) { 229 device_printf(dev, "%d cores detected.\n", sc->siba_cid.ncores); 230 } 231 232 /* 233 * Now we know how many cores are on this siba, release the 234 * mapping and allocate a new mapping spanning all cores on the bus. 235 */ 236 rid = MIPS_MEM_RID; 237 error = bus_release_resource(dev, SYS_RES_MEMORY, rid, 238 sc->siba_mem_res); 239 if (error != 0) { 240 device_printf(dev, "error %d releasing resource\n", error); 241 return (ENXIO); 242 } 243
| |
244 return (0); 245} 246 247static int 248siba_nexus_attach(device_t dev) 249{
| 78 return (0); 79} 80 81static int 82siba_nexus_attach(device_t dev) 83{
|
250 struct siba_nexus_softc *sc = device_get_softc(dev); 251 uint32_t total; 252 int error, rid;
| 84 struct siba_nexus_softc *sc; 85 int error;
|
253
| 86
|
254 if (siba_debug) 255 printf("%s: entry\n", __func__);
| 87 sc = device_get_softc(dev);
|
256 257 /* Enumerate the bus. */
| 88 89 /* Enumerate the bus. */
|
258 if ((error = siba_add_children(dev, &sc->siba_cid)))
| 90 if ((error = siba_add_children(dev, NULL))) { 91 device_printf(dev, "error %d enumerating children\n", error);
|
259 return (error);
| 92 return (error);
|
260 261 /* Allocate full core aperture */ 262 total = sc->siba_cid.ncores; 263 sc->siba_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 264 sc->siba_maddr, sc->siba_maddr + total - 1, total, RF_ACTIVE); 265 if (sc->siba_mem_res == NULL) { 266 device_printf(dev, "unable to allocate entire aperture\n"); 267 return (ENXIO);
| |
268 }
| 93 }
|
269 sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res); 270 sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res); 271 sc->siba_maddr = rman_get_start(sc->siba_mem_res); 272 sc->siba_msize = rman_get_size(sc->siba_mem_res);
| |
273
| 94
|
274 if (siba_debug) { 275 device_printf(dev, "after remapping: start %08x len %08x\n", 276 sc->siba_maddr, sc->siba_msize); 277 } 278 bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->siba_maddr, 279 sc->siba_msize); 280 281 /* 282 * We need a manager for the space we claim on nexus to 283 * satisfy requests from children. 284 * We need to keep the source reservation we took because 285 * otherwise it may be claimed elsewhere. 286 * XXX move to softc 287 */ 288 mem_rman.rm_start = sc->siba_maddr; 289 mem_rman.rm_end = sc->siba_maddr + sc->siba_msize - 1; 290 mem_rman.rm_type = RMAN_ARRAY; 291 mem_rman.rm_descr = "SiBa I/O memory addresses"; 292 if (rman_init(&mem_rman) != 0 || 293 rman_manage_region(&mem_rman, mem_rman.rm_start, 294 mem_rman.rm_end) != 0) { 295 panic("%s: mem_rman", __func__); 296 } 297
| |
298 return (siba_attach(dev)); 299} 300 301static const struct bhnd_chipid * 302siba_nexus_get_chipid(device_t dev, device_t child) { 303 struct siba_nexus_softc *sc = device_get_softc(dev); 304 return (&sc->siba_cid); 305} 306
| 95 return (siba_attach(dev)); 96} 97 98static const struct bhnd_chipid * 99siba_nexus_get_chipid(device_t dev, device_t child) { 100 struct siba_nexus_softc *sc = device_get_softc(dev); 101 return (&sc->siba_cid); 102} 103
|
307static struct resource * 308siba_nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, 309 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 310{ 311 struct resource *rv; 312 struct resource_list *rl; 313 struct resource_list_entry *rle; 314 int isdefault, needactivate; 315 316#if 0 317 if (siba_debug) 318 printf("%s: entry\n", __func__); 319#endif 320 321 isdefault = (start == 0UL && end == ~0UL && count == 1); 322 needactivate = flags & RF_ACTIVE; 323 rl = BUS_GET_RESOURCE_LIST(bus, child); 324 rle = NULL; 325 326 if (isdefault) { 327 rle = resource_list_find(rl, type, *rid); 328 if (rle == NULL) 329 return (NULL); 330 if (rle->res != NULL) 331 panic("%s: resource entry is busy", __func__); 332 start = rle->start; 333 end = rle->end; 334 count = rle->count; 335 } 336 337 /* 338 * If the request is for a resource which we manage, 339 * attempt to satisfy the allocation ourselves. 340 */ 341 if (type == SYS_RES_MEMORY && 342 start >= mem_rman.rm_start && end <= mem_rman.rm_end) { 343 344 rv = rman_reserve_resource(&mem_rman, start, end, count, 345 flags, child); 346 if (rv == 0) { 347 printf("%s: could not reserve resource\n", __func__); 348 return (0); 349 } 350 351 rman_set_rid(rv, *rid); 352 353 if (needactivate) { 354 if (bus_activate_resource(child, type, *rid, rv)) { 355 printf("%s: could not activate resource\n", 356 __func__); 357 rman_release_resource(rv); 358 return (0); 359 } 360 } 361 362 return (rv); 363 } 364 365 /* 366 * Pass the request to the parent, usually MIPS nexus. 367 */ 368 if (siba_debug) 369 printf("%s: proxying request to parent\n", __func__); 370 return (resource_list_alloc(rl, bus, child, type, rid, 371 start, end, count, flags)); 372} 373 374/* 375 * The parent bus is responsible for resource activation; in the 376 * case of MIPS, this boils down to setting the virtual address and 377 * bus handle by mapping the physical address into KSEG1. 378 */ 379static int 380siba_nexus_activate_resource(device_t bus, device_t child, int type, int rid, 381 struct resource *r) 382{ 383 return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, type, 384 rid, r)); 385} 386 387// TODO - depends on bhnd(4) IRQ support 388#ifdef notyet 389static struct siba_devinfo * 390siba_nexus_setup_devinfo(device_t dev, uint8_t idx) 391{ 392 struct siba_nexus_softc *sc = device_get_softc(dev); 393 struct siba_devinfo *sdi; 394 uint32_t idlo, idhi, rev; 395 uint16_t vendorid, devid; 396 bus_addr_t baseaddr; 397 398 sdi = malloc(sizeof(*sdi), M_DEVBUF, M_WAITOK | M_ZERO); 399 resource_list_init(&sdi->sdi_rl); 400 401 idlo = siba_mips_read_4(sc, idx, SIBA_IDLOW); 402 idhi = siba_mips_read_4(sc, idx, SIBA_IDHIGH); 403 404 vendorid = (idhi & SIBA_IDHIGH_VENDORMASK) >> 405 SIBA_IDHIGH_VENDOR_SHIFT; 406 devid = ((idhi & 0x8ff0) >> 4); 407 rev = (idhi & SIBA_IDHIGH_REVLO); 408 rev |= (idhi & SIBA_IDHIGH_REVHI) >> SIBA_IDHIGH_REVHI_SHIFT; 409 410 sdi->sdi_vid = vendorid; 411 sdi->sdi_devid = devid; 412 sdi->sdi_rev = rev; 413 sdi->sdi_idx = idx; 414 sdi->sdi_irq = siba_getirq(devid); 415 416 /* 417 * Determine memory window on bus and irq if one is needed. 418 */ 419 baseaddr = sc->siba_maddr + (idx * SIBA_CORE_SIZE); 420 resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, 421 MIPS_MEM_RID, /* XXX */ 422 baseaddr, baseaddr + SIBA_CORE_LEN - 1, SIBA_CORE_LEN); 423 424 if (sdi->sdi_irq != 0xff) { 425 resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, 426 0, sdi->sdi_irq, sdi->sdi_irq, 1); 427 } 428 429 return (sdi); 430} 431#endif 432
| |
433static device_method_t siba_nexus_methods[] = { 434 /* Device interface */
| 104static device_method_t siba_nexus_methods[] = { 105 /* Device interface */
|
435 DEVMETHOD(device_attach, siba_nexus_attach), 436 DEVMETHOD(device_probe, siba_nexus_probe),
| 106 DEVMETHOD(device_probe, siba_nexus_probe), 107 DEVMETHOD(device_attach, siba_nexus_attach),
|
437
| 108
|
438 /* Bus interface */ 439 DEVMETHOD(bus_activate_resource,siba_nexus_activate_resource), 440 DEVMETHOD(bus_alloc_resource, siba_nexus_alloc_resource), 441 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 442 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 443
| |
444 /* bhnd interface */
| 109 /* bhnd interface */
|
445 DEVMETHOD(bhnd_get_chipid, siba_nexus_get_chipid),
| 110 DEVMETHOD(bhnd_bus_get_chipid, siba_nexus_get_chipid),
|
446 447 DEVMETHOD_END 448}; 449
| 111 112 DEVMETHOD_END 113}; 114
|
450DEFINE_CLASS_1(bhnd, siba_nexus_driver, siba_nexus_methods, 451 sizeof(struct siba_nexus_softc), siba_driver);
| 115DEFINE_CLASS_2(bhnd, siba_nexus_driver, siba_nexus_methods, 116 sizeof(struct siba_nexus_softc), bhnd_nexus_driver, siba_driver);
|
452
| 117
|
453DRIVER_MODULE(siba_nexus, nexus, siba_driver, bhnd_devclass, 0, 0);
| 118DRIVER_MODULE(siba_nexus, nexus, siba_nexus_driver, bhnd_devclass, 0, 0);
|
| |