Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmfmac/chip.c
178665 views
// SPDX-License-Identifier: ISC1/*2* Copyright (c) 2014 Broadcom Corporation3*/4#include <linux/kernel.h>5#include <linux/delay.h>6#include <linux/list.h>7#include <linux/ssb/ssb_regs.h>8#include <linux/bcma/bcma.h>9#include <linux/bcma/bcma_regs.h>1011#include <defs.h>12#include <soc.h>13#include <brcm_hw_ids.h>14#include <brcmu_utils.h>15#include <chipcommon.h>16#include "debug.h"17#include "chip.h"1819/* SOC Interconnect types (aka chip types) */20#define SOCI_SB 021#define SOCI_AI 12223/* PL-368 DMP definitions */24#define DMP_DESC_TYPE_MSK 0x0000000F25#define DMP_DESC_EMPTY 0x0000000026#define DMP_DESC_VALID 0x0000000127#define DMP_DESC_COMPONENT 0x0000000128#define DMP_DESC_MASTER_PORT 0x0000000329#define DMP_DESC_ADDRESS 0x0000000530#define DMP_DESC_ADDRSIZE_GT32 0x0000000831#define DMP_DESC_EOT 0x0000000F3233#define DMP_COMP_DESIGNER 0xFFF0000034#define DMP_COMP_DESIGNER_S 2035#define DMP_COMP_PARTNUM 0x000FFF0036#define DMP_COMP_PARTNUM_S 837#define DMP_COMP_CLASS 0x000000F038#define DMP_COMP_CLASS_S 439#define DMP_COMP_REVISION 0xFF00000040#define DMP_COMP_REVISION_S 2441#define DMP_COMP_NUM_SWRAP 0x00F8000042#define DMP_COMP_NUM_SWRAP_S 1943#define DMP_COMP_NUM_MWRAP 0x0007C00044#define DMP_COMP_NUM_MWRAP_S 1445#define DMP_COMP_NUM_SPORT 0x00003E0046#define DMP_COMP_NUM_SPORT_S 947#define DMP_COMP_NUM_MPORT 0x000001F048#define DMP_COMP_NUM_MPORT_S 44950#define DMP_MASTER_PORT_UID 0x0000FF0051#define DMP_MASTER_PORT_UID_S 852#define DMP_MASTER_PORT_NUM 0x000000F053#define DMP_MASTER_PORT_NUM_S 45455#define DMP_SLAVE_ADDR_BASE 0xFFFFF00056#define DMP_SLAVE_ADDR_BASE_S 1257#define DMP_SLAVE_PORT_NUM 0x00000F0058#define DMP_SLAVE_PORT_NUM_S 859#define DMP_SLAVE_TYPE 0x000000C060#define DMP_SLAVE_TYPE_S 661#define DMP_SLAVE_TYPE_SLAVE 062#define DMP_SLAVE_TYPE_BRIDGE 163#define DMP_SLAVE_TYPE_SWRAP 264#define DMP_SLAVE_TYPE_MWRAP 365#define DMP_SLAVE_SIZE_TYPE 0x0000003066#define DMP_SLAVE_SIZE_TYPE_S 467#define DMP_SLAVE_SIZE_4K 068#define DMP_SLAVE_SIZE_8K 169#define DMP_SLAVE_SIZE_16K 270#define DMP_SLAVE_SIZE_DESC 37172/* EROM CompIdentB */73#define CIB_REV_MASK 0xff00000074#define CIB_REV_SHIFT 247576/* ARM CR4 core specific control flag bits */77#define ARMCR4_BCMA_IOCTL_CPUHALT 0x00207879/* D11 core specific control flag bits */80#define D11_BCMA_IOCTL_PHYCLOCKEN 0x000481#define D11_BCMA_IOCTL_PHYRESET 0x00088283/* chip core base & ramsize */84/* bcm4329 */85/* SDIO device core, ID 0x829 */86#define BCM4329_CORE_BUS_BASE 0x1801100087/* internal memory core, ID 0x80e */88#define BCM4329_CORE_SOCRAM_BASE 0x1800300089/* ARM Cortex M3 core, ID 0x82a */90#define BCM4329_CORE_ARM_BASE 0x180020009192/* Max possibly supported memory size (limited by IO mapped memory) */93#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024)9495#define CORE_SB(base, field) \96(base + SBCONFIGOFF + offsetof(struct sbconfig, field))97#define SBCOREREV(sbidh) \98((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \99((sbidh) & SSB_IDHIGH_RCLO))100101struct sbconfig {102u32 PAD[2];103u32 sbipsflag; /* initiator port ocp slave flag */104u32 PAD[3];105u32 sbtpsflag; /* target port ocp slave flag */106u32 PAD[11];107u32 sbtmerrloga; /* (sonics >= 2.3) */108u32 PAD;109u32 sbtmerrlog; /* (sonics >= 2.3) */110u32 PAD[3];111u32 sbadmatch3; /* address match3 */112u32 PAD;113u32 sbadmatch2; /* address match2 */114u32 PAD;115u32 sbadmatch1; /* address match1 */116u32 PAD[7];117u32 sbimstate; /* initiator agent state */118u32 sbintvec; /* interrupt mask */119u32 sbtmstatelow; /* target state */120u32 sbtmstatehigh; /* target state */121u32 sbbwa0; /* bandwidth allocation table0 */122u32 PAD;123u32 sbimconfiglow; /* initiator configuration */124u32 sbimconfighigh; /* initiator configuration */125u32 sbadmatch0; /* address match0 */126u32 PAD;127u32 sbtmconfiglow; /* target configuration */128u32 sbtmconfighigh; /* target configuration */129u32 sbbconfig; /* broadcast configuration */130u32 PAD;131u32 sbbstate; /* broadcast state */132u32 PAD[3];133u32 sbactcnfg; /* activate configuration */134u32 PAD[3];135u32 sbflagst; /* current sbflags */136u32 PAD[3];137u32 sbidlow; /* identification */138u32 sbidhigh; /* identification */139};140141#define INVALID_RAMBASE ((u32)(~0))142143/* bankidx and bankinfo reg defines corerev >= 8 */144#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000145#define SOCRAM_BANKINFO_SZMASK 0x0000007f146#define SOCRAM_BANKIDX_ROM_MASK 0x00000100147148#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8149/* socram bankinfo memtype */150#define SOCRAM_MEMTYPE_RAM 0151#define SOCRAM_MEMTYPE_R0M 1152#define SOCRAM_MEMTYPE_DEVRAM 2153154#define SOCRAM_BANKINFO_SZBASE 8192155#define SRCI_LSS_MASK 0x00f00000156#define SRCI_LSS_SHIFT 20157#define SRCI_SRNB_MASK 0xf0158#define SRCI_SRNB_MASK_EXT 0x100159#define SRCI_SRNB_SHIFT 4160#define SRCI_SRBSZ_MASK 0xf161#define SRCI_SRBSZ_SHIFT 0162#define SR_BSZ_BASE 14163164struct sbsocramregs {165u32 coreinfo;166u32 bwalloc;167u32 extracoreinfo;168u32 biststat;169u32 bankidx;170u32 standbyctrl;171172u32 errlogstatus; /* rev 6 */173u32 errlogaddr; /* rev 6 */174/* used for patching rev 3 & 5 */175u32 cambankidx;176u32 cambankstandbyctrl;177u32 cambankpatchctrl;178u32 cambankpatchtblbaseaddr;179u32 cambankcmdreg;180u32 cambankdatareg;181u32 cambankmaskreg;182u32 PAD[1];183u32 bankinfo; /* corev 8 */184u32 bankpda;185u32 PAD[14];186u32 extmemconfig;187u32 extmemparitycsr;188u32 extmemparityerrdata;189u32 extmemparityerrcnt;190u32 extmemwrctrlandsize;191u32 PAD[84];192u32 workaround;193u32 pwrctl; /* corerev >= 2 */194u32 PAD[133];195u32 sr_control; /* corerev >= 15 */196u32 sr_status; /* corerev >= 15 */197u32 sr_address; /* corerev >= 15 */198u32 sr_data; /* corerev >= 15 */199};200201#define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f)202#define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f)203204#define ARMCR4_CAP (0x04)205#define ARMCR4_BANKIDX (0x40)206#define ARMCR4_BANKINFO (0x44)207#define ARMCR4_BANKPDA (0x4C)208209#define ARMCR4_TCBBNB_MASK 0xf0210#define ARMCR4_TCBBNB_SHIFT 4211#define ARMCR4_TCBANB_MASK 0xf212#define ARMCR4_TCBANB_SHIFT 0213214#define ARMCR4_BSZ_MASK 0x7f215#define ARMCR4_BSZ_MULT 8192216#define ARMCR4_BLK_1K_MASK 0x200217218struct brcmf_core_priv {219struct brcmf_core pub;220u32 wrapbase;221struct list_head list;222struct brcmf_chip_priv *chip;223};224225struct brcmf_chip_priv {226struct brcmf_chip pub;227const struct brcmf_buscore_ops *ops;228void *ctx;229/* assured first core is chipcommon, second core is buscore */230struct list_head cores;231u16 num_cores;232233bool (*iscoreup)(struct brcmf_core_priv *core);234void (*coredisable)(struct brcmf_core_priv *core, u32 prereset,235u32 reset);236void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset,237u32 postreset);238};239240static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci,241struct brcmf_core *core)242{243u32 regdata;244245regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh));246core->rev = SBCOREREV(regdata);247}248249static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core)250{251struct brcmf_chip_priv *ci;252u32 regdata;253u32 address;254255ci = core->chip;256address = CORE_SB(core->pub.base, sbtmstatelow);257regdata = ci->ops->read32(ci->ctx, address);258regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |259SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);260return SSB_TMSLOW_CLOCK == regdata;261}262263static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core)264{265struct brcmf_chip_priv *ci;266u32 regdata;267bool ret;268269ci = core->chip;270regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);271ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;272273regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);274ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);275276return ret;277}278279static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core,280u32 prereset, u32 reset)281{282struct brcmf_chip_priv *ci;283u32 val, base;284285ci = core->chip;286base = core->pub.base;287val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));288if (val & SSB_TMSLOW_RESET)289return;290291val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));292if ((val & SSB_TMSLOW_CLOCK) != 0) {293/*294* set target reject and spin until busy is clear295* (preserve core-specific bits)296*/297val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));298ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),299val | SSB_TMSLOW_REJECT);300301val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));302udelay(1);303SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh))304& SSB_TMSHIGH_BUSY), 100000);305306val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));307if (val & SSB_TMSHIGH_BUSY)308brcmf_err("core state still busy\n");309310val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));311if (val & SSB_IDLOW_INITIATOR) {312val = ci->ops->read32(ci->ctx,313CORE_SB(base, sbimstate));314val |= SSB_IMSTATE_REJECT;315ci->ops->write32(ci->ctx,316CORE_SB(base, sbimstate), val);317val = ci->ops->read32(ci->ctx,318CORE_SB(base, sbimstate));319udelay(1);320SPINWAIT((ci->ops->read32(ci->ctx,321CORE_SB(base, sbimstate)) &322SSB_IMSTATE_BUSY), 100000);323}324325/* set reset and reject while enabling the clocks */326val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |327SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;328ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);329val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));330udelay(10);331332/* clear the initiator reject bit */333val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));334if (val & SSB_IDLOW_INITIATOR) {335val = ci->ops->read32(ci->ctx,336CORE_SB(base, sbimstate));337val &= ~SSB_IMSTATE_REJECT;338ci->ops->write32(ci->ctx,339CORE_SB(base, sbimstate), val);340}341}342343/* leave reset and reject asserted */344ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),345(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));346udelay(1);347}348349static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,350u32 prereset, u32 reset)351{352struct brcmf_chip_priv *ci;353u32 regdata;354355ci = core->chip;356357/* if core is already in reset, skip reset */358regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);359if ((regdata & BCMA_RESET_CTL_RESET) != 0)360goto in_reset_configure;361362/* configure reset */363ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,364prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);365ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);366367/* put in reset */368ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL,369BCMA_RESET_CTL_RESET);370usleep_range(10, 20);371372/* wait till reset is 1 */373SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=374BCMA_RESET_CTL_RESET, 300);375376in_reset_configure:377/* in-reset configure */378ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,379reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);380ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);381}382383static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset,384u32 reset, u32 postreset)385{386struct brcmf_chip_priv *ci;387u32 regdata;388u32 base;389390ci = core->chip;391base = core->pub.base;392/*393* Must do the disable sequence first to work for394* arbitrary current core state.395*/396brcmf_chip_sb_coredisable(core, 0, 0);397398/*399* Now do the initialization sequence.400* set reset while enabling the clock and401* forcing them on throughout the core402*/403ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),404SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |405SSB_TMSLOW_RESET);406regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));407udelay(1);408409/* clear any serror */410regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));411if (regdata & SSB_TMSHIGH_SERR)412ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);413414regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate));415if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {416regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);417ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata);418}419420/* clear reset and allow it to propagate throughout the core */421ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),422SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);423regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));424udelay(1);425426/* leave clock enabled */427ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),428SSB_TMSLOW_CLOCK);429regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));430udelay(1);431}432433static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset,434u32 reset, u32 postreset)435{436struct brcmf_chip_priv *ci;437int count;438struct brcmf_core *d11core2 = NULL;439struct brcmf_core_priv *d11priv2 = NULL;440441ci = core->chip;442443/* special handle two D11 cores reset */444if (core->pub.id == BCMA_CORE_80211) {445d11core2 = brcmf_chip_get_d11core(&ci->pub, 1);446if (d11core2) {447brcmf_dbg(INFO, "found two d11 cores, reset both\n");448d11priv2 = container_of(d11core2,449struct brcmf_core_priv, pub);450}451}452453/* must disable first to work for arbitrary current core state */454brcmf_chip_ai_coredisable(core, prereset, reset);455if (d11priv2)456brcmf_chip_ai_coredisable(d11priv2, prereset, reset);457458count = 0;459while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) &460BCMA_RESET_CTL_RESET) {461ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0);462count++;463if (count > 50)464break;465usleep_range(40, 60);466}467468if (d11priv2) {469count = 0;470while (ci->ops->read32(ci->ctx,471d11priv2->wrapbase + BCMA_RESET_CTL) &472BCMA_RESET_CTL_RESET) {473ci->ops->write32(ci->ctx,474d11priv2->wrapbase + BCMA_RESET_CTL,4750);476count++;477if (count > 50)478break;479usleep_range(40, 60);480}481}482483ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,484postreset | BCMA_IOCTL_CLK);485ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);486487if (d11priv2) {488ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL,489postreset | BCMA_IOCTL_CLK);490ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL);491}492}493494char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)495{496const char *fmt;497498fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u";499snprintf(buf, len, fmt, id, rev);500return buf;501}502503static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,504u16 coreid, u32 base,505u32 wrapbase)506{507struct brcmf_core_priv *core;508509core = kzalloc(sizeof(*core), GFP_KERNEL);510if (!core)511return ERR_PTR(-ENOMEM);512513core->pub.id = coreid;514core->pub.base = base;515core->chip = ci;516core->wrapbase = wrapbase;517518list_add_tail(&core->list, &ci->cores);519return &core->pub;520}521522/* safety check for chipinfo */523static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)524{525struct brcmf_core_priv *core;526bool need_socram = false;527bool has_socram = false;528bool cpu_found = false;529int idx = 1;530531list_for_each_entry(core, &ci->cores, list) {532brcmf_dbg(INFO, " [%-2d] core 0x%x:%-3d base 0x%08x wrap 0x%08x\n",533idx++, core->pub.id, core->pub.rev, core->pub.base,534core->wrapbase);535536switch (core->pub.id) {537case BCMA_CORE_ARM_CM3:538cpu_found = true;539need_socram = true;540break;541case BCMA_CORE_INTERNAL_MEM:542has_socram = true;543break;544case BCMA_CORE_ARM_CR4:545cpu_found = true;546break;547case BCMA_CORE_ARM_CA7:548cpu_found = true;549break;550default:551break;552}553}554555if (!cpu_found) {556brcmf_err("CPU core not detected\n");557return -ENXIO;558}559/* check RAM core presence for ARM CM3 core */560if (need_socram && !has_socram) {561brcmf_err("RAM core not provided with ARM CM3 core\n");562return -ENODEV;563}564return 0;565}566567static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg)568{569return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg);570}571572static void brcmf_chip_core_write32(struct brcmf_core_priv *core,573u16 reg, u32 val)574{575core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val);576}577578static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx,579u32 *banksize)580{581u32 bankinfo;582u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);583584bankidx |= idx;585brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx);586bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo));587*banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1;588*banksize *= SOCRAM_BANKINFO_SZBASE;589return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK);590}591592static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,593u32 *srsize)594{595u32 coreinfo;596uint nb, banksize, lss;597bool retent;598int i;599600*ramsize = 0;601*srsize = 0;602603if (WARN_ON(sr->pub.rev < 4))604return;605606if (!brcmf_chip_iscoreup(&sr->pub))607brcmf_chip_resetcore(&sr->pub, 0, 0, 0);608609/* Get info for determining size */610coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));611nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;612613if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {614banksize = (coreinfo & SRCI_SRBSZ_MASK);615lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;616if (lss != 0)617nb--;618*ramsize = nb * (1 << (banksize + SR_BSZ_BASE));619if (lss != 0)620*ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));621} else {622/* length of SRAM Banks increased for corerev greater than 23 */623if (sr->pub.rev >= 23) {624nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT))625>> SRCI_SRNB_SHIFT;626} else {627nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;628}629for (i = 0; i < nb; i++) {630retent = brcmf_chip_socram_banksize(sr, i, &banksize);631*ramsize += banksize;632if (retent)633*srsize += banksize;634}635}636637/* hardcoded save&restore memory sizes */638switch (sr->chip->pub.chip) {639case BRCM_CC_4334_CHIP_ID:640if (sr->chip->pub.chiprev < 2)641*srsize = (32 * 1024);642break;643case BRCM_CC_43430_CHIP_ID:644case CY_CC_43439_CHIP_ID:645/* assume sr for now as we can not check646* firmware sr capability at this point.647*/648*srsize = (64 * 1024);649break;650default:651break;652}653}654655/** Return the SYS MEM size */656static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem)657{658u32 memsize = 0;659u32 coreinfo;660u32 idx;661u32 nb;662u32 banksize;663664if (!brcmf_chip_iscoreup(&sysmem->pub))665brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0);666667coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo));668nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;669670for (idx = 0; idx < nb; idx++) {671brcmf_chip_socram_banksize(sysmem, idx, &banksize);672memsize += banksize;673}674675return memsize;676}677678/** Return the TCM-RAM size of the ARMCR4 core. */679static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)680{681u32 corecap;682u32 memsize = 0;683u32 nab;684u32 nbb;685u32 totb;686u32 bxinfo;687u32 blksize;688u32 idx;689690corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);691692nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;693nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;694totb = nab + nbb;695696for (idx = 0; idx < totb; idx++) {697brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);698bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);699blksize = ARMCR4_BSZ_MULT;700if (bxinfo & ARMCR4_BLK_1K_MASK)701blksize >>= 3;702703memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize;704}705706return memsize;707}708709static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)710{711switch (ci->pub.chip) {712case BRCM_CC_4345_CHIP_ID:713case BRCM_CC_43454_CHIP_ID:714return 0x198000;715case BRCM_CC_4335_CHIP_ID:716case BRCM_CC_4339_CHIP_ID:717case BRCM_CC_4350_CHIP_ID:718case BRCM_CC_4354_CHIP_ID:719case BRCM_CC_4356_CHIP_ID:720case BRCM_CC_43567_CHIP_ID:721case BRCM_CC_43569_CHIP_ID:722case BRCM_CC_43570_CHIP_ID:723case BRCM_CC_4358_CHIP_ID:724case BRCM_CC_43602_CHIP_ID:725case BRCM_CC_4371_CHIP_ID:726return 0x180000;727case BRCM_CC_43465_CHIP_ID:728case BRCM_CC_43525_CHIP_ID:729case BRCM_CC_4365_CHIP_ID:730case BRCM_CC_4366_CHIP_ID:731case BRCM_CC_43664_CHIP_ID:732case BRCM_CC_43666_CHIP_ID:733return 0x200000;734case BRCM_CC_4355_CHIP_ID:735case BRCM_CC_4359_CHIP_ID:736return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000;737case BRCM_CC_4364_CHIP_ID:738case CY_CC_4373_CHIP_ID:739return 0x160000;740case BRCM_CC_43751_CHIP_ID:741case BRCM_CC_43752_CHIP_ID:742case BRCM_CC_4377_CHIP_ID:743return 0x170000;744case BRCM_CC_4378_CHIP_ID:745return 0x352000;746case BRCM_CC_4387_CHIP_ID:747return 0x740000;748default:749brcmf_err("unknown chip: %s\n", ci->pub.name);750break;751}752return INVALID_RAMBASE;753}754755int brcmf_chip_get_raminfo(struct brcmf_chip *pub)756{757struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv,758pub);759struct brcmf_core_priv *mem_core;760struct brcmf_core *mem;761762mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4);763if (mem) {764mem_core = container_of(mem, struct brcmf_core_priv, pub);765ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);766ci->pub.rambase = brcmf_chip_tcm_rambase(ci);767if (ci->pub.rambase == INVALID_RAMBASE) {768brcmf_err("RAM base not provided with ARM CR4 core\n");769return -EINVAL;770}771} else {772mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM);773if (mem) {774mem_core = container_of(mem, struct brcmf_core_priv,775pub);776ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core);777ci->pub.rambase = brcmf_chip_tcm_rambase(ci);778if (ci->pub.rambase == INVALID_RAMBASE) {779brcmf_err("RAM base not provided with ARM CA7 core\n");780return -EINVAL;781}782} else {783mem = brcmf_chip_get_core(&ci->pub,784BCMA_CORE_INTERNAL_MEM);785if (!mem) {786brcmf_err("No memory cores found\n");787return -ENOMEM;788}789mem_core = container_of(mem, struct brcmf_core_priv,790pub);791brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,792&ci->pub.srsize);793}794}795brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",796ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,797ci->pub.srsize, ci->pub.srsize);798799if (!ci->pub.ramsize) {800brcmf_err("RAM size is undetermined\n");801return -ENOMEM;802}803804if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {805brcmf_err("RAM size is incorrect\n");806return -ENOMEM;807}808809return 0;810}811812static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,813u8 *type)814{815u32 val;816817/* read next descriptor */818val = ci->ops->read32(ci->ctx, *eromaddr);819*eromaddr += 4;820821if (!type)822return val;823824/* determine descriptor type */825*type = (val & DMP_DESC_TYPE_MSK);826if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)827*type = DMP_DESC_ADDRESS;828829return val;830}831832static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,833u32 *regbase, u32 *wrapbase)834{835u8 desc;836u32 val, szdesc;837u8 stype, sztype, wraptype;838839*regbase = 0;840*wrapbase = 0;841842val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);843if (desc == DMP_DESC_MASTER_PORT) {844wraptype = DMP_SLAVE_TYPE_MWRAP;845} else if (desc == DMP_DESC_ADDRESS) {846/* revert erom address */847*eromaddr -= 4;848wraptype = DMP_SLAVE_TYPE_SWRAP;849} else {850*eromaddr -= 4;851return -EILSEQ;852}853854do {855/* locate address descriptor */856do {857val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);858/* unexpected table end */859if (desc == DMP_DESC_EOT) {860*eromaddr -= 4;861return -EFAULT;862}863} while (desc != DMP_DESC_ADDRESS &&864desc != DMP_DESC_COMPONENT);865866/* stop if we crossed current component border */867if (desc == DMP_DESC_COMPONENT) {868*eromaddr -= 4;869return 0;870}871872/* skip upper 32-bit address descriptor */873if (val & DMP_DESC_ADDRSIZE_GT32)874brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);875876sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;877878/* next size descriptor can be skipped */879if (sztype == DMP_SLAVE_SIZE_DESC) {880szdesc = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);881/* skip upper size descriptor if present */882if (szdesc & DMP_DESC_ADDRSIZE_GT32)883brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);884}885886/* look for 4K or 8K register regions */887if (sztype != DMP_SLAVE_SIZE_4K &&888sztype != DMP_SLAVE_SIZE_8K)889continue;890891stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;892893/* only regular slave and wrapper */894if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)895*regbase = val & DMP_SLAVE_ADDR_BASE;896if (*wrapbase == 0 && stype == wraptype)897*wrapbase = val & DMP_SLAVE_ADDR_BASE;898} while (*regbase == 0 || *wrapbase == 0);899900return 0;901}902903static904int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)905{906struct brcmf_core *core;907u32 eromaddr;908u8 desc_type = 0;909u32 val;910u16 id;911u8 nmw, nsw, rev;912u32 base, wrap;913int err;914915eromaddr = ci->ops->read32(ci->ctx,916CORE_CC_REG(ci->pub.enum_base, eromptr));917918while (desc_type != DMP_DESC_EOT) {919val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);920if (!(val & DMP_DESC_VALID))921continue;922923if (desc_type == DMP_DESC_EMPTY)924continue;925926/* need a component descriptor */927if (desc_type != DMP_DESC_COMPONENT)928continue;929930id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;931932/* next descriptor must be component as well */933val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);934if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))935return -EFAULT;936937/* only look at cores with master port(s) */938nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;939nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;940rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;941942/* need core with ports */943if (nmw + nsw == 0 &&944id != BCMA_CORE_PMU &&945id != BCMA_CORE_GCI)946continue;947948/* try to obtain register address info */949err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);950if (err)951continue;952953/* finally a core to be added */954core = brcmf_chip_add_core(ci, id, base, wrap);955if (IS_ERR(core))956return PTR_ERR(core);957958core->rev = rev;959}960961return 0;962}963964u32 brcmf_chip_enum_base(u16 devid)965{966return SI_ENUM_BASE_DEFAULT;967}968969static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)970{971struct brcmf_core *core;972u32 regdata;973u32 socitype;974int ret;975const u32 READ_FAILED = 0xFFFFFFFF;976977/* Get CC core rev978* Chipid is assume to be at offset 0 from SI_ENUM_BASE979* For different chiptypes or old sdio hosts w/o chipcommon,980* other ways of recognition should be added here.981*/982regdata = ci->ops->read32(ci->ctx,983CORE_CC_REG(ci->pub.enum_base, chipid));984if (regdata == READ_FAILED) {985brcmf_err("MMIO read failed: 0x%08x\n", regdata);986return -ENODEV;987}988989ci->pub.chip = regdata & CID_ID_MASK;990ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;991socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;992993brcmf_chip_name(ci->pub.chip, ci->pub.chiprev,994ci->pub.name, sizeof(ci->pub.name));995brcmf_dbg(INFO, "found %s chip: %s\n",996socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name);997998if (socitype == SOCI_SB) {999if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {1000brcmf_err("SB chip is not supported\n");1001return -ENODEV;1002}1003ci->iscoreup = brcmf_chip_sb_iscoreup;1004ci->coredisable = brcmf_chip_sb_coredisable;1005ci->resetcore = brcmf_chip_sb_resetcore;10061007core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,1008SI_ENUM_BASE_DEFAULT, 0);1009brcmf_chip_sb_corerev(ci, core);1010core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,1011BCM4329_CORE_BUS_BASE, 0);1012brcmf_chip_sb_corerev(ci, core);1013core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,1014BCM4329_CORE_SOCRAM_BASE, 0);1015brcmf_chip_sb_corerev(ci, core);1016core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,1017BCM4329_CORE_ARM_BASE, 0);1018brcmf_chip_sb_corerev(ci, core);10191020core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);1021brcmf_chip_sb_corerev(ci, core);1022} else if (socitype == SOCI_AI) {1023ci->iscoreup = brcmf_chip_ai_iscoreup;1024ci->coredisable = brcmf_chip_ai_coredisable;1025ci->resetcore = brcmf_chip_ai_resetcore;10261027brcmf_chip_dmp_erom_scan(ci);1028} else {1029brcmf_err("chip backplane type %u is not supported\n",1030socitype);1031return -ENODEV;1032}10331034ret = brcmf_chip_cores_check(ci);1035if (ret)1036return ret;10371038/* assure chip is passive for core access */1039brcmf_chip_set_passive(&ci->pub);10401041/* Call bus specific reset function now. Cores have been determined1042* but further access may require a chip specific reset at this point.1043*/1044if (ci->ops->reset) {1045ci->ops->reset(ci->ctx, &ci->pub);1046brcmf_chip_set_passive(&ci->pub);1047}10481049return brcmf_chip_get_raminfo(&ci->pub);1050}10511052static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)1053{1054struct brcmf_core *core;1055struct brcmf_core_priv *cpu;1056u32 val;105710581059core = brcmf_chip_get_core(&chip->pub, id);1060if (!core)1061return;10621063switch (id) {1064case BCMA_CORE_ARM_CM3:1065brcmf_chip_coredisable(core, 0, 0);1066break;1067case BCMA_CORE_ARM_CR4:1068case BCMA_CORE_ARM_CA7:1069cpu = container_of(core, struct brcmf_core_priv, pub);10701071/* clear all IOCTL bits except HALT bit */1072val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);1073val &= ARMCR4_BCMA_IOCTL_CPUHALT;1074brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,1075ARMCR4_BCMA_IOCTL_CPUHALT);1076break;1077default:1078brcmf_err("unknown id: %u\n", id);1079break;1080}1081}10821083static int brcmf_chip_setup(struct brcmf_chip_priv *chip)1084{1085struct brcmf_chip *pub;1086struct brcmf_core_priv *cc;1087struct brcmf_core *pmu;1088u32 base;1089u32 val;1090int ret = 0;10911092pub = &chip->pub;1093cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);1094base = cc->pub.base;10951096/* get chipcommon capabilites */1097pub->cc_caps = chip->ops->read32(chip->ctx,1098CORE_CC_REG(base, capabilities));1099pub->cc_caps_ext = chip->ops->read32(chip->ctx,1100CORE_CC_REG(base,1101capabilities_ext));11021103/* get pmu caps & rev */1104pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */1105if (pub->cc_caps & CC_CAP_PMU) {1106val = chip->ops->read32(chip->ctx,1107CORE_CC_REG(pmu->base, pmucapabilities));1108pub->pmurev = val & PCAP_REV_MASK;1109pub->pmucaps = val;1110}11111112brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",1113cc->pub.rev, pub->pmurev, pub->pmucaps);11141115/* execute bus core specific setup */1116if (chip->ops->setup)1117ret = chip->ops->setup(chip->ctx, pub);11181119return ret;1120}11211122struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,1123const struct brcmf_buscore_ops *ops)1124{1125struct brcmf_chip_priv *chip;1126int err = 0;11271128if (WARN_ON(!ops->read32))1129err = -EINVAL;1130if (WARN_ON(!ops->write32))1131err = -EINVAL;1132if (WARN_ON(!ops->prepare))1133err = -EINVAL;1134if (WARN_ON(!ops->activate))1135err = -EINVAL;1136if (err < 0)1137return ERR_PTR(-EINVAL);11381139chip = kzalloc(sizeof(*chip), GFP_KERNEL);1140if (!chip)1141return ERR_PTR(-ENOMEM);11421143INIT_LIST_HEAD(&chip->cores);1144chip->num_cores = 0;1145chip->ops = ops;1146chip->ctx = ctx;1147chip->pub.enum_base = brcmf_chip_enum_base(devid);11481149err = ops->prepare(ctx);1150if (err < 0)1151goto fail;11521153err = brcmf_chip_recognition(chip);1154if (err < 0)1155goto fail;11561157err = brcmf_chip_setup(chip);1158if (err < 0)1159goto fail;11601161return &chip->pub;11621163fail:1164brcmf_chip_detach(&chip->pub);1165return ERR_PTR(err);1166}11671168void brcmf_chip_detach(struct brcmf_chip *pub)1169{1170struct brcmf_chip_priv *chip;1171struct brcmf_core_priv *core;1172struct brcmf_core_priv *tmp;11731174chip = container_of(pub, struct brcmf_chip_priv, pub);1175list_for_each_entry_safe(core, tmp, &chip->cores, list) {1176list_del(&core->list);1177kfree(core);1178}1179kfree(chip);1180}11811182struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit)1183{1184struct brcmf_chip_priv *chip;1185struct brcmf_core_priv *core;11861187chip = container_of(pub, struct brcmf_chip_priv, pub);1188list_for_each_entry(core, &chip->cores, list) {1189if (core->pub.id == BCMA_CORE_80211) {1190if (unit-- == 0)1191return &core->pub;1192}1193}1194return NULL;1195}11961197struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid)1198{1199struct brcmf_chip_priv *chip;1200struct brcmf_core_priv *core;12011202chip = container_of(pub, struct brcmf_chip_priv, pub);1203list_for_each_entry(core, &chip->cores, list)1204if (core->pub.id == coreid)1205return &core->pub;12061207return NULL;1208}12091210struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub)1211{1212struct brcmf_chip_priv *chip;1213struct brcmf_core_priv *cc;12141215chip = container_of(pub, struct brcmf_chip_priv, pub);1216cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);1217if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON))1218return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON);1219return &cc->pub;1220}12211222struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)1223{1224struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);1225struct brcmf_core *pmu;12261227/* See if there is separated PMU core available */1228if (cc->rev >= 35 &&1229pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {1230pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);1231if (pmu)1232return pmu;1233}12341235/* Fallback to ChipCommon core for older hardware */1236return cc;1237}12381239bool brcmf_chip_iscoreup(struct brcmf_core *pub)1240{1241struct brcmf_core_priv *core;12421243core = container_of(pub, struct brcmf_core_priv, pub);1244return core->chip->iscoreup(core);1245}12461247void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset)1248{1249struct brcmf_core_priv *core;12501251core = container_of(pub, struct brcmf_core_priv, pub);1252core->chip->coredisable(core, prereset, reset);1253}12541255void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset,1256u32 postreset)1257{1258struct brcmf_core_priv *core;12591260core = container_of(pub, struct brcmf_core_priv, pub);1261core->chip->resetcore(core, prereset, reset, postreset);1262}12631264static void1265brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)1266{1267struct brcmf_core *core;1268struct brcmf_core_priv *sr;12691270brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);1271core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);1272brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |1273D11_BCMA_IOCTL_PHYCLOCKEN,1274D11_BCMA_IOCTL_PHYCLOCKEN,1275D11_BCMA_IOCTL_PHYCLOCKEN);1276core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);1277brcmf_chip_resetcore(core, 0, 0, 0);12781279/* disable bank #3 remap for this device */1280if (chip->pub.chip == BRCM_CC_43430_CHIP_ID ||1281chip->pub.chip == CY_CC_43439_CHIP_ID) {1282sr = container_of(core, struct brcmf_core_priv, pub);1283brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3);1284brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0);1285}1286}12871288static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)1289{1290struct brcmf_core *core;12911292core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);1293if (!brcmf_chip_iscoreup(core)) {1294brcmf_err("SOCRAM core is down after reset?\n");1295return false;1296}12971298chip->ops->activate(chip->ctx, &chip->pub, 0);12991300core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);1301brcmf_chip_resetcore(core, 0, 0, 0);13021303return true;1304}13051306static inline void1307brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)1308{1309int i;1310struct brcmf_core *core;13111312brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);13131314/* Disable the cores only and let the firmware enable them.1315* Releasing reset ourselves breaks BCM4387 in weird ways.1316*/1317for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++)1318brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET |1319D11_BCMA_IOCTL_PHYCLOCKEN,1320D11_BCMA_IOCTL_PHYCLOCKEN);1321}13221323static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)1324{1325struct brcmf_core *core;13261327chip->ops->activate(chip->ctx, &chip->pub, rstvec);13281329/* restore ARM */1330core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);1331brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);13321333return true;1334}13351336static inline void1337brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip)1338{1339struct brcmf_core *core;13401341brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7);13421343core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);1344brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |1345D11_BCMA_IOCTL_PHYCLOCKEN,1346D11_BCMA_IOCTL_PHYCLOCKEN,1347D11_BCMA_IOCTL_PHYCLOCKEN);1348}13491350static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec)1351{1352struct brcmf_core *core;13531354chip->ops->activate(chip->ctx, &chip->pub, rstvec);13551356/* restore ARM */1357core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7);1358brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);13591360return true;1361}13621363void brcmf_chip_set_passive(struct brcmf_chip *pub)1364{1365struct brcmf_chip_priv *chip;1366struct brcmf_core *arm;13671368brcmf_dbg(TRACE, "Enter\n");13691370chip = container_of(pub, struct brcmf_chip_priv, pub);1371arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);1372if (arm) {1373brcmf_chip_cr4_set_passive(chip);1374return;1375}1376arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);1377if (arm) {1378brcmf_chip_ca7_set_passive(chip);1379return;1380}1381arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);1382if (arm) {1383brcmf_chip_cm3_set_passive(chip);1384return;1385}1386}13871388bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)1389{1390struct brcmf_chip_priv *chip;1391struct brcmf_core *arm;13921393brcmf_dbg(TRACE, "Enter\n");13941395chip = container_of(pub, struct brcmf_chip_priv, pub);1396arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);1397if (arm)1398return brcmf_chip_cr4_set_active(chip, rstvec);1399arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);1400if (arm)1401return brcmf_chip_ca7_set_active(chip, rstvec);1402arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);1403if (arm)1404return brcmf_chip_cm3_set_active(chip);14051406return false;1407}14081409bool brcmf_chip_sr_capable(struct brcmf_chip *pub)1410{1411u32 base, addr, reg, pmu_cc3_mask = ~0;1412struct brcmf_chip_priv *chip;1413struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);14141415brcmf_dbg(TRACE, "Enter\n");14161417/* old chips with PMU version less than 17 don't support save restore */1418if (pub->pmurev < 17)1419return false;14201421base = brcmf_chip_get_chipcommon(pub)->base;1422chip = container_of(pub, struct brcmf_chip_priv, pub);14231424switch (pub->chip) {1425case BRCM_CC_4354_CHIP_ID:1426case BRCM_CC_4356_CHIP_ID:1427case BRCM_CC_4345_CHIP_ID:1428case BRCM_CC_43454_CHIP_ID:1429/* explicitly check SR engine enable bit */1430pmu_cc3_mask = BIT(2);1431fallthrough;1432case BRCM_CC_43241_CHIP_ID:1433case BRCM_CC_4335_CHIP_ID:1434case BRCM_CC_4339_CHIP_ID:1435/* read PMU chipcontrol register 3 */1436addr = CORE_CC_REG(pmu->base, chipcontrol_addr);1437chip->ops->write32(chip->ctx, addr, 3);1438addr = CORE_CC_REG(pmu->base, chipcontrol_data);1439reg = chip->ops->read32(chip->ctx, addr);1440return (reg & pmu_cc3_mask) != 0;1441case BRCM_CC_43430_CHIP_ID:1442case CY_CC_43439_CHIP_ID:1443addr = CORE_CC_REG(base, sr_control1);1444reg = chip->ops->read32(chip->ctx, addr);1445return reg != 0;1446case BRCM_CC_4355_CHIP_ID:1447case CY_CC_4373_CHIP_ID:1448/* explicitly check SR engine enable bit */1449addr = CORE_CC_REG(base, sr_control0);1450reg = chip->ops->read32(chip->ctx, addr);1451return (reg & CC_SR_CTL0_ENABLE_MASK) != 0;1452case BRCM_CC_4359_CHIP_ID:1453case BRCM_CC_43751_CHIP_ID:1454case BRCM_CC_43752_CHIP_ID:1455case CY_CC_43012_CHIP_ID:1456addr = CORE_CC_REG(pmu->base, retention_ctl);1457reg = chip->ops->read32(chip->ctx, addr);1458return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |1459PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;1460default:1461addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);1462reg = chip->ops->read32(chip->ctx, addr);1463if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)1464return false;14651466addr = CORE_CC_REG(pmu->base, retention_ctl);1467reg = chip->ops->read32(chip->ctx, addr);1468return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |1469PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;1470}1471}147214731474