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 215098e0b10SHector Martin #define ARMCR4_BSZ_MASK 0x7f 21605491d2cSKalle Valo #define ARMCR4_BSZ_MULT 8192 217098e0b10SHector Martin #define ARMCR4_BLK_1K_MASK 0x200 21805491d2cSKalle Valo 21905491d2cSKalle Valo struct brcmf_core_priv { 22005491d2cSKalle Valo struct brcmf_core pub; 22105491d2cSKalle Valo u32 wrapbase; 22205491d2cSKalle Valo struct list_head list; 22305491d2cSKalle Valo struct brcmf_chip_priv *chip; 22405491d2cSKalle Valo }; 22505491d2cSKalle Valo 22605491d2cSKalle Valo struct brcmf_chip_priv { 22705491d2cSKalle Valo struct brcmf_chip pub; 22805491d2cSKalle Valo const struct brcmf_buscore_ops *ops; 22905491d2cSKalle Valo void *ctx; 23005491d2cSKalle Valo /* assured first core is chipcommon, second core is buscore */ 23105491d2cSKalle Valo struct list_head cores; 23205491d2cSKalle Valo u16 num_cores; 23305491d2cSKalle Valo 23405491d2cSKalle Valo bool (*iscoreup)(struct brcmf_core_priv *core); 23505491d2cSKalle Valo void (*coredisable)(struct brcmf_core_priv *core, u32 prereset, 23605491d2cSKalle Valo u32 reset); 23705491d2cSKalle Valo void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset, 23805491d2cSKalle Valo u32 postreset); 23905491d2cSKalle Valo }; 24005491d2cSKalle Valo 24105491d2cSKalle Valo static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci, 24205491d2cSKalle Valo struct brcmf_core *core) 24305491d2cSKalle Valo { 24405491d2cSKalle Valo u32 regdata; 24505491d2cSKalle Valo 24605491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh)); 24705491d2cSKalle Valo core->rev = SBCOREREV(regdata); 24805491d2cSKalle Valo } 24905491d2cSKalle Valo 25005491d2cSKalle Valo static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core) 25105491d2cSKalle Valo { 25205491d2cSKalle Valo struct brcmf_chip_priv *ci; 25305491d2cSKalle Valo u32 regdata; 25405491d2cSKalle Valo u32 address; 25505491d2cSKalle Valo 25605491d2cSKalle Valo ci = core->chip; 25705491d2cSKalle Valo address = CORE_SB(core->pub.base, sbtmstatelow); 25805491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, address); 25905491d2cSKalle Valo regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | 26005491d2cSKalle Valo SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); 26105491d2cSKalle Valo return SSB_TMSLOW_CLOCK == regdata; 26205491d2cSKalle Valo } 26305491d2cSKalle Valo 26405491d2cSKalle Valo static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core) 26505491d2cSKalle Valo { 26605491d2cSKalle Valo struct brcmf_chip_priv *ci; 26705491d2cSKalle Valo u32 regdata; 26805491d2cSKalle Valo bool ret; 26905491d2cSKalle Valo 27005491d2cSKalle Valo ci = core->chip; 27105491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 27205491d2cSKalle Valo ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; 27305491d2cSKalle Valo 27405491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); 27505491d2cSKalle Valo ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); 27605491d2cSKalle Valo 27705491d2cSKalle Valo return ret; 27805491d2cSKalle Valo } 27905491d2cSKalle Valo 28005491d2cSKalle Valo static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core, 28105491d2cSKalle Valo u32 prereset, u32 reset) 28205491d2cSKalle Valo { 28305491d2cSKalle Valo struct brcmf_chip_priv *ci; 28405491d2cSKalle Valo u32 val, base; 28505491d2cSKalle Valo 28605491d2cSKalle Valo ci = core->chip; 28705491d2cSKalle Valo base = core->pub.base; 28805491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 28905491d2cSKalle Valo if (val & SSB_TMSLOW_RESET) 29005491d2cSKalle Valo return; 29105491d2cSKalle Valo 29205491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 29305491d2cSKalle Valo if ((val & SSB_TMSLOW_CLOCK) != 0) { 29405491d2cSKalle Valo /* 29505491d2cSKalle Valo * set target reject and spin until busy is clear 29605491d2cSKalle Valo * (preserve core-specific bits) 29705491d2cSKalle Valo */ 29805491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 29905491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 30005491d2cSKalle Valo val | SSB_TMSLOW_REJECT); 30105491d2cSKalle Valo 30205491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 30305491d2cSKalle Valo udelay(1); 30405491d2cSKalle Valo SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)) 30505491d2cSKalle Valo & SSB_TMSHIGH_BUSY), 100000); 30605491d2cSKalle Valo 30705491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); 30805491d2cSKalle Valo if (val & SSB_TMSHIGH_BUSY) 30905491d2cSKalle Valo brcmf_err("core state still busy\n"); 31005491d2cSKalle Valo 31105491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); 31205491d2cSKalle Valo if (val & SSB_IDLOW_INITIATOR) { 31305491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 31405491d2cSKalle Valo CORE_SB(base, sbimstate)); 31505491d2cSKalle Valo val |= SSB_IMSTATE_REJECT; 31605491d2cSKalle Valo ci->ops->write32(ci->ctx, 31705491d2cSKalle Valo CORE_SB(base, sbimstate), val); 31805491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 31905491d2cSKalle Valo CORE_SB(base, sbimstate)); 32005491d2cSKalle Valo udelay(1); 32105491d2cSKalle Valo SPINWAIT((ci->ops->read32(ci->ctx, 32205491d2cSKalle Valo CORE_SB(base, sbimstate)) & 32305491d2cSKalle Valo SSB_IMSTATE_BUSY), 100000); 32405491d2cSKalle Valo } 32505491d2cSKalle Valo 32605491d2cSKalle Valo /* set reset and reject while enabling the clocks */ 32705491d2cSKalle Valo val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | 32805491d2cSKalle Valo SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; 32905491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val); 33005491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 33105491d2cSKalle Valo udelay(10); 33205491d2cSKalle Valo 33305491d2cSKalle Valo /* clear the initiator reject bit */ 33405491d2cSKalle Valo val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow)); 33505491d2cSKalle Valo if (val & SSB_IDLOW_INITIATOR) { 33605491d2cSKalle Valo val = ci->ops->read32(ci->ctx, 33705491d2cSKalle Valo CORE_SB(base, sbimstate)); 33805491d2cSKalle Valo val &= ~SSB_IMSTATE_REJECT; 33905491d2cSKalle Valo ci->ops->write32(ci->ctx, 34005491d2cSKalle Valo CORE_SB(base, sbimstate), val); 34105491d2cSKalle Valo } 34205491d2cSKalle Valo } 34305491d2cSKalle Valo 34405491d2cSKalle Valo /* leave reset and reject asserted */ 34505491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 34605491d2cSKalle Valo (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); 34705491d2cSKalle Valo udelay(1); 34805491d2cSKalle Valo } 34905491d2cSKalle Valo 35005491d2cSKalle Valo static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, 35105491d2cSKalle Valo u32 prereset, u32 reset) 35205491d2cSKalle Valo { 35305491d2cSKalle Valo struct brcmf_chip_priv *ci; 35405491d2cSKalle Valo u32 regdata; 35505491d2cSKalle Valo 35605491d2cSKalle Valo ci = core->chip; 35705491d2cSKalle Valo 35805491d2cSKalle Valo /* if core is already in reset, skip reset */ 35905491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); 36005491d2cSKalle Valo if ((regdata & BCMA_RESET_CTL_RESET) != 0) 36105491d2cSKalle Valo goto in_reset_configure; 36205491d2cSKalle Valo 36305491d2cSKalle Valo /* configure reset */ 36405491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 36505491d2cSKalle Valo prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); 36605491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 36705491d2cSKalle Valo 36805491d2cSKalle Valo /* put in reset */ 36905491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 37005491d2cSKalle Valo BCMA_RESET_CTL_RESET); 37105491d2cSKalle Valo usleep_range(10, 20); 37205491d2cSKalle Valo 37305491d2cSKalle Valo /* wait till reset is 1 */ 37405491d2cSKalle Valo SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) != 37505491d2cSKalle Valo BCMA_RESET_CTL_RESET, 300); 37605491d2cSKalle Valo 37705491d2cSKalle Valo in_reset_configure: 37805491d2cSKalle Valo /* in-reset configure */ 37905491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 38005491d2cSKalle Valo reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); 38105491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 38205491d2cSKalle Valo } 38305491d2cSKalle Valo 38405491d2cSKalle Valo static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset, 38505491d2cSKalle Valo u32 reset, u32 postreset) 38605491d2cSKalle Valo { 38705491d2cSKalle Valo struct brcmf_chip_priv *ci; 38805491d2cSKalle Valo u32 regdata; 38905491d2cSKalle Valo u32 base; 39005491d2cSKalle Valo 39105491d2cSKalle Valo ci = core->chip; 39205491d2cSKalle Valo base = core->pub.base; 39305491d2cSKalle Valo /* 39405491d2cSKalle Valo * Must do the disable sequence first to work for 39505491d2cSKalle Valo * arbitrary current core state. 39605491d2cSKalle Valo */ 39705491d2cSKalle Valo brcmf_chip_sb_coredisable(core, 0, 0); 39805491d2cSKalle Valo 39905491d2cSKalle Valo /* 40005491d2cSKalle Valo * Now do the initialization sequence. 40105491d2cSKalle Valo * set reset while enabling the clock and 40205491d2cSKalle Valo * forcing them on throughout the core 40305491d2cSKalle Valo */ 40405491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 40505491d2cSKalle Valo SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | 40605491d2cSKalle Valo SSB_TMSLOW_RESET); 40705491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 40805491d2cSKalle Valo udelay(1); 40905491d2cSKalle Valo 41005491d2cSKalle Valo /* clear any serror */ 41105491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh)); 41205491d2cSKalle Valo if (regdata & SSB_TMSHIGH_SERR) 41305491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0); 41405491d2cSKalle Valo 41505491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate)); 41605491d2cSKalle Valo if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) { 41705491d2cSKalle Valo regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO); 41805491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata); 41905491d2cSKalle Valo } 42005491d2cSKalle Valo 42105491d2cSKalle Valo /* clear reset and allow it to propagate throughout the core */ 42205491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 42305491d2cSKalle Valo SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK); 42405491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 42505491d2cSKalle Valo udelay(1); 42605491d2cSKalle Valo 42705491d2cSKalle Valo /* leave clock enabled */ 42805491d2cSKalle Valo ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), 42905491d2cSKalle Valo SSB_TMSLOW_CLOCK); 43005491d2cSKalle Valo regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow)); 43105491d2cSKalle Valo udelay(1); 43205491d2cSKalle Valo } 43305491d2cSKalle Valo 43405491d2cSKalle Valo static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset, 43505491d2cSKalle Valo u32 reset, u32 postreset) 43605491d2cSKalle Valo { 43705491d2cSKalle Valo struct brcmf_chip_priv *ci; 43805491d2cSKalle Valo int count; 4391b8d2e0aSWright Feng struct brcmf_core *d11core2 = NULL; 4401b8d2e0aSWright Feng struct brcmf_core_priv *d11priv2 = NULL; 44105491d2cSKalle Valo 44205491d2cSKalle Valo ci = core->chip; 44305491d2cSKalle Valo 4441b8d2e0aSWright Feng /* special handle two D11 cores reset */ 4451b8d2e0aSWright Feng if (core->pub.id == BCMA_CORE_80211) { 4461b8d2e0aSWright Feng d11core2 = brcmf_chip_get_d11core(&ci->pub, 1); 4471b8d2e0aSWright Feng if (d11core2) { 4481b8d2e0aSWright Feng brcmf_dbg(INFO, "found two d11 cores, reset both\n"); 4491b8d2e0aSWright Feng d11priv2 = container_of(d11core2, 4501b8d2e0aSWright Feng struct brcmf_core_priv, pub); 4511b8d2e0aSWright Feng } 4521b8d2e0aSWright Feng } 4531b8d2e0aSWright Feng 45405491d2cSKalle Valo /* must disable first to work for arbitrary current core state */ 45505491d2cSKalle Valo brcmf_chip_ai_coredisable(core, prereset, reset); 4561b8d2e0aSWright Feng if (d11priv2) 4571b8d2e0aSWright Feng brcmf_chip_ai_coredisable(d11priv2, prereset, reset); 45805491d2cSKalle Valo 45905491d2cSKalle Valo count = 0; 46005491d2cSKalle Valo while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) & 46105491d2cSKalle Valo BCMA_RESET_CTL_RESET) { 46205491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0); 46305491d2cSKalle Valo count++; 46405491d2cSKalle Valo if (count > 50) 46505491d2cSKalle Valo break; 46605491d2cSKalle Valo usleep_range(40, 60); 46705491d2cSKalle Valo } 46805491d2cSKalle Valo 4691b8d2e0aSWright Feng if (d11priv2) { 4701b8d2e0aSWright Feng count = 0; 4711b8d2e0aSWright Feng while (ci->ops->read32(ci->ctx, 4721b8d2e0aSWright Feng d11priv2->wrapbase + BCMA_RESET_CTL) & 4731b8d2e0aSWright Feng BCMA_RESET_CTL_RESET) { 4741b8d2e0aSWright Feng ci->ops->write32(ci->ctx, 4751b8d2e0aSWright Feng d11priv2->wrapbase + BCMA_RESET_CTL, 4761b8d2e0aSWright Feng 0); 4771b8d2e0aSWright Feng count++; 4781b8d2e0aSWright Feng if (count > 50) 4791b8d2e0aSWright Feng break; 4801b8d2e0aSWright Feng usleep_range(40, 60); 4811b8d2e0aSWright Feng } 4821b8d2e0aSWright Feng } 4831b8d2e0aSWright Feng 48405491d2cSKalle Valo ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, 48505491d2cSKalle Valo postreset | BCMA_IOCTL_CLK); 48605491d2cSKalle Valo ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); 4871b8d2e0aSWright Feng 4881b8d2e0aSWright Feng if (d11priv2) { 4891b8d2e0aSWright Feng ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL, 4901b8d2e0aSWright Feng postreset | BCMA_IOCTL_CLK); 4911b8d2e0aSWright Feng ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL); 4921b8d2e0aSWright Feng } 49305491d2cSKalle Valo } 49405491d2cSKalle Valo 495756a2b39SArend Van Spriel char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) 49605491d2cSKalle Valo { 49705491d2cSKalle Valo const char *fmt; 49805491d2cSKalle Valo 499756a2b39SArend Van Spriel fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u"; 500756a2b39SArend Van Spriel snprintf(buf, len, fmt, id, rev); 50105491d2cSKalle Valo return buf; 50205491d2cSKalle Valo } 50305491d2cSKalle Valo 50405491d2cSKalle Valo static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci, 50505491d2cSKalle Valo u16 coreid, u32 base, 50605491d2cSKalle Valo u32 wrapbase) 50705491d2cSKalle Valo { 50805491d2cSKalle Valo struct brcmf_core_priv *core; 50905491d2cSKalle Valo 51005491d2cSKalle Valo core = kzalloc(sizeof(*core), GFP_KERNEL); 51105491d2cSKalle Valo if (!core) 51205491d2cSKalle Valo return ERR_PTR(-ENOMEM); 51305491d2cSKalle Valo 51405491d2cSKalle Valo core->pub.id = coreid; 51505491d2cSKalle Valo core->pub.base = base; 51605491d2cSKalle Valo core->chip = ci; 51705491d2cSKalle Valo core->wrapbase = wrapbase; 51805491d2cSKalle Valo 51905491d2cSKalle Valo list_add_tail(&core->list, &ci->cores); 52005491d2cSKalle Valo return &core->pub; 52105491d2cSKalle Valo } 52205491d2cSKalle Valo 52305491d2cSKalle Valo /* safety check for chipinfo */ 52405491d2cSKalle Valo static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) 52505491d2cSKalle Valo { 52605491d2cSKalle Valo struct brcmf_core_priv *core; 52705491d2cSKalle Valo bool need_socram = false; 52805491d2cSKalle Valo bool has_socram = false; 52905491d2cSKalle Valo bool cpu_found = false; 53005491d2cSKalle Valo int idx = 1; 53105491d2cSKalle Valo 53205491d2cSKalle Valo list_for_each_entry(core, &ci->cores, list) { 5338e73facbSArend van Spriel brcmf_dbg(INFO, " [%-2d] core 0x%x:%-3d base 0x%08x wrap 0x%08x\n", 53405491d2cSKalle Valo idx++, core->pub.id, core->pub.rev, core->pub.base, 53505491d2cSKalle Valo core->wrapbase); 53605491d2cSKalle Valo 53705491d2cSKalle Valo switch (core->pub.id) { 53805491d2cSKalle Valo case BCMA_CORE_ARM_CM3: 53905491d2cSKalle Valo cpu_found = true; 54005491d2cSKalle Valo need_socram = true; 54105491d2cSKalle Valo break; 54205491d2cSKalle Valo case BCMA_CORE_INTERNAL_MEM: 54305491d2cSKalle Valo has_socram = true; 54405491d2cSKalle Valo break; 54505491d2cSKalle Valo case BCMA_CORE_ARM_CR4: 54605491d2cSKalle Valo cpu_found = true; 54705491d2cSKalle Valo break; 54805491d2cSKalle Valo case BCMA_CORE_ARM_CA7: 54905491d2cSKalle Valo cpu_found = true; 55005491d2cSKalle Valo break; 55105491d2cSKalle Valo default: 55205491d2cSKalle Valo break; 55305491d2cSKalle Valo } 55405491d2cSKalle Valo } 55505491d2cSKalle Valo 55605491d2cSKalle Valo if (!cpu_found) { 55705491d2cSKalle Valo brcmf_err("CPU core not detected\n"); 55805491d2cSKalle Valo return -ENXIO; 55905491d2cSKalle Valo } 56005491d2cSKalle Valo /* check RAM core presence for ARM CM3 core */ 56105491d2cSKalle Valo if (need_socram && !has_socram) { 56205491d2cSKalle Valo brcmf_err("RAM core not provided with ARM CM3 core\n"); 56305491d2cSKalle Valo return -ENODEV; 56405491d2cSKalle Valo } 56505491d2cSKalle Valo return 0; 56605491d2cSKalle Valo } 56705491d2cSKalle Valo 56805491d2cSKalle Valo static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg) 56905491d2cSKalle Valo { 57005491d2cSKalle Valo return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg); 57105491d2cSKalle Valo } 57205491d2cSKalle Valo 57305491d2cSKalle Valo static void brcmf_chip_core_write32(struct brcmf_core_priv *core, 57405491d2cSKalle Valo u16 reg, u32 val) 57505491d2cSKalle Valo { 57605491d2cSKalle Valo core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val); 57705491d2cSKalle Valo } 57805491d2cSKalle Valo 57905491d2cSKalle Valo static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx, 58005491d2cSKalle Valo u32 *banksize) 58105491d2cSKalle Valo { 58205491d2cSKalle Valo u32 bankinfo; 58305491d2cSKalle Valo u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 58405491d2cSKalle Valo 58505491d2cSKalle Valo bankidx |= idx; 58605491d2cSKalle Valo brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx); 58705491d2cSKalle Valo bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo)); 58805491d2cSKalle Valo *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1; 58905491d2cSKalle Valo *banksize *= SOCRAM_BANKINFO_SZBASE; 59005491d2cSKalle Valo return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK); 59105491d2cSKalle Valo } 59205491d2cSKalle Valo 59305491d2cSKalle Valo static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, 59405491d2cSKalle Valo u32 *srsize) 59505491d2cSKalle Valo { 59605491d2cSKalle Valo u32 coreinfo; 59705491d2cSKalle Valo uint nb, banksize, lss; 59805491d2cSKalle Valo bool retent; 59905491d2cSKalle Valo int i; 60005491d2cSKalle Valo 60105491d2cSKalle Valo *ramsize = 0; 60205491d2cSKalle Valo *srsize = 0; 60305491d2cSKalle Valo 60405491d2cSKalle Valo if (WARN_ON(sr->pub.rev < 4)) 60505491d2cSKalle Valo return; 60605491d2cSKalle Valo 60705491d2cSKalle Valo if (!brcmf_chip_iscoreup(&sr->pub)) 60805491d2cSKalle Valo brcmf_chip_resetcore(&sr->pub, 0, 0, 0); 60905491d2cSKalle Valo 61005491d2cSKalle Valo /* Get info for determining size */ 61105491d2cSKalle Valo coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo)); 61205491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 61305491d2cSKalle Valo 61405491d2cSKalle Valo if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) { 61505491d2cSKalle Valo banksize = (coreinfo & SRCI_SRBSZ_MASK); 61605491d2cSKalle Valo lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 61705491d2cSKalle Valo if (lss != 0) 61805491d2cSKalle Valo nb--; 61905491d2cSKalle Valo *ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); 62005491d2cSKalle Valo if (lss != 0) 62105491d2cSKalle Valo *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 62205491d2cSKalle Valo } else { 62335cb51b2SChi-Hsien Lin /* length of SRAM Banks increased for corerev greater than 23 */ 62435cb51b2SChi-Hsien Lin if (sr->pub.rev >= 23) { 62535cb51b2SChi-Hsien Lin nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT)) 62635cb51b2SChi-Hsien Lin >> SRCI_SRNB_SHIFT; 62735cb51b2SChi-Hsien Lin } else { 62805491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 62935cb51b2SChi-Hsien Lin } 63005491d2cSKalle Valo for (i = 0; i < nb; i++) { 63105491d2cSKalle Valo retent = brcmf_chip_socram_banksize(sr, i, &banksize); 63205491d2cSKalle Valo *ramsize += banksize; 63305491d2cSKalle Valo if (retent) 63405491d2cSKalle Valo *srsize += banksize; 63505491d2cSKalle Valo } 63605491d2cSKalle Valo } 63705491d2cSKalle Valo 63805491d2cSKalle Valo /* hardcoded save&restore memory sizes */ 63905491d2cSKalle Valo switch (sr->chip->pub.chip) { 64005491d2cSKalle Valo case BRCM_CC_4334_CHIP_ID: 64105491d2cSKalle Valo if (sr->chip->pub.chiprev < 2) 64205491d2cSKalle Valo *srsize = (32 * 1024); 64305491d2cSKalle Valo break; 64405491d2cSKalle Valo case BRCM_CC_43430_CHIP_ID: 645be376df7SMarek Vasut case CY_CC_43439_CHIP_ID: 64605491d2cSKalle Valo /* assume sr for now as we can not check 64705491d2cSKalle Valo * firmware sr capability at this point. 64805491d2cSKalle Valo */ 64905491d2cSKalle Valo *srsize = (64 * 1024); 65005491d2cSKalle Valo break; 65105491d2cSKalle Valo default: 65205491d2cSKalle Valo break; 65305491d2cSKalle Valo } 65405491d2cSKalle Valo } 65505491d2cSKalle Valo 65605491d2cSKalle Valo /** Return the SYS MEM size */ 65705491d2cSKalle Valo static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) 65805491d2cSKalle Valo { 65905491d2cSKalle Valo u32 memsize = 0; 66005491d2cSKalle Valo u32 coreinfo; 66105491d2cSKalle Valo u32 idx; 66205491d2cSKalle Valo u32 nb; 66305491d2cSKalle Valo u32 banksize; 66405491d2cSKalle Valo 66505491d2cSKalle Valo if (!brcmf_chip_iscoreup(&sysmem->pub)) 66605491d2cSKalle Valo brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0); 66705491d2cSKalle Valo 66805491d2cSKalle Valo coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo)); 66905491d2cSKalle Valo nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 67005491d2cSKalle Valo 67105491d2cSKalle Valo for (idx = 0; idx < nb; idx++) { 67205491d2cSKalle Valo brcmf_chip_socram_banksize(sysmem, idx, &banksize); 67305491d2cSKalle Valo memsize += banksize; 67405491d2cSKalle Valo } 67505491d2cSKalle Valo 67605491d2cSKalle Valo return memsize; 67705491d2cSKalle Valo } 67805491d2cSKalle Valo 67905491d2cSKalle Valo /** Return the TCM-RAM size of the ARMCR4 core. */ 68005491d2cSKalle Valo static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) 68105491d2cSKalle Valo { 68205491d2cSKalle Valo u32 corecap; 68305491d2cSKalle Valo u32 memsize = 0; 68405491d2cSKalle Valo u32 nab; 68505491d2cSKalle Valo u32 nbb; 68605491d2cSKalle Valo u32 totb; 68705491d2cSKalle Valo u32 bxinfo; 688098e0b10SHector Martin u32 blksize; 68905491d2cSKalle Valo u32 idx; 69005491d2cSKalle Valo 69105491d2cSKalle Valo corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); 69205491d2cSKalle Valo 69305491d2cSKalle Valo nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; 69405491d2cSKalle Valo nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; 69505491d2cSKalle Valo totb = nab + nbb; 69605491d2cSKalle Valo 69705491d2cSKalle Valo for (idx = 0; idx < totb; idx++) { 69805491d2cSKalle Valo brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); 69905491d2cSKalle Valo bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); 700098e0b10SHector Martin blksize = ARMCR4_BSZ_MULT; 701098e0b10SHector Martin if (bxinfo & ARMCR4_BLK_1K_MASK) 702098e0b10SHector Martin blksize >>= 3; 703098e0b10SHector Martin 704098e0b10SHector Martin memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize; 70505491d2cSKalle Valo } 70605491d2cSKalle Valo 70705491d2cSKalle Valo return memsize; 70805491d2cSKalle Valo } 70905491d2cSKalle Valo 71005491d2cSKalle Valo static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) 71105491d2cSKalle Valo { 71205491d2cSKalle Valo switch (ci->pub.chip) { 71305491d2cSKalle Valo case BRCM_CC_4345_CHIP_ID: 714ed26edf7SZhao, Jiaqing case BRCM_CC_43454_CHIP_ID: 71505491d2cSKalle Valo return 0x198000; 71605491d2cSKalle Valo case BRCM_CC_4335_CHIP_ID: 71705491d2cSKalle Valo case BRCM_CC_4339_CHIP_ID: 71805491d2cSKalle Valo case BRCM_CC_4350_CHIP_ID: 71905491d2cSKalle Valo case BRCM_CC_4354_CHIP_ID: 72005491d2cSKalle Valo case BRCM_CC_4356_CHIP_ID: 72105491d2cSKalle Valo case BRCM_CC_43567_CHIP_ID: 72205491d2cSKalle Valo case BRCM_CC_43569_CHIP_ID: 72305491d2cSKalle Valo case BRCM_CC_43570_CHIP_ID: 72405491d2cSKalle Valo case BRCM_CC_4358_CHIP_ID: 72505491d2cSKalle Valo case BRCM_CC_43602_CHIP_ID: 72605491d2cSKalle Valo case BRCM_CC_4371_CHIP_ID: 72705491d2cSKalle Valo return 0x180000; 72843819926SHante Meuleman case BRCM_CC_43465_CHIP_ID: 72943819926SHante Meuleman case BRCM_CC_43525_CHIP_ID: 73005491d2cSKalle Valo case BRCM_CC_4365_CHIP_ID: 73105491d2cSKalle Valo case BRCM_CC_4366_CHIP_ID: 7321f589e25SDan Haab case BRCM_CC_43664_CHIP_ID: 733f4add103SRafał Miłecki case BRCM_CC_43666_CHIP_ID: 73405491d2cSKalle Valo return 0x200000; 73554f01f56SHector Martin case BRCM_CC_4355_CHIP_ID: 7366647274eSSoeren Moch case BRCM_CC_4359_CHIP_ID: 7376647274eSSoeren Moch return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; 73824f0bd13Sbrian m. carlson case BRCM_CC_4364_CHIP_ID: 7390ec9eb90SChi-Hsien Lin case CY_CC_4373_CHIP_ID: 7400ec9eb90SChi-Hsien Lin return 0x160000; 741d2587c57SAngus Ainslie case CY_CC_43752_CHIP_ID: 742bf8bbd90SHector Martin case BRCM_CC_4377_CHIP_ID: 743d2587c57SAngus Ainslie return 0x170000; 744e8b80bf2SHector Martin case BRCM_CC_4378_CHIP_ID: 745e8b80bf2SHector Martin return 0x352000; 746*117ace40SHector Martin case BRCM_CC_4387_CHIP_ID: 747*117ace40SHector Martin return 0x740000; 74805491d2cSKalle Valo default: 74905491d2cSKalle Valo brcmf_err("unknown chip: %s\n", ci->pub.name); 75005491d2cSKalle Valo break; 75105491d2cSKalle Valo } 7522c4fa29eSArend van Spriel return INVALID_RAMBASE; 75305491d2cSKalle Valo } 75405491d2cSKalle Valo 75582f93cf4SRafał Miłecki int brcmf_chip_get_raminfo(struct brcmf_chip *pub) 75605491d2cSKalle Valo { 75782f93cf4SRafał Miłecki struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv, 75882f93cf4SRafał Miłecki pub); 75905491d2cSKalle Valo struct brcmf_core_priv *mem_core; 76005491d2cSKalle Valo struct brcmf_core *mem; 76105491d2cSKalle Valo 76205491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); 76305491d2cSKalle Valo if (mem) { 76405491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, pub); 76505491d2cSKalle Valo ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); 76605491d2cSKalle Valo ci->pub.rambase = brcmf_chip_tcm_rambase(ci); 7672c4fa29eSArend van Spriel if (ci->pub.rambase == INVALID_RAMBASE) { 76805491d2cSKalle Valo brcmf_err("RAM base not provided with ARM CR4 core\n"); 76905491d2cSKalle Valo return -EINVAL; 77005491d2cSKalle Valo } 77105491d2cSKalle Valo } else { 77205491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM); 77305491d2cSKalle Valo if (mem) { 77405491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, 77505491d2cSKalle Valo pub); 77605491d2cSKalle Valo ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core); 77705491d2cSKalle Valo ci->pub.rambase = brcmf_chip_tcm_rambase(ci); 7782c4fa29eSArend van Spriel if (ci->pub.rambase == INVALID_RAMBASE) { 77905491d2cSKalle Valo brcmf_err("RAM base not provided with ARM CA7 core\n"); 78005491d2cSKalle Valo return -EINVAL; 78105491d2cSKalle Valo } 78205491d2cSKalle Valo } else { 78305491d2cSKalle Valo mem = brcmf_chip_get_core(&ci->pub, 78405491d2cSKalle Valo BCMA_CORE_INTERNAL_MEM); 78505491d2cSKalle Valo if (!mem) { 78605491d2cSKalle Valo brcmf_err("No memory cores found\n"); 78705491d2cSKalle Valo return -ENOMEM; 78805491d2cSKalle Valo } 78905491d2cSKalle Valo mem_core = container_of(mem, struct brcmf_core_priv, 79005491d2cSKalle Valo pub); 79105491d2cSKalle Valo brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, 79205491d2cSKalle Valo &ci->pub.srsize); 79305491d2cSKalle Valo } 79405491d2cSKalle Valo } 79505491d2cSKalle Valo brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", 79605491d2cSKalle Valo ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, 79705491d2cSKalle Valo ci->pub.srsize, ci->pub.srsize); 79805491d2cSKalle Valo 79905491d2cSKalle Valo if (!ci->pub.ramsize) { 80005491d2cSKalle Valo brcmf_err("RAM size is undetermined\n"); 80105491d2cSKalle Valo return -ENOMEM; 80205491d2cSKalle Valo } 80305491d2cSKalle Valo 80405491d2cSKalle Valo if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { 80505491d2cSKalle Valo brcmf_err("RAM size is incorrect\n"); 80605491d2cSKalle Valo return -ENOMEM; 80705491d2cSKalle Valo } 80805491d2cSKalle Valo 80905491d2cSKalle Valo return 0; 81005491d2cSKalle Valo } 81105491d2cSKalle Valo 81205491d2cSKalle Valo static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, 81305491d2cSKalle Valo u8 *type) 81405491d2cSKalle Valo { 81505491d2cSKalle Valo u32 val; 81605491d2cSKalle Valo 81705491d2cSKalle Valo /* read next descriptor */ 81805491d2cSKalle Valo val = ci->ops->read32(ci->ctx, *eromaddr); 81905491d2cSKalle Valo *eromaddr += 4; 82005491d2cSKalle Valo 82105491d2cSKalle Valo if (!type) 82205491d2cSKalle Valo return val; 82305491d2cSKalle Valo 82405491d2cSKalle Valo /* determine descriptor type */ 82505491d2cSKalle Valo *type = (val & DMP_DESC_TYPE_MSK); 82605491d2cSKalle Valo if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS) 82705491d2cSKalle Valo *type = DMP_DESC_ADDRESS; 82805491d2cSKalle Valo 82905491d2cSKalle Valo return val; 83005491d2cSKalle Valo } 83105491d2cSKalle Valo 83205491d2cSKalle Valo static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr, 83305491d2cSKalle Valo u32 *regbase, u32 *wrapbase) 83405491d2cSKalle Valo { 83505491d2cSKalle Valo u8 desc; 836b021a6bcSChi-Hsien Lin u32 val, szdesc; 83705491d2cSKalle Valo u8 stype, sztype, wraptype; 83805491d2cSKalle Valo 83905491d2cSKalle Valo *regbase = 0; 84005491d2cSKalle Valo *wrapbase = 0; 84105491d2cSKalle Valo 84205491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc); 84305491d2cSKalle Valo if (desc == DMP_DESC_MASTER_PORT) { 84405491d2cSKalle Valo wraptype = DMP_SLAVE_TYPE_MWRAP; 84505491d2cSKalle Valo } else if (desc == DMP_DESC_ADDRESS) { 84605491d2cSKalle Valo /* revert erom address */ 84705491d2cSKalle Valo *eromaddr -= 4; 84805491d2cSKalle Valo wraptype = DMP_SLAVE_TYPE_SWRAP; 84905491d2cSKalle Valo } else { 85005491d2cSKalle Valo *eromaddr -= 4; 85105491d2cSKalle Valo return -EILSEQ; 85205491d2cSKalle Valo } 85305491d2cSKalle Valo 85405491d2cSKalle Valo do { 85505491d2cSKalle Valo /* locate address descriptor */ 85605491d2cSKalle Valo do { 85705491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc); 85805491d2cSKalle Valo /* unexpected table end */ 85905491d2cSKalle Valo if (desc == DMP_DESC_EOT) { 86005491d2cSKalle Valo *eromaddr -= 4; 86105491d2cSKalle Valo return -EFAULT; 86205491d2cSKalle Valo } 863a4f4abd0SRafał Miłecki } while (desc != DMP_DESC_ADDRESS && 864a4f4abd0SRafał Miłecki desc != DMP_DESC_COMPONENT); 865a4f4abd0SRafał Miłecki 866a4f4abd0SRafał Miłecki /* stop if we crossed current component border */ 867a4f4abd0SRafał Miłecki if (desc == DMP_DESC_COMPONENT) { 868a4f4abd0SRafał Miłecki *eromaddr -= 4; 869a4f4abd0SRafał Miłecki return 0; 870a4f4abd0SRafał Miłecki } 87105491d2cSKalle Valo 87205491d2cSKalle Valo /* skip upper 32-bit address descriptor */ 87305491d2cSKalle Valo if (val & DMP_DESC_ADDRSIZE_GT32) 87405491d2cSKalle Valo brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 87505491d2cSKalle Valo 87605491d2cSKalle Valo sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S; 87705491d2cSKalle Valo 87805491d2cSKalle Valo /* next size descriptor can be skipped */ 87905491d2cSKalle Valo if (sztype == DMP_SLAVE_SIZE_DESC) { 880b021a6bcSChi-Hsien Lin szdesc = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 88105491d2cSKalle Valo /* skip upper size descriptor if present */ 882b021a6bcSChi-Hsien Lin if (szdesc & DMP_DESC_ADDRSIZE_GT32) 88305491d2cSKalle Valo brcmf_chip_dmp_get_desc(ci, eromaddr, NULL); 88405491d2cSKalle Valo } 88505491d2cSKalle Valo 886b021a6bcSChi-Hsien Lin /* look for 4K or 8K register regions */ 887b021a6bcSChi-Hsien Lin if (sztype != DMP_SLAVE_SIZE_4K && 888b021a6bcSChi-Hsien Lin sztype != DMP_SLAVE_SIZE_8K) 88905491d2cSKalle Valo continue; 89005491d2cSKalle Valo 89105491d2cSKalle Valo stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S; 89205491d2cSKalle Valo 89305491d2cSKalle Valo /* only regular slave and wrapper */ 89405491d2cSKalle Valo if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE) 89505491d2cSKalle Valo *regbase = val & DMP_SLAVE_ADDR_BASE; 89605491d2cSKalle Valo if (*wrapbase == 0 && stype == wraptype) 89705491d2cSKalle Valo *wrapbase = val & DMP_SLAVE_ADDR_BASE; 89805491d2cSKalle Valo } while (*regbase == 0 || *wrapbase == 0); 89905491d2cSKalle Valo 90005491d2cSKalle Valo return 0; 90105491d2cSKalle Valo } 90205491d2cSKalle Valo 90305491d2cSKalle Valo static 90405491d2cSKalle Valo int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) 90505491d2cSKalle Valo { 90605491d2cSKalle Valo struct brcmf_core *core; 90705491d2cSKalle Valo u32 eromaddr; 90805491d2cSKalle Valo u8 desc_type = 0; 90905491d2cSKalle Valo u32 val; 91005491d2cSKalle Valo u16 id; 9117af496b9Szhengbin u8 nmw, nsw, rev; 91205491d2cSKalle Valo u32 base, wrap; 91305491d2cSKalle Valo int err; 91405491d2cSKalle Valo 9151ce050c1SArend van Spriel eromaddr = ci->ops->read32(ci->ctx, 9161ce050c1SArend van Spriel CORE_CC_REG(ci->pub.enum_base, eromptr)); 91705491d2cSKalle Valo 91805491d2cSKalle Valo while (desc_type != DMP_DESC_EOT) { 91905491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); 92005491d2cSKalle Valo if (!(val & DMP_DESC_VALID)) 92105491d2cSKalle Valo continue; 92205491d2cSKalle Valo 92305491d2cSKalle Valo if (desc_type == DMP_DESC_EMPTY) 92405491d2cSKalle Valo continue; 92505491d2cSKalle Valo 92605491d2cSKalle Valo /* need a component descriptor */ 92705491d2cSKalle Valo if (desc_type != DMP_DESC_COMPONENT) 92805491d2cSKalle Valo continue; 92905491d2cSKalle Valo 93005491d2cSKalle Valo id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S; 93105491d2cSKalle Valo 93205491d2cSKalle Valo /* next descriptor must be component as well */ 93305491d2cSKalle Valo val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); 93405491d2cSKalle Valo if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT)) 93505491d2cSKalle Valo return -EFAULT; 93605491d2cSKalle Valo 93705491d2cSKalle Valo /* only look at cores with master port(s) */ 93805491d2cSKalle Valo nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S; 93905491d2cSKalle Valo nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S; 94005491d2cSKalle Valo rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S; 94105491d2cSKalle Valo 94205491d2cSKalle Valo /* need core with ports */ 94344977b81SRafał Miłecki if (nmw + nsw == 0 && 944b021a6bcSChi-Hsien Lin id != BCMA_CORE_PMU && 945b021a6bcSChi-Hsien Lin id != BCMA_CORE_GCI) 94605491d2cSKalle Valo continue; 94705491d2cSKalle Valo 94805491d2cSKalle Valo /* try to obtain register address info */ 94905491d2cSKalle Valo err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap); 95005491d2cSKalle Valo if (err) 95105491d2cSKalle Valo continue; 95205491d2cSKalle Valo 95305491d2cSKalle Valo /* finally a core to be added */ 95405491d2cSKalle Valo core = brcmf_chip_add_core(ci, id, base, wrap); 95505491d2cSKalle Valo if (IS_ERR(core)) 95605491d2cSKalle Valo return PTR_ERR(core); 95705491d2cSKalle Valo 95805491d2cSKalle Valo core->rev = rev; 95905491d2cSKalle Valo } 96005491d2cSKalle Valo 96105491d2cSKalle Valo return 0; 96205491d2cSKalle Valo } 96305491d2cSKalle Valo 9641ce050c1SArend van Spriel u32 brcmf_chip_enum_base(u16 devid) 9651ce050c1SArend van Spriel { 9661ce050c1SArend van Spriel return SI_ENUM_BASE_DEFAULT; 9671ce050c1SArend van Spriel } 9681ce050c1SArend van Spriel 96905491d2cSKalle Valo static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) 97005491d2cSKalle Valo { 97105491d2cSKalle Valo struct brcmf_core *core; 97205491d2cSKalle Valo u32 regdata; 97305491d2cSKalle Valo u32 socitype; 97405491d2cSKalle Valo int ret; 97505491d2cSKalle Valo 97605491d2cSKalle Valo /* Get CC core rev 97705491d2cSKalle Valo * Chipid is assume to be at offset 0 from SI_ENUM_BASE 97805491d2cSKalle Valo * For different chiptypes or old sdio hosts w/o chipcommon, 97905491d2cSKalle Valo * other ways of recognition should be added here. 98005491d2cSKalle Valo */ 9811ce050c1SArend van Spriel regdata = ci->ops->read32(ci->ctx, 9821ce050c1SArend van Spriel CORE_CC_REG(ci->pub.enum_base, chipid)); 98305491d2cSKalle Valo ci->pub.chip = regdata & CID_ID_MASK; 98405491d2cSKalle Valo ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; 98505491d2cSKalle Valo socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 98605491d2cSKalle Valo 987756a2b39SArend Van Spriel brcmf_chip_name(ci->pub.chip, ci->pub.chiprev, 988756a2b39SArend Van Spriel ci->pub.name, sizeof(ci->pub.name)); 989c88cfa07SArend Van Spriel brcmf_dbg(INFO, "found %s chip: %s\n", 990c88cfa07SArend Van Spriel socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name); 99105491d2cSKalle Valo 99205491d2cSKalle Valo if (socitype == SOCI_SB) { 99305491d2cSKalle Valo if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) { 99405491d2cSKalle Valo brcmf_err("SB chip is not supported\n"); 99505491d2cSKalle Valo return -ENODEV; 99605491d2cSKalle Valo } 99705491d2cSKalle Valo ci->iscoreup = brcmf_chip_sb_iscoreup; 99805491d2cSKalle Valo ci->coredisable = brcmf_chip_sb_coredisable; 99905491d2cSKalle Valo ci->resetcore = brcmf_chip_sb_resetcore; 100005491d2cSKalle Valo 100105491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON, 10021ce050c1SArend van Spriel SI_ENUM_BASE_DEFAULT, 0); 100305491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 100405491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV, 100505491d2cSKalle Valo BCM4329_CORE_BUS_BASE, 0); 100605491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 100705491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM, 100805491d2cSKalle Valo BCM4329_CORE_SOCRAM_BASE, 0); 100905491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 101005491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3, 101105491d2cSKalle Valo BCM4329_CORE_ARM_BASE, 0); 101205491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 101305491d2cSKalle Valo 101405491d2cSKalle Valo core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0); 101505491d2cSKalle Valo brcmf_chip_sb_corerev(ci, core); 101605491d2cSKalle Valo } else if (socitype == SOCI_AI) { 101705491d2cSKalle Valo ci->iscoreup = brcmf_chip_ai_iscoreup; 101805491d2cSKalle Valo ci->coredisable = brcmf_chip_ai_coredisable; 101905491d2cSKalle Valo ci->resetcore = brcmf_chip_ai_resetcore; 102005491d2cSKalle Valo 102105491d2cSKalle Valo brcmf_chip_dmp_erom_scan(ci); 102205491d2cSKalle Valo } else { 102305491d2cSKalle Valo brcmf_err("chip backplane type %u is not supported\n", 102405491d2cSKalle Valo socitype); 102505491d2cSKalle Valo return -ENODEV; 102605491d2cSKalle Valo } 102705491d2cSKalle Valo 102805491d2cSKalle Valo ret = brcmf_chip_cores_check(ci); 102905491d2cSKalle Valo if (ret) 103005491d2cSKalle Valo return ret; 103105491d2cSKalle Valo 103205491d2cSKalle Valo /* assure chip is passive for core access */ 103305491d2cSKalle Valo brcmf_chip_set_passive(&ci->pub); 103405491d2cSKalle Valo 103505491d2cSKalle Valo /* Call bus specific reset function now. Cores have been determined 103605491d2cSKalle Valo * but further access may require a chip specific reset at this point. 103705491d2cSKalle Valo */ 103805491d2cSKalle Valo if (ci->ops->reset) { 103905491d2cSKalle Valo ci->ops->reset(ci->ctx, &ci->pub); 104005491d2cSKalle Valo brcmf_chip_set_passive(&ci->pub); 104105491d2cSKalle Valo } 104205491d2cSKalle Valo 104382f93cf4SRafał Miłecki return brcmf_chip_get_raminfo(&ci->pub); 104405491d2cSKalle Valo } 104505491d2cSKalle Valo 104605491d2cSKalle Valo static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) 104705491d2cSKalle Valo { 104805491d2cSKalle Valo struct brcmf_core *core; 104905491d2cSKalle Valo struct brcmf_core_priv *cpu; 105005491d2cSKalle Valo u32 val; 105105491d2cSKalle Valo 105205491d2cSKalle Valo 105305491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, id); 105405491d2cSKalle Valo if (!core) 105505491d2cSKalle Valo return; 105605491d2cSKalle Valo 105705491d2cSKalle Valo switch (id) { 105805491d2cSKalle Valo case BCMA_CORE_ARM_CM3: 105905491d2cSKalle Valo brcmf_chip_coredisable(core, 0, 0); 106005491d2cSKalle Valo break; 106105491d2cSKalle Valo case BCMA_CORE_ARM_CR4: 106205491d2cSKalle Valo case BCMA_CORE_ARM_CA7: 106305491d2cSKalle Valo cpu = container_of(core, struct brcmf_core_priv, pub); 106405491d2cSKalle Valo 106505491d2cSKalle Valo /* clear all IOCTL bits except HALT bit */ 106605491d2cSKalle Valo val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL); 106705491d2cSKalle Valo val &= ARMCR4_BCMA_IOCTL_CPUHALT; 106805491d2cSKalle Valo brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT, 106905491d2cSKalle Valo ARMCR4_BCMA_IOCTL_CPUHALT); 107005491d2cSKalle Valo break; 107105491d2cSKalle Valo default: 107205491d2cSKalle Valo brcmf_err("unknown id: %u\n", id); 107305491d2cSKalle Valo break; 107405491d2cSKalle Valo } 107505491d2cSKalle Valo } 107605491d2cSKalle Valo 107705491d2cSKalle Valo static int brcmf_chip_setup(struct brcmf_chip_priv *chip) 107805491d2cSKalle Valo { 107905491d2cSKalle Valo struct brcmf_chip *pub; 108005491d2cSKalle Valo struct brcmf_core_priv *cc; 1081e2b397f1SRafał Miłecki struct brcmf_core *pmu; 108205491d2cSKalle Valo u32 base; 108305491d2cSKalle Valo u32 val; 108405491d2cSKalle Valo int ret = 0; 108505491d2cSKalle Valo 108605491d2cSKalle Valo pub = &chip->pub; 108705491d2cSKalle Valo cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list); 108805491d2cSKalle Valo base = cc->pub.base; 108905491d2cSKalle Valo 109005491d2cSKalle Valo /* get chipcommon capabilites */ 109105491d2cSKalle Valo pub->cc_caps = chip->ops->read32(chip->ctx, 109205491d2cSKalle Valo CORE_CC_REG(base, capabilities)); 10939befe919SRafał Miłecki pub->cc_caps_ext = chip->ops->read32(chip->ctx, 10949befe919SRafał Miłecki CORE_CC_REG(base, 10959befe919SRafał Miłecki capabilities_ext)); 109605491d2cSKalle Valo 109705491d2cSKalle Valo /* get pmu caps & rev */ 1098e2b397f1SRafał Miłecki pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */ 109905491d2cSKalle Valo if (pub->cc_caps & CC_CAP_PMU) { 110005491d2cSKalle Valo val = chip->ops->read32(chip->ctx, 1101e2b397f1SRafał Miłecki CORE_CC_REG(pmu->base, pmucapabilities)); 110205491d2cSKalle Valo pub->pmurev = val & PCAP_REV_MASK; 110305491d2cSKalle Valo pub->pmucaps = val; 110405491d2cSKalle Valo } 110505491d2cSKalle Valo 110605491d2cSKalle Valo brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n", 110705491d2cSKalle Valo cc->pub.rev, pub->pmurev, pub->pmucaps); 110805491d2cSKalle Valo 110905491d2cSKalle Valo /* execute bus core specific setup */ 111005491d2cSKalle Valo if (chip->ops->setup) 111105491d2cSKalle Valo ret = chip->ops->setup(chip->ctx, pub); 111205491d2cSKalle Valo 111305491d2cSKalle Valo return ret; 111405491d2cSKalle Valo } 111505491d2cSKalle Valo 11161ce050c1SArend van Spriel struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid, 111705491d2cSKalle Valo const struct brcmf_buscore_ops *ops) 111805491d2cSKalle Valo { 111905491d2cSKalle Valo struct brcmf_chip_priv *chip; 112005491d2cSKalle Valo int err = 0; 112105491d2cSKalle Valo 112205491d2cSKalle Valo if (WARN_ON(!ops->read32)) 112305491d2cSKalle Valo err = -EINVAL; 112405491d2cSKalle Valo if (WARN_ON(!ops->write32)) 112505491d2cSKalle Valo err = -EINVAL; 112605491d2cSKalle Valo if (WARN_ON(!ops->prepare)) 112705491d2cSKalle Valo err = -EINVAL; 112805491d2cSKalle Valo if (WARN_ON(!ops->activate)) 112905491d2cSKalle Valo err = -EINVAL; 113005491d2cSKalle Valo if (err < 0) 113105491d2cSKalle Valo return ERR_PTR(-EINVAL); 113205491d2cSKalle Valo 113305491d2cSKalle Valo chip = kzalloc(sizeof(*chip), GFP_KERNEL); 113405491d2cSKalle Valo if (!chip) 113505491d2cSKalle Valo return ERR_PTR(-ENOMEM); 113605491d2cSKalle Valo 113705491d2cSKalle Valo INIT_LIST_HEAD(&chip->cores); 113805491d2cSKalle Valo chip->num_cores = 0; 113905491d2cSKalle Valo chip->ops = ops; 114005491d2cSKalle Valo chip->ctx = ctx; 11411ce050c1SArend van Spriel chip->pub.enum_base = brcmf_chip_enum_base(devid); 114205491d2cSKalle Valo 114305491d2cSKalle Valo err = ops->prepare(ctx); 114405491d2cSKalle Valo if (err < 0) 114505491d2cSKalle Valo goto fail; 114605491d2cSKalle Valo 114705491d2cSKalle Valo err = brcmf_chip_recognition(chip); 114805491d2cSKalle Valo if (err < 0) 114905491d2cSKalle Valo goto fail; 115005491d2cSKalle Valo 115105491d2cSKalle Valo err = brcmf_chip_setup(chip); 115205491d2cSKalle Valo if (err < 0) 115305491d2cSKalle Valo goto fail; 115405491d2cSKalle Valo 115505491d2cSKalle Valo return &chip->pub; 115605491d2cSKalle Valo 115705491d2cSKalle Valo fail: 115805491d2cSKalle Valo brcmf_chip_detach(&chip->pub); 115905491d2cSKalle Valo return ERR_PTR(err); 116005491d2cSKalle Valo } 116105491d2cSKalle Valo 116205491d2cSKalle Valo void brcmf_chip_detach(struct brcmf_chip *pub) 116305491d2cSKalle Valo { 116405491d2cSKalle Valo struct brcmf_chip_priv *chip; 116505491d2cSKalle Valo struct brcmf_core_priv *core; 116605491d2cSKalle Valo struct brcmf_core_priv *tmp; 116705491d2cSKalle Valo 116805491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 116905491d2cSKalle Valo list_for_each_entry_safe(core, tmp, &chip->cores, list) { 117005491d2cSKalle Valo list_del(&core->list); 117105491d2cSKalle Valo kfree(core); 117205491d2cSKalle Valo } 117305491d2cSKalle Valo kfree(chip); 117405491d2cSKalle Valo } 117505491d2cSKalle Valo 11761b8d2e0aSWright Feng struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit) 11771b8d2e0aSWright Feng { 11781b8d2e0aSWright Feng struct brcmf_chip_priv *chip; 11791b8d2e0aSWright Feng struct brcmf_core_priv *core; 11801b8d2e0aSWright Feng 11811b8d2e0aSWright Feng chip = container_of(pub, struct brcmf_chip_priv, pub); 11821b8d2e0aSWright Feng list_for_each_entry(core, &chip->cores, list) { 11831b8d2e0aSWright Feng if (core->pub.id == BCMA_CORE_80211) { 11841b8d2e0aSWright Feng if (unit-- == 0) 11851b8d2e0aSWright Feng return &core->pub; 11861b8d2e0aSWright Feng } 11871b8d2e0aSWright Feng } 11881b8d2e0aSWright Feng return NULL; 11891b8d2e0aSWright Feng } 11901b8d2e0aSWright Feng 119105491d2cSKalle Valo struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid) 119205491d2cSKalle Valo { 119305491d2cSKalle Valo struct brcmf_chip_priv *chip; 119405491d2cSKalle Valo struct brcmf_core_priv *core; 119505491d2cSKalle Valo 119605491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 119705491d2cSKalle Valo list_for_each_entry(core, &chip->cores, list) 119805491d2cSKalle Valo if (core->pub.id == coreid) 119905491d2cSKalle Valo return &core->pub; 120005491d2cSKalle Valo 120105491d2cSKalle Valo return NULL; 120205491d2cSKalle Valo } 120305491d2cSKalle Valo 120405491d2cSKalle Valo struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub) 120505491d2cSKalle Valo { 120605491d2cSKalle Valo struct brcmf_chip_priv *chip; 120705491d2cSKalle Valo struct brcmf_core_priv *cc; 120805491d2cSKalle Valo 120905491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 121005491d2cSKalle Valo cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list); 121105491d2cSKalle Valo if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON)) 121205491d2cSKalle Valo return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON); 121305491d2cSKalle Valo return &cc->pub; 121405491d2cSKalle Valo } 121505491d2cSKalle Valo 1216e2b397f1SRafał Miłecki struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub) 1217e2b397f1SRafał Miłecki { 1218e2b397f1SRafał Miłecki struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub); 1219e2b397f1SRafał Miłecki struct brcmf_core *pmu; 1220e2b397f1SRafał Miłecki 1221e2b397f1SRafał Miłecki /* See if there is separated PMU core available */ 1222e2b397f1SRafał Miłecki if (cc->rev >= 35 && 1223e2b397f1SRafał Miłecki pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { 1224e2b397f1SRafał Miłecki pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); 1225e2b397f1SRafał Miłecki if (pmu) 1226e2b397f1SRafał Miłecki return pmu; 1227e2b397f1SRafał Miłecki } 1228e2b397f1SRafał Miłecki 1229e2b397f1SRafał Miłecki /* Fallback to ChipCommon core for older hardware */ 1230e2b397f1SRafał Miłecki return cc; 1231e2b397f1SRafał Miłecki } 1232e2b397f1SRafał Miłecki 123305491d2cSKalle Valo bool brcmf_chip_iscoreup(struct brcmf_core *pub) 123405491d2cSKalle Valo { 123505491d2cSKalle Valo struct brcmf_core_priv *core; 123605491d2cSKalle Valo 123705491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 123805491d2cSKalle Valo return core->chip->iscoreup(core); 123905491d2cSKalle Valo } 124005491d2cSKalle Valo 124105491d2cSKalle Valo void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset) 124205491d2cSKalle Valo { 124305491d2cSKalle Valo struct brcmf_core_priv *core; 124405491d2cSKalle Valo 124505491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 124605491d2cSKalle Valo core->chip->coredisable(core, prereset, reset); 124705491d2cSKalle Valo } 124805491d2cSKalle Valo 124905491d2cSKalle Valo void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset, 125005491d2cSKalle Valo u32 postreset) 125105491d2cSKalle Valo { 125205491d2cSKalle Valo struct brcmf_core_priv *core; 125305491d2cSKalle Valo 125405491d2cSKalle Valo core = container_of(pub, struct brcmf_core_priv, pub); 125505491d2cSKalle Valo core->chip->resetcore(core, prereset, reset, postreset); 125605491d2cSKalle Valo } 125705491d2cSKalle Valo 125805491d2cSKalle Valo static void 125905491d2cSKalle Valo brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) 126005491d2cSKalle Valo { 126105491d2cSKalle Valo struct brcmf_core *core; 126205491d2cSKalle Valo struct brcmf_core_priv *sr; 126305491d2cSKalle Valo 126405491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); 126505491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); 126605491d2cSKalle Valo brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | 126705491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 126805491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 126905491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 127005491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); 127105491d2cSKalle Valo brcmf_chip_resetcore(core, 0, 0, 0); 127205491d2cSKalle Valo 127305491d2cSKalle Valo /* disable bank #3 remap for this device */ 1274be376df7SMarek Vasut if (chip->pub.chip == BRCM_CC_43430_CHIP_ID || 1275be376df7SMarek Vasut chip->pub.chip == CY_CC_43439_CHIP_ID) { 127605491d2cSKalle Valo sr = container_of(core, struct brcmf_core_priv, pub); 127705491d2cSKalle Valo brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3); 127805491d2cSKalle Valo brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0); 127905491d2cSKalle Valo } 128005491d2cSKalle Valo } 128105491d2cSKalle Valo 128205491d2cSKalle Valo static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) 128305491d2cSKalle Valo { 128405491d2cSKalle Valo struct brcmf_core *core; 128505491d2cSKalle Valo 128605491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); 128705491d2cSKalle Valo if (!brcmf_chip_iscoreup(core)) { 128805491d2cSKalle Valo brcmf_err("SOCRAM core is down after reset?\n"); 128905491d2cSKalle Valo return false; 129005491d2cSKalle Valo } 129105491d2cSKalle Valo 129205491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, 0); 129305491d2cSKalle Valo 129405491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); 129505491d2cSKalle Valo brcmf_chip_resetcore(core, 0, 0, 0); 129605491d2cSKalle Valo 129705491d2cSKalle Valo return true; 129805491d2cSKalle Valo } 129905491d2cSKalle Valo 130005491d2cSKalle Valo static inline void 130105491d2cSKalle Valo brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) 130205491d2cSKalle Valo { 13033c7c07caSHector Martin int i; 130405491d2cSKalle Valo struct brcmf_core *core; 130505491d2cSKalle Valo 130605491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); 130705491d2cSKalle Valo 13083c7c07caSHector Martin /* Disable the cores only and let the firmware enable them. 13093c7c07caSHector Martin * Releasing reset ourselves breaks BCM4387 in weird ways. 13103c7c07caSHector Martin */ 13113c7c07caSHector Martin for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++) 13123c7c07caSHector Martin brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET | 131305491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 131405491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 131505491d2cSKalle Valo } 131605491d2cSKalle Valo 131705491d2cSKalle Valo static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) 131805491d2cSKalle Valo { 131905491d2cSKalle Valo struct brcmf_core *core; 132005491d2cSKalle Valo 132105491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, rstvec); 132205491d2cSKalle Valo 132305491d2cSKalle Valo /* restore ARM */ 132405491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); 132505491d2cSKalle Valo brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); 132605491d2cSKalle Valo 132705491d2cSKalle Valo return true; 132805491d2cSKalle Valo } 132905491d2cSKalle Valo 133005491d2cSKalle Valo static inline void 133105491d2cSKalle Valo brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip) 133205491d2cSKalle Valo { 133305491d2cSKalle Valo struct brcmf_core *core; 133405491d2cSKalle Valo 133505491d2cSKalle Valo brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7); 133605491d2cSKalle Valo 133705491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); 133805491d2cSKalle Valo brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | 133905491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 134005491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN, 134105491d2cSKalle Valo D11_BCMA_IOCTL_PHYCLOCKEN); 134205491d2cSKalle Valo } 134305491d2cSKalle Valo 134405491d2cSKalle Valo static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec) 134505491d2cSKalle Valo { 134605491d2cSKalle Valo struct brcmf_core *core; 134705491d2cSKalle Valo 134805491d2cSKalle Valo chip->ops->activate(chip->ctx, &chip->pub, rstvec); 134905491d2cSKalle Valo 135005491d2cSKalle Valo /* restore ARM */ 135105491d2cSKalle Valo core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7); 135205491d2cSKalle Valo brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); 135305491d2cSKalle Valo 135405491d2cSKalle Valo return true; 135505491d2cSKalle Valo } 135605491d2cSKalle Valo 135705491d2cSKalle Valo void brcmf_chip_set_passive(struct brcmf_chip *pub) 135805491d2cSKalle Valo { 135905491d2cSKalle Valo struct brcmf_chip_priv *chip; 136005491d2cSKalle Valo struct brcmf_core *arm; 136105491d2cSKalle Valo 136205491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 136305491d2cSKalle Valo 136405491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 136505491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); 136605491d2cSKalle Valo if (arm) { 136705491d2cSKalle Valo brcmf_chip_cr4_set_passive(chip); 136805491d2cSKalle Valo return; 136905491d2cSKalle Valo } 137005491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); 137105491d2cSKalle Valo if (arm) { 137205491d2cSKalle Valo brcmf_chip_ca7_set_passive(chip); 137305491d2cSKalle Valo return; 137405491d2cSKalle Valo } 137505491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); 137605491d2cSKalle Valo if (arm) { 137705491d2cSKalle Valo brcmf_chip_cm3_set_passive(chip); 137805491d2cSKalle Valo return; 137905491d2cSKalle Valo } 138005491d2cSKalle Valo } 138105491d2cSKalle Valo 138205491d2cSKalle Valo bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) 138305491d2cSKalle Valo { 138405491d2cSKalle Valo struct brcmf_chip_priv *chip; 138505491d2cSKalle Valo struct brcmf_core *arm; 138605491d2cSKalle Valo 138705491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 138805491d2cSKalle Valo 138905491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 139005491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); 139105491d2cSKalle Valo if (arm) 139205491d2cSKalle Valo return brcmf_chip_cr4_set_active(chip, rstvec); 139305491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); 139405491d2cSKalle Valo if (arm) 139505491d2cSKalle Valo return brcmf_chip_ca7_set_active(chip, rstvec); 139605491d2cSKalle Valo arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); 139705491d2cSKalle Valo if (arm) 139805491d2cSKalle Valo return brcmf_chip_cm3_set_active(chip); 139905491d2cSKalle Valo 140005491d2cSKalle Valo return false; 140105491d2cSKalle Valo } 140205491d2cSKalle Valo 140305491d2cSKalle Valo bool brcmf_chip_sr_capable(struct brcmf_chip *pub) 140405491d2cSKalle Valo { 140505491d2cSKalle Valo u32 base, addr, reg, pmu_cc3_mask = ~0; 140605491d2cSKalle Valo struct brcmf_chip_priv *chip; 1407e2b397f1SRafał Miłecki struct brcmf_core *pmu = brcmf_chip_get_pmu(pub); 140805491d2cSKalle Valo 140905491d2cSKalle Valo brcmf_dbg(TRACE, "Enter\n"); 141005491d2cSKalle Valo 141105491d2cSKalle Valo /* old chips with PMU version less than 17 don't support save restore */ 141205491d2cSKalle Valo if (pub->pmurev < 17) 141305491d2cSKalle Valo return false; 141405491d2cSKalle Valo 141505491d2cSKalle Valo base = brcmf_chip_get_chipcommon(pub)->base; 141605491d2cSKalle Valo chip = container_of(pub, struct brcmf_chip_priv, pub); 141705491d2cSKalle Valo 141805491d2cSKalle Valo switch (pub->chip) { 141905491d2cSKalle Valo case BRCM_CC_4354_CHIP_ID: 1420496aec57SChristian Daudt case BRCM_CC_4356_CHIP_ID: 1421e3720dadSDouble Lo case BRCM_CC_4345_CHIP_ID: 1422ed26edf7SZhao, Jiaqing case BRCM_CC_43454_CHIP_ID: 142305491d2cSKalle Valo /* explicitly check SR engine enable bit */ 142405491d2cSKalle Valo pmu_cc3_mask = BIT(2); 14250bde10dcSGustavo A. R. Silva fallthrough; 142605491d2cSKalle Valo case BRCM_CC_43241_CHIP_ID: 142705491d2cSKalle Valo case BRCM_CC_4335_CHIP_ID: 142805491d2cSKalle Valo case BRCM_CC_4339_CHIP_ID: 142905491d2cSKalle Valo /* read PMU chipcontrol register 3 */ 1430e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, chipcontrol_addr); 143105491d2cSKalle Valo chip->ops->write32(chip->ctx, addr, 3); 1432e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, chipcontrol_data); 143305491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 143405491d2cSKalle Valo return (reg & pmu_cc3_mask) != 0; 143505491d2cSKalle Valo case BRCM_CC_43430_CHIP_ID: 1436be376df7SMarek Vasut case CY_CC_43439_CHIP_ID: 143705491d2cSKalle Valo addr = CORE_CC_REG(base, sr_control1); 143805491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 143905491d2cSKalle Valo return reg != 0; 144054f01f56SHector Martin case BRCM_CC_4355_CHIP_ID: 14412f2d389eSChi-Hsien Lin case CY_CC_4373_CHIP_ID: 14422f2d389eSChi-Hsien Lin /* explicitly check SR engine enable bit */ 14432f2d389eSChi-Hsien Lin addr = CORE_CC_REG(base, sr_control0); 14442f2d389eSChi-Hsien Lin reg = chip->ops->read32(chip->ctx, addr); 14452f2d389eSChi-Hsien Lin return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; 1446d4aef159SSoeren Moch case BRCM_CC_4359_CHIP_ID: 1447d2587c57SAngus Ainslie case CY_CC_43752_CHIP_ID: 144835cb51b2SChi-Hsien Lin case CY_CC_43012_CHIP_ID: 144935cb51b2SChi-Hsien Lin addr = CORE_CC_REG(pmu->base, retention_ctl); 145035cb51b2SChi-Hsien Lin reg = chip->ops->read32(chip->ctx, addr); 145135cb51b2SChi-Hsien Lin return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | 145235cb51b2SChi-Hsien Lin PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; 145305491d2cSKalle Valo default: 1454e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, pmucapabilities_ext); 145505491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 145605491d2cSKalle Valo if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) 145705491d2cSKalle Valo return false; 145805491d2cSKalle Valo 1459e2b397f1SRafał Miłecki addr = CORE_CC_REG(pmu->base, retention_ctl); 146005491d2cSKalle Valo reg = chip->ops->read32(chip->ctx, addr); 146105491d2cSKalle Valo return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | 146205491d2cSKalle Valo PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; 146305491d2cSKalle Valo } 146405491d2cSKalle Valo } 1465