1 /* 2 * Broadcom specific AMBA 3 * ChipCommon Power Management Unit driver 4 * 5 * Copyright 2009, Michael Buesch <m@bues.ch> 6 * Copyright 2007, Broadcom Corporation 7 * 8 * Licensed under the GNU/GPL. See COPYING for details. 9 */ 10 11 #include "bcma_private.h" 12 #include <linux/bcma/bcma.h> 13 14 static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) 15 { 16 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 17 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 18 return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); 19 } 20 21 void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) 22 { 23 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 24 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 25 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); 26 } 27 EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); 28 29 void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 30 u32 set) 31 { 32 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 33 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 34 bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); 35 } 36 EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); 37 38 void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 39 u32 offset, u32 mask, u32 set) 40 { 41 bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); 42 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); 43 bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); 44 } 45 EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); 46 47 void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 48 u32 set) 49 { 50 bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); 51 bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); 52 bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); 53 } 54 EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); 55 56 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) 57 { 58 struct bcma_bus *bus = cc->core->bus; 59 60 switch (bus->chipinfo.id) { 61 case 0x4313: 62 case 0x4331: 63 case 43224: 64 case 43225: 65 break; 66 default: 67 pr_err("PLL init unknown for device 0x%04X\n", 68 bus->chipinfo.id); 69 } 70 } 71 72 static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 73 { 74 struct bcma_bus *bus = cc->core->bus; 75 u32 min_msk = 0, max_msk = 0; 76 77 switch (bus->chipinfo.id) { 78 case 0x4313: 79 min_msk = 0x200D; 80 max_msk = 0xFFFF; 81 break; 82 case 43224: 83 case 43225: 84 break; 85 default: 86 pr_err("PMU resource config unknown for device 0x%04X\n", 87 bus->chipinfo.id); 88 } 89 90 /* Set the resource masks. */ 91 if (min_msk) 92 bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); 93 if (max_msk) 94 bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); 95 } 96 97 void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) 98 { 99 struct bcma_bus *bus = cc->core->bus; 100 101 switch (bus->chipinfo.id) { 102 case 0x4313: 103 case 0x4331: 104 case 43224: 105 case 43225: 106 break; 107 default: 108 pr_err("PMU switch/regulators init unknown for device " 109 "0x%04X\n", bus->chipinfo.id); 110 } 111 } 112 113 /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ 114 void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) 115 { 116 struct bcma_bus *bus = cc->core->bus; 117 u32 val; 118 119 val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); 120 if (enable) { 121 val |= BCMA_CHIPCTL_4331_EXTPA_EN; 122 if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) 123 val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 124 } else { 125 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; 126 val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 127 } 128 bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); 129 } 130 131 void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 132 { 133 struct bcma_bus *bus = cc->core->bus; 134 135 switch (bus->chipinfo.id) { 136 case 0x4313: 137 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); 138 break; 139 case 0x4331: 140 /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ 141 break; 142 case 43224: 143 if (bus->chipinfo.rev == 0) { 144 pr_err("Workarounds for 43224 rev 0 not fully " 145 "implemented\n"); 146 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); 147 } else { 148 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); 149 } 150 break; 151 case 43225: 152 break; 153 default: 154 pr_err("Workarounds unknown for device 0x%04X\n", 155 bus->chipinfo.id); 156 } 157 } 158 159 void bcma_pmu_init(struct bcma_drv_cc *cc) 160 { 161 u32 pmucap; 162 163 pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); 164 cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); 165 166 pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, 167 pmucap); 168 169 if (cc->pmu.rev == 1) 170 bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, 171 ~BCMA_CC_PMU_CTL_NOILPONW); 172 else 173 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 174 BCMA_CC_PMU_CTL_NOILPONW); 175 176 if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) 177 pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); 178 179 bcma_pmu_pll_init(cc); 180 bcma_pmu_resources_init(cc); 181 bcma_pmu_swreg_init(cc); 182 bcma_pmu_workarounds(cc); 183 } 184 185 u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc) 186 { 187 struct bcma_bus *bus = cc->core->bus; 188 189 switch (bus->chipinfo.id) { 190 case 0x4716: 191 case 0x4748: 192 case 47162: 193 case 0x4313: 194 case 0x5357: 195 case 0x4749: 196 case 53572: 197 /* always 20Mhz */ 198 return 20000 * 1000; 199 case 0x5356: 200 case 0x5300: 201 /* always 25Mhz */ 202 return 25000 * 1000; 203 default: 204 pr_warn("No ALP clock specified for %04X device, " 205 "pmu rev. %d, using default %d Hz\n", 206 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); 207 } 208 return BCMA_CC_PMU_ALP_CLOCK; 209 } 210 211 /* Find the output of the "m" pll divider given pll controls that start with 212 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. 213 */ 214 static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) 215 { 216 u32 tmp, div, ndiv, p1, p2, fc; 217 struct bcma_bus *bus = cc->core->bus; 218 219 BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); 220 221 BUG_ON(!m || m > 4); 222 223 if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) { 224 /* Detect failure in clock setting */ 225 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 226 if (tmp & 0x40000) 227 return 133 * 1000000; 228 } 229 230 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); 231 p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; 232 p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; 233 234 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); 235 div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & 236 BCMA_CC_PPL_MDIV_MASK; 237 238 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); 239 ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; 240 241 /* Do calculation in Mhz */ 242 fc = bcma_pmu_alp_clock(cc) / 1000000; 243 fc = (p1 * ndiv * fc) / p2; 244 245 /* Return clock in Hertz */ 246 return (fc / div) * 1000000; 247 } 248 249 /* query bus clock frequency for PMU-enabled chipcommon */ 250 u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) 251 { 252 struct bcma_bus *bus = cc->core->bus; 253 254 switch (bus->chipinfo.id) { 255 case 0x4716: 256 case 0x4748: 257 case 47162: 258 return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 259 BCMA_CC_PMU5_MAINPLL_SSB); 260 case 0x5356: 261 return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 262 BCMA_CC_PMU5_MAINPLL_SSB); 263 case 0x5357: 264 case 0x4749: 265 return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 266 BCMA_CC_PMU5_MAINPLL_SSB); 267 case 0x5300: 268 return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, 269 BCMA_CC_PMU5_MAINPLL_SSB); 270 case 53572: 271 return 75000000; 272 default: 273 pr_warn("No backplane clock specified for %04X device, " 274 "pmu rev. %d, using default %d Hz\n", 275 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); 276 } 277 return BCMA_CC_PMU_HT_CLOCK; 278 } 279 280 /* query cpu clock frequency for PMU-enabled chipcommon */ 281 u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) 282 { 283 struct bcma_bus *bus = cc->core->bus; 284 285 if (bus->chipinfo.id == 53572) 286 return 300000000; 287 288 if (cc->pmu.rev >= 5) { 289 u32 pll; 290 switch (bus->chipinfo.id) { 291 case 0x5356: 292 pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 293 break; 294 case 0x5357: 295 case 0x4749: 296 pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 297 break; 298 default: 299 pll = BCMA_CC_PMU4716_MAINPLL_PLL0; 300 break; 301 } 302 303 /* TODO: if (bus->chipinfo.id == 0x5300) 304 return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */ 305 return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 306 } 307 308 return bcma_pmu_get_clockcontrol(cc); 309 } 310