From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:45:28 +0000 Subject: [PATCH] add boot partition size --- kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/siutils.c | 1759 +++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 1,183 insertions(+), 576 deletions(-) diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/siutils.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/siutils.c index cb64267..f2746a3 100644 --- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/siutils.c +++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/siutils.c @@ -1,16 +1,17 @@ -/* SPDX-License-Identifier: GPL-2.0 */ /* * Misc utility routines for accessing chip-specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2019, Broadcom Corporation - * + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation + * + * Copyright (C) 1999-2017, Broadcom Corporation + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -18,7 +19,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -26,7 +27,7 @@ * * <<Broadcom-WL-IPTag/Open:>> * - * $Id: siutils.c 722050 2019-08-21 02:24:57Z $ + * $Id: siutils.c 701025 2017-05-23 10:23:52Z $ */ #include <bcm_cfg.h> @@ -38,8 +39,12 @@ #include <bcmdevs.h> #include <hndsoc.h> #include <sbchipc.h> +#include <sbgci.h> +#ifndef BCMSDIO +#include <pcie_core.h> +#endif // endif #ifdef BCMPCIEDEV -#include <pciedev.h> +/ #endif /* BCMPCIEDEV */ #include <pcicfg.h> #include <sbpcmcia.h> @@ -54,10 +59,9 @@ #include <bcmsdpcm.h> #endif /* BCMSDIO */ #include <hndpmu.h> - -#ifdef LOAD_DHD_WITH_FW_ALIVE -#include <dhd_chip_info.h> -#endif +#ifdef BCMSPI +#include <spid.h> +#endif /* BCMSPI */ #ifdef BCM_SDRBL #include <hndcpu.h> @@ -65,8 +69,28 @@ #ifdef HNDGCI #include <hndgci.h> #endif /* HNDGCI */ +#ifdef WLGCIMBHLR +#include <hnd_gci.h> +#endif /* WLGCIMBHLR */ +#ifdef BCMULP +#include <ulp.h> +#endif /* BCMULP */ +#include <hndlhl.h> + +#include <lpflags.h> #include "siutils_priv.h" +#ifdef SECI_UART +/* Defines the set of GPIOs to be used for SECI UART if not specified in NVRAM */ +/* For further details on each ppin functionality please refer to PINMUX table in + * Top level architecture of BCMXXXX Chip + */ +#define DEFAULT_SECI_UART_PINMUX 0x08090a0b +#define DEFAULT_SECI_UART_PINMUX_43430 0x0102 +static bool force_seci_clk = 0; +#endif /* SECI_UART */ + +#define XTAL_FREQ_26000KHZ 26000 /** * A set of PMU registers is clocked in the ILP domain, which has an implication on register write @@ -83,26 +107,35 @@ (regoff) == OFFSETOF(chipcregs_t, pmuwatchdog) || \ (regoff) == OFFSETOF(chipcregs_t, res_req_timer)) +#define GCI_FEM_CTRL_WAR 0x11111111 + +#ifndef AXI_TO_VAL +#define AXI_TO_VAL 19 +#endif /* AXI_TO_VAL */ + +#ifndef AXI_TO_VAL_4347 +/* + * Increase BP timeout for fast clock and short PCIe timeouts + * New timeout: 2 ** 25 cycles + */ +#define AXI_TO_VAL_4347 25 +#endif /* AXI_TO_VAL_4347 */ + /* local prototypes */ -static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, +static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, uint bustype, void *sdh, char **vars, uint *varsz); static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, - uint *origidx, void *regs); - + uint *origidx, volatile void *regs); static bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff); - -#ifdef BCMLTECOEX -static void si_config_gcigpio(si_t *sih, uint32 gci_pos, uint8 gcigpio, - uint8 gpioctl_mask, uint8 gpioctl_val); -#endif /* BCMLTECOEX */ - /* global variable to indicate reservation/release of gpio's */ static uint32 si_gpioreservation = 0; /* global flag to prevent shared resources from being initialized multiple times in si_attach() */ +static bool si_onetimeinit = FALSE; + #ifdef SR_DEBUG static const uint32 si_power_island_test_array[] = { 0x0000, 0x0001, 0x0010, 0x0011, @@ -113,6 +146,11 @@ #endif /* SR_DEBUG */ int do_4360_pcie2_war = 0; + +#ifdef BCMULP +/* Variable to store boot_type: warm_boot/cold_boot/etc. */ +static int boot_type = 0; +#endif // endif /* global kernel resource */ static si_info_t ksii; @@ -130,19 +168,21 @@ * varsz - pointer to int to return the size of the vars */ si_t * -si_attach(uint devid, osl_t *osh, void *regs, +si_attach(uint devid, osl_t *osh, volatile void *regs, uint bustype, void *sdh, char **vars, uint *varsz) { si_info_t *sii; si_cores_info_t *cores_info; /* alloc si_info_t */ - if ((sii = MALLOCZ(osh, sizeof (si_info_t))) == NULL) { + /* freed after ucode download for firmware builds */ + if ((sii = MALLOCZ_NOPERSIST(osh, sizeof(si_info_t))) == NULL) { SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); return (NULL); } /* alloc si_cores_info_t */ - if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, sizeof (si_cores_info_t))) == NULL) { + if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, + sizeof(si_cores_info_t))) == NULL) { SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); MFREE(osh, sii, sizeof(si_info_t)); return (NULL); @@ -160,10 +200,39 @@ return (si_t *)sii; } +static uint32 wd_msticks; /**< watchdog timer ticks normalized to ms */ -static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ +/** Returns the backplane address of the chipcommon core for a particular chip */ +uint32 +si_enum_base(uint devid) +{ + // NIC/DHD build + switch (devid) { + case BCM7271_CHIP_ID: + case BCM7271_D11AC_ID: + case BCM7271_D11AC2G_ID: + case BCM7271_D11AC5G_ID: + return 0xF1800000; + } -/** generic kernel variant of si_attach() */ + return SI_ENUM_BASE_DEFAULT; +} + +/** Returns the backplane address of the PCIE core for a particular chip */ +uint32 +si_pcie_enum_base(uint devid) +{ + switch (devid) { + case CYW55560_WLAN_ID: + case CYW89570_WLAN_ID: + return SI_ENUM_PCIE2_BASE; + } + + /* Default - In future chips if devid is not matched */ + return SI_ENUM_PCIE2_BASE; +} + +/** generic kernel variant of si_attach(). Is not called for Linux WLAN NIC builds. */ si_t * si_kattach(osl_t *osh) { @@ -172,12 +241,14 @@ if (!ksii_attached) { void *regs = NULL; - regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + const uint device_id = BCM4710_DEVICE_ID; // pick an arbitrary default device_id + + regs = REG_MAP(si_enum_base(device_id), SI_CORE_SIZE); // map physical to virtual cores_info = (si_cores_info_t *)&ksii_cores_info; ksii.cores_info = cores_info; ASSERT(osh); - if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, + if (si_doattach(&ksii, device_id, osh, regs, SI_BUS, NULL, osh != SI_OSH ? &(ksii.vars) : NULL, osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) { @@ -189,30 +260,30 @@ /* save ticks normalized to ms for si_watchdog_ms() */ if (PMUCTL_ENAB(&ksii.pub)) { - /* based on 32KHz ILP clock */ - wd_msticks = 32; + /* based on 32KHz ILP clock */ + wd_msticks = 32; } else { wd_msticks = ALP_CLOCK / 1000; } ksii_attached = TRUE; SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", - ksii.pub.ccrev, wd_msticks)); + CCREV(ksii.pub.ccrev), wd_msticks)); } return &ksii.pub; } - static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) { + BCM_REFERENCE(sdh); + BCM_REFERENCE(devid); /* need to set memseg flag for CF card first before any sb registers access */ if (BUSTYPE(bustype) == PCMCIA_BUS) sii->memseg = TRUE; - -#if defined(BCMSDIO) +#if defined(BCMSDIO) && !defined(BCMSDIOLITE) if (BUSTYPE(bustype) == SDIO_BUS) { int err; uint8 clkset; @@ -245,7 +316,25 @@ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); } -#endif /* BCMSDIO && BCMDONGLEHOST */ +#ifdef BCMSPI + /* Avoid backplane accesses before wake-wlan (i.e. htavail) for spi. + * F1 read accesses may return correct data but with data-not-available dstatus bit set. + */ + if (BUSTYPE(bustype) == SPI_BUS) { + + int err; + uint32 regdata; + /* wake up wlan function :WAKE_UP goes as HT_AVAIL request in hardware */ + regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL); + SI_MSG(("F0 REG0 rd = 0x%x\n", regdata)); + regdata |= WAKE_UP; + + bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err); + + OSL_DELAY(100000); + } +#endif /* BCMSPI */ +#endif /* BCMSDIO && BCMDONGLEHOST && !BCMSDIOLITE */ return TRUE; } @@ -268,46 +357,31 @@ origidx = sii->curidx; pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0); pmu = si_setcoreidx(&sii->pub, pmucoreidx); - pmuaddr = (uint32)(unsigned long)((uint8*)pmu + offset); + pmuaddr = (uint32)(uintptr)((volatile uint8*)pmu + offset); si_setcoreidx(sih, origidx); } else - pmuaddr = SI_ENUM_BASE + offset; + pmuaddr = SI_ENUM_BASE(sih) + offset; done: - SI_MSG(("%s: addrRET: %x\n", __FUNCTION__, pmuaddr)); + printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr); return pmuaddr; } static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, - uint *origidx, void *regs) + uint *origidx, volatile void *regs) { si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; bool pci, pcie, pcie_gen2 = FALSE; uint i; uint pciidx, pcieidx, pcirev, pcierev; + struct si_pub *sih = &sii->pub; -#ifdef LOAD_DHD_WITH_FW_ALIVE - if(alive == FW_ALIVE_MAGIC) { - switch(card_dev) { - case BCM43430_CHIP_ID: - if(card_rev == 2) - memcpy(&sii->pub, &sii_pub_43436, sizeof(sii->pub)); - else - memcpy(&sii->pub, &sii_pub_43430, sizeof(sii->pub)); - break; - - case BCM43012_CHIP_ID: - memcpy(&sii->pub, &sii_pub_43012, sizeof(sii->pub)); - break; - } - return true; - } -#endif - +#if defined(BCM_BACKPLANE_TIMEOUT) || defined(AXI_TIMEOUTS) /* first, enable backplane timeouts */ - if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) - ai_enable_backplane_timeouts(&sii->pub); + si_slave_wrapper_add(&sii->pub); +#endif // endif + sii->curidx = 0; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); @@ -316,33 +390,50 @@ sii->pub.ccrev = (int)si_corerev(&sii->pub); /* get chipcommon chipstatus */ - if (sii->pub.ccrev >= 11) - sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); + if (CCREV(sii->pub.ccrev) >= 11) { + /* TODO : We need a better approach to avoid this access in secure mode chips */ + if (sii->pub.chip != CYW55500_CHIP_ID && + sii->pub.chip != CYW55560_CHIP_ID) { + sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); + } + } - /* get chipcommon capabilites */ - sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); - /* get chipcommon extended capabilities */ + if (!sih->chipidpresent) { + /* get chipcommon capabilites */ + sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); + /* get chipcommon extended capabilities */ + if (CCREV(sii->pub.ccrev) >= 35) + sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); - if (sii->pub.ccrev >= 35) - sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); + /* get pmu rev and caps */ + if (sii->pub.cccaps & CC_CAP_PMU) { + if (AOB_ENAB(&sii->pub)) { + uint pmucoreidx; + pmuregs_t *pmu; + struct si_pub *sih = &sii->pub; - /* get pmu rev and caps */ - if (sii->pub.cccaps & CC_CAP_PMU) { - if (AOB_ENAB(&sii->pub)) { - uint pmucoreidx; - pmuregs_t *pmu; - pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0); - pmu = si_setcoreidx(&sii->pub, pmucoreidx); - sii->pub.pmucaps = R_REG(sii->osh, &pmu->pmucapabilities); - si_setcoreidx(&sii->pub, SI_CC_IDX); - } else - sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); + pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0); + if (!GOODIDX(pmucoreidx)) { + SI_ERROR(("si_buscore_setup: si_findcoreidx failed\n")); + return FALSE; + } - sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; + pmu = si_setcoreidx(&sii->pub, pmucoreidx); + sii->pub.pmucaps = R_REG(sii->osh, &pmu->pmucapabilities); + si_setcoreidx(&sii->pub, SI_CC_IDX); + + sii->pub.gcirev = si_corereg(sih, GCI_CORE_IDX(sih), + GCI_OFFSETOF(sih, gci_corecaps0), 0, 0) & + GCI_CAP0_REV_MASK; + } else + sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); + + sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; + } } SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", - sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, + CCREV(sii->pub.ccrev), sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, sii->pub.pmucaps)); /* figure out bus/orignal core idx */ @@ -362,28 +453,23 @@ crev = si_corerev(&sii->pub); /* Display cores found */ - SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", - i, cid, crev, cores_info->coresba[i], cores_info->regs[i])); + SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x size:%x regs 0x%p\n", + i, cid, crev, sii->coresba[i], sii->coresba_size[i], + OSL_OBFUSCATE_BUF(sii->regs[i]))); if (BUSTYPE(bustype) == SI_BUS) { /* now look at the chipstatus register to figure the pacakge */ /* for SDIO but downloaded on PCIE dev */ +#ifdef BCMPCIEDEV_ENABLED if (cid == PCIE2_CORE_ID) { - if (BCM43602_CHIP(sii->pub.chip) || - (CHIPID(sii->pub.chip) == BCM4365_CHIP_ID) || - (CHIPID(sii->pub.chip) == BCM4366_CHIP_ID) || - ((CHIPID(sii->pub.chip) == BCM4345_CHIP_ID || - CHIPID(sii->pub.chip) == BCM43454_CHIP_ID) && - CST4345_CHIPMODE_PCIE(sii->pub.chipst))) { pcieidx = i; pcierev = crev; pcie = TRUE; pcie_gen2 = TRUE; - } } +#endif // endif - } - else if (BUSTYPE(bustype) == PCI_BUS) { + } else if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { pciidx = i; pcirev = crev; @@ -418,7 +504,6 @@ *origidx = i; } - #if defined(PCIE_FULL_DONGLE) if (pcie) { if (pcie_gen2) @@ -449,11 +534,6 @@ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, sii->pub.buscorerev)); - if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && - (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3)) - OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); - - #if defined(BCMSDIO) /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was * already running. @@ -471,9 +551,6 @@ return TRUE; } - - - uint16 si_chipid(si_t *sih) { @@ -482,6 +559,7 @@ return (sii->chipnew) ? sii->chipnew : sih->chip; } +/* CHIP_ID's being mapped here should not be used anywhere else in the code */ static void si_chipid_fixup(si_t *sih) { @@ -493,49 +571,162 @@ sii->chipnew = sih->chip; /* save it */ sii->pub.chip = BCM43570_CHIP_ID; /* chip class */ break; + case BCM43562_CHIP_ID: case BCM4358_CHIP_ID: case BCM43566_CHIP_ID: sii->chipnew = sih->chip; /* save it */ sii->pub.chip = BCM43569_CHIP_ID; /* chip class */ break; case BCM4356_CHIP_ID: + case BCM4371_CHIP_ID: sii->chipnew = sih->chip; /* save it */ sii->pub.chip = BCM4354_CHIP_ID; /* chip class */ break; + case BCM4357_CHIP_ID: + case BCM4361_CHIP_ID: + sii->chipnew = sih->chip; /* save it */ + sii->pub.chip = BCM4347_CHIP_ID; /* chip class */ + break; +#ifdef CHIPS_CUSTOMER_HW6 + case BCM4377_CHIP_ID: + sii->chipnew = sih->chip; /* save it */ + sii->pub.chip = BCM4369_CHIP_ID; /* chip class */ + break; +#endif /* CHIPS_CUSTOMER_HW6 */ default: break; } } +#ifdef BCMULP +static void +si_check_boot_type(si_t *sih, osl_t *osh) +{ + if (sih->pmurev >= 30) { + boot_type = PMU_REG_NEW(sih, swscratch, 0, 0); + } else { + boot_type = CHIPC_REG(sih, flashdata, 0, 0); + } + + SI_ERROR(("%s: boot_type: 0x%08x\n", __func__, boot_type)); +} +#endif /* BCMULP */ + +#ifdef BCM_BACKPLANE_TIMEOUT +uint32 +si_clear_backplane_to_fast(void *sih, void *addr) +{ + si_t *_sih = DISCARD_QUAL(sih, si_t); + + if (CHIPTYPE(_sih->socitype) == SOCI_AI) { + return ai_clear_backplane_to_fast(_sih, addr); + } + + return 0; +} + +const si_axi_error_info_t * +si_get_axi_errlog_info(si_t *sih) +{ + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + return (const si_axi_error_info_t *)sih->err_info; + } + + return NULL; +} + +void +si_reset_axi_errlog_info(si_t *sih) +{ + if (sih->err_info) { + sih->err_info->count = 0; + } +} +#endif /* BCM_BACKPLANE_TIMEOUT */ + +#ifdef BCMSDIO +void * +si_get_sdio_addrbase(void *sdh) +{ + uint8 devctl; + int err = 0; + uint32 addr = 0; + + devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); + if (err) + return NULL; + + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, + SBSDIO_DEVICE_CTL, devctl | SBSDIO_DEVCTL_ADDR_RESET, &err); + if (err) + goto exit; + + addr |= (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, NULL) << 8) | + (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, NULL) << 16) | + (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, NULL) << 24); + + SI_MSG(("%s: sdiod core address is 0x%x\n", __FUNCTION__, addr)); +exit: + if (err) { + SI_ERROR(("%s: Get SDIO core base address failed, err=%d", __FUNCTION__, err)); + addr = 0; + } + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); + + return (void *)((uintptr)addr); +} +#endif /* BCMSDIO */ + /** - * Allocate an si handle. This function may be called multiple times. + * Allocate an si handle. This function may be called multiple times. This function is called by + * both si_attach() and si_kattach(). * * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this * function set 'vars' to NULL. */ static si_info_t * -si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, +si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, uint bustype, void *sdh, char **vars, uint *varsz) { struct si_pub *sih = &sii->pub; - uint32 w, savewin; + uint32 w = 0; + uint32 savewin; chipcregs_t *cc; char *pvars = NULL; uint origidx; -#if !defined(_CFEZ_) || defined(CFG_WL) -#endif +#ifdef NVSRCX + char *sromvars; +#endif // endif + uint32 erombase; +#ifdef BCMSDIO + uint8 cardcap; + sdpcmd_regs_t *sdioc; +#endif // endif ASSERT(GOODREGS(regs)); savewin = 0; sih->buscoreidx = BADIDX; + sii->device_removed = FALSE; sii->curmap = regs; sii->sdh = sdh; sii->osh = osh; sii->second_bar0win = ~0x0; + sih->enum_base = si_enum_base(devid); +#if defined(BCM_BACKPLANE_TIMEOUT) + sih->err_info = MALLOCZ(osh, sizeof(si_axi_error_info_t)); + if (sih->err_info == NULL) { + SI_ERROR(("%s: %zu bytes MALLOC FAILED", + __FUNCTION__, sizeof(si_axi_error_info_t))); + } +#endif /* BCM_BACKPLANE_TIMEOUT */ + +#if defined(BCM_BACKPLANE_TIMEOUT) + osl_set_bpt_cb(osh, (void *)si_clear_backplane_to_fast, (void *)sih); +#endif // endif /* check to see if we are a si core mimic'ing a pci core */ if ((bustype == PCI_BUS) && @@ -548,29 +739,42 @@ /* find Chipcommon address */ if (bustype == PCI_BUS) { savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) - savewin = SI_ENUM_BASE; - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); + if (!GOODCOREADDR(savewin, SI_ENUM_BASE(sih))) + savewin = SI_ENUM_BASE(sih); + OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE(sih)); if (!regs) return NULL; cc = (chipcregs_t *)regs; + erombase = R_REG(osh, &cc->eromptr); #ifdef BCMSDIO } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { cc = (chipcregs_t *)sii->curmap; -#endif + cardcap = bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL); + if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) { + sih->chipidpresent = TRUE; + sdioc = si_get_sdio_addrbase(sdh); + w = R_REG(osh, &sdioc->chipid); + erombase = R_REG(osh, &sdioc->eromptr); + } else { + erombase = R_REG(osh, &cc->eromptr); + } + if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_SECURE_MODE) { + sih->secureboot = TRUE; + } +#endif // endif } else { - cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE(sih), SI_CORE_SIZE); + erombase = R_REG(osh, &cc->eromptr); } sih->bustype = bustype; #ifdef BCMBUSTYPE - /* Fix the -Werror=tautological-compare compiling error */ if (bustype != BUSTYPE(bustype)) { SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype))); return NULL; } -#endif +#endif // endif /* bus/core/clk setup for register access */ if (!si_buscore_prep(sii, bustype, devid, sdh)) { @@ -587,7 +791,8 @@ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); return NULL; } - w = R_REG(osh, &cc->chipid); + if (!w) + w = R_REG(osh, &cc->chipid); if ((w & 0xfffff) == 148277) w -= 65532; sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; /* Might as wll fill in chip id rev & pkg */ @@ -597,24 +802,50 @@ si_chipid_fixup(sih); - if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && CHIPREV(sih->chiprev == 0) && - (sih->chippkg != BCM4329_289PIN_PKG_ID)) { - sih->chippkg = BCM4329_182PIN_PKG_ID; + if (CHIPID(sih->chip) == BCM43465_CHIP_ID) { + sih->chip = BCM4366_CHIP_ID; + } else if (CHIPID(sih->chip) == BCM43525_CHIP_ID) { + sih->chip = BCM4365_CHIP_ID; } + sih->issim = IS_SIM(sih->chippkg); + +#ifdef CHIPS_CUSTOMER_HW6 + if (MULTIBP_CAP(sih)) + { + sih->_multibp_enable = TRUE; + } +#endif // endif /* scan for cores */ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || - (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) { + (CHIPTYPE(sii->pub.socitype) == SOCI_NAI) || + (CHIPTYPE(sii->pub.socitype) == SOCI_DVTBUS)) { + if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) SI_MSG(("Found chip type AI (0x%08x)\n", w)); - else + else if (CHIPTYPE(sii->pub.socitype) == SOCI_NAI) SI_MSG(("Found chip type NAI (0x%08x)\n", w)); + else + SI_MSG(("Found chip type DVT (0x%08x)\n", w)); /* pass chipc address instead of original core base */ - ai_scan(&sii->pub, (void *)(uintptr)cc, devid); + + if (sii->osh) { + sii->axi_wrapper = (axi_wrapper_t *)MALLOCZ(sii->osh, + (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS)); + + if (sii->axi_wrapper == NULL) { + SI_ERROR(("%s: %zu bytes MALLOC Failed", __FUNCTION__, + (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS))); + } + } else { + sii->axi_wrapper = NULL; + } + + ai_scan(&sii->pub, (void *)(uintptr)cc, erombase, devid); } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); /* pass chipc address instead of original core base */ @@ -634,17 +865,19 @@ SI_ERROR(("si_doattach: si_buscore_setup failed\n")); goto exit; } +#ifdef BCMULP + if (BCMULP_ENAB()) { + si_check_boot_type(sih, osh); + if (ulp_module_init(osh, sih) != BCME_OK) { + ULP_ERR(("%s: err in ulp_module_init\n", __FUNCTION__)); + goto exit; + } + } +#endif /* BCMULP */ #if !defined(_CFEZ_) || defined(CFG_WL) - if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) - >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | - CST4322_SPROM_PRESENT))) { - SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__)); - return NULL; - } - /* assume current core is CC */ - if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || + if ((CCREV(sii->pub.ccrev) == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || CHIPID(sih->chip) == BCM43235_CHIP_ID || CHIPID(sih->chip) == BCM43234_CHIP_ID || CHIPID(sih->chip) == BCM43238_CHIP_ID) && @@ -661,10 +894,54 @@ OSL_DELAY(10); } + /* Set the clkdiv2 divisor bits (2:0) to 0x4 if srom is present */ + if (bustype == SI_BUS) { + uint32 clkdiv2, sromprsnt, capabilities, srom_supported; + capabilities = R_REG(osh, &cc->capabilities); + srom_supported = capabilities & SROM_SUPPORTED; + if (srom_supported) + { + sromprsnt = R_REG(osh, &cc->sromcontrol); + sromprsnt = sromprsnt & SROM_PRSNT_MASK; + if (sromprsnt) { + /* SROM clock come from backplane clock/div2. Must <= 1Mhz */ + clkdiv2 = (R_REG(osh, &cc->clkdiv2) & ~CLKD2_SROM); + clkdiv2 |= CLKD2_SROMDIV_192; + W_REG(osh, &cc->clkdiv2, clkdiv2); + } + } + } + if (bustype == PCI_BUS) { +#ifdef BCMQT + /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF. + * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz + */ + { + uint otpclkdiv = 0; + + if ((CHIPID(sih->chip) == BCM43131_CHIP_ID) || + (CHIPID(sih->chip) == BCM43217_CHIP_ID)) { + otpclkdiv = 4; + } + + if (otpclkdiv != 0) { + uint clkdiv, savecore; + savecore = si_coreidx(sih); + si_setcore(sih, CC_CORE_ID, 0); + + clkdiv = R_REG(osh, &cc->clkdiv); + clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT); + W_REG(osh, &cc->clkdiv, clkdiv); + + SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv)); + si_setcoreidx(sih, savecore); + } + } +#endif /* BCMQT */ } -#endif +#endif // endif #ifdef BCM_SDRBL /* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is * not turned on, then we want to hold arm in reset. @@ -689,35 +966,34 @@ pvars = NULL; BCM_REFERENCE(pvars); + { + sii->lhl_ps_mode = LHL_PS_MODE_0; + } + if (!si_onetimeinit) { - if (sii->pub.ccrev >= 20) { + if (CCREV(sii->pub.ccrev) >= 20) { uint32 gpiopullup = 0, gpiopulldown = 0; cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ASSERT(cc != NULL); - - /* 4314/43142 has pin muxing, don't clear gpio bits */ - if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || - (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { - gpiopullup |= 0x402e0; - gpiopulldown |= 0x20500; - } - - - W_REG(osh, &cc->gpiopullup, gpiopullup); - W_REG(osh, &cc->gpiopulldown, gpiopulldown); + BCM_REFERENCE(gpiopullup); + BCM_REFERENCE(gpiopulldown); si_setcoreidx(sih, origidx); } + } /* clear any previous epidiag-induced target abort */ ASSERT(!si_taclear(sih, FALSE)); +#if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED) + si_pmustatstimer_init(sih); +#endif /* BCMPMU_STATS */ #ifdef BOOTLOADER_CONSOLE_OUTPUT /* Enable console prints */ si_muxenab(sii, 3); -#endif +#endif // endif return (sii); @@ -734,7 +1010,6 @@ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint idx; - if (BUSTYPE(sih->bustype) == SI_BUS) for (idx = 0; idx < SI_MAXCORES; idx++) if (cores_info->regs[idx]) { @@ -742,11 +1017,23 @@ cores_info->regs[idx] = NULL; } - #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) if (cores_info != &ksii_cores_info) #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ MFREE(sii->osh, cores_info, sizeof(si_cores_info_t)); + +#if defined(BCM_BACKPLANE_TIMEOUT) + if (sih->err_info) { + MFREE(sii->osh, sih->err_info, sizeof(si_axi_error_info_t)); + sii->pub.err_info = NULL; + } +#endif /* BCM_BACKPLANE_TIMEOUT */ + + if (sii->axi_wrapper) { + MFREE(sii->osh, sii->axi_wrapper, + (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS)); + sii->axi_wrapper = NULL; + } #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) if (sii != &ksii) @@ -811,7 +1098,9 @@ if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_intflag(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return R_REG(sii->osh, ((uint32 *)(uintptr) (sii->oob_router + OOB_STATUSA))); else { @@ -825,7 +1114,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_flag(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_flag(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_flag(sih); @@ -838,7 +1129,9 @@ uint si_flag_alt(si_t *sih) { - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_flag_alt(sih); else { ASSERT(0); @@ -851,12 +1144,31 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_setint(sih, siflag); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_setint(sih, siflag); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_setint(sih, siflag); else ASSERT(0); +} + +uint32 +si_oobr_baseaddr(si_t *sih, bool second) +{ + si_info_t *sii = SI_INFO(sih); + + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return 0; + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + return (second ? sii->oob_router1 : sii->oob_router); + else { + ASSERT(0); + return 0; + } } uint @@ -877,7 +1189,7 @@ return sii->curidx; } -void * +volatile void * si_d11_switch_addrbase(si_t *sih, uint coreunit) { return si_setcore(sih, D11_CORE_ID, coreunit); @@ -914,7 +1226,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corevendor(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corevendor(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corevendor(sih); @@ -935,7 +1249,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corerev(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corerev(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corerev(sih); @@ -945,6 +1261,15 @@ } } +uint +si_corerev_minor(si_t *sih) +{ + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + return ai_corerev_minor(sih); + } else { + return 0; + } +} /* return index of coreid or BADIDX if not found */ uint @@ -954,7 +1279,6 @@ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint found; uint i; - found = 0; @@ -1029,7 +1353,7 @@ } /** return current register mapping */ -void * +volatile void * si_coreregs(si_t *sih) { si_info_t *sii; @@ -1045,7 +1369,7 @@ * must be called with interrupts off. * Moreover, callers should keep interrupts off during switching out of and back to d11 core */ -void * +volatile void * si_setcore(si_t *sih, uint coreid, uint coreunit) { uint idx; @@ -1056,7 +1380,9 @@ if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, idx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, idx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, idx); @@ -1066,12 +1392,14 @@ } } -void * +volatile void * si_setcoreidx(si_t *sih, uint coreidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, coreidx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, coreidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, coreidx); @@ -1082,12 +1410,11 @@ } /** Turn off interrupt as required by sb_setcore, before switch core */ -void * +volatile void * si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) { - void *cc; + volatile void *cc; si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; if (SI_FAST(sii)) { /* Overloading the origidx variable to remember the coreid, @@ -1096,9 +1423,9 @@ */ *origidx = coreid; if (coreid == CC_CORE_ID) - return (void *)CCREGS_FAST(sii); - else if (coreid == sih->buscoretype) - return (void *)PCIEREGS(sii); + return (volatile void *)CCREGS_FAST(sii); + else if (coreid == BUSCORETYPE(sih->buscoretype)) + return (volatile void *)PCIEREGS(sii); } INTR_OFF(sii, *intr_val); *origidx = sii->curidx; @@ -1113,9 +1440,8 @@ si_restore_core(si_t *sih, uint coreid, uint intr_val) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) + if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == BUSCORETYPE(sih->buscoretype)))) return; si_setcoreidx(sih, coreid); @@ -1127,7 +1453,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_numaddrspaces(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_numaddrspaces(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_numaddrspaces(sih); @@ -1137,30 +1465,47 @@ } } +/* Return the address of the nth address space in the current core + * Arguments: + * sih : Pointer to struct si_t + * spidx : slave port index + * baidx : base address index + */ + uint32 -si_addrspace(si_t *sih, uint asidx) +si_addrspace(si_t *sih, uint spidx, uint baidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspace(sih, asidx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) - return ai_addrspace(sih, asidx); + return sb_addrspace(sih, baidx); + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + return ai_addrspace(sih, spidx, baidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) - return ub_addrspace(sih, asidx); + return ub_addrspace(sih, baidx); else { ASSERT(0); return 0; } } +/* Return the size of the nth address space in the current core + * Arguments: + * sih : Pointer to struct si_t + * spidx : slave port index + * baidx : base address index + */ uint32 -si_addrspacesize(si_t *sih, uint asidx) +si_addrspacesize(si_t *sih, uint spidx, uint baidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspacesize(sih, asidx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) - return ai_addrspacesize(sih, asidx); + return sb_addrspacesize(sih, baidx); + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + return ai_addrspacesize(sih, spidx, baidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) - return ub_addrspacesize(sih, asidx); + return ub_addrspacesize(sih, baidx); else { ASSERT(0); return 0; @@ -1171,7 +1516,9 @@ si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) { /* Only supported for SOCI_AI */ - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_coreaddrspaceX(sih, asidx, addr, size); else *size = 0; @@ -1182,7 +1529,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_core_cflags(sih, mask, val); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_core_cflags(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_core_cflags(sih, mask, val); @@ -1197,7 +1546,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_cflags_wo(sih, mask, val); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_cflags_wo(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_cflags_wo(sih, mask, val); @@ -1210,7 +1561,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_core_sflags(sih, mask, val); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_core_sflags(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_core_sflags(sih, mask, val); @@ -1220,12 +1573,30 @@ } } +void +si_commit(si_t *sih) +{ + if (CHIPTYPE(sih->socitype) == SOCI_SB) + sb_commit(sih); + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + ; + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + ; + else { + ASSERT(0); + } +} + bool si_iscoreup(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_iscoreup(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_iscoreup(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_iscoreup(sih); @@ -1239,7 +1610,9 @@ si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) { /* only for AI back plane chips */ - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return (ai_wrap_reg(sih, offset, mask, val)); return 0; } @@ -1272,13 +1645,20 @@ bcmerror = BCME_ERROR; } } - return bcmerror; } -uint + +void +si_invalidate_second_bar0win(si_t *sih) +{ + si_info_t *sii = SI_INFO(sih); + sii->second_bar0win = ~0x0; +} + +int si_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read) { - uint32 *r = NULL; + volatile uint32 *r = NULL; uint32 region = 0; si_info_t *sii = SI_INFO(sih); @@ -1307,31 +1687,30 @@ * PCI_SECOND_BAR0_OFFSET : secondar bar-0 offset * regoff : actual reg offset */ - r = (uint32 *)((char *)sii->curmap + PCI_SECOND_BAR0_OFFSET + addr); + r = (volatile uint32 *)((volatile char *)sii->curmap + PCI_SECOND_BAR0_OFFSET + addr); SI_VMSG(("si curmap %p region %x regaddr %x effective addr %p READ %d\n", - (char*)sii->curmap, region, addr, r, read)); + (volatile char*)sii->curmap, region, addr, r, read)); switch (size) { case sizeof(uint8) : if (read) - *val = R_REG(sii->osh, (uint8*)r); + *val = R_REG(sii->osh, (volatile uint8*)r); else - W_REG(sii->osh, (uint8*)r, *val); + W_REG(sii->osh, (volatile uint8*)r, *val); break; case sizeof(uint16) : if (read) - *val = R_REG(sii->osh, (uint16*)r); + *val = R_REG(sii->osh, (volatile uint16*)r); else - W_REG(sii->osh, (uint16*)r, *val); + W_REG(sii->osh, (volatile uint16*)r, *val); break; case sizeof(uint32) : if (read) - *val = R_REG(sii->osh, (uint32*)r); + *val = R_REG(sii->osh, (volatile uint32*)r); else - W_REG(sii->osh, (uint32*)r, *val); + W_REG(sii->osh, (volatile uint32*)r, *val); break; - default : SI_ERROR(("Invalid size %d \n", size)); return (BCME_ERROR); @@ -1345,7 +1724,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corereg(sih, coreidx, regoff, mask, val); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corereg(sih, coreidx, regoff, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corereg(sih, coreidx, regoff, mask, val); @@ -1353,6 +1734,12 @@ ASSERT(0); return 0; } +} + +uint +si_corereg_writeonly(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) +{ + return ai_corereg_writeonly(sih, coreidx, regoff, mask, val); } /** ILP sensitive register access needs special treatment to avoid backplane stalls */ @@ -1375,7 +1762,7 @@ int pmustatus_offset; /* prevent backplane stall on double write to 'ILP domain' registers in the PMU */ - if (mask != 0 && sih->pmurev >= 22 && + if (mask != 0 && PMUREV(sih->pmurev) >= 22 && si_pmu_is_ilp_sensitive(idx, regoff)) { pmustatus_offset = AOB_ENAB(sih) ? OFFSETOF(pmuregs_t, pmustatus) : OFFSETOF(chipcregs_t, pmustatus); @@ -1396,12 +1783,14 @@ * For accessing registers that would need a core switch, this function will return * NULL. */ -uint32 * +volatile uint32 * si_corereg_addr(si_t *sih, uint coreidx, uint regoff) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corereg_addr(sih, coreidx, regoff); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corereg_addr(sih, coreidx, regoff); else { return 0; @@ -1413,7 +1802,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_disable(sih, bits); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_disable(sih, bits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_disable(sih, bits); @@ -1424,7 +1815,9 @@ { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_reset(sih, bits, resetbits); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_reset(sih, bits, resetbits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_reset(sih, bits, resetbits); @@ -1455,6 +1848,64 @@ return result; } +uint +si_num_slaveports(si_t *sih, uint coreid) +{ + uint idx = si_findcoreidx(sih, coreid, 0); + uint num = 0; + + if (idx != BADIDX) { + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + num = ai_num_slaveports(sih, idx); + } + } + return num; +} + +uint32 +si_get_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint core_id, uint coreunit) +{ + si_info_t *sii = SI_INFO(sih); + uint origidx = sii->curidx; + uint32 addr = 0x0; + + if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI))) + goto done; + + si_setcore(sih, core_id, coreunit); + + addr = ai_addrspace(sih, spidx, baidx); + + si_setcoreidx(sih, origidx); + +done: + return addr; +} + +uint32 +si_get_d11_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint coreunit) +{ + si_info_t *sii = SI_INFO(sih); + uint origidx = sii->curidx; + uint32 addr = 0x0; + + if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI))) + goto done; + + si_setcore(sih, D11_CORE_ID, coreunit); + + addr = ai_addrspace(sih, spidx, baidx); + + si_setcoreidx(sih, origidx); + +done: + return addr; +} + static uint32 factor6(uint32 x) { @@ -1478,7 +1929,6 @@ { return div ? clock / div : 0; } - /** calculate the speed the SI would run at given a set of clockcontrol values */ uint32 @@ -1562,7 +2012,6 @@ return (clock); } - return 0; } /** @@ -1575,7 +2024,13 @@ uint hosti = 0; switch (CHIPID(sih->chip)) { - + case BCM43018_CHIP_ID: + case BCM43430_CHIP_ID: + hosti = CHIP_HOSTIF_SDIOMODE; + break; + case BCM43012_CHIP_ID: + hosti = CHIP_HOSTIF_SDIOMODE; + break; CASE_BCM43602_CHIP: hosti = CHIP_HOSTIF_PCIEMODE; break; @@ -1601,8 +2056,7 @@ hosti = CHIP_HOSTIF_PCIEMODE; break; - case BCM4345_CHIP_ID: - case BCM43454_CHIP_ID: + CASE_BCM4345_CHIP: if (CST4345_CHIPMODE_USB20D(sih->chipst) || CST4345_CHIPMODE_HSIC(sih->chipst)) hosti = CHIP_HOSTIF_USBMODE; else if (CST4345_CHIPMODE_SDIOD(sih->chipst)) @@ -1612,22 +2066,47 @@ break; case BCM4349_CHIP_GRPID: + case BCM53573_CHIP_GRPID: if (CST4349_CHIPMODE_SDIOD(sih->chipst)) hosti = CHIP_HOSTIF_SDIOMODE; else if (CST4349_CHIPMODE_PCIE(sih->chipst)) hosti = CHIP_HOSTIF_PCIEMODE; break; + case BCM4364_CHIP_ID: + if (CST4364_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4364_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; case BCM4373_CHIP_ID: - if (CST4373_CHIPMODE_USB20D(sih->chipst)) - hosti = CHIP_HOSTIF_USBMODE; - else if (CST4373_CHIPMODE_SDIOD(sih->chipst)) - hosti = CHIP_HOSTIF_SDIOMODE; - else if (CST4373_CHIPMODE_PCIE(sih->chipst)) - hosti = CHIP_HOSTIF_PCIEMODE; - break; + if (CST4373_CHIPMODE_USB20D(sih->chipst)) + hosti = CHIP_HOSTIF_USBMODE; + else if (CST4373_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4373_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; + + case BCM4347_CHIP_GRPID: + if (CST4347_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4347_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; + case BCM4369_CHIP_GRPID: + if (CST4369_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4369_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; +#ifdef CHIPS_CUSTOMER_HW6 + case BCM4368_CHIP_GRPID: + hosti = CHIP_HOSTIF_PCIEMODE; + break; +#endif /* CHIPS_CUSTOMER_HW6 */ + case BCM4350_CHIP_ID: case BCM4354_CHIP_ID: - case BCM4356_CHIP_ID: case BCM43556_CHIP_ID: case BCM43558_CHIP_ID: case BCM43566_CHIP_ID: @@ -1654,26 +2133,15 @@ return hosti; } - /** set chip watchdog reset timer to fire in 'ticks' */ void si_watchdog(si_t *sih, uint ticks) { uint nb, maxt; + uint pmu_wdt = 1; - if (PMUCTL_ENAB(sih)) { - -#if !defined(_CFEZ_) || defined(CFG_WL) - if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && - (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { - si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); - si_setcore(sih, USB20D_CORE_ID, 0); - si_core_disable(sih, 1); - si_setcore(sih, CC_CORE_ID, 0); - } -#endif - - nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); + if (PMUCTL_ENAB(sih) && pmu_wdt) { + nb = (CCREV(sih->ccrev) < 26) ? 16 : ((CCREV(sih->ccrev) >= 37) ? 32 : 24); /* The mips compiler uses the sllv instruction, * so we specially handle the 32-bit case. */ @@ -1694,8 +2162,13 @@ SPINWAIT((PMU_REG(sih, pmustatus, 0, 0) & PST_ILPFASTLPO), PMU_MAX_TRANSITION_DLY); } - - pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks); + if (sih->chip == CYW55500_CHIP_ID || + sih->chip == CYW55560_CHIP_ID) { + si_corereg(sih, si_findcoreidx(sih, PMU_CORE_ID, 0), + OFFSETOF(pmuregs_t, pmuwatchdog), ~0, ticks); + } else { + pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks); + } } else { maxt = (1 << 28) - 1; if (ticks > maxt) @@ -1723,8 +2196,6 @@ return FALSE; } - - /** return the slow clock source - LPO, XTAL, or PCI */ static uint si_slowclk_src(si_info_t *sii) @@ -1733,14 +2204,14 @@ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); - if (sii->pub.ccrev < 6) { + if (CCREV(sii->pub.ccrev) < 6) { if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & PCI_CFG_GPIO_SCS)) return (SCC_SS_PCI); else return (SCC_SS_XTAL); - } else if (sii->pub.ccrev < 10) { + } else if (CCREV(sii->pub.ccrev) < 10) { cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); ASSERT(cc); return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); @@ -1761,12 +2232,12 @@ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); slowclk = si_slowclk_src(sii); - if (sii->pub.ccrev < 6) { + if (CCREV(sii->pub.ccrev) < 6) { if (slowclk == SCC_SS_PCI) return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); else return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); - } else if (sii->pub.ccrev < 10) { + } else if (CCREV(sii->pub.ccrev) < 10) { div = 4 * (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); if (slowclk == SCC_SS_LPO) @@ -1804,7 +2275,7 @@ pll_delay += XTAL_ON_DELAY; /* Starting with 4318 it is ILP that is used for the delays */ - slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); + slowmaxfreq = si_slowclk_freq(sii, (CCREV(sii->pub.ccrev) >= 10) ? FALSE : TRUE, cc); pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; @@ -1836,7 +2307,7 @@ ASSERT(cc != NULL); /* set all Instaclk chip ILP to 1 MHz */ - if (sih->ccrev >= 10) + if (CCREV(sih->ccrev) >= 10) SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); @@ -1848,9 +2319,8 @@ si_setcoreidx(sih, origidx); } - /** change logical "focus" to the gpio core for optimized access */ -void * +volatile void * si_gpiosetcore(si_t *sih) { return (si_setcoreidx(sih, SI_CC_IDX)); @@ -2029,11 +2499,25 @@ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); } +uint32 +si_gpioeventintmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) +{ + uint regoff; + /* gpios could be shared on router platforms */ + if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { + mask = priority ? (si_gpioreservation & mask) : + ((si_gpioreservation | mask) & ~(si_gpioreservation)); + val &= mask; + } + regoff = OFFSETOF(chipcregs_t, gpioeventintmask); + return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); +} + /* assign the gpio to an led */ uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val) { - if (sih->ccrev < 16) + if (CCREV(sih->ccrev) < 16) return 0xffffffff; /* gpio led powersave reg */ @@ -2044,7 +2528,7 @@ uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) { - if (sih->ccrev < 16) + if (CCREV(sih->ccrev) < 16) return 0xffffffff; return (si_corereg(sih, SI_CC_IDX, @@ -2056,7 +2540,7 @@ { uint offs; - if (sih->ccrev < 20) + if (CCREV(sih->ccrev) < 20) return 0xffffffff; offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); @@ -2068,7 +2552,7 @@ { uint offs; - if (sih->ccrev < 11) + if (CCREV(sih->ccrev) < 11) return 0xffffffff; if (regtype == GPIO_REGEVT) @@ -2088,7 +2572,7 @@ { uint offs; - if (sih->ccrev < 11) + if (CCREV(sih->ccrev) < 11) return 0xffffffff; offs = OFFSETOF(chipcregs_t, intmask); @@ -2113,7 +2597,6 @@ si_sysmem_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; @@ -2170,7 +2653,6 @@ void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; sbsocramregs_t *regs; @@ -2207,7 +2689,6 @@ si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; sbsocramregs_t *regs; @@ -2255,8 +2736,7 @@ (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT); } W_REG(sii->osh, ®s->bankinfo, bankinfo); - } - else if (i == 0) { + } else if (i == 0) { if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) { *enable = 1; if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK) @@ -2281,7 +2761,6 @@ si_socdevram_remap_isenb(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; sbsocramregs_t *regs; @@ -2342,7 +2821,6 @@ si_socdevram_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; uint32 memsize = 0; @@ -2389,7 +2867,6 @@ si_socdevram_remap_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; uint32 memsize = 0, banksz; @@ -2455,7 +2932,6 @@ si_socram_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; @@ -2518,27 +2994,26 @@ return memsize; } - /** Return the TCM-RAM size of the ARMCR4 core. */ uint32 si_tcm_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; - uint8 *regs; - bool wasup; + volatile uint8 *regs; + bool wasup = FALSE; uint32 corecap; uint memsize = 0; + uint banku_size = 0; uint32 nab = 0; uint32 nbb = 0; uint32 totb = 0; uint32 bxinfo = 0; uint32 idx = 0; - uint32 *arm_cap_reg; - uint32 *arm_bidx; - uint32 *arm_binfo; + volatile uint32 *arm_cap_reg; + volatile uint32 *arm_bidx; + volatile uint32 *arm_binfo; /* Block ints and save current core */ INTR_OFF(sii, intr_val); @@ -2551,28 +3026,37 @@ /* Get info for determining size. If in reset, come out of reset, * but remain in halt */ - if (!(wasup = si_iscoreup(sih))) - si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT); + if (!sih->secureboot) { + if (!(wasup = si_iscoreup(sih))) + si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT); + } - arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP); + arm_cap_reg = (volatile uint32 *)(regs + SI_CR4_CAP); corecap = R_REG(sii->osh, arm_cap_reg); nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; totb = nab + nbb; - arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX); - arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO); + arm_bidx = (volatile uint32 *)(regs + SI_CR4_BANKIDX); + arm_binfo = (volatile uint32 *)(regs + SI_CR4_BANKINFO); for (idx = 0; idx < totb; idx++) { W_REG(sii->osh, arm_bidx, idx); bxinfo = R_REG(sii->osh, arm_binfo); - memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; + if (bxinfo & ARMCR4_BUNITSZ_MASK) { + banku_size = ARMCR4_BSZ_1K; + } else { + banku_size = ARMCR4_BSZ_8K; + } + memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * banku_size; } /* Return to previous state and core */ - if (!wasup) - si_core_disable(sih, 0); + if (!sih->secureboot) { + if (!wasup) + si_core_disable(sih, 0); + } si_setcoreidx(sih, origidx); done: @@ -2602,7 +3086,6 @@ si_socram_srmem_size(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; @@ -2611,10 +3094,6 @@ uint corerev; uint32 coreinfo; uint memsize = 0; - - if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) { - return (32 * 1024); - } if (CHIPID(sih->chip) == BCM43430_CHIP_ID || CHIPID(sih->chip) == BCM43018_CHIP_ID) { @@ -2657,13 +3136,11 @@ return memsize; } - #if !defined(_CFEZ_) || defined(CFG_WL) void si_btcgpiowar(si_t *sih) { si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint origidx; uint intr_val = 0; chipcregs_t *cc; @@ -2683,43 +3160,6 @@ ASSERT(cc != NULL); W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); - - /* restore the original index */ - si_setcoreidx(sih, origidx); - - INTR_RESTORE(sii, intr_val); -} - -void -si_chipcontrl_btshd0_4331(si_t *sih, bool on) -{ - si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - chipcregs_t *cc; - uint origidx; - uint32 val; - uint intr_val = 0; - - INTR_OFF(sii, intr_val); - - origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - val = R_REG(sii->osh, &cc->chipcontrol); - - /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */ - if (on) { - /* Enable bt_shd0 on gpio4: */ - val |= (CCTRL4331_BT_SHD0_ON_GPIO4); - W_REG(sii->osh, &cc->chipcontrol, val); - } else { - val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4); - W_REG(sii->osh, &cc->chipcontrol, val); - } /* restore the original index */ si_setcoreidx(sih, origidx); @@ -2759,42 +3199,6 @@ return val; } -void -si_chipcontrl_epa4331(si_t *sih, bool on) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - uint32 val; - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - val = R_REG(sii->osh, &cc->chipcontrol); - - if (on) { - if (sih->chippkg == 9 || sih->chippkg == 0xb) { - val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); - /* Ext PA Controls for 4331 12x9 Package */ - W_REG(sii->osh, &cc->chipcontrol, val); - } else { - /* Ext PA Controls for 4331 12x12 Package */ - if (CHIPREV(sih->chiprev) > 0) { - W_REG(sii->osh, &cc->chipcontrol, val | - (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2)); - } else { - W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); - } - } - } else { - val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5); - W_REG(sii->osh, &cc->chipcontrol, val); - } - - si_setcoreidx(sih, origidx); -} - /** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */ void si_chipcontrl_srom4360(si_t *sih, bool on) @@ -2824,141 +3228,41 @@ si_setcoreidx(sih, origidx); } +/** + * The SROM clock is derived from the backplane clock. 4365 (200Mhz) and 43684 (240Mhz) have a fast + * backplane clock that requires a higher-than-POR-default clock divisor ratio for the SROM clock. + */ void -si_clk_srom4365(si_t *sih) +si_srom_clk_set(si_t *sih) { si_info_t *sii = SI_INFO(sih); chipcregs_t *cc; uint origidx = si_coreidx(sih); uint32 val; + uint32 divisor = 1; if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); return; } + val = R_REG(sii->osh, &cc->clkdiv2); - W_REG(sii->osh, &cc->clkdiv2, ((val&~0xf) | 0x4)); - - si_setcoreidx(sih, origidx); -} - -void -si_d11rsdb_core1_alt_reg_clk_dis(si_t *sih) -{ -#if defined(WLRSDB) && !defined(WLRSDB_DISABLED) - ai_d11rsdb_core1_alt_reg_clk_dis(sih); -#endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */ -} - -void -si_d11rsdb_core1_alt_reg_clk_en(si_t *sih) -{ -#if defined(WLRSDB) && !defined(WLRSDB_DISABLED) - ai_d11rsdb_core1_alt_reg_clk_en(sih); -#endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */ -} - -void -si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) -{ - si_info_t *sii; - chipcregs_t *cc; - uint origidx; - uint32 val; - bool sel_chip; - - sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) || - (CHIPID(sih->chip) == BCM43431_CHIP_ID); - sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb)); - - if (!sel_chip) - return; - - sii = SI_INFO(sih); - origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - val = R_REG(sii->osh, &cc->chipcontrol); - - if (enter_wowl) { - val |= CCTRL4331_EXTPA_EN; - W_REG(sii->osh, &cc->chipcontrol, val); + if (BCM4365_CHIP(sih->chip)) { + divisor = CLKD2_SROMDIV_192; /* divide 200 by 192 -> SPROM clock ~ 1.04Mhz */ } else { - val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); - W_REG(sii->osh, &cc->chipcontrol, val); - } - si_setcoreidx(sih, origidx); -} -#endif - -uint -si_pll_reset(si_t *sih) -{ - uint err = 0; - - return (err); -} - -/** Enable BT-COEX & Ex-PA for 4313 */ -void -si_epa_4313war(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; + ASSERT(0); } - /* EPA Fix */ - W_REG(sii->osh, &cc->gpiocontrol, - R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); - + W_REG(sii->osh, &cc->clkdiv2, ((val & ~CLKD2_SROM) | divisor)); si_setcoreidx(sih, origidx); } - -void -si_clk_pmu_htavail_set(si_t *sih, bool set_clear) -{ -} +#endif // endif void si_pmu_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag) { } -/** Re-enable synth_pwrsw resource in min_res_mask for 4313 */ -void -si_pmu_synth_pwrsw_4313_war(si_t *sih) -{ -} - -/** WL/BT control for 4313 btcombo boards >= P250 */ -void -si_btcombo_p250_4313_war(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - W_REG(sii->osh, &cc->gpiocontrol, - R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK); - - W_REG(sii->osh, &cc->gpioouten, - R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK); - - si_setcoreidx(sih, origidx); -} void si_btc_enable_chipcontrol(si_t *sih) { @@ -2977,22 +3281,13 @@ si_setcoreidx(sih, origidx); } -void -si_btcombo_43228_war(si_t *sih) + +/** cache device removed state */ +void si_set_device_removed(si_t *sih, bool status) { si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK); - W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK); - - si_setcoreidx(sih, origidx); + sii->device_removed = status; } /** check if the device is removed */ @@ -3000,6 +3295,11 @@ si_deviceremoved(si_t *sih) { uint32 w; + si_info_t *sii = SI_INFO(sih); + + if (sii->device_removed) { + return TRUE; + } switch (BUSTYPE(sih->bustype)) { case PCI_BUS: @@ -3013,9 +3313,20 @@ } bool +si_is_warmboot(void) +{ + +#ifdef BCMULP + return (boot_type == WARM_BOOT); +#else + return FALSE; +#endif // endif +} + +bool si_is_sprom_available(si_t *sih) { - if (sih->ccrev >= 31) { + if (CCREV(sih->ccrev) >= 31) { si_info_t *sii; uint origidx; chipcregs_t *cc; @@ -3034,52 +3345,35 @@ } switch (CHIPID(sih->chip)) { - case BCM4312_CHIP_ID: - return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); - case BCM4325_CHIP_ID: - return (sih->chipst & CST4325_SPROM_SEL) != 0; - case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: - case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: - case BCM4342_CHIP_ID: { - uint32 spromotp; - spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> - CST4322_SPROM_OTP_SEL_SHIFT; - return (spromotp & CST4322_SPROM_PRESENT) != 0; - } - case BCM4329_CHIP_ID: - return (sih->chipst & CST4329_SPROM_SEL) != 0; - case BCM4315_CHIP_ID: - return (sih->chipst & CST4315_SPROM_SEL) != 0; - case BCM4319_CHIP_ID: - return (sih->chipst & CST4319_SPROM_SEL) != 0; - case BCM4336_CHIP_ID: - case BCM43362_CHIP_ID: - return (sih->chipst & CST4336_SPROM_PRESENT) != 0; - case BCM4330_CHIP_ID: - return (sih->chipst & CST4330_SPROM_PRESENT) != 0; - case BCM4313_CHIP_ID: - return (sih->chipst & CST4313_SPROM_PRESENT) != 0; - case BCM4331_CHIP_ID: - case BCM43431_CHIP_ID: - return (sih->chipst & CST4331_SPROM_PRESENT) != 0; - case BCM43239_CHIP_ID: - return ((sih->chipst & CST43239_SPROM_MASK) && - !(sih->chipst & CST43239_SFLASH_MASK)); - case BCM4324_CHIP_ID: - case BCM43242_CHIP_ID: - return ((sih->chipst & CST4324_SPROM_MASK) && - !(sih->chipst & CST4324_SFLASH_MASK)); + case BCM43018_CHIP_ID: + case BCM43430_CHIP_ID: + return FALSE; case BCM4335_CHIP_ID: - case BCM4345_CHIP_ID: - case BCM43454_CHIP_ID: + CASE_BCM4345_CHIP: return ((sih->chipst & CST4335_SPROM_MASK) && !(sih->chipst & CST4335_SFLASH_MASK)); case BCM4349_CHIP_GRPID: return (sih->chipst & CST4349_SPROM_PRESENT) != 0; + case BCM53573_CHIP_GRPID: + return FALSE; /* SPROM PRESENT is not defined for 53573 as of now */ + case BCM4364_CHIP_ID: + return (sih->chipst & CST4364_SPROM_PRESENT) != 0; + case BCM4369_CHIP_GRPID: + if (CHIPREV(sih->chiprev) == 0) { + /* WAR for 4369a0: HW4369-1729. no sprom, default to otp always. */ + return 0; + } else { + return (sih->chipst & CST4369_SPROM_PRESENT) != 0; + } +#ifdef CHIPS_CUSTOMER_HW6 + case BCM4368_CHIP_ID: + return FALSE; +#endif /* CHIPS_CUSTOMER_HW6 */ + case BCM4347_CHIP_GRPID: + return (sih->chipst & CST4347_SPROM_PRESENT) != 0; break; case BCM4350_CHIP_ID: case BCM4354_CHIP_ID: - case BCM4356_CHIP_ID: case BCM43556_CHIP_ID: case BCM43558_CHIP_ID: case BCM43566_CHIP_ID: @@ -3092,15 +3386,15 @@ return (sih->chipst & CST43602_SPROM_PRESENT) != 0; case BCM43131_CHIP_ID: case BCM43217_CHIP_ID: - case BCM43227_CHIP_ID: - case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; + case BCM4373_CHIP_ID: + case BCM43012_CHIP_ID: + return FALSE; default: return TRUE; } } - uint32 si_get_sromctl(si_t *sih) { @@ -3156,7 +3450,6 @@ uint origidx, intr_val = 0; uint ret_val; si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; origidx = si_coreidx(sih); @@ -3171,7 +3464,6 @@ return ret_val; } - /* cleanup the timer from the host when ARM is been halted * without a chance for ARM cleanup its resources * If left not cleanup, Intr from a software timer can still @@ -3183,8 +3475,7 @@ uint32 mask; mask = PRRT_REQ_ACTIVE | PRRT_INTEN | PRRT_HT_REQ; - if (CHIPID(sih->chip) != BCM4328_CHIP_ID) - mask <<= 14; + mask <<= 14; /* clear mask bits */ pmu_corereg(sih, SI_CC_IDX, res_req_timer, mask, 0); /* readback to ensure write completes */ @@ -3197,67 +3488,17 @@ { } - -#ifdef SURVIVE_PERST_ENAB -static uint32 -si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - if (!PCIE(sii)) - return (0); - - return pcie_survive_perst(sii->pch, mask, val); -} - -static void -si_watchdog_reset(si_t *sih) -{ - uint32 i; - - /* issue a watchdog reset */ - pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, 2, 2); - /* do busy wait for 20ms */ - for (i = 0; i < 2000; i++) { - OSL_DELAY(10); - } -} -#endif /* SURVIVE_PERST_ENAB */ - +/* Caller of this function should make sure is on PCIE core + * Used in pciedev.c. + */ void -si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val) +si_pcie_disable_oobselltr(si_t *sih) { -#ifdef SURVIVE_PERST_ENAB - if (BUSTYPE(sih->bustype) != PCI_BUS) - return; - - if ((CHIPID(sih->chip) != BCM4360_CHIP_ID && CHIPID(sih->chip) != BCM4352_CHIP_ID) || - (CHIPREV(sih->chiprev) >= 4)) - return; - - if (reset) { - si_info_t *sii = SI_INFO(sih); - uint32 bar0win, bar0win_after; - - /* save the bar0win */ - bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - - si_watchdog_reset(sih); - - bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - if (bar0win_after != bar0win) { - SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n", - __FUNCTION__, bar0win, bar0win_after)); - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win); - } - } - if (sperst_mask) { - /* enable survive perst */ - si_pcie_survive_perst(sih, sperst_mask, sperst_val); - } -#endif /* SURVIVE_PERST_ENAB */ + ASSERT(si_coreid(sih) == PCIE2_CORE_ID); + if (PCIECOREREV(sih->buscorerev) >= 23) + si_wrapperreg(sih, AI_OOBSELIND74, ~0, 0); + else + si_wrapperreg(sih, AI_OOBSELIND30, ~0, 0); } void @@ -3285,11 +3526,117 @@ { } +#if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) +uint32 +si_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wrap) +{ + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) { + return ai_clear_backplane_to_per_core(sih, coreid, coreunit, wrap); + } + return AXI_WRAP_STS_NONE; +} +#endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ + +uint32 +si_clear_backplane_to(si_t *sih) +{ + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) { + return ai_clear_backplane_to(sih); + } + + return 0; +} + +void +si_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout_exp, uint32 cid) +{ +#if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) + /* Enable only for AXI */ + if (CHIPTYPE(sih->socitype) != SOCI_AI) { + return; + } + + ai_update_backplane_timeouts(sih, enable, timeout_exp, cid); +#endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ +} + +/* + * This routine adds the AXI timeouts for + * chipcommon, pcie and ARM slave wrappers + */ +void +si_slave_wrapper_add(si_t *sih) +{ +#if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) + uint32 axi_to = 0; + + /* Enable only for AXI */ + if ((CHIPTYPE(sih->socitype) != SOCI_AI) && + (CHIPTYPE(sih->socitype) != SOCI_DVTBUS)) { + return; + } + + if (CHIPID(sih->chip) == BCM4345_CHIP_ID && CHIPREV(sih->chiprev) >= 6) { + si_info_t *sii = SI_INFO(sih); + + int wrapper_idx = (int)sii->axi_num_wrappers - 1; + + ASSERT(wrapper_idx >= 0); /* axi_wrapper[] not initialised */ + do { + if (sii->axi_wrapper[wrapper_idx].wrapper_type == AI_SLAVE_WRAPPER && + sii->axi_wrapper[wrapper_idx].cid == 0xfff) { + sii->axi_wrapper[wrapper_idx].wrapper_addr = 0x1810b000; + break; + } + } while (wrapper_idx-- > 0); + ASSERT(wrapper_idx >= 0); /* all addresses valid for the chiprev under test */ + } + + if (BCM4347_CHIP(sih->chip)) { + axi_to = AXI_TO_VAL_4347; + } + else { + axi_to = AXI_TO_VAL; + } + + /* All required slave wrappers are added in ai_scan */ + ai_update_backplane_timeouts(sih, TRUE, axi_to, 0); + +#ifdef DISABLE_PCIE2_AXI_TIMEOUT + ai_update_backplane_timeouts(sih, FALSE, 0, PCIE_CORE_ID); + ai_update_backplane_timeouts(sih, FALSE, 0, PCIE2_CORE_ID); +#endif // endif + +#endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ + +} void si_pll_sr_reinit(si_t *sih) { +} + +/* Programming d11 core oob settings for 4364 + * WARs for HW4364-237 and HW4364-166 +*/ +void +si_config_4364_d11_oob(si_t *sih, uint coreid) +{ + uint save_idx; + + save_idx = si_coreidx(sih); + si_setcore(sih, coreid, 0); + si_wrapperreg(sih, AI_OOBSELINC30, ~0, 0x81828180); + si_wrapperreg(sih, AI_OOBSELINC74, ~0, 0x87868183); + si_wrapperreg(sih, AI_OOBSELOUTB74, ~0, 0x84858484); + si_setcore(sih, coreid, 1); + si_wrapperreg(sih, AI_OOBSELINC30, ~0, 0x81828180); + si_wrapperreg(sih, AI_OOBSELINC74, ~0, 0x87868184); + si_wrapperreg(sih, AI_OOBSELOUTB74, ~0, 0x84868484); + si_setcoreidx(sih, save_idx); } void @@ -3301,6 +3648,7 @@ /* disable PLL open loop operation */ switch (CHIPID(sih->chip)) { #ifdef SAVERESTORE + case BCM43018_CHIP_ID: case BCM43430_CHIP_ID: if (SR_ENAB() && sr_isenab(sih)) { /* read back the pll openloop state */ @@ -3314,9 +3662,268 @@ } break; #endif /* SAVERESTORE */ + case BCM4347_CHIP_GRPID: + case BCM4369_CHIP_GRPID: + si_pmu_chipcontrol(sih, PMU_CHIPCTL1, + PMU_CC1_ENABLE_CLOSED_LOOP_MASK, PMU_CC1_ENABLE_CLOSED_LOOP); + break; default: /* any unsupported chip bail */ return; } -#endif +#endif // endif +} + +#if defined(BCMSRPWR) && !defined(BCMSRPWR_DISABLED) +bool _bcmsrpwr = TRUE; +#else +bool _bcmsrpwr = FALSE; +#endif // endif + +#define PWRREQ_OFFSET(sih) OFFSETOF(chipcregs_t, powerctl) + +static void +si_corereg_pciefast_write(si_t *sih, uint regoff, uint val) +{ + volatile uint32 *r = NULL; + si_info_t *sii = SI_INFO(sih); + + ASSERT((BUSTYPE(sih->bustype) == PCI_BUS)); + + r = (volatile uint32 *)((volatile char *)sii->curmap + + PCI_16KB0_PCIREGS_OFFSET + regoff); + + W_REG(sii->osh, r, val); +} + +static uint +si_corereg_pciefast_read(si_t *sih, uint regoff) +{ + volatile uint32 *r = NULL; + si_info_t *sii = SI_INFO(sih); + + ASSERT((BUSTYPE(sih->bustype) == PCI_BUS)); + + r = (volatile uint32 *)((volatile char *)sii->curmap + + PCI_16KB0_PCIREGS_OFFSET + regoff); + + return R_REG(sii->osh, r); +} + +uint32 +si_srpwr_request(si_t *sih, uint32 mask, uint32 val) +{ + uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ? + OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih); + uint32 mask2 = mask; + uint32 val2 = val; + volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih) + + (uintptr)offset); + + if (mask || val) { + mask <<= SRPWR_REQON_SHIFT; + val <<= SRPWR_REQON_SHIFT; + + /* Return if requested power request is already set */ + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + r = si_corereg_pciefast_read(sih, offset); + } + + if ((r & mask) == val) { + return r; + } + + r = (r & ~mask) | val; + + if (BUSTYPE(sih->bustype) == SI_BUS) { + W_REG(OSH_NULL, fast_srpwr_addr, r); + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + si_corereg_pciefast_write(sih, offset, r); + r = si_corereg_pciefast_read(sih, offset); + } + + if (val2) { + if ((r & (mask2 << SRPWR_STATUS_SHIFT)) == + (val2 << SRPWR_STATUS_SHIFT)) { + return r; + } + si_srpwr_stat_spinwait(sih, mask2, val2); + } + } else { + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + r = si_corereg_pciefast_read(sih, offset); + } + } + + return r; +} + +uint32 +si_srpwr_stat_spinwait(si_t *sih, uint32 mask, uint32 val) +{ + uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ? + OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih); + volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih) + + (uintptr)offset); + + ASSERT(mask); + ASSERT(val); + + /* spinwait on pwrstatus */ + mask <<= SRPWR_STATUS_SHIFT; + val <<= SRPWR_STATUS_SHIFT; + + if (BUSTYPE(sih->bustype) == SI_BUS) { + SPINWAIT(((R_REG(OSH_NULL, fast_srpwr_addr) & mask) != val), + PMU_MAX_TRANSITION_DLY); + r = R_REG(OSH_NULL, fast_srpwr_addr) & mask; + ASSERT(r == val); + } else { + SPINWAIT(((si_corereg_pciefast_read(sih, offset) & mask) != val), + PMU_MAX_TRANSITION_DLY); + r = si_corereg_pciefast_read(sih, offset) & mask; + ASSERT(r == val); + } + + r = (r >> SRPWR_STATUS_SHIFT) & SRPWR_DMN_ALL_MASK(sih); + + return r; +} + +uint32 +si_srpwr_stat(si_t *sih) +{ + uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ? + OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih); + uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx; + + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = si_corereg(sih, cidx, offset, 0, 0); + } else { + r = si_corereg_pciefast_read(sih, offset); + } + + r = (r >> SRPWR_STATUS_SHIFT) & SRPWR_DMN_ALL_MASK(sih); + + return r; +} + +uint32 +si_srpwr_domain(si_t *sih) +{ + uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ? + OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih); + uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx; + + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = si_corereg(sih, cidx, offset, 0, 0); + } else { + r = si_corereg_pciefast_read(sih, offset); + } + + r = (r >> SRPWR_DMN_ID_SHIFT) & SRPWR_DMN_ID_MASK; + + return r; +} + +uint32 +si_srpwr_domain_all_mask(si_t *sih) +{ + uint32 mask = SRPWR_DMN0_PCIE_MASK | + SRPWR_DMN1_ARMBPSD_MASK | + SRPWR_DMN2_MACAUX_MASK | + SRPWR_DMN3_MACMAIN_MASK; + + if (si_scan_core_present(sih)) { + mask |= SRPWR_DMN4_MACSCAN_MASK; + } + + return mask; +} + +/* Utility API to read/write the raw registers with absolute address. + * This function can be invoked from either FW or host driver. + */ +uint32 +si_raw_reg(si_t *sih, uint32 reg, uint32 val, uint32 wrire_req) +{ + si_info_t *sii = SI_INFO(sih); + uint32 address_space = reg & ~0xFFF; + volatile uint32 * addr = (void*)(uintptr)(reg); + uint32 prev_value = 0; + uint32 cfg_reg = 0; + + if (sii == NULL) { + return 0; + } + + /* No need to translate the absolute address on SI bus */ + if (BUSTYPE(sih->bustype) == SI_BUS) { + goto skip_cfg; + } + + /* This API supports only the PCI host interface */ + if (BUSTYPE(sih->bustype) != PCI_BUS) { + return ID32_INVALID; + } + + if (PCIE_GEN2(sii)) { + /* Use BAR0 Secondary window is PCIe Gen2. + * Set the secondary BAR0 Window to current register of interest + */ + addr = (volatile uint32*)(((volatile uint8*)sii->curmap) + + PCI_SEC_BAR0_WIN_OFFSET + (reg & 0xfff)); + cfg_reg = PCIE2_BAR0_CORE2_WIN; + + } else { + /* PCIe Gen1 do not have secondary BAR0 window. + * reuse the BAR0 WIN2 + */ + addr = (volatile uint32*)(((volatile uint8*)sii->curmap) + + PCI_BAR0_WIN2_OFFSET + (reg & 0xfff)); + cfg_reg = PCI_BAR0_WIN2; + } + + prev_value = OSL_PCI_READ_CONFIG(sii->osh, cfg_reg, 4); + + if (prev_value != address_space) { + OSL_PCI_WRITE_CONFIG(sii->osh, cfg_reg, + sizeof(uint32), address_space); + } else { + prev_value = 0; + } + +skip_cfg: + if (wrire_req) { + W_REG(sii->osh, addr, val); + } else { + val = R_REG(sii->osh, addr); + } + + if (prev_value) { + /* Restore BAR0 WIN2 for PCIE GEN1 devices */ + OSL_PCI_WRITE_CONFIG(sii->osh, + cfg_reg, sizeof(uint32), prev_value); + } + + return val; +} + +uint8 +si_lhl_ps_mode(si_t *sih) +{ + si_info_t *sii = SI_INFO(sih); + return sii->lhl_ps_mode; +} + +bool +BCMRAMFN(si_scan_core_present)(si_t *sih) +{ + return ((si_numcoreunits(sih, D11_CORE_ID) >= 2) && + (si_numcoreunits(sih, SR_CORE_ID) > 4)); } -- Gitblit v1.6.2