1daeccac2SArend van Spriel // SPDX-License-Identifier: ISC 205491d2cSKalle Valo /* 305491d2cSKalle Valo * Copyright (c) 2014 Broadcom Corporation 405491d2cSKalle Valo */ 505491d2cSKalle Valo #include <linux/kernel.h> 605491d2cSKalle Valo #include <linux/delay.h> 705491d2cSKalle Valo #include <linux/list.h> 805491d2cSKalle Valo #include <linux/ssb/ssb_regs.h> 905491d2cSKalle Valo #include <linux/bcma/bcma.h> 1005491d2cSKalle Valo #include <linux/bcma/bcma_regs.h> 1105491d2cSKalle Valo 1205491d2cSKalle Valo #include <defs.h> 1305491d2cSKalle Valo #include <soc.h> 1405491d2cSKalle Valo #include <brcm_hw_ids.h> 1505491d2cSKalle Valo #include <brcmu_utils.h> 1605491d2cSKalle Valo #include <chipcommon.h> 1705491d2cSKalle Valo #include "debug.h" 1805491d2cSKalle Valo #include "chip.h" 1905491d2cSKalle Valo 2005491d2cSKalle Valo /* SOC Interconnect types (aka chip types) */ 2105491d2cSKalle Valo #define SOCI_SB 0 2205491d2cSKalle Valo #define SOCI_AI 1 2305491d2cSKalle Valo 2405491d2cSKalle Valo /* PL-368 DMP definitions */ 2505491d2cSKalle Valo #define DMP_DESC_TYPE_MSK 0x0000000F 2605491d2cSKalle Valo #define DMP_DESC_EMPTY 0x00000000 2705491d2cSKalle Valo #define DMP_DESC_VALID 0x00000001 2805491d2cSKalle Valo #define DMP_DESC_COMPONENT 0x00000001 2905491d2cSKalle Valo #define DMP_DESC_MASTER_PORT 0x00000003 3005491d2cSKalle Valo #define DMP_DESC_ADDRESS 0x00000005 3105491d2cSKalle Valo #define DMP_DESC_ADDRSIZE_GT32 0x00000008 3205491d2cSKalle Valo #define DMP_DESC_EOT 0x0000000F 3305491d2cSKalle Valo 3405491d2cSKalle Valo #define DMP_COMP_DESIGNER 0xFFF00000 3505491d2cSKalle Valo #define DMP_COMP_DESIGNER_S 20 3605491d2cSKalle Valo #define DMP_COMP_PARTNUM 0x000FFF00 3705491d2cSKalle Valo #define DMP_COMP_PARTNUM_S 8 3805491d2cSKalle Valo #define DMP_COMP_CLASS 0x000000F0 3905491d2cSKalle Valo #define DMP_COMP_CLASS_S 4 4005491d2cSKalle Valo #define DMP_COMP_REVISION 0xFF000000 4105491d2cSKalle Valo #define DMP_COMP_REVISION_S 24 4205491d2cSKalle Valo #define DMP_COMP_NUM_SWRAP 0x00F80000 4305491d2cSKalle Valo #define DMP_COMP_NUM_SWRAP_S 19 4405491d2cSKalle Valo #define DMP_COMP_NUM_MWRAP 0x0007C000 4505491d2cSKalle Valo #define DMP_COMP_NUM_MWRAP_S 14 4605491d2cSKalle Valo #define DMP_COMP_NUM_SPORT 0x00003E00 4705491d2cSKalle Valo #define DMP_COMP_NUM_SPORT_S 9 4805491d2cSKalle Valo #define DMP_COMP_NUM_MPORT 0x000001F0 4905491d2cSKalle Valo #define DMP_COMP_NUM_MPORT_S 4 5005491d2cSKalle Valo 5105491d2cSKalle Valo #define DMP_MASTER_PORT_UID 0x0000FF00 5205491d2cSKalle Valo #define DMP_MASTER_PORT_UID_S 8 5305491d2cSKalle Valo #define DMP_MASTER_PORT_NUM 0x000000F0 5405491d2cSKalle Valo #define DMP_MASTER_PORT_NUM_S 4 5505491d2cSKalle Valo 5605491d2cSKalle Valo #define DMP_SLAVE_ADDR_BASE 0xFFFFF000 5705491d2cSKalle Valo #define DMP_SLAVE_ADDR_BASE_S 12 5805491d2cSKalle Valo #define DMP_SLAVE_PORT_NUM 0x00000F00 5905491d2cSKalle Valo #define DMP_SLAVE_PORT_NUM_S 8 6005491d2cSKalle Valo #define DMP_SLAVE_TYPE 0x000000C0 6105491d2cSKalle Valo #define DMP_SLAVE_TYPE_S 6 6205491d2cSKalle Valo #define DMP_SLAVE_TYPE_SLAVE 0 6305491d2cSKalle Valo #define DMP_SLAVE_TYPE_BRIDGE 1 6405491d2cSKalle Valo #define DMP_SLAVE_TYPE_SWRAP 2 6505491d2cSKalle Valo #define DMP_SLAVE_TYPE_MWRAP 3 6605491d2cSKalle Valo #define DMP_SLAVE_SIZE_TYPE 0x00000030 6705491d2cSKalle Valo #define DMP_SLAVE_SIZE_TYPE_S 4 6805491d2cSKalle Valo #define DMP_SLAVE_SIZE_4K 0 6905491d2cSKalle Valo #define DMP_SLAVE_SIZE_8K 1 7005491d2cSKalle Valo #define DMP_SLAVE_SIZE_16K 2 7105491d2cSKalle Valo #define DMP_SLAVE_SIZE_DESC 3 7205491d2cSKalle Valo 7305491d2cSKalle Valo /* EROM CompIdentB */ 7405491d2cSKalle Valo #define CIB_REV_MASK 0xff000000 7505491d2cSKalle Valo #define CIB_REV_SHIFT 24 7605491d2cSKalle Valo 7705491d2cSKalle Valo /* ARM CR4 core specific control flag bits */ 7805491d2cSKalle Valo #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 7905491d2cSKalle Valo 8005491d2cSKalle Valo /* D11 core specific control flag bits */ 8105491d2cSKalle Valo #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004 8205491d2cSKalle Valo #define D11_BCMA_IOCTL_PHYRESET 0x0008 8305491d2cSKalle Valo 8405491d2cSKalle Valo /* chip core base & ramsize */ 8505491d2cSKalle Valo /* bcm4329 */ 8605491d2cSKalle Valo /* SDIO device core, ID 0x829 */ 8705491d2cSKalle Valo #define BCM4329_CORE_BUS_BASE 0x18011000 8805491d2cSKalle Valo /* internal memory core, ID 0x80e */ 8905491d2cSKalle Valo #define BCM4329_CORE_SOCRAM_BASE 0x18003000 9005491d2cSKalle Valo /* ARM Cortex M3 core, ID 0x82a */ 9105491d2cSKalle Valo #define BCM4329_CORE_ARM_BASE 0x18002000 9205491d2cSKalle Valo 9305491d2cSKalle Valo /* Max possibly supported memory size (limited by IO mapped memory) */ 9405491d2cSKalle Valo #define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024) 9505491d2cSKalle Valo 9605491d2cSKalle Valo #define CORE_SB(base, field) \ 9705491d2cSKalle Valo (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) 9805491d2cSKalle Valo #define SBCOREREV(sbidh) \ 9905491d2cSKalle Valo ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \ 10005491d2cSKalle Valo ((sbidh) & SSB_IDHIGH_RCLO)) 10105491d2cSKalle Valo 10205491d2cSKalle Valo struct sbconfig { 10305491d2cSKalle Valo u32 PAD[2]; 10405491d2cSKalle Valo u32 sbipsflag; /* initiator port ocp slave flag */ 10505491d2cSKalle Valo u32 PAD[3]; 10605491d2cSKalle Valo u32 sbtpsflag; /* target port ocp slave flag */ 10705491d2cSKalle Valo u32 PAD[11]; 10805491d2cSKalle Valo u32 sbtmerrloga; /* (sonics >= 2.3) */ 10905491d2cSKalle Valo u32 PAD; 11005491d2cSKalle Valo u32 sbtmerrlog; /* (sonics >= 2.3) */ 11105491d2cSKalle Valo u32 PAD[3]; 11205491d2cSKalle Valo u32 sbadmatch3; /* address match3 */ 11305491d2cSKalle Valo u32 PAD; 11405491d2cSKalle Valo u32 sbadmatch2; /* address match2 */ 11505491d2cSKalle Valo u32 PAD; 11605491d2cSKalle Valo u32 sbadmatch1; /* address match1 */ 11705491d2cSKalle Valo u32 PAD[7]; 11805491d2cSKalle Valo u32 sbimstate; /* initiator agent state */ 11905491d2cSKalle Valo u32 sbintvec; /* interrupt mask */ 12005491d2cSKalle Valo u32 sbtmstatelow; /* target state */ 12105491d2cSKalle Valo u32 sbtmstatehigh; /* target state */ 12205491d2cSKalle Valo u32 sbbwa0; /* bandwidth allocation table0 */ 12305491d2cSKalle Valo u32 PAD; 12405491d2cSKalle Valo u32 sbimconfiglow; /* initiator configuration */ 12505491d2cSKalle Valo u32 sbimconfighigh; /* initiator configuration */ 12605491d2cSKalle Valo u32 sbadmatch0; /* address match0 */ 12705491d2cSKalle Valo u32 PAD; 12805491d2cSKalle Valo u32 sbtmconfiglow; /* target configuration */ 12905491d2cSKalle Valo u32 sbtmconfighigh; /* target configuration */ 13005491d2cSKalle Valo u32 sbbconfig; /* broadcast configuration */ 13105491d2cSKalle Valo u32 PAD; 13205491d2cSKalle Valo u32 sbbstate; /* broadcast state */ 13305491d2cSKalle Valo u32 PAD[3]; 13405491d2cSKalle Valo u32 sbactcnfg; /* activate configuration */ 13505491d2cSKalle Valo u32 PAD[3]; 13605491d2cSKalle Valo u32 sbflagst; /* current sbflags */ 13705491d2cSKalle Valo u32 PAD[3]; 13805491d2cSKalle Valo u32 sbidlow; /* identification */ 13905491d2cSKalle Valo u32 sbidhigh; /* identification */ 14005491d2cSKalle Valo }; 14105491d2cSKalle Valo 1422c4fa29eSArend van Spriel #define INVALID_RAMBASE ((u32)(~0)) 1432c4fa29eSArend van Spriel 14405491d2cSKalle Valo /* bankidx and bankinfo reg defines corerev >= 8 */ 14505491d2cSKalle Valo #define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 14605491d2cSKalle Valo #define SOCRAM_BANKINFO_SZMASK 0x0000007f 14705491d2cSKalle Valo #define SOCRAM_BANKIDX_ROM_MASK 0x00000100 14805491d2cSKalle Valo 14905491d2cSKalle Valo #define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 15005491d2cSKalle Valo /* socram bankinfo memtype */ 15105491d2cSKalle Valo #define SOCRAM_MEMTYPE_RAM 0 15205491d2cSKalle Valo #define SOCRAM_MEMTYPE_R0M 1 15305491d2cSKalle Valo #define SOCRAM_MEMTYPE_DEVRAM 2 15405491d2cSKalle Valo 15505491d2cSKalle Valo #define SOCRAM_BANKINFO_SZBASE 8192 15605491d2cSKalle Valo #define SRCI_LSS_MASK 0x00f00000 15705491d2cSKalle Valo #define SRCI_LSS_SHIFT 20 15805491d2cSKalle Valo #define SRCI_SRNB_MASK 0xf0 15935cb51b2SChi-Hsien Lin #define SRCI_SRNB_MASK_EXT 0x100 16005491d2cSKalle Valo #define SRCI_SRNB_SHIFT 4 16105491d2cSKalle Valo #define SRCI_SRBSZ_MASK 0xf 16205491d2cSKalle Valo #define SRCI_SRBSZ_SHIFT 0 16305491d2cSKalle Valo #define SR_BSZ_BASE 14 16405491d2cSKalle Valo 16505491d2cSKalle Valo struct sbsocramregs { 16605491d2cSKalle Valo u32 coreinfo; 16705491d2cSKalle Valo u32 bwalloc; 16805491d2cSKalle Valo u32 extracoreinfo; 16905491d2cSKalle Valo u32 biststat; 17005491d2cSKalle Valo u32 bankidx; 17105491d2cSKalle Valo u32 standbyctrl; 17205491d2cSKalle Valo 17305491d2cSKalle Valo u32 errlogstatus; /* rev 6 */ 17405491d2cSKalle Valo u32 errlogaddr; /* rev 6 */ 17505491d2cSKalle Valo /* used for patching rev 3 & 5 */ 17605491d2cSKalle Valo u32 cambankidx; 17705491d2cSKalle Valo u32 cambankstandbyctrl; 17805491d2cSKalle Valo u32 cambankpatchctrl; 17905491d2cSKalle Valo u32 cambankpatchtblbaseaddr; 18005491d2cSKalle Valo u32 cambankcmdreg; 18105491d2cSKalle Valo u32 cambankdatareg; 18205491d2cSKalle Valo u32 cambankmaskreg; 18305491d2cSKalle Valo u32 PAD[1]; 18405491d2cSKalle Valo u32 bankinfo; /* corev 8 */ 18505491d2cSKalle Valo u32 bankpda; 18605491d2cSKalle Valo u32 PAD[14]; 18705491d2cSKalle Valo u32 extmemconfig; 18805491d2cSKalle Valo u32 extmemparitycsr; 18905491d2cSKalle Valo u32 extmemparityerrdata; 19005491d2cSKalle Valo u32 extmemparityerrcnt; 19105491d2cSKalle Valo u32 extmemwrctrlandsize; 19205491d2cSKalle Valo u32 PAD[84]; 19305491d2cSKalle Valo u32 workaround; 19405491d2cSKalle Valo u32 pwrctl; /* corerev >= 2 */ 19505491d2cSKalle Valo u32 PAD[133]; 19605491d2cSKalle Valo u32 sr_control; /* corerev >= 15 */ 19705491d2cSKalle Valo u32 sr_status; /* corerev >= 15 */ 19805491d2cSKalle Valo u32 sr_address; /* corerev >= 15 */ 19905491d2cSKalle Valo u32 sr_data; /* corerev >= 15 */ 20005491d2cSKalle Valo }; 20105491d2cSKalle Valo 20205491d2cSKalle Valo #define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) 20305491d2cSKalle Valo #define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f) 20405491d2cSKalle Valo 20505491d2cSKalle Valo #define ARMCR4_CAP (0x04) 20605491d2cSKalle Valo #define ARMCR4_BANKIDX (0x40) 20705491d2cSKalle Valo #define ARMCR4_BANKINFO (0x44) 20805491d2cSKalle Valo #define ARMCR4_BANKPDA (0x4C) 20905491d2cSKalle Valo 21005491d2cSKalle Valo #define ARMCR4_TCBBNB_MASK 0xf0 21105491d2cSKalle Valo #define ARMCR4_TCBBNB_SHIFT 4 21205491d2cSKalle Valo #define ARMCR4_TCBANB_MASK 0xf 21305491d2cSKalle Valo #define ARMCR4_TCBANB_SHIFT 0 21405491d2cSKalle Valo 21505491d2cSKalle Valo #define ARMCR4_BSZ_MASK 0x3f 21605491d2cSKalle Valo #define ARMCR4_BSZ_MULT 8192 21705491d2cSKalle Valo 21805491d2cSKalle Valo struct brcmf_core_priv { 21905491d2cSKalle Valo struct brcmf_core pub; 22005491d2cSKalle Valo u32 wrapbase; 22105491d2cSKalle Valo struct list_head list; 22205491d2cSKalle Valo struct brcmf_chip_priv *chip; 22305491d2cSKalle Valo }; 22405491d2cSKalle Valo 22505491d2cSKalle Valo struct brcmf_chip_priv { 22605491d2cSKalle Valo struct brcmf_chip pub; 22705491d2cSKalle Valo const struct brcmf_buscore_ops *ops; 22805491d2cSKalle Valo void *ctx; 22905491d2cSKalle Valo /* assured first core is chipcommon, second core is buscore */ 23005491d2cSKalle Valo struct list_head cores; 23105491d2cSKalle Valo u16 num_cores; 23205491d2cSKalle Valo 23305491d2cSKalle Valo bool (*iscoreup)(struct brcmf_core_priv *core); 23405491d2cSKalle Valo void (*coredisable)(struct brcmf_core_priv *core, u32 prereset, 23505491d2cSKalle Valo u32 reset); 23605491d2cSKalle Valo void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset, 23705491d2cSKalle Valo u32 postreset); 23805491d2cSKalle Valo }; 23905491d2cSKalle Valo 24005491d2cSKalle Valo static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci, 24105491d2cSKalle Valo struct brcmf_core *core) 24205491d2cSKalle Valo { 24305491d2cSKalle Valo u32 regdata; 24405491d2cSKalle Valo 24505491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh)); 24605491d2cSKalle Valo core->rev = SBCOREREV(regdata); 24705491d2cSKalle Valo } 24805491d2cSKalle Valo 24905491d2cSKalle Valo static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core) 25005491d2cSKalle Valo { 25105491d2cSKalle Valo struct brcmf_chip_priv *ci; 25205491d2cSKalle Valo u32 regdata; 25305491d2cSKalle Valo u32 address; 25405491d2cSKalle Valo 25505491d2cSKalle Valo ci = core->chip; 25605491d2cSKalle Valo address = CORE_SB(core->pub.base, sbtmstatelow); 25705491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, address); 25805491d2cSKalle Valo regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | 25905491d2cSKalle Valo SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); 26005491d2cSKalle Valo return SSB_TMSLOW_CLOCK == regdata; 26105491d2cSKalle Valo } 26205491d2cSKalle Valo 26305491d2cSKalle Valo static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core) 26405491d2cSKalle Valo { 26505491d2cSKalle Valo struct brcmf_chip_priv *ci; 26605491d2cSKalle Valo u32 regdata; 26705491d2cSKalle Valo bool ret; 26805491d2cSKalle Valo 26905491d2cSKalle Valo ci = core->chip; 27005491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 27105491d2cSKalle Valo ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; 27205491d2cSKalle Valo 27305491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); 27405491d2cSKalle Valo ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); 27505491d2cSKalle Valo 27605491d2cSKalle Valo return ret; 27705491d2cSKalle Valo } 27805491d2cSKalle Valo 27905491d2cSKalle Valo static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core, 28005491d2cSKalle Valo u32 prereset, u32 reset) 28105491d2cSKalle Valo { 28205491d2cSKalle Valo struct brcmf_chip_priv *ci; 28305491d2cSKalle Valo u32 val, base; 28405491d2cSKalle Valo 28505491d2cSKalle Valo ci = core->chip; 28605491d2cSKalle Valo base = core->pub.base; 28705491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 28805491d2cSKalle Valo if (val & SSB_TMSLOW_RESET) 28905491d2cSKalle Valo return; 29005491d2cSKalle Valo 29105491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 29205491d2cSKalle Valo if ((val & SSB_TMSLOW_CLOCK) != 0) { 29305491d2cSKalle Valo /* 29405491d2cSKalle Valo * set target reject and spin until busy is clear 29505491d2cSKalle Valo * (preserve core-specific bits) 29605491d2cSKalle Valo */ 29705491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 29805491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 29905491d2cSKalle Valo val | SSB_TMSLOW_REJECT); 30005491d2cSKalle Valo 30105491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 30205491d2cSKalle Valo udelay(1); 30305491d2cSKalle Valo SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)) 30405491d2cSKalle Valo & SSB_TMSHIGH_BUSY), 100000); 30505491d2cSKalle Valo 30605491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); 30705491d2cSKalle Valo if (val & SSB_TMSHIGH_BUSY) 30805491d2cSKalle Valo brcmf_err("core state still busy\n"); 30905491d2cSKalle Valo 31005491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); 31105491d2cSKalle Valo if (val & SSB_IDLOW_INITIATOR) { 31205491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 31305491d2cSKalle Valo CORE_SB(base, sbimstate)); 31405491d2cSKalle Valo val |= SSB_IMSTATE_REJECT; 31505491d2cSKalle Valo ci->ops->write32(ci->ctx, 31605491d2cSKalle Valo CORE_SB(base, sbimstate), val); 31705491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 31805491d2cSKalle Valo CORE_SB(base, sbimstate)); 31905491d2cSKalle Valo udelay(1); 32005491d2cSKalle Valo SPINWAIT((ci->ops->read32(ci->ctx, 32105491d2cSKalle Valo CORE_SB(base, sbimstate)) & 32205491d2cSKalle Valo SSB_IMSTATE_BUSY), 100000); 32305491d2cSKalle Valo } 32405491d2cSKalle Valo 32505491d2cSKalle Valo /* set reset and reject while enabling the clocks */ 32605491d2cSKalle Valo val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | 32705491d2cSKalle Valo SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; 32805491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val); 32905491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 33005491d2cSKalle Valo udelay(10); 33105491d2cSKalle Valo 33205491d2cSKalle Valo /* clear the initiator reject bit */ 33305491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); 33405491d2cSKalle Valo if (val & SSB_IDLOW_INITIATOR) { 33505491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 33605491d2cSKalle Valo CORE_SB(base, sbimstate)); 33705491d2cSKalle Valo val &= ~SSB_IMSTATE_REJECT; 33805491d2cSKalle Valo ci->ops->write32(ci->ctx, 33905491d2cSKalle Valo CORE_SB(base, sbimstate), val); 34005491d2cSKalle Valo } 34105491d2cSKalle Valo } 34205491d2cSKalle Valo 34305491d2cSKalle Valo /* leave reset and reject asserted */ 34405491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 34505491d2cSKalle Valo (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); 34605491d2cSKalle Valo udelay(1); 34705491d2cSKalle Valo } 34805491d2cSKalle Valo 34905491d2cSKalle Valo static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, 35005491d2cSKalle Valo u32 prereset, u32 reset) 35105491d2cSKalle Valo { 35205491d2cSKalle Valo struct brcmf_chip_priv *ci; 35305491d2cSKalle Valo u32 regdata; 35405491d2cSKalle Valo 35505491d2cSKalle Valo ci = core->chip; 35605491d2cSKalle Valo 35705491d2cSKalle Valo /* if core is already in reset, skip reset */ 35805491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); 35905491d2cSKalle Valo if ((regdata & BCMA_RESET_CTL_RESET) != 0) 36005491d2cSKalle Valo goto in_reset_configure; 36105491d2cSKalle Valo 36205491d2cSKalle Valo /* configure reset */ 36305491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 36405491d2cSKalle Valo prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); 36505491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 36605491d2cSKalle Valo 36705491d2cSKalle Valo /* put in reset */ 36805491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 36905491d2cSKalle Valo BCMA_RESET_CTL_RESET); 37005491d2cSKalle Valo usleep_range(10, 20); 37105491d2cSKalle Valo 37205491d2cSKalle Valo /* wait till reset is 1 */ 37305491d2cSKalle Valo SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) != 37405491d2cSKalle Valo BCMA_RESET_CTL_RESET, 300); 37505491d2cSKalle Valo 37605491d2cSKalle Valo in_reset_configure: 37705491d2cSKalle Valo /* in-reset configure */ 37805491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 37905491d2cSKalle Valo reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); 38005491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 38105491d2cSKalle Valo } 38205491d2cSKalle Valo 38305491d2cSKalle Valo static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset, 38405491d2cSKalle Valo u32 reset, u32 postreset) 38505491d2cSKalle Valo { 38605491d2cSKalle Valo struct brcmf_chip_priv *ci; 38705491d2cSKalle Valo u32 regdata; 38805491d2cSKalle Valo u32 base; 38905491d2cSKalle Valo 39005491d2cSKalle Valo ci = core->chip; 39105491d2cSKalle Valo base = core->pub.base; 39205491d2cSKalle Valo /* 39305491d2cSKalle Valo * Must do the disable sequence first to work for 39405491d2cSKalle Valo * arbitrary current core state. 39505491d2cSKalle Valo */ 39605491d2cSKalle Valo brcmf_chip_sb_coredisable(core, 0, 0); 39705491d2cSKalle Valo 39805491d2cSKalle Valo /* 39905491d2cSKalle Valo * Now do the initialization sequence. 40005491d2cSKalle Valo * set reset while enabling the clock and 40105491d2cSKalle Valo * forcing them on throughout the core 40205491d2cSKalle Valo */ 40305491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 40405491d2cSKalle Valo SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | 40505491d2cSKalle Valo SSB_TMSLOW_RESET); 40605491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 40705491d2cSKalle Valo udelay(1); 40805491d2cSKalle Valo 40905491d2cSKalle Valo /* clear any serror */ 41005491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); 41105491d2cSKalle Valo if (regdata & SSB_TMSHIGH_SERR) 41205491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0); 41305491d2cSKalle Valo 41405491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate)); 41505491d2cSKalle Valo if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) { 41605491d2cSKalle Valo regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO); 41705491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata); 41805491d2cSKalle Valo } 41905491d2cSKalle Valo 42005491d2cSKalle Valo /* clear reset and allow it to propagate throughout the core */ 42105491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 42205491d2cSKalle Valo SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK); 42305491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 42405491d2cSKalle Valo udelay(1); 42505491d2cSKalle Valo 42605491d2cSKalle Valo /* leave clock enabled */ 42705491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 42805491d2cSKalle Valo SSB_TMSLOW_CLOCK); 42905491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 43005491d2cSKalle Valo udelay(1); 43105491d2cSKalle Valo } 43205491d2cSKalle Valo 43305491d2cSKalle Valo static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset, 43405491d2cSKalle Valo u32 reset, u32 postreset) 43505491d2cSKalle Valo { 43605491d2cSKalle Valo struct brcmf_chip_priv *ci; 43705491d2cSKalle Valo int count; 4381b8d2e0aSWright Feng struct brcmf_core *d11core2 = NULL; 4391b8d2e0aSWright Feng struct brcmf_core_priv *d11priv2 = NULL; 44005491d2cSKalle Valo 44105491d2cSKalle Valo ci = core->chip; 44205491d2cSKalle Valo 4431b8d2e0aSWright Feng /* special handle two D11 cores reset */ 4441b8d2e0aSWright Feng if (core->pub.id == BCMA_CORE_80211) { 4451b8d2e0aSWright Feng d11core2 = brcmf_chip_get_d11core(&ci->pub, 1); 4461b8d2e0aSWright Feng if (d11core2) { 4471b8d2e0aSWright Feng brcmf_dbg(INFO, "found two d11 cores, reset both\n"); 4481b8d2e0aSWright Feng d11priv2 = container_of(d11core2, 4491b8d2e0aSWright Feng struct brcmf_core_priv, pub); 4501b8d2e0aSWright Feng } 4511b8d2e0aSWright Feng } 4521b8d2e0aSWright Feng 45305491d2cSKalle Valo /* must disable first to work for arbitrary current core state */ 45405491d2cSKalle Valo brcmf_chip_ai_coredisable(core, prereset, reset); 4551b8d2e0aSWright Feng if (d11priv2) 4561b8d2e0aSWright Feng brcmf_chip_ai_coredisable(d11priv2, prereset, reset); 45705491d2cSKalle Valo 45805491d2cSKalle Valo count = 0; 45905491d2cSKalle Valo while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) & 46005491d2cSKalle Valo BCMA_RESET_CTL_RESET) { 46105491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0); 46205491d2cSKalle Valo count++; 46305491d2cSKalle Valo if (count > 50) 46405491d2cSKalle Valo break; 46505491d2cSKalle Valo usleep_range(40, 60); 46605491d2cSKalle Valo } 46705491d2cSKalle Valo 4681b8d2e0aSWright Feng if (d11priv2) { 4691b8d2e0aSWright Feng count = 0; 4701b8d2e0aSWright Feng while (ci->ops->read32(ci->ctx, 4711b8d2e0aSWright Feng d11priv2->wrapbase + BCMA_RESET_CTL) & 4721b8d2e0aSWright Feng BCMA_RESET_CTL_RESET) { 4731b8d2e0aSWright Feng ci->ops->write32(ci->ctx, 4741b8d2e0aSWright Feng d11priv2->wrapbase + BCMA_RESET_CTL, 4751b8d2e0aSWright Feng 0); 4761b8d2e0aSWright Feng count++; 4771b8d2e0aSWright Feng if (count > 50) 4781b8d2e0aSWright Feng break; 4791b8d2e0aSWright Feng usleep_range(40, 60); 4801b8d2e0aSWright Feng } 4811b8d2e0aSWright Feng } 4821b8d2e0aSWright Feng 48305491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 48405491d2cSKalle Valo postreset | BCMA_IOCTL_CLK); 48505491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 4861b8d2e0aSWright Feng 4871b8d2e0aSWright Feng if (d11priv2) { 4881b8d2e0aSWright Feng ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL, 4891b8d2e0aSWright Feng postreset | BCMA_IOCTL_CLK); 4901b8d2e0aSWright Feng ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL); 4911b8d2e0aSWright Feng } 49205491d2cSKalle Valo } 49305491d2cSKalle Valo 494756a2b39SArend Van Spriel char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) 49505491d2cSKalle Valo { 49605491d2cSKalle Valo const char *fmt; 49705491d2cSKalle Valo 498756a2b39SArend Van Spriel fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u"; 499756a2b39SArend Van Spriel snprintf(buf, len, fmt, id, rev); 50005491d2cSKalle Valo return buf; 50105491d2cSKalle Valo } 50205491d2cSKalle Valo 50305491d2cSKalle Valo static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci, 50405491d2cSKalle Valo u16 coreid, u32 base, 50505491d2cSKalle Valo u32 wrapbase) 50605491d2cSKalle Valo { 50705491d2cSKalle Valo struct brcmf_core_priv *core; 50805491d2cSKalle Valo 50905491d2cSKalle Valo core = kzalloc(sizeof(*core), GFP_KERNEL); 51005491d2cSKalle Valo if (!core) 51105491d2cSKalle Valo return ERR_PTR(-ENOMEM); 51205491d2cSKalle Valo 51305491d2cSKalle Valo core->pub.id = coreid; 51405491d2cSKalle Valo core->pub.base = base; 51505491d2cSKalle Valo core->chip = ci; 51605491d2cSKalle Valo core->wrapbase = wrapbase; 51705491d2cSKalle Valo 51805491d2cSKalle Valo list_add_tail(&core->list, &ci->cores); 51905491d2cSKalle Valo return &core->pub; 52005491d2cSKalle Valo } 52105491d2cSKalle Valo 52205491d2cSKalle Valo /* safety check for chipinfo */ 52305491d2cSKalle Valo static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) 52405491d2cSKalle Valo { 52505491d2cSKalle Valo struct brcmf_core_priv *core; 52605491d2cSKalle Valo bool need_socram = false; 52705491d2cSKalle Valo bool has_socram = false; 52805491d2cSKalle Valo bool cpu_found = false; 52905491d2cSKalle Valo int idx = 1; 53005491d2cSKalle Valo 53105491d2cSKalle Valo list_for_each_entry(core, &ci->cores, list) { 5328e73facbSArend van Spriel brcmf_dbg(INFO, " [%-2d] core 0x%x:%-3d base 0x%08x wrap 0x%08x\n", 53305491d2cSKalle Valo idx++, core->pub.id, core->pub.rev, core->pub.base, 53405491d2cSKalle Valo core->wrapbase); 53505491d2cSKalle Valo 53605491d2cSKalle Valo switch (core->pub.id) { 53705491d2cSKalle Valo case BCMA_CORE_ARM_CM3: 53805491d2cSKalle Valo cpu_found = true; 53905491d2cSKalle Valo need_socram = true; 54005491d2cSKalle Valo break; 54105491d2cSKalle Valo case BCMA_CORE_INTERNAL_MEM: 54205491d2cSKalle Valo has_socram = true; 54305491d2cSKalle Valo break; 54405491d2cSKalle Valo case BCMA_CORE_ARM_CR4: 54505491d2cSKalle Valo cpu_found = true; 54605491d2cSKalle Valo break; 54705491d2cSKalle Valo case BCMA_CORE_ARM_CA7: 54805491d2cSKalle Valo cpu_found = true; 54905491d2cSKalle Valo break; 55005491d2cSKalle Valo default: 55105491d2cSKalle Valo break; 55205491d2cSKalle Valo } 55305491d2cSKalle Valo } 55405491d2cSKalle Valo 55505491d2cSKalle Valo if (!cpu_found) { 55605491d2cSKalle Valo brcmf_err("CPU core not detected\n"); 55705491d2cSKalle Valo return -ENXIO; 55805491d2cSKalle Valo } 55905491d2cSKalle Valo /* check RAM core presence for ARM CM3 core */ 56005491d2cSKalle Valo if (need_socram && !has_socram) { 56105491d2cSKalle Valo brcmf_err("RAM core not provided with ARM CM3 core\n"); 56205491d2cSKalle Valo return -ENODEV; 56305491d2cSKalle Valo } 56405491d2cSKalle Valo return 0; 56505491d2cSKalle Valo } 56605491d2cSKalle Valo 56705491d2cSKalle Valo static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg) 56805491d2cSKalle Valo { 56905491d2cSKalle Valo return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg); 57005491d2cSKalle Valo } 57105491d2cSKalle Valo 57205491d2cSKalle Valo static void brcmf_chip_core_write32(struct brcmf_core_priv *core, 57305491d2cSKalle Valo u16 reg, u32 val) 57405491d2cSKalle Valo { 57505491d2cSKalle Valo core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val); 57605491d2cSKalle Valo } 57705491d2cSKalle Valo 57805491d2cSKalle Valo static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx, 57905491d2cSKalle Valo u32 *banksize) 58005491d2cSKalle Valo { 58105491d2cSKalle Valo u32 bankinfo; 58205491d2cSKalle Valo u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 58305491d2cSKalle Valo 58405491d2cSKalle Valo bankidx |= idx; 58505491d2cSKalle Valo brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx); 58605491d2cSKalle Valo bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo)); 58705491d2cSKalle Valo *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1; 58805491d2cSKalle Valo *banksize *= SOCRAM_BANKINFO_SZBASE; 58905491d2cSKalle Valo return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK); 59005491d2cSKalle Valo } 59105491d2cSKalle Valo 59205491d2cSKalle Valo static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, 59305491d2cSKalle Valo u32 *srsize) 59405491d2cSKalle Valo { 59505491d2cSKalle Valo u32 coreinfo; 59605491d2cSKalle Valo uint nb, banksize, lss; 59705491d2cSKalle Valo bool retent; 59805491d2cSKalle Valo int i; 59905491d2cSKalle Valo 60005491d2cSKalle Valo *ramsize = 0; 60105491d2cSKalle Valo *srsize = 0; 60205491d2cSKalle Valo 60305491d2cSKalle Valo if (WARN_ON(sr->pub.rev < 4)) 60405491d2cSKalle Valo return; 60505491d2cSKalle Valo 60605491d2cSKalle Valo if (!brcmf_chip_iscoreup(&sr->pub)) 60705491d2cSKalle Valo brcmf_chip_resetcore(&sr->pub, 0, 0, 0); 60805491d2cSKalle Valo 60905491d2cSKalle Valo /* Get info for determining size */ 61005491d2cSKalle Valo coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo)); 61105491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 61205491d2cSKalle Valo 61305491d2cSKalle Valo if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) { 61405491d2cSKalle Valo banksize = (coreinfo & SRCI_SRBSZ_MASK); 61505491d2cSKalle Valo lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 61605491d2cSKalle Valo if (lss != 0) 61705491d2cSKalle Valo nb--; 61805491d2cSKalle Valo *ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); 61905491d2cSKalle Valo if (lss != 0) 62005491d2cSKalle Valo *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 62105491d2cSKalle Valo } else { 62235cb51b2SChi-Hsien Lin /* length of SRAM Banks increased for corerev greater than 23 */ 62335cb51b2SChi-Hsien Lin if (sr->pub.rev >= 23) { 62435cb51b2SChi-Hsien Lin nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT)) 62535cb51b2SChi-Hsien Lin >> SRCI_SRNB_SHIFT; 62635cb51b2SChi-Hsien Lin } else { 62705491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 62835cb51b2SChi-Hsien Lin } 62905491d2cSKalle Valo for (i = 0; i < nb; i++) { 63005491d2cSKalle Valo retent = brcmf_chip_socram_banksize(sr, i, &banksize); 63105491d2cSKalle Valo *ramsize += banksize; 63205491d2cSKalle Valo if (retent) 63305491d2cSKalle Valo *srsize += banksize; 63405491d2cSKalle Valo } 63505491d2cSKalle Valo } 63605491d2cSKalle Valo 63705491d2cSKalle Valo /* hardcoded save&restore memory sizes */ 63805491d2cSKalle Valo switch (sr->chip->pub.chip) { 63905491d2cSKalle Valo case BRCM_CC_4334_CHIP_ID: 64005491d2cSKalle Valo if (sr->chip->pub.chiprev < 2) 64105491d2cSKalle Valo *srsize = (32 * 1024); 64205491d2cSKalle Valo break; 64305491d2cSKalle Valo case BRCM_CC_43430_CHIP_ID: 64405491d2cSKalle Valo /* assume sr for now as we can not check 64505491d2cSKalle Valo * firmware sr capability at this point. 64605491d2cSKalle Valo */ 64705491d2cSKalle Valo *srsize = (64 * 1024); 64805491d2cSKalle Valo break; 64905491d2cSKalle Valo default: 65005491d2cSKalle Valo break; 65105491d2cSKalle Valo } 65205491d2cSKalle Valo } 65305491d2cSKalle Valo 65405491d2cSKalle Valo /** Return the SYS MEM size */ 65505491d2cSKalle Valo static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) 65605491d2cSKalle Valo { 65705491d2cSKalle Valo u32 memsize = 0; 65805491d2cSKalle Valo u32 coreinfo; 65905491d2cSKalle Valo u32 idx; 66005491d2cSKalle Valo u32 nb; 66105491d2cSKalle Valo u32 banksize; 66205491d2cSKalle Valo 66305491d2cSKalle Valo if (!brcmf_chip_iscoreup(&sysmem->pub)) 66405491d2cSKalle Valo brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0); 66505491d2cSKalle Valo 66605491d2cSKalle Valo coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo)); 66705491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 66805491d2cSKalle Valo 66905491d2cSKalle Valo for (idx = 0; idx < nb; idx++) { 67005491d2cSKalle Valo brcmf_chip_socram_banksize(sysmem, idx, &banksize); 67105491d2cSKalle Valo memsize += banksize; 67205491d2cSKalle Valo } 67305491d2cSKalle Valo 67405491d2cSKalle Valo return memsize; 67505491d2cSKalle Valo } 67605491d2cSKalle Valo 67705491d2cSKalle Valo /** Return the TCM-RAM size of the ARMCR4 core. */ 67805491d2cSKalle Valo static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) 67905491d2cSKalle Valo { 68005491d2cSKalle Valo u32 corecap; 68105491d2cSKalle Valo u32 memsize = 0; 68205491d2cSKalle Valo u32 nab; 68305491d2cSKalle Valo u32 nbb; 68405491d2cSKalle Valo u32 totb; 68505491d2cSKalle Valo u32 bxinfo; 68605491d2cSKalle Valo u32 idx; 68705491d2cSKalle Valo 68805491d2cSKalle Valo corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); 68905491d2cSKalle Valo 69005491d2cSKalle Valo nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; 69105491d2cSKalle Valo nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; 69205491d2cSKalle Valo totb = nab + nbb; 69305491d2cSKalle Valo 69405491d2cSKalle Valo for (idx = 0; idx < totb; idx++) { 69505491d2cSKalle Valo brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); 69605491d2cSKalle Valo bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); 69705491d2cSKalle Valo memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; 69805491d2cSKalle Valo } 69905491d2cSKalle Valo 70005491d2cSKalle Valo return memsize; 70105491d2cSKalle Valo } 70205491d2cSKalle Valo 70305491d2cSKalle Valo static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) 70405491d2cSKalle Valo { 70505491d2cSKalle Valo switch (ci->pub.chip) { 70605491d2cSKalle Valo case BRCM_CC_4345_CHIP_ID: 70705491d2cSKalle Valo return 0x198000; 70805491d2cSKalle Valo case BRCM_CC_4335_CHIP_ID: 70905491d2cSKalle Valo case BRCM_CC_4339_CHIP_ID: 71005491d2cSKalle Valo case BRCM_CC_4350_CHIP_ID: 71105491d2cSKalle Valo case BRCM_CC_4354_CHIP_ID: 71205491d2cSKalle Valo case BRCM_CC_4356_CHIP_ID: 71305491d2cSKalle Valo case BRCM_CC_43567_CHIP_ID: 71405491d2cSKalle Valo case BRCM_CC_43569_CHIP_ID: 71505491d2cSKalle Valo case BRCM_CC_43570_CHIP_ID: 71605491d2cSKalle Valo case BRCM_CC_4358_CHIP_ID: 71705491d2cSKalle Valo case BRCM_CC_43602_CHIP_ID: 71805491d2cSKalle Valo case BRCM_CC_4371_CHIP_ID: 71905491d2cSKalle Valo return 0x180000; 72043819926SHante Meuleman case BRCM_CC_43465_CHIP_ID: 72143819926SHante Meuleman case BRCM_CC_43525_CHIP_ID: 72205491d2cSKalle Valo case BRCM_CC_4365_CHIP_ID: 72305491d2cSKalle Valo case BRCM_CC_4366_CHIP_ID: 7241f589e25SDan Haab case BRCM_CC_43664_CHIP_ID: 725f4add103SRafał Miłecki case BRCM_CC_43666_CHIP_ID: 72605491d2cSKalle Valo return 0x200000; 7276647274eSSoeren Moch case BRCM_CC_4359_CHIP_ID: 7286647274eSSoeren Moch return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; 72924f0bd13Sbrian m. carlson case BRCM_CC_4364_CHIP_ID: 7300ec9eb90SChi-Hsien Lin case CY_CC_4373_CHIP_ID: 7310ec9eb90SChi-Hsien Lin return 0x160000; 732*d2587c57SAngus Ainslie case CY_CC_43752_CHIP_ID: 733*d2587c57SAngus Ainslie return 0x170000; 73405491d2cSKalle Valo default: 73505491d2cSKalle Valo brcmf_err("unknown chip: %s\n", ci->pub.name); 73605491d2cSKalle Valo break; 73705491d2cSKalle Valo } 7382c4fa29eSArend van Spriel return INVALID_RAMBASE; 73905491d2cSKalle Valo } 74005491d2cSKalle Valo 74182f93cf4SRafał Miłecki int brcmf_chip_get_raminfo(struct brcmf_chip *pub) 74205491d2cSKalle Valo { 74382f93cf4SRafał Miłecki struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv, 74482f93cf4SRafał Miłecki pub); 74505491d2cSKalle Valo struct brcmf_core_priv *mem_core; 74605491d2cSKalle Valo struct brcmf_core *mem; 74705491d2cSKalle Valo 74805491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); 74905491d2cSKalle Valo if (mem) { 75005491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, pub); 75105491d2cSKalle Valo ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); 75205491d2cSKalle Valo ci->pub.rambase = brcmf_chip_tcm_rambase(ci); 7532c4fa29eSArend van Spriel if (ci->pub.rambase == INVALID_RAMBASE) { 75405491d2cSKalle Valo brcmf_err("RAM base not provided with ARM CR4 core\n"); 75505491d2cSKalle Valo return -EINVAL; 75605491d2cSKalle Valo } 75705491d2cSKalle Valo } else { 75805491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM); 75905491d2cSKalle Valo if (mem) { 76005491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, 76105491d2cSKalle Valo pub); 76205491d2cSKalle Valo ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core); 76305491d2cSKalle Valo ci->pub.rambase = brcmf_chip_tcm_rambase(ci); 7642c4fa29eSArend van Spriel if (ci->pub.rambase == INVALID_RAMBASE) { 76505491d2cSKalle Valo brcmf_err("RAM base not provided with ARM CA7 core\n"); 76605491d2cSKalle Valo return -EINVAL; 76705491d2cSKalle Valo } 76805491d2cSKalle Valo } else { 76905491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, 77005491d2cSKalle Valo BCMA_CORE_INTERNAL_MEM); 77105491d2cSKalle Valo if (!mem) { 77205491d2cSKalle Valo brcmf_err("No memory cores found\n"); 77305491d2cSKalle Valo return -ENOMEM; 77405491d2cSKalle Valo } 77505491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, 77605491d2cSKalle Valo pub); 77705491d2cSKalle Valo brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, 77805491d2cSKalle Valo &ci->pub.srsize); 77905491d2cSKalle Valo } 78005491d2cSKalle Valo } 78105491d2cSKalle Valo brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", 78205491d2cSKalle Valo ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, 78305491d2cSKalle Valo ci->pub.srsize, ci->pub.srsize); 78405491d2cSKalle Valo 78505491d2cSKalle Valo if (!ci->pub.ramsize) { 78605491d2cSKalle Valo brcmf_err("RAM size is undetermined\n"); 78705491d2cSKalle Valo return -ENOMEM; 78805491d2cSKalle Valo } 78905491d2cSKalle Valo 79005491d2cSKalle Valo if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { 79105491d2cSKalle Valo brcmf_err("RAM size is incorrect\n"); 79205491d2cSKalle Valo return -ENOMEM; 79305491d2cSKalle Valo } 79405491d2cSKalle Valo 79505491d2cSKalle Valo return 0; 79605491d2cSKalle Valo } 79705491d2cSKalle Valo 79805491d2cSKalle Valo static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, 79905491d2cSKalle Valo u8 *type) 80005491d2cSKalle Valo { 80105491d2cSKalle Valo u32 val; 80205491d2cSKalle Valo 80305491d2cSKalle Valo /* read next descriptor */ 80405491d2cSKalle Valo val = ci->ops->read32(ci->ctx, *eromaddr); 80505491d2cSKalle Valo *eromaddr += 4; 80605491d2cSKalle Valo 80705491d2cSKalle Valo if (!type) 80805491d2cSKalle Valo return val; 80905491d2cSKalle Valo 81005491d2cSKalle Valo /* determine descriptor type */ 81105491d2cSKalle Valo *type = (val & DMP_DESC_TYPE_MSK); 81205491d2cSKalle Valo if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS) 81305491d2cSKalle Valo *type = DMP_DESC_ADDRESS; 81405491d2cSKalle Valo 81505491d2cSKalle Valo return val; 81605491d2cSKalle Valo } 81705491d2cSKalle Valo 81805491d2cSKalle Valo static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr, 81905491d2cSKalle Valo u32 *regbase, u32 *wrapbase) 82005491d2cSKalle Valo { 82105491d2cSKalle Valo u8 desc; 822b021a6bcSChi-Hsien Lin u32 val, szdesc; 82305491d2cSKalle Valo u8 stype, sztype, wraptype; 82405491d2cSKalle Valo 82505491d2cSKalle Valo *regbase = 0; 82605491d2cSKalle Valo *wrapbase = 0; 82705491d2cSKalle Valo 82805491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc); 82905491d2cSKalle Valo if (desc == DMP_DESC_MASTER_PORT) { 83005491d2cSKalle Valo wraptype = DMP_SLAVE_TYPE_MWRAP; 83105491d2cSKalle Valo } else if (desc == DMP_DESC_ADDRESS) { 83205491d2cSKalle Valo /* revert erom address */ 83305491d2cSKalle Valo *eromaddr -= 4; 83405491d2cSKalle Valo wraptype = DMP_SLAVE_TYPE_SWRAP; 83505491d2cSKalle Valo } else { 83605491d2cSKalle Valo *eromaddr -= 4; 83705491d2cSKalle Valo return -EILSEQ; 83805491d2cSKalle Valo } 83905491d2cSKalle Valo 84005491d2cSKalle Valo do { 84105491d2cSKalle Valo /* locate address descriptor */ 84205491d2cSKalle Valo do { 84305491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc); 84405491d2cSKalle Valo /* unexpected table end */ 84505491d2cSKalle Valo if (desc == DMP_DESC_EOT) { 84605491d2cSKalle Valo *eromaddr -= 4; 84705491d2cSKalle Valo return -EFAULT; 84805491d2cSKalle Valo } 849a4f4abd0SRafał Miłecki } while (desc != DMP_DESC_ADDRESS && 850a4f4abd0SRafał Miłecki desc != DMP_DESC_COMPONENT); 851a4f4abd0SRafał Miłecki 852a4f4abd0SRafał Miłecki /* stop if we crossed current component border */ 853a4f4abd0SRafał Miłecki if (desc == DMP_DESC_COMPONENT) { 854a4f4abd0SRafał Miłecki *eromaddr -= 4; 855a4f4abd0SRafał Miłecki return 0; 856a4f4abd0SRafał Miłecki } 85705491d2cSKalle Valo 85805491d2cSKalle Valo /* skip upper 32-bit address descriptor */ 85905491d2cSKalle Valo if (val & DMP_DESC_ADDRSIZE_GT32) 86005491d2cSKalle Valo brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 86105491d2cSKalle Valo 86205491d2cSKalle Valo sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S; 86305491d2cSKalle Valo 86405491d2cSKalle Valo /* next size descriptor can be skipped */ 86505491d2cSKalle Valo if (sztype == DMP_SLAVE_SIZE_DESC) { 866b021a6bcSChi-Hsien Lin szdesc = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 86705491d2cSKalle Valo /* skip upper size descriptor if present */ 868b021a6bcSChi-Hsien Lin if (szdesc & DMP_DESC_ADDRSIZE_GT32) 86905491d2cSKalle Valo brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 87005491d2cSKalle Valo } 87105491d2cSKalle Valo 872b021a6bcSChi-Hsien Lin /* look for 4K or 8K register regions */ 873b021a6bcSChi-Hsien Lin if (sztype != DMP_SLAVE_SIZE_4K && 874b021a6bcSChi-Hsien Lin sztype != DMP_SLAVE_SIZE_8K) 87505491d2cSKalle Valo continue; 87605491d2cSKalle Valo 87705491d2cSKalle Valo stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S; 87805491d2cSKalle Valo 87905491d2cSKalle Valo /* only regular slave and wrapper */ 88005491d2cSKalle Valo if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE) 88105491d2cSKalle Valo *regbase = val & DMP_SLAVE_ADDR_BASE; 88205491d2cSKalle Valo if (*wrapbase == 0 && stype == wraptype) 88305491d2cSKalle Valo *wrapbase = val & DMP_SLAVE_ADDR_BASE; 88405491d2cSKalle Valo } while (*regbase == 0 || *wrapbase == 0); 88505491d2cSKalle Valo 88605491d2cSKalle Valo return 0; 88705491d2cSKalle Valo } 88805491d2cSKalle Valo 88905491d2cSKalle Valo static 89005491d2cSKalle Valo int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) 89105491d2cSKalle Valo { 89205491d2cSKalle Valo struct brcmf_core *core; 89305491d2cSKalle Valo u32 eromaddr; 89405491d2cSKalle Valo u8 desc_type = 0; 89505491d2cSKalle Valo u32 val; 89605491d2cSKalle Valo u16 id; 8977af496b9Szhengbin u8 nmw, nsw, rev; 89805491d2cSKalle Valo u32 base, wrap; 89905491d2cSKalle Valo int err; 90005491d2cSKalle Valo 9011ce050c1SArend van Spriel eromaddr = ci->ops->read32(ci->ctx, 9021ce050c1SArend van Spriel CORE_CC_REG(ci->pub.enum_base, eromptr)); 90305491d2cSKalle Valo 90405491d2cSKalle Valo while (desc_type != DMP_DESC_EOT) { 90505491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); 90605491d2cSKalle Valo if (!(val & DMP_DESC_VALID)) 90705491d2cSKalle Valo continue; 90805491d2cSKalle Valo 90905491d2cSKalle Valo if (desc_type == DMP_DESC_EMPTY) 91005491d2cSKalle Valo continue; 91105491d2cSKalle Valo 91205491d2cSKalle Valo /* need a component descriptor */ 91305491d2cSKalle Valo if (desc_type != DMP_DESC_COMPONENT) 91405491d2cSKalle Valo continue; 91505491d2cSKalle Valo 91605491d2cSKalle Valo id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S; 91705491d2cSKalle Valo 91805491d2cSKalle Valo /* next descriptor must be component as well */ 91905491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); 92005491d2cSKalle Valo if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT)) 92105491d2cSKalle Valo return -EFAULT; 92205491d2cSKalle Valo 92305491d2cSKalle Valo /* only look at cores with master port(s) */ 92405491d2cSKalle Valo nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S; 92505491d2cSKalle Valo nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S; 92605491d2cSKalle Valo rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S; 92705491d2cSKalle Valo 92805491d2cSKalle Valo /* need core with ports */ 92944977b81SRafał Miłecki if (nmw + nsw == 0 && 930b021a6bcSChi-Hsien Lin id != BCMA_CORE_PMU && 931b021a6bcSChi-Hsien Lin id != BCMA_CORE_GCI) 93205491d2cSKalle Valo continue; 93305491d2cSKalle Valo 93405491d2cSKalle Valo /* try to obtain register address info */ 93505491d2cSKalle Valo err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap); 93605491d2cSKalle Valo if (err) 93705491d2cSKalle Valo continue; 93805491d2cSKalle Valo 93905491d2cSKalle Valo /* finally a core to be added */ 94005491d2cSKalle Valo core = brcmf_chip_add_core(ci, id, base, wrap); 94105491d2cSKalle Valo if (IS_ERR(core)) 94205491d2cSKalle Valo return PTR_ERR(core); 94305491d2cSKalle Valo 94405491d2cSKalle Valo core->rev = rev; 94505491d2cSKalle Valo } 94605491d2cSKalle Valo 94705491d2cSKalle Valo return 0; 94805491d2cSKalle Valo } 94905491d2cSKalle Valo 9501ce050c1SArend van Spriel u32 brcmf_chip_enum_base(u16 devid) 9511ce050c1SArend van Spriel { 9521ce050c1SArend van Spriel return SI_ENUM_BASE_DEFAULT; 9531ce050c1SArend van Spriel } 9541ce050c1SArend van Spriel 95505491d2cSKalle Valo static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) 95605491d2cSKalle Valo { 95705491d2cSKalle Valo struct brcmf_core *core; 95805491d2cSKalle Valo u32 regdata; 95905491d2cSKalle Valo u32 socitype; 96005491d2cSKalle Valo int ret; 96105491d2cSKalle Valo 96205491d2cSKalle Valo /* Get CC core rev 96305491d2cSKalle Valo * Chipid is assume to be at offset 0 from SI_ENUM_BASE 96405491d2cSKalle Valo * For different chiptypes or old sdio hosts w/o chipcommon, 96505491d2cSKalle Valo * other ways of recognition should be added here. 96605491d2cSKalle Valo */ 9671ce050c1SArend van Spriel regdata = ci->ops->read32(ci->ctx, 9681ce050c1SArend van Spriel CORE_CC_REG(ci->pub.enum_base, chipid)); 96905491d2cSKalle Valo ci->pub.chip = regdata & CID_ID_MASK; 97005491d2cSKalle Valo ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; 97105491d2cSKalle Valo socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 97205491d2cSKalle Valo 973756a2b39SArend Van Spriel brcmf_chip_name(ci->pub.chip, ci->pub.chiprev, 974756a2b39SArend Van Spriel ci->pub.name, sizeof(ci->pub.name)); 975c88cfa07SArend Van Spriel brcmf_dbg(INFO, "found %s chip: %s\n", 976c88cfa07SArend Van Spriel socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name); 97705491d2cSKalle Valo 97805491d2cSKalle Valo if (socitype == SOCI_SB) { 97905491d2cSKalle Valo if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) { 98005491d2cSKalle Valo brcmf_err("SB chip is not supported\n"); 98105491d2cSKalle Valo return -ENODEV; 98205491d2cSKalle Valo } 98305491d2cSKalle Valo ci->iscoreup = brcmf_chip_sb_iscoreup; 98405491d2cSKalle Valo ci->coredisable = brcmf_chip_sb_coredisable; 98505491d2cSKalle Valo ci->resetcore = brcmf_chip_sb_resetcore; 98605491d2cSKalle Valo 98705491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON, 9881ce050c1SArend van Spriel SI_ENUM_BASE_DEFAULT, 0); 98905491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 99005491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV, 99105491d2cSKalle Valo BCM4329_CORE_BUS_BASE, 0); 99205491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 99305491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM, 99405491d2cSKalle Valo BCM4329_CORE_SOCRAM_BASE, 0); 99505491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 99605491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3, 99705491d2cSKalle Valo BCM4329_CORE_ARM_BASE, 0); 99805491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 99905491d2cSKalle Valo 100005491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0); 100105491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 100205491d2cSKalle Valo } else if (socitype == SOCI_AI) { 100305491d2cSKalle Valo ci->iscoreup = brcmf_chip_ai_iscoreup; 100405491d2cSKalle Valo ci->coredisable = brcmf_chip_ai_coredisable; 100505491d2cSKalle Valo ci->resetcore = brcmf_chip_ai_resetcore; 100605491d2cSKalle Valo 100705491d2cSKalle Valo brcmf_chip_dmp_erom_scan(ci); 100805491d2cSKalle Valo } else { 100905491d2cSKalle Valo brcmf_err("chip backplane type %u is not supported\n", 101005491d2cSKalle Valo socitype); 101105491d2cSKalle Valo return -ENODEV; 101205491d2cSKalle Valo } 101305491d2cSKalle Valo 101405491d2cSKalle Valo ret = brcmf_chip_cores_check(ci); 101505491d2cSKalle Valo if (ret) 101605491d2cSKalle Valo return ret; 101705491d2cSKalle Valo 101805491d2cSKalle Valo /* assure chip is passive for core access */ 101905491d2cSKalle Valo brcmf_chip_set_passive(&ci->pub); 102005491d2cSKalle Valo 102105491d2cSKalle Valo /* Call bus specific reset function now. Cores have been determined 102205491d2cSKalle Valo * but further access may require a chip specific reset at this point. 102305491d2cSKalle Valo */ 102405491d2cSKalle Valo if (ci->ops->reset) { 102505491d2cSKalle Valo ci->ops->reset(ci->ctx, &ci->pub); 102605491d2cSKalle Valo brcmf_chip_set_passive(&ci->pub); 102705491d2cSKalle Valo } 102805491d2cSKalle Valo 102982f93cf4SRafał Miłecki return brcmf_chip_get_raminfo(&ci->pub); 103005491d2cSKalle Valo } 103105491d2cSKalle Valo 103205491d2cSKalle Valo static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) 103305491d2cSKalle Valo { 103405491d2cSKalle Valo struct brcmf_core *core; 103505491d2cSKalle Valo struct brcmf_core_priv *cpu; 103605491d2cSKalle Valo u32 val; 103705491d2cSKalle Valo 103805491d2cSKalle Valo 103905491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, id); 104005491d2cSKalle Valo if (!core) 104105491d2cSKalle Valo return; 104205491d2cSKalle Valo 104305491d2cSKalle Valo switch (id) { 104405491d2cSKalle Valo case BCMA_CORE_ARM_CM3: 104505491d2cSKalle Valo brcmf_chip_coredisable(core, 0, 0); 104605491d2cSKalle Valo break; 104705491d2cSKalle Valo case BCMA_CORE_ARM_CR4: 104805491d2cSKalle Valo case BCMA_CORE_ARM_CA7: 104905491d2cSKalle Valo cpu = container_of(core, struct brcmf_core_priv, pub); 105005491d2cSKalle Valo 105105491d2cSKalle Valo /* clear all IOCTL bits except HALT bit */ 105205491d2cSKalle Valo val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL); 105305491d2cSKalle Valo val &= ARMCR4_BCMA_IOCTL_CPUHALT; 105405491d2cSKalle Valo brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT, 105505491d2cSKalle Valo ARMCR4_BCMA_IOCTL_CPUHALT); 105605491d2cSKalle Valo break; 105705491d2cSKalle Valo default: 105805491d2cSKalle Valo brcmf_err("unknown id: %u\n", id); 105905491d2cSKalle Valo break; 106005491d2cSKalle Valo } 106105491d2cSKalle Valo } 106205491d2cSKalle Valo 106305491d2cSKalle Valo static int brcmf_chip_setup(struct brcmf_chip_priv *chip) 106405491d2cSKalle Valo { 106505491d2cSKalle Valo struct brcmf_chip *pub; 106605491d2cSKalle Valo struct brcmf_core_priv *cc; 1067e2b397f1SRafał Miłecki struct brcmf_core *pmu; 106805491d2cSKalle Valo u32 base; 106905491d2cSKalle Valo u32 val; 107005491d2cSKalle Valo int ret = 0; 107105491d2cSKalle Valo 107205491d2cSKalle Valo pub = &chip->pub; 107305491d2cSKalle Valo cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list); 107405491d2cSKalle Valo base = cc->pub.base; 107505491d2cSKalle Valo 107605491d2cSKalle Valo /* get chipcommon capabilites */ 107705491d2cSKalle Valo pub->cc_caps = chip->ops->read32(chip->ctx, 107805491d2cSKalle Valo CORE_CC_REG(base, capabilities)); 10799befe919SRafał Miłecki pub->cc_caps_ext = chip->ops->read32(chip->ctx, 10809befe919SRafał Miłecki CORE_CC_REG(base, 10819befe919SRafał Miłecki capabilities_ext)); 108205491d2cSKalle Valo 108305491d2cSKalle Valo /* get pmu caps & rev */ 1084e2b397f1SRafał Miłecki pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */ 108505491d2cSKalle Valo if (pub->cc_caps & CC_CAP_PMU) { 108605491d2cSKalle Valo val = chip->ops->read32(chip->ctx, 1087e2b397f1SRafał Miłecki CORE_CC_REG(pmu->base, pmucapabilities)); 108805491d2cSKalle Valo pub->pmurev = val & PCAP_REV_MASK; 108905491d2cSKalle Valo pub->pmucaps = val; 109005491d2cSKalle Valo } 109105491d2cSKalle Valo 109205491d2cSKalle Valo brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n", 109305491d2cSKalle Valo cc->pub.rev, pub->pmurev, pub->pmucaps); 109405491d2cSKalle Valo 109505491d2cSKalle Valo /* execute bus core specific setup */ 109605491d2cSKalle Valo if (chip->ops->setup) 109705491d2cSKalle Valo ret = chip->ops->setup(chip->ctx, pub); 109805491d2cSKalle Valo 109905491d2cSKalle Valo return ret; 110005491d2cSKalle Valo } 110105491d2cSKalle Valo 11021ce050c1SArend van Spriel struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid, 110305491d2cSKalle Valo const struct brcmf_buscore_ops *ops) 110405491d2cSKalle Valo { 110505491d2cSKalle Valo struct brcmf_chip_priv *chip; 110605491d2cSKalle Valo int err = 0; 110705491d2cSKalle Valo 110805491d2cSKalle Valo if (WARN_ON(!ops->read32)) 110905491d2cSKalle Valo err = -EINVAL; 111005491d2cSKalle Valo if (WARN_ON(!ops->write32)) 111105491d2cSKalle Valo err = -EINVAL; 111205491d2cSKalle Valo if (WARN_ON(!ops->prepare)) 111305491d2cSKalle Valo err = -EINVAL; 111405491d2cSKalle Valo if (WARN_ON(!ops->activate)) 111505491d2cSKalle Valo err = -EINVAL; 111605491d2cSKalle Valo if (err < 0) 111705491d2cSKalle Valo return ERR_PTR(-EINVAL); 111805491d2cSKalle Valo 111905491d2cSKalle Valo chip = kzalloc(sizeof(*chip), GFP_KERNEL); 112005491d2cSKalle Valo if (!chip) 112105491d2cSKalle Valo return ERR_PTR(-ENOMEM); 112205491d2cSKalle Valo 112305491d2cSKalle Valo INIT_LIST_HEAD(&chip->cores); 112405491d2cSKalle Valo chip->num_cores = 0; 112505491d2cSKalle Valo chip->ops = ops; 112605491d2cSKalle Valo chip->ctx = ctx; 11271ce050c1SArend van Spriel chip->pub.enum_base = brcmf_chip_enum_base(devid); 112805491d2cSKalle Valo 112905491d2cSKalle Valo err = ops->prepare(ctx); 113005491d2cSKalle Valo if (err < 0) 113105491d2cSKalle Valo goto fail; 113205491d2cSKalle Valo 113305491d2cSKalle Valo err = brcmf_chip_recognition(chip); 113405491d2cSKalle Valo if (err < 0) 113505491d2cSKalle Valo goto fail; 113605491d2cSKalle Valo 113705491d2cSKalle Valo err = brcmf_chip_setup(chip); 113805491d2cSKalle Valo if (err < 0) 113905491d2cSKalle Valo goto fail; 114005491d2cSKalle Valo 114105491d2cSKalle Valo return &chip->pub; 114205491d2cSKalle Valo 114305491d2cSKalle Valo fail: 114405491d2cSKalle Valo brcmf_chip_detach(&chip->pub); 114505491d2cSKalle Valo return ERR_PTR(err); 114605491d2cSKalle Valo } 114705491d2cSKalle Valo 114805491d2cSKalle Valo void brcmf_chip_detach(struct brcmf_chip *pub) 114905491d2cSKalle Valo { 115005491d2cSKalle Valo struct brcmf_chip_priv *chip; 115105491d2cSKalle Valo struct brcmf_core_priv *core; 115205491d2cSKalle Valo struct brcmf_core_priv *tmp; 115305491d2cSKalle Valo 115405491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 115505491d2cSKalle Valo list_for_each_entry_safe(core, tmp, &chip->cores, list) { 115605491d2cSKalle Valo list_del(&core->list); 115705491d2cSKalle Valo kfree(core); 115805491d2cSKalle Valo } 115905491d2cSKalle Valo kfree(chip); 116005491d2cSKalle Valo } 116105491d2cSKalle Valo 11621b8d2e0aSWright Feng struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit) 11631b8d2e0aSWright Feng { 11641b8d2e0aSWright Feng struct brcmf_chip_priv *chip; 11651b8d2e0aSWright Feng struct brcmf_core_priv *core; 11661b8d2e0aSWright Feng 11671b8d2e0aSWright Feng chip = container_of(pub, struct brcmf_chip_priv, pub); 11681b8d2e0aSWright Feng list_for_each_entry(core, &chip->cores, list) { 11691b8d2e0aSWright Feng if (core->pub.id == BCMA_CORE_80211) { 11701b8d2e0aSWright Feng if (unit-- == 0) 11711b8d2e0aSWright Feng return &core->pub; 11721b8d2e0aSWright Feng } 11731b8d2e0aSWright Feng } 11741b8d2e0aSWright Feng return NULL; 11751b8d2e0aSWright Feng } 11761b8d2e0aSWright Feng 117705491d2cSKalle Valo struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid) 117805491d2cSKalle Valo { 117905491d2cSKalle Valo struct brcmf_chip_priv *chip; 118005491d2cSKalle Valo struct brcmf_core_priv *core; 118105491d2cSKalle Valo 118205491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 118305491d2cSKalle Valo list_for_each_entry(core, &chip->cores, list) 118405491d2cSKalle Valo if (core->pub.id == coreid) 118505491d2cSKalle Valo return &core->pub; 118605491d2cSKalle Valo 118705491d2cSKalle Valo return NULL; 118805491d2cSKalle Valo } 118905491d2cSKalle Valo 119005491d2cSKalle Valo struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub) 119105491d2cSKalle Valo { 119205491d2cSKalle Valo struct brcmf_chip_priv *chip; 119305491d2cSKalle Valo struct brcmf_core_priv *cc; 119405491d2cSKalle Valo 119505491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 119605491d2cSKalle Valo cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list); 119705491d2cSKalle Valo if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON)) 119805491d2cSKalle Valo return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON); 119905491d2cSKalle Valo return &cc->pub; 120005491d2cSKalle Valo } 120105491d2cSKalle Valo 1202e2b397f1SRafał Miłecki struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub) 1203e2b397f1SRafał Miłecki { 1204e2b397f1SRafał Miłecki struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub); 1205e2b397f1SRafał Miłecki struct brcmf_core *pmu; 1206e2b397f1SRafał Miłecki 1207e2b397f1SRafał Miłecki /* See if there is separated PMU core available */ 1208e2b397f1SRafał Miłecki if (cc->rev >= 35 && 1209e2b397f1SRafał Miłecki pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { 1210e2b397f1SRafał Miłecki pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); 1211e2b397f1SRafał Miłecki if (pmu) 1212e2b397f1SRafał Miłecki return pmu; 1213e2b397f1SRafał Miłecki } 1214e2b397f1SRafał Miłecki 1215e2b397f1SRafał Miłecki /* Fallback to ChipCommon core for older hardware */ 1216e2b397f1SRafał Miłecki return cc; 1217e2b397f1SRafał Miłecki } 1218e2b397f1SRafał Miłecki 121905491d2cSKalle Valo bool brcmf_chip_iscoreup(struct brcmf_core *pub) 122005491d2cSKalle Valo { 122105491d2cSKalle Valo struct brcmf_core_priv *core; 122205491d2cSKalle Valo 122305491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 122405491d2cSKalle Valo return core->chip->iscoreup(core); 122505491d2cSKalle Valo } 122605491d2cSKalle Valo 122705491d2cSKalle Valo void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset) 122805491d2cSKalle Valo { 122905491d2cSKalle Valo struct brcmf_core_priv *core; 123005491d2cSKalle Valo 123105491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 123205491d2cSKalle Valo core->chip->coredisable(core, prereset, reset); 123305491d2cSKalle Valo } 123405491d2cSKalle Valo 123505491d2cSKalle Valo void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset, 123605491d2cSKalle Valo u32 postreset) 123705491d2cSKalle Valo { 123805491d2cSKalle Valo struct brcmf_core_priv *core; 123905491d2cSKalle Valo 124005491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 124105491d2cSKalle Valo core->chip->resetcore(core, prereset, reset, postreset); 124205491d2cSKalle Valo } 124305491d2cSKalle Valo 124405491d2cSKalle Valo static void 124505491d2cSKalle Valo brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) 124605491d2cSKalle Valo { 124705491d2cSKalle Valo struct brcmf_core *core; 124805491d2cSKalle Valo struct brcmf_core_priv *sr; 124905491d2cSKalle Valo 125005491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); 125105491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); 125205491d2cSKalle Valo brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | 125305491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 125405491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 125505491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 125605491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); 125705491d2cSKalle Valo brcmf_chip_resetcore(core, 0, 0, 0); 125805491d2cSKalle Valo 125905491d2cSKalle Valo /* disable bank #3 remap for this device */ 126005491d2cSKalle Valo if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) { 126105491d2cSKalle Valo sr = container_of(core, struct brcmf_core_priv, pub); 126205491d2cSKalle Valo brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3); 126305491d2cSKalle Valo brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0); 126405491d2cSKalle Valo } 126505491d2cSKalle Valo } 126605491d2cSKalle Valo 126705491d2cSKalle Valo static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) 126805491d2cSKalle Valo { 126905491d2cSKalle Valo struct brcmf_core *core; 127005491d2cSKalle Valo 127105491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); 127205491d2cSKalle Valo if (!brcmf_chip_iscoreup(core)) { 127305491d2cSKalle Valo brcmf_err("SOCRAM core is down after reset?\n"); 127405491d2cSKalle Valo return false; 127505491d2cSKalle Valo } 127605491d2cSKalle Valo 127705491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, 0); 127805491d2cSKalle Valo 127905491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); 128005491d2cSKalle Valo brcmf_chip_resetcore(core, 0, 0, 0); 128105491d2cSKalle Valo 128205491d2cSKalle Valo return true; 128305491d2cSKalle Valo } 128405491d2cSKalle Valo 128505491d2cSKalle Valo static inline void 128605491d2cSKalle Valo brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) 128705491d2cSKalle Valo { 128805491d2cSKalle Valo struct brcmf_core *core; 128905491d2cSKalle Valo 129005491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); 129105491d2cSKalle Valo 129205491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); 129305491d2cSKalle Valo brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | 129405491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 129505491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 129605491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 129705491d2cSKalle Valo } 129805491d2cSKalle Valo 129905491d2cSKalle Valo static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) 130005491d2cSKalle Valo { 130105491d2cSKalle Valo struct brcmf_core *core; 130205491d2cSKalle Valo 130305491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, rstvec); 130405491d2cSKalle Valo 130505491d2cSKalle Valo /* restore ARM */ 130605491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); 130705491d2cSKalle Valo brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); 130805491d2cSKalle Valo 130905491d2cSKalle Valo return true; 131005491d2cSKalle Valo } 131105491d2cSKalle Valo 131205491d2cSKalle Valo static inline void 131305491d2cSKalle Valo brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip) 131405491d2cSKalle Valo { 131505491d2cSKalle Valo struct brcmf_core *core; 131605491d2cSKalle Valo 131705491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7); 131805491d2cSKalle Valo 131905491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); 132005491d2cSKalle Valo brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | 132105491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 132205491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 132305491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 132405491d2cSKalle Valo } 132505491d2cSKalle Valo 132605491d2cSKalle Valo static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec) 132705491d2cSKalle Valo { 132805491d2cSKalle Valo struct brcmf_core *core; 132905491d2cSKalle Valo 133005491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, rstvec); 133105491d2cSKalle Valo 133205491d2cSKalle Valo /* restore ARM */ 133305491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7); 133405491d2cSKalle Valo brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); 133505491d2cSKalle Valo 133605491d2cSKalle Valo return true; 133705491d2cSKalle Valo } 133805491d2cSKalle Valo 133905491d2cSKalle Valo void brcmf_chip_set_passive(struct brcmf_chip *pub) 134005491d2cSKalle Valo { 134105491d2cSKalle Valo struct brcmf_chip_priv *chip; 134205491d2cSKalle Valo struct brcmf_core *arm; 134305491d2cSKalle Valo 134405491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 134505491d2cSKalle Valo 134605491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 134705491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); 134805491d2cSKalle Valo if (arm) { 134905491d2cSKalle Valo brcmf_chip_cr4_set_passive(chip); 135005491d2cSKalle Valo return; 135105491d2cSKalle Valo } 135205491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); 135305491d2cSKalle Valo if (arm) { 135405491d2cSKalle Valo brcmf_chip_ca7_set_passive(chip); 135505491d2cSKalle Valo return; 135605491d2cSKalle Valo } 135705491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); 135805491d2cSKalle Valo if (arm) { 135905491d2cSKalle Valo brcmf_chip_cm3_set_passive(chip); 136005491d2cSKalle Valo return; 136105491d2cSKalle Valo } 136205491d2cSKalle Valo } 136305491d2cSKalle Valo 136405491d2cSKalle Valo bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) 136505491d2cSKalle Valo { 136605491d2cSKalle Valo struct brcmf_chip_priv *chip; 136705491d2cSKalle Valo struct brcmf_core *arm; 136805491d2cSKalle Valo 136905491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 137005491d2cSKalle Valo 137105491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 137205491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); 137305491d2cSKalle Valo if (arm) 137405491d2cSKalle Valo return brcmf_chip_cr4_set_active(chip, rstvec); 137505491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); 137605491d2cSKalle Valo if (arm) 137705491d2cSKalle Valo return brcmf_chip_ca7_set_active(chip, rstvec); 137805491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); 137905491d2cSKalle Valo if (arm) 138005491d2cSKalle Valo return brcmf_chip_cm3_set_active(chip); 138105491d2cSKalle Valo 138205491d2cSKalle Valo return false; 138305491d2cSKalle Valo } 138405491d2cSKalle Valo 138505491d2cSKalle Valo bool brcmf_chip_sr_capable(struct brcmf_chip *pub) 138605491d2cSKalle Valo { 138705491d2cSKalle Valo u32 base, addr, reg, pmu_cc3_mask = ~0; 138805491d2cSKalle Valo struct brcmf_chip_priv *chip; 1389e2b397f1SRafał Miłecki struct brcmf_core *pmu = brcmf_chip_get_pmu(pub); 139005491d2cSKalle Valo 139105491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 139205491d2cSKalle Valo 139305491d2cSKalle Valo /* old chips with PMU version less than 17 don't support save restore */ 139405491d2cSKalle Valo if (pub->pmurev < 17) 139505491d2cSKalle Valo return false; 139605491d2cSKalle Valo 139705491d2cSKalle Valo base = brcmf_chip_get_chipcommon(pub)->base; 139805491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 139905491d2cSKalle Valo 140005491d2cSKalle Valo switch (pub->chip) { 140105491d2cSKalle Valo case BRCM_CC_4354_CHIP_ID: 1402496aec57SChristian Daudt case BRCM_CC_4356_CHIP_ID: 1403e3720dadSDouble Lo case BRCM_CC_4345_CHIP_ID: 140405491d2cSKalle Valo /* explicitly check SR engine enable bit */ 140505491d2cSKalle Valo pmu_cc3_mask = BIT(2); 14060bde10dcSGustavo A. R. Silva fallthrough; 140705491d2cSKalle Valo case BRCM_CC_43241_CHIP_ID: 140805491d2cSKalle Valo case BRCM_CC_4335_CHIP_ID: 140905491d2cSKalle Valo case BRCM_CC_4339_CHIP_ID: 141005491d2cSKalle Valo /* read PMU chipcontrol register 3 */ 1411e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, chipcontrol_addr); 141205491d2cSKalle Valo chip->ops->write32(chip->ctx, addr, 3); 1413e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, chipcontrol_data); 141405491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 141505491d2cSKalle Valo return (reg & pmu_cc3_mask) != 0; 141605491d2cSKalle Valo case BRCM_CC_43430_CHIP_ID: 141705491d2cSKalle Valo addr = CORE_CC_REG(base, sr_control1); 141805491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 141905491d2cSKalle Valo return reg != 0; 14202f2d389eSChi-Hsien Lin case CY_CC_4373_CHIP_ID: 14212f2d389eSChi-Hsien Lin /* explicitly check SR engine enable bit */ 14222f2d389eSChi-Hsien Lin addr = CORE_CC_REG(base, sr_control0); 14232f2d389eSChi-Hsien Lin reg = chip->ops->read32(chip->ctx, addr); 14242f2d389eSChi-Hsien Lin return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; 1425d4aef159SSoeren Moch case BRCM_CC_4359_CHIP_ID: 1426*d2587c57SAngus Ainslie case CY_CC_43752_CHIP_ID: 142735cb51b2SChi-Hsien Lin case CY_CC_43012_CHIP_ID: 142835cb51b2SChi-Hsien Lin addr = CORE_CC_REG(pmu->base, retention_ctl); 142935cb51b2SChi-Hsien Lin reg = chip->ops->read32(chip->ctx, addr); 143035cb51b2SChi-Hsien Lin return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | 143135cb51b2SChi-Hsien Lin PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; 143205491d2cSKalle Valo default: 1433e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, pmucapabilities_ext); 143405491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 143505491d2cSKalle Valo if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) 143605491d2cSKalle Valo return false; 143705491d2cSKalle Valo 1438e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, retention_ctl); 143905491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 144005491d2cSKalle Valo return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | 144105491d2cSKalle Valo PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; 144205491d2cSKalle Valo } 144305491d2cSKalle Valo } 1444