Index: head/sys/dev/siba/siba_bwn.c =================================================================== --- head/sys/dev/siba/siba_bwn.c (revision 299408) +++ head/sys/dev/siba/siba_bwn.c (revision 299409) @@ -1,441 +1,441 @@ /*- * Copyright (c) 2009-2010 Weongyo Jeong * 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$"); /* * Sonics Silicon Backplane front-end for bwn(4). */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * PCI glue. */ struct siba_bwn_softc { /* Child driver using MSI. */ device_t ssc_msi_child; struct siba_softc ssc_siba; }; #define BS_BAR 0x10 #define PCI_VENDOR_BROADCOM 0x14e4 #define N(a) (sizeof(a) / sizeof(a[0])) static const struct siba_dev { uint16_t vid; uint16_t did; const char *desc; } siba_devices[] = { { PCI_VENDOR_BROADCOM, 0x4301, "Broadcom BCM4301 802.11b Wireless" }, { PCI_VENDOR_BROADCOM, 0x4306, "Unknown" }, { PCI_VENDOR_BROADCOM, 0x4307, "Broadcom BCM4307 802.11b Wireless" }, { PCI_VENDOR_BROADCOM, 0x4311, "Broadcom BCM4311 802.11b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4312, "Broadcom BCM4312 802.11a/b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4315, "Broadcom BCM4312 802.11b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4318, "Broadcom BCM4318 802.11b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4319, "Broadcom BCM4318 802.11a/b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4320, "Broadcom BCM4306 802.11b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4321, "Broadcom BCM4306 802.11a Wireless" }, { PCI_VENDOR_BROADCOM, 0x4324, "Broadcom BCM4309 802.11a/b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4325, "Broadcom BCM4306 802.11b/g Wireless" }, - { PCI_VENDOR_BROADCOM, 0x4328, "Unknown" }, + { PCI_VENDOR_BROADCOM, 0x4328, "Broadcom BCM4321 802.11a/b/g Wireless" }, { PCI_VENDOR_BROADCOM, 0x4329, "Unknown" }, { PCI_VENDOR_BROADCOM, 0x432b, "Unknown" } }; int siba_core_attach(struct siba_softc *); int siba_core_detach(struct siba_softc *); int siba_core_suspend(struct siba_softc *); int siba_core_resume(struct siba_softc *); static int siba_bwn_probe(device_t dev) { int i; uint16_t did, vid; did = pci_get_device(dev); vid = pci_get_vendor(dev); for (i = 0; i < N(siba_devices); i++) { if (siba_devices[i].did == did && siba_devices[i].vid == vid) { device_set_desc(dev, siba_devices[i].desc); return (BUS_PROBE_DEFAULT); } } return (ENXIO); } static int siba_bwn_attach(device_t dev) { struct siba_bwn_softc *ssc = device_get_softc(dev); struct siba_softc *siba = &ssc->ssc_siba; siba->siba_dev = dev; siba->siba_type = SIBA_TYPE_PCI; /* * Enable bus mastering. */ pci_enable_busmaster(dev); /* * Setup memory-mapping of PCI registers. */ siba->siba_mem_rid = SIBA_PCIR_BAR; siba->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &siba->siba_mem_rid, RF_ACTIVE); if (siba->siba_mem_res == NULL) { device_printf(dev, "cannot map register space\n"); return (ENXIO); } siba->siba_mem_bt = rman_get_bustag(siba->siba_mem_res); siba->siba_mem_bh = rman_get_bushandle(siba->siba_mem_res); /* Get more PCI information */ siba->siba_pci_did = pci_get_device(dev); siba->siba_pci_vid = pci_get_vendor(dev); siba->siba_pci_subvid = pci_get_subvendor(dev); siba->siba_pci_subdid = pci_get_subdevice(dev); siba->siba_pci_revid = pci_get_revid(dev); return (siba_core_attach(siba)); } static int siba_bwn_detach(device_t dev) { struct siba_bwn_softc *ssc = device_get_softc(dev); struct siba_softc *siba = &ssc->ssc_siba; /* check if device was removed */ siba->siba_invalid = !bus_child_present(dev); pci_disable_busmaster(dev); bus_generic_detach(dev); siba_core_detach(siba); bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res); return (0); } static int siba_bwn_shutdown(device_t dev) { device_t *devlistp; int devcnt, error = 0, i; error = device_get_children(dev, &devlistp, &devcnt); if (error != 0) return (error); for (i = 0 ; i < devcnt ; i++) device_shutdown(devlistp[i]); free(devlistp, M_TEMP); return (0); } static int siba_bwn_suspend(device_t dev) { struct siba_bwn_softc *ssc = device_get_softc(dev); struct siba_softc *siba = &ssc->ssc_siba; device_t *devlistp; int devcnt, error = 0, i, j; error = device_get_children(dev, &devlistp, &devcnt); if (error != 0) return (error); for (i = 0 ; i < devcnt ; i++) { error = DEVICE_SUSPEND(devlistp[i]); if (error) { for (j = 0; j < i; j++) DEVICE_RESUME(devlistp[j]); free(devlistp, M_TEMP); return (error); } } free(devlistp, M_TEMP); return (siba_core_suspend(siba)); } static int siba_bwn_resume(device_t dev) { struct siba_bwn_softc *ssc = device_get_softc(dev); struct siba_softc *siba = &ssc->ssc_siba; device_t *devlistp; int devcnt, error = 0, i; error = siba_core_resume(siba); if (error != 0) return (error); error = device_get_children(dev, &devlistp, &devcnt); if (error != 0) return (error); for (i = 0 ; i < devcnt ; i++) DEVICE_RESUME(devlistp[i]); free(devlistp, M_TEMP); return (0); } /* proxying to the parent */ static struct resource * siba_bwn_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) { return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, type, rid, start, end, count, flags)); } /* proxying to the parent */ static int siba_bwn_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type, rid, r)); } /* proxying to the parent */ static int siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, void **cookiep) { return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, filter, intr, arg, cookiep)); } /* proxying to the parent */ static int siba_bwn_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); } static int siba_bwn_find_cap(device_t dev, device_t child, int capability, int *capreg) { return (pci_find_cap(dev, capability, capreg)); } static int siba_bwn_find_extcap(device_t dev, device_t child, int capability, int *capreg) { return (pci_find_extcap(dev, capability, capreg)); } static int siba_bwn_find_htcap(device_t dev, device_t child, int capability, int *capreg) { return (pci_find_htcap(dev, capability, capreg)); } static int siba_bwn_alloc_msi(device_t dev, device_t child, int *count) { struct siba_bwn_softc *ssc; int error; ssc = device_get_softc(dev); if (ssc->ssc_msi_child != NULL) return (EBUSY); error = pci_alloc_msi(dev, count); if (error == 0) ssc->ssc_msi_child = child; return (error); } static int siba_bwn_release_msi(device_t dev, device_t child) { struct siba_bwn_softc *ssc; int error; ssc = device_get_softc(dev); if (ssc->ssc_msi_child != child) return (ENXIO); error = pci_release_msi(dev); if (error == 0) ssc->ssc_msi_child = NULL; return (error); } static int siba_bwn_msi_count(device_t dev, device_t child) { return (pci_msi_count(dev)); } static int siba_bwn_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct siba_dev_softc *sd; struct siba_softc *siba; sd = device_get_ivars(child); siba = sd->sd_bus; switch (which) { case SIBA_IVAR_VENDOR: *result = sd->sd_id.sd_vendor; break; case SIBA_IVAR_DEVICE: *result = sd->sd_id.sd_device; break; case SIBA_IVAR_REVID: *result = sd->sd_id.sd_rev; break; case SIBA_IVAR_PCI_VENDOR: *result = siba->siba_pci_vid; break; case SIBA_IVAR_PCI_DEVICE: *result = siba->siba_pci_did; break; case SIBA_IVAR_PCI_SUBVENDOR: *result = siba->siba_pci_subvid; break; case SIBA_IVAR_PCI_SUBDEVICE: *result = siba->siba_pci_subdid; break; case SIBA_IVAR_PCI_REVID: *result = siba->siba_pci_revid; break; case SIBA_IVAR_CHIPID: *result = siba->siba_chipid; break; case SIBA_IVAR_CHIPREV: *result = siba->siba_chiprev; break; case SIBA_IVAR_CHIPPKG: *result = siba->siba_chippkg; break; case SIBA_IVAR_TYPE: *result = siba->siba_type; break; case SIBA_IVAR_CC_PMUFREQ: *result = siba->siba_cc.scc_pmu.freq; break; case SIBA_IVAR_CC_CAPS: *result = siba->siba_cc.scc_caps; break; case SIBA_IVAR_CC_POWERDELAY: *result = siba->siba_cc.scc_powerup_delay; break; case SIBA_IVAR_PCICORE_REVID: *result = siba->siba_pci.spc_dev->sd_id.sd_rev; break; default: return (ENOENT); } return (0); } static device_method_t siba_bwn_methods[] = { /* Device interface */ DEVMETHOD(device_probe, siba_bwn_probe), DEVMETHOD(device_attach, siba_bwn_attach), DEVMETHOD(device_detach, siba_bwn_detach), DEVMETHOD(device_shutdown, siba_bwn_shutdown), DEVMETHOD(device_suspend, siba_bwn_suspend), DEVMETHOD(device_resume, siba_bwn_resume), /* Bus interface */ DEVMETHOD(bus_alloc_resource, siba_bwn_alloc_resource), DEVMETHOD(bus_release_resource, siba_bwn_release_resource), DEVMETHOD(bus_read_ivar, siba_bwn_read_ivar), DEVMETHOD(bus_setup_intr, siba_bwn_setup_intr), DEVMETHOD(bus_teardown_intr, siba_bwn_teardown_intr), /* PCI interface */ DEVMETHOD(pci_find_cap, siba_bwn_find_cap), DEVMETHOD(pci_find_extcap, siba_bwn_find_extcap), DEVMETHOD(pci_find_htcap, siba_bwn_find_htcap), DEVMETHOD(pci_alloc_msi, siba_bwn_alloc_msi), DEVMETHOD(pci_release_msi, siba_bwn_release_msi), DEVMETHOD(pci_msi_count, siba_bwn_msi_count), DEVMETHOD_END }; static driver_t siba_bwn_driver = { "siba_bwn", siba_bwn_methods, sizeof(struct siba_bwn_softc) }; static devclass_t siba_bwn_devclass; DRIVER_MODULE(siba_bwn, pci, siba_bwn_driver, siba_bwn_devclass, 0, 0); MODULE_VERSION(siba_bwn, 1); Index: head/sys/dev/siba/siba_core.c =================================================================== --- head/sys/dev/siba/siba_core.c (revision 299408) +++ head/sys/dev/siba/siba_core.c (revision 299409) @@ -1,2630 +1,2722 @@ /*- * Copyright (c) 2009-2010 Weongyo Jeong * 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$"); /* * the Sonics Silicon Backplane driver. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SIBA_DEBUG enum { SIBA_DEBUG_SCAN = 0x00000001, /* scan */ SIBA_DEBUG_PMU = 0x00000002, /* PMU */ SIBA_DEBUG_PLL = 0x00000004, /* PLL */ SIBA_DEBUG_SWITCHCORE = 0x00000008, /* switching core */ SIBA_DEBUG_SPROM = 0x00000010, /* SPROM */ SIBA_DEBUG_CORE = 0x00000020, /* handling cores */ SIBA_DEBUG_ANY = 0xffffffff }; #define DPRINTF(siba, m, fmt, ...) do { \ if (siba->siba_debug & (m)) \ printf(fmt, __VA_ARGS__); \ } while (0) #else #define DPRINTF(siba, m, fmt, ...) do { (void) siba; } while (0) #endif #define N(a) (sizeof(a) / sizeof(a[0])) static void siba_pci_gpio(struct siba_softc *, uint32_t, int); static void siba_scan(struct siba_softc *); static int siba_switchcore(struct siba_softc *, uint8_t); static int siba_pci_switchcore_sub(struct siba_softc *, uint8_t); static uint32_t siba_scan_read_4(struct siba_softc *, uint8_t, uint16_t); static uint16_t siba_dev2chipid(struct siba_softc *); static uint16_t siba_pci_read_2(struct siba_dev_softc *, uint16_t); static uint32_t siba_pci_read_4(struct siba_dev_softc *, uint16_t); static void siba_pci_write_2(struct siba_dev_softc *, uint16_t, uint16_t); static void siba_pci_write_4(struct siba_dev_softc *, uint16_t, uint32_t); static void siba_cc_clock(struct siba_cc *, enum siba_clock); static void siba_cc_pmu_init(struct siba_cc *); static void siba_cc_power_init(struct siba_cc *); static void siba_cc_powerup_delay(struct siba_cc *); static int siba_cc_clockfreq(struct siba_cc *, int); static void siba_cc_pmu1_pll0_init(struct siba_cc *, uint32_t); static void siba_cc_pmu0_pll0_init(struct siba_cc *, uint32_t); static enum siba_clksrc siba_cc_clksrc(struct siba_cc *); static const struct siba_cc_pmu1_plltab *siba_cc_pmu1_plltab_find(uint32_t); static uint32_t siba_cc_pll_read(struct siba_cc *, uint32_t); static void siba_cc_pll_write(struct siba_cc *, uint32_t, uint32_t); static const struct siba_cc_pmu0_plltab * siba_cc_pmu0_plltab_findentry(uint32_t); static int siba_pci_sprom(struct siba_softc *, struct siba_sprom *); static int siba_sprom_read(struct siba_softc *, uint16_t *, uint16_t); static int sprom_check_crc(const uint16_t *, size_t); static uint8_t siba_crc8(uint8_t, uint8_t); static void siba_sprom_r123(struct siba_sprom *, const uint16_t *); static void siba_sprom_r45(struct siba_sprom *, const uint16_t *); static void siba_sprom_r8(struct siba_sprom *, const uint16_t *); static int8_t siba_sprom_r123_antgain(uint8_t, const uint16_t *, uint16_t, uint16_t); static uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *); static uint32_t siba_pcicore_read_4(struct siba_pci *, uint16_t); static void siba_pcicore_write_4(struct siba_pci *, uint16_t, uint32_t); static uint32_t siba_pcie_read(struct siba_pci *, uint32_t); static void siba_pcie_write(struct siba_pci *, uint32_t, uint32_t); static void siba_pcie_mdio_write(struct siba_pci *, uint8_t, uint8_t, uint16_t); static void siba_pci_read_multi_1(struct siba_dev_softc *, void *, size_t, uint16_t); static void siba_pci_read_multi_2(struct siba_dev_softc *, void *, size_t, uint16_t); static void siba_pci_read_multi_4(struct siba_dev_softc *, void *, size_t, uint16_t); static void siba_pci_write_multi_1(struct siba_dev_softc *, const void *, size_t, uint16_t); static void siba_pci_write_multi_2(struct siba_dev_softc *, const void *, size_t, uint16_t); static void siba_pci_write_multi_4(struct siba_dev_softc *, const void *, size_t, uint16_t); static const char *siba_core_name(uint16_t); static void siba_pcicore_init(struct siba_pci *); static uint32_t siba_read_4_sub(struct siba_dev_softc *, uint16_t); static void siba_write_4_sub(struct siba_dev_softc *, uint16_t, uint32_t); static void siba_powerup_sub(struct siba_softc *, int); static int siba_powerdown_sub(struct siba_softc *); static int siba_dev_isup_sub(struct siba_dev_softc *); static void siba_dev_up_sub(struct siba_dev_softc *, uint32_t); static void siba_dev_down_sub(struct siba_dev_softc *, uint32_t); int siba_core_attach(struct siba_softc *); int siba_core_detach(struct siba_softc *); int siba_core_suspend(struct siba_softc *); int siba_core_resume(struct siba_softc *); uint8_t siba_getncores(device_t, uint16_t); static const struct siba_bus_ops siba_pci_ops = { .read_2 = siba_pci_read_2, .read_4 = siba_pci_read_4, .write_2 = siba_pci_write_2, .write_4 = siba_pci_write_4, .read_multi_1 = siba_pci_read_multi_1, .read_multi_2 = siba_pci_read_multi_2, .read_multi_4 = siba_pci_read_multi_4, .write_multi_1 = siba_pci_write_multi_1, .write_multi_2 = siba_pci_write_multi_2, .write_multi_4 = siba_pci_write_multi_4, }; static const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] = SIBA_CC_PMU_4325_RES_UPDOWN; static const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] = SIBA_CC_PMU_4325_RES_DEPEND; static const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] = SIBA_CC_PMU_4328_RES_UPDOWN; static const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] = SIBA_CC_PMU_4328_RES_DEPEND; static const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] = SIBA_CC_PMU0_PLLTAB_ENTRY; static const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] = SIBA_CC_PMU1_PLLTAB_ENTRY; int siba_core_attach(struct siba_softc *siba) { struct siba_cc *scc; int error; KASSERT(siba->siba_type == SIBA_TYPE_PCI, ("unsupported BUS type (%#x)", siba->siba_type)); siba->siba_ops = &siba_pci_ops; siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1); siba_scan(siba); /* XXX init PCI or PCMCIA host devices */ siba_powerup_sub(siba, 0); /* init ChipCommon */ scc = &siba->siba_cc; if (scc->scc_dev != NULL) { siba_cc_pmu_init(scc); siba_cc_power_init(scc); siba_cc_clock(scc, SIBA_CLOCK_FAST); siba_cc_powerup_delay(scc); } error = siba_pci_sprom(siba, &siba->siba_sprom); if (error) { siba_powerdown_sub(siba); return (error); } siba_pcicore_init(&siba->siba_pci); siba_powerdown_sub(siba); return (bus_generic_attach(siba->siba_dev)); } int siba_core_detach(struct siba_softc *siba) { /* detach & delete all children */ device_delete_children(siba->siba_dev); return (0); } static void siba_pci_gpio(struct siba_softc *siba, uint32_t what, int on) { uint32_t in, out; uint16_t status; if (siba->siba_type != SIBA_TYPE_PCI) return; out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4); if (on == 0) { if (what & SIBA_GPIO_PLL) out |= SIBA_GPIO_PLL; if (what & SIBA_GPIO_CRYSTAL) out &= ~SIBA_GPIO_CRYSTAL; pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev, SIBA_GPIO_OUT_EN, 4) | what, 4); return; } in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4); if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) { if (what & SIBA_GPIO_CRYSTAL) { out |= SIBA_GPIO_CRYSTAL; if (what & SIBA_GPIO_PLL) out |= SIBA_GPIO_PLL; pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev, SIBA_GPIO_OUT_EN, 4) | what, 4); DELAY(1000); } if (what & SIBA_GPIO_PLL) { out &= ~SIBA_GPIO_PLL; pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); DELAY(5000); } } status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2); status &= ~PCIM_STATUS_STABORT; pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2); } static void siba_scan(struct siba_softc *siba) { struct siba_dev_softc *sd; uint32_t idhi, tmp; device_t child; int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0, n_pci = 0; KASSERT(siba->siba_type == SIBA_TYPE_PCI, ("unsupported BUS type (%#x)", siba->siba_type)); siba->siba_ndevs = 0; error = siba_switchcore(siba, 0); /* need the first core */ if (error) return; idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH); if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) { tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID); siba->siba_chipid = SIBA_CC_ID(tmp); siba->siba_chiprev = SIBA_CC_REV(tmp); siba->siba_chippkg = SIBA_CC_PKG(tmp); if (SIBA_IDHIGH_REV(idhi) >= 4) siba->siba_ndevs = SIBA_CC_NCORES(tmp); siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0, SIBA_CC_CAPS); } else { if (siba->siba_type == SIBA_TYPE_PCI) { siba->siba_chipid = siba_dev2chipid(siba); siba->siba_chiprev = pci_read_config(siba->siba_dev, PCIR_REVID, 2); siba->siba_chippkg = 0; } else { siba->siba_chipid = 0x4710; siba->siba_chiprev = 0; siba->siba_chippkg = 0; } } if (siba->siba_ndevs == 0) siba->siba_ndevs = siba_getncores(siba->siba_dev, siba->siba_chipid); if (siba->siba_ndevs > SIBA_MAX_CORES) { device_printf(siba->siba_dev, "too many siba cores (max %d %d)\n", SIBA_MAX_CORES, siba->siba_ndevs); return; } /* looking basic information about each cores/devices */ for (i = 0; i < siba->siba_ndevs; i++) { error = siba_switchcore(siba, i); if (error) return; sd = &(siba->siba_devs[dev_i]); idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH); sd->sd_bus = siba; sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi); sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi); sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi); sd->sd_ops = siba->siba_ops; sd->sd_coreidx = i; DPRINTF(siba, SIBA_DEBUG_SCAN, "core %d (%s) found (cc %#xrev %#x vendor %#x)\n", i, siba_core_name(sd->sd_id.sd_device), sd->sd_id.sd_device, sd->sd_id.sd_rev, sd->sd_id.vendor); switch (sd->sd_id.sd_device) { case SIBA_DEVID_CHIPCOMMON: n_cc++; if (n_cc > 1) { device_printf(siba->siba_dev, "warn: multiple ChipCommon\n"); break; } siba->siba_cc.scc_dev = sd; break; case SIBA_DEVID_80211: n_80211++; if (n_80211 > 1) { device_printf(siba->siba_dev, "warn: multiple 802.11 core\n"); continue; } break; case SIBA_DEVID_PCI: case SIBA_DEVID_PCIE: n_pci++; error = pci_find_cap(siba->siba_dev, PCIY_EXPRESS, &base); is_pcie = (error == 0) ? 1 : 0; if (n_pci > 1) { device_printf(siba->siba_dev, "warn: multiple PCI(E) cores\n"); break; } if (sd->sd_id.sd_device == SIBA_DEVID_PCI && is_pcie == 1) continue; if (sd->sd_id.sd_device == SIBA_DEVID_PCIE && is_pcie == 0) continue; siba->siba_pci.spc_dev = sd; break; case SIBA_DEVID_MODEM: case SIBA_DEVID_PCMCIA: break; default: device_printf(siba->siba_dev, "unsupported coreid (%s)\n", siba_core_name(sd->sd_id.sd_device)); break; } dev_i++; child = device_add_child(siba->siba_dev, NULL, -1); if (child == NULL) { device_printf(siba->siba_dev, "child attach failed\n"); continue; } device_set_ivars(child, sd); } siba->siba_ndevs = dev_i; } static int siba_switchcore(struct siba_softc *siba, uint8_t idx) { switch (siba->siba_type) { case SIBA_TYPE_PCI: return (siba_pci_switchcore_sub(siba, idx)); default: KASSERT(0 == 1, ("%s: unsupported bustype %#x", __func__, siba->siba_type)); } return (0); } static int siba_pci_switchcore_sub(struct siba_softc *siba, uint8_t idx) { #define RETRY_MAX 50 int i; uint32_t dir; dir = SIBA_REGWIN(idx); for (i = 0; i < RETRY_MAX; i++) { pci_write_config(siba->siba_dev, SIBA_BAR0, dir, 4); if (pci_read_config(siba->siba_dev, SIBA_BAR0, 4) == dir) return (0); DELAY(10); } return (ENODEV); #undef RETRY_MAX } static int siba_pci_switchcore(struct siba_softc *siba, struct siba_dev_softc *sd) { int error; DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "Switching to %s core, index %d\n", siba_core_name(sd->sd_id.sd_device), sd->sd_coreidx); error = siba_pci_switchcore_sub(siba, sd->sd_coreidx); if (error == 0) siba->siba_curdev = sd; return (error); } static uint32_t siba_scan_read_4(struct siba_softc *siba, uint8_t coreidx, uint16_t offset) { (void)coreidx; KASSERT(siba->siba_type == SIBA_TYPE_PCI, ("unsupported BUS type (%#x)", siba->siba_type)); return (SIBA_READ_4(siba, offset)); } static uint16_t siba_dev2chipid(struct siba_softc *siba) { uint16_t chipid = 0; switch (siba->siba_pci_did) { case 0x4301: chipid = 0x4301; break; case 0x4305: case 0x4306: case 0x4307: chipid = 0x4307; break; case 0x4403: chipid = 0x4402; break; case 0x4610: case 0x4611: case 0x4612: case 0x4613: case 0x4614: case 0x4615: chipid = 0x4610; break; case 0x4710: case 0x4711: case 0x4712: case 0x4713: case 0x4714: case 0x4715: chipid = 0x4710; break; case 0x4320: case 0x4321: case 0x4322: case 0x4323: case 0x4324: case 0x4325: chipid = 0x4309; break; case PCI_DEVICE_ID_BCM4401: case PCI_DEVICE_ID_BCM4401B0: case PCI_DEVICE_ID_BCM4401B1: chipid = 0x4401; break; default: device_printf(siba->siba_dev, "unknown PCI did (%d)\n", siba->siba_pci_did); } return (chipid); } /* * Earlier ChipCommon revisions have hardcoded number of cores * present dependent on the ChipCommon ID. */ uint8_t siba_getncores(device_t dev, uint16_t chipid) { switch (chipid) { case 0x4401: case 0x4402: return (3); case 0x4301: case 0x4307: return (5); case 0x4306: return (6); case SIBA_CCID_SENTRY5: return (7); case 0x4310: return (8); case SIBA_CCID_BCM4710: case 0x4610: case SIBA_CCID_BCM4704: return (9); default: device_printf(dev, "unknown the chipset ID %#x\n", chipid); } return (1); } static const char * siba_core_name(uint16_t coreid) { switch (coreid) { case SIBA_DEVID_CHIPCOMMON: return ("ChipCommon"); case SIBA_DEVID_ILINE20: return ("ILine 20"); case SIBA_DEVID_SDRAM: return ("SDRAM"); case SIBA_DEVID_PCI: return ("PCI"); case SIBA_DEVID_MIPS: return ("MIPS"); case SIBA_DEVID_ETHERNET: return ("Fast Ethernet"); case SIBA_DEVID_MODEM: return ("Modem"); case SIBA_DEVID_USB11_HOSTDEV: return ("USB 1.1 Hostdev"); case SIBA_DEVID_ADSL: return ("ADSL"); case SIBA_DEVID_ILINE100: return ("ILine 100"); case SIBA_DEVID_IPSEC: return ("IPSEC"); case SIBA_DEVID_PCMCIA: return ("PCMCIA"); case SIBA_DEVID_INTERNAL_MEM: return ("Internal Memory"); case SIBA_DEVID_SDRAMDDR: return ("MEMC SDRAM"); case SIBA_DEVID_EXTIF: return ("EXTIF"); case SIBA_DEVID_80211: return ("IEEE 802.11"); case SIBA_DEVID_MIPS_3302: return ("MIPS 3302"); case SIBA_DEVID_USB11_HOST: return ("USB 1.1 Host"); case SIBA_DEVID_USB11_DEV: return ("USB 1.1 Device"); case SIBA_DEVID_USB20_HOST: return ("USB 2.0 Host"); case SIBA_DEVID_USB20_DEV: return ("USB 2.0 Device"); case SIBA_DEVID_SDIO_HOST: return ("SDIO Host"); case SIBA_DEVID_ROBOSWITCH: return ("Roboswitch"); case SIBA_DEVID_PARA_ATA: return ("PATA"); case SIBA_DEVID_SATA_XORDMA: return ("SATA XOR-DMA"); case SIBA_DEVID_ETHERNET_GBIT: return ("GBit Ethernet"); case SIBA_DEVID_PCIE: return ("PCI-Express"); case SIBA_DEVID_MIMO_PHY: return ("MIMO PHY"); case SIBA_DEVID_SRAM_CTRLR: return ("SRAM Controller"); case SIBA_DEVID_MINI_MACPHY: return ("Mini MACPHY"); case SIBA_DEVID_ARM_1176: return ("ARM 1176"); case SIBA_DEVID_ARM_7TDMI: return ("ARM 7TDMI"); } return ("unknown"); } static uint16_t siba_pci_read_2(struct siba_dev_softc *sd, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return (0xffff); return (SIBA_READ_2(siba, offset)); } static uint32_t siba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return (0xffff); return (SIBA_READ_4(siba, offset)); } static void siba_pci_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return; SIBA_WRITE_2(siba, offset, value); } static void siba_pci_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return; SIBA_WRITE_4(siba, offset, value); } static void siba_pci_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { memset(buffer, 0xff, count); return; } SIBA_READ_MULTI_1(siba, offset, buffer, count); } static void siba_pci_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { memset(buffer, 0xff, count); return; } KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__)); SIBA_READ_MULTI_2(siba, offset, buffer, count >> 1); } static void siba_pci_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) { memset(buffer, 0xff, count); return; } KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__)); SIBA_READ_MULTI_4(siba, offset, buffer, count >> 2); } static void siba_pci_write_multi_1(struct siba_dev_softc *sd, const void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return; SIBA_WRITE_MULTI_1(siba, offset, buffer, count); } static void siba_pci_write_multi_2(struct siba_dev_softc *sd, const void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return; KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__)); SIBA_WRITE_MULTI_2(siba, offset, buffer, count >> 1); } static void siba_pci_write_multi_4(struct siba_dev_softc *sd, const void *buffer, size_t count, uint16_t offset) { struct siba_softc *siba = sd->sd_bus; if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) return; KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__)); SIBA_WRITE_MULTI_4(siba, offset, buffer, count >> 2); } void siba_powerup(device_t dev, int dynamic) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; siba_powerup_sub(siba, dynamic); } static void siba_powerup_sub(struct siba_softc *siba, int dynamic) { siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1); siba_cc_clock(&siba->siba_cc, (dynamic != 0) ? SIBA_CLOCK_DYNAMIC : SIBA_CLOCK_FAST); } static void siba_cc_clock(struct siba_cc *scc, enum siba_clock clock) { struct siba_dev_softc *sd = scc->scc_dev; struct siba_softc *siba; uint32_t tmp; if (sd == NULL) return; siba = sd->sd_bus; /* * chipcommon < r6 (no dynamic clock control) * chipcommon >= r10 (unknown) */ if (sd->sd_id.sd_rev < 6 || sd->sd_id.sd_rev >= 10 || (scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0) return; switch (clock) { case SIBA_CLOCK_DYNAMIC: tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & ~(SIBA_CC_CLKSLOW_ENXTAL | SIBA_CC_CLKSLOW_FSLOW | SIBA_CC_CLKSLOW_IPLL); if ((tmp & SIBA_CC_CLKSLOW_SRC) != SIBA_CC_CLKSLOW_SRC_CRYSTAL) tmp |= SIBA_CC_CLKSLOW_ENXTAL; SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, tmp); if (tmp & SIBA_CC_CLKSLOW_ENXTAL) siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 0); break; case SIBA_CLOCK_SLOW: SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) | SIBA_CC_CLKSLOW_FSLOW); break; case SIBA_CLOCK_FAST: /* crystal on */ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 1); SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) | SIBA_CC_CLKSLOW_IPLL) & ~SIBA_CC_CLKSLOW_FSLOW); break; default: KASSERT(0 == 1, ("%s: unsupported clock %#x", __func__, clock)); } } uint16_t siba_read_2(device_t dev, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); return (sd->sd_ops->read_2(sd, offset)); } uint32_t siba_read_4(device_t dev, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); return (siba_read_4_sub(sd, offset)); } static uint32_t siba_read_4_sub(struct siba_dev_softc *sd, uint16_t offset) { return (sd->sd_ops->read_4(sd, offset)); } void siba_write_2(device_t dev, uint16_t offset, uint16_t value) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->write_2(sd, offset, value); } void siba_write_4(device_t dev, uint16_t offset, uint32_t value) { struct siba_dev_softc *sd = device_get_ivars(dev); return (siba_write_4_sub(sd, offset, value)); } static void siba_write_4_sub(struct siba_dev_softc *sd, uint16_t offset, uint32_t value) { sd->sd_ops->write_4(sd, offset, value); } void siba_read_multi_1(device_t dev, void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->read_multi_1(sd, buffer, count, offset); } void siba_read_multi_2(device_t dev, void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->read_multi_2(sd, buffer, count, offset); } void siba_read_multi_4(device_t dev, void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->read_multi_4(sd, buffer, count, offset); } void siba_write_multi_1(device_t dev, const void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->write_multi_1(sd, buffer, count, offset); } void siba_write_multi_2(device_t dev, const void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->write_multi_2(sd, buffer, count, offset); } void siba_write_multi_4(device_t dev, const void *buffer, size_t count, uint16_t offset) { struct siba_dev_softc *sd = device_get_ivars(dev); sd->sd_ops->write_multi_4(sd, buffer, count, offset); } static void siba_cc_pmu_init(struct siba_cc *scc) { const struct siba_cc_pmu_res_updown *updown = NULL; const struct siba_cc_pmu_res_depend *depend = NULL; struct siba_dev_softc *sd = scc->scc_dev; struct siba_softc *siba = sd->sd_bus; uint32_t min = 0, max = 0, pmucap; unsigned int i, updown_size, depend_size; if ((scc->scc_caps & SIBA_CC_CAPS_PMU) == 0) return; pmucap = SIBA_CC_READ32(scc, SIBA_CC_PMUCAPS); scc->scc_pmu.rev = (pmucap & SIBA_CC_PMUCAPS_REV); DPRINTF(siba, SIBA_DEBUG_PMU, "PMU(r%u) found (caps %#x)\n", scc->scc_pmu.rev, pmucap); if (scc->scc_pmu.rev >= 1) { if (siba->siba_chiprev < 2 && siba->siba_chipid == 0x4325) SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL, ~SIBA_CC_PMUCTL_NOILP); else SIBA_CC_SET32(scc, SIBA_CC_PMUCTL, SIBA_CC_PMUCTL_NOILP); } /* initialize PLL & PMU resources */ switch (siba->siba_chipid) { case 0x4312: siba_cc_pmu1_pll0_init(scc, 0 /* use default */); /* use the default: min = 0xcbb max = 0x7ffff */ break; case 0x4325: siba_cc_pmu1_pll0_init(scc, 0 /* use default */); updown = siba_cc_pmu_4325_updown; updown_size = N(siba_cc_pmu_4325_updown); depend = siba_cc_pmu_4325_depend; depend_size = N(siba_cc_pmu_4325_depend); min = (1 << SIBA_CC_PMU_4325_BURST) | (1 << SIBA_CC_PMU_4325_LN); if (SIBA_CC_READ32(scc, SIBA_CC_CHIPSTAT) & SIBA_CC_CHST_4325_PMUTOP_2B) min |= (1 << SIBA_CC_PMU_4325_CLBURST); max = 0xfffff; break; case 0x4328: siba_cc_pmu0_pll0_init(scc, 0 /* use default */); updown = siba_cc_pmu_4328_updown; updown_size = N(siba_cc_pmu_4328_updown); depend = siba_cc_pmu_4328_depend; depend_size = N(siba_cc_pmu_4328_depend); min = (1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) | (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM) | (1 << SIBA_CC_PMU_4328_CRYSTAL_EN); max = 0xfffff; break; case 0x5354: siba_cc_pmu0_pll0_init(scc, 0 /* use default */); max = 0xfffff; break; default: device_printf(siba->siba_dev, "unknown chipid %#x for PLL & PMU init\n", siba->siba_chipid); } if (updown) { for (i = 0; i < updown_size; i++) { SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL, updown[i].res); SIBA_CC_WRITE32(scc, SIBA_CC_PMU_UPDNTM, updown[i].updown); } } if (depend) { for (i = 0; i < depend_size; i++) { SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL, depend[i].res); switch (depend[i].task) { case SIBA_CC_PMU_DEP_SET: SIBA_CC_WRITE32(scc, SIBA_CC_PMU_DEPMSK, depend[i].depend); break; case SIBA_CC_PMU_DEP_ADD: SIBA_CC_SET32(scc, SIBA_CC_PMU_DEPMSK, depend[i].depend); break; case SIBA_CC_PMU_DEP_REMOVE: SIBA_CC_MASK32(scc, SIBA_CC_PMU_DEPMSK, ~(depend[i].depend)); break; default: KASSERT(0 == 1, ("%s:%d: assertion failed", __func__, __LINE__)); } } } if (min) SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min); if (max) SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max); } static void siba_cc_power_init(struct siba_cc *scc) { struct siba_softc *siba = scc->scc_dev->sd_bus; int maxfreq; if (siba->siba_chipid == 0x4321) { if (siba->siba_chiprev == 0) SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0x3a4); else if (siba->siba_chiprev == 1) SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0xa4); } if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0) return; if (scc->scc_dev->sd_id.sd_rev >= 10) SIBA_CC_WRITE32(scc, SIBA_CC_CLKSYSCTL, (SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) & 0xffff) | 0x40000); else { maxfreq = siba_cc_clockfreq(scc, 1); SIBA_CC_WRITE32(scc, SIBA_CC_PLLONDELAY, (maxfreq * 150 + 999999) / 1000000); SIBA_CC_WRITE32(scc, SIBA_CC_FREFSELDELAY, (maxfreq * 15 + 999999) / 1000000); } } static void siba_cc_powerup_delay(struct siba_cc *scc) { struct siba_softc *siba = scc->scc_dev->sd_bus; int min; if (siba->siba_type != SIBA_TYPE_PCI || !(scc->scc_caps & SIBA_CC_CAPS_PWCTL)) return; min = siba_cc_clockfreq(scc, 0); scc->scc_powerup_delay = howmany((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000, min); } static int siba_cc_clockfreq(struct siba_cc *scc, int max) { enum siba_clksrc src; int div = 1, limit = 0; src = siba_cc_clksrc(scc); if (scc->scc_dev->sd_id.sd_rev < 6) { div = (src == SIBA_CC_CLKSRC_PCI) ? 64 : (src == SIBA_CC_CLKSRC_CRYSTAL) ? 32 : 1; KASSERT(div != 1, ("%s: unknown clock %d", __func__, src)); } else if (scc->scc_dev->sd_id.sd_rev < 10) { switch (src) { case SIBA_CC_CLKSRC_CRYSTAL: case SIBA_CC_CLKSRC_PCI: div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) >> 16) + 1) * 4; break; case SIBA_CC_CLKSRC_LOWPW: break; } } else div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) >> 16) + 1) * 4; switch (src) { case SIBA_CC_CLKSRC_CRYSTAL: limit = (max) ? 20200000 : 19800000; break; case SIBA_CC_CLKSRC_LOWPW: limit = (max) ? 43000 : 25000; break; case SIBA_CC_CLKSRC_PCI: limit = (max) ? 34000000 : 25000000; break; } return (limit / div); } static void siba_cc_pmu1_pll0_init(struct siba_cc *scc, uint32_t freq) { struct siba_dev_softc *sd = scc->scc_dev; struct siba_softc *siba = sd->sd_bus; const struct siba_cc_pmu1_plltab *e = NULL; uint32_t bufsth = 0, pll, pmu; unsigned int i; KASSERT(freq == 0, ("%s:%d: assertion vail", __func__, __LINE__)); if (siba->siba_chipid == 0x4312) { scc->scc_pmu.freq = 20000; return; } e = siba_cc_pmu1_plltab_find(SIBA_CC_PMU1_DEFAULT_FREQ); KASSERT(e != NULL, ("%s:%d: assertion vail", __func__, __LINE__)); scc->scc_pmu.freq = e->freq; pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); if (SIBA_CC_PMUCTL_XF_VAL(pmu) == e->xf) return; DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n", (e->freq / 1000), (e->freq % 1000)); /* turn PLL off */ switch (siba->siba_chipid) { case 0x4325: bufsth = 0x222222; SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) | (1 << SIBA_CC_PMU_4325_HT))); SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) | (1 << SIBA_CC_PMU_4325_HT))); break; default: KASSERT(0 == 1, ("%s:%d: assertion failed", __func__, __LINE__)); } for (i = 0; i < 1500; i++) { if (!(SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT)) break; DELAY(10); } if (SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT) device_printf(siba->siba_dev, "failed to turn PLL off!\n"); pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL0); pll &= ~(SIBA_CC_PMU1_PLL0_P1DIV | SIBA_CC_PMU1_PLL0_P2DIV); pll |= ((uint32_t)e->p1div << 20) & SIBA_CC_PMU1_PLL0_P1DIV; pll |= ((uint32_t)e->p2div << 24) & SIBA_CC_PMU1_PLL0_P2DIV; siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, pll); pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL2); pll &= ~(SIBA_CC_PMU1_PLL2_NDIVINT | SIBA_CC_PMU1_PLL2_NDIVMODE); pll |= ((uint32_t)e->ndiv_int << 20) & SIBA_CC_PMU1_PLL2_NDIVINT; pll |= (1 << 17) & SIBA_CC_PMU1_PLL2_NDIVMODE; siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, pll); pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL3); pll &= ~SIBA_CC_PMU1_PLL3_NDIVFRAC; pll |= ((uint32_t)e->ndiv_frac << 0) & SIBA_CC_PMU1_PLL3_NDIVFRAC; siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, pll); if (bufsth) { pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL5); pll &= ~SIBA_CC_PMU1_PLL5_CLKDRV; pll |= (bufsth << 8) & SIBA_CC_PMU1_PLL5_CLKDRV; siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, pll); } pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); pmu &= ~(SIBA_CC_PMUCTL_ILP | SIBA_CC_PMUCTL_XF); pmu |= ((((uint32_t)e->freq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP; pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF; SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu); } static void siba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq) { struct siba_dev_softc *sd = scc->scc_dev; struct siba_softc *siba = sd->sd_bus; const struct siba_cc_pmu0_plltab *e = NULL; uint32_t pmu, tmp, pll; unsigned int i; if ((siba->siba_chipid == 0x5354) && !xtalfreq) xtalfreq = 25000; if (xtalfreq) e = siba_cc_pmu0_plltab_findentry(xtalfreq); if (!e) e = siba_cc_pmu0_plltab_findentry( SIBA_CC_PMU0_DEFAULT_XTALFREQ); KASSERT(e != NULL, ("%s:%d: fail", __func__, __LINE__)); xtalfreq = e->freq; scc->scc_pmu.freq = e->freq; pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); if (((pmu & SIBA_CC_PMUCTL_XF) >> 2) == e->xf) return; DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n", (xtalfreq / 1000), (xtalfreq % 1000)); KASSERT(siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354, ("%s:%d: fail", __func__, __LINE__)); switch (siba->siba_chipid) { case 0x4328: SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU)); SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU)); break; case 0x5354: SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU)); SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES, ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU)); break; } for (i = 1500; i; i--) { tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS); if (!(tmp & SIBA_CC_CLKCTLSTATUS_HT)) break; DELAY(10); } tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS); if (tmp & SIBA_CC_CLKCTLSTATUS_HT) device_printf(siba->siba_dev, "failed to turn PLL off!\n"); /* set PDIV */ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL0); if (xtalfreq >= SIBA_CC_PMU0_PLL0_PDIV_FREQ) pll |= SIBA_CC_PMU0_PLL0_PDIV_MSK; else pll &= ~SIBA_CC_PMU0_PLL0_PDIV_MSK; siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL0, pll); /* set WILD */ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL1); pll &= ~(SIBA_CC_PMU0_PLL1_STOPMOD | SIBA_CC_PMU0_PLL1_IMSK | SIBA_CC_PMU0_PLL1_FMSK); pll |= ((uint32_t)e->wb_int << 28) & SIBA_CC_PMU0_PLL1_IMSK; pll |= ((uint32_t)e->wb_frac << 8) & SIBA_CC_PMU0_PLL1_FMSK; if (e->wb_frac == 0) pll |= SIBA_CC_PMU0_PLL1_STOPMOD; siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL1, pll); /* set WILD */ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL2); pll &= ~SIBA_CC_PMU0_PLL2_IMSKHI; pll |= (((uint32_t)e->wb_int >> 4) << 0) & SIBA_CC_PMU0_PLL2_IMSKHI; siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL2, pll); /* set freq and divisor. */ pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL); pmu &= ~SIBA_CC_PMUCTL_ILP; pmu |= (((xtalfreq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP; pmu &= ~SIBA_CC_PMUCTL_XF; pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF; SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu); } static enum siba_clksrc siba_cc_clksrc(struct siba_cc *scc) { struct siba_dev_softc *sd = scc->scc_dev; struct siba_softc *siba = sd->sd_bus; if (sd->sd_id.sd_rev < 6) { if (siba->siba_type == SIBA_TYPE_PCI) { if (pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4) & 0x10) return (SIBA_CC_CLKSRC_PCI); return (SIBA_CC_CLKSRC_CRYSTAL); } if (siba->siba_type == SIBA_TYPE_SSB || siba->siba_type == SIBA_TYPE_PCMCIA) return (SIBA_CC_CLKSRC_CRYSTAL); } if (sd->sd_id.sd_rev < 10) { switch (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 0x7) { case 0: return (SIBA_CC_CLKSRC_LOWPW); case 1: return (SIBA_CC_CLKSRC_CRYSTAL); case 2: return (SIBA_CC_CLKSRC_PCI); default: break; } } return (SIBA_CC_CLKSRC_CRYSTAL); } static const struct siba_cc_pmu1_plltab * siba_cc_pmu1_plltab_find(uint32_t crystalfreq) { const struct siba_cc_pmu1_plltab *e; unsigned int i; for (i = 0; i < N(siba_cc_pmu1_plltab); i++) { e = &siba_cc_pmu1_plltab[i]; if (crystalfreq == e->freq) return (e); } return (NULL); } static uint32_t siba_cc_pll_read(struct siba_cc *scc, uint32_t offset) { SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset); return (SIBA_CC_READ32(scc, SIBA_CC_PLLCTL_DATA)); } static void siba_cc_pll_write(struct siba_cc *scc, uint32_t offset, uint32_t value) { SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset); SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, value); } static const struct siba_cc_pmu0_plltab * siba_cc_pmu0_plltab_findentry(uint32_t crystalfreq) { const struct siba_cc_pmu0_plltab *e; unsigned int i; for (i = 0; i < N(siba_cc_pmu0_plltab); i++) { e = &siba_cc_pmu0_plltab[i]; if (e->freq == crystalfreq) return (e); } return (NULL); } static int siba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom) { int error = ENOMEM; uint16_t *buf; buf = malloc(SIBA_SPROMSIZE_R123 * sizeof(uint16_t), M_DEVBUF, M_NOWAIT | M_ZERO); if (buf == NULL) return (ENOMEM); siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123); error = sprom_check_crc(buf, siba->siba_spromsize); if (error) { free(buf, M_DEVBUF); buf = malloc(SIBA_SPROMSIZE_R4 * sizeof(uint16_t), M_DEVBUF, M_NOWAIT | M_ZERO); if (buf == NULL) return (ENOMEM); siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R4); error = sprom_check_crc(buf, siba->siba_spromsize); if (error) device_printf(siba->siba_dev, "warn: bad SPROM CRC\n"); } bzero(sprom, sizeof(*sprom)); sprom->rev = buf[siba->siba_spromsize - 1] & 0x00FF; DPRINTF(siba, SIBA_DEBUG_SPROM, "SPROM rev %d\n", sprom->rev); memset(sprom->mac_eth, 0xff, 6); memset(sprom->mac_80211a, 0xff, 6); if ((siba->siba_chipid & 0xff00) == 0x4400) { sprom->rev = 1; siba_sprom_r123(sprom, buf); } else if (siba->siba_chipid == 0x4321) { sprom->rev = 4; siba_sprom_r45(sprom, buf); } else { switch (sprom->rev) { case 1: case 2: case 3: siba_sprom_r123(sprom, buf); break; case 4: case 5: siba_sprom_r45(sprom, buf); break; case 8: siba_sprom_r8(sprom, buf); break; default: device_printf(siba->siba_dev, "unknown SPROM revision %d.\n", sprom->rev); siba_sprom_r123(sprom, buf); } } if (sprom->bf_lo == 0xffff) sprom->bf_lo = 0; if (sprom->bf_hi == 0xffff) sprom->bf_hi = 0; free(buf, M_DEVBUF); return (error); } static int siba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len) { int i; for (i = 0; i < len; i++) sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2)); siba->siba_spromsize = len; return (0); } static int sprom_check_crc(const uint16_t *sprom, size_t size) { int word; uint8_t crc0, crc1 = 0xff; crc0 = (sprom[size - 1] & SIBA_SPROM_REV_CRC) >> 8; for (word = 0; word < size - 1; word++) { crc1 = siba_crc8(crc1, sprom[word] & 0x00ff); crc1 = siba_crc8(crc1, (sprom[word] & 0xff00) >> 8); } crc1 = siba_crc8(crc1, sprom[size - 1] & 0x00ff); crc1 ^= 0xff; return ((crc0 != crc1) ? EPROTO : 0); } static uint8_t siba_crc8(uint8_t crc, uint8_t data) { static const uint8_t ct[] = { 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3, 0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, 0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f, 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b, 0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, 0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09, 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91, 0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01, 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38, 0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, 0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f, 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5, 0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, 0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82, 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1, 0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5, 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3, 0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, 0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1, 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5, 0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, 0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49, 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1, 0x26, 0x68, 0x9f, }; return (ct[crc ^ data]); } #define SIBA_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask)) #define SIBA_OFFSET(offset) \ (((offset) - SIBA_SPROM_BASE) / sizeof(uint16_t)) #define SIBA_SHIFTOUT_SUB(__x, __mask) \ (((__x) & (__mask)) / SIBA_LOWEST_SET_BIT(__mask)) #define SIBA_SHIFTOUT(_var, _offset, _mask) \ out->_var = SIBA_SHIFTOUT_SUB(in[SIBA_OFFSET(_offset)], (_mask)) #define SIBA_SHIFTOUT_4(_var, _offset, _mask, _shift) \ out->_var = ((((uint32_t)in[SIBA_OFFSET((_offset)+2)] << 16 | \ in[SIBA_OFFSET(_offset)]) & (_mask)) >> (_shift)) static void siba_sprom_r123(struct siba_sprom *out, const uint16_t *in) { int i; uint16_t v; int8_t gain; uint16_t loc[3]; if (out->rev == 3) loc[0] = SIBA_SPROM3_MAC_80211BG; else { loc[0] = SIBA_SPROM1_MAC_80211BG; loc[1] = SIBA_SPROM1_MAC_ETH; loc[2] = SIBA_SPROM1_MAC_80211A; } for (i = 0; i < 3; i++) { v = in[SIBA_OFFSET(loc[0]) + i]; *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); } if (out->rev < 3) { for (i = 0; i < 3; i++) { v = in[SIBA_OFFSET(loc[1]) + i]; *(((uint16_t *)out->mac_eth) + i) = htobe16(v); } for (i = 0; i < 3; i++) { v = in[SIBA_OFFSET(loc[2]) + i]; *(((uint16_t *)out->mac_80211a) + i) = htobe16(v); } } SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM1_ETHPHY, SIBA_SPROM1_ETHPHY_MII_ETH0); SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM1_ETHPHY, SIBA_SPROM1_ETHPHY_MII_ETH1); SIBA_SHIFTOUT(mdio_eth0, SIBA_SPROM1_ETHPHY, SIBA_SPROM1_ETHPHY_MDIO_ETH0); SIBA_SHIFTOUT(mdio_eth1, SIBA_SPROM1_ETHPHY, SIBA_SPROM1_ETHPHY_MDIO_ETH1); SIBA_SHIFTOUT(brev, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_BREV); SIBA_SHIFTOUT(ccode, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_CCODE); SIBA_SHIFTOUT(ant_a, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTA); SIBA_SHIFTOUT(ant_bg, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTBG); SIBA_SHIFTOUT(pa0b0, SIBA_SPROM1_PA0B0, 0xffff); SIBA_SHIFTOUT(pa0b1, SIBA_SPROM1_PA0B1, 0xffff); SIBA_SHIFTOUT(pa0b2, SIBA_SPROM1_PA0B2, 0xffff); SIBA_SHIFTOUT(pa1b0, SIBA_SPROM1_PA1B0, 0xffff); SIBA_SHIFTOUT(pa1b1, SIBA_SPROM1_PA1B1, 0xffff); SIBA_SHIFTOUT(pa1b2, SIBA_SPROM1_PA1B2, 0xffff); SIBA_SHIFTOUT(gpio0, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P0); SIBA_SHIFTOUT(gpio1, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P1); SIBA_SHIFTOUT(gpio2, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P2); SIBA_SHIFTOUT(gpio3, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P3); SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_A); SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_BG); SIBA_SHIFTOUT(tssi_a, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_A); SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_BG); SIBA_SHIFTOUT(bf_lo, SIBA_SPROM1_BFLOW, 0xffff); if (out->rev >= 2) SIBA_SHIFTOUT(bf_hi, SIBA_SPROM2_BFHIGH, 0xffff); /* antenna gain */ gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_BG, 0); out->again.ghz24.a0 = out->again.ghz24.a1 = gain; out->again.ghz24.a2 = out->again.ghz24.a3 = gain; gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_A, 8); out->again.ghz5.a0 = out->again.ghz5.a1 = gain; out->again.ghz5.a2 = out->again.ghz5.a3 = gain; } static void siba_sprom_r45(struct siba_sprom *out, const uint16_t *in) { int i; uint16_t v; uint16_t mac_80211bg_offset; + const uint16_t pwr_info_offset[] = { + SIBA_SPROM4_PWR_INFO_CORE0, SIBA_SPROM4_PWR_INFO_CORE1, + SIBA_SPROM4_PWR_INFO_CORE2, SIBA_SPROM4_PWR_INFO_CORE3 + }; if (out->rev == 4) mac_80211bg_offset = SIBA_SPROM4_MAC_80211BG; else mac_80211bg_offset = SIBA_SPROM5_MAC_80211BG; for (i = 0; i < 3; i++) { v = in[SIBA_OFFSET(mac_80211bg_offset) + i]; *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); } SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET0A); SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET1A); if (out->rev == 4) { SIBA_SHIFTOUT(ccode, SIBA_SPROM4_CCODE, 0xffff); SIBA_SHIFTOUT(bf_lo, SIBA_SPROM4_BFLOW, 0xffff); SIBA_SHIFTOUT(bf_hi, SIBA_SPROM4_BFHIGH, 0xffff); } else { SIBA_SHIFTOUT(ccode, SIBA_SPROM5_CCODE, 0xffff); SIBA_SHIFTOUT(bf_lo, SIBA_SPROM5_BFLOW, 0xffff); SIBA_SHIFTOUT(bf_hi, SIBA_SPROM5_BFHIGH, 0xffff); } SIBA_SHIFTOUT(ant_a, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_A); SIBA_SHIFTOUT(ant_bg, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_BG); SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_MAXP_BG_MASK); SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_TSSI_BG); SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_MAXP_A_MASK); SIBA_SHIFTOUT(tssi_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_TSSI_A); if (out->rev == 4) { SIBA_SHIFTOUT(gpio0, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P0); SIBA_SHIFTOUT(gpio1, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P1); SIBA_SHIFTOUT(gpio2, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P2); SIBA_SHIFTOUT(gpio3, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P3); } else { SIBA_SHIFTOUT(gpio0, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P0); SIBA_SHIFTOUT(gpio1, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P1); SIBA_SHIFTOUT(gpio2, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P2); SIBA_SHIFTOUT(gpio3, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P3); } /* antenna gain */ SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN0); SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN1); SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN2); SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN3); bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5)); + + /* Extract core power info */ + for (i = 0; i < nitems(pwr_info_offset); i++) { + uint16_t o = pwr_info_offset[i]; + + SIBA_SHIFTOUT(core_pwr_info[i].itssi_2g, o + SIBA_SPROM4_2G_MAXP_ITSSI, + SIBA_SPROM4_2G_ITSSI); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_2g, o + SIBA_SPROM4_2G_MAXP_ITSSI, + SIBA_SPROM4_2G_MAXP); + + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[0], o + SIBA_SPROM4_2G_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[1], o + SIBA_SPROM4_2G_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[2], o + SIBA_SPROM4_2G_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[3], o + SIBA_SPROM4_2G_PA_3, ~0); + + SIBA_SHIFTOUT(core_pwr_info[i].itssi_5g, o + SIBA_SPROM4_5G_MAXP_ITSSI, + SIBA_SPROM4_5G_ITSSI); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5g, o + SIBA_SPROM4_5G_MAXP_ITSSI, + SIBA_SPROM4_5G_MAXP); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gh, o + SIBA_SPROM4_5GHL_MAXP, + SIBA_SPROM4_5GH_MAXP); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gl, o + SIBA_SPROM4_5GHL_MAXP, + SIBA_SPROM4_5GL_MAXP); + + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[0], o + SIBA_SPROM4_5GL_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[1], o + SIBA_SPROM4_5GL_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[2], o + SIBA_SPROM4_5GL_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[3], o + SIBA_SPROM4_5GL_PA_3, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[0], o + SIBA_SPROM4_5G_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[1], o + SIBA_SPROM4_5G_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[2], o + SIBA_SPROM4_5G_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[3], o + SIBA_SPROM4_5G_PA_3, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[0], o + SIBA_SPROM4_5GH_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[1], o + SIBA_SPROM4_5GH_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[2], o + SIBA_SPROM4_5GH_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[3], o + SIBA_SPROM4_5GH_PA_3, ~0); + } } static void siba_sprom_r8(struct siba_sprom *out, const uint16_t *in) { int i; uint16_t v; + uint16_t pwr_info_offset[] = { + SIBA_SROM8_PWR_INFO_CORE0, SIBA_SROM8_PWR_INFO_CORE1, + SIBA_SROM8_PWR_INFO_CORE2, SIBA_SROM8_PWR_INFO_CORE3 + }; for (i = 0; i < 3; i++) { v = in[SIBA_OFFSET(SIBA_SPROM8_MAC_80211BG) + i]; *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v); } SIBA_SHIFTOUT(ccode, SIBA_SPROM8_CCODE, 0xffff); SIBA_SHIFTOUT(bf_lo, SIBA_SPROM8_BFLOW, 0xffff); SIBA_SHIFTOUT(bf_hi, SIBA_SPROM8_BFHIGH, 0xffff); SIBA_SHIFTOUT(bf2_lo, SIBA_SPROM8_BFL2LO, 0xffff); SIBA_SHIFTOUT(bf2_hi, SIBA_SPROM8_BFL2HI, 0xffff); SIBA_SHIFTOUT(ant_a, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_A); SIBA_SHIFTOUT(ant_bg, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_BG); SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_MAXP_BG_MASK); SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_TSSI_BG); SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_MAXP_A_MASK); SIBA_SHIFTOUT(tssi_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_TSSI_A); SIBA_SHIFTOUT(maxpwr_ah, SIBA_SPROM8_MAXP_AHL, SIBA_SPROM8_MAXP_AH_MASK); SIBA_SHIFTOUT(maxpwr_al, SIBA_SPROM8_MAXP_AHL, SIBA_SPROM8_MAXP_AL_MASK); SIBA_SHIFTOUT(gpio0, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P0); SIBA_SHIFTOUT(gpio1, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P1); SIBA_SHIFTOUT(gpio2, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P2); SIBA_SHIFTOUT(gpio3, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P3); SIBA_SHIFTOUT(tri2g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI2G); SIBA_SHIFTOUT(tri5g, SIBA_SPROM8_TRI25G, SIBA_SPROM8_TRI5G); SIBA_SHIFTOUT(tri5gl, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GL); SIBA_SHIFTOUT(tri5gh, SIBA_SPROM8_TRI5GHL, SIBA_SPROM8_TRI5GH); SIBA_SHIFTOUT(rxpo2g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO2G); SIBA_SHIFTOUT(rxpo5g, SIBA_SPROM8_RXPO, SIBA_SPROM8_RXPO5G); SIBA_SHIFTOUT(rssismf2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMF2G); SIBA_SHIFTOUT(rssismc2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISMC2G); SIBA_SHIFTOUT(rssisav2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_RSSISAV2G); SIBA_SHIFTOUT(bxa2g, SIBA_SPROM8_RSSIPARM2G, SIBA_SPROM8_BXA2G); SIBA_SHIFTOUT(rssismf5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMF5G); SIBA_SHIFTOUT(rssismc5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISMC5G); SIBA_SHIFTOUT(rssisav5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_RSSISAV5G); SIBA_SHIFTOUT(bxa5g, SIBA_SPROM8_RSSIPARM5G, SIBA_SPROM8_BXA5G); SIBA_SHIFTOUT(pa0b0, SIBA_SPROM8_PA0B0, 0xffff); SIBA_SHIFTOUT(pa0b1, SIBA_SPROM8_PA0B1, 0xffff); SIBA_SHIFTOUT(pa0b2, SIBA_SPROM8_PA0B2, 0xffff); SIBA_SHIFTOUT(pa1b0, SIBA_SPROM8_PA1B0, 0xffff); SIBA_SHIFTOUT(pa1b1, SIBA_SPROM8_PA1B1, 0xffff); SIBA_SHIFTOUT(pa1b2, SIBA_SPROM8_PA1B2, 0xffff); SIBA_SHIFTOUT(pa1lob0, SIBA_SPROM8_PA1LOB0, 0xffff); SIBA_SHIFTOUT(pa1lob1, SIBA_SPROM8_PA1LOB1, 0xffff); SIBA_SHIFTOUT(pa1lob2, SIBA_SPROM8_PA1LOB2, 0xffff); SIBA_SHIFTOUT(pa1hib0, SIBA_SPROM8_PA1HIB0, 0xffff); SIBA_SHIFTOUT(pa1hib1, SIBA_SPROM8_PA1HIB1, 0xffff); SIBA_SHIFTOUT(pa1hib2, SIBA_SPROM8_PA1HIB2, 0xffff); SIBA_SHIFTOUT(cck2gpo, SIBA_SPROM8_CCK2GPO, 0xffff); SIBA_SHIFTOUT_4(ofdm2gpo, SIBA_SPROM8_OFDM2GPO, 0xffffffff, 0); SIBA_SHIFTOUT_4(ofdm5glpo, SIBA_SPROM8_OFDM5GLPO, 0xffffffff, 0); SIBA_SHIFTOUT_4(ofdm5gpo, SIBA_SPROM8_OFDM5GPO, 0xffffffff, 0); SIBA_SHIFTOUT_4(ofdm5ghpo, SIBA_SPROM8_OFDM5GHPO, 0xffffffff, 0); /* antenna gain */ SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN0); SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN1); SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2); SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3); bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5)); /* FEM */ SIBA_SHIFTOUT(fem.ghz2.tssipos, SIBA_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS); SIBA_SHIFTOUT(fem.ghz2.extpa_gain, SIBA_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN); SIBA_SHIFTOUT(fem.ghz2.pdet_range, SIBA_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE); SIBA_SHIFTOUT(fem.ghz2.tr_iso, SIBA_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO); SIBA_SHIFTOUT(fem.ghz2.antswlut, SIBA_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT); SIBA_SHIFTOUT(fem.ghz5.tssipos, SIBA_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS); SIBA_SHIFTOUT(fem.ghz5.extpa_gain, SIBA_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN); SIBA_SHIFTOUT(fem.ghz5.pdet_range, SIBA_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE); SIBA_SHIFTOUT(fem.ghz5.tr_iso, SIBA_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO); SIBA_SHIFTOUT(fem.ghz5.antswlut, SIBA_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT); + + /* Extract cores power info info */ + for (i = 0; i < nitems(pwr_info_offset); i++) { + uint16_t o = pwr_info_offset[i]; + SIBA_SHIFTOUT(core_pwr_info[i].itssi_2g, o + SIBA_SROM8_2G_MAXP_ITSSI, + SIBA_SPROM8_2G_ITSSI); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_2g, o + SIBA_SROM8_2G_MAXP_ITSSI, + SIBA_SPROM8_2G_MAXP); + + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[0], o + SIBA_SROM8_2G_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[1], o + SIBA_SROM8_2G_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_2g[2], o + SIBA_SROM8_2G_PA_2, ~0); + + SIBA_SHIFTOUT(core_pwr_info[i].itssi_5g, o + SIBA_SROM8_5G_MAXP_ITSSI, + SIBA_SPROM8_5G_ITSSI); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5g, o + SIBA_SROM8_5G_MAXP_ITSSI, + SIBA_SPROM8_5G_MAXP); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gh, o + SIBA_SPROM8_5GHL_MAXP, + SIBA_SPROM8_5GH_MAXP); + SIBA_SHIFTOUT(core_pwr_info[i].maxpwr_5gl, o + SIBA_SPROM8_5GHL_MAXP, + SIBA_SPROM8_5GL_MAXP); + + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[0], o + SIBA_SROM8_5GL_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[1], o + SIBA_SROM8_5GL_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gl[2], o + SIBA_SROM8_5GL_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[0], o + SIBA_SROM8_5G_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[1], o + SIBA_SROM8_5G_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5g[2], o + SIBA_SROM8_5G_PA_2, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[0], o + SIBA_SROM8_5GH_PA_0, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[1], o + SIBA_SROM8_5GH_PA_1, ~0); + SIBA_SHIFTOUT(core_pwr_info[i].pa_5gh[2], o + SIBA_SROM8_5GH_PA_2, ~0); + } } static int8_t siba_sprom_r123_antgain(uint8_t sprom_revision, const uint16_t *in, uint16_t mask, uint16_t shift) { uint16_t v; uint8_t gain; v = in[SIBA_OFFSET(SIBA_SPROM1_AGAIN)]; gain = (v & mask) >> shift; gain = (gain == 0xff) ? 2 : (sprom_revision == 1) ? gain << 2 : ((gain & 0xc0) >> 6) | ((gain & 0x3f) << 2); return ((int8_t)gain); } #undef SIBA_LOWEST_SET_BIT #undef SIBA_OFFSET #undef SIBA_SHIFTOUT_SUB #undef SIBA_SHIFTOUT int siba_powerdown(device_t dev) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; return (siba_powerdown_sub(siba)); } static int siba_powerdown_sub(struct siba_softc *siba) { struct siba_cc *scc; if (siba->siba_type == SIBA_TYPE_SSB) return (0); scc = &siba->siba_cc; if (!scc->scc_dev || scc->scc_dev->sd_id.sd_rev < 5) return (0); siba_cc_clock(scc, SIBA_CLOCK_SLOW); siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0); return (0); } static void siba_pcicore_init(struct siba_pci *spc) { struct siba_dev_softc *sd = spc->spc_dev; if (sd == NULL) return; if (!siba_dev_isup_sub(sd)) siba_dev_up_sub(sd, 0); KASSERT(spc->spc_hostmode == 0, ("%s:%d: hostmode", __func__, __LINE__)); /* disable PCI interrupt */ siba_write_4_sub(spc->spc_dev, SIBA_INTR_MASK, 0); } int siba_dev_isup(device_t dev) { struct siba_dev_softc *sd = device_get_ivars(dev); return (siba_dev_isup_sub(sd)); } static int siba_dev_isup_sub(struct siba_dev_softc *sd) { uint32_t reject, val; reject = siba_tmslow_reject_bitmask(sd); val = siba_read_4_sub(sd, SIBA_TGSLOW); val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject; return (val == SIBA_TGSLOW_CLOCK); } void siba_dev_up(device_t dev, uint32_t flags) { struct siba_dev_softc *sd = device_get_ivars(dev); siba_dev_up_sub(sd, flags); } static void siba_dev_up_sub(struct siba_dev_softc *sd, uint32_t flags) { uint32_t val; siba_dev_down_sub(sd, flags); siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags); siba_read_4_sub(sd, SIBA_TGSLOW); DELAY(1); if (siba_read_4_sub(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR) siba_write_4_sub(sd, SIBA_TGSHIGH, 0); val = siba_read_4_sub(sd, SIBA_IAS); if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) { val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT); siba_write_4_sub(sd, SIBA_IAS, val); } siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags); siba_read_4_sub(sd, SIBA_TGSLOW); DELAY(1); siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags); siba_read_4_sub(sd, SIBA_TGSLOW); DELAY(1); } static uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *sd) { uint32_t rev = siba_read_4_sub(sd, SIBA_IDLOW) & SIBA_IDLOW_SSBREV; switch (rev) { case SIBA_IDLOW_SSBREV_22: return (SIBA_TGSLOW_REJECT_22); case SIBA_IDLOW_SSBREV_23: return (SIBA_TGSLOW_REJECT_23); case SIBA_IDLOW_SSBREV_24: case SIBA_IDLOW_SSBREV_25: case SIBA_IDLOW_SSBREV_26: case SIBA_IDLOW_SSBREV_27: return (SIBA_TGSLOW_REJECT_23); default: KASSERT(0 == 1, ("%s:%d: unknown backplane rev %#x\n", __func__, __LINE__, rev)); } return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23); } void siba_dev_down(device_t dev, uint32_t flags) { struct siba_dev_softc *sd = device_get_ivars(dev); siba_dev_down_sub(sd, flags); } static void siba_dev_down_sub(struct siba_dev_softc *sd, uint32_t flags) { struct siba_softc *siba = sd->sd_bus; uint32_t reject, val; int i; if (siba_read_4_sub(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET) return; reject = siba_tmslow_reject_bitmask(sd); siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK); for (i = 0; i < 1000; i++) { val = siba_read_4_sub(sd, SIBA_TGSLOW); if (val & reject) break; DELAY(10); } if ((val & reject) == 0) { device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n", reject, SIBA_TGSLOW); } for (i = 0; i < 1000; i++) { val = siba_read_4_sub(sd, SIBA_TGSHIGH); if (!(val & SIBA_TGSHIGH_BUSY)) break; DELAY(10); } if ((val & SIBA_TGSHIGH_BUSY) != 0) { device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n", SIBA_TGSHIGH_BUSY, SIBA_TGSHIGH); } siba_write_4_sub(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK | reject | SIBA_TGSLOW_RESET | flags); siba_read_4_sub(sd, SIBA_TGSLOW); DELAY(1); siba_write_4_sub(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags); siba_read_4_sub(sd, SIBA_TGSLOW); DELAY(1); } static void siba_pcicore_setup(struct siba_pci *spc, struct siba_dev_softc *sd) { struct siba_dev_softc *psd = spc->spc_dev; struct siba_softc *siba = psd->sd_bus; uint32_t tmp; if (psd->sd_id.sd_device == SIBA_DEVID_PCI) { siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2) | SIBA_PCICORE_SBTOPCI_PREF | SIBA_PCICORE_SBTOPCI_BURST); if (psd->sd_id.sd_rev < 5) { tmp = siba_read_4_sub(psd, SIBA_IMCFGLO); tmp &= ~SIBA_IMCFGLO_SERTO; tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO; tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */; siba_write_4_sub(psd, SIBA_IMCFGLO, tmp); /* broadcast value */ sd = (siba->siba_cc.scc_dev != NULL) ? siba->siba_cc.scc_dev : siba->siba_pci.spc_dev; if (sd != NULL) { siba_write_4_sub(sd, SIBA_PCICORE_BCAST_ADDR, 0xfd8); siba_read_4_sub(sd, SIBA_PCICORE_BCAST_ADDR); siba_write_4_sub(sd, SIBA_PCICORE_BCAST_DATA, 0); siba_read_4_sub(sd, SIBA_PCICORE_BCAST_DATA); } } else if (psd->sd_id.sd_rev >= 11) { tmp = siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2); tmp |= SIBA_PCICORE_SBTOPCI_MRM; siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, tmp); } } else { KASSERT(psd->sd_id.sd_device == SIBA_DEVID_PCIE, ("only PCIE")); if ((psd->sd_id.sd_rev == 0) || (psd->sd_id.sd_rev == 1)) siba_pcie_write(spc, 0x4, siba_pcie_read(spc, 0x4) | 0x8); if (psd->sd_id.sd_rev == 0) { siba_pcie_mdio_write(spc, 0x1f, 2, 0x8128); /* Timer */ siba_pcie_mdio_write(spc, 0x1f, 6, 0x0100); /* CDR */ siba_pcie_mdio_write(spc, 0x1f, 7, 0x1466); /* CDR BW */ } else if (psd->sd_id.sd_rev == 1) siba_pcie_write(spc, 0x100, siba_pcie_read(spc, 0x100) | 0x40); } spc->spc_inited = 1; } void siba_pcicore_intr(device_t dev) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; struct siba_pci *spc = &siba->siba_pci; struct siba_dev_softc *psd = spc->spc_dev; uint32_t tmp; if (siba->siba_type != SIBA_TYPE_PCI || !psd) return; KASSERT(siba == psd->sd_bus, ("different pointers")); /* enable interrupts */ if (siba->siba_dev != NULL && (psd->sd_id.sd_rev >= 6 || psd->sd_id.sd_device == SIBA_DEVID_PCIE)) { tmp = pci_read_config(siba->siba_dev, SIBA_IRQMASK, 4); tmp |= (1 << sd->sd_coreidx) << 8; pci_write_config(siba->siba_dev, SIBA_IRQMASK, tmp, 4); } else { tmp = siba_read_4_sub(sd, SIBA_TPS); tmp &= SIBA_TPS_BPFLAG; siba_write_4_sub(psd, SIBA_INTR_MASK, siba_read_4_sub(psd, SIBA_INTR_MASK) | (1 << tmp)); } /* setup PCIcore */ if (spc->spc_inited == 0) siba_pcicore_setup(spc, sd); } static uint32_t siba_pcicore_read_4(struct siba_pci *spc, uint16_t offset) { return (siba_read_4_sub(spc->spc_dev, offset)); } static void siba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value) { siba_write_4_sub(spc->spc_dev, offset, value); } static uint32_t siba_pcie_read(struct siba_pci *spc, uint32_t address) { siba_pcicore_write_4(spc, 0x130, address); return (siba_pcicore_read_4(spc, 0x134)); } static void siba_pcie_write(struct siba_pci *spc, uint32_t address, uint32_t data) { siba_pcicore_write_4(spc, 0x130, address); siba_pcicore_write_4(spc, 0x134, data); } static void siba_pcie_mdio_write(struct siba_pci *spc, uint8_t device, uint8_t address, uint16_t data) { int i; siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0x80 | 0x2); siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_DATA, (1 << 30) | (1 << 28) | ((uint32_t)device << 22) | ((uint32_t)address << 18) | (1 << 17) | data); DELAY(10); for (i = 0; i < 10; i++) { if (siba_pcicore_read_4(spc, SIBA_PCICORE_MDIO_CTL) & 0x100) break; DELAY(1000); } siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0); } uint32_t siba_dma_translation(device_t dev) { #ifdef INVARIANTS struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; KASSERT(siba->siba_type == SIBA_TYPE_PCI, ("unsupported bustype %d\n", siba->siba_type)); #endif return (SIBA_PCI_DMA); } void siba_barrier(device_t dev, int flags) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; SIBA_BARRIER(siba, flags); } static void siba_cc_suspend(struct siba_cc *scc) { siba_cc_clock(scc, SIBA_CLOCK_SLOW); } static void siba_cc_resume(struct siba_cc *scc) { siba_cc_power_init(scc); siba_cc_clock(scc, SIBA_CLOCK_FAST); } int siba_core_suspend(struct siba_softc *siba) { siba_cc_suspend(&siba->siba_cc); siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0); return (0); } int siba_core_resume(struct siba_softc *siba) { siba->siba_pci.spc_inited = 0; siba->siba_curdev = NULL; siba_powerup_sub(siba, 0); /* XXX setup H/W for PCMCIA??? */ siba_cc_resume(&siba->siba_cc); siba_powerdown_sub(siba); return (0); } static void siba_cc_regctl_setmask(struct siba_cc *cc, uint32_t offset, uint32_t mask, uint32_t set) { SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR); SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_ADDR, offset); SIBA_CC_READ32(cc, SIBA_CC_REGCTL_ADDR); SIBA_CC_WRITE32(cc, SIBA_CC_REGCTL_DATA, (SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA) & mask) | set); SIBA_CC_READ32(cc, SIBA_CC_REGCTL_DATA); } void siba_cc_pmu_set_ldovolt(device_t dev, int id, uint32_t volt) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; struct siba_cc *scc = &siba->siba_cc; uint32_t *p = NULL, info[5][3] = { { 2, 25, 0xf }, { 3, 1, 0xf }, { 3, 9, 0xf }, { 3, 17, 0x3f }, { 0, 21, 0x3f } }; if (siba->siba_chipid == 0x4312) { if (id != SIBA_LDO_PAREF) return; p = info[4]; siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]), (volt & p[2]) << p[1]); return; } if (siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354) { switch (id) { case SIBA_LDO_PAREF: p = info[3]; break; case SIBA_LDO_VOLT1: p = info[0]; break; case SIBA_LDO_VOLT2: p = info[1]; break; case SIBA_LDO_VOLT3: p = info[2]; break; default: KASSERT(0 == 1, ("%s: unsupported voltage ID %#x", __func__, id)); return; } siba_cc_regctl_setmask(scc, p[0], ~(p[2] << p[1]), (volt & p[2]) << p[1]); } } void siba_cc_pmu_set_ldoparef(device_t dev, uint8_t on) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; struct siba_cc *scc = &siba->siba_cc; int ldo; ldo = ((siba->siba_chipid == 0x4312) ? SIBA_CC_PMU_4312_PA_REF : ((siba->siba_chipid == 0x4328) ? SIBA_CC_PMU_4328_PA_REF : ((siba->siba_chipid == 0x5354) ? SIBA_CC_PMU_5354_PA_REF : -1))); if (ldo == -1) return; if (on) SIBA_CC_SET32(scc, SIBA_CC_PMU_MINRES, 1 << ldo); else SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES, ~(1 << ldo)); SIBA_CC_READ32(scc, SIBA_CC_PMU_MINRES); } int siba_read_sprom(device_t dev, device_t child, int which, uintptr_t *result) { struct siba_dev_softc *sd = device_get_ivars(child); struct siba_softc *siba = sd->sd_bus; switch (which) { case SIBA_SPROMVAR_REV: *result = siba->siba_sprom.rev; break; case SIBA_SPROMVAR_MAC_80211BG: *((uint8_t **) result) = siba->siba_sprom.mac_80211bg; break; case SIBA_SPROMVAR_MAC_ETH: *((uint8_t **) result) = siba->siba_sprom.mac_eth; break; case SIBA_SPROMVAR_MAC_80211A: *((uint8_t **) result) = siba->siba_sprom.mac_80211a; break; case SIBA_SPROMVAR_MII_ETH0: *result = siba->siba_sprom.mii_eth0; break; case SIBA_SPROMVAR_MII_ETH1: *result = siba->siba_sprom.mii_eth1; break; case SIBA_SPROMVAR_MDIO_ETH0: *result = siba->siba_sprom.mdio_eth0; break; case SIBA_SPROMVAR_MDIO_ETH1: *result = siba->siba_sprom.mdio_eth1; break; case SIBA_SPROMVAR_BREV: *result = siba->siba_sprom.brev; break; case SIBA_SPROMVAR_CCODE: *result = siba->siba_sprom.ccode; break; case SIBA_SPROMVAR_ANT_A: *result = siba->siba_sprom.ant_a; break; case SIBA_SPROMVAR_ANT_BG: *result = siba->siba_sprom.ant_bg; break; case SIBA_SPROMVAR_PA0B0: *result = siba->siba_sprom.pa0b0; break; case SIBA_SPROMVAR_PA0B1: *result = siba->siba_sprom.pa0b1; break; case SIBA_SPROMVAR_PA0B2: *result = siba->siba_sprom.pa0b2; break; case SIBA_SPROMVAR_PA1B0: *result = siba->siba_sprom.pa1b0; break; case SIBA_SPROMVAR_PA1B1: *result = siba->siba_sprom.pa1b1; break; case SIBA_SPROMVAR_PA1B2: *result = siba->siba_sprom.pa1b2; break; case SIBA_SPROMVAR_PA1LOB0: *result = siba->siba_sprom.pa1lob0; break; case SIBA_SPROMVAR_PA1LOB1: *result = siba->siba_sprom.pa1lob1; break; case SIBA_SPROMVAR_PA1LOB2: *result = siba->siba_sprom.pa1lob2; break; case SIBA_SPROMVAR_PA1HIB0: *result = siba->siba_sprom.pa1hib0; break; case SIBA_SPROMVAR_PA1HIB1: *result = siba->siba_sprom.pa1hib1; break; case SIBA_SPROMVAR_PA1HIB2: *result = siba->siba_sprom.pa1hib2; break; case SIBA_SPROMVAR_GPIO0: *result = siba->siba_sprom.gpio0; break; case SIBA_SPROMVAR_GPIO1: *result = siba->siba_sprom.gpio1; break; case SIBA_SPROMVAR_GPIO2: *result = siba->siba_sprom.gpio2; break; case SIBA_SPROMVAR_GPIO3: *result = siba->siba_sprom.gpio3; break; case SIBA_SPROMVAR_MAXPWR_AL: *result = siba->siba_sprom.maxpwr_al; break; case SIBA_SPROMVAR_MAXPWR_A: *result = siba->siba_sprom.maxpwr_a; break; case SIBA_SPROMVAR_MAXPWR_AH: *result = siba->siba_sprom.maxpwr_ah; break; case SIBA_SPROMVAR_MAXPWR_BG: *result = siba->siba_sprom.maxpwr_bg; break; case SIBA_SPROMVAR_RXPO2G: *result = siba->siba_sprom.rxpo2g; break; case SIBA_SPROMVAR_RXPO5G: *result = siba->siba_sprom.rxpo5g; break; case SIBA_SPROMVAR_TSSI_A: *result = siba->siba_sprom.tssi_a; break; case SIBA_SPROMVAR_TSSI_BG: *result = siba->siba_sprom.tssi_bg; break; case SIBA_SPROMVAR_TRI2G: *result = siba->siba_sprom.tri2g; break; case SIBA_SPROMVAR_TRI5GL: *result = siba->siba_sprom.tri5gl; break; case SIBA_SPROMVAR_TRI5G: *result = siba->siba_sprom.tri5g; break; case SIBA_SPROMVAR_TRI5GH: *result = siba->siba_sprom.tri5gh; break; case SIBA_SPROMVAR_RSSISAV2G: *result = siba->siba_sprom.rssisav2g; break; case SIBA_SPROMVAR_RSSISMC2G: *result = siba->siba_sprom.rssismc2g; break; case SIBA_SPROMVAR_RSSISMF2G: *result = siba->siba_sprom.rssismf2g; break; case SIBA_SPROMVAR_BXA2G: *result = siba->siba_sprom.bxa2g; break; case SIBA_SPROMVAR_RSSISAV5G: *result = siba->siba_sprom.rssisav5g; break; case SIBA_SPROMVAR_RSSISMC5G: *result = siba->siba_sprom.rssismc5g; break; case SIBA_SPROMVAR_RSSISMF5G: *result = siba->siba_sprom.rssismf5g; break; case SIBA_SPROMVAR_BXA5G: *result = siba->siba_sprom.bxa5g; break; case SIBA_SPROMVAR_CCK2GPO: *result = siba->siba_sprom.cck2gpo; break; case SIBA_SPROMVAR_OFDM2GPO: *result = siba->siba_sprom.ofdm2gpo; break; case SIBA_SPROMVAR_OFDM5GLPO: *result = siba->siba_sprom.ofdm5glpo; break; case SIBA_SPROMVAR_OFDM5GPO: *result = siba->siba_sprom.ofdm5gpo; break; case SIBA_SPROMVAR_OFDM5GHPO: *result = siba->siba_sprom.ofdm5ghpo; break; case SIBA_SPROMVAR_BF_LO: *result = siba->siba_sprom.bf_lo; break; case SIBA_SPROMVAR_BF_HI: *result = siba->siba_sprom.bf_hi; break; case SIBA_SPROMVAR_BF2_LO: *result = siba->siba_sprom.bf2_lo; break; case SIBA_SPROMVAR_BF2_HI: *result = siba->siba_sprom.bf2_hi; break; case SIBA_SPROMVAR_FEM_2GHZ_TSSIPOS: *result = siba->siba_sprom.fem.ghz2.tssipos; break; case SIBA_SPROMVAR_FEM_2GHZ_EXTPAGAIN: *result = siba->siba_sprom.fem.ghz2.extpa_gain; break; case SIBA_SPROMVAR_FEM_2GHZ_PDET_RANGE: *result = siba->siba_sprom.fem.ghz2.pdet_range; break; case SIBA_SPROMVAR_FEM_2GHZ_TR_ISO: *result = siba->siba_sprom.fem.ghz2.tr_iso; break; case SIBA_SPROMVAR_FEM_2GHZ_ANTSWLUT: *result = siba->siba_sprom.fem.ghz2.antswlut; break; case SIBA_SPROMVAR_FEM_5GHZ_TSSIPOS: *result = siba->siba_sprom.fem.ghz5.tssipos; break; case SIBA_SPROMVAR_FEM_5GHZ_EXTPAGAIN: *result = siba->siba_sprom.fem.ghz5.extpa_gain; break; case SIBA_SPROMVAR_FEM_5GHZ_PDET_RANGE: *result = siba->siba_sprom.fem.ghz5.pdet_range; break; case SIBA_SPROMVAR_FEM_5GHZ_TR_ISO: *result = siba->siba_sprom.fem.ghz5.tr_iso; break; case SIBA_SPROMVAR_FEM_5GHZ_ANTSWLUT: *result = siba->siba_sprom.fem.ghz5.antswlut; break; default: return (ENOENT); } return (0); } int siba_write_sprom(device_t dev, device_t child, int which, uintptr_t value) { struct siba_dev_softc *sd = device_get_ivars(child); struct siba_softc *siba = sd->sd_bus; switch (which) { case SIBA_SPROMVAR_REV: siba->siba_sprom.rev = value; break; case SIBA_SPROMVAR_MII_ETH0: siba->siba_sprom.mii_eth0 = value; break; case SIBA_SPROMVAR_MII_ETH1: siba->siba_sprom.mii_eth1 = value; break; case SIBA_SPROMVAR_MDIO_ETH0: siba->siba_sprom.mdio_eth0 = value; break; case SIBA_SPROMVAR_MDIO_ETH1: siba->siba_sprom.mdio_eth1 = value; break; case SIBA_SPROMVAR_BREV: siba->siba_sprom.brev = value; break; case SIBA_SPROMVAR_CCODE: siba->siba_sprom.ccode = value; break; case SIBA_SPROMVAR_ANT_A: siba->siba_sprom.ant_a = value; break; case SIBA_SPROMVAR_ANT_BG: siba->siba_sprom.ant_bg = value; break; case SIBA_SPROMVAR_PA0B0: siba->siba_sprom.pa0b0 = value; break; case SIBA_SPROMVAR_PA0B1: siba->siba_sprom.pa0b1 = value; break; case SIBA_SPROMVAR_PA0B2: siba->siba_sprom.pa0b2 = value; break; case SIBA_SPROMVAR_PA1B0: siba->siba_sprom.pa1b0 = value; break; case SIBA_SPROMVAR_PA1B1: siba->siba_sprom.pa1b1 = value; break; case SIBA_SPROMVAR_PA1B2: siba->siba_sprom.pa1b2 = value; break; case SIBA_SPROMVAR_PA1LOB0: siba->siba_sprom.pa1lob0 = value; break; case SIBA_SPROMVAR_PA1LOB1: siba->siba_sprom.pa1lob1 = value; break; case SIBA_SPROMVAR_PA1LOB2: siba->siba_sprom.pa1lob2 = value; break; case SIBA_SPROMVAR_PA1HIB0: siba->siba_sprom.pa1hib0 = value; break; case SIBA_SPROMVAR_PA1HIB1: siba->siba_sprom.pa1hib1 = value; break; case SIBA_SPROMVAR_PA1HIB2: siba->siba_sprom.pa1hib2 = value; break; case SIBA_SPROMVAR_GPIO0: siba->siba_sprom.gpio0 = value; break; case SIBA_SPROMVAR_GPIO1: siba->siba_sprom.gpio1 = value; break; case SIBA_SPROMVAR_GPIO2: siba->siba_sprom.gpio2 = value; break; case SIBA_SPROMVAR_GPIO3: siba->siba_sprom.gpio3 = value; break; case SIBA_SPROMVAR_MAXPWR_AL: siba->siba_sprom.maxpwr_al = value; break; case SIBA_SPROMVAR_MAXPWR_A: siba->siba_sprom.maxpwr_a = value; break; case SIBA_SPROMVAR_MAXPWR_AH: siba->siba_sprom.maxpwr_ah = value; break; case SIBA_SPROMVAR_MAXPWR_BG: siba->siba_sprom.maxpwr_bg = value; break; case SIBA_SPROMVAR_RXPO2G: siba->siba_sprom.rxpo2g = value; break; case SIBA_SPROMVAR_RXPO5G: siba->siba_sprom.rxpo5g = value; break; case SIBA_SPROMVAR_TSSI_A: siba->siba_sprom.tssi_a = value; break; case SIBA_SPROMVAR_TSSI_BG: siba->siba_sprom.tssi_bg = value; break; case SIBA_SPROMVAR_TRI2G: siba->siba_sprom.tri2g = value; break; case SIBA_SPROMVAR_TRI5GL: siba->siba_sprom.tri5gl = value; break; case SIBA_SPROMVAR_TRI5G: siba->siba_sprom.tri5g = value; break; case SIBA_SPROMVAR_TRI5GH: siba->siba_sprom.tri5gh = value; break; case SIBA_SPROMVAR_RSSISAV2G: siba->siba_sprom.rssisav2g = value; break; case SIBA_SPROMVAR_RSSISMC2G: siba->siba_sprom.rssismc2g = value; break; case SIBA_SPROMVAR_RSSISMF2G: siba->siba_sprom.rssismf2g = value; break; case SIBA_SPROMVAR_BXA2G: siba->siba_sprom.bxa2g = value; break; case SIBA_SPROMVAR_RSSISAV5G: siba->siba_sprom.rssisav5g = value; break; case SIBA_SPROMVAR_RSSISMC5G: siba->siba_sprom.rssismc5g = value; break; case SIBA_SPROMVAR_RSSISMF5G: siba->siba_sprom.rssismf5g = value; break; case SIBA_SPROMVAR_BXA5G: siba->siba_sprom.bxa5g = value; break; case SIBA_SPROMVAR_CCK2GPO: siba->siba_sprom.cck2gpo = value; break; case SIBA_SPROMVAR_OFDM2GPO: siba->siba_sprom.ofdm2gpo = value; break; case SIBA_SPROMVAR_OFDM5GLPO: siba->siba_sprom.ofdm5glpo = value; break; case SIBA_SPROMVAR_OFDM5GPO: siba->siba_sprom.ofdm5gpo = value; break; case SIBA_SPROMVAR_OFDM5GHPO: siba->siba_sprom.ofdm5ghpo = value; break; case SIBA_SPROMVAR_BF_LO: siba->siba_sprom.bf_lo = value; break; case SIBA_SPROMVAR_BF_HI: siba->siba_sprom.bf_hi = value; break; case SIBA_SPROMVAR_BF2_LO: siba->siba_sprom.bf2_lo = value; break; case SIBA_SPROMVAR_BF2_HI: siba->siba_sprom.bf2_hi = value; break; default: return (ENOENT); } return (0); } #define SIBA_GPIOCTL 0x06c uint32_t siba_gpio_get(device_t dev) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; struct siba_dev_softc *gpiodev, *pcidev = NULL; pcidev = siba->siba_pci.spc_dev; gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev; if (!gpiodev) return (-1); return (siba_read_4_sub(gpiodev, SIBA_GPIOCTL)); } void siba_gpio_set(device_t dev, uint32_t value) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; struct siba_dev_softc *gpiodev, *pcidev = NULL; pcidev = siba->siba_pci.spc_dev; gpiodev = siba->siba_cc.scc_dev ? siba->siba_cc.scc_dev : pcidev; if (!gpiodev) return; siba_write_4_sub(gpiodev, SIBA_GPIOCTL, value); } void siba_fix_imcfglobug(device_t dev) { struct siba_dev_softc *sd = device_get_ivars(dev); struct siba_softc *siba = sd->sd_bus; uint32_t tmp; if (siba->siba_pci.spc_dev == NULL) return; if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI || siba->siba_pci.spc_dev->sd_id.sd_rev > 5) return; tmp = siba_read_4_sub(sd, SIBA_IMCFGLO) & ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO); switch (siba->siba_type) { case SIBA_TYPE_PCI: case SIBA_TYPE_PCMCIA: tmp |= 0x32; break; case SIBA_TYPE_SSB: tmp |= 0x53; break; } siba_write_4_sub(sd, SIBA_IMCFGLO, tmp); } + +int +siba_sprom_get_core_power_info(device_t dev, int core, + struct siba_sprom_core_pwr_info *c) +{ + struct siba_dev_softc *sd = device_get_ivars(dev); + struct siba_softc *siba = sd->sd_bus; + + if (core < 0 || core > 3) { + return (EINVAL); + } + memcpy(c, &siba->siba_sprom.core_pwr_info[core], sizeof(*c)); + return (0); +} + Index: head/sys/dev/siba/sibareg.h =================================================================== --- head/sys/dev/siba/sibareg.h (revision 299408) +++ head/sys/dev/siba/sibareg.h (revision 299409) @@ -1,471 +1,547 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * 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. * * $FreeBSD$ */ /* * TODO: sprom * TODO: implement dma translation bits (if needed for system bus) */ #ifndef _SIBA_SIBAREG_H_ #define _SIBA_SIBAREG_H_ #define PCI_DEVICE_ID_BCM4401 0x4401 #define PCI_DEVICE_ID_BCM4401B0 0x4402 #define PCI_DEVICE_ID_BCM4401B1 0x170c #define SIBA_PCIR_BAR PCIR_BAR(0) #define SIBA_CCID_BCM4710 0x4710 #define SIBA_CCID_BCM4704 0x4704 #define SIBA_CCID_SENTRY5 0x5365 /* * ChipCommon registers. */ #define SIBA_CC_CHIPID 0x0000 #define SIBA_CC_IDMASK 0x0000ffff #define SIBA_CC_ID(id) (id & SIBA_CC_IDMASK) #define SIBA_CC_REVMASK 0x000f0000 #define SIBA_CC_REVSHIFT 16 #define SIBA_CC_REV(id) \ ((id & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT) #define SIBA_CC_PKGMASK 0x00F00000 #define SIBA_CC_PKGSHIFT 20 #define SIBA_CC_PKG(id) \ ((id & SIBA_CC_PKGMASK) >> SIBA_CC_PKGSHIFT) #define SIBA_CC_NCORESMASK 0x0F000000 #define SIBA_CC_NCORESSHIFT 24 #define SIBA_CC_NCORES(id) \ ((id & SIBA_CC_NCORESMASK) >> SIBA_CC_NCORESSHIFT) #define SIBA_CC_CAPS 0x0004 #define SIBA_CC_CAPS_PWCTL 0x00040000 #define SIBA_CC_CAPS_PMU 0x10000000 /* PMU (rev >= 20) */ #define SIBA_CC_CHIPCTL 0x0028 /* rev >= 11 */ #define SIBA_CC_CHIPSTAT 0x002C /* rev >= 11 */ #define SIBA_CC_BCAST_ADDR 0x0050 /* Broadcast Address */ #define SIBA_CC_BCAST_DATA 0x0054 /* Broadcast Data */ #define SIBA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */ #define SIBA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ #define SIBA_CC_CLKSLOW 0x00b8 /* 6 <= Rev <= 9 only */ #define SIBA_CC_CLKSLOW_SRC 0x00000007 #define SIBA_CC_CLKSLOW_SRC_CRYSTAL 0x00000001 #define SIBA_CC_CLKSLOW_FSLOW 0x00000800 #define SIBA_CC_CLKSLOW_IPLL 0x00001000 #define SIBA_CC_CLKSLOW_ENXTAL 0x00002000 #define SIBA_CC_CLKSYSCTL 0x00C0 /* Rev >= 3 only */ #define SIBA_CC_CLKCTLSTATUS 0x01e0 #define SIBA_CC_CLKCTLSTATUS_HT 0x00010000 #define SIBA_CC_UART0 0x0300 /* offset of UART0 */ #define SIBA_CC_UART1 0x0400 /* offset of UART1 */ #define SIBA_CC_PMUCTL 0x0600 /* PMU control */ #define SIBA_CC_PMUCTL_ILP 0xffff0000 /* mask */ #define SIBA_CC_PMUCTL_NOILP 0x00000200 #define SIBA_CC_PMUCTL_XF 0x0000007c /* crystal freq */ #define SIBA_CC_PMUCTL_XF_VAL(id) ((id & 0x0000007c) >> 2) #define SIBA_CC_PMUCAPS 0x0604 #define SIBA_CC_PMUCAPS_REV 0x000000ff #define SIBA_CC_PMU_MINRES 0x0618 #define SIBA_CC_PMU_MAXRES 0x061c #define SIBA_CC_PMU_TABSEL 0x0620 #define SIBA_CC_PMU_DEPMSK 0x0624 #define SIBA_CC_PMU_UPDNTM 0x0628 #define SIBA_CC_REGCTL_ADDR 0x0658 #define SIBA_CC_REGCTL_DATA 0x065c #define SIBA_CC_PLLCTL_ADDR 0x0660 #define SIBA_CC_PLLCTL_DATA 0x0664 #define SIBA_CC_PMU0_PLL0 0 #define SIBA_CC_PMU0_PLL0_PDIV_MSK 0x00000001 #define SIBA_CC_PMU0_PLL0_PDIV_FREQ 25000 #define SIBA_CC_PMU0_PLL1 1 #define SIBA_CC_PMU0_PLL1_IMSK 0xf0000000 #define SIBA_CC_PMU0_PLL1_FMSK 0x0fffff00 #define SIBA_CC_PMU0_PLL1_STOPMOD 0x00000040 #define SIBA_CC_PMU0_PLL2 2 #define SIBA_CC_PMU0_PLL2_IMSKHI 0x0000000f #define SIBA_CC_PMU1_PLL0 0 #define SIBA_CC_PMU1_PLL0_P1DIV 0x00f00000 #define SIBA_CC_PMU1_PLL0_P2DIV 0x0f000000 #define SIBA_CC_PMU1_PLL2 2 #define SIBA_CC_PMU1_PLL2_NDIVMODE 0x000e0000 #define SIBA_CC_PMU1_PLL2_NDIVINT 0x1ff00000 #define SIBA_CC_PMU1_PLL3 3 #define SIBA_CC_PMU1_PLL3_NDIVFRAC 0x00ffffff #define SIBA_CC_PMU1_PLL5 5 #define SIBA_CC_PMU1_PLL5_CLKDRV 0xffffff00 #define SIBA_CC_PMU0_DEFAULT_XTALFREQ 20000 #define SIBA_CC_PMU1_DEFAULT_FREQ 15360 #define SIBA_CC_PMU1_PLLTAB_ENTRY \ { \ { 12000, 1, 3, 22, 0x9, 0xffffef }, \ { 13000, 2, 1, 6, 0xb, 0x483483 }, \ { 14400, 3, 1, 10, 0xa, 0x1c71c7 }, \ { 15360, 4, 1, 5, 0xb, 0x755555 }, \ { 16200, 5, 1, 10, 0x5, 0x6e9e06 }, \ { 16800, 6, 1, 10, 0x5, 0x3cf3cf }, \ { 19200, 7, 1, 9, 0x5, 0x17b425 }, \ { 19800, 8, 1, 11, 0x4, 0xa57eb }, \ { 20000, 9, 1, 11, 0x4, 0 }, \ { 24000, 10, 3, 11, 0xa, 0 }, \ { 25000, 11, 5, 16, 0xb, 0 }, \ { 26000, 12, 1, 2, 0x10, 0xec4ec4 }, \ { 30000, 13, 3, 8, 0xb, 0 }, \ { 38400, 14, 1, 5, 0x4, 0x955555 }, \ { 40000, 15, 1, 2, 0xb, 0 } \ } #define SIBA_CC_PMU0_PLLTAB_ENTRY \ { \ { 12000, 1, 73, 349525, }, { 13000, 2, 67, 725937, }, \ { 14400, 3, 61, 116508, }, { 15360, 4, 57, 305834, }, \ { 16200, 5, 54, 336579, }, { 16800, 6, 52, 399457, }, \ { 19200, 7, 45, 873813, }, { 19800, 8, 44, 466033, }, \ { 20000, 9, 44, 0, }, { 25000, 10, 70, 419430, }, \ { 26000, 11, 67, 725937, }, { 30000, 12, 58, 699050, }, \ { 38400, 13, 45, 873813, }, { 40000, 14, 45, 0, }, \ } #define SIBA_CC_PMU_4312_PA_REF 2 #define SIBA_CC_PMU_4325_BURST 1 #define SIBA_CC_PMU_4325_CLBURST 3 #define SIBA_CC_PMU_4325_LN 10 #define SIBA_CC_PMU_4325_CRYSTAL 13 #define SIBA_CC_PMU_4325_RX_PWR 15 #define SIBA_CC_PMU_4325_TX_PWR 16 #define SIBA_CC_PMU_4325_LOGEN_PWR 18 #define SIBA_CC_PMU_4325_AFE_PWR 19 #define SIBA_CC_PMU_4325_BBPLL_PWR 20 #define SIBA_CC_PMU_4325_HT 21 #define SIBA_CC_PMU_4328_EXT_SWITCH_PWM 0 #define SIBA_CC_PMU_4328_BB_SWITCH_PWM 1 #define SIBA_CC_PMU_4328_BB_SWITCH_BURST 2 #define SIBA_CC_PMU_4328_BB_EXT_SWITCH_BURST 3 #define SIBA_CC_PMU_4328_ILP_REQUEST 4 #define SIBA_CC_PMU_4328_RADSWITCH_PWM 5 /* radio switch */ #define SIBA_CC_PMU_4328_RADSWITCH_BURST 6 #define SIBA_CC_PMU_4328_ROM_SWITCH 7 #define SIBA_CC_PMU_4328_PA_REF 8 #define SIBA_CC_PMU_4328_RADIO 9 #define SIBA_CC_PMU_4328_AFE 10 #define SIBA_CC_PMU_4328_PLL 11 #define SIBA_CC_PMU_4328_BG_FILTBYP 12 #define SIBA_CC_PMU_4328_TX_FILTBYP 13 #define SIBA_CC_PMU_4328_RX_FILTBYP 14 #define SIBA_CC_PMU_4328_CRYSTAL_PU 15 #define SIBA_CC_PMU_4328_CRYSTAL_EN 16 #define SIBA_CC_PMU_4328_BB_PLL_FILTBYP 17 #define SIBA_CC_PMU_4328_RF_PLL_FILTBYP 18 #define SIBA_CC_PMU_4328_BB_PLL_PU 19 #define SIBA_CC_PMU_5354_PA_REF 8 #define SIBA_CC_PMU_5354_BB_PLL_PU 19 #define SIBA_CC_PMU_4325_RES_UPDOWN \ { \ { SIBA_CC_PMU_4325_CRYSTAL, 0x1501 } \ } #define SIBA_CC_PMU_4325_RES_DEPEND \ { \ { SIBA_CC_PMU_4325_HT, SIBA_CC_PMU_DEP_ADD, \ ((1 << SIBA_CC_PMU_4325_RX_PWR) | \ (1 << SIBA_CC_PMU_4325_TX_PWR) | \ (1 << SIBA_CC_PMU_4325_LOGEN_PWR) | \ (1 << SIBA_CC_PMU_4325_AFE_PWR)) } \ } #define SIBA_CC_PMU_4328_RES_UPDOWN \ { \ { SIBA_CC_PMU_4328_EXT_SWITCH_PWM, 0x0101 }, \ { SIBA_CC_PMU_4328_BB_SWITCH_PWM, 0x1f01 }, \ { SIBA_CC_PMU_4328_BB_SWITCH_BURST, 0x010f }, \ { SIBA_CC_PMU_4328_BB_EXT_SWITCH_BURST, 0x0101 }, \ { SIBA_CC_PMU_4328_ILP_REQUEST, 0x0202 }, \ { SIBA_CC_PMU_4328_RADSWITCH_PWM, 0x0f01 }, \ { SIBA_CC_PMU_4328_RADSWITCH_BURST, 0x0f01 }, \ { SIBA_CC_PMU_4328_ROM_SWITCH, 0x0101 }, \ { SIBA_CC_PMU_4328_PA_REF, 0x0f01 }, \ { SIBA_CC_PMU_4328_RADIO, 0x0f01 }, \ { SIBA_CC_PMU_4328_AFE, 0x0f01 }, \ { SIBA_CC_PMU_4328_PLL, 0x0f01 }, \ { SIBA_CC_PMU_4328_BG_FILTBYP, 0x0101 }, \ { SIBA_CC_PMU_4328_TX_FILTBYP, 0x0101 }, \ { SIBA_CC_PMU_4328_RX_FILTBYP, 0x0101 }, \ { SIBA_CC_PMU_4328_CRYSTAL_PU, 0x0101 }, \ { SIBA_CC_PMU_4328_CRYSTAL_EN, 0xa001 }, \ { SIBA_CC_PMU_4328_BB_PLL_FILTBYP, 0x0101 }, \ { SIBA_CC_PMU_4328_RF_PLL_FILTBYP, 0x0101 }, \ { SIBA_CC_PMU_4328_BB_PLL_PU, 0x0701 }, \ } #define SIBA_CC_PMU_4328_RES_DEPEND \ { \ { SIBA_CC_PMU_4328_ILP_REQUEST, SIBA_CC_PMU_DEP_SET, \ ((1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) | \ (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM)) }, \ } #define SIBA_CC_CHST_4325_PMUTOP_2B 0x00000200 #define SIBA_BAR0 0x80 #define SIBA_IRQMASK 0x94 #define SIBA_GPIO_IN 0xb0 #define SIBA_GPIO_OUT 0xb4 #define SIBA_GPIO_OUT_EN 0xb8 #define SIBA_GPIO_CRYSTAL 0x40 #define SIBA_GPIO_PLL 0x80 #define SIBA_REGWIN(x) \ (SIBA_ENUM_START + ((x) * SIBA_CORE_LEN)) #define SIBA_CORE_LEN 0x00001000 /* Size of cfg per core */ #define SIBA_CFG_END 0x00010000 /* Upper bound of cfg space */ #define SIBA_MAX_CORES (SIBA_CFG_END/SIBA_CORE_LEN) /* #max cores */ #define SIBA_ENUM_START 0x18000000U #define SIBA_ENUM_END 0x18010000U #define SIBA_DMA_TRANSLATION_MASK 0xc0000000 #define SIBA_PCI_DMA 0x40000000U #define SIBA_TPS 0x0f18 #define SIBA_TPS_BPFLAG 0x0000003f #define SIBA_IAS 0x0f90 /* Initiator Agent State */ #define SIBA_IAS_INBAND_ERR 0x00020000 #define SIBA_IAS_TIMEOUT 0x00040000 #define SIBA_INTR_MASK 0x0f94 #define SIBA_TGSLOW 0x0f98 #define SIBA_TGSLOW_RESET 0x00000001 /* target state low */ #define SIBA_TGSLOW_REJECT_22 0x00000002 #define SIBA_TGSLOW_REJECT_23 0x00000004 #define SIBA_TGSLOW_CLOCK 0x00010000 #define SIBA_TGSLOW_FGC 0x00020000 #define SIBA_TGSHIGH 0x0f9c #define SIBA_TGSHIGH_SERR 0x00000001 #define SIBA_TGSHIGH_BUSY 0x00000004 #define SIBA_TGSHIGH_DMA64 0x10000000 #define SIBA_IMCFGLO 0x0fa8 #define SIBA_IMCFGLO_SERTO 0x00000007 #define SIBA_IMCFGLO_REQTO 0x00000070 #define SIBA_IDLOW 0x0ff8 #define SIBA_IDLOW_SSBREV 0xf0000000 #define SIBA_IDLOW_SSBREV_22 0x00000000 #define SIBA_IDLOW_SSBREV_23 0x10000000 #define SIBA_IDLOW_SSBREV_24 0x40000000 #define SIBA_IDLOW_SSBREV_25 0x50000000 #define SIBA_IDLOW_SSBREV_26 0x60000000 #define SIBA_IDLOW_SSBREV_27 0x70000000 #define SIBA_IDHIGH 0x0ffc #define SIBA_IDHIGH_CORECODEMASK 0x00008FF0 /* Core Code */ #define SIBA_IDHIGH_CORECODE_SHIFT 4 #define SIBA_IDHIGH_CORECODE(id) \ ((id & SIBA_IDHIGH_CORECODEMASK) >> SIBA_IDHIGH_CORECODE_SHIFT) /* Revision Code (low part) */ #define SIBA_IDHIGH_REVLO 0x0000000f /* Revision Code (high part) */ #define SIBA_IDHIGH_REVHI 0x00007000 #define SIBA_IDHIGH_REVHI_SHIFT 8 #define SIBA_IDHIGH_REV(id) \ ((id & SIBA_IDHIGH_REVLO) | ((id & SIBA_IDHIGH_REVHI) >> \ - SIBA_IDHIGH_REVHI_SHIFT)) + SIBA_IDHIGH_REVHI_SHIFT)) #define SIBA_IDHIGH_VENDORMASK 0xFFFF0000 /* Vendor Code */ #define SIBA_IDHIGH_VENDOR_SHIFT 16 #define SIBA_IDHIGH_VENDOR(id) \ ((id & SIBA_IDHIGH_VENDORMASK) >> SIBA_IDHIGH_VENDOR_SHIFT) #define SIBA_SPROMSIZE_R123 64 #define SIBA_SPROMSIZE_R4 220 #define SIBA_SPROM_BASE 0x1000 #define SIBA_SPROM_REV_CRC 0xff00 + #define SIBA_SPROM1_MAC_80211BG 0x1048 #define SIBA_SPROM1_MAC_ETH 0x104e #define SIBA_SPROM1_MAC_80211A 0x1054 #define SIBA_SPROM1_ETHPHY 0x105a #define SIBA_SPROM1_ETHPHY_MII_ETH0 0x001f #define SIBA_SPROM1_ETHPHY_MII_ETH1 0x03e0 #define SIBA_SPROM1_ETHPHY_MDIO_ETH0 (1 << 14) #define SIBA_SPROM1_ETHPHY_MDIO_ETH1 (1 << 15) #define SIBA_SPROM1_BOARDINFO 0x105c #define SIBA_SPROM1_BOARDINFO_BREV 0x00ff #define SIBA_SPROM1_BOARDINFO_CCODE 0x0f00 #define SIBA_SPROM1_BOARDINFO_ANTBG 0x3000 #define SIBA_SPROM1_BOARDINFO_ANTA 0xc000 #define SIBA_SPROM1_PA0B0 0x105e #define SIBA_SPROM1_PA0B1 0x1060 #define SIBA_SPROM1_PA0B2 0x1062 #define SIBA_SPROM1_GPIOA 0x1064 #define SIBA_SPROM1_GPIOA_P0 0x00ff #define SIBA_SPROM1_GPIOA_P1 0xff00 #define SIBA_SPROM1_GPIOB 0x1066 #define SIBA_SPROM1_GPIOB_P2 0x00ff #define SIBA_SPROM1_GPIOB_P3 0xff00 #define SIBA_SPROM1_MAXPWR 0x1068 #define SIBA_SPROM1_MAXPWR_BG 0x00ff #define SIBA_SPROM1_MAXPWR_A 0xff00 #define SIBA_SPROM1_PA1B0 0x106a #define SIBA_SPROM1_PA1B1 0x106c #define SIBA_SPROM1_PA1B2 0x106e #define SIBA_SPROM1_TSSI 0x1070 #define SIBA_SPROM1_TSSI_BG 0x00ff #define SIBA_SPROM1_TSSI_A 0xff00 #define SIBA_SPROM1_BFLOW 0x1072 #define SIBA_SPROM1_AGAIN 0x1074 #define SIBA_SPROM1_AGAIN_BG 0x00ff #define SIBA_SPROM1_AGAIN_A 0xff00 + #define SIBA_SPROM2_BFHIGH 0x1038 + #define SIBA_SPROM3_MAC_80211BG 0x104a + #define SIBA_SPROM4_MAC_80211BG 0x104c #define SIBA_SPROM4_ETHPHY 0x105a #define SIBA_SPROM4_ETHPHY_ET0A 0x001f #define SIBA_SPROM4_ETHPHY_ET1A 0x03e0 #define SIBA_SPROM4_CCODE 0x1052 #define SIBA_SPROM4_ANTAVAIL 0x105d #define SIBA_SPROM4_ANTAVAIL_A 0x00ff #define SIBA_SPROM4_ANTAVAIL_BG 0xff00 #define SIBA_SPROM4_BFLOW 0x1044 #define SIBA_SPROM4_AGAIN01 0x105e #define SIBA_SPROM4_AGAIN0 0x00ff #define SIBA_SPROM4_AGAIN1 0xff00 #define SIBA_SPROM4_AGAIN23 0x1060 #define SIBA_SPROM4_AGAIN2 0x00ff #define SIBA_SPROM4_AGAIN3 0xff00 #define SIBA_SPROM4_BFHIGH 0x1046 #define SIBA_SPROM4_MAXP_BG 0x1080 #define SIBA_SPROM4_MAXP_BG_MASK 0x00ff #define SIBA_SPROM4_TSSI_BG 0xff00 #define SIBA_SPROM4_MAXP_A 0x108a #define SIBA_SPROM4_MAXP_A_MASK 0x00ff #define SIBA_SPROM4_TSSI_A 0xff00 #define SIBA_SPROM4_GPIOA 0x1056 #define SIBA_SPROM4_GPIOA_P0 0x00ff #define SIBA_SPROM4_GPIOA_P1 0xff00 #define SIBA_SPROM4_GPIOB 0x1058 #define SIBA_SPROM4_GPIOB_P2 0x00ff #define SIBA_SPROM4_GPIOB_P3 0xff00 + +/* The following four blocks share the same structure */ +#define SIBA_SPROM4_PWR_INFO_CORE0 0x0080 +#define SIBA_SPROM4_PWR_INFO_CORE1 0x00AE +#define SIBA_SPROM4_PWR_INFO_CORE2 0x00DC +#define SIBA_SPROM4_PWR_INFO_CORE3 0x010A + +#define SIBA_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */ +#define SIBA_SPROM4_2G_MAXP 0x00FF +#define SIBA_SPROM4_2G_ITSSI 0xFF00 +#define SIBA_SPROM4_2G_ITSSI_SHIFT 8 +#define SIBA_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */ +#define SIBA_SPROM4_2G_PA_1 0x04 +#define SIBA_SPROM4_2G_PA_2 0x06 +#define SIBA_SPROM4_2G_PA_3 0x08 +#define SIBA_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */ +#define SIBA_SPROM4_5G_MAXP 0x00FF +#define SIBA_SPROM4_5G_ITSSI 0xFF00 +#define SIBA_SPROM4_5G_ITSSI_SHIFT 8 +#define SIBA_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */ +#define SIBA_SPROM4_5GH_MAXP 0x00FF +#define SIBA_SPROM4_5GL_MAXP 0xFF00 +#define SIBA_SPROM4_5GL_MAXP_SHIFT 8 +#define SIBA_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */ +#define SIBA_SPROM4_5G_PA_1 0x10 +#define SIBA_SPROM4_5G_PA_2 0x12 +#define SIBA_SPROM4_5G_PA_3 0x14 +#define SIBA_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */ +#define SIBA_SPROM4_5GL_PA_1 0x18 +#define SIBA_SPROM4_5GL_PA_2 0x1A +#define SIBA_SPROM4_5GL_PA_3 0x1C +#define SIBA_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */ +#define SIBA_SPROM4_5GH_PA_1 0x20 +#define SIBA_SPROM4_5GH_PA_2 0x22 +#define SIBA_SPROM4_5GH_PA_3 0x24 + #define SIBA_SPROM5_BFLOW 0x104a #define SIBA_SPROM5_BFHIGH 0x104c #define SIBA_SPROM5_MAC_80211BG 0x1052 #define SIBA_SPROM5_CCODE 0x1044 #define SIBA_SPROM5_GPIOA 0x1076 #define SIBA_SPROM5_GPIOA_P0 0x00ff #define SIBA_SPROM5_GPIOA_P1 0xff00 #define SIBA_SPROM5_GPIOB 0x1078 #define SIBA_SPROM5_GPIOB_P2 0x00ff #define SIBA_SPROM5_GPIOB_P3 0xff00 + #define SIBA_SPROM8_BFLOW 0x1084 #define SIBA_SPROM8_BFHIGH 0x1086 #define SIBA_SPROM8_BFL2LO 0x1088 #define SIBA_SPROM8_BFL2HI 0x108a #define SIBA_SPROM8_MAC_80211BG 0x108c #define SIBA_SPROM8_CCODE 0x1092 #define SIBA_SPROM8_ANTAVAIL 0x109c #define SIBA_SPROM8_ANTAVAIL_A 0xff00 #define SIBA_SPROM8_ANTAVAIL_BG 0x00ff #define SIBA_SPROM8_AGAIN01 0x109e #define SIBA_SPROM8_AGAIN0 0x00ff #define SIBA_SPROM8_AGAIN1 0xff00 #define SIBA_SPROM8_GPIOA 0x1096 #define SIBA_SPROM8_GPIOA_P0 0x00ff #define SIBA_SPROM8_GPIOA_P1 0xff00 #define SIBA_SPROM8_GPIOB 0x1098 #define SIBA_SPROM8_GPIOB_P2 0x00ff #define SIBA_SPROM8_GPIOB_P3 0xff00 #define SIBA_SPROM8_AGAIN23 0x10a0 #define SIBA_SPROM8_AGAIN2 0x00ff #define SIBA_SPROM8_AGAIN3 0xff00 #define SIBA_SPROM8_RSSIPARM2G 0x10a4 #define SIBA_SPROM8_RSSISMF2G 0x000f #define SIBA_SPROM8_RSSISMC2G 0x00f0 #define SIBA_SPROM8_RSSISAV2G 0x0700 /* BITMASK */ #define SIBA_SPROM8_BXA2G 0x1800 /* BITMASK */ #define SIBA_SPROM8_RSSIPARM5G 0x10a6 #define SIBA_SPROM8_RSSISMF5G 0x000f #define SIBA_SPROM8_RSSISMC5G 0x00f0 #define SIBA_SPROM8_RSSISAV5G 0x0700 /* BITMASK */ #define SIBA_SPROM8_BXA5G 0x1800 /* BITMASK */ #define SIBA_SPROM8_TRI25G 0x10a8 #define SIBA_SPROM8_TRI2G 0x00ff #define SIBA_SPROM8_TRI5G 0xff00 #define SIBA_SPROM8_TRI5GHL 0x10aa #define SIBA_SPROM8_TRI5GL 0x00ff #define SIBA_SPROM8_TRI5GH 0xff00 #define SIBA_SPROM8_RXPO 0x10ac #define SIBA_SPROM8_RXPO2G 0x00ff #define SIBA_SPROM8_RXPO5G 0xff00 + +/* The FEM blocks share the same structure */ #define SIBA_SPROM8_FEM2G 0x00AE #define SIBA_SPROM8_FEM5G 0x00B0 #define SSB_SROM8_FEM_TSSIPOS 0x0001 #define SSB_SROM8_FEM_EXTPA_GAIN 0x0006 #define SSB_SROM8_FEM_PDET_RANGE 0x00F8 #define SSB_SROM8_FEM_TR_ISO 0x0700 #define SSB_SROM8_FEM_ANTSWLUT 0xF800 + #define SIBA_SPROM8_MAXP_BG 0x10c0 #define SIBA_SPROM8_MAXP_BG_MASK 0x00ff #define SIBA_SPROM8_TSSI_BG 0xff00 #define SIBA_SPROM8_PA0B0 0x10c2 #define SIBA_SPROM8_PA0B1 0x10c4 #define SIBA_SPROM8_PA0B2 0x10c6 #define SIBA_SPROM8_MAXP_A 0x10c8 #define SIBA_SPROM8_MAXP_A_MASK 0x00ff #define SIBA_SPROM8_TSSI_A 0xff00 #define SIBA_SPROM8_MAXP_AHL 0x10ca #define SIBA_SPROM8_MAXP_AH_MASK 0x00ff #define SIBA_SPROM8_MAXP_AL_MASK 0xff00 #define SIBA_SPROM8_PA1B0 0x10cc #define SIBA_SPROM8_PA1B1 0x10ce #define SIBA_SPROM8_PA1B2 0x10d0 #define SIBA_SPROM8_PA1LOB0 0x10d2 #define SIBA_SPROM8_PA1LOB1 0x10d4 #define SIBA_SPROM8_PA1LOB2 0x10d6 #define SIBA_SPROM8_PA1HIB0 0x10d8 #define SIBA_SPROM8_PA1HIB1 0x10da #define SIBA_SPROM8_PA1HIB2 0x10dc #define SIBA_SPROM8_CCK2GPO 0x1140 #define SIBA_SPROM8_OFDM2GPO 0x1142 #define SIBA_SPROM8_OFDM5GPO 0x1146 #define SIBA_SPROM8_OFDM5GLPO 0x114a #define SIBA_SPROM8_OFDM5GHPO 0x114e +/* There are 4 blocks with power info sharing the same layout */ +#define SIBA_SROM8_PWR_INFO_CORE0 0x00C0 +#define SIBA_SROM8_PWR_INFO_CORE1 0x00E0 +#define SIBA_SROM8_PWR_INFO_CORE2 0x0100 +#define SIBA_SROM8_PWR_INFO_CORE3 0x0120 + +#define SIBA_SROM8_2G_MAXP_ITSSI 0x00 +#define SIBA_SPROM8_2G_MAXP 0x00FF +#define SIBA_SPROM8_2G_ITSSI 0xFF00 +#define SIBA_SPROM8_2G_ITSSI_SHIFT 8 +#define SIBA_SROM8_2G_PA_0 0x02 /* 2GHz power amp settings */ +#define SIBA_SROM8_2G_PA_1 0x04 +#define SIBA_SROM8_2G_PA_2 0x06 +#define SIBA_SROM8_5G_MAXP_ITSSI 0x08 /* 5GHz ITSSI and 5.3GHz Max Power */ +#define SIBA_SPROM8_5G_MAXP 0x00FF +#define SIBA_SPROM8_5G_ITSSI 0xFF00 +#define SIBA_SPROM8_5G_ITSSI_SHIFT 8 +#define SIBA_SPROM8_5GHL_MAXP 0x0A /* 5.2GHz and 5.8GHz Max Power */ +#define SIBA_SPROM8_5GH_MAXP 0x00FF +#define SIBA_SPROM8_5GL_MAXP 0xFF00 +#define SIBA_SPROM8_5GL_MAXP_SHIFT 8 +#define SIBA_SROM8_5G_PA_0 0x0C /* 5.3GHz power amp settings */ +#define SIBA_SROM8_5G_PA_1 0x0E +#define SIBA_SROM8_5G_PA_2 0x10 +#define SIBA_SROM8_5GL_PA_0 0x12 /* 5.2GHz power amp settings */ +#define SIBA_SROM8_5GL_PA_1 0x14 +#define SIBA_SROM8_5GL_PA_2 0x16 +#define SIBA_SROM8_5GH_PA_0 0x18 /* 5.8GHz power amp settings */ +#define SIBA_SROM8_5GH_PA_1 0x1A +#define SIBA_SROM8_5GH_PA_2 0x1C + #define SIBA_BOARDVENDOR_DELL 0x1028 #define SIBA_BOARDVENDOR_BCM 0x14e4 #define SIBA_BOARD_BCM4309G 0x0421 #define SIBA_BOARD_MP4318 0x044a #define SIBA_BOARD_BU4306 0x0416 #define SIBA_BOARD_BU4309 0x040a +#define SIBA_BOARD_BCM4321 0x046d #define SIBA_PCICORE_BCAST_ADDR SIBA_CC_BCAST_ADDR #define SIBA_PCICORE_BCAST_DATA SIBA_CC_BCAST_DATA #define SIBA_PCICORE_SBTOPCI0 0x0100 #define SIBA_PCICORE_SBTOPCI1 0x0104 #define SIBA_PCICORE_SBTOPCI2 0x0108 #define SIBA_PCICORE_MDIO_CTL 0x0128 #define SIBA_PCICORE_MDIO_DATA 0x012c #define SIBA_PCICORE_SBTOPCI_PREF 0x00000004 #define SIBA_PCICORE_SBTOPCI_BURST 0x00000008 #define SIBA_PCICORE_SBTOPCI_MRM 0x00000020 #define SIBA_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ #endif /* _SIBA_SIBAREG_H_ */ Index: head/sys/dev/siba/sibavar.h =================================================================== --- head/sys/dev/siba/sibavar.h (revision 299408) +++ head/sys/dev/siba/sibavar.h (revision 299409) @@ -1,605 +1,615 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * 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. * * $FreeBSD$ */ #ifndef _SIBA_SIBAVAR_H_ #define _SIBA_SIBAVAR_H_ #include struct siba_softc; struct siba_dev_softc; enum siba_type { SIBA_TYPE_SSB, SIBA_TYPE_PCI, SIBA_TYPE_PCMCIA, }; enum siba_device_ivars { SIBA_IVAR_VENDOR, SIBA_IVAR_DEVICE, SIBA_IVAR_REVID, SIBA_IVAR_CORE_INDEX, SIBA_IVAR_PCI_VENDOR, SIBA_IVAR_PCI_DEVICE, SIBA_IVAR_PCI_SUBVENDOR, SIBA_IVAR_PCI_SUBDEVICE, SIBA_IVAR_PCI_REVID, SIBA_IVAR_CHIPID, SIBA_IVAR_CHIPREV, SIBA_IVAR_CHIPPKG, SIBA_IVAR_TYPE, SIBA_IVAR_CC_PMUFREQ, SIBA_IVAR_CC_CAPS, SIBA_IVAR_CC_POWERDELAY, SIBA_IVAR_PCICORE_REVID }; #define SIBA_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(siba, var, SIBA, ivar, type) SIBA_ACCESSOR(vendor, VENDOR, uint16_t) SIBA_ACCESSOR(device, DEVICE, uint16_t) SIBA_ACCESSOR(revid, REVID, uint8_t) SIBA_ACCESSOR(core_index, CORE_INDEX, uint8_t) SIBA_ACCESSOR(pci_vendor, PCI_VENDOR, uint16_t) SIBA_ACCESSOR(pci_device, PCI_DEVICE, uint16_t) SIBA_ACCESSOR(pci_subvendor, PCI_SUBVENDOR, uint16_t) SIBA_ACCESSOR(pci_subdevice, PCI_SUBDEVICE, uint16_t) SIBA_ACCESSOR(pci_revid, PCI_REVID, uint8_t) SIBA_ACCESSOR(chipid, CHIPID, uint16_t) SIBA_ACCESSOR(chiprev, CHIPREV, uint16_t) SIBA_ACCESSOR(chippkg, CHIPPKG, uint8_t) SIBA_ACCESSOR(type, TYPE, enum siba_type) SIBA_ACCESSOR(cc_pmufreq, CC_PMUFREQ, uint32_t) SIBA_ACCESSOR(cc_caps, CC_CAPS, uint32_t) SIBA_ACCESSOR(cc_powerdelay, CC_POWERDELAY, uint16_t) SIBA_ACCESSOR(pcicore_revid, PCICORE_REVID, uint8_t) #undef SIBA_ACCESSOR /* XXX just for SPROM1? */ enum { SIBA_CCODE_WORLD, SIBA_CCODE_THAILAND, SIBA_CCODE_ISRAEL, SIBA_CCODE_JORDAN, SIBA_CCODE_CHINA, SIBA_CCODE_JAPAN, SIBA_CCODE_USA_CANADA_ANZ, SIBA_CCODE_EUROPE, SIBA_CCODE_USA_LOW, SIBA_CCODE_JAPAN_HIGH, SIBA_CCODE_ALL, SIBA_CCODE_NONE, }; #define siba_mips_read_2(sc, core, reg) \ bus_space_read_2((sc)->siba_mem_bt, (sc)->siba_mem_bh, \ (core * SIBA_CORE_LEN) + (reg)) #define siba_mips_read_4(sc, core, reg) \ bus_space_read_4((sc)->siba_mem_bt, (sc)->siba_mem_bh, \ (core * SIBA_CORE_LEN) + (reg)) #define siba_mips_write_2(sc, core, reg, val) \ bus_space_write_2((sc)->siba_mem_bt, (sc)->siba_mem_bh, \ (core * SIBA_CORE_LEN) + (reg), (val)) #define siba_mips_write_4(sc, core, reg, val) \ bus_space_write_4((sc)->siba_mem_bt, (sc)->siba_mem_bh, \ (core * SIBA_CORE_LEN) + (reg), (val)) #define SIBA_READ_4(siba, reg) \ bus_space_read_4((siba)->siba_mem_bt, (siba)->siba_mem_bh, (reg)) #define SIBA_READ_2(siba, reg) \ bus_space_read_2((siba)->siba_mem_bt, (siba)->siba_mem_bh, (reg)) #define SIBA_READ_MULTI_1(siba, reg, addr, count) \ bus_space_read_multi_1((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_READ_MULTI_2(siba, reg, addr, count) \ bus_space_read_multi_2((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_READ_MULTI_4(siba, reg, addr, count) \ bus_space_read_multi_4((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_WRITE_4(siba, reg, val) \ bus_space_write_4((siba)->siba_mem_bt, (siba)->siba_mem_bh, \ (reg), (val)) #define SIBA_WRITE_2(siba, reg, val) \ bus_space_write_2((siba)->siba_mem_bt, (siba)->siba_mem_bh, \ (reg), (val)) #define SIBA_WRITE_MULTI_1(siba, reg, addr, count) \ bus_space_write_multi_1((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_WRITE_MULTI_2(siba, reg, addr, count) \ bus_space_write_multi_2((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_WRITE_MULTI_4(siba, reg, addr, count) \ bus_space_write_multi_4((siba)->siba_mem_bt, (siba)->siba_mem_bh,\ (reg), (addr), (count)) #define SIBA_BARRIER(siba, flags) \ bus_space_barrier((siba)->siba_mem_bt, (siba)->siba_mem_bh, (0),\ (0), (flags)) #define SIBA_SETBITS_4(siba, reg, bits) \ SIBA_WRITE_4((siba), (reg), SIBA_READ_4((siba), (reg)) | (bits)) #define SIBA_SETBITS_2(siba, reg, bits) \ SIBA_WRITE_2((siba), (reg), SIBA_READ_2((siba), (reg)) | (bits)) #define SIBA_FILT_SETBITS_4(siba, reg, filt, bits) \ SIBA_WRITE_4((siba), (reg), (SIBA_READ_4((siba), \ (reg)) & (filt)) | (bits)) #define SIBA_FILT_SETBITS_2(siba, reg, filt, bits) \ SIBA_WRITE_2((siba), (reg), (SIBA_READ_2((siba), \ (reg)) & (filt)) | (bits)) #define SIBA_CLRBITS_4(siba, reg, bits) \ SIBA_WRITE_4((siba), (reg), SIBA_READ_4((siba), (reg)) & ~(bits)) #define SIBA_CLRBITS_2(siba, reg, bits) \ SIBA_WRITE_2((siba), (reg), SIBA_READ_2((siba), (reg)) & ~(bits)) #define SIBA_CC_READ32(scc, offset) \ siba_read_4_sub((scc)->scc_dev, offset) #define SIBA_CC_WRITE32(scc, offset, val) \ siba_write_4_sub((scc)->scc_dev, offset, val) #define SIBA_CC_MASK32(scc, offset, mask) \ SIBA_CC_WRITE32(scc, offset, SIBA_CC_READ32(scc, offset) & (mask)) #define SIBA_CC_SET32(scc, offset, set) \ SIBA_CC_WRITE32(scc, offset, SIBA_CC_READ32(scc, offset) | (set)) #define SIBA_CC_MASKSET32(scc, offset, mask, set) \ SIBA_CC_WRITE32(scc, offset, \ (SIBA_CC_READ32(scc, offset) & (mask)) | (set)) enum siba_clock { SIBA_CLOCK_DYNAMIC, SIBA_CLOCK_SLOW, SIBA_CLOCK_FAST, }; enum siba_clksrc { SIBA_CC_CLKSRC_PCI, SIBA_CC_CLKSRC_CRYSTAL, SIBA_CC_CLKSRC_LOWPW, }; struct siba_cc_pmu0_plltab { uint16_t freq; /* in kHz.*/ uint8_t xf; /* crystal frequency */ uint8_t wb_int; uint32_t wb_frac; }; struct siba_cc_pmu1_plltab { uint16_t freq; uint8_t xf; uint8_t p1div; uint8_t p2div; uint8_t ndiv_int; uint32_t ndiv_frac; }; struct siba_cc_pmu_res_updown { uint8_t res; uint16_t updown; }; #define SIBA_CC_PMU_DEP_SET 1 #define SIBA_CC_PMU_DEP_ADD 2 #define SIBA_CC_PMU_DEP_REMOVE 3 struct siba_cc_pmu_res_depend { uint8_t res; uint8_t task; uint32_t depend; }; enum siba_sprom_vars { SIBA_SPROMVAR_REV, SIBA_SPROMVAR_MAC_80211BG, SIBA_SPROMVAR_MAC_ETH, SIBA_SPROMVAR_MAC_80211A, SIBA_SPROMVAR_MII_ETH0, SIBA_SPROMVAR_MII_ETH1, SIBA_SPROMVAR_MDIO_ETH0, SIBA_SPROMVAR_MDIO_ETH1, SIBA_SPROMVAR_BREV, SIBA_SPROMVAR_CCODE, SIBA_SPROMVAR_ANT_A, SIBA_SPROMVAR_ANT_BG, SIBA_SPROMVAR_PA0B0, SIBA_SPROMVAR_PA0B1, SIBA_SPROMVAR_PA0B2, SIBA_SPROMVAR_PA1B0, SIBA_SPROMVAR_PA1B1, SIBA_SPROMVAR_PA1B2, SIBA_SPROMVAR_PA1LOB0, SIBA_SPROMVAR_PA1LOB1, SIBA_SPROMVAR_PA1LOB2, SIBA_SPROMVAR_PA1HIB0, SIBA_SPROMVAR_PA1HIB1, SIBA_SPROMVAR_PA1HIB2, SIBA_SPROMVAR_GPIO0, SIBA_SPROMVAR_GPIO1, SIBA_SPROMVAR_GPIO2, SIBA_SPROMVAR_GPIO3, SIBA_SPROMVAR_MAXPWR_AL, SIBA_SPROMVAR_MAXPWR_A, SIBA_SPROMVAR_MAXPWR_AH, SIBA_SPROMVAR_MAXPWR_BG, SIBA_SPROMVAR_RXPO2G, SIBA_SPROMVAR_RXPO5G, SIBA_SPROMVAR_TSSI_A, SIBA_SPROMVAR_TSSI_BG, SIBA_SPROMVAR_TRI2G, SIBA_SPROMVAR_TRI5GL, SIBA_SPROMVAR_TRI5G, SIBA_SPROMVAR_TRI5GH, SIBA_SPROMVAR_RSSISAV2G, SIBA_SPROMVAR_RSSISMC2G, SIBA_SPROMVAR_RSSISMF2G, SIBA_SPROMVAR_BXA2G, SIBA_SPROMVAR_RSSISAV5G, SIBA_SPROMVAR_RSSISMC5G, SIBA_SPROMVAR_RSSISMF5G, SIBA_SPROMVAR_BXA5G, SIBA_SPROMVAR_CCK2GPO, SIBA_SPROMVAR_OFDM2GPO, SIBA_SPROMVAR_OFDM5GLPO, SIBA_SPROMVAR_OFDM5GPO, SIBA_SPROMVAR_OFDM5GHPO, SIBA_SPROMVAR_BF_LO, SIBA_SPROMVAR_BF_HI, SIBA_SPROMVAR_BF2_LO, SIBA_SPROMVAR_BF2_HI, SIBA_SPROMVAR_FEM_2GHZ_TSSIPOS, SIBA_SPROMVAR_FEM_2GHZ_EXTPAGAIN, SIBA_SPROMVAR_FEM_2GHZ_PDET_RANGE, SIBA_SPROMVAR_FEM_2GHZ_TR_ISO, SIBA_SPROMVAR_FEM_2GHZ_ANTSWLUT, SIBA_SPROMVAR_FEM_5GHZ_TSSIPOS, SIBA_SPROMVAR_FEM_5GHZ_EXTPAGAIN, SIBA_SPROMVAR_FEM_5GHZ_PDET_RANGE, SIBA_SPROMVAR_FEM_5GHZ_TR_ISO, SIBA_SPROMVAR_FEM_5GHZ_ANTSWLUT, }; int siba_read_sprom(device_t, device_t, int, uintptr_t *); int siba_write_sprom(device_t, device_t, int, uintptr_t); /** * Generic sprom accessor generation macros for siba(4) drivers */ #define __SPROM_ACCESSOR(varp, var, ivarp, ivar, type) \ \ static __inline type varp ## _get_ ## var(device_t dev) \ { \ uintptr_t v; \ siba_read_sprom(device_get_parent(dev), dev, \ ivarp ## _SPROMVAR_ ## ivar, &v); \ return ((type) v); \ } \ \ static __inline void varp ## _set_ ## var(device_t dev, type t) \ { \ uintptr_t v = (uintptr_t) t; \ siba_write_sprom(device_get_parent(dev), dev, \ ivarp ## _SPROMVAR_ ## ivar, v); \ } #define SIBA_SPROM_ACCESSOR(var, ivar, type) \ __SPROM_ACCESSOR(siba_sprom, var, SIBA, ivar, type) SIBA_SPROM_ACCESSOR(rev, REV, uint8_t); SIBA_SPROM_ACCESSOR(mac_80211bg, MAC_80211BG, uint8_t *); SIBA_SPROM_ACCESSOR(mac_eth, MAC_ETH, uint8_t *); SIBA_SPROM_ACCESSOR(mac_80211a, MAC_80211A, uint8_t *); SIBA_SPROM_ACCESSOR(mii_eth0, MII_ETH0, uint8_t); SIBA_SPROM_ACCESSOR(mii_eth1, MII_ETH1, uint8_t); SIBA_SPROM_ACCESSOR(mdio_eth0, MDIO_ETH0, uint8_t); SIBA_SPROM_ACCESSOR(mdio_eth1, MDIO_ETH1, uint8_t); SIBA_SPROM_ACCESSOR(brev, BREV, uint8_t); SIBA_SPROM_ACCESSOR(ccode, CCODE, uint8_t); SIBA_SPROM_ACCESSOR(ant_a, ANT_A, uint8_t); SIBA_SPROM_ACCESSOR(ant_bg, ANT_BG, uint8_t); SIBA_SPROM_ACCESSOR(pa0b0, PA0B0, uint16_t); SIBA_SPROM_ACCESSOR(pa0b1, PA0B1, uint16_t); SIBA_SPROM_ACCESSOR(pa0b2, PA0B2, uint16_t); SIBA_SPROM_ACCESSOR(pa1b0, PA1B0, uint16_t); SIBA_SPROM_ACCESSOR(pa1b1, PA1B1, uint16_t); SIBA_SPROM_ACCESSOR(pa1b2, PA1B2, uint16_t); SIBA_SPROM_ACCESSOR(pa1lob0, PA1LOB0, uint16_t); SIBA_SPROM_ACCESSOR(pa1lob1, PA1LOB1, uint16_t); SIBA_SPROM_ACCESSOR(pa1lob2, PA1LOB2, uint16_t); SIBA_SPROM_ACCESSOR(pa1hib0, PA1HIB0, uint16_t); SIBA_SPROM_ACCESSOR(pa1hib1, PA1HIB1, uint16_t); SIBA_SPROM_ACCESSOR(pa1hib2, PA1HIB2, uint16_t); SIBA_SPROM_ACCESSOR(gpio0, GPIO0, uint8_t); SIBA_SPROM_ACCESSOR(gpio1, GPIO1, uint8_t); SIBA_SPROM_ACCESSOR(gpio2, GPIO2, uint8_t); SIBA_SPROM_ACCESSOR(gpio3, GPIO3, uint8_t); SIBA_SPROM_ACCESSOR(maxpwr_al, MAXPWR_AL, uint16_t); SIBA_SPROM_ACCESSOR(maxpwr_a, MAXPWR_A, uint16_t); SIBA_SPROM_ACCESSOR(maxpwr_ah, MAXPWR_AH, uint16_t); SIBA_SPROM_ACCESSOR(maxpwr_bg, MAXPWR_BG, uint16_t); SIBA_SPROM_ACCESSOR(rxpo2g, RXPO2G, uint8_t); SIBA_SPROM_ACCESSOR(rxpo5g, RXPO5G, uint8_t); SIBA_SPROM_ACCESSOR(tssi_a, TSSI_A, uint8_t); SIBA_SPROM_ACCESSOR(tssi_bg, TSSI_BG, uint8_t); SIBA_SPROM_ACCESSOR(tri2g, TRI2G, uint8_t); SIBA_SPROM_ACCESSOR(tri5gl, TRI5GL, uint8_t); SIBA_SPROM_ACCESSOR(tri5g, TRI5G, uint8_t); SIBA_SPROM_ACCESSOR(tri5gh, TRI5GH, uint8_t); SIBA_SPROM_ACCESSOR(rssisav2g, RSSISAV2G, uint8_t); SIBA_SPROM_ACCESSOR(rssismc2g, RSSISMC2G, uint8_t); SIBA_SPROM_ACCESSOR(rssismf2g, RSSISMF2G, uint8_t); SIBA_SPROM_ACCESSOR(bxa2g, BXA2G, uint8_t); SIBA_SPROM_ACCESSOR(rssisav5g, RSSISAV5G, uint8_t); SIBA_SPROM_ACCESSOR(rssismc5g, RSSISMC5G, uint8_t); SIBA_SPROM_ACCESSOR(rssismf5g, RSSISMF5G, uint8_t); SIBA_SPROM_ACCESSOR(bxa5g, BXA5G, uint8_t); SIBA_SPROM_ACCESSOR(cck2gpo, CCK2GPO, uint16_t); SIBA_SPROM_ACCESSOR(ofdm2gpo, OFDM2GPO, uint32_t); SIBA_SPROM_ACCESSOR(ofdm5glpo, OFDM5GLPO, uint32_t); SIBA_SPROM_ACCESSOR(ofdm5gpo, OFDM5GPO, uint32_t); SIBA_SPROM_ACCESSOR(ofdm5ghpo, OFDM5GHPO, uint32_t); SIBA_SPROM_ACCESSOR(bf_lo, BF_LO, uint16_t); SIBA_SPROM_ACCESSOR(bf_hi, BF_HI, uint16_t); SIBA_SPROM_ACCESSOR(bf2_lo, BF2_LO, uint16_t); SIBA_SPROM_ACCESSOR(bf2_hi, BF2_HI, uint16_t); /* 2GHz FEM */ SIBA_SPROM_ACCESSOR(fem_2ghz_tssipos, FEM_2GHZ_TSSIPOS, uint8_t); SIBA_SPROM_ACCESSOR(fem_2ghz_extpa_gain, FEM_2GHZ_EXTPAGAIN, uint8_t); SIBA_SPROM_ACCESSOR(fem_2ghz_pdet_range, FEM_2GHZ_PDET_RANGE, uint8_t); SIBA_SPROM_ACCESSOR(fem_2ghz_tr_iso, FEM_2GHZ_TR_ISO, uint8_t); SIBA_SPROM_ACCESSOR(fem_2ghz_antswlut, FEM_2GHZ_ANTSWLUT, uint8_t); /* 5GHz FEM */ SIBA_SPROM_ACCESSOR(fem_5ghz_tssipos, FEM_5GHZ_TSSIPOS, uint8_t); SIBA_SPROM_ACCESSOR(fem_5ghz_extpa_gain, FEM_5GHZ_EXTPAGAIN, uint8_t); SIBA_SPROM_ACCESSOR(fem_5ghz_pdet_range, FEM_5GHZ_PDET_RANGE, uint8_t); SIBA_SPROM_ACCESSOR(fem_5ghz_tr_iso, FEM_5GHZ_TR_ISO, uint8_t); SIBA_SPROM_ACCESSOR(fem_5ghz_antswlut, FEM_5GHZ_ANTSWLUT, uint8_t); #undef SIBA_SPROM_ACCESSOR +struct siba_sprom_core_pwr_info { + uint8_t itssi_2g, itssi_5g; + uint8_t maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh; + uint8_t pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4]; +}; + struct siba_sprom { uint8_t rev; /* revision */ uint8_t mac_80211bg[6]; /* address for 802.11b/g */ uint8_t mac_eth[6]; /* address for Ethernet */ uint8_t mac_80211a[6]; /* address for 802.11a */ uint8_t mii_eth0; /* MII address for eth0 */ uint8_t mii_eth1; /* MII address for eth1 */ uint8_t mdio_eth0; /* MDIO for eth0 */ uint8_t mdio_eth1; /* MDIO for eth1 */ uint8_t brev; /* board revision */ uint8_t ccode; /* Country Code */ uint8_t ant_a; /* A-PHY antenna */ uint8_t ant_bg; /* B/G-PHY antenna */ uint16_t pa0b0; uint16_t pa0b1; uint16_t pa0b2; uint16_t pa1b0; uint16_t pa1b1; uint16_t pa1b2; uint16_t pa1lob0; uint16_t pa1lob1; uint16_t pa1lob2; uint16_t pa1hib0; uint16_t pa1hib1; uint16_t pa1hib2; uint8_t gpio0; uint8_t gpio1; uint8_t gpio2; uint8_t gpio3; uint16_t maxpwr_al; uint16_t maxpwr_a; /* A-PHY Max Power */ uint16_t maxpwr_ah; uint16_t maxpwr_bg; /* BG-PHY Max Power */ uint8_t rxpo2g; uint8_t rxpo5g; uint8_t tssi_a; /* Idle TSSI */ uint8_t tssi_bg; /* Idle TSSI */ uint8_t tri2g; uint8_t tri5gl; uint8_t tri5g; uint8_t tri5gh; uint8_t rssisav2g; uint8_t rssismc2g; uint8_t rssismf2g; uint8_t bxa2g; uint8_t rssisav5g; uint8_t rssismc5g; uint8_t rssismf5g; uint8_t bxa5g; uint16_t cck2gpo; uint32_t ofdm2gpo; uint32_t ofdm5glpo; uint32_t ofdm5gpo; uint32_t ofdm5ghpo; uint16_t bf_lo; /* boardflags */ uint16_t bf_hi; /* boardflags */ uint16_t bf2_lo; uint16_t bf2_hi; + struct siba_sprom_core_pwr_info core_pwr_info[4]; + struct { struct { int8_t a0, a1, a2, a3; } ghz24; struct { int8_t a0, a1, a2, a3; } ghz5; } again; /* antenna gain */ struct { struct { uint8_t tssipos, extpa_gain, pdet_range, tr_iso; uint8_t antswlut; } ghz2; struct { uint8_t tssipos, extpa_gain, pdet_range, tr_iso; uint8_t antswlut; } ghz5; } fem; }; #define SIBA_LDO_PAREF 0 #define SIBA_LDO_VOLT1 1 #define SIBA_LDO_VOLT2 2 #define SIBA_LDO_VOLT3 3 struct siba_cc_pmu { uint8_t rev; /* PMU rev */ uint32_t freq; /* crystal freq in kHz */ }; struct siba_cc { struct siba_dev_softc *scc_dev; uint32_t scc_caps; struct siba_cc_pmu scc_pmu; uint16_t scc_powerup_delay; }; struct siba_pci { struct siba_dev_softc *spc_dev; uint8_t spc_inited; uint8_t spc_hostmode; }; struct siba_bus_ops { uint16_t (*read_2)(struct siba_dev_softc *, uint16_t); uint32_t (*read_4)(struct siba_dev_softc *, uint16_t); void (*write_2)(struct siba_dev_softc *, uint16_t, uint16_t); void (*write_4)(struct siba_dev_softc *, uint16_t, uint32_t); void (*read_multi_1)(struct siba_dev_softc *, void *, size_t, uint16_t); void (*read_multi_2)(struct siba_dev_softc *, void *, size_t, uint16_t); void (*read_multi_4)(struct siba_dev_softc *, void *, size_t, uint16_t); void (*write_multi_1)(struct siba_dev_softc *, const void *, size_t, uint16_t); void (*write_multi_2)(struct siba_dev_softc *, const void *, size_t, uint16_t); void (*write_multi_4)(struct siba_dev_softc *, const void *, size_t, uint16_t); }; struct siba_dev_softc { struct siba_softc *sd_bus; struct siba_devid sd_id; const struct siba_bus_ops *sd_ops; uint8_t sd_coreidx; }; struct siba_devinfo { struct resource_list sdi_rl; /*devhandle_t sdi_devhandle; XXX*/ /*struct rman sdi_intr_rman;*/ /* Accessors are needed for ivars below. */ uint16_t sdi_vid; uint16_t sdi_devid; uint8_t sdi_rev; uint8_t sdi_idx; /* core index on bus */ uint8_t sdi_irq; /* TODO */ }; struct siba_softc { /* * common variables which used for siba(4) bus and siba_bwn bridge. */ device_t siba_dev; /* Device ID */ struct resource *siba_mem_res; bus_space_tag_t siba_mem_bt; bus_space_handle_t siba_mem_bh; bus_addr_t siba_maddr; bus_size_t siba_msize; uint8_t siba_ncores; /* * the following variables are only used for siba_bwn bridge. */ enum siba_type siba_type; int siba_invalid; struct siba_dev_softc *siba_curdev; /* only for PCI */ struct siba_dev_softc siba_devs[SIBA_MAX_CORES]; int siba_ndevs; uint16_t siba_pci_vid; uint16_t siba_pci_did; uint16_t siba_pci_subvid; uint16_t siba_pci_subdid; uint8_t siba_pci_revid; int siba_mem_rid; uint16_t siba_chipid; /* for CORE 0 */ uint16_t siba_chiprev; uint8_t siba_chippkg; struct siba_cc siba_cc; /* ChipCommon */ struct siba_pci siba_pci; /* PCI-core */ const struct siba_bus_ops *siba_ops; struct siba_sprom siba_sprom; /* SPROM */ uint16_t siba_spromsize; /* in word size */ }; void siba_powerup(device_t, int); int siba_powerdown(device_t); uint16_t siba_read_2(device_t, uint16_t); void siba_write_2(device_t, uint16_t, uint16_t); uint32_t siba_read_4(device_t, uint16_t); void siba_write_4(device_t, uint16_t, uint32_t); void siba_dev_up(device_t, uint32_t); void siba_dev_down(device_t, uint32_t); int siba_dev_isup(device_t); void siba_pcicore_intr(device_t); uint32_t siba_dma_translation(device_t); void siba_read_multi_1(device_t, void *, size_t, uint16_t); void siba_read_multi_2(device_t, void *, size_t, uint16_t); void siba_read_multi_4(device_t, void *, size_t, uint16_t); void siba_write_multi_1(device_t, const void *, size_t, uint16_t); void siba_write_multi_2(device_t, const void *, size_t, uint16_t); void siba_write_multi_4(device_t, const void *, size_t, uint16_t); void siba_barrier(device_t, int); void siba_cc_pmu_set_ldovolt(device_t, int, uint32_t); void siba_cc_pmu_set_ldoparef(device_t, uint8_t); void siba_gpio_set(device_t, uint32_t); uint32_t siba_gpio_get(device_t); void siba_fix_imcfglobug(device_t); +int siba_sprom_get_core_power_info(device_t, int, + struct siba_sprom_core_pwr_info *); #endif /* _SIBA_SIBAVAR_H_ */