Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcma: get CPU clock

Add method to return the clock of the CPU. This is needed by the arch
code to calculate the mips_hpt_frequency.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Hauke Mehrtens and committed by
John W. Linville
908debc8 e3afe0e5

+161
+1
drivers/bcma/bcma_private.h
··· 36 36 37 37 /* driver_chipcommon_pmu.c */ 38 38 u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc); 39 + u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc); 39 40 40 41 #ifdef CONFIG_BCMA_HOST_PCI 41 42 /* host_pci.c */
+107
drivers/bcma/driver_chipcommon_pmu.c
··· 11 11 #include "bcma_private.h" 12 12 #include <linux/bcma/bcma.h> 13 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 + 14 21 static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 15 22 u32 offset, u32 mask, u32 set) 16 23 { ··· 168 161 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); 169 162 } 170 163 return BCMA_CC_PMU_ALP_CLOCK; 164 + } 165 + 166 + /* Find the output of the "m" pll divider given pll controls that start with 167 + * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. 168 + */ 169 + static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) 170 + { 171 + u32 tmp, div, ndiv, p1, p2, fc; 172 + struct bcma_bus *bus = cc->core->bus; 173 + 174 + BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); 175 + 176 + BUG_ON(!m || m > 4); 177 + 178 + if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) { 179 + /* Detect failure in clock setting */ 180 + tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 181 + if (tmp & 0x40000) 182 + return 133 * 1000000; 183 + } 184 + 185 + tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); 186 + p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; 187 + p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; 188 + 189 + tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); 190 + div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & 191 + BCMA_CC_PPL_MDIV_MASK; 192 + 193 + tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); 194 + ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; 195 + 196 + /* Do calculation in Mhz */ 197 + fc = bcma_pmu_alp_clock(cc) / 1000000; 198 + fc = (p1 * ndiv * fc) / p2; 199 + 200 + /* Return clock in Hertz */ 201 + return (fc / div) * 1000000; 202 + } 203 + 204 + /* query bus clock frequency for PMU-enabled chipcommon */ 205 + u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) 206 + { 207 + struct bcma_bus *bus = cc->core->bus; 208 + 209 + switch (bus->chipinfo.id) { 210 + case 0x4716: 211 + case 0x4748: 212 + case 47162: 213 + return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 214 + BCMA_CC_PMU5_MAINPLL_SSB); 215 + case 0x5356: 216 + return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 217 + BCMA_CC_PMU5_MAINPLL_SSB); 218 + case 0x5357: 219 + case 0x4749: 220 + return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 221 + BCMA_CC_PMU5_MAINPLL_SSB); 222 + case 0x5300: 223 + return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, 224 + BCMA_CC_PMU5_MAINPLL_SSB); 225 + case 53572: 226 + return 75000000; 227 + default: 228 + pr_warn("No backplane clock specified for %04X device, " 229 + "pmu rev. %d, using default %d Hz\n", 230 + bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); 231 + } 232 + return BCMA_CC_PMU_HT_CLOCK; 233 + } 234 + 235 + /* query cpu clock frequency for PMU-enabled chipcommon */ 236 + u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) 237 + { 238 + struct bcma_bus *bus = cc->core->bus; 239 + 240 + if (bus->chipinfo.id == 53572) 241 + return 300000000; 242 + 243 + if (cc->pmu.rev >= 5) { 244 + u32 pll; 245 + switch (bus->chipinfo.id) { 246 + case 0x5356: 247 + pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 248 + break; 249 + case 0x5357: 250 + case 0x4749: 251 + pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 252 + break; 253 + default: 254 + pll = BCMA_CC_PMU4716_MAINPLL_PLL0; 255 + break; 256 + } 257 + 258 + /* TODO: if (bus->chipinfo.id == 0x5300) 259 + return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */ 260 + return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 261 + } 262 + 263 + return bcma_pmu_get_clockcontrol(cc); 171 264 }
+12
drivers/bcma/driver_mips.c
··· 166 166 } 167 167 } 168 168 169 + u32 bcma_cpu_clock(struct bcma_drv_mips *mcore) 170 + { 171 + struct bcma_bus *bus = mcore->core->bus; 172 + 173 + if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) 174 + return bcma_pmu_get_clockcpu(&bus->drv_cc); 175 + 176 + pr_err("No PMU available, need this to get the cpu clock\n"); 177 + return 0; 178 + } 179 + EXPORT_SYMBOL(bcma_cpu_clock); 180 + 169 181 static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) 170 182 { 171 183 struct bcma_bus *bus = mcore->core->bus;
+39
include/linux/bcma/bcma_driver_chipcommon.h
··· 241 241 #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ 242 242 #define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ 243 243 244 + /* Divider allocation in 4716/47162/5356 */ 245 + #define BCMA_CC_PMU5_MAINPLL_CPU 1 246 + #define BCMA_CC_PMU5_MAINPLL_MEM 2 247 + #define BCMA_CC_PMU5_MAINPLL_SSB 3 248 + 249 + /* PLL usage in 4716/47162 */ 250 + #define BCMA_CC_PMU4716_MAINPLL_PLL0 12 251 + 252 + /* PLL usage in 5356/5357 */ 253 + #define BCMA_CC_PMU5356_MAINPLL_PLL0 0 254 + #define BCMA_CC_PMU5357_MAINPLL_PLL0 0 255 + 256 + /* 4706 PMU */ 257 + #define BCMA_CC_PMU4706_MAINPLL_PLL0 0 258 + 244 259 /* ALP clock on pre-PMU chips */ 245 260 #define BCMA_CC_PMU_ALP_CLOCK 20000000 261 + /* HT clock for systems with PMU-enabled chipcommon */ 262 + #define BCMA_CC_PMU_HT_CLOCK 80000000 263 + 264 + /* PMU rev 5 (& 6) */ 265 + #define BCMA_CC_PPL_P1P2_OFF 0 266 + #define BCMA_CC_PPL_P1_MASK 0x0f000000 267 + #define BCMA_CC_PPL_P1_SHIFT 24 268 + #define BCMA_CC_PPL_P2_MASK 0x00f00000 269 + #define BCMA_CC_PPL_P2_SHIFT 20 270 + #define BCMA_CC_PPL_M14_OFF 1 271 + #define BCMA_CC_PPL_MDIV_MASK 0x000000ff 272 + #define BCMA_CC_PPL_MDIV_WIDTH 8 273 + #define BCMA_CC_PPL_NM5_OFF 2 274 + #define BCMA_CC_PPL_NDIV_MASK 0xfff00000 275 + #define BCMA_CC_PPL_NDIV_SHIFT 20 276 + #define BCMA_CC_PPL_FMAB_OFF 3 277 + #define BCMA_CC_PPL_MRAT_MASK 0xf0000000 278 + #define BCMA_CC_PPL_MRAT_SHIFT 28 279 + #define BCMA_CC_PPL_ABRAT_MASK 0x08000000 280 + #define BCMA_CC_PPL_ABRAT_SHIFT 27 281 + #define BCMA_CC_PPL_FDIV_MASK 0x07ffffff 282 + #define BCMA_CC_PPL_PLLCTL_OFF 4 283 + #define BCMA_CC_PPL_PCHI_OFF 5 284 + #define BCMA_CC_PPL_PCHI_MASK 0x0000003f 246 285 247 286 /* Data for the PMU, if available. 248 287 * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
+2
include/linux/bcma/bcma_driver_mips.h
··· 44 44 static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } 45 45 #endif 46 46 47 + extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); 48 + 47 49 extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); 48 50 49 51 #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */