diff options
| author | Hauke Mehrtens <hauke@hauke-m.de> | 2011-07-22 19:20:11 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-08-08 14:29:29 -0400 |
| commit | 908debc8da0d5a91418f71c6a462f62bd2ac69ef (patch) | |
| tree | 886072e213b3a67650a53574be916ec105d15b61 | |
| parent | e3afe0e5be7576ac1282ea9fbbc9b352bb379227 (diff) | |
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>
| -rw-r--r-- | drivers/bcma/bcma_private.h | 1 | ||||
| -rw-r--r-- | drivers/bcma/driver_chipcommon_pmu.c | 107 | ||||
| -rw-r--r-- | drivers/bcma/driver_mips.c | 12 | ||||
| -rw-r--r-- | include/linux/bcma/bcma_driver_chipcommon.h | 39 | ||||
| -rw-r--r-- | include/linux/bcma/bcma_driver_mips.h | 2 |
5 files changed, 161 insertions, 0 deletions
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 22d3052e1906..30a3085d3354 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
| @@ -36,6 +36,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc); | |||
| 36 | 36 | ||
| 37 | /* driver_chipcommon_pmu.c */ | 37 | /* driver_chipcommon_pmu.c */ |
| 38 | u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc); | 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 | #ifdef CONFIG_BCMA_HOST_PCI | 41 | #ifdef CONFIG_BCMA_HOST_PCI |
| 41 | /* host_pci.c */ | 42 | /* host_pci.c */ |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 354caeea6397..5940c81e7e12 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
| @@ -11,6 +11,13 @@ | |||
| 11 | #include "bcma_private.h" | 11 | #include "bcma_private.h" |
| 12 | #include <linux/bcma/bcma.h> | 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 | static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | 21 | static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, |
| 15 | u32 offset, u32 mask, u32 set) | 22 | u32 offset, u32 mask, u32 set) |
| 16 | { | 23 | { |
| @@ -162,3 +169,103 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc) | |||
| 162 | } | 169 | } |
| 163 | return BCMA_CC_PMU_ALP_CLOCK; | 170 | return BCMA_CC_PMU_ALP_CLOCK; |
| 164 | } | 171 | } |
| 172 | |||
| 173 | /* Find the output of the "m" pll divider given pll controls that start with | ||
| 174 | * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. | ||
| 175 | */ | ||
| 176 | static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) | ||
| 177 | { | ||
| 178 | u32 tmp, div, ndiv, p1, p2, fc; | ||
| 179 | struct bcma_bus *bus = cc->core->bus; | ||
| 180 | |||
| 181 | BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); | ||
| 182 | |||
| 183 | BUG_ON(!m || m > 4); | ||
| 184 | |||
| 185 | if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) { | ||
| 186 | /* Detect failure in clock setting */ | ||
| 187 | tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | ||
| 188 | if (tmp & 0x40000) | ||
| 189 | return 133 * 1000000; | ||
| 190 | } | ||
| 191 | |||
| 192 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); | ||
| 193 | p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; | ||
| 194 | p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; | ||
| 195 | |||
| 196 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); | ||
| 197 | div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & | ||
| 198 | BCMA_CC_PPL_MDIV_MASK; | ||
| 199 | |||
| 200 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); | ||
| 201 | ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; | ||
| 202 | |||
| 203 | /* Do calculation in Mhz */ | ||
| 204 | fc = bcma_pmu_alp_clock(cc) / 1000000; | ||
| 205 | fc = (p1 * ndiv * fc) / p2; | ||
| 206 | |||
| 207 | /* Return clock in Hertz */ | ||
| 208 | return (fc / div) * 1000000; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* query bus clock frequency for PMU-enabled chipcommon */ | ||
| 212 | u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) | ||
| 213 | { | ||
| 214 | struct bcma_bus *bus = cc->core->bus; | ||
| 215 | |||
| 216 | switch (bus->chipinfo.id) { | ||
| 217 | case 0x4716: | ||
| 218 | case 0x4748: | ||
| 219 | case 47162: | ||
| 220 | return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, | ||
| 221 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
| 222 | case 0x5356: | ||
| 223 | return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, | ||
| 224 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
| 225 | case 0x5357: | ||
| 226 | case 0x4749: | ||
| 227 | return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, | ||
| 228 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
| 229 | case 0x5300: | ||
| 230 | return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, | ||
| 231 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
| 232 | case 53572: | ||
| 233 | return 75000000; | ||
| 234 | default: | ||
| 235 | pr_warn("No backplane clock specified for %04X device, " | ||
| 236 | "pmu rev. %d, using default %d Hz\n", | ||
| 237 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); | ||
| 238 | } | ||
| 239 | return BCMA_CC_PMU_HT_CLOCK; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* query cpu clock frequency for PMU-enabled chipcommon */ | ||
| 243 | u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) | ||
| 244 | { | ||
| 245 | struct bcma_bus *bus = cc->core->bus; | ||
| 246 | |||
| 247 | if (bus->chipinfo.id == 53572) | ||
| 248 | return 300000000; | ||
| 249 | |||
| 250 | if (cc->pmu.rev >= 5) { | ||
| 251 | u32 pll; | ||
| 252 | switch (bus->chipinfo.id) { | ||
| 253 | case 0x5356: | ||
| 254 | pll = BCMA_CC_PMU5356_MAINPLL_PLL0; | ||
| 255 | break; | ||
| 256 | case 0x5357: | ||
| 257 | case 0x4749: | ||
| 258 | pll = BCMA_CC_PMU5357_MAINPLL_PLL0; | ||
| 259 | break; | ||
| 260 | default: | ||
| 261 | pll = BCMA_CC_PMU4716_MAINPLL_PLL0; | ||
| 262 | break; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* TODO: if (bus->chipinfo.id == 0x5300) | ||
| 266 | return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */ | ||
| 267 | return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); | ||
| 268 | } | ||
| 269 | |||
| 270 | return bcma_pmu_get_clockcontrol(cc); | ||
| 271 | } | ||
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index b17233cb75c6..c3e9dff4224e 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c | |||
| @@ -166,6 +166,18 @@ static void bcma_core_mips_dump_irq(struct bcma_bus *bus) | |||
| 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 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) | 181 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) |
| 170 | { | 182 | { |
| 171 | struct bcma_bus *bus = mcore->core->bus; | 183 | struct bcma_bus *bus = mcore->core->bus; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index b9a930eb44cd..6083725dd22e 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
| @@ -241,8 +241,47 @@ | |||
| 241 | #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ | 241 | #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ |
| 242 | #define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ | 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 | /* ALP clock on pre-PMU chips */ | 259 | /* ALP clock on pre-PMU chips */ |
| 245 | #define BCMA_CC_PMU_ALP_CLOCK 20000000 | 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 | /* Data for the PMU, if available. | 286 | /* Data for the PMU, if available. |
| 248 | * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) | 287 | * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) |
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h index 82b3bfd32c76..c0043645cdcb 100644 --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h | |||
| @@ -44,6 +44,8 @@ extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); | |||
| 44 | static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } | 44 | static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); | ||
| 48 | |||
| 47 | extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); | 49 | extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); |
| 48 | 50 | ||
| 49 | #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ | 51 | #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ |
