Index: share/man/man4/siba.4 =================================================================== --- share/man/man4/siba.4 (revision 0) +++ share/man/man4/siba.4 (revision 0) @@ -0,0 +1,91 @@ +.\" Copyright (c) 2008 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. +.\" 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: src/share/man/man4/siba.4,v 1.5 2009/10/18 00:46:59 weongyo Exp $ +.\" +.Dd January 08, 2010 +.Dt SIBA 4 +.Os +.Sh NAME +.Nm siba +.Nd Silicon Backplane by Sonics Inc. +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your kernel configuration file: +.Bd -ragged -offset indent +.Cd "device siba" +.Ed +.Pp +Alternatively, to load the driver as a module at boot time, +place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +siba_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver supports Silicon Backplane, its interblock communications +architecture, by Sonics Inc which could be found most of Broadcom +wireless NICs. +.Pp +The bus connects all of its functional blocks. +These functional blocks, known as cores, use the Open Core Protocol +(OCP) interface to communicate with agents attached to the Solicon +Backplane. +.Pp +Each NICs or devices have a member of a family of chips built using +the same Silicon Backplane architecture and +each member of the family contains a different set of cores, but +shares basic architectural features such as address space definition, +interrupt and error architecture, and backplane register definitions. +.Pp +Each core can have an initiator agent that passes read and write +requests onto the system backplane and a target agent that returns +responses to those requests. +Not all cores contain both an initiator and a target agent. +Initiator agents are present in cores that contain +host interfaces (PCI, PCMCIA), embedded processors (MIPS), +or DMA processors associated with communications cores. +.Pp +All cores other than PCMCIA have a target agent. +.Sh SEE ALSO +.Xr bwn 4 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 9.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Bruce M. Simpson +.Aq bms@FreeBSD.org +and +.An Weongyo Jeong +.Aq weongyo@FreeBSD.org . +.Sh CAVEATS +Host mode isn't supported at this moment. Index: sys/modules/siba/Makefile =================================================================== --- sys/modules/siba/Makefile (revision 0) +++ sys/modules/siba/Makefile (revision 0) @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/siba + +KMOD= siba +SRCS= siba.c siba_pcib.c sibareg.h sibavar.h +SRCS+= device_if.h bus_if.h pci_if.h + +.include Index: sys/dev/siba/siba.c =================================================================== --- sys/dev/siba/siba.c (revision 202165) +++ sys/dev/siba/siba.c (working copy) @@ -1,665 +1,2001 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. + * 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. - * 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. + * 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. * - * 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. + * 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 + +#include #include -#include -#include -/* - * TODO: De-mipsify this code. - * TODO: cpu clock calculation. -> move to siba_cc instance - * TODO: Hardwire IRQs for attached cores on siba at probe time. - * TODO: Support detach. - * TODO: Power management. - * TODO: code cleanup. - * TODO: Support deployments of siba other than as a system bus. - */ - -#ifndef MIPS_MEM_RID -#define MIPS_MEM_RID 0x20 +#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])) -extern int rman_debug; +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 uint8_t siba_getncores(device_t, uint16_t); +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 *); +device_t siba_add_child(device_t, struct siba_softc *, int, const char *, + int); +int siba_suspend(struct siba_softc *); +int siba_resume(struct siba_softc *); -static struct rman mem_rman; /* XXX move to softc */ +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 int siba_debug = 1; -static const char descfmt[] = "Sonics SiliconBackplane rev %s"; -#define SIBA_DEVDESCLEN sizeof(descfmt) + 8 +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; -/* - * Device identifiers and descriptions. - */ -static struct siba_devid siba_devids[] = { - { SIBA_VID_BROADCOM, SIBA_DEVID_CHIPCOMMON, SIBA_REV_ANY, - "ChipCommon" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_SDRAM, SIBA_REV_ANY, - "SDRAM controller" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_PCI, SIBA_REV_ANY, - "PCI host interface" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_MIPS, SIBA_REV_ANY, - "MIPS core" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_ETHERNET, SIBA_REV_ANY, - "Ethernet core" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_USB, SIBA_REV_ANY, - "USB host controller" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_IPSEC, SIBA_REV_ANY, - "IPSEC accelerator" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_SDRAMDDR, SIBA_REV_ANY, - "SDRAM/DDR controller" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_MIPS_3302, SIBA_REV_ANY, - "MIPS 3302 core" }, - { 0, 0, 0, NULL } -}; +int +siba_attach(struct siba_softc *siba) +{ + struct siba_cc *scc; + int error; -static int siba_activate_resource(device_t, device_t, int, int, - struct resource *); -static device_t siba_add_child(device_t, int, const char *, int); -static struct resource * - siba_alloc_resource(device_t, device_t, int, int *, u_long, - u_long, u_long, u_int); -static int siba_attach(device_t); -#ifdef notyet -static void siba_destroy_devinfo(struct siba_devinfo *); -#endif -static struct siba_devid * - siba_dev_match(uint16_t, uint16_t, uint8_t); -static struct resource_list * - siba_get_reslist(device_t, device_t); -static uint8_t siba_getirq(uint16_t); -static uint8_t siba_getncores(uint16_t); -static int siba_print_all_resources(device_t dev); -static int siba_print_child(device_t, device_t); -static int siba_probe(device_t); -static void siba_probe_nomatch(device_t, device_t); -int siba_read_ivar(device_t, device_t, int, uintptr_t *); -static struct siba_devinfo * - siba_setup_devinfo(device_t, uint8_t); -int siba_write_ivar(device_t, device_t, int, uintptr_t); + 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(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); + } + + /* fetch various internal informations for PCI */ + siba->siba_board_vendor = pci_read_config(siba->siba_dev, + PCIR_SUBVEND_0, 2); + siba->siba_board_type = pci_read_config(siba->siba_dev, PCIR_SUBDEV_0, + 2); + siba->siba_board_rev = pci_read_config(siba->siba_dev, PCIR_REVID, 2); + error = siba_pci_sprom(siba, &siba->siba_sprom); + if (error) { + siba_powerdown(siba); + return (error); + } + + siba_powerdown(siba); + return (0); +} + +int +siba_detach(struct siba_softc *siba) +{ + device_t *devlistp; + int devcnt, error = 0, i; + + error = device_get_children(siba->siba_dev, &devlistp, &devcnt); + if (error != 0) + return (0); + + for ( i = 0 ; i < devcnt ; i++) + device_delete_child(siba->siba_dev, devlistp[i]); + free(devlistp, M_TEMP); + 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; + 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.cid = SIBA_IDHIGH_CORECODE(idhi); + sd->sd_id.rev = SIBA_IDHIGH_REV(idhi); + sd->sd_id.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.cid), + sd->sd_id.cid, sd->sd_id.rev, sd->sd_id.vendor); + + switch (sd->sd_id.cid) { + 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_extcap(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.cid == SIBA_DEVID_PCI && is_pcie == 1) + continue; + if (sd->sd_id.cid == 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.cid)); + break; + } + dev_i++; + } + 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.cid), 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. */ static uint8_t -siba_getncores(uint16_t ccid) +siba_getncores(device_t dev, uint16_t chipid) { - uint8_t ncores; - - switch (ccid) { + switch (chipid) { + case 0x4401: + case 0x4402: + return (3); + case 0x4301: + case 0x4307: + return (5); + case 0x4306: + return (6); case SIBA_CCID_SENTRY5: - ncores = 7; - break; + return (7); + case 0x4310: + return (8); case SIBA_CCID_BCM4710: + case 0x4610: case SIBA_CCID_BCM4704: - ncores = 9; - break; + return (9); default: - ncores = 0; + device_printf(dev, "unknown the chipset ID %#x\n", chipid); } - return (ncores); + return (1); } -/* - * On the Sentry5, the system bus IRQs are the same as the - * MIPS IRQs. Particular cores are hardwired to certain IRQ lines. - */ -static uint8_t -siba_getirq(uint16_t devid) +static const char * +siba_core_name(uint16_t coreid) { - uint8_t irq; - switch (devid) { + switch (coreid) { case SIBA_DEVID_CHIPCOMMON: - irq = 0; - break; + 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: - irq = 1; - break; + 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: - irq = 2; - break; - case SIBA_DEVID_USB: - irq = 3; - break; - case SIBA_DEVID_PCI: - irq = 4; - break; -#if 0 - /* - * 5 is reserved for the MIPS on-chip timer interrupt; - * it is hard-wired by the tick driver. - */ - case SIBA_DEVID_MIPS: + 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: - irq = 5; - break; -#endif - default: - irq = 0xFF; /* this core does not need an irq */ - break; + 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"); +} - return (irq); +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 int -siba_probe(device_t dev) +static uint32_t +siba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset) { - struct siba_softc *sc = device_get_softc(dev); - uint32_t idlo, idhi; - uint16_t ccid; - int rid; + struct siba_softc *siba = sd->sd_bus; - sc->sc_dev = dev; + if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) + return (0xffff); - //rman_debug = 1; /* XXX */ + return (SIBA_READ_4(siba, offset)); +} - /* - * Map the ChipCommon register set using the hints the kernel - * was compiled with. - */ - rid = MIPS_MEM_RID; - sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->sc_mem == NULL) { - device_printf(dev, "unable to allocate probe aperture\n"); - return (ENXIO); +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; } - sc->sc_bt = rman_get_bustag(sc->sc_mem); - sc->sc_bh = rman_get_bushandle(sc->sc_mem); - sc->sc_maddr = rman_get_start(sc->sc_mem); - sc->sc_msize = rman_get_size(sc->sc_mem); - if (siba_debug) { - device_printf(dev, "start %08x len %08x\n", - sc->sc_maddr, sc->sc_msize); + 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; } - idlo = siba_read_4(sc, 0, SIBA_CORE_IDLO); - idhi = siba_read_4(sc, 0, SIBA_CORE_IDHI); - ccid = ((idhi & 0x8ff0) >> 4); - if (siba_debug) { - device_printf(dev, "idlo = %08x\n", idlo); - device_printf(dev, "idhi = %08x\n", idhi); - device_printf(dev, " chipcore id = %08x\n", ccid); + 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(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; /* - * For now, check that the first core is the ChipCommon core. + * chipcommon < r6 (no dynamic clock control) + * chipcommon >= r10 (unknown) */ - if (ccid != SIBA_DEVID_CHIPCOMMON) { - if (siba_debug) - device_printf(dev, "first core is not ChipCommon\n"); - return (ENXIO); + if (sd->sd_id.rev < 6 || sd->sd_id.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)); } +} - /* - * Determine backplane revision and set description string. - */ - uint32_t rev; - char *revp; - char descbuf[SIBA_DEVDESCLEN]; +uint16_t +siba_read_2(struct siba_dev_softc *sd, uint16_t offset) +{ - rev = idlo & 0xF0000000; - revp = "unknown"; - if (rev == 0x00000000) - revp = "2.2"; - else if (rev == 0x10000000) - revp = "2.3"; + return (sd->sd_ops->read_2(sd, offset)); +} - (void)snprintf(descbuf, sizeof(descbuf), descfmt, revp); - device_set_desc_copy(dev, descbuf); +uint32_t +siba_read_4(struct siba_dev_softc *sd, uint16_t offset) +{ - /* - * Determine how many cores are present on this siba bus, so - * that we may map them all. - */ - uint32_t ccidreg; - uint16_t cc_id; - uint16_t cc_rev; + return (sd->sd_ops->read_4(sd, offset)); +} - ccidreg = siba_read_4(sc, 0, SIBA_CC_CCID); - cc_id = (ccidreg & SIBA_CC_IDMASK); - cc_rev = (ccidreg & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT; - if (siba_debug) { - device_printf(dev, "ccid = %08x, cc_id = %04x, cc_rev = %04x\n", - ccidreg, cc_id, cc_rev); +void +siba_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value) +{ + + sd->sd_ops->write_2(sd, offset, value); +} + +void +siba_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value) +{ + + sd->sd_ops->write_4(sd, offset, value); +} + +void +siba_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count, + uint16_t offset) +{ + + sd->sd_ops->read_multi_1(sd, buffer, count, offset); +} + +void +siba_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count, + uint16_t offset) +{ + + sd->sd_ops->read_multi_2(sd, buffer, count, offset); +} + +void +siba_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count, + uint16_t offset) +{ + + sd->sd_ops->read_multi_4(sd, buffer, count, offset); +} + +void +siba_write_multi_1(struct siba_dev_softc *sd, const void *buffer, + size_t count, uint16_t offset) +{ + + sd->sd_ops->write_multi_1(sd, buffer, count, offset); +} + +void +siba_write_multi_2(struct siba_dev_softc *sd, const void *buffer, + size_t count, uint16_t offset) +{ + + sd->sd_ops->write_multi_2(sd, buffer, count, offset); +} + +void +siba_write_multi_4(struct siba_dev_softc *sd, const void *buffer, + size_t count, uint16_t offset) +{ + + 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); } - sc->sc_ncores = siba_getncores(cc_id); - if (siba_debug) { - device_printf(dev, "%d cores detected.\n", sc->sc_ncores); + /* 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); } - /* - * Now we know how many cores are on this siba, release the - * mapping and allocate a new mapping spanning all cores on the bus. - */ - rid = MIPS_MEM_RID; - int result; - result = bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem); - if (result != 0) { - device_printf(dev, "error %d releasing resource\n", result); - return (ENXIO); + 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__)); + } + } + } - uint32_t total; - total = sc->sc_ncores * SIBA_CORE_LEN; + if (min) + SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min); + if (max) + SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max); +} - /* XXX Don't allocate the entire window until we - * enumerate the bus. Once the bus has been enumerated, - * and instance variables/children instantiated + populated, - * release the resource so children may attach. - */ - sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - sc->sc_maddr, sc->sc_maddr + total - 1, total, RF_ACTIVE); - if (sc->sc_mem == NULL) { - device_printf(dev, "unable to allocate entire aperture\n"); - return (ENXIO); - } - sc->sc_bt = rman_get_bustag(sc->sc_mem); - sc->sc_bh = rman_get_bushandle(sc->sc_mem); - sc->sc_maddr = rman_get_start(sc->sc_mem); - sc->sc_msize = rman_get_size(sc->sc_mem); +static void +siba_cc_power_init(struct siba_cc *scc) +{ + struct siba_softc *siba = scc->scc_dev->sd_bus; + int maxfreq; - if (siba_debug) { - device_printf(dev, "after remapping: start %08x len %08x\n", - sc->sc_maddr, sc->sc_msize); + 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); } - bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->sc_maddr, sc->sc_msize); - /* - * We need a manager for the space we claim on nexus to - * satisfy requests from children. - * We need to keep the source reservation we took because - * otherwise it may be claimed elsewhere. - * XXX move to softc - */ - mem_rman.rm_start = sc->sc_maddr; - mem_rman.rm_end = sc->sc_maddr + sc->sc_msize - 1; - mem_rman.rm_type = RMAN_ARRAY; - mem_rman.rm_descr = "SiBa I/O memory addresses"; - if (rman_init(&mem_rman) != 0 || - rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end) != 0) { - panic("%s: mem_rman", __func__); + if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0) + return; + + if (scc->scc_dev->sd_id.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); } +} - return (0); +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 = + (((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000) + + (min - 1)) / min; } static int -siba_attach(device_t dev) +siba_cc_clockfreq(struct siba_cc *scc, int max) { - struct siba_softc *sc = device_get_softc(dev); - struct siba_devinfo *sdi; - device_t child; - int idx; + enum siba_clksrc src; + int div = 1, limit = 0; - if (siba_debug) - printf("%s: entry\n", __func__); + src = siba_cc_clksrc(scc); + if (scc->scc_dev->sd_id.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.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; - bus_generic_probe(dev); + 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; + } - /* - * Now that all bus space is mapped and visible to the CPU, - * enumerate its children. - * NB: only one core may be mapped at any time if the siba bus - * is the child of a PCI or PCMCIA bus. - */ - for (idx = 0; idx < sc->sc_ncores; idx++) { - sdi = siba_setup_devinfo(dev, idx); - child = device_add_child(dev, NULL, -1); - if (child == NULL) - panic("%s: device_add_child() failed\n", __func__); - device_set_ivars(child, sdi); + 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; } - return (bus_generic_attach(dev)); + 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 struct siba_devid * -siba_dev_match(uint16_t vid, uint16_t devid, uint8_t rev) +static void +siba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq) { - size_t i, bound; - struct siba_devid *sd; + 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; - bound = sizeof(siba_devids) / sizeof(struct siba_devid); - sd = &siba_devids[0]; - for (i = 0; i < bound; i++, sd++) { - if (((vid == SIBA_VID_ANY) || (vid == sd->sd_vendor)) && - ((devid == SIBA_DEVID_ANY) || (devid == sd->sd_device)) && - ((rev == SIBA_REV_ANY) || (rev == sd->sd_rev) || - (sd->sd_rev == SIBA_REV_ANY))) + 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); } - if (i == bound) - sd = NULL; + 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"); - return (sd); + /* 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 int -siba_print_child(device_t bus, device_t child) +static enum siba_clksrc +siba_cc_clksrc(struct siba_cc *scc) { - int retval = 0; + struct siba_dev_softc *sd = scc->scc_dev; + struct siba_softc *siba = sd->sd_bus; - retval += bus_print_child_header(bus, child); - retval += siba_print_all_resources(child); - if (device_get_flags(child)) - retval += printf(" flags %#x", device_get_flags(child)); - retval += printf(" on %s\n", device_get_nameunit(bus)); + if (sd->sd_id.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.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 (retval); + return (SIBA_CC_CLKSRC_CRYSTAL); } -static struct resource * -siba_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) +static const struct siba_cc_pmu1_plltab * +siba_cc_pmu1_plltab_find(uint32_t crystalfreq) { - struct resource *rv; - struct resource_list *rl; - struct resource_list_entry *rle; - int isdefault, needactivate; + const struct siba_cc_pmu1_plltab *e; + unsigned int i; -#if 0 - if (siba_debug) - printf("%s: entry\n", __func__); -#endif + for (i = 0; i < N(siba_cc_pmu1_plltab); i++) { + e = &siba_cc_pmu1_plltab[i]; + if (crystalfreq == e->freq) + return (e); + } - isdefault = (start == 0UL && end == ~0UL && count == 1); - needactivate = flags & RF_ACTIVE; - rl = BUS_GET_RESOURCE_LIST(bus, child); - rle = NULL; + return (NULL); +} - if (isdefault) { - rle = resource_list_find(rl, type, *rid); - if (rle == NULL) - return (NULL); - if (rle->res != NULL) - panic("%s: resource entry is busy", __func__); - start = rle->start; - end = rle->end; - count = rle->count; +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); } - /* - * If the request is for a resource which we manage, - * attempt to satisfy the allocation ourselves. - */ - if (type == SYS_RES_MEMORY && - start >= mem_rman.rm_start && end <= mem_rman.rm_end) { + return (NULL); +} - rv = rman_reserve_resource(&mem_rman, start, end, count, - flags, child); - if (rv == 0) { - printf("%s: could not reserve resource\n", __func__); - return (0); - } +static int +siba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom) +{ + int error = ENOMEM; + uint16_t *buf; - rman_set_rid(rv, *rid); + 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"); + } - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - printf("%s: could not activate resource\n", - __func__); - rman_release_resource(rv); - return (0); - } + 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); } - - return (rv); } - /* - * Pass the request to the parent, usually MIPS nexus. - */ - if (siba_debug) - printf("%s: proxying request to parent\n", __func__); - return (resource_list_alloc(rl, bus, child, type, rid, - start, end, count, flags)); + if (sprom->bf_lo == 0xffff) + sprom->bf_lo = 0; + if (sprom->bf_hi == 0xffff) + sprom->bf_hi = 0; + + free(buf, M_DEVBUF); + return (error); } -/* - * The parent bus is responsible for resource activation; in the - * case of MIPS, this boils down to setting the virtual address and - * bus handle by mapping the physical address into KSEG1. - */ static int -siba_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +siba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len) { + int i; - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, type, - rid, r)); + for (i = 0; i < len; i++) + sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2)); + + siba->siba_spromsize = len; + return (0); } -static struct siba_devinfo * -siba_setup_devinfo(device_t dev, uint8_t idx) +static int +sprom_check_crc(const uint16_t *sprom, size_t size) { - struct siba_softc *sc = device_get_softc(dev); - struct siba_devinfo *sdi; - uint32_t idlo, idhi, rev; - uint16_t vendorid, devid; - bus_addr_t baseaddr; + int word; + uint8_t crc0, crc1 = 0xff; - sdi = malloc(sizeof(*sdi), M_DEVBUF, M_WAITOK | M_ZERO); - resource_list_init(&sdi->sdi_rl); + 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; - idlo = siba_read_4(sc, idx, SIBA_CORE_IDLO); - idhi = siba_read_4(sc, idx, SIBA_CORE_IDHI); + return ((crc0 != crc1) ? EPROTO : 0); +} - vendorid = (idhi & SIBA_IDHIGH_VC) >> SIBA_IDHIGH_VC_SHIFT; - devid = ((idhi & 0x8ff0) >> 4); - rev = (idhi & SIBA_IDHIGH_RCLO); - rev |= (idhi & SIBA_IDHIGH_RCHI) >> SIBA_IDHIGH_RCHI_SHIFT; +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]); +} - sdi->sdi_vid = vendorid; - sdi->sdi_devid = devid; - sdi->sdi_rev = rev; - sdi->sdi_idx = idx; - sdi->sdi_irq = siba_getirq(devid); +#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)) - /* - * Determine memory window on bus and irq if one is needed. - */ - baseaddr = sc->sc_maddr + (idx * SIBA_CORE_LEN); - resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, - MIPS_MEM_RID, /* XXX */ - baseaddr, baseaddr + SIBA_CORE_LEN - 1, SIBA_CORE_LEN); +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 (sdi->sdi_irq != 0xff) { - resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, - 0, sdi->sdi_irq, sdi->sdi_irq, 1); + 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); - return (sdi); + /* 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; } -#ifdef notyet static void -siba_destroy_devinfo(struct siba_devinfo *sdi) +siba_sprom_r45(struct siba_sprom *out, const uint16_t *in) { + int i; + uint16_t v; + uint16_t mac_80211bg_offset; - resource_list_free(&sdi->sdi_rl); - free(sdi, M_DEVBUF); + 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)); } -#endif -/* XXX is this needed? */ -static device_t -siba_add_child(device_t dev, int order, const char *name, int unit) +static void +siba_sprom_r8(struct siba_sprom *out, const uint16_t *in) { -#if 1 + int i; + uint16_t v; - device_printf(dev, "%s: entry\n", __func__); - return (NULL); -#else - device_t child; - struct siba_devinfo *sdi; + for (i = 0; i < 3; i++) { + v = in[SIBA_OFFSET(SIBA_SPROM1_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(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(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); - child = device_add_child_ordered(dev, order, name, unit); - if (child == NULL) - return (NULL); + /* 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)); +} - sdi = malloc(sizeof(struct siba_devinfo), M_DEVBUF, M_NOWAIT|M_ZERO); - if (sdi == NULL) - return (NULL); +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; - device_set_ivars(child, sdi); - return (child); -#endif + 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_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +siba_powerdown(struct siba_softc *siba) { - struct siba_devinfo *sdi; + struct siba_cc *scc; - sdi = device_get_ivars(child); + if (siba->siba_type == SIBA_TYPE_SSB) + return (0); - switch (which) { - case SIBA_IVAR_VENDOR: - *result = sdi->sdi_vid; - break; - case SIBA_IVAR_DEVICE: - *result = sdi->sdi_devid; - break; - case SIBA_IVAR_REVID: - *result = sdi->sdi_rev; - break; - case SIBA_IVAR_CORE_INDEX: - *result = sdi->sdi_idx; - break; + scc = &siba->siba_cc; + if (!scc->scc_dev || scc->scc_dev->sd_id.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; + struct siba_softc *siba; + + if (sd == NULL) + return; + + siba = sd->sd_bus; + if (!siba_dev_isup(sd)) + siba_dev_up(sd, 0); + + KASSERT(spc->spc_hostmode == 0, + ("%s:%d: hostmode", __func__, __LINE__)); + /* disable PCI interrupt */ + siba_write_4(spc->spc_dev, SIBA_INTR_MASK, 0); +} + +int +siba_dev_isup(struct siba_dev_softc *sd) +{ + uint32_t reject, val; + + reject = siba_tmslow_reject_bitmask(sd); + val = siba_read_4(sd, SIBA_TGSLOW); + val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject; + + return (val == SIBA_TGSLOW_CLOCK); +} + +void +siba_dev_up(struct siba_dev_softc *sd, uint32_t flags) +{ + uint32_t val; + + siba_dev_down(sd, flags); + siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK | + SIBA_TGSLOW_FGC | flags); + siba_read_4(sd, SIBA_TGSLOW); + DELAY(1); + + if (siba_read_4(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR) + siba_write_4(sd, SIBA_TGSHIGH, 0); + + val = siba_read_4(sd, SIBA_IAS); + if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) { + val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT); + siba_write_4(sd, SIBA_IAS, val); + } + + siba_write_4(sd, SIBA_TGSLOW, + SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags); + siba_read_4(sd, SIBA_TGSLOW); + DELAY(1); + + siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags); + siba_read_4(sd, SIBA_TGSLOW); + DELAY(1); +} + +static uint32_t +siba_tmslow_reject_bitmask(struct siba_dev_softc *sd) +{ + uint32_t rev = siba_read_4(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: - return (ENOENT); + KASSERT(0 == 1, + ("%s:%d: unknown backplane rev %#x\n", + __func__, __LINE__, rev)); } + return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23); +} - return (0); +void +siba_dev_down(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(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET) + return; + + reject = siba_tmslow_reject_bitmask(sd); + siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK); + + for (i = 0; i < 1000; i++) { + val = siba_read_4(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(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(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK | + reject | SIBA_TGSLOW_RESET | flags); + siba_read_4(sd, SIBA_TGSLOW); + DELAY(1); + siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags); + siba_read_4(sd, SIBA_TGSLOW); + DELAY(1); } -int -siba_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +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; - return (EINVAL); + if (psd->sd_id.cid == 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.rev < 5) { + tmp = siba_read_4(psd, SIBA_IMCFGLO); + tmp &= ~SIBA_IMCFGLO_SERTO; + tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO; + tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */; + siba_write_4(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(sd, SIBA_PCICORE_BCAST_ADDR, + 0xfd8); + siba_read_4(sd, SIBA_PCICORE_BCAST_ADDR); + siba_write_4(sd, SIBA_PCICORE_BCAST_DATA, 0); + siba_read_4(sd, SIBA_PCICORE_BCAST_DATA); + } + } else if (psd->sd_id.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.cid == SIBA_DEVID_PCIE, ("only PCIE")); + if ((psd->sd_id.rev == 0) || (psd->sd_id.rev == 1)) + siba_pcie_write(spc, 0x4, + siba_pcie_read(spc, 0x4) | 0x8); + if (psd->sd_id.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.rev == 1) + siba_pcie_write(spc, 0x100, + siba_pcie_read(spc, 0x100) | 0x40); + } + spc->spc_inited = 1; } +void +siba_pcicore_intr(struct siba_pci *spc, struct siba_dev_softc *sd) +{ + struct siba_dev_softc *psd = spc->spc_dev; + struct siba_softc *siba; + uint32_t tmp; + + if (sd->sd_bus->siba_type != SIBA_TYPE_PCI || !psd) + return; + + siba = psd->sd_bus; + /* enable interrupts */ + if (siba->siba_dev != NULL && + (psd->sd_id.rev >= 6 || psd->sd_id.cid == 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(sd, SIBA_TPS); + tmp &= SIBA_TPS_BPFLAG; + siba_write_4(psd, SIBA_INTR_MASK, + siba_read_4(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(spc->spc_dev, offset)); +} + static void -siba_probe_nomatch(device_t dev, device_t child) +siba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value) { - /* - * Announce devices which weren't attached after we probed the bus. - */ - if (siba_debug) { - struct siba_devid *sd; + siba_write_4(spc->spc_dev, offset, value); +} - sd = siba_dev_match(siba_get_vendor(child), - siba_get_device(child), SIBA_REV_ANY); - if (sd != NULL && sd->sd_desc != NULL) { - device_printf(dev, "<%s> " - "at device %d (no driver attached)\n", - sd->sd_desc, siba_get_core_index(child)); - } else { - device_printf(dev, "<0x%04x, 0x%04x> " - "at device %d (no driver attached)\n", - siba_get_vendor(child), siba_get_device(child), - siba_get_core_index(child)); +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(struct siba_dev_softc *sd) +{ + + KASSERT(sd->sd_bus->siba_type == SIBA_TYPE_PCI, + ("unsupported bustype %d\n", sd->sd_bus->siba_type)); + return (SIBA_PCI_DMA); +} + +void +siba_barrier(struct siba_dev_softc *sd, int flags) +{ + struct siba_softc *siba = sd->sd_bus; + + SIBA_BARRIER(siba, flags); +} + +/* + * Attach it as child. + */ +device_t +siba_add_child(device_t dev, struct siba_softc *siba, int order, + const char *name, int unit) +{ + struct siba_dev_softc *sd; + device_t child; + int idx = 0, i; + + child = device_add_child(dev, name, unit); + if (child == NULL) + return (NULL); + + siba_powerup(siba, 0); + siba_pcicore_init(&siba->siba_pci); + siba_powerdown(siba); + + for (i = 0; i < siba->siba_ndevs; i++) { + sd = &(siba->siba_devs[i]); + + if (sd->sd_id.cid != SIBA_DEVID_80211) { + DPRINTF(siba, SIBA_DEBUG_CORE, + "skip to register coreid %#x (%s)\n", + sd->sd_id.cid, siba_core_name(sd->sd_id.cid)); + continue; } + + DPRINTF(siba, SIBA_DEBUG_CORE, + "siba: attaching coreid %#x (%s) idx %d\n", + sd->sd_id.cid, siba_core_name(sd->sd_id.cid), idx); + + KASSERT(sd->sd_id.cid == SIBA_DEVID_80211, + ("%s:%d: SIBA_DEVID_80211 is only supportted currently.", + __func__, __LINE__)); + + device_set_ivars(child, sd); + device_probe_and_attach(child); + idx++; } + return (child); } -static int -siba_print_all_resources(device_t dev) +static void +siba_cc_suspend(struct siba_cc *scc) { - struct siba_devinfo *sdi = device_get_ivars(dev); - struct resource_list *rl = &sdi->sdi_rl; - int retval = 0; - if (STAILQ_FIRST(rl)) - retval += printf(" at"); + siba_cc_clock(scc, SIBA_CLOCK_SLOW); +} - retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); - retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); +static void +siba_cc_resume(struct siba_cc *scc) +{ - return (retval); + siba_cc_power_init(scc); + siba_cc_clock(scc, SIBA_CLOCK_FAST); } -static struct resource_list * -siba_get_reslist(device_t dev, device_t child) +int +siba_suspend(struct siba_softc *siba) { - struct siba_devinfo *sdi = device_get_ivars(child); - return (&sdi->sdi_rl); + siba_cc_suspend(&siba->siba_cc); + siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0); + return (0); } -static device_method_t siba_methods[] = { - /* Device interface */ - DEVMETHOD(device_attach, siba_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_probe, siba_probe), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), +int +siba_resume(struct siba_softc *siba) +{ - /* Bus interface */ - DEVMETHOD(bus_activate_resource,siba_activate_resource), - DEVMETHOD(bus_add_child, siba_add_child), - DEVMETHOD(bus_alloc_resource, siba_alloc_resource), - DEVMETHOD(bus_get_resource_list,siba_get_reslist), - DEVMETHOD(bus_print_child, siba_print_child), - DEVMETHOD(bus_probe_nomatch, siba_probe_nomatch), - DEVMETHOD(bus_read_ivar, siba_read_ivar), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - DEVMETHOD(bus_write_ivar, siba_write_ivar), + siba->siba_pci.spc_inited = 0; + siba->siba_curdev = NULL; - {0, 0}, -}; + siba_powerup(siba, 0); + /* XXX setup H/W for PCMCIA??? */ + siba_cc_resume(&siba->siba_cc); + siba_powerdown(siba); -static driver_t siba_driver = { - "siba", - siba_methods, - sizeof(struct siba_softc), -}; -static devclass_t siba_devclass; - -DRIVER_MODULE(siba, nexus, siba_driver, siba_devclass, 0, 0); + return (0); +} Index: sys/dev/siba/sibareg.h =================================================================== --- sys/dev/siba/sibareg.h (revision 202165) +++ sys/dev/siba/sibareg.h (working copy) @@ -1,73 +1,434 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. + * 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. - * 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. + * 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. * - * 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$ + * 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. */ +#ifndef _IF_BWN_SSBREG_H +#define _IF_BWN_SSBREG_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 + /* - * TODO: sprom - * TODO: implement dma translation bits (if needed for system bus) + * ChipCommon registers. */ +#define SIBA_CC_CHIPID 0x0000 +#define SIBA_CC_ID(id) (id & 0x0000ffff) +#define SIBA_CC_REV(id) ((id & 0x000f0000) >> 16) +#define SIBA_CC_PKG(id) ((id & 0x00f00000) >> 20) +#define SIBA_CC_NCORES(id) ((id & 0x0f000000) >> 24) +#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_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_PLLCTL_ADDR 0x0660 +#define SIBA_CC_PLLCTL_DATA 0x0664 -#ifndef _SIBA_SIBAREG_H_ -#define _SIBA_SIBAREG_H_ +#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_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_CC_PMU0_DEFAULT_XTALFREQ 20000 +#define SIBA_CC_PMU1_DEFAULT_FREQ 15360 -/* offset of high ID register */ -#define SIBA_CORE_IDLO 0x00000ff8 -#define SIBA_CORE_IDHI 0x00000ffc +#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_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_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 + /* - * Offsets of ChipCommon core registers. - * XXX: move to siba_cc + * Device IDs */ -#define SIBA_CC_UART0 0x00000300 /* offset of UART0 */ -#define SIBA_CC_UART1 0x00000400 /* offset of UART1 */ +#define SIBA_DEVID_ANY 0xffff +#define SIBA_DEVID_CHIPCOMMON 0x800 +#define SIBA_DEVID_ILINE20 0x801 +#define SIBA_DEVID_SDRAM 0x803 +#define SIBA_DEVID_PCI 0x804 +#define SIBA_DEVID_MIPS 0x805 +#define SIBA_DEVID_ETHERNET 0x806 +#define SIBA_DEVID_MODEM 0x807 +#define SIBA_DEVID_USB11_HOSTDEV 0x808 +#define SIBA_DEVID_ADSL 0x809 +#define SIBA_DEVID_ILINE100 0x80a +#define SIBA_DEVID_IPSEC 0x80b +#define SIBA_DEVID_PCMCIA 0x80d +#define SIBA_DEVID_INTERNAL_MEM 0x80e +#define SIBA_DEVID_SDRAMDDR 0x80f +#define SIBA_DEVID_EXTIF 0x811 +#define SIBA_DEVID_80211 0x812 +#define SIBA_DEVID_MIPS_3302 0x816 +#define SIBA_DEVID_USB11_HOST 0x817 +#define SIBA_DEVID_USB11_DEV 0x818 +#define SIBA_DEVID_USB20_HOST 0x819 +#define SIBA_DEVID_USB20_DEV 0x81a +#define SIBA_DEVID_SDIO_HOST 0x81b +#define SIBA_DEVID_ROBOSWITCH 0x81c +#define SIBA_DEVID_PARA_ATA 0x81d +#define SIBA_DEVID_SATA_XORDMA 0x81e +#define SIBA_DEVID_ETHERNET_GBIT 0x81f +#define SIBA_DEVID_PCIE 0x820 +#define SIBA_DEVID_MIMO_PHY 0x821 +#define SIBA_DEVID_SRAM_CTRLR 0x822 +#define SIBA_DEVID_MINI_MACPHY 0x823 +#define SIBA_DEVID_ARM_1176 0x824 +#define SIBA_DEVID_ARM_7TDMI 0x825 -#define SIBA_CC_CCID 0x0000 -#define SIBA_CC_IDMASK 0x0000FFFF -#define SIBA_CC_REVMASK 0x000F0000 -#define SIBA_CC_REVSHIFT 16 -#define SIBA_CC_PACKMASK 0x00F00000 -#define SIBA_CC_PACKSHIFT 20 -#define SIBA_CC_NRCORESMASK 0x0F000000 -#define SIBA_CC_NRCORESSHIFT 24 +/* + * Vendor IDs + */ +#define SIBA_VID_ANY 0xffff +#define SIBA_VID_BROADCOM 0x4243 -#define SIBA_IDHIGH_RCLO 0x0000000F /* Revision Code (low part) */ -#define SIBA_IDHIGH_CC 0x00008FF0 /* Core Code */ -#define SIBA_IDHIGH_CC_SHIFT 4 -#define SIBA_IDHIGH_RCHI 0x00007000 /* Revision Code (high part) */ -#define SIBA_IDHIGH_RCHI_SHIFT 8 -#define SIBA_IDHIGH_VC 0xFFFF0000 /* Vendor Code */ -#define SIBA_IDHIGH_VC_SHIFT 16 +#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_CCID_BCM4710 0x4710 -#define SIBA_CCID_BCM4704 0x4704 -#define SIBA_CCID_SENTRY5 0x5365 +#define SIBA_REGWIN(x) \ + (SIBA_ENUM_START + ((x) * SIBA_CORESIZE)) +#define SIBA_CORESIZE 0x1000 +#define SIBA_MAX_CORES \ + ((SIBA_ENUM_END - SIBA_ENUM_START) / SIBA_CORESIZE) +#define SIBA_ENUM_START 0x18000000U +#define SIBA_ENUM_END 0x18010000U -#endif /* _SIBA_SIBAREG_H_ */ +#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_REVLO 0x0000000f +#define SIBA_IDHIGH_REVHI 0x00007000 +#define SIBA_IDHIGH_CORECODE(id) ((id & 0x8ff0) >> 4) +#define SIBA_IDHIGH_REV(id) \ + ((id & SIBA_IDHIGH_REVLO) | ((id & SIBA_IDHIGH_REVHI) >> 8)) +#define SIBA_IDHIGH_VENDOR(id) ((id & 0xffff0000) >> 16) + +#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 +#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_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_AGAIN23 0x10a0 +#define SIBA_SPROM8_AGAIN2 0x00ff +#define SIBA_SPROM8_AGAIN3 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_MAXP_BG 0x10c0 +#define SIBA_SPROM8_MAXP_BG_MASK 0x00ff +#define SIBA_SPROM8_TSSI_BG 0xff00 +#define SIBA_SPROM8_MAXP_A 0x10c8 +#define SIBA_SPROM8_MAXP_A_MASK 0x00ff +#define SIBA_SPROM8_TSSI_A 0xff00 + +#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_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 + +#endif Index: sys/dev/siba/siba_ids.h =================================================================== --- sys/dev/siba/siba_ids.h (revision 202165) +++ sys/dev/siba/siba_ids.h (working copy) @@ -1,71 +0,0 @@ -/*- - * 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_SIBA_IDS_H_ -#define _SIBA_SIBA_IDS_H_ - -/* - * Constants and structures for SiBa bus enumeration. - */ - -struct siba_devid { - uint16_t sd_vendor; - uint16_t sd_device; - uint8_t sd_rev; - char *sd_desc; -}; - -/* - * Device IDs - */ -#define SIBA_DEVID_ANY 0xffff -#define SIBA_DEVID_CHIPCOMMON 0x0800 -#define SIBA_DEVID_INSIDELINE 0x0801 -#define SIBA_DEVID_SDRAM 0x0803 -#define SIBA_DEVID_PCI 0x0804 -#define SIBA_DEVID_MIPS 0x0805 -#define SIBA_DEVID_ETHERNET 0x0806 -#define SIBA_DEVID_MODEM 0x0807 -#define SIBA_DEVID_USB 0x0808 -#define SIBA_DEVID_IPSEC 0x080b -#define SIBA_DEVID_SDRAMDDR 0x080f -#define SIBA_DEVID_EXTIF 0x0811 -#define SIBA_DEVID_MIPS_3302 0x0816 - -/* - * Vendor IDs - */ -#define SIBA_VID_ANY 0xffff -#define SIBA_VID_BROADCOM 0x4243 - -/* - * Revision IDs - */ -#define SIBA_REV_ANY 0xff - -#endif /*_SIBA_SIBA_IDS_H_ */ Index: sys/dev/siba/siba_cc.c =================================================================== --- sys/dev/siba/siba_cc.c (revision 202165) +++ sys/dev/siba/siba_cc.c (working copy) @@ -1,154 +0,0 @@ -/*- - * 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. - */ - -/* - * Child driver for ChipCommon core. - * This is not MI code at the moment. - * Two 16C550 compatible UARTs live here. On the WGT634U, uart1 is the - * system console, and uart0 is not pinned out. - * Because their presence is conditional, they should probably - * be attached from here. - * GPIO lives here. - * The hardware watchdog lives here. - * Clock control registers live here. - * You don't need to read them to determine the clock speed on the 5365, - * which is always 200MHz and thus may be hardcoded (for now). - * Flash config registers live here. There may or may not be system flash. - * The external interface bus lives here (conditionally). - * There is a JTAG interface here which may be used to attach probes to - * the SoC for debugging. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -static int siba_cc_attach(device_t); -static int siba_cc_probe(device_t); -static void siba_cc_intr(void *v); - -static int -siba_cc_probe(device_t dev) -{ - - if (siba_get_vendor(dev) == SIBA_VID_BROADCOM && - siba_get_device(dev) == SIBA_DEVID_CHIPCOMMON) { - device_set_desc(dev, "ChipCommon core"); - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -struct siba_cc_softc { - void *notused; -}; - -static int -siba_cc_attach(device_t dev) -{ - //struct siba_cc_softc *sc = device_get_softc(dev); - struct resource *mem; - struct resource *irq; - int rid; - - /* - * Allocate the resources which the parent bus has already - * determined for us. - * TODO: interrupt routing - */ -#define MIPS_MEM_RID 0x20 - rid = MIPS_MEM_RID; - mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (mem == NULL) { - device_printf(dev, "unable to allocate memory\n"); - return (ENXIO); - } - - rid = 0; - irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0); - if (irq == NULL) { - device_printf(dev, "unable to allocate irq\n"); - return (ENXIO); - } - - /* now setup the interrupt */ - /* may be fast, exclusive or mpsafe at a later date */ - - /* - * XXX is this interrupt line in ChipCommon used for anything - * other than the uart? in that case we shouldn't hog it ourselves - * and let uart claim it to avoid polled mode. - */ - int err; - void *cookie; - err = bus_setup_intr(dev, irq, INTR_TYPE_TTY, NULL, siba_cc_intr, NULL, - &cookie); - if (err != 0) { - device_printf(dev, "unable to setup intr\n"); - return (ENXIO); - } - - /* TODO: attach uart child */ - - return (0); -} - -static void -siba_cc_intr(void *v) -{ - -} - -static device_method_t siba_cc_methods[] = { - /* Device interface */ - DEVMETHOD(device_attach, siba_cc_attach), - DEVMETHOD(device_probe, siba_cc_probe), - - {0, 0}, -}; - -static driver_t siba_cc_driver = { - "siba_cc", - siba_cc_methods, - sizeof(struct siba_softc), -}; -static devclass_t siba_cc_devclass; - -DRIVER_MODULE(siba_cc, siba, siba_cc_driver, siba_cc_devclass, 0, 0); Index: sys/dev/siba/siba_pcibvar.h =================================================================== --- sys/dev/siba/siba_pcibvar.h (revision 202165) +++ sys/dev/siba/siba_pcibvar.h (working copy) @@ -1,52 +0,0 @@ -/*- - * 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_PCIBVAR_H_ -#define _SIBA_PCIBVAR_H_ - -#include - -struct siba_pcib_softc { - device_t sc_dev; /* Device ID */ - u_int sc_bus; /* PCI bus number */ - struct resource *sc_mem; /* siba memory window */ - struct resource *sc_csr; /* config space */ - - bus_space_tag_t sc_bt; - bus_space_handle_t sc_bh; -#if 0 - bus_addr_t sc_maddr; - bus_size_t sc_msize; - - struct bus_space sc_pci_memt; - struct bus_space sc_pci_iot; - bus_dma_tag_t sc_dmat; -#endif -}; - -#endif /* _SIBA_PCIBVAR_H_ */ Index: sys/dev/siba/siba_pcib.c =================================================================== --- sys/dev/siba/siba_pcib.c (revision 202165) +++ sys/dev/siba/siba_pcib.c (working copy) @@ -1,433 +1,310 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. + * 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. - * 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. + * 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. * - * 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. + * 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. */ -/* - * Child driver for PCI host bridge core. - */ - #include __FBSDID("$FreeBSD$"); +/* + * PCI/Cardbus front-end for 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 -#include -#include -#include -#include - -#include #include -#include +#include -#include "pcib_if.h" - -#include #include -#include -#include +#include -#ifndef MIPS_MEM_RID -#define MIPS_MEM_RID 0x20 -#endif - -#define SBPCI_SLOTMAX 15 - -#define SBPCI_READ_4(sc, reg) \ - bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg)) - -#define SBPCI_WRITE_4(sc, reg, val) \ - bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg), (val)) - /* - * PCI Configuration space window (64MB). - * contained in SBTOPCI1 window. + * PCI glue. */ -#define SBPCI_CFGBASE 0x0C000000 -#define SBPCI_CFGSIZE 0x01000000 -#define SBPCI_SBTOPCI0 0x100 -#define SBPCI_SBTOPCI1 0x104 -#define SBPCI_SBTOPCI2 0x108 +struct siba_pci_softc { + struct siba_softc psc_siba; +}; -/* - * TODO: implement type 1 config space access (ie beyond bus 0) - * we may need to tweak the windows to do this - * TODO: interrupt routing. - * TODO: fully implement bus allocation. - * TODO: implement resource managers. - * TODO: code cleanup. - */ +#define BS_BAR 0x10 +#define PCI_VENDOR_BROADCOM 0x14e4 +#define N(a) (sizeof(a) / sizeof(a[0])) -static int siba_pcib_activate_resource(device_t, device_t, int, - int, struct resource *); -static struct resource * - siba_pcib_alloc_resource(device_t, device_t, int, int *, - u_long , u_long, u_long, u_int); -static int siba_pcib_attach(device_t); -static int siba_pcib_deactivate_resource(device_t, device_t, int, - int, struct resource *); -static int siba_pcib_maxslots(device_t); -static int siba_pcib_probe(device_t); -static u_int32_t - siba_pcib_read_config(device_t, u_int, u_int, u_int, u_int, +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 BCM4315 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, 0x4329, "Unknown" }, + { PCI_VENDOR_BROADCOM, 0x432b, "Unknown" } +}; + +device_t siba_add_child(device_t, struct siba_softc *, int, const char *, int); -static int siba_pcib_read_ivar(device_t, device_t, int, uintptr_t *); -static int siba_pcib_release_resource(device_t, device_t, int, int, - struct resource *); -static int siba_pcib_route_interrupt(device_t, device_t, int); -static int siba_pcib_setup_intr(device_t, device_t, struct resource *, - int, driver_filter_t *, driver_intr_t *, void *, void **); -static int siba_pcib_teardown_intr(device_t, device_t, struct resource *, - void *); -static void siba_pcib_write_config(device_t, u_int, u_int, u_int, u_int, - u_int32_t, int); -static int siba_pcib_write_ivar(device_t, device_t, int, uintptr_t); +int siba_suspend(struct siba_softc *); +int siba_resume(struct siba_softc *); static int -siba_pcib_probe(device_t dev) +siba_pci_probe(device_t dev) { + int i; + uint16_t did, vid; - /* TODO: support earlier cores. */ - /* TODO: Check if PCI host mode is enabled in the SPROM. */ - if (siba_get_vendor(dev) == SIBA_VID_BROADCOM && - siba_get_device(dev) == SIBA_DEVID_PCI) { - device_set_desc(dev, "SiBa-to-PCI host bridge"); - return (BUS_PROBE_DEFAULT); - } + 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); } -//extern int rman_debug; - static int -siba_pcib_attach(device_t dev) +siba_pci_attach(device_t dev) { - struct siba_pcib_softc *sc = device_get_softc(dev); - int rid; + struct siba_pci_softc *psc = device_get_softc(dev); + struct siba_softc *siba = &psc->psc_siba; + siba->siba_dev = dev; + siba->siba_type = SIBA_TYPE_PCI; + /* - * Allocate the resources which the parent bus has already - * determined for us. + * Enable bus mastering. */ - rid = MIPS_MEM_RID; /* XXX */ - //rman_debug = 1; - sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->sc_mem == NULL) { - device_printf(dev, "unable to allocate memory\n"); - return (ENXIO); - } + pci_enable_busmaster(dev); - sc->sc_bt = rman_get_bustag(sc->sc_mem); - sc->sc_bh = rman_get_bushandle(sc->sc_mem); - - device_printf(dev, "bridge registers addr 0x%08x vaddr %p\n", - (uint32_t)sc->sc_bh, rman_get_virtual(sc->sc_mem)); - - SBPCI_WRITE_4(sc, 0x0000, 0x05); - SBPCI_WRITE_4(sc, 0x0000, 0x0D); - DELAY(150); - SBPCI_WRITE_4(sc, 0x0000, 0x0F); - SBPCI_WRITE_4(sc, 0x0010, 0x01); - DELAY(1); - - bus_space_handle_t sc_cfg_hand; - int error; - - /* - * XXX this doesn't actually do anything on mips; however... should - * we not be mapping to KSEG1? we need to wire down the range. + /* + * Setup memory-mapping of PCI registers. */ - error = bus_space_map(sc->sc_bt, SBPCI_CFGBASE, SBPCI_CFGSIZE, - 0, &sc_cfg_hand); - if (error) { - device_printf(dev, "cannot map PCI configuration space\n"); + 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); } - device_printf(dev, "mapped pci config space at 0x%08x\n", - (uint32_t)sc_cfg_hand); + siba->siba_mem_bt = rman_get_bustag(siba->siba_mem_res); + siba->siba_mem_bh = rman_get_bushandle(siba->siba_mem_res); - /* - * Setup configuration, io, and dma space windows. - * XXX we need to be able to do type 1 too. - * we probably don't need to be able to do i/o cycles. - */ - SBPCI_WRITE_4(sc, SBPCI_SBTOPCI0, 1); /* I/O read/write window */ - SBPCI_WRITE_4(sc, SBPCI_SBTOPCI1, 2); /* type 0 configuration only */ - SBPCI_WRITE_4(sc, SBPCI_SBTOPCI2, 1 << 30); /* memory only */ - DELAY(500); + /* 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); - /* XXX resource managers */ - - device_add_child(dev, "pci", -1); - return (bus_generic_attach(dev)); + return (siba_attach(siba)); } -/* bus functions */ - static int -siba_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +siba_pci_detach(device_t dev) { - struct siba_pcib_softc *sc; + struct siba_pci_softc *psc = device_get_softc(dev); + struct siba_softc *siba = &psc->psc_siba; - sc = device_get_softc(dev); - switch (which) { - case PCIB_IVAR_BUS: - *result = sc->sc_bus; - return (0); - } + /* check if device was removed */ + siba->siba_invalid = !bus_child_present(dev); - return (ENOENT); + pci_disable_busmaster(dev); + bus_generic_detach(dev); + siba_detach(siba); + bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res); + + return (0); } static int -siba_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +siba_pci_shutdown(device_t dev) { - struct siba_pcib_softc *sc; + device_t *devlistp; + int devcnt, error = 0, i; - sc = device_get_softc(dev); - switch (which) { - case PCIB_IVAR_BUS: - sc->sc_bus = value; - return (0); - } + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); - return (ENOENT); + for (i = 0 ; i < devcnt ; i++) + device_shutdown(devlistp[i]); + free(devlistp, M_TEMP); + return (0); } static int -siba_pcib_setup_intr(device_t dev, device_t child, struct resource *ires, - int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, - void **cookiep) +siba_pci_suspend(device_t dev) { + struct siba_pci_softc *psc = device_get_softc(dev); + struct siba_softc *siba = &psc->psc_siba; + device_t *devlistp; + int devcnt, error = 0, i, j; - return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - filt, intr, arg, cookiep)); -} + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); -static int -siba_pcib_teardown_intr(device_t dev, device_t child, struct resource *vec, - void *cookie) -{ - - return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec, cookie)); -} - -static struct resource * -siba_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ -#if 1 - - //device_printf(bus, "%s: not yet implemented\n", __func__); - return (NULL); -#else - bus_space_tag_t tag; - struct siba_pcib_softc *sc = device_get_softc(bus); - struct rman *rmanp; - struct resource *rv; - - tag = 0; - rv = NULL; - switch (type) { - case SYS_RES_IRQ: - rmanp = &sc->sc_irq_rman; - break; - - case SYS_RES_MEMORY: - rmanp = &sc->sc_mem_rman; - tag = &sc->sc_pci_memt; - break; - - default: - return (rv); - } - - rv = rman_reserve_resource(rmanp, start, end, count, flags, child); - if (rv != NULL) { - rman_set_rid(rv, *rid); - if (type == SYS_RES_MEMORY) { -#if 0 - rman_set_bustag(rv, tag); - rman_set_bushandle(rv, rman_get_bushandle(sc->sc_mem) + - (rman_get_start(rv) - IXP425_PCI_MEM_HWBASE)); -#endif + for (i = 0 ; i < devcnt ; i++) { + error = DEVICE_SUSPEND(devlistp[i]); + if (error) { + for (j = 0; j < i; i++) + DEVICE_RESUME(devlistp[j]); + return (error); } } - - return (rv); -#endif + free(devlistp, M_TEMP); + return (siba_suspend(siba)); } static int -siba_pcib_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +siba_pci_resume(device_t dev) { + struct siba_pci_softc *psc = device_get_softc(dev); + struct siba_softc *siba = &psc->psc_siba; + device_t *devlistp; + int devcnt, error = 0, i; - device_printf(bus, "%s: not yet implemented\n", __func__); - device_printf(bus, "%s called activate_resource\n", - device_get_nameunit(child)); - return (ENXIO); -} + error = siba_resume(siba); + if (error != 0) + return (error); -static int -siba_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); - device_printf(bus, "%s: not yet implemented\n", __func__); - device_printf(bus, "%s called deactivate_resource\n", - device_get_nameunit(child)); - return (ENXIO); + for (i = 0 ; i < devcnt ; i++) + DEVICE_RESUME(devlistp[i]); + free(devlistp, M_TEMP); + return (0); } -static int -siba_pcib_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +static device_t +siba_pci_add_child(device_t dev, int order, const char *name, int unit) { + struct siba_pci_softc *psc = device_get_softc(dev); + struct siba_softc *siba = &psc->psc_siba; - device_printf(bus, "%s: not yet implemented\n", __func__); - device_printf(bus, "%s called release_resource\n", - device_get_nameunit(child)); - return (ENXIO); + return (siba_add_child(dev, siba, order, name, unit)); } -/* pcib interface functions */ - -static int -siba_pcib_maxslots(device_t dev) +/* proxying to the parent */ +static struct resource * +siba_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) { - return (SBPCI_SLOTMAX); + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + type, rid, start, end, count, flags)); } -/* - * This needs hacking and fixery. It is currently broke and hangs. - * Debugging it will be tricky; there seems to be no way to enable - * a target abort which would cause a nice target abort. - * Look at linux again? - */ -static u_int32_t -siba_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) +/* proxying to the parent */ +static int +siba_pci_release_resource(device_t dev, device_t child, int type, + int rid, struct resource *r) { - struct siba_pcib_softc *sc = device_get_softc(dev); - bus_addr_t cfgaddr; - uint32_t cfgtag; - uint32_t val; - /* XXX anything higher than slot 2 currently seems to hang the bus. - * not sure why this is; look at linux again - */ - if (bus != 0 || slot > 2) { - printf("%s: bad b/s/f %d/%d/%d\n", __func__, bus, slot, func); - return 0xffffffff; // XXX - } - - device_printf(dev, "requested %d bytes from b/s/f %d/%d/%d reg %d\n", - bytes, bus, slot, func, reg); - - /* - * The configuration tag on the broadcom is weird. - */ - SBPCI_WRITE_4(sc, SBPCI_SBTOPCI1, 2); /* XXX again??? */ - cfgtag = ((1 << slot) << 16) | (func << 8); - cfgaddr = SBPCI_CFGBASE | cfgtag | (reg & ~3); - - /* cfg space i/o is always 32 bits on this bridge */ - printf("reading 4 bytes from %08x\n", cfgaddr); - val = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(cfgaddr); /* XXX MIPS */ - - val = bswap32(val); /* XXX seems to be needed for now */ - - /* swizzle and return what was asked for */ - val &= 0xffffffff >> ((4 - bytes) * 8); - - return (val); + return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type, + rid, r)); } -static void -siba_pcib_write_config(device_t dev, u_int bus, u_int slot, - u_int func, u_int reg, u_int32_t val, int bytes) +/* proxying to the parent */ +static int +siba_pci_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) { - /* write to pci configuration space */ - //device_printf(dev, "%s: not yet implemented\n", __func__); + return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, + filter, intr, arg, cookiep)); } +/* proxying to the parent */ static int -siba_pcib_route_interrupt(device_t bridge, device_t device, int pin) +siba_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) { - //device_printf(bridge, "%s: not yet implemented\n", __func__); - return (-1); + return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); } -static device_method_t siba_pcib_methods[] = { +static device_method_t siba_pci_methods[] = { /* Device interface */ - DEVMETHOD(device_attach, siba_pcib_attach), - DEVMETHOD(device_probe, siba_pcib_probe), + DEVMETHOD(device_probe, siba_pci_probe), + DEVMETHOD(device_attach, siba_pci_attach), + DEVMETHOD(device_detach, siba_pci_detach), + DEVMETHOD(device_shutdown, siba_pci_shutdown), + DEVMETHOD(device_suspend, siba_pci_suspend), + DEVMETHOD(device_resume, siba_pci_resume), /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, siba_pcib_read_ivar), - DEVMETHOD(bus_write_ivar, siba_pcib_write_ivar), - DEVMETHOD(bus_setup_intr, siba_pcib_setup_intr), - DEVMETHOD(bus_teardown_intr, siba_pcib_teardown_intr), - DEVMETHOD(bus_alloc_resource, siba_pcib_alloc_resource), - DEVMETHOD(bus_activate_resource, siba_pcib_activate_resource), - DEVMETHOD(bus_deactivate_resource, siba_pcib_deactivate_resource), - DEVMETHOD(bus_release_resource, siba_pcib_release_resource), + DEVMETHOD(bus_add_child, siba_pci_add_child), + DEVMETHOD(bus_alloc_resource, siba_pci_alloc_resource), + DEVMETHOD(bus_release_resource, siba_pci_release_resource), + DEVMETHOD(bus_setup_intr, siba_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, siba_pci_teardown_intr), - /* pcib interface */ - DEVMETHOD(pcib_maxslots, siba_pcib_maxslots), - DEVMETHOD(pcib_read_config, siba_pcib_read_config), - DEVMETHOD(pcib_write_config, siba_pcib_write_config), - DEVMETHOD(pcib_route_interrupt, siba_pcib_route_interrupt), - - {0, 0}, + { 0,0 } }; - -static driver_t siba_pcib_driver = { - "pcib", - siba_pcib_methods, - sizeof(struct siba_softc), +static driver_t siba_pci_driver = { + "siba", + siba_pci_methods, + sizeof(struct siba_pci_softc) }; -static devclass_t siba_pcib_devclass; - -DRIVER_MODULE(siba_pcib, siba, siba_pcib_driver, siba_pcib_devclass, 0, 0); +static devclass_t siba_pci_devclass; +DRIVER_MODULE(siba, pci, siba_pci_driver, siba_pci_devclass, 0, 0); +MODULE_VERSION(siba, 1); Index: sys/dev/siba/sibavar.h =================================================================== --- sys/dev/siba/sibavar.h (revision 202165) +++ sys/dev/siba/sibavar.h (working copy) @@ -1,92 +1,325 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. + * 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. - * 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. + * 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. * - * 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$ + * 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. */ -#ifndef _SIBA_SIBAVAR_H_ -#define _SIBA_SIBAVAR_H_ +#ifndef _IF_BWN_SSBVAR_H +#define _IF_BWN_SSBVAR_H -#include +struct siba_softc; +struct siba_dev_softc; -struct siba_softc { - device_t sc_dev; /* Device ID */ - struct resource *sc_mem; /* Memory window on nexus */ +/* 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, +}; - bus_space_tag_t sc_bt; - bus_space_handle_t sc_bh; - bus_addr_t sc_maddr; - bus_size_t sc_msize; +#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)) - uint8_t sc_ncores; +#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((scc)->scc_dev, offset) +#define SIBA_CC_WRITE32(scc, offset, val) \ + siba_write_4((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_type { + SIBA_TYPE_SSB, + SIBA_TYPE_PCI, + SIBA_TYPE_PCMCIA, }; -struct siba_devinfo { - struct resource_list sdi_rl; - /*devhandle_t sdi_devhandle; XXX*/ - /*struct rman sdi_intr_rman;*/ +enum siba_clock { + SIBA_CLOCK_DYNAMIC, + SIBA_CLOCK_SLOW, + SIBA_CLOCK_FAST, +}; - /* 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 */ +enum siba_clksrc { + SIBA_CC_CLKSRC_PCI, + SIBA_CC_CLKSRC_CRYSTAL, + SIBA_CC_CLKSRC_LOWPW, }; -#define siba_read_2(sc, core, reg) \ - bus_space_read_2((sc)->sc_bt, (sc)->sc_bh, \ - (core * SIBA_CORE_LEN) + (reg)) +struct siba_cc_pmu0_plltab { + uint16_t freq; /* in kHz.*/ + uint8_t xf; /* crystal frequency */ + uint8_t wb_int; + uint32_t wb_frac; +}; -#define siba_read_4(sc, core, reg) \ - bus_space_read_4((sc)->sc_bt, (sc)->sc_bh, \ - (core * SIBA_CORE_LEN) + (reg)) +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; +}; -#define siba_write_2(sc, core, reg, val) \ - bus_space_write_2((sc)->sc_bt, (sc)->sc_bh, \ - (core * SIBA_CORE_LEN) + (reg), (val)) +struct siba_cc_pmu_res_updown { + uint8_t res; + uint16_t updown; +}; -#define siba_write_4(sc, core, reg, val) \ - bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, \ - (core * SIBA_CORE_LEN) + (reg), (val)) +#define SIBA_CC_PMU_DEP_SET 1 +#define SIBA_CC_PMU_DEP_ADD 2 +#define SIBA_CC_PMU_DEP_REMOVE 3 -enum siba_device_ivars { - SIBA_IVAR_VENDOR, - SIBA_IVAR_DEVICE, - SIBA_IVAR_REVID, - SIBA_IVAR_CORE_INDEX +struct siba_cc_pmu_res_depend { + uint8_t res; + uint8_t task; + uint32_t depend; }; -#define SIBA_ACCESSOR(var, ivar, type) \ - __BUS_ACCESSOR(siba, var, SIBA, ivar, type) +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; + uint8_t gpio0; + uint8_t gpio1; + uint8_t gpio2; + uint8_t gpio3; + uint16_t maxpwr_a; /* A-PHY Max Power */ + uint16_t maxpwr_bg; /* BG-PHY Max Power */ + uint8_t tssi_a; /* Idle TSSI */ + uint8_t tssi_bg; /* Idle TSSI */ + uint16_t bf_lo; /* boardflags */ + uint16_t bf_hi; /* boardflags */ + struct { + struct { + int8_t a0, a1, a2, a3; + } ghz24; + struct { + int8_t a0, a1, a2, a3; + } ghz5; + } again; /* antenna gain */ +}; -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) +struct siba_cc_pmu { + uint8_t rev; /* PMU rev */ + uint32_t freq; /* crystal freq in kHz */ +}; -#undef SIBA_ACCESSOR +struct siba_cc { + struct siba_dev_softc *scc_dev; + uint32_t scc_caps; + struct siba_cc_pmu scc_pmu; + uint16_t scc_powerup_delay; +}; -#endif /* _SIBA_SIBAVAR_H_ */ +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); +}; + +/* SSB device ID */ +struct siba_devid { + uint16_t vendor; + uint16_t cid; + uint8_t rev; +}; +#define SIBA_DEV(_vendor, _cid, _rev) \ + { SIBA_VID_##_vendor, SIBA_DEVID_##_cid, _rev, } + +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_softc { + device_t siba_dev; + 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; + int siba_mem_rid; + struct resource *siba_mem_res; + bus_space_tag_t siba_mem_bt; + bus_space_handle_t siba_mem_bh; + + 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; + + /* board informations */ + uint16_t siba_board_vendor; + uint16_t siba_board_type; + uint16_t siba_board_rev; + struct siba_sprom siba_sprom; /* SPROM */ + uint16_t siba_spromsize; /* in word size */ +}; + +int siba_attach(struct siba_softc *); +int siba_detach(struct siba_softc *); +void siba_powerup(struct siba_softc *, int); +uint16_t siba_read_2(struct siba_dev_softc *, uint16_t); +void siba_write_2(struct siba_dev_softc *, uint16_t, uint16_t); +uint32_t siba_read_4(struct siba_dev_softc *, uint16_t); +void siba_write_4(struct siba_dev_softc *, uint16_t, uint32_t); +void siba_dev_up(struct siba_dev_softc *, uint32_t); +void siba_dev_down(struct siba_dev_softc *, uint32_t); +int siba_powerdown(struct siba_softc *); +int siba_dev_isup(struct siba_dev_softc *); +void siba_pcicore_intr(struct siba_pci *, struct siba_dev_softc *); +uint32_t siba_dma_translation(struct siba_dev_softc *); +void *siba_dma_alloc_consistent(struct siba_dev_softc *, size_t, + bus_addr_t *); +void siba_read_multi_1(struct siba_dev_softc *, void *, size_t, + uint16_t); +void siba_read_multi_2(struct siba_dev_softc *, void *, size_t, + uint16_t); +void siba_read_multi_4(struct siba_dev_softc *, void *, size_t, + uint16_t); +void siba_write_multi_1(struct siba_dev_softc *, const void *, + size_t, uint16_t); +void siba_write_multi_2(struct siba_dev_softc *, const void *, + size_t, uint16_t); +void siba_write_multi_4(struct siba_dev_softc *, const void *, + size_t, uint16_t); +void siba_barrier(struct siba_dev_softc *, int); + +#endif