Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2010 Broadcom Corporation
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
0013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  *
0016  * File contents: support functions for PCI/PCIe
0017  */
0018 
0019 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0020 
0021 #include <linux/delay.h>
0022 
0023 #include <defs.h>
0024 #include <chipcommon.h>
0025 #include <brcmu_utils.h>
0026 #include <brcm_hw_ids.h>
0027 #include <soc.h>
0028 #include "types.h"
0029 #include "pub.h"
0030 #include "pmu.h"
0031 #include "aiutils.h"
0032 
0033 /* slow_clk_ctl */
0034  /* slow clock source mask */
0035 #define SCC_SS_MASK     0x00000007
0036  /* source of slow clock is LPO */
0037 #define SCC_SS_LPO      0x00000000
0038  /* source of slow clock is crystal */
0039 #define SCC_SS_XTAL     0x00000001
0040  /* source of slow clock is PCI */
0041 #define SCC_SS_PCI      0x00000002
0042  /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
0043 #define SCC_LF          0x00000200
0044  /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
0045 #define SCC_LP          0x00000400
0046  /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
0047 #define SCC_FS          0x00000800
0048  /* IgnorePllOffReq, 1/0:
0049   *  power logic ignores/honors PLL clock disable requests from core
0050   */
0051 #define SCC_IP          0x00001000
0052  /* XtalControlEn, 1/0:
0053   *  power logic does/doesn't disable crystal when appropriate
0054   */
0055 #define SCC_XC          0x00002000
0056  /* XtalPU (RO), 1/0: crystal running/disabled */
0057 #define SCC_XP          0x00004000
0058  /* ClockDivider (SlowClk = 1/(4+divisor)) */
0059 #define SCC_CD_MASK     0xffff0000
0060 #define SCC_CD_SHIFT        16
0061 
0062 /* system_clk_ctl */
0063  /* ILPen: Enable Idle Low Power */
0064 #define SYCC_IE         0x00000001
0065  /* ALPen: Enable Active Low Power */
0066 #define SYCC_AE         0x00000002
0067  /* ForcePLLOn */
0068 #define SYCC_FP         0x00000004
0069  /* Force ALP (or HT if ALPen is not set */
0070 #define SYCC_AR         0x00000008
0071  /* Force HT */
0072 #define SYCC_HR         0x00000010
0073  /* ClkDiv  (ILP = 1/(4 * (divisor + 1)) */
0074 #define SYCC_CD_MASK        0xffff0000
0075 #define SYCC_CD_SHIFT       16
0076 
0077 #define CST4329_SPROM_OTP_SEL_MASK  0x00000003
0078  /* OTP is powered up, use def. CIS, no SPROM */
0079 #define CST4329_DEFCIS_SEL      0
0080  /* OTP is powered up, SPROM is present */
0081 #define CST4329_SPROM_SEL       1
0082  /* OTP is powered up, no SPROM */
0083 #define CST4329_OTP_SEL         2
0084  /* OTP is powered down, SPROM is present */
0085 #define CST4329_OTP_PWRDN       3
0086 
0087 #define CST4329_SPI_SDIO_MODE_MASK  0x00000004
0088 #define CST4329_SPI_SDIO_MODE_SHIFT 2
0089 
0090 /* 43224 chip-specific ChipControl register bits */
0091 #define CCTRL43224_GPIO_TOGGLE          0x8000
0092  /* 12 mA drive strength */
0093 #define CCTRL_43224A0_12MA_LED_DRIVE    0x00F000F0
0094  /* 12 mA drive strength for later 43224s */
0095 #define CCTRL_43224B0_12MA_LED_DRIVE    0xF0
0096 
0097 /* 43236 Chip specific ChipStatus register bits */
0098 #define CST43236_SFLASH_MASK        0x00000040
0099 #define CST43236_OTP_MASK       0x00000080
0100 #define CST43236_HSIC_MASK      0x00000100  /* USB/HSIC */
0101 #define CST43236_BP_CLK         0x00000200  /* 120/96Mbps */
0102 #define CST43236_BOOT_MASK      0x00001800
0103 #define CST43236_BOOT_SHIFT     11
0104 #define CST43236_BOOT_FROM_SRAM     0 /* boot from SRAM, ARM in reset */
0105 #define CST43236_BOOT_FROM_ROM      1 /* boot from ROM */
0106 #define CST43236_BOOT_FROM_FLASH    2 /* boot from FLASH */
0107 #define CST43236_BOOT_FROM_INVALID  3
0108 
0109 /* 4331 chip-specific ChipControl register bits */
0110  /* 0 disable */
0111 #define CCTRL4331_BT_COEXIST        (1<<0)
0112  /* 0 SECI is disabled (JTAG functional) */
0113 #define CCTRL4331_SECI          (1<<1)
0114  /* 0 disable */
0115 #define CCTRL4331_EXT_LNA       (1<<2)
0116  /* sprom/gpio13-15 mux */
0117 #define CCTRL4331_SPROM_GPIO13_15       (1<<3)
0118  /* 0 ext pa disable, 1 ext pa enabled */
0119 #define CCTRL4331_EXTPA_EN      (1<<4)
0120  /* set drive out GPIO_CLK on sprom_cs pin */
0121 #define CCTRL4331_GPIOCLK_ON_SPROMCS    (1<<5)
0122  /* use sprom_cs pin as PCIE mdio interface */
0123 #define CCTRL4331_PCIE_MDIO_ON_SPROMCS  (1<<6)
0124  /* aband extpa will be at gpio2/5 and sprom_dout */
0125 #define CCTRL4331_EXTPA_ON_GPIO2_5  (1<<7)
0126  /* override core control on pipe_AuxClkEnable */
0127 #define CCTRL4331_OVR_PIPEAUXCLKEN  (1<<8)
0128  /* override core control on pipe_AuxPowerDown */
0129 #define CCTRL4331_OVR_PIPEAUXPWRDOWN    (1<<9)
0130  /* pcie_auxclkenable */
0131 #define CCTRL4331_PCIE_AUXCLKEN     (1<<10)
0132  /* pcie_pipe_pllpowerdown */
0133 #define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11)
0134  /* enable bt_shd0 at gpio4 */
0135 #define CCTRL4331_BT_SHD0_ON_GPIO4  (1<<16)
0136  /* enable bt_shd1 at gpio5 */
0137 #define CCTRL4331_BT_SHD1_ON_GPIO5  (1<<17)
0138 
0139 /* 4331 Chip specific ChipStatus register bits */
0140  /* crystal frequency 20/40Mhz */
0141 #define CST4331_XTAL_FREQ       0x00000001
0142 #define CST4331_SPROM_PRESENT       0x00000002
0143 #define CST4331_OTP_PRESENT     0x00000004
0144 #define CST4331_LDO_RF          0x00000008
0145 #define CST4331_LDO_PAR         0x00000010
0146 
0147 /* 4319 chip-specific ChipStatus register bits */
0148 #define CST4319_SPI_CPULESSUSB      0x00000001
0149 #define CST4319_SPI_CLK_POL     0x00000002
0150 #define CST4319_SPI_CLK_PH      0x00000008
0151  /* gpio [7:6], SDIO CIS selection */
0152 #define CST4319_SPROM_OTP_SEL_MASK  0x000000c0
0153 #define CST4319_SPROM_OTP_SEL_SHIFT 6
0154  /* use default CIS, OTP is powered up */
0155 #define CST4319_DEFCIS_SEL      0x00000000
0156  /* use SPROM, OTP is powered up */
0157 #define CST4319_SPROM_SEL       0x00000040
0158  /* use OTP, OTP is powered up */
0159 #define CST4319_OTP_SEL         0x00000080
0160  /* use SPROM, OTP is powered down */
0161 #define CST4319_OTP_PWRDN       0x000000c0
0162  /* gpio [8], sdio/usb mode */
0163 #define CST4319_SDIO_USB_MODE       0x00000100
0164 #define CST4319_REMAP_SEL_MASK      0x00000600
0165 #define CST4319_ILPDIV_EN       0x00000800
0166 #define CST4319_XTAL_PD_POL     0x00001000
0167 #define CST4319_LPO_SEL         0x00002000
0168 #define CST4319_RES_INIT_MODE       0x0000c000
0169  /* PALDO is configured with external PNP */
0170 #define CST4319_PALDO_EXTPNP        0x00010000
0171 #define CST4319_CBUCK_MODE_MASK     0x00060000
0172 #define CST4319_CBUCK_MODE_BURST    0x00020000
0173 #define CST4319_CBUCK_MODE_LPBURST  0x00060000
0174 #define CST4319_RCAL_VALID      0x01000000
0175 #define CST4319_RCAL_VALUE_MASK     0x3e000000
0176 #define CST4319_RCAL_VALUE_SHIFT    25
0177 
0178 /* 4336 chip-specific ChipStatus register bits */
0179 #define CST4336_SPI_MODE_MASK       0x00000001
0180 #define CST4336_SPROM_PRESENT       0x00000002
0181 #define CST4336_OTP_PRESENT     0x00000004
0182 #define CST4336_ARMREMAP_0      0x00000008
0183 #define CST4336_ILPDIV_EN_MASK      0x00000010
0184 #define CST4336_ILPDIV_EN_SHIFT     4
0185 #define CST4336_XTAL_PD_POL_MASK    0x00000020
0186 #define CST4336_XTAL_PD_POL_SHIFT   5
0187 #define CST4336_LPO_SEL_MASK        0x00000040
0188 #define CST4336_LPO_SEL_SHIFT       6
0189 #define CST4336_RES_INIT_MODE_MASK  0x00000180
0190 #define CST4336_RES_INIT_MODE_SHIFT 7
0191 #define CST4336_CBUCK_MODE_MASK     0x00000600
0192 #define CST4336_CBUCK_MODE_SHIFT    9
0193 
0194 /* 4313 chip-specific ChipStatus register bits */
0195 #define CST4313_SPROM_PRESENT           1
0196 #define CST4313_OTP_PRESENT         2
0197 #define CST4313_SPROM_OTP_SEL_MASK      0x00000002
0198 #define CST4313_SPROM_OTP_SEL_SHIFT     0
0199 
0200 /* 4313 Chip specific ChipControl register bits */
0201  /* 12 mA drive strengh for later 4313 */
0202 #define CCTRL_4313_12MA_LED_DRIVE    0x00000007
0203 
0204 /* Manufacturer Ids */
0205 #define MFGID_ARM       0x43b
0206 #define MFGID_BRCM      0x4bf
0207 #define MFGID_MIPS      0x4a7
0208 
0209 /* Enumeration ROM registers */
0210 #define ER_EROMENTRY        0x000
0211 #define ER_REMAPCONTROL     0xe00
0212 #define ER_REMAPSELECT      0xe04
0213 #define ER_MASTERSELECT     0xe10
0214 #define ER_ITCR         0xf00
0215 #define ER_ITIP         0xf04
0216 
0217 /* Erom entries */
0218 #define ER_TAG          0xe
0219 #define ER_TAG1         0x6
0220 #define ER_VALID        1
0221 #define ER_CI           0
0222 #define ER_MP           2
0223 #define ER_ADD          4
0224 #define ER_END          0xe
0225 #define ER_BAD          0xffffffff
0226 
0227 /* EROM CompIdentA */
0228 #define CIA_MFG_MASK        0xfff00000
0229 #define CIA_MFG_SHIFT       20
0230 #define CIA_CID_MASK        0x000fff00
0231 #define CIA_CID_SHIFT       8
0232 #define CIA_CCL_MASK        0x000000f0
0233 #define CIA_CCL_SHIFT       4
0234 
0235 /* EROM CompIdentB */
0236 #define CIB_REV_MASK        0xff000000
0237 #define CIB_REV_SHIFT       24
0238 #define CIB_NSW_MASK        0x00f80000
0239 #define CIB_NSW_SHIFT       19
0240 #define CIB_NMW_MASK        0x0007c000
0241 #define CIB_NMW_SHIFT       14
0242 #define CIB_NSP_MASK        0x00003e00
0243 #define CIB_NSP_SHIFT       9
0244 #define CIB_NMP_MASK        0x000001f0
0245 #define CIB_NMP_SHIFT       4
0246 
0247 /* EROM AddrDesc */
0248 #define AD_ADDR_MASK        0xfffff000
0249 #define AD_SP_MASK      0x00000f00
0250 #define AD_SP_SHIFT     8
0251 #define AD_ST_MASK      0x000000c0
0252 #define AD_ST_SHIFT     6
0253 #define AD_ST_SLAVE     0x00000000
0254 #define AD_ST_BRIDGE        0x00000040
0255 #define AD_ST_SWRAP     0x00000080
0256 #define AD_ST_MWRAP     0x000000c0
0257 #define AD_SZ_MASK      0x00000030
0258 #define AD_SZ_SHIFT     4
0259 #define AD_SZ_4K        0x00000000
0260 #define AD_SZ_8K        0x00000010
0261 #define AD_SZ_16K       0x00000020
0262 #define AD_SZ_SZD       0x00000030
0263 #define AD_AG32         0x00000008
0264 #define AD_ADDR_ALIGN       0x00000fff
0265 #define AD_SZ_BASE      0x00001000  /* 4KB */
0266 
0267 /* EROM SizeDesc */
0268 #define SD_SZ_MASK      0xfffff000
0269 #define SD_SG32         0x00000008
0270 #define SD_SZ_ALIGN     0x00000fff
0271 
0272 /* PCI config space bit 4 for 4306c0 slow clock source */
0273 #define PCI_CFG_GPIO_SCS    0x10
0274 /* PCI config space GPIO 14 for Xtal power-up */
0275 #define PCI_CFG_GPIO_XTAL   0x40
0276 /* PCI config space GPIO 15 for PLL power-down */
0277 #define PCI_CFG_GPIO_PLL    0x80
0278 
0279 /* power control defines */
0280 #define PLL_DELAY       150 /* us pll on delay */
0281 #define FREF_DELAY      200 /* us fref change delay */
0282 #define XTAL_ON_DELAY       1000    /* us crystal power-on delay */
0283 
0284 /* resetctrl */
0285 #define AIRC_RESET      1
0286 
0287 #define NOREV       -1  /* Invalid rev */
0288 
0289 /* GPIO Based LED powersave defines */
0290 #define DEFAULT_GPIO_ONTIME 10  /* Default: 10% on */
0291 #define DEFAULT_GPIO_OFFTIME    90  /* Default: 10% on */
0292 
0293 /* When Srom support present, fields in sromcontrol */
0294 #define SRC_START       0x80000000
0295 #define SRC_BUSY        0x80000000
0296 #define SRC_OPCODE      0x60000000
0297 #define SRC_OP_READ     0x00000000
0298 #define SRC_OP_WRITE        0x20000000
0299 #define SRC_OP_WRDIS        0x40000000
0300 #define SRC_OP_WREN     0x60000000
0301 #define SRC_OTPSEL      0x00000010
0302 #define SRC_LOCK        0x00000008
0303 #define SRC_SIZE_MASK       0x00000006
0304 #define SRC_SIZE_1K     0x00000000
0305 #define SRC_SIZE_4K     0x00000002
0306 #define SRC_SIZE_16K        0x00000004
0307 #define SRC_SIZE_SHIFT      1
0308 #define SRC_PRESENT     0x00000001
0309 
0310 /* External PA enable mask */
0311 #define GPIO_CTRL_EPA_EN_MASK 0x40
0312 
0313 #define DEFAULT_GPIOTIMERVAL \
0314     ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
0315 
0316 #define BADIDX      (SI_MAXCORES + 1)
0317 
0318 #define IS_SIM(chippkg) \
0319     ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
0320 
0321 #define GOODCOREADDR(x, b) \
0322     (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
0323         IS_ALIGNED((x), SI_CORE_SIZE))
0324 
0325 struct aidmp {
0326     u32 oobselina30;    /* 0x000 */
0327     u32 oobselina74;    /* 0x004 */
0328     u32 PAD[6];
0329     u32 oobselinb30;    /* 0x020 */
0330     u32 oobselinb74;    /* 0x024 */
0331     u32 PAD[6];
0332     u32 oobselinc30;    /* 0x040 */
0333     u32 oobselinc74;    /* 0x044 */
0334     u32 PAD[6];
0335     u32 oobselind30;    /* 0x060 */
0336     u32 oobselind74;    /* 0x064 */
0337     u32 PAD[38];
0338     u32 oobselouta30;   /* 0x100 */
0339     u32 oobselouta74;   /* 0x104 */
0340     u32 PAD[6];
0341     u32 oobseloutb30;   /* 0x120 */
0342     u32 oobseloutb74;   /* 0x124 */
0343     u32 PAD[6];
0344     u32 oobseloutc30;   /* 0x140 */
0345     u32 oobseloutc74;   /* 0x144 */
0346     u32 PAD[6];
0347     u32 oobseloutd30;   /* 0x160 */
0348     u32 oobseloutd74;   /* 0x164 */
0349     u32 PAD[38];
0350     u32 oobsynca;   /* 0x200 */
0351     u32 oobseloutaen;   /* 0x204 */
0352     u32 PAD[6];
0353     u32 oobsyncb;   /* 0x220 */
0354     u32 oobseloutben;   /* 0x224 */
0355     u32 PAD[6];
0356     u32 oobsyncc;   /* 0x240 */
0357     u32 oobseloutcen;   /* 0x244 */
0358     u32 PAD[6];
0359     u32 oobsyncd;   /* 0x260 */
0360     u32 oobseloutden;   /* 0x264 */
0361     u32 PAD[38];
0362     u32 oobaextwidth;   /* 0x300 */
0363     u32 oobainwidth;    /* 0x304 */
0364     u32 oobaoutwidth;   /* 0x308 */
0365     u32 PAD[5];
0366     u32 oobbextwidth;   /* 0x320 */
0367     u32 oobbinwidth;    /* 0x324 */
0368     u32 oobboutwidth;   /* 0x328 */
0369     u32 PAD[5];
0370     u32 oobcextwidth;   /* 0x340 */
0371     u32 oobcinwidth;    /* 0x344 */
0372     u32 oobcoutwidth;   /* 0x348 */
0373     u32 PAD[5];
0374     u32 oobdextwidth;   /* 0x360 */
0375     u32 oobdinwidth;    /* 0x364 */
0376     u32 oobdoutwidth;   /* 0x368 */
0377     u32 PAD[37];
0378     u32 ioctrlset;  /* 0x400 */
0379     u32 ioctrlclear;    /* 0x404 */
0380     u32 ioctrl;     /* 0x408 */
0381     u32 PAD[61];
0382     u32 iostatus;   /* 0x500 */
0383     u32 PAD[127];
0384     u32 ioctrlwidth;    /* 0x700 */
0385     u32 iostatuswidth;  /* 0x704 */
0386     u32 PAD[62];
0387     u32 resetctrl;  /* 0x800 */
0388     u32 resetstatus;    /* 0x804 */
0389     u32 resetreadid;    /* 0x808 */
0390     u32 resetwriteid;   /* 0x80c */
0391     u32 PAD[60];
0392     u32 errlogctrl; /* 0x900 */
0393     u32 errlogdone; /* 0x904 */
0394     u32 errlogstatus;   /* 0x908 */
0395     u32 errlogaddrlo;   /* 0x90c */
0396     u32 errlogaddrhi;   /* 0x910 */
0397     u32 errlogid;   /* 0x914 */
0398     u32 errloguser; /* 0x918 */
0399     u32 errlogflags;    /* 0x91c */
0400     u32 PAD[56];
0401     u32 intstatus;  /* 0xa00 */
0402     u32 PAD[127];
0403     u32 config;     /* 0xe00 */
0404     u32 PAD[63];
0405     u32 itcr;       /* 0xf00 */
0406     u32 PAD[3];
0407     u32 itipooba;   /* 0xf10 */
0408     u32 itipoobb;   /* 0xf14 */
0409     u32 itipoobc;   /* 0xf18 */
0410     u32 itipoobd;   /* 0xf1c */
0411     u32 PAD[4];
0412     u32 itipoobaout;    /* 0xf30 */
0413     u32 itipoobbout;    /* 0xf34 */
0414     u32 itipoobcout;    /* 0xf38 */
0415     u32 itipoobdout;    /* 0xf3c */
0416     u32 PAD[4];
0417     u32 itopooba;   /* 0xf50 */
0418     u32 itopoobb;   /* 0xf54 */
0419     u32 itopoobc;   /* 0xf58 */
0420     u32 itopoobd;   /* 0xf5c */
0421     u32 PAD[4];
0422     u32 itopoobain; /* 0xf70 */
0423     u32 itopoobbin; /* 0xf74 */
0424     u32 itopoobcin; /* 0xf78 */
0425     u32 itopoobdin; /* 0xf7c */
0426     u32 PAD[4];
0427     u32 itopreset;  /* 0xf90 */
0428     u32 PAD[15];
0429     u32 peripherialid4; /* 0xfd0 */
0430     u32 peripherialid5; /* 0xfd4 */
0431     u32 peripherialid6; /* 0xfd8 */
0432     u32 peripherialid7; /* 0xfdc */
0433     u32 peripherialid0; /* 0xfe0 */
0434     u32 peripherialid1; /* 0xfe4 */
0435     u32 peripherialid2; /* 0xfe8 */
0436     u32 peripherialid3; /* 0xfec */
0437     u32 componentid0;   /* 0xff0 */
0438     u32 componentid1;   /* 0xff4 */
0439     u32 componentid2;   /* 0xff8 */
0440     u32 componentid3;   /* 0xffc */
0441 };
0442 
0443 static bool
0444 ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
0445 {
0446     /* no cores found, bail out */
0447     if (cc->bus->nr_cores == 0)
0448         return false;
0449 
0450     /* get chipcommon rev */
0451     sii->pub.ccrev = cc->id.rev;
0452 
0453     /* get chipcommon chipstatus */
0454     sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
0455 
0456     /* get chipcommon capabilites */
0457     sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
0458 
0459     /* get pmu rev and caps */
0460     if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
0461         sii->pub.pmucaps = bcma_read32(cc,
0462                            CHIPCREGOFFS(pmucapabilities));
0463         sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
0464     }
0465 
0466     return true;
0467 }
0468 
0469 static struct si_info *ai_doattach(struct si_info *sii,
0470                    struct bcma_bus *pbus)
0471 {
0472     struct si_pub *sih = &sii->pub;
0473     struct bcma_device *cc;
0474 
0475     sii->icbus = pbus;
0476     sii->pcibus = pbus->host_pci;
0477 
0478     /* switch to Chipcommon core */
0479     cc = pbus->drv_cc.core;
0480 
0481     sih->chip = pbus->chipinfo.id;
0482     sih->chiprev = pbus->chipinfo.rev;
0483     sih->chippkg = pbus->chipinfo.pkg;
0484     sih->boardvendor = pbus->boardinfo.vendor;
0485     sih->boardtype = pbus->boardinfo.type;
0486 
0487     if (!ai_buscore_setup(sii, cc))
0488         goto exit;
0489 
0490     /* === NVRAM, clock is ready === */
0491     bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
0492     bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
0493 
0494     /* PMU specific initializations */
0495     if (ai_get_cccaps(sih) & CC_CAP_PMU) {
0496         (void)si_pmu_measure_alpclk(sih);
0497     }
0498 
0499     return sii;
0500 
0501  exit:
0502 
0503     return NULL;
0504 }
0505 
0506 /*
0507  * Allocate a si handle and do the attach.
0508  */
0509 struct si_pub *
0510 ai_attach(struct bcma_bus *pbus)
0511 {
0512     struct si_info *sii;
0513 
0514     /* alloc struct si_info */
0515     sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC);
0516     if (sii == NULL)
0517         return NULL;
0518 
0519     if (ai_doattach(sii, pbus) == NULL) {
0520         kfree(sii);
0521         return NULL;
0522     }
0523 
0524     return (struct si_pub *) sii;
0525 }
0526 
0527 /* may be called with core in reset */
0528 void ai_detach(struct si_pub *sih)
0529 {
0530     struct si_info *sii;
0531 
0532     sii = container_of(sih, struct si_info, pub);
0533 
0534     kfree(sii);
0535 }
0536 
0537 /*
0538  * read/modify chipcommon core register.
0539  */
0540 uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
0541 {
0542     struct bcma_device *cc;
0543     u32 w;
0544     struct si_info *sii;
0545 
0546     sii = container_of(sih, struct si_info, pub);
0547     cc = sii->icbus->drv_cc.core;
0548 
0549     /* mask and set */
0550     if (mask || val)
0551         bcma_maskset32(cc, regoff, ~mask, val);
0552 
0553     /* readback */
0554     w = bcma_read32(cc, regoff);
0555 
0556     return w;
0557 }
0558 
0559 /* return the slow clock source - LPO, XTAL, or PCI */
0560 static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
0561 {
0562     return SCC_SS_XTAL;
0563 }
0564 
0565 /*
0566 * return the ILP (slowclock) min or max frequency
0567 * precondition: we've established the chip has dynamic clk control
0568 */
0569 static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
0570                 struct bcma_device *cc)
0571 {
0572     uint div;
0573 
0574     /* Chipc rev 10 is InstaClock */
0575     div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
0576     div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
0577     return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
0578 }
0579 
0580 static void
0581 ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
0582 {
0583     uint slowmaxfreq, pll_delay, slowclk;
0584     uint pll_on_delay, fref_sel_delay;
0585 
0586     pll_delay = PLL_DELAY;
0587 
0588     /*
0589      * If the slow clock is not sourced by the xtal then
0590      * add the xtal_on_delay since the xtal will also be
0591      * powered down by dynamic clk control logic.
0592      */
0593 
0594     slowclk = ai_slowclk_src(sih, cc);
0595     if (slowclk != SCC_SS_XTAL)
0596         pll_delay += XTAL_ON_DELAY;
0597 
0598     /* Starting with 4318 it is ILP that is used for the delays */
0599     slowmaxfreq =
0600         ai_slowclk_freq(sih, false, cc);
0601 
0602     pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
0603     fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
0604 
0605     bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay);
0606     bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay);
0607 }
0608 
0609 /* initialize power control delay registers */
0610 void ai_clkctl_init(struct si_pub *sih)
0611 {
0612     struct si_info *sii = container_of(sih, struct si_info, pub);
0613     struct bcma_device *cc;
0614 
0615     if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
0616         return;
0617 
0618     cc = sii->icbus->drv_cc.core;
0619     if (cc == NULL)
0620         return;
0621 
0622     /* set all Instaclk chip ILP to 1 MHz */
0623     bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
0624                (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
0625 
0626     ai_clkctl_setdelay(sih, cc);
0627 }
0628 
0629 /*
0630  * return the value suitable for writing to the
0631  * dot11 core FAST_PWRUP_DELAY register
0632  */
0633 u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
0634 {
0635     struct si_info *sii;
0636     struct bcma_device *cc;
0637     uint slowminfreq;
0638     u16 fpdelay;
0639 
0640     sii = container_of(sih, struct si_info, pub);
0641     if (ai_get_cccaps(sih) & CC_CAP_PMU) {
0642         fpdelay = si_pmu_fast_pwrup_delay(sih);
0643         return fpdelay;
0644     }
0645 
0646     if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
0647         return 0;
0648 
0649     fpdelay = 0;
0650     cc = sii->icbus->drv_cc.core;
0651     if (cc) {
0652         slowminfreq = ai_slowclk_freq(sih, false, cc);
0653         fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
0654                 * 1000000) + (slowminfreq - 1)) / slowminfreq;
0655     }
0656     return fpdelay;
0657 }
0658 
0659 /*
0660  *  clock control policy function throught chipcommon
0661  *
0662  *    set dynamic clk control mode (forceslow, forcefast, dynamic)
0663  *    returns true if we are forcing fast clock
0664  *    this is a wrapper over the next internal function
0665  *      to allow flexible policy settings for outside caller
0666  */
0667 bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
0668 {
0669     struct si_info *sii;
0670     struct bcma_device *cc;
0671 
0672     sii = container_of(sih, struct si_info, pub);
0673 
0674     cc = sii->icbus->drv_cc.core;
0675     bcma_core_set_clockmode(cc, mode);
0676     return mode == BCMA_CLKMODE_FAST;
0677 }
0678 
0679 /* Enable BT-COEX & Ex-PA for 4313 */
0680 void ai_epa_4313war(struct si_pub *sih)
0681 {
0682     struct si_info *sii = container_of(sih, struct si_info, pub);
0683     struct bcma_device *cc;
0684 
0685     cc = sii->icbus->drv_cc.core;
0686 
0687     /* EPA Fix */
0688     bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
0689 }
0690 
0691 /* check if the device is removed */
0692 bool ai_deviceremoved(struct si_pub *sih)
0693 {
0694     u32 w = 0;
0695     struct si_info *sii;
0696 
0697     sii = container_of(sih, struct si_info, pub);
0698 
0699     if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
0700         return false;
0701 
0702     pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
0703     if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
0704         return true;
0705 
0706     return false;
0707 }