Index: head/sys/dev/bhnd/bhnd_subr.c =================================================================== --- head/sys/dev/bhnd/bhnd_subr.c (revision 305952) +++ head/sys/dev/bhnd/bhnd_subr.c (revision 305953) @@ -1,1678 +1,1678 @@ /*- * Copyright (c) 2015 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "nvram/bhnd_nvram.h" #include "bhnd_chipc_if.h" #include "bhnd_nvram_if.h" #include "bhnd_nvram_map.h" #include "bhndreg.h" #include "bhndvar.h" /* BHND core device description table. */ static const struct bhnd_core_desc { uint16_t vendor; uint16_t device; bhnd_devclass_t class; const char *desc; } bhnd_core_descs[] = { #define BHND_CDESC(_mfg, _cid, _cls, _desc) \ { BHND_MFGID_ ## _mfg, BHND_COREID_ ## _cid, \ BHND_DEVCLASS_ ## _cls, _desc } BHND_CDESC(BCM, CC, CC, "ChipCommon I/O Controller"), BHND_CDESC(BCM, ILINE20, OTHER, "iLine20 HPNA"), BHND_CDESC(BCM, SRAM, RAM, "SRAM"), BHND_CDESC(BCM, SDRAM, RAM, "SDRAM"), BHND_CDESC(BCM, PCI, PCI, "PCI Bridge"), - BHND_CDESC(BCM, MIPS, CPU, "MIPS Core"), + BHND_CDESC(BCM, MIPS, CPU, "BMIPS CPU"), BHND_CDESC(BCM, ENET, ENET_MAC, "Fast Ethernet MAC"), BHND_CDESC(BCM, CODEC, OTHER, "V.90 Modem Codec"), BHND_CDESC(BCM, USB, USB_DUAL, "USB 1.1 Device/Host Controller"), BHND_CDESC(BCM, ADSL, OTHER, "ADSL Core"), BHND_CDESC(BCM, ILINE100, OTHER, "iLine100 HPNA"), BHND_CDESC(BCM, IPSEC, OTHER, "IPsec Accelerator"), BHND_CDESC(BCM, UTOPIA, OTHER, "UTOPIA ATM Core"), BHND_CDESC(BCM, PCMCIA, PCCARD, "PCMCIA Bridge"), BHND_CDESC(BCM, SOCRAM, RAM, "Internal Memory"), BHND_CDESC(BCM, MEMC, MEMC, "MEMC SDRAM Controller"), BHND_CDESC(BCM, OFDM, OTHER, "OFDM PHY"), BHND_CDESC(BCM, EXTIF, OTHER, "External Interface"), BHND_CDESC(BCM, D11, WLAN, "802.11 MAC/PHY/Radio"), BHND_CDESC(BCM, APHY, WLAN_PHY, "802.11a PHY"), BHND_CDESC(BCM, BPHY, WLAN_PHY, "802.11b PHY"), BHND_CDESC(BCM, GPHY, WLAN_PHY, "802.11g PHY"), - BHND_CDESC(BCM, MIPS33, CPU, "MIPS3302 Core"), + BHND_CDESC(BCM, MIPS33, CPU, "BMIPS33 CPU"), BHND_CDESC(BCM, USB11H, USB_HOST, "USB 1.1 Host Controller"), BHND_CDESC(BCM, USB11D, USB_DEV, "USB 1.1 Device Controller"), BHND_CDESC(BCM, USB20H, USB_HOST, "USB 2.0 Host Controller"), BHND_CDESC(BCM, USB20D, USB_DEV, "USB 2.0 Device Controller"), BHND_CDESC(BCM, SDIOH, OTHER, "SDIO Host Controller"), BHND_CDESC(BCM, ROBO, OTHER, "RoboSwitch"), BHND_CDESC(BCM, ATA100, OTHER, "Parallel ATA Controller"), BHND_CDESC(BCM, SATAXOR, OTHER, "SATA DMA/XOR Controller"), BHND_CDESC(BCM, GIGETH, ENET_MAC, "Gigabit Ethernet MAC"), BHND_CDESC(BCM, PCIE, PCIE, "PCIe Bridge"), BHND_CDESC(BCM, NPHY, WLAN_PHY, "802.11n 2x2 PHY"), BHND_CDESC(BCM, SRAMC, MEMC, "SRAM Controller"), BHND_CDESC(BCM, MINIMAC, OTHER, "MINI MAC/PHY"), BHND_CDESC(BCM, ARM11, CPU, "ARM1176 CPU"), BHND_CDESC(BCM, ARM7S, CPU, "ARM7TDMI-S CPU"), BHND_CDESC(BCM, LPPHY, WLAN_PHY, "802.11a/b/g PHY"), BHND_CDESC(BCM, PMU, PMU, "PMU"), BHND_CDESC(BCM, SSNPHY, WLAN_PHY, "802.11n Single-Stream PHY"), BHND_CDESC(BCM, SDIOD, OTHER, "SDIO Device Core"), BHND_CDESC(BCM, ARMCM3, CPU, "ARM Cortex-M3 CPU"), BHND_CDESC(BCM, HTPHY, WLAN_PHY, "802.11n 4x4 PHY"), BHND_CDESC(MIPS,MIPS74K, CPU, "MIPS74k CPU"), BHND_CDESC(BCM, GMAC, ENET_MAC, "Gigabit MAC core"), BHND_CDESC(BCM, DMEMC, MEMC, "DDR1/DDR2 Memory Controller"), BHND_CDESC(BCM, PCIERC, OTHER, "PCIe Root Complex"), BHND_CDESC(BCM, OCP, SOC_BRIDGE, "OCP to OCP Bridge"), BHND_CDESC(BCM, SC, OTHER, "Shared Common Core"), BHND_CDESC(BCM, AHB, SOC_BRIDGE, "OCP to AHB Bridge"), BHND_CDESC(BCM, SPIH, OTHER, "SPI Host Controller"), BHND_CDESC(BCM, I2S, OTHER, "I2S Digital Audio Interface"), BHND_CDESC(BCM, DMEMS, MEMC, "SDR/DDR1 Memory Controller"), BHND_CDESC(BCM, UBUS_SHIM, OTHER, "BCM6362/UBUS WLAN SHIM"), BHND_CDESC(BCM, PCIE2, PCIE, "PCIe Bridge (Gen2)"), BHND_CDESC(ARM, APB_BRIDGE, SOC_BRIDGE, "BP135 AMBA3 AXI to APB Bridge"), BHND_CDESC(ARM, PL301, SOC_ROUTER, "PL301 AMBA3 Interconnect"), BHND_CDESC(ARM, EROM, EROM, "PL366 Device Enumeration ROM"), BHND_CDESC(ARM, OOB_ROUTER, OTHER, "PL367 OOB Interrupt Router"), BHND_CDESC(ARM, AXI_UNMAPPED, OTHER, "Unmapped Address Ranges"), BHND_CDESC(BCM, 4706_CC, CC, "ChipCommon I/O Controller"), BHND_CDESC(BCM, NS_PCIE2, PCIE, "PCIe Bridge (Gen2)"), BHND_CDESC(BCM, NS_DMA, OTHER, "DMA engine"), BHND_CDESC(BCM, NS_SDIO, OTHER, "SDIO 3.0 Host Controller"), BHND_CDESC(BCM, NS_USB20H, USB_HOST, "USB 2.0 Host Controller"), BHND_CDESC(BCM, NS_USB30H, USB_HOST, "USB 3.0 Host Controller"), BHND_CDESC(BCM, NS_A9JTAG, OTHER, "ARM Cortex A9 JTAG Interface"), BHND_CDESC(BCM, NS_DDR23_MEMC, MEMC, "Denali DDR2/DD3 Memory Controller"), BHND_CDESC(BCM, NS_ROM, NVRAM, "System ROM"), BHND_CDESC(BCM, NS_NAND, NVRAM, "NAND Flash Controller"), BHND_CDESC(BCM, NS_QSPI, NVRAM, "QSPI Flash Controller"), BHND_CDESC(BCM, NS_CC_B, CC_B, "ChipCommon B Auxiliary I/O Controller"), BHND_CDESC(BCM, 4706_SOCRAM, RAM, "Internal Memory"), BHND_CDESC(BCM, IHOST_ARMCA9, CPU, "ARM Cortex A9 CPU"), BHND_CDESC(BCM, 4706_GMAC_CMN, ENET, "Gigabit MAC (Common)"), BHND_CDESC(BCM, 4706_GMAC, ENET_MAC, "Gigabit MAC"), BHND_CDESC(BCM, AMEMC, MEMC, "Denali DDR1/DDR2 Memory Controller"), #undef BHND_CDESC /* Derived from inspection of the BCM4331 cores that provide PrimeCell * IDs. Due to lack of documentation, the surmised device name/purpose * provided here may be incorrect. */ { BHND_MFGID_ARM, BHND_PRIMEID_EROM, BHND_DEVCLASS_OTHER, "PL364 Device Enumeration ROM" }, { BHND_MFGID_ARM, BHND_PRIMEID_SWRAP, BHND_DEVCLASS_OTHER, "PL368 Device Management Interface" }, { BHND_MFGID_ARM, BHND_PRIMEID_MWRAP, BHND_DEVCLASS_OTHER, "PL369 Device Management Interface" }, { 0, 0, 0, NULL } }; /** * Return the name for a given JEP106 manufacturer ID. * * @param vendor A JEP106 Manufacturer ID, including the non-standard ARM 4-bit * JEP106 continuation code. */ const char * bhnd_vendor_name(uint16_t vendor) { switch (vendor) { case BHND_MFGID_ARM: return "ARM"; case BHND_MFGID_BCM: return "Broadcom"; case BHND_MFGID_MIPS: return "MIPS"; default: return "unknown"; } } /** * Return the name of a port type. */ const char * bhnd_port_type_name(bhnd_port_type port_type) { switch (port_type) { case BHND_PORT_DEVICE: return ("device"); case BHND_PORT_BRIDGE: return ("bridge"); case BHND_PORT_AGENT: return ("agent"); default: return "unknown"; } } /** * Return the name of an NVRAM source. */ const char * bhnd_nvram_src_name(bhnd_nvram_src nvram_src) { switch (nvram_src) { case BHND_NVRAM_SRC_FLASH: return ("flash"); case BHND_NVRAM_SRC_OTP: return ("OTP"); case BHND_NVRAM_SRC_SPROM: return ("SPROM"); case BHND_NVRAM_SRC_UNKNOWN: return ("none"); default: return ("unknown"); } } static const struct bhnd_core_desc * bhnd_find_core_desc(uint16_t vendor, uint16_t device) { for (u_int i = 0; bhnd_core_descs[i].desc != NULL; i++) { if (bhnd_core_descs[i].vendor != vendor) continue; if (bhnd_core_descs[i].device != device) continue; return (&bhnd_core_descs[i]); } return (NULL); } /** * Return a human-readable name for a BHND core. * * @param vendor The core designer's JEDEC-106 Manufacturer ID * @param device The core identifier. */ const char * bhnd_find_core_name(uint16_t vendor, uint16_t device) { const struct bhnd_core_desc *desc; if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) return ("unknown"); return desc->desc; } /** * Return the device class for a BHND core. * * @param vendor The core designer's JEDEC-106 Manufacturer ID * @param device The core identifier. */ bhnd_devclass_t bhnd_find_core_class(uint16_t vendor, uint16_t device) { const struct bhnd_core_desc *desc; if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) return (BHND_DEVCLASS_OTHER); return desc->class; } /** * Return a human-readable name for a BHND core. * * @param ci The core's info record. */ const char * bhnd_core_name(const struct bhnd_core_info *ci) { return bhnd_find_core_name(ci->vendor, ci->device); } /** * Return the device class for a BHND core. * * @param ci The core's info record. */ bhnd_devclass_t bhnd_core_class(const struct bhnd_core_info *ci) { return bhnd_find_core_class(ci->vendor, ci->device); } /** * Write a human readable name representation of the given * BHND_CHIPID_* constant to @p buffer. * * @param buffer Output buffer, or NULL to compute the required size. * @param size Capacity of @p buffer, in bytes. * @param chip_id Chip ID to be formatted. * * @return Returns the required number of bytes on success, or a negative * integer on failure. No more than @p size-1 characters be written, with * the @p size'th set to '\0'. * * @sa BHND_CHIPID_MAX_NAMELEN */ int bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id) { /* All hex formatted IDs are within the range of 0x4000-0x9C3F (40000-1) */ if (chip_id >= 0x4000 && chip_id <= 0x9C3F) return (snprintf(buffer, size, "BCM%hX", chip_id)); else return (snprintf(buffer, size, "BCM%hu", chip_id)); } /** * Initialize a core info record with data from from a bhnd-attached @p dev. * * @param dev A bhnd device. * @param core The record to be initialized. */ struct bhnd_core_info bhnd_get_core_info(device_t dev) { return (struct bhnd_core_info) { .vendor = bhnd_get_vendor(dev), .device = bhnd_get_device(dev), .hwrev = bhnd_get_hwrev(dev), .core_idx = bhnd_get_core_index(dev), .unit = bhnd_get_core_unit(dev) }; } /** * Find a @p class child device with @p unit on @p dev. * * @param parent The bhnd-compatible bus to be searched. * @param class The device class to match on. * @param unit The core unit number; specify -1 to return the first match * regardless of unit number. * * @retval device_t if a matching child device is found. * @retval NULL if no matching child device is found. */ device_t bhnd_find_child(device_t dev, bhnd_devclass_t class, int unit) { struct bhnd_core_match md = { BHND_MATCH_CORE_CLASS(class), BHND_MATCH_CORE_UNIT(unit) }; if (unit == -1) md.m.match.core_unit = 0; return bhnd_match_child(dev, &md); } /** * Find the first child device on @p dev that matches @p desc. * * @param parent The bhnd-compatible bus to be searched. * @param desc A match descriptor. * * @retval device_t if a matching child device is found. * @retval NULL if no matching child device is found. */ device_t bhnd_match_child(device_t dev, const struct bhnd_core_match *desc) { device_t *devlistp; device_t match; int devcnt; int error; error = device_get_children(dev, &devlistp, &devcnt); if (error != 0) return (NULL); match = NULL; for (int i = 0; i < devcnt; i++) { struct bhnd_core_info ci = bhnd_get_core_info(devlistp[i]); if (bhnd_core_matches(&ci, desc)) { match = devlistp[i]; goto done; } } done: free(devlistp, M_TEMP); return match; } /** * Walk up the bhnd device hierarchy to locate the root device * to which the bhndb bridge is attached. * * This can be used from within bhnd host bridge drivers to locate the * actual upstream host device. * * @param dev A bhnd device. * @param bus_class The expected bus (e.g. "pci") to which the bridge root * should be attached. * * @retval device_t if a matching parent device is found. * @retval NULL @p dev is not attached via a bhndb bus * @retval NULL no parent device is attached via @p bus_class. */ device_t bhnd_find_bridge_root(device_t dev, devclass_t bus_class) { devclass_t bhndb_class; device_t parent; KASSERT(device_get_devclass(device_get_parent(dev)) == bhnd_devclass, ("%s not a bhnd device", device_get_nameunit(dev))); bhndb_class = devclass_find("bhndb"); /* Walk the device tree until we hit a bridge */ parent = dev; while ((parent = device_get_parent(parent)) != NULL) { if (device_get_devclass(parent) == bhndb_class) break; } /* No bridge? */ if (parent == NULL) return (NULL); /* Search for a parent attached to the expected bus class */ while ((parent = device_get_parent(parent)) != NULL) { device_t bus; bus = device_get_parent(parent); if (bus != NULL && device_get_devclass(bus) == bus_class) return (parent); } /* Not found */ return (NULL); } /** * Find the first core in @p cores that matches @p desc. * * @param cores The table to search. * @param num_cores The length of @p cores. * @param desc A match descriptor. * * @retval bhnd_core_info if a matching core is found. * @retval NULL if no matching core is found. */ const struct bhnd_core_info * bhnd_match_core(const struct bhnd_core_info *cores, u_int num_cores, const struct bhnd_core_match *desc) { for (u_int i = 0; i < num_cores; i++) { if (bhnd_core_matches(&cores[i], desc)) return &cores[i]; } return (NULL); } /** * Find the first core in @p cores with the given @p class. * * @param cores The table to search. * @param num_cores The length of @p cores. * @param desc A match descriptor. * * @retval bhnd_core_info if a matching core is found. * @retval NULL if no matching core is found. */ const struct bhnd_core_info * bhnd_find_core(const struct bhnd_core_info *cores, u_int num_cores, bhnd_devclass_t class) { struct bhnd_core_match md = { BHND_MATCH_CORE_CLASS(class) }; return bhnd_match_core(cores, num_cores, &md); } /** * Create an equality match descriptor for @p core. * * @param core The core info to be matched on. * @param desc On return, will be populated with a match descriptor for @p core. */ struct bhnd_core_match bhnd_core_get_match_desc(const struct bhnd_core_info *core) { return ((struct bhnd_core_match) { BHND_MATCH_CORE_VENDOR(core->vendor), BHND_MATCH_CORE_ID(core->device), BHND_MATCH_CORE_REV(HWREV_EQ(core->hwrev)), BHND_MATCH_CORE_CLASS(bhnd_core_class(core)), BHND_MATCH_CORE_IDX(core->core_idx), BHND_MATCH_CORE_UNIT(core->unit) }); } /** * Return true if the @p lhs is equal to @p rhs * * @param lhs The first bhnd core descriptor to compare. * @param rhs The second bhnd core descriptor to compare. * * @retval true if @p lhs is equal to @p rhs * @retval false if @p lhs is not equal to @p rhs */ bool bhnd_cores_equal(const struct bhnd_core_info *lhs, const struct bhnd_core_info *rhs) { struct bhnd_core_match md; /* Use an equality match descriptor to perform the comparison */ md = bhnd_core_get_match_desc(rhs); return (bhnd_core_matches(lhs, &md)); } /** * Return true if the @p core matches @p desc. * * @param core A bhnd core descriptor. * @param desc A match descriptor to compare against @p core. * * @retval true if @p core matches @p match * @retval false if @p core does not match @p match. */ bool bhnd_core_matches(const struct bhnd_core_info *core, const struct bhnd_core_match *desc) { if (desc->m.match.core_vendor && desc->core_vendor != core->vendor) return (false); if (desc->m.match.core_id && desc->core_id != core->device) return (false); if (desc->m.match.core_unit && desc->core_unit != core->unit) return (false); if (desc->m.match.core_rev && !bhnd_hwrev_matches(core->hwrev, &desc->core_rev)) return (false); if (desc->m.match.core_idx && desc->core_idx != core->core_idx) return (false); if (desc->m.match.core_class && desc->core_class != bhnd_core_class(core)) return (false); return true; } /** * Return true if the @p chip matches @p desc. * * @param chip A bhnd chip identifier. * @param desc A match descriptor to compare against @p chip. * * @retval true if @p chip matches @p match * @retval false if @p chip does not match @p match. */ bool bhnd_chip_matches(const struct bhnd_chipid *chip, const struct bhnd_chip_match *desc) { if (desc->m.match.chip_id && chip->chip_id != desc->chip_id) return (false); if (desc->m.match.chip_pkg && chip->chip_pkg != desc->chip_pkg) return (false); if (desc->m.match.chip_rev && !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) return (false); return (true); } /** * Return true if the @p board matches @p desc. * * @param board The bhnd board info. * @param desc A match descriptor to compare against @p board. * * @retval true if @p chip matches @p match * @retval false if @p chip does not match @p match. */ bool bhnd_board_matches(const struct bhnd_board_info *board, const struct bhnd_board_match *desc) { if (desc->m.match.board_srom_rev && !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev)) return (false); if (desc->m.match.board_vendor && board->board_vendor != desc->board_vendor) return (false); if (desc->m.match.board_type && board->board_type != desc->board_type) return (false); if (desc->m.match.board_rev && !bhnd_hwrev_matches(board->board_rev, &desc->board_rev)) return (false); return (true); } /** * Return true if the @p hwrev matches @p desc. * * @param hwrev A bhnd hardware revision. * @param desc A match descriptor to compare against @p core. * * @retval true if @p hwrev matches @p match * @retval false if @p hwrev does not match @p match. */ bool bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc) { if (desc->start != BHND_HWREV_INVALID && desc->start > hwrev) return false; if (desc->end != BHND_HWREV_INVALID && desc->end < hwrev) return false; return true; } /** * Return true if the @p dev matches @p desc. * * @param dev A bhnd device. * @param desc A match descriptor to compare against @p dev. * * @retval true if @p dev matches @p match * @retval false if @p dev does not match @p match. */ bool bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc) { struct bhnd_core_info core; const struct bhnd_chipid *chip; struct bhnd_board_info board; device_t parent; int error; /* Construct individual match descriptors */ struct bhnd_core_match m_core = { _BHND_CORE_MATCH_COPY(desc) }; struct bhnd_chip_match m_chip = { _BHND_CHIP_MATCH_COPY(desc) }; struct bhnd_board_match m_board = { _BHND_BOARD_MATCH_COPY(desc) }; /* Fetch and match core info */ if (m_core.m.match_flags) { /* Only applicable to bhnd-attached cores */ parent = device_get_parent(dev); if (device_get_devclass(parent) != bhnd_devclass) { device_printf(dev, "attempting to match core " "attributes against non-core device\n"); return (false); } core = bhnd_get_core_info(dev); if (!bhnd_core_matches(&core, &m_core)) return (false); } /* Fetch and match chip info */ if (m_chip.m.match_flags) { chip = bhnd_get_chipid(dev); if (!bhnd_chip_matches(chip, &m_chip)) return (false); } /* Fetch and match board info. * * This is not available until after NVRAM is up; earlier device * matches should not include board requirements */ if (m_board.m.match_flags) { if ((error = bhnd_read_board_info(dev, &board))) { device_printf(dev, "failed to read required board info " "during device matching: %d\n", error); return (false); } if (!bhnd_board_matches(&board, &m_board)) return (false); } /* All matched */ return (true); } /** * Search @p table for an entry matching @p dev. * * @param dev A bhnd device to match against @p table. * @param table The device table to search. * @param entry_size The @p table entry size, in bytes. * * @retval bhnd_device the first matching device, if any. * @retval NULL if no matching device is found in @p table. */ const struct bhnd_device * bhnd_device_lookup(device_t dev, const struct bhnd_device *table, size_t entry_size) { const struct bhnd_device *entry; device_t hostb, parent; bhnd_attach_type attach_type; uint32_t dflags; parent = device_get_parent(dev); hostb = bhnd_find_hostb_device(parent); attach_type = bhnd_get_attach_type(dev); for (entry = table; !BHND_DEVICE_IS_END(entry); entry = (const struct bhnd_device *) ((const char *) entry + entry_size)) { /* match core info */ if (!bhnd_device_matches(dev, &entry->core)) continue; /* match device flags */ dflags = entry->device_flags; /* hostb implies BHND_ATTACH_ADAPTER requirement */ if (dflags & BHND_DF_HOSTB) dflags |= BHND_DF_ADAPTER; if (dflags & BHND_DF_ADAPTER) if (attach_type != BHND_ATTACH_ADAPTER) continue; if (dflags & BHND_DF_HOSTB) if (dev != hostb) continue; if (dflags & BHND_DF_SOC) if (attach_type != BHND_ATTACH_NATIVE) continue; /* device found */ return (entry); } /* not found */ return (NULL); } /** * Scan the device @p table for all quirk flags applicable to @p dev. * * @param dev A bhnd device to match against @p table. * @param table The device table to search. * * @return returns all matching quirk flags. */ uint32_t bhnd_device_quirks(device_t dev, const struct bhnd_device *table, size_t entry_size) { const struct bhnd_device *dent; const struct bhnd_device_quirk *qent, *qtable; uint32_t quirks; /* Locate the device entry */ if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) return (0); /* Quirks table is optional */ qtable = dent->quirks_table; if (qtable == NULL) return (0); /* Collect matching device quirk entries */ quirks = 0; for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { if (bhnd_device_matches(dev, &qent->desc)) quirks |= qent->quirks; } return (quirks); } /** * Allocate bhnd(4) resources defined in @p rs from a parent bus. * * @param dev The device requesting ownership of the resources. * @param rs A standard bus resource specification. This will be updated * with the allocated resource's RIDs. * @param res On success, the allocated bhnd resources. * * @retval 0 success * @retval non-zero if allocation of any non-RF_OPTIONAL resource fails, * all allocated resources will be released and a regular * unix error code will be returned. */ int bhnd_alloc_resources(device_t dev, struct resource_spec *rs, struct bhnd_resource **res) { /* Initialize output array */ for (u_int i = 0; rs[i].type != -1; i++) res[i] = NULL; for (u_int i = 0; rs[i].type != -1; i++) { res[i] = bhnd_alloc_resource_any(dev, rs[i].type, &rs[i].rid, rs[i].flags); /* Clean up all allocations on failure */ if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) { bhnd_release_resources(dev, rs, res); return (ENXIO); } } return (0); } /** * Release bhnd(4) resources defined in @p rs from a parent bus. * * @param dev The device that owns the resources. * @param rs A standard bus resource specification previously initialized * by @p bhnd_alloc_resources. * @param res The bhnd resources to be released. */ void bhnd_release_resources(device_t dev, const struct resource_spec *rs, struct bhnd_resource **res) { for (u_int i = 0; rs[i].type != -1; i++) { if (res[i] == NULL) continue; bhnd_release_resource(dev, rs[i].type, rs[i].rid, res[i]); res[i] = NULL; } } /** * Parse the CHIPC_ID_* fields from the ChipCommon CHIPC_ID * register, returning its bhnd_chipid representation. * * @param idreg The CHIPC_ID register value. * @param enum_addr The enumeration address to include in the result. * * @warning * On early siba(4) devices, the ChipCommon core does not provide * a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions * (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return * an invalid `ncores` value. */ struct bhnd_chipid bhnd_parse_chipid(uint32_t idreg, bhnd_addr_t enum_addr) { struct bhnd_chipid result; /* Fetch the basic chip info */ result.chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP); result.chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG); result.chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV); result.chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); result.ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE); result.enum_addr = enum_addr; return (result); } /** * Determine the correct core count for a chip identification value that * may contain an invalid core count. * * On some early siba(4) devices (see CHIPC_NCORES_MIN_HWREV()), the ChipCommon * core does not provide a valid CHIPC_ID_NUMCORE field. * * @param cid The chip identification to be queried. * @param chipc_hwrev The hardware revision of the ChipCommon core from which * @p cid was parsed. * @param[out] ncores On success, will be set to the correct core count. * * @retval 0 If the core count is already correct, or was mapped to a * a correct value. * @retval EINVAL If the core count is incorrect, but the chip was not * recognized. */ int bhnd_chipid_fixed_ncores(const struct bhnd_chipid *cid, uint16_t chipc_hwrev, uint8_t *ncores) { /* bcma(4), and most siba(4) devices */ if (CHIPC_NCORES_MIN_HWREV(chipc_hwrev)) { *ncores = cid->ncores; return (0); } /* broken siba(4) chipsets */ switch (cid->chip_id) { case BHND_CHIPID_BCM4306: *ncores = 6; break; case BHND_CHIPID_BCM4704: *ncores = 9; break; case BHND_CHIPID_BCM5365: /* * BCM5365 does support ID_NUMCORE in at least * some of its revisions, but for unknown * reasons, Broadcom's drivers always exclude * the ChipCommon revision (0x5) used by BCM5365 * from the set of revisions supporting * ID_NUMCORE, and instead supply a fixed value. * * Presumably, at least some of these devices * shipped with a broken ID_NUMCORE value. */ *ncores = 7; break; default: return (EINVAL); } return (0); } /** * Allocate the resource defined by @p rs via @p dev, use it * to read the ChipCommon ID register relative to @p chipc_offset, * then release the resource. * * @param dev The device owning @p rs. * @param rs A resource spec that encompasses the ChipCommon register block. * @param chipc_offset The offset of the ChipCommon registers within @p rs. * @param[out] result the chip identification data. * * @retval 0 success * @retval non-zero if the ChipCommon identification data could not be read. */ int bhnd_read_chipid(device_t dev, struct resource_spec *rs, bus_size_t chipc_offset, struct bhnd_chipid *result) { struct resource *res; bhnd_addr_t enum_addr; uint32_t reg; uint8_t chip_type; int error, rid, rtype; rid = rs->rid; rtype = rs->type; error = 0; /* Allocate the ChipCommon window resource and fetch the chipid data */ res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "failed to allocate bhnd chipc resource\n"); return (ENXIO); } /* Fetch the basic chip info */ reg = bus_read_4(res, chipc_offset + CHIPC_ID); chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS); /* Fetch the EROMPTR */ if (BHND_CHIPTYPE_HAS_EROM(chip_type)) { enum_addr = bus_read_4(res, chipc_offset + CHIPC_EROMPTR); } else if (chip_type == BHND_CHIPTYPE_SIBA) { /* siba(4) uses the ChipCommon base address as the enumeration * address */ enum_addr = BHND_DEFAULT_CHIPC_ADDR; } else { device_printf(dev, "unknown chip type %hhu\n", chip_type); error = ENODEV; goto cleanup; } *result = bhnd_parse_chipid(reg, enum_addr); /* Fix the core count on early siba(4) devices */ if (chip_type == BHND_CHIPTYPE_SIBA) { uint32_t idh; uint16_t chipc_hwrev; /* * We need the ChipCommon revision to determine whether * the ncore field is valid. * * We can safely assume the siba IDHIGH register is mapped * within the chipc register block. */ idh = bus_read_4(res, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); chipc_hwrev = SIBA_IDH_CORE_REV(idh); error = bhnd_chipid_fixed_ncores(result, chipc_hwrev, &result->ncores); if (error) goto cleanup; } cleanup: /* Clean up */ bus_release_resource(dev, rtype, rid, res); return (error); } /** * Read an NVRAM variable's NUL-terminated string value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] buf A buffer large enough to hold @p len bytes. On * success, the NUL-terminated string value will be * written to this buffer. This argment may be NULL if * the value is not desired. * @param len The maximum capacity of @p buf. * @param[out] rlen On success, will be set to the actual size of * the requested value (including NUL termination). This * argment may be NULL if the size is not desired. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too * small to hold the requested value. * @retval EFTYPE If the variable data cannot be coerced to a valid * string representation. * @retval ERANGE If value coercion would overflow @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len, size_t *rlen) { size_t larg; int error; larg = len; error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_CSTR); if (rlen != NULL) *rlen = larg; return (error); } /** * Read an NVRAM variable's unsigned integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * @param width The output integer type width (1, 2, or * 4 bytes). * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) an * unsigned representation of the given @p width. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width) { bhnd_nvram_type type; size_t len; switch (width) { case 1: type = BHND_NVRAM_TYPE_UINT8; break; case 2: type = BHND_NVRAM_TYPE_UINT16; break; case 4: type = BHND_NVRAM_TYPE_UINT32; break; default: device_printf(dev, "unsupported NVRAM integer width: %d\n", width); return (EINVAL); } len = width; return (bhnd_nvram_getvar(dev, name, value, &len, type)); } /** * Read an NVRAM variable's unsigned 8-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) uint8_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's unsigned 16-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * uint16_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's unsigned 32-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * uint32_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * @param width The output integer type width (1, 2, or * 4 bytes). * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) an * signed representation of the given @p width. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width) { bhnd_nvram_type type; size_t len; switch (width) { case 1: type = BHND_NVRAM_TYPE_INT8; break; case 2: type = BHND_NVRAM_TYPE_INT16; break; case 4: type = BHND_NVRAM_TYPE_INT32; break; default: device_printf(dev, "unsupported NVRAM integer width: %d\n", width); return (EINVAL); } len = width; return (bhnd_nvram_getvar(dev, name, value, &len, type)); } /** * Read an NVRAM variable's signed 8-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) int8_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed 16-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * int16_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed 32-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * int32_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's array value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] buf A buffer large enough to hold @p size bytes. * On success, the requested value will be written * to this buffer. * @param[in,out] size The required number of bytes to write to * @p buf. * @param type The desired array element data representation. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval ENXIO If less than @p size bytes are available. * @retval ENOMEM If a buffer of @p size is too small to hold the * requested value. * @retval EFTYPE If the variable data cannot be coerced to a * a valid instance of @p type. * @retval ERANGE If value coercion would overflow (or underflow) a * representation of @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size, bhnd_nvram_type type) { size_t nbytes; int error; /* Attempt read */ nbytes = size; if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type))) return (error); /* Verify that the expected number of bytes were fetched */ if (nbytes < size) return (ENXIO); return (0); } /** * Using the bhnd(4) bus-level core information and a custom core name, * populate @p dev's device description. * * @param dev A bhnd-bus attached device. * @param dev_name The core's name (e.g. "SDIO Device Core") */ void bhnd_set_custom_core_desc(device_t dev, const char *dev_name) { const char *vendor_name; char *desc; vendor_name = bhnd_get_vendor_name(dev); asprintf(&desc, M_BHND, "%s %s, rev %hhu", vendor_name, dev_name, bhnd_get_hwrev(dev)); if (desc != NULL) { device_set_desc_copy(dev, desc); free(desc, M_BHND); } else { device_set_desc(dev, dev_name); } } /** * Using the bhnd(4) bus-level core information, populate @p dev's device * description. * * @param dev A bhnd-bus attached device. */ void bhnd_set_default_core_desc(device_t dev) { bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev)); } /** * Using the bhnd @p chip_id, populate the bhnd(4) bus @p dev's device * description. * * @param dev A bhnd-bus attached device. */ void bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id) { const char *bus_name; char *desc; char chip_name[BHND_CHIPID_MAX_NAMELEN]; /* Determine chip type's bus name */ switch (chip_id->chip_type) { case BHND_CHIPTYPE_SIBA: bus_name = "SIBA bus"; break; case BHND_CHIPTYPE_BCMA: case BHND_CHIPTYPE_BCMA_ALT: bus_name = "BCMA bus"; break; case BHND_CHIPTYPE_UBUS: bus_name = "UBUS bus"; break; default: bus_name = "Unknown Type"; break; } /* Format chip name */ bhnd_format_chip_id(chip_name, sizeof(chip_name), chip_id->chip_id); /* Format and set device description */ asprintf(&desc, M_BHND, "%s %s", chip_name, bus_name); if (desc != NULL) { device_set_desc_copy(dev, desc); free(desc, M_BHND); } else { device_set_desc(dev, bus_name); } } /** * Helper function for implementing BHND_BUS_IS_HW_DISABLED(). * * If a parent device is available, this implementation delegates the * request to the BHND_BUS_IS_HW_DISABLED() method on the parent of @p dev. * * If no parent device is available (i.e. on a the bus root), the hardware * is assumed to be usable and false is returned. */ bool bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child) { if (device_get_parent(dev) != NULL) return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), child)); return (false); } /** * Helper function for implementing BHND_BUS_GET_CHIPID(). * * This implementation delegates the request to the BHND_BUS_GET_CHIPID() * method on the parent of @p dev. If no parent exists, the implementation * will panic. */ const struct bhnd_chipid * bhnd_bus_generic_get_chipid(device_t dev, device_t child) { if (device_get_parent(dev) != NULL) return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child)); panic("missing BHND_BUS_GET_CHIPID()"); } /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ #define BHND_GV(_dest, _name) \ bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest, \ sizeof(_dest)) #define REQ_BHND_GV(_dest, _name) do { \ if ((error = BHND_GV(_dest, _name))) { \ device_printf(dev, \ "error reading " __STRING(_name) ": %d\n", error); \ return (error); \ } \ } while(0) #define OPT_BHND_GV(_dest, _name, _default) do { \ if ((error = BHND_GV(_dest, _name))) { \ if (error != ENOENT) { \ device_printf(dev, \ "error reading " \ __STRING(_name) ": %d\n", error); \ return (error); \ } \ _dest = _default; \ } \ } while(0) /** * Helper function for implementing BHND_BUS_READ_BOARDINFO(). * * This implementation populates @p info with information from NVRAM, * defaulting board_vendor and board_type fields to 0 if the * requested variables cannot be found. * * This behavior is correct for most SoCs, but must be overridden on * bridged (PCI, PCMCIA, etc) devices to produce a complete bhnd_board_info * result. */ int bhnd_bus_generic_read_board_info(device_t dev, device_t child, struct bhnd_board_info *info) { int error; OPT_BHND_GV(info->board_vendor, BOARDVENDOR, 0); OPT_BHND_GV(info->board_type, BOARDTYPE, 0); /* srom >= 2 */ REQ_BHND_GV(info->board_rev, BOARDREV); OPT_BHND_GV(info->board_srom_rev,SROMREV, 0); /* missing in some SoC NVRAM */ REQ_BHND_GV(info->board_flags, BOARDFLAGS); OPT_BHND_GV(info->board_flags2, BOARDFLAGS2, 0); /* srom >= 4 */ OPT_BHND_GV(info->board_flags3, BOARDFLAGS3, 0); /* srom >= 11 */ return (0); } #undef BHND_GV #undef BHND_GV_REQ #undef BHND_GV_OPT /** * Helper function for implementing BHND_BUS_GET_NVRAM_VAR(). * * This implementation searches @p dev for a usable NVRAM child device. * * If no usable child device is found on @p dev, the request is delegated to * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. */ int bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size, bhnd_nvram_type type) { device_t nvram; device_t parent; /* Make sure we're holding Giant for newbus */ GIANT_REQUIRED; /* Look for a directly-attached NVRAM child */ if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL) return BHND_NVRAM_GETVAR(nvram, name, buf, size, type); /* Try to delegate to parent */ if ((parent = device_get_parent(dev)) == NULL) return (ENODEV); return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, name, buf, size, type)); } /** * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). * * This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation * of the underlying resource to BUS_ALLOC_RESOURCE(), and activation * to @p dev's BHND_BUS_ACTIVATE_RESOURCE(). */ struct bhnd_resource * bhnd_bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct bhnd_resource *br; struct resource *res; int error; br = NULL; res = NULL; /* Allocate the real bus resource (without activating it) */ res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end, count, (flags & ~RF_ACTIVE)); if (res == NULL) return (NULL); /* Allocate our bhnd resource wrapper. */ br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); if (br == NULL) goto failed; br->direct = false; br->res = res; /* Attempt activation */ if (flags & RF_ACTIVE) { error = BHND_BUS_ACTIVATE_RESOURCE(dev, child, type, *rid, br); if (error) goto failed; } return (br); failed: if (res != NULL) BUS_RELEASE_RESOURCE(dev, child, type, *rid, res); free(br, M_BHND); return (NULL); } /** * Helper function for implementing BHND_BUS_RELEASE_RESOURCE(). * * This implementation of BHND_BUS_RELEASE_RESOURCE() delegates release of * the backing resource to BUS_RELEASE_RESOURCE(). */ int bhnd_bus_generic_release_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { int error; if ((error = BUS_RELEASE_RESOURCE(dev, child, type, rid, r->res))) return (error); free(r, M_BHND); return (0); } /** * Helper function for implementing BHND_BUS_ACTIVATE_RESOURCE(). * * This implementation of BHND_BUS_ACTIVATE_RESOURCE() first calls the * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. * * If this fails, and if @p dev is the direct parent of @p child, standard * resource activation is attempted via bus_activate_resource(). This enables * direct use of the bhnd(4) resource APIs on devices that may not be attached * to a parent bhnd bus or bridge. */ int bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { int error; bool passthrough; passthrough = (device_get_parent(child) != dev); /* Try to delegate to the parent */ if (device_get_parent(dev) != NULL) { error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r); } else { error = ENODEV; } /* If bhnd(4) activation has failed and we're the child's direct * parent, try falling back on standard resource activation. */ if (error && !passthrough) { error = bus_activate_resource(child, type, rid, r->res); if (!error) r->direct = true; } return (error); } /** * Helper function for implementing BHND_BUS_DEACTIVATE_RESOURCE(). * * This implementation of BHND_BUS_ACTIVATE_RESOURCE() simply calls the * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. */ int bhnd_bus_generic_deactivate_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { if (device_get_parent(dev) != NULL) return (BHND_BUS_DEACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r)); return (EINVAL); } Index: head/sys/mips/broadcom/bcm_mips_exts.h =================================================================== --- head/sys/mips/broadcom/bcm_mips_exts.h (revision 305952) +++ head/sys/mips/broadcom/bcm_mips_exts.h (nonexistent) @@ -1,190 +0,0 @@ -/*- - * Copyright 2000,2001,2002,2003 Broadcom Corporation. - * All rights reserved. - * - * This file is derived from the sbmips32.h header distributed - * by Broadcom with the CFE 1.4.2 sources. - * - * This software is furnished under license and may be used and - * copied only in accordance with the following terms and - * conditions. Subject to these conditions, you may download, - * copy, install, use, modify and distribute modified or unmodified - * copies of this software in source and/or binary form. No title - * or ownership is transferred hereby. - * - * 1) Any source code used, modified or distributed must reproduce - * and retain this copyright notice and list of conditions - * as they appear in the source file. - * - * 2) No right is granted to use any trade name, trademark, or - * logo of Broadcom Corporation. The "Broadcom Corporation" - * name may not be used to endorse or promote products derived - * from this software without the prior written permission of - * Broadcom Corporation. - * - * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT - * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN - * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - - -/* ********************************************************************* - * Broadcom Common Firmware Environment (CFE) - * - * MIPS32 CPU definitions File: sbmips32.h - * - * This module contains constants and macros specific to the - * Broadcom MIPS32 core. In addition to generic MIPS32, it - * includes definitions for the MIP32-01 and MIPS3302 OCP cores - * for the Silicon Backplane. - * - *********************************************************************/ - -#ifndef _MIPS_BROADCOM_BCM_MIPS_EXTS_H_ -#define _MIPS_BROADCOM_BCM_MIPS_EXTS_H_ - -#include - -/* - * The following Broadcom Custom CP0 Registers appear in the Broadcom - * BMIPS330x MIPS32 core. - */ - -#define MIPS_COP_0_BCMCFG 22 - -/* - * Custom CP0 Accessors - */ - -#define BCM_MIPS_RW32_COP0_SEL(n,r,s) \ -static __inline uint32_t \ -bcm_mips_rd_ ## n(void) \ -{ \ - int v0; \ - __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \ - : [v0] "=&r"(v0)); \ - mips_barrier(); \ - return (v0); \ -} \ -static __inline void \ -bcm_mips_wr_ ## n(uint32_t a0) \ -{ \ - __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \ - __XSTRING(COP0_SYNC)";" \ - "nop;" \ - "nop;" \ - : \ - : [a0] "r"(a0)); \ - mips_barrier(); \ -} struct __hack - -BCM_MIPS_RW32_COP0_SEL(pllcfg1, MIPS_COP_0_CONFIG, 1); -BCM_MIPS_RW32_COP0_SEL(pllcfg2, MIPS_COP_0_CONFIG, 2); -BCM_MIPS_RW32_COP0_SEL(clksync, MIPS_COP_0_CONFIG, 3); -BCM_MIPS_RW32_COP0_SEL(pllcfg3, MIPS_COP_0_CONFIG, 4); -BCM_MIPS_RW32_COP0_SEL(rstcfg, MIPS_COP_0_CONFIG, 5); - -/* - * Broadcom PLLConfig1 Register (22, select 1) - */ - -/* SoftMIPSPLLCfg */ -#define MIPS_BCMCFG_PLLCFG1_MC_SHIFT 10 -#define MIPS_BCMCFG_PLLCFG1_MC_MASK 0xFFFFFC00 - -/* SoftISBPLLCfg */ -#define MIPS_BCMCFG_PLLCFG1_BC_SHIFT 5 -#define MIPS_BCMCFG_PLLCFG1_BC_MASK 0x000003E0 - -/* SoftRefPLLCfg */ -#define MIPS_BCMCFG_PLLCFG1_PC_SHIFT 0 -#define MIPS_BCMCFG_PLLCFG1_PC_MASK 0x0000001F - -/* - * Broadcom PLLConfig2 Register (22, select 2) - */ - -/* Soft1to1ClkRatio */ -#define MIPS_BCMCFG_PLLCFG2_CR (1<<23) - -/* SoftUSBxPLLCfg */ -#define MIPS_BCMCFG_PLLCFG2_UC_SHIFT 15 -#define MIPS_BCMCFG_PLLCFG2_UC_MASK 0x007F8000 - -/* SoftIDExPLLCfg */ -#define MIPS_BCMCFG_PLLCFG2_IC_SHIFT 7 -#define MIPS_BCMCFG_PLLCFG2_IC_MASK 0x00007F80 - -#define MIPS_BCMCFG_PLLCFG2_BE (1<<6) /* ISBxSoftCfgEnable */ -#define MIPS_BCMCFG_PLLCFG2_UE (1<<5) /* USBxSoftCfgEnable */ -#define MIPS_BCMCFG_PLLCFG2_IE (1<<4) /* IDExSoftCfgEnable */ -#define MIPS_BCMCFG_PLLCFG2_CA (1<<3) /* CfgActive */ -#define MIPS_BCMCFG_PLLCFG2_CF (1<<2) /* RefSoftCfgEnable */ -#define MIPS_BCMCFG_PLLCFG2_CI (1<<1) /* ISBSoftCfgEnable */ -#define MIPS_BCMCFG_PLLCFG2_CC (1<<0) /* MIPSSoftCfgEnable */ - -/* - * Broadcom ClkSync Register (22, select 3) - */ -/* SoftClkCfgHigh */ -#define MIPS_BCMCFG_CLKSYNC_CH_SHIFT 16 -#define MIPS_BCMCFG_CLKSYNC_CH_MASK 0xFFFF0000 - -/* SoftClkCfgLow */ -#define MIPS_BCMCFG_CLKSYNC_CL_SHIFT 0 -#define MIPS_BCMCFG_CLKSYNC_CL_MASK 0x0000FFFF - -/* - * Broadcom ISBxPLLConfig3 Register (22, select 4) - */ - -/* AsyncClkRatio */ -#define MIPS_BCMCFG_PLLCFG3_AR_SHIFT 23 -#define MIPS_BCMCFG_PLLCFG3_AR_MASK 0x01800000 - -#define MIPS_BCMCFG_PLLCFG3_SM (1<<22) /* SyncMode */ - -/* SoftISBxPLLCfg */ -#define MIPS_BCMCFG_PLLCFG3_IC_SHIFT 0 -#define MIPS_BCMCFG_PLLCFG3_IC_MASK 0x003FFFFF - -/* - * Broadcom BRCMRstConfig Register (22, select 5) - */ - -#define MIPS_BCMCFG_RSTCFG_SR (1<<18) /* SSMR */ -#define MIPS_BCMCFG_RSTCFG_DT (1<<16) /* BHTD */ - -/* RStSt */ -#define MIPS_BCMCFG_RSTCFG_RS_SHIFT 8 -#define MIPS_BCMCFG_RSTCFG_RS_MASK 0x00001F00 -#define MIPS_BCMCFG_RST_OTHER 0x00 -#define MIPS_BCMCFG_RST_SH 0x01 -#define MIPS_BCMCFG_RST_SS 0x02 -#define MIPS_BCMCFG_RST_EJTAG 0x04 -#define MIPS_BCMCFG_RST_WDOG 0x08 -#define MIPS_BCMCFG_RST_CRC 0x10 - -#define MIPS_BCMCFG_RSTCFG_CR (1<<7) /* RStCr */ - -/* WBMD */ -#define MIPS_BCMCFG_RSTCFG_WD_SHIFT 3 -#define MIPS_BCMCFG_RSTCFG_WD_MASK 0x00000078 - -#define MIPS_BCMCFG_RSTCFG_SS (1<<2) /* SSR */ -#define MIPS_BCMCFG_RSTCFG_SH (1<<1) /* SHR */ -#define MIPS_BCMCFG_RSTCFG_BR (1<<0) /* BdR */ - -#endif /* _MIPS_BROADCOM_BCM_MIPS_EXTS_H_ */ Property changes on: head/sys/mips/broadcom/bcm_mips_exts.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_mipscore.c =================================================================== --- head/sys/mips/broadcom/bcm_mipscore.c (revision 305952) +++ head/sys/mips/broadcom/bcm_mipscore.c (nonexistent) @@ -1,126 +0,0 @@ -/*- - * Copyright (c) 2016 Michael Zhilin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "bcm_mipscore.h" - -static const struct resource_spec mipscore_rspec[MIPSCORE_MAX_RSPEC] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, -1, 0 } -}; - -#define MIPSCORE_DEV(_vendor, _core) \ - BHND_DEVICE(_vendor, _core, NULL, NULL, BHND_DF_SOC) - -struct bhnd_device mipscore_match[] = { - MIPSCORE_DEV(BCM, MIPS), - MIPSCORE_DEV(BCM, MIPS33), - MIPSCORE_DEV(MIPS, MIPS74K), - BHND_DEVICE_END -}; - -static int -mipscore_probe(device_t dev) -{ - const struct bhnd_device *id; - - id = bhnd_device_lookup(dev, mipscore_match, sizeof(mipscore_match[0])); - if (id == NULL) - return (ENXIO); - - bhnd_set_default_core_desc(dev); - return (BUS_PROBE_DEFAULT); -} - -static int -mipscore_attach(device_t dev) -{ - struct mipscore_softc *sc; - struct resource *res; - uint32_t intmask; - uint16_t devid; - int error; - - sc = device_get_softc(dev); - devid = bhnd_get_device(dev); - - sc->devid = devid; - sc->dev = dev; - - /* Allocate bus resources */ - memcpy(sc->rspec, mipscore_rspec, sizeof(sc->rspec)); - error = bhnd_alloc_resources(dev, sc->rspec, sc->res); - if (error) - return (error); - - res = sc->res[0]->res; - if (res == NULL) - return (ENXIO); - - if (devid == BHND_COREID_MIPS74K) { - intmask = (1 << 31); - /* Use intmask5 register to route the timer interrupt */ - bus_write_4(res, offsetof(struct mipscore_regs, intmask[5]), - intmask); - } - - return (0); -} - -static device_method_t mipscore_methods[] = { - DEVMETHOD(device_probe, mipscore_probe), - DEVMETHOD(device_attach, mipscore_attach), - DEVMETHOD_END -}; - -devclass_t bhnd_mipscore_devclass; - -DEFINE_CLASS_0(bhnd_mips, mipscore_driver, mipscore_methods, - sizeof(struct mipscore_softc)); -EARLY_DRIVER_MODULE(bhnd_mips, bhnd, mipscore_driver, - bhnd_mipscore_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); -MODULE_VERSION(bhnd_mips, 1); Property changes on: head/sys/mips/broadcom/bcm_mipscore.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_mipscore.h =================================================================== --- head/sys/mips/broadcom/bcm_mipscore.h (revision 305952) +++ head/sys/mips/broadcom/bcm_mipscore.h (nonexistent) @@ -1,60 +0,0 @@ -/*- - * Copyright (c) 2016 Michael Zhilin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - * $FreeBSD$ - */ - -#ifndef _BHND_CORES_MIPS_MIPSCOREVAR_H_ -#define _BHND_CORES_MIPS_MIPSCOREVAR_H_ - -#define MIPSCORE_MAX_RSPEC 2 - -struct mipscore_softc { - device_t dev; /* CPU device */ - uint32_t devid; - struct resource_spec rspec[MIPSCORE_MAX_RSPEC]; - struct bhnd_resource *res[MIPSCORE_MAX_RSPEC]; -}; - -struct mipscore_regs { - uint32_t corecontrol; - uint32_t exceptionbase; - uint32_t PAD1[1]; /* unmapped address */ - uint32_t biststatus; - uint32_t intstatus; - uint32_t intmask[6]; - uint32_t nmimask; - uint32_t PAD2[4]; /* unmapped addresses */ - uint32_t gpioselect; - uint32_t gpiooutput; - uint32_t gpioenable; - uint32_t PAD3[101]; /* unmapped addresses */ - uint32_t clkcontrolstatus; -}; - -#endif /* _BHND_CORES_MIPS_MIPSCOREVAR_H_ */ Property changes on: head/sys/mips/broadcom/bcm_mipscore.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_bmips.c =================================================================== --- head/sys/mips/broadcom/bcm_bmips.c (nonexistent) +++ head/sys/mips/broadcom/bcm_bmips.c (revision 305953) @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "bcm_bmipsreg.h" + +/* + * BMIPS32 and BMIPS3300 core driver. + * + * These cores are only found on siba(4) chipsets, allowing + * us to assume the availability of siba interrupt registers. + */ + +static const struct bhnd_device bcm_bmips_devs[] = { + BHND_DEVICE(BCM, MIPS33, NULL, NULL, BHND_DF_SOC), + BHND_DEVICE_END +}; + +struct bcm_bmips_softc { + device_t dev; + struct resource *mem_res; + int mem_rid; +}; + +static int +bcm_bmips_probe(device_t dev) +{ + const struct bhnd_device *id; + + id = bhnd_device_lookup(dev, bcm_bmips_devs, + sizeof(bcm_bmips_devs[0])); + if (id == NULL) + return (ENXIO); + + bhnd_set_default_core_desc(dev); + return (BUS_PROBE_DEFAULT); +} + +static int +bcm_bmips_attach(device_t dev) +{ + struct bcm_bmips_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Allocate bus resources */ + sc->mem_rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, + RF_ACTIVE); + if (sc->mem_res == NULL) + return (ENXIO); + + return (0); +} + +static int +bcm_bmips_detach(device_t dev) +{ + struct bcm_bmips_softc *sc; + + sc = device_get_softc(dev); + + bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res); + + return (0); +} + +static device_method_t bcm_bmips_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bcm_bmips_probe), + DEVMETHOD(device_attach, bcm_bmips_attach), + DEVMETHOD(device_detach, bcm_bmips_detach), + + DEVMETHOD_END +}; + +static devclass_t bcm_mips_devclass; + +DEFINE_CLASS_0(bcm_mips, bcm_bmips_driver, bcm_bmips_methods, sizeof(struct bcm_bmips_softc)); +EARLY_DRIVER_MODULE(bcm_bmips, bhnd, bcm_bmips_driver, bcm_mips_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); + +MODULE_VERSION(bcm_bmips, 1); +MODULE_DEPEND(bcm_bmips, bhnd, 1, 1, 1); Property changes on: head/sys/mips/broadcom/bcm_bmips.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_bmips_exts.h =================================================================== --- head/sys/mips/broadcom/bcm_bmips_exts.h (nonexistent) +++ head/sys/mips/broadcom/bcm_bmips_exts.h (revision 305953) @@ -0,0 +1,190 @@ +/*- + * Copyright 2000,2001,2002,2003 Broadcom Corporation. + * All rights reserved. + * + * This file is derived from the sbmips32.h header distributed + * by Broadcom with the CFE 1.4.2 sources. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + + +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS32 CPU definitions File: sbmips32.h + * + * This module contains constants and macros specific to the + * Broadcom MIPS32 core. In addition to generic MIPS32, it + * includes definitions for the MIP32-01 and MIPS3302 OCP cores + * for the Silicon Backplane. + * + *********************************************************************/ + +#ifndef _MIPS_BROADCOM_BCM_BMIPS_EXTS_H_ +#define _MIPS_BROADCOM_BCM_BMIPS_EXTS_H_ + +#include + +/* + * The following Broadcom Custom CP0 Registers appear in the Broadcom + * BMIPS330x MIPS32 core. + */ + +#define BMIPS_COP_0_BCMCFG 22 + +/* + * Custom CP0 Accessors + */ + +#define BCM_BMIPS_RW32_COP0_SEL(n,r,s) \ +static __inline uint32_t \ +bcm_bmips_rd_ ## n(void) \ +{ \ + int v0; \ + __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \ + : [v0] "=&r"(v0)); \ + mips_barrier(); \ + return (v0); \ +} \ +static __inline void \ +bcm_bmips_wr_ ## n(uint32_t a0) \ +{ \ + __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \ + __XSTRING(COP0_SYNC)";" \ + "nop;" \ + "nop;" \ + : \ + : [a0] "r"(a0)); \ + mips_barrier(); \ +} struct __hack + +BCM_BMIPS_RW32_COP0_SEL(pllcfg1, MIPS_COP_0_CONFIG, 1); +BCM_BMIPS_RW32_COP0_SEL(pllcfg2, MIPS_COP_0_CONFIG, 2); +BCM_BMIPS_RW32_COP0_SEL(clksync, MIPS_COP_0_CONFIG, 3); +BCM_BMIPS_RW32_COP0_SEL(pllcfg3, MIPS_COP_0_CONFIG, 4); +BCM_BMIPS_RW32_COP0_SEL(rstcfg, MIPS_COP_0_CONFIG, 5); + +/* + * Broadcom PLLConfig1 Register (22, select 1) + */ + +/* SoftMIPSPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG1_MC_SHIFT 10 +#define BMIPS_BCMCFG_PLLCFG1_MC_MASK 0xFFFFFC00 + +/* SoftISBPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG1_BC_SHIFT 5 +#define BMIPS_BCMCFG_PLLCFG1_BC_MASK 0x000003E0 + +/* SoftRefPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG1_PC_SHIFT 0 +#define BMIPS_BCMCFG_PLLCFG1_PC_MASK 0x0000001F + +/* + * Broadcom PLLConfig2 Register (22, select 2) + */ + +/* Soft1to1ClkRatio */ +#define BMIPS_BCMCFG_PLLCFG2_CR (1<<23) + +/* SoftUSBxPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG2_UC_SHIFT 15 +#define BMIPS_BCMCFG_PLLCFG2_UC_MASK 0x007F8000 + +/* SoftIDExPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG2_IC_SHIFT 7 +#define BMIPS_BCMCFG_PLLCFG2_IC_MASK 0x00007F80 + +#define BMIPS_BCMCFG_PLLCFG2_BE (1<<6) /* ISBxSoftCfgEnable */ +#define BMIPS_BCMCFG_PLLCFG2_UE (1<<5) /* USBxSoftCfgEnable */ +#define BMIPS_BCMCFG_PLLCFG2_IE (1<<4) /* IDExSoftCfgEnable */ +#define BMIPS_BCMCFG_PLLCFG2_CA (1<<3) /* CfgActive */ +#define BMIPS_BCMCFG_PLLCFG2_CF (1<<2) /* RefSoftCfgEnable */ +#define BMIPS_BCMCFG_PLLCFG2_CI (1<<1) /* ISBSoftCfgEnable */ +#define BMIPS_BCMCFG_PLLCFG2_CC (1<<0) /* MIPSSoftCfgEnable */ + +/* + * Broadcom ClkSync Register (22, select 3) + */ +/* SoftClkCfgHigh */ +#define BMIPS_BCMCFG_CLKSYNC_CH_SHIFT 16 +#define BMIPS_BCMCFG_CLKSYNC_CH_MASK 0xFFFF0000 + +/* SoftClkCfgLow */ +#define BMIPS_BCMCFG_CLKSYNC_CL_SHIFT 0 +#define BMIPS_BCMCFG_CLKSYNC_CL_MASK 0x0000FFFF + +/* + * Broadcom ISBxPLLConfig3 Register (22, select 4) + */ + +/* AsyncClkRatio */ +#define BMIPS_BCMCFG_PLLCFG3_AR_SHIFT 23 +#define BMIPS_BCMCFG_PLLCFG3_AR_MASK 0x01800000 + +#define BMIPS_BCMCFG_PLLCFG3_SM (1<<22) /* SyncMode */ + +/* SoftISBxPLLCfg */ +#define BMIPS_BCMCFG_PLLCFG3_IC_SHIFT 0 +#define BMIPS_BCMCFG_PLLCFG3_IC_MASK 0x003FFFFF + +/* + * Broadcom BRCMRstConfig Register (22, select 5) + */ + +#define BMIPS_BCMCFG_RSTCFG_SR (1<<18) /* SSMR */ +#define BMIPS_BCMCFG_RSTCFG_DT (1<<16) /* BHTD */ + +/* RStSt */ +#define BMIPS_BCMCFG_RSTCFG_RS_SHIFT 8 +#define BMIPS_BCMCFG_RSTCFG_RS_MASK 0x00001F00 +#define BMIPS_BCMCFG_RST_OTHER 0x00 +#define BMIPS_BCMCFG_RST_SH 0x01 +#define BMIPS_BCMCFG_RST_SS 0x02 +#define BMIPS_BCMCFG_RST_EJTAG 0x04 +#define BMIPS_BCMCFG_RST_WDOG 0x08 +#define BMIPS_BCMCFG_RST_CRC 0x10 + +#define BMIPS_BCMCFG_RSTCFG_CR (1<<7) /* RStCr */ + +/* WBMD */ +#define BMIPS_BCMCFG_RSTCFG_WD_SHIFT 3 +#define BMIPS_BCMCFG_RSTCFG_WD_MASK 0x00000078 + +#define BMIPS_BCMCFG_RSTCFG_SS (1<<2) /* SSR */ +#define BMIPS_BCMCFG_RSTCFG_SH (1<<1) /* SHR */ +#define BMIPS_BCMCFG_RSTCFG_BR (1<<0) /* BdR */ + +#endif /* _MIPS_BROADCOM_BCM_BMIPS_EXTS_H_ */ Property changes on: head/sys/mips/broadcom/bcm_bmips_exts.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_bmipsreg.h =================================================================== --- head/sys/mips/broadcom/bcm_bmipsreg.h (nonexistent) +++ head/sys/mips/broadcom/bcm_bmipsreg.h (revision 305953) @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _MIPS_BROADCOM_BMIPSREG_H_ +#define _MIPS_BROADCOM_BMIPSREG_H_ + +/* + * Common BMIPS32/BMIPS3300 Registers + */ +#define BCM_BMIPS_CORECTL 0x00 /**< core control */ +#define BCM_BMIPS_CORECTL_FORCE_RST 0x01 /**< force reset */ +#define BCM_BMIPS_CORECTL_NO_FLSH_EXC 0x02 /**< flash exception disable */ +#define BCM_BMIPS_INTR_STATUS 0x20 /**< interrupt status */ +#define BCM_BMIPS_INTR_MASK 0x24 /**< interrupt mask */ +#define BCM_BMIPS_TIMER_INTMASK 0x01 /**< timer interrupt mask */ +#define BCM_BMIPS_TIMER_CTRL 0x28 /**< timer interval (?) */ + +/* + * Broadcom BMIPS32 (BHND_COREID_MIPS) + */ + +#define BCM_BMIPS32_CORECTL BCM_BMIPS_CORECTL +#define BCM_BMIPS32_BIST_STATUS 0x04 /**< built-in self-test status */ +#define BCM_BMIPS32_INTR_STATUS BCM_BMIPS_INTR_STATUS +#define BCM_BMIPS32_INTR_MASK BCM_BMIPS_INTR_MASK +#define BCM_BMIPS32_TIMER_CTRL BCM_BMIPS_TIMER_CTRL + +/* + * Broadcom BMIPS3300+ (BHND_COREID_MIPS33) + */ + +#define BCM_BMIPS33_CORECTL BCM_BMIPS_CORECTL +#define BCM_BMIPS33_BIST_CTRL 0x04 /**< build-in self-test control */ +#define BCM_BMIPS33_BIST_CTRL_DUMP 0x01 /**< BIST dump */ +#define BCM_BMIPS33_BIST_CTRL_DEBUG 0x02 /**< BIST debug */ +#define BCM_BMIPS33_BIST_CTRL_HOLD 0x04 /**< BIST hold */ +#define BCM_BMIPS33_BIST_STATUS 0x08 /**< built-in self-test status */ +#define BCM_BMIPS33_INTR_STATUS BCM_BMIPS_INTR_STATUS +#define BCM_BMIPS33_INTR_MASK BCM_BMIPS_INTR_MASK +#define BCM_BMIPS33_TIMER_CTRL BCM_BMIPS_TIMER_CTRL +#define BCM_BMIPS33_TEST_MUX_SEL 0x30 /**< test multiplexer select (?) */ +#define BCM_BMIPS33_TEST_MUX_EN 0x34 /**< test multiplexer enable (?) */ +#define BCM_BMIPS33_EJTAG_GPIO_EN 0x2C /**< ejtag gpio enable */ + +#endif /* _MIPS_BROADCOM_BMIPSREG_H_ */ Property changes on: head/sys/mips/broadcom/bcm_bmipsreg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_machdep.c =================================================================== --- head/sys/mips/broadcom/bcm_machdep.c (revision 305952) +++ head/sys/mips/broadcom/bcm_machdep.c (revision 305953) @@ -1,534 +1,534 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * Copyright (c) 2016 Michael Zhilin * Copyright (c) 2016 Landon Fuller * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bcm_machdep.h" -#include "bcm_mips_exts.h" +#include "bcm_bmips_exts.h" #ifdef CFE #include #endif #if 0 #define BCM_TRACE(_fmt, ...) printf(_fmt, ##__VA_ARGS__) #else #define BCM_TRACE(_fmt, ...) #endif static int bcm_init_platform_data(struct bcm_platform *bp); static int bcm_find_core(struct bcm_platform *bp, uint16_t vendor, uint16_t device, int unit, struct bhnd_core_info *info, uintptr_t *addr); static int bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls, kobj_ops_t erom_ops, bhnd_erom_t *erom, size_t esize, struct bhnd_chipid *cid); extern int *edata; extern int *end; static struct bcm_platform bcm_platform_data; static bool bcm_platform_data_avail = false; struct bcm_platform * bcm_get_platform(void) { if (!bcm_platform_data_avail) panic("platform data not available"); return (&bcm_platform_data); } static bus_addr_t bcm_get_bus_addr(void) { long maddr; if (resource_long_value("bhnd", 0, "maddr", &maddr) == 0) return ((u_long)maddr); return (BHND_DEFAULT_CHIPC_ADDR); } /** * Search the device enumeration table for a core matching @p vendor, * @p device, and @p unit. * * @param bp Platform state containing a valid EROM parser. * @param vendor The core's required vendor. * @param device The core's required device id. * @param unit The core's required unit number. * @param[out] info If non-NULL, will be populated with the core * info. * @param[out] addr If non-NULL, will be populated with the core's * physical register address. */ static int bcm_find_core(struct bcm_platform *bp, uint16_t vendor, uint16_t device, int unit, struct bhnd_core_info *info, uintptr_t *addr) { struct bhnd_core_match md; bhnd_addr_t b_addr; bhnd_size_t b_size; int error; md = (struct bhnd_core_match) { BHND_MATCH_CORE_VENDOR(vendor), BHND_MATCH_CORE_ID(BHND_COREID_CC), BHND_MATCH_CORE_UNIT(0) }; /* Fetch core info */ error = bhnd_erom_lookup_core_addr(&bp->erom.obj, &md, BHND_PORT_DEVICE, 0, 0, info, &b_addr, &b_size); if (error) return (error); if (addr != NULL && b_addr > UINTPTR_MAX) { BCM_ERR("core address %#jx overflows native address width\n", (uintmax_t)b_addr); return (ERANGE); } if (addr != NULL) *addr = b_addr; return (0); } /** * Probe and attach a bhnd_erom parser instance for the bhnd bus. * * @param[out] erom_cls The probed EROM class. * @param[out] erom_ops The storage to be used when compiling * @p erom_cls. * @param[out] erom The storage to be used when initializing the * static instance of @p erom_cls. * @param esize The total available number of bytes allocated * for @p erom. If this is less than is required * by @p erom_cls ENOMEM will be returned. * @param[out] cid On success, the probed chip identification. */ static int bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls, kobj_ops_t erom_ops, bhnd_erom_t *erom, size_t esize, struct bhnd_chipid *cid) { bhnd_erom_class_t **clsp; bus_space_tag_t bst; bus_space_handle_t bsh; bus_addr_t bus_addr; int error, prio, result; bus_addr = bcm_get_bus_addr(); *erom_cls = NULL; prio = 0; bst = mips_bus_space_generic; bsh = BCM_SOC_BSH(bus_addr, 0); SET_FOREACH(clsp, bhnd_erom_class_set) { struct bhnd_chipid pcid; bhnd_erom_class_t *cls; struct kobj_ops kops; cls = *clsp; /* Compile the class' ops table */ kobj_class_compile_static(cls, &kops); /* Probe the bus address */ result = bhnd_erom_probe_static(cls, bst, bsh, bus_addr, NULL, &pcid); /* Drop pointer to stack allocated ops table */ cls->ops = NULL; /* The parser did not match if an error was returned */ if (result > 0) continue; /* Check for a new highest priority match */ if (*erom_cls == NULL || result > prio) { prio = result; *cid = pcid; *erom_cls = cls; } /* Terminate immediately on BUS_PROBE_SPECIFIC */ if (result == BUS_PROBE_SPECIFIC) break; } /* Valid EROM class probed? */ if (*erom_cls == NULL) { BCM_ERR("no erom parser found for root bus at %#jx\n", (uintmax_t)bus_addr); return (ENOENT); } /* Using the provided storage, recompile the erom class ... */ kobj_class_compile_static(*erom_cls, erom_ops); /* ... and initialize the erom parser instance */ bsh = BCM_SOC_BSH(cid->enum_addr, 0); error = bhnd_erom_init_static(*erom_cls, erom, esize, cid, mips_bus_space_generic, bsh); return (error); } /** * Populate platform configuration data. */ static int bcm_init_platform_data(struct bcm_platform *bp) { bool aob, pmu; int error; /* Fetch CFE console handle (if any). Must be initialized before * any calls to printf/early_putc. */ #ifdef CFE if ((bp->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0) bp->cfe_console = -1; #endif /* Probe and attach device table provider, populating our * chip identification */ error = bcm_erom_probe_and_attach(&bp->erom_impl, &bp->erom_ops, &bp->erom.obj, sizeof(bp->erom), &bp->cid); if (error) { BCM_ERR("error attaching erom parser: %d\n", error); return (error); } /* Fetch chipcommon core info */ error = bcm_find_core(bp, BHND_MFGID_BCM, BHND_COREID_CC, 0, &bp->cc_id, &bp->cc_addr); if (error) { BCM_ERR("error locating chipc core: %d\n", error); return (error); } /* Fetch chipc capability flags */ bp->cc_caps = BCM_SOC_READ_4(bp->cc_addr, CHIPC_CAPABILITIES); bp->cc_caps_ext = 0x0; if (CHIPC_HWREV_HAS_CAP_EXT(bp->cc_id.hwrev)) bp->cc_caps_ext = BCM_CHIPC_READ_4(bp, CHIPC_CAPABILITIES_EXT); /* Fetch PMU info */ pmu = CHIPC_GET_FLAG(bp->cc_caps, CHIPC_CAP_PMU); aob = CHIPC_GET_FLAG(bp->cc_caps_ext, CHIPC_CAP2_AOB); if (pmu && aob) { /* PMU block mapped to a PMU core on the Always-on-Bus (aob) */ error = bcm_find_core(bp, BHND_MFGID_BCM, BHND_COREID_PMU, 0, &bp->pmu_id, &bp->pmu_addr); if (error) { BCM_ERR("error locating pmu core: %d\n", error); return (error); } } else if (pmu) { /* PMU block mapped to chipc */ bp->pmu_addr = bp->cc_addr; bp->pmu_id = bp->cc_id; } else { /* No PMU */ bp->pmu_addr = 0x0; memset(&bp->pmu_id, 0, sizeof(bp->pmu_id)); } /* Initialize PMU query state */ if (pmu) { error = bhnd_pmu_query_init(&bp->pmu, NULL, bp->cid, &bcm_pmu_soc_io, bp); if (error) { BCM_ERR("bhnd_pmu_query_init() failed: %d\n", error); return (error); } } bcm_platform_data_avail = true; return (0); } void platform_cpu_init() { /* Nothing special */ } static void mips_init(void) { int i, j; printf("entry: mips_init()\n"); #ifdef CFE /* * Query DRAM memory map from CFE. */ physmem = 0; for (i = 0; i < 10; i += 2) { int result; uint64_t addr, len, type; result = cfe_enummem(i / 2, 0, &addr, &len, &type); if (result < 0) { BCM_TRACE("There is no phys memory for: %d\n", i); phys_avail[i] = phys_avail[i + 1] = 0; break; } if (type != CFE_MI_AVAILABLE) { BCM_TRACE("phys memory is not available: %d\n", i); continue; } phys_avail[i] = addr; if (i == 0 && addr == 0) { /* * If this is the first physical memory segment probed * from CFE, omit the region at the start of physical * memory where the kernel has been loaded. */ phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); } BCM_TRACE("phys memory is available for: %d\n", i); BCM_TRACE(" => addr = %jx\n", addr); BCM_TRACE(" => len = %jd\n", len); phys_avail[i + 1] = addr + len; physmem += len; } BCM_TRACE("Total phys memory is : %ld\n", physmem); realmem = btoc(physmem); #endif for (j = 0; j < i; j++) dump_avail[j] = phys_avail[j]; physmem = realmem; init_param1(); init_param2(physmem); mips_cpu_init(); pmap_bootstrap(); mips_proc0_init(); mutex_init(); kdb_init(); #ifdef KDB if (boothowto & RB_KDB) kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); #endif } void platform_reset(void) { struct bcm_platform *bp; bool bcm4785war; printf("bcm::platform_reset()\n"); intr_disable(); #ifdef CFE /* Fall back on CFE if reset requested during platform * data initialization */ if (!bcm_platform_data_avail) { cfe_exit(0, 0); while (1); } #endif bp = bcm_get_platform(); bcm4785war = false; /* Handle BCM4785-specific behavior */ if (bp->cid.chip_id == BHND_CHIPID_BCM4785) { bcm4785war = true; /* Switch to async mode */ - bcm_mips_wr_pllcfg3(MIPS_BCMCFG_PLLCFG3_SM); + bcm_bmips_wr_pllcfg3(BMIPS_BCMCFG_PLLCFG3_SM); } /* Set watchdog (PMU or ChipCommon) */ if (bp->pmu_addr != 0x0) { BCM_PMU_WRITE_4(bp, BHND_PMU_WATCHDOG, 1); } else BCM_CHIPC_WRITE_4(bp, CHIPC_WATCHDOG, 1); /* BCM4785 */ if (bcm4785war) { mips_sync(); __asm __volatile("wait"); } while (1); } void platform_start(__register_t a0, __register_t a1, __register_t a2, __register_t a3) { vm_offset_t kernend; uint64_t platform_counter_freq; int error; /* clear the BSS and SBSS segments */ kernend = (vm_offset_t)&end; memset(&edata, 0, kernend - (vm_offset_t)(&edata)); mips_postboot_fixup(); /* Initialize pcpu stuff */ mips_pcpu0_init(); #ifdef CFE /* * Initialize CFE firmware trampolines. This must be done * before any CFE APIs are called, including writing * to the CFE console. * * CFE passes the following values in registers: * a0: firmware handle * a2: firmware entry point * a3: entry point seal */ if (a3 == CFE_EPTSEAL) cfe_init(a0, a2); #endif /* Init BCM platform data */ if ((error = bcm_init_platform_data(&bcm_platform_data))) panic("bcm_init_platform_data() failed: %d", error); platform_counter_freq = bcm_get_cpufreq(bcm_get_platform()); /* CP0 ticks every two cycles */ mips_timer_early_init(platform_counter_freq / 2); cninit(); mips_init(); mips_timer_init_params(platform_counter_freq, 1); } /* * CFE-based EARLY_PRINTF support. To use, add the following to the kernel * config: * option EARLY_PRINTF * option CFE * device cfe */ #if defined(EARLY_PRINTF) && defined(CFE) static void bcm_cfe_eputc(int c) { unsigned char ch; int handle; ch = (unsigned char) c; /* bcm_get_platform() cannot be used here, as we may be called * from bcm_init_platform_data(). */ if ((handle = bcm_platform_data.cfe_console) < 0) return; if (ch == '\n') early_putc('\r'); while ((cfe_write(handle, &ch, 1)) == 0) continue; } early_putc_t *early_putc = bcm_cfe_eputc; #endif /* EARLY_PRINTF */ Index: head/sys/mips/broadcom/bcm_mips74k.c =================================================================== --- head/sys/mips/broadcom/bcm_mips74k.c (nonexistent) +++ head/sys/mips/broadcom/bcm_mips74k.c (revision 305953) @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "bcm_mips74kreg.h" + +/* + * Broadcom MIPS74K Core + * + * These cores are only found on bcma(4) chipsets, allowing + * us to assume the availability of bcma interrupt registers. + */ + +static const struct bhnd_device bcm_mips74k_devs[] = { + BHND_DEVICE(MIPS, MIPS74K, NULL, NULL, BHND_DF_SOC), + BHND_DEVICE_END +}; + +struct bcm_mips74k_softc { + device_t dev; + struct resource *mem_res; + int mem_rid; +}; + +static int +bcm_mips74k_probe(device_t dev) +{ + const struct bhnd_device *id; + + id = bhnd_device_lookup(dev, bcm_mips74k_devs, + sizeof(bcm_mips74k_devs[0])); + if (id == NULL) + return (ENXIO); + + bhnd_set_default_core_desc(dev); + return (BUS_PROBE_DEFAULT); +} + +static int +bcm_mips74k_attach(device_t dev) +{ + struct bcm_mips74k_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Allocate bus resources */ + sc->mem_rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, + RF_ACTIVE); + if (sc->mem_res == NULL) + return (ENXIO); + + /* Route MIPS timer to IRQ5 */ + bus_write_4(sc->mem_res, BCM_MIPS74K_INTR5_SEL, + (1<mem_rid, sc->mem_res); + + return (0); +} + +static device_method_t bcm_mips74k_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bcm_mips74k_probe), + DEVMETHOD(device_attach, bcm_mips74k_attach), + DEVMETHOD(device_detach, bcm_mips74k_detach), + + DEVMETHOD_END +}; + +static devclass_t bcm_mips_devclass; + +DEFINE_CLASS_0(bcm_mips, bcm_mips74k_driver, bcm_mips74k_methods, sizeof(struct bcm_mips74k_softc)); +EARLY_DRIVER_MODULE(bcm_mips74k, bhnd, bcm_mips74k_driver, bcm_mips_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); +MODULE_VERSION(bcm_mips74k, 1); +MODULE_DEPEND(bcm_mips74k, bhnd, 1, 1, 1); Property changes on: head/sys/mips/broadcom/bcm_mips74k.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/mips/broadcom/bcm_mips74kreg.h =================================================================== --- head/sys/mips/broadcom/bcm_mips74kreg.h (nonexistent) +++ head/sys/mips/broadcom/bcm_mips74kreg.h (revision 305953) @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _MIPS_BROADCOM_MIPS74KREG_H_ +#define _MIPS_BROADCOM_MIPS74KREG_H_ + +#define BCM_MIPS74K_CORECTL 0x00 /**< core control */ +#define BCM_MIPS74K_EXCBASE 0x04 /**< exception base */ + +#define BCM_MIPS74K_BIST_STATUS 0x0C /**< built-in self-test status */ +#define BCM_MIPS74K_INTR_STATUS 0x10 /**< interrupt status */ + +/* INTR(0-5)_MASK map bcma(4) OOB interrupt bus lines to MIPS hardware + * interrupts. */ +#define BCM_MIPS74K_INTR0_SEL 0x14 /**< IRQ0 OOBSEL mask */ +#define BCM_MIPS74K_INTR1_SEL 0x18 /**< IRQ1 OOBSEL mask */ +#define BCM_MIPS74K_INTR2_SEL 0x1C /**< IRQ2 OOBSEL mask */ +#define BCM_MIPS74K_INTR3_SEL 0x20 /**< IRQ3 OOBSEL mask */ +#define BCM_MIPS74K_INTR4_SEL 0x24 /**< IRQ4 OOBSEL mask */ +#define BCM_MIPS74K_INTR5_SEL 0x28 /**< IRQ5 OOBSEL mask */ + +#define BCM_MIPS74K_INTR_SEL(_intr) \ + (BCM_MIPS74K_INTR0_SEL + ((_intr) * 4)) + +#define BCM_MIPS74K_NMI_MASK 0x2C /**< nmi mask */ + +#define BCM_MIPS74K_GPIO_SEL 0x40 /**< gpio select */ +#define BCM_MIPS74K_GPIO_OUT 0x44 /**< gpio output enable */ +#define BCM_MIPS74K_GPIO_EN 0x48 /**< gpio enable */ + + +#define BCM_MIPS74K_TIMER_IVEC 31 /**< MIPS timer OOBSEL value */ + +#endif /* _MIPS_BROADCOM_MIPS74KREG_H_ */ Property changes on: head/sys/mips/broadcom/bcm_mips74kreg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/mips/broadcom/files.broadcom =================================================================== --- head/sys/mips/broadcom/files.broadcom (revision 305952) +++ head/sys/mips/broadcom/files.broadcom (revision 305953) @@ -1,26 +1,27 @@ # $FreeBSD$ # TODO: Add attachment elsewhere in the tree # for USB 1.1 OHCI, Ethernet and IPSEC cores # which are believed to be devices we have drivers for # which just need to be tweaked for attachment to an BHND system bus. mips/broadcom/bcm_machdep.c standard +mips/broadcom/bcm_bmips.c optional siba_nexus siba +mips/broadcom/bcm_mips74k.c optional bcma_nexus bcma mips/broadcom/bcm_pmu.c standard mips/mips/tick.c standard mips/mips/mips_pic.c standard kern/subr_intr.c standard kern/pic_if.m standard kern/msi_if.m optional intrng mips/broadcom/uart_cpu_chipc.c optional uart mips/broadcom/uart_bus_chipc.c optional uart -mips/broadcom/bcm_mipscore.c standard # TODO: Replace with BCM47xx/57xx/etc-aware geom_map geom/geom_flashmap.c standard # USB bits dev/bhnd/cores/usb/bhnd_usb.c optional usb dev/bhnd/cores/usb/bhnd_ehci.c optional ehci -dev/bhnd/cores/usb/bhnd_ohci.c optional ohci \ No newline at end of file +dev/bhnd/cores/usb/bhnd_ohci.c optional ohci