Commit 908debc8da0d5a91418f71c6a462f62bd2ac69ef

Authored by Hauke Mehrtens
Committed by John W. Linville
1 parent e3afe0e5be

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>

Showing 5 changed files with 161 additions and 0 deletions Side-by-side Diff

drivers/bcma/bcma_private.h
... ... @@ -36,6 +36,7 @@
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 */
drivers/bcma/driver_chipcommon_pmu.c
... ... @@ -11,6 +11,13 @@
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 {
... ... @@ -161,5 +168,105 @@
161 168 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
162 169 }
163 170 return BCMA_CC_PMU_ALP_CLOCK;
  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);
164 271 }
drivers/bcma/driver_mips.c
... ... @@ -166,6 +166,18 @@
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;
include/linux/bcma/bcma_driver_chipcommon.h
... ... @@ -241,8 +241,47 @@
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)
include/linux/bcma/bcma_driver_mips.h
... ... @@ -44,6 +44,8 @@
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_ */