From 79ee2bdad6118d7f40b1dfb9970648de83d0aff0 Mon Sep 17 00:00:00 2001 From: mb Date: Mon, 2 Feb 2009 20:00:04 +0000 Subject: [PATCH] bcm47xx: Implement 4312 and part of 4325 PLL init. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@14373 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../810-ssb-add-pmu-support.patch | 113 +++++++++++++++++- 1 file changed, 108 insertions(+), 5 deletions(-) diff --git a/target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch b/target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch index c5ee8f5c6..1c88b380c 100644 --- a/target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch +++ b/target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch @@ -13,8 +13,8 @@ Index: linux-2.6.28.2/drivers/ssb/Makefile Index: linux-2.6.28.2/drivers/ssb/driver_chipcommon_pmu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.28.2/drivers/ssb/driver_chipcommon_pmu.c 2009-02-01 21:16:15.000000000 +0100 -@@ -0,0 +1,378 @@ ++++ linux-2.6.28.2/drivers/ssb/driver_chipcommon_pmu.c 2009-02-02 20:57:13.000000000 +0100 +@@ -0,0 +1,481 @@ +/* + * Sonics Silicon Backplane + * Broadcom ChipCommon Power Management Unit driver @@ -176,11 +176,116 @@ Index: linux-2.6.28.2/drivers/ssb/driver_chipcommon_pmu.c + chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); +} + ++struct pmu1_plltab_entry { ++ u16 freq; /* Crystal frequency in kHz.*/ ++ u8 xf; /* Crystal frequency value for PMU control */ ++ u8 ndiv_int; ++ u32 ndiv_frac; ++ u8 p1div; ++ u8 p2div; ++}; ++ ++static const struct pmu1_plltab_entry pmu1_plltab[] = { ++ { .freq = 12000, .xf = 1, .p1div = 3, .p2div = 22, .ndiv_int = 0x9, .ndiv_frac = 0xFFFFEF, }, ++ { .freq = 13000, .xf = 2, .p1div = 1, .p2div = 6, .ndiv_int = 0xb, .ndiv_frac = 0x483483, }, ++ { .freq = 14400, .xf = 3, .p1div = 1, .p2div = 10, .ndiv_int = 0xa, .ndiv_frac = 0x1C71C7, }, ++ { .freq = 15360, .xf = 4, .p1div = 1, .p2div = 5, .ndiv_int = 0xb, .ndiv_frac = 0x755555, }, ++ { .freq = 16200, .xf = 5, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x6E9E06, }, ++ { .freq = 16800, .xf = 6, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x3CF3CF, }, ++ { .freq = 19200, .xf = 7, .p1div = 1, .p2div = 9, .ndiv_int = 0x5, .ndiv_frac = 0x17B425, }, ++ { .freq = 19800, .xf = 8, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0xA57EB, }, ++ { .freq = 20000, .xf = 9, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0, }, ++ { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int = 0xa, .ndiv_frac = 0, }, ++ { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int = 0xb, .ndiv_frac = 0, }, ++ { .freq = 26000, .xf = 12, .p1div = 1, .p2div = 2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, }, ++ { .freq = 30000, .xf = 13, .p1div = 3, .p2div = 8, .ndiv_int = 0xb, .ndiv_frac = 0, }, ++ { .freq = 38400, .xf = 14, .p1div = 1, .p2div = 5, .ndiv_int = 0x4, .ndiv_frac = 0x955555, }, ++ { .freq = 40000, .xf = 15, .p1div = 1, .p2div = 2, .ndiv_int = 0xb, .ndiv_frac = 0, }, ++}; ++ ++#define SSB_PMU1_DEFAULT_XTALFREQ 15360 ++ ++static const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq) ++{ ++ const struct pmu1_plltab_entry *e; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) { ++ e = &pmu1_plltab[i]; ++ if (e->freq == crystalfreq) ++ return e; ++ } ++ ++ return NULL; ++} ++ +/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ +static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, + u32 crystalfreq) +{ -+ WARN_ON(1); ++ struct ssb_bus *bus = cc->dev->bus; ++ const struct pmu1_plltab_entry *e = NULL; ++ u32 buffer_strength = 0; ++ u32 tmp, pllctl, pmuctl; ++ unsigned int i; ++ ++ if (bus->chip_id == 0x4312) { ++ /* We do not touch the BCM4312 PLL and assume ++ * the default crystal settings work out-of-the-box. */ ++ cc->pmu.crystalfreq = 20000; ++ return; ++ } ++ ++ if (crystalfreq) ++ e = pmu1_plltab_find_entry(crystalfreq); ++ if (!e) ++ e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ); ++ BUG_ON(!e); ++ crystalfreq = e->freq; ++ cc->pmu.crystalfreq = e->freq; ++ ++ /* Check if the PLL already is programmed to this frequency. */ ++ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); ++ if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { ++ /* We're already there... */ ++ return; ++ } ++ ++ ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", ++ (crystalfreq / 1000), (crystalfreq % 1000)); ++ ++WARN_ON(1); //TODO not fully implemented, yet. ++return; ++ /* First turn the PLL off. */ ++ switch (bus->chip_id) { ++ case 0x4325: ++ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ++ ~((1 << SSB_PLLRES_4325_BBPLL_PWRSW_PU) | ++ (1 << SSB_PLLRES_4325_HT_AVAIL))); ++ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, ++ ~((1 << SSB_PLLRES_4325_BBPLL_PWRSW_PU) | ++ (1 << SSB_PLLRES_4325_HT_AVAIL))); ++ /* Adjust the BBPLL to 2 on all channels later. */ ++ buffer_strength = 0x222222; ++ break; ++ default: ++ SSB_WARN_ON(1); ++ } ++ for (i = 1500; i; i--) { ++ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); ++ if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) ++ break; ++ udelay(10); ++ } ++ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); ++ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) ++ ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); ++ ++ /* Set p1div and p2div. */ ++ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); ++ //TODO ++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl); ++ + //TODO +} + @@ -370,8 +475,6 @@ Index: linux-2.6.28.2/drivers/ssb/driver_chipcommon_pmu.c + struct ssb_bus *bus = cc->dev->bus; + u32 pmucap; + -+if (bus->chip_id != 0x5354) return; //FIXME currently only 5354 code implemented. -+ + if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) + return; + -- 2.20.1