diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2009-11-29 12:09:42 +0000 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2009-11-29 12:09:42 +0000 |
commit | 6384a68295482b34bfe359b1dfd7d2bdecc8fd6c (patch) | |
tree | 4f3a81776b1b9457fa1da236b1cc1e2949544e1f /target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch | |
parent | 32e3529836aad24907fab8bf73250825fc8b233c (diff) | |
download | upstream-6384a68295482b34bfe359b1dfd7d2bdecc8fd6c.tar.gz upstream-6384a68295482b34bfe359b1dfd7d2bdecc8fd6c.tar.bz2 upstream-6384a68295482b34bfe359b1dfd7d2bdecc8fd6c.zip |
Remove patches already applied in generic and refresh patches.
This fixes #6200
SVN-Revision: 18597
Diffstat (limited to 'target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch | 823 |
1 files changed, 0 insertions, 823 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 deleted file mode 100644 index 7ab70aa54a..0000000000 --- a/target/linux/brcm47xx/patches-2.6.28/810-ssb-add-pmu-support.patch +++ /dev/null @@ -1,823 +0,0 @@ -Sent to mainline on 2009 Feb 03. - -For further modifications, please use separate patch files. This simpifies -keeping track of what is upstream and what is not. Thanks. - ---mb - - ---- a/drivers/ssb/Makefile -+++ b/drivers/ssb/Makefile -@@ -9,6 +9,7 @@ ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia. - - # built-in drivers - ssb-y += driver_chipcommon.o -+ssb-y += driver_chipcommon_pmu.o - ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o - ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o - ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o ---- /dev/null -+++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -0,0 +1,508 @@ -+/* -+ * Sonics Silicon Backplane -+ * Broadcom ChipCommon Power Management Unit driver -+ * -+ * Copyright 2009, Michael Buesch <mb@bu3sch.de> -+ * Copyright 2007, Broadcom Corporation -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include <linux/ssb/ssb.h> -+#include <linux/ssb/ssb_regs.h> -+#include <linux/ssb/ssb_driver_chipcommon.h> -+#include <linux/delay.h> -+ -+#include "ssb_private.h" -+ -+static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) -+{ -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); -+ return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA); -+} -+ -+static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, -+ u32 offset, u32 value) -+{ -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); -+} -+ -+struct pmu0_plltab_entry { -+ u16 freq; /* Crystal frequency in kHz.*/ -+ u8 xf; /* Crystal frequency value for PMU control */ -+ u8 wb_int; -+ u32 wb_frac; -+}; -+ -+static const struct pmu0_plltab_entry pmu0_plltab[] = { -+ { .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, }, -+ { .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, }, -+ { .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, }, -+ { .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, }, -+ { .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, }, -+ { .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, }, -+ { .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, }, -+ { .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, }, -+ { .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, }, -+ { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, }, -+ { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, }, -+ { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, }, -+ { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, }, -+ { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, }, -+}; -+#define SSB_PMU0_DEFAULT_XTALFREQ 20000 -+ -+static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq) -+{ -+ const struct pmu0_plltab_entry *e; -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) { -+ e = &pmu0_plltab[i]; -+ if (e->freq == crystalfreq) -+ return e; -+ } -+ -+ return NULL; -+} -+ -+/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ -+static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, -+ u32 crystalfreq) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ const struct pmu0_plltab_entry *e = NULL; -+ u32 pmuctl, tmp, pllctl; -+ unsigned int i; -+ -+ if ((bus->chip_id == 0x5354) && !crystalfreq) { -+ /* The 5354 crystal freq is 25MHz */ -+ crystalfreq = 25000; -+ } -+ if (crystalfreq) -+ e = pmu0_plltab_find_entry(crystalfreq); -+ if (!e) -+ e = pmu0_plltab_find_entry(SSB_PMU0_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)); -+ -+ /* First turn the PLL off. */ -+ switch (bus->chip_id) { -+ case 0x4328: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~(1 << SSB_PMURES_4328_BB_PLL_PU)); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~(1 << SSB_PMURES_4328_BB_PLL_PU)); -+ break; -+ case 0x5354: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~(1 << SSB_PMURES_5354_BB_PLL_PU)); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~(1 << SSB_PMURES_5354_BB_PLL_PU)); -+ 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 PDIV in PLL control 0. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); -+ if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ) -+ pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK; -+ else -+ pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl); -+ -+ /* Set WILD in PLL control 1. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1); -+ pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD; -+ pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK); -+ pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK; -+ pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK; -+ if (e->wb_frac == 0) -+ pllctl |= SSB_PMU0_PLLCTL1_STOPMOD; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl); -+ -+ /* Set WILD in PLL control 2. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2); -+ pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI; -+ pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl); -+ -+ /* Set the crystalfrequency and the divisor. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) -+ & SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ 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) -+{ -+ 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)); -+ -+ /* First turn the PLL off. */ -+ switch (bus->chip_id) { -+ case 0x4325: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_HT_AVAIL))); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | -+ (1 << SSB_PMURES_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); -+ pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV); -+ pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV; -+ pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl); -+ -+ /* Set ndiv int and ndiv mode */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2); -+ pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE); -+ pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT; -+ pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl); -+ -+ /* Set ndiv frac */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3); -+ pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC; -+ pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl); -+ -+ /* Change the drive strength, if required. */ -+ if (buffer_strength) { -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5); -+ pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV; -+ pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl); -+ } -+ -+ /* Tune the crystalfreq and the divisor. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ); -+ pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) -+ & SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); -+} -+ -+static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ -+ -+ if (bus->bustype == SSB_BUSTYPE_SSB) { -+ /* TODO: The user may override the crystal frequency. */ -+ } -+ -+ switch (bus->chip_id) { -+ case 0x4312: -+ case 0x4325: -+ ssb_pmu1_pllinit_r0(cc, crystalfreq); -+ break; -+ case 0x4328: -+ case 0x5354: -+ ssb_pmu0_pllinit_r0(cc, crystalfreq); -+ break; -+ default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PLL init unknown for device %04X\n", -+ bus->chip_id); -+ } -+} -+ -+struct pmu_res_updown_tab_entry { -+ u8 resource; /* The resource number */ -+ u16 updown; /* The updown value */ -+}; -+ -+enum pmu_res_depend_tab_task { -+ PMU_RES_DEP_SET = 1, -+ PMU_RES_DEP_ADD, -+ PMU_RES_DEP_REMOVE, -+}; -+ -+struct pmu_res_depend_tab_entry { -+ u8 resource; /* The resource number */ -+ u8 task; /* SET | ADD | REMOVE */ -+ u32 depend; /* The depend mask */ -+}; -+ -+static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = { -+ { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM, .updown = 0x1F01, }, -+ { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST, .updown = 0x010F, }, -+ { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_ILP_REQUEST, .updown = 0x0202, }, -+ { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_ROM_SWITCH, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_PA_REF_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_RADIO_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_AFE_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_PLL_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_BG_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_TX_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_RX_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_XTAL_PU, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_XTAL_EN, .updown = 0xA001, }, -+ { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_BB_PLL_PU, .updown = 0x0701, }, -+}; -+ -+static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = { -+ { -+ /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */ -+ .resource = SSB_PMURES_4328_ILP_REQUEST, -+ .task = PMU_RES_DEP_SET, -+ .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)), -+ }, -+}; -+ -+static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = { -+ { .resource = SSB_PMURES_4325_XTAL_PU, .updown = 0x1501, }, -+}; -+ -+static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = { -+ { -+ /* Adjust HT-Available dependencies. */ -+ .resource = SSB_PMURES_4325_HT_AVAIL, -+ .task = PMU_RES_DEP_ADD, -+ .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_TX_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_AFE_PWRSW_PU)), -+ }, -+}; -+ -+static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 min_msk = 0, max_msk = 0; -+ unsigned int i; -+ const struct pmu_res_updown_tab_entry *updown_tab = NULL; -+ unsigned int updown_tab_size; -+ const struct pmu_res_depend_tab_entry *depend_tab = NULL; -+ unsigned int depend_tab_size; -+ -+ switch (bus->chip_id) { -+ case 0x4312: -+ /* We keep the default settings: -+ * min_msk = 0xCBB -+ * max_msk = 0x7FFFF -+ */ -+ break; -+ case 0x4325: -+ /* Power OTP down later. */ -+ min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) | -+ (1 << SSB_PMURES_4325_LNLDO2_PU); -+ if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) & -+ SSB_CHIPCO_CHST_4325_PMUTOP_2B) -+ min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST); -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ updown_tab = pmu_res_updown_tab_4325a0; -+ updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0); -+ depend_tab = pmu_res_depend_tab_4325a0; -+ depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0); -+ break; -+ case 0x4328: -+ min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_XTAL_EN); -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ updown_tab = pmu_res_updown_tab_4328a0; -+ updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0); -+ depend_tab = pmu_res_depend_tab_4328a0; -+ depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0); -+ break; -+ case 0x5354: -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ break; -+ default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PMU resource config unknown for device %04X\n", -+ bus->chip_id); -+ } -+ -+ if (updown_tab) { -+ for (i = 0; i < updown_tab_size; i++) { -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, -+ updown_tab[i].resource); -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM, -+ updown_tab[i].updown); -+ } -+ } -+ if (depend_tab) { -+ for (i = 0; i < depend_tab_size; i++) { -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, -+ depend_tab[i].resource); -+ switch (depend_tab[i].task) { -+ case PMU_RES_DEP_SET: -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ depend_tab[i].depend); -+ break; -+ case PMU_RES_DEP_ADD: -+ chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ depend_tab[i].depend); -+ break; -+ case PMU_RES_DEP_REMOVE: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ ~(depend_tab[i].depend)); -+ break; -+ default: -+ SSB_WARN_ON(1); -+ } -+ } -+ } -+ -+ /* Set the resource masks. */ -+ if (min_msk) -+ chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk); -+ if (max_msk) -+ chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); -+} -+ -+void ssb_pmu_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 pmucap; -+ -+ if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) -+ return; -+ -+ pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); -+ cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); -+ -+ ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", -+ cc->pmu.rev, pmucap); -+ -+ if (cc->pmu.rev >= 1) { -+ if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) { -+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, -+ ~SSB_CHIPCO_PMU_CTL_NOILPONW); -+ } else { -+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, -+ SSB_CHIPCO_PMU_CTL_NOILPONW); -+ } -+ } -+ ssb_pmu_pll_init(cc); -+ ssb_pmu_resources_init(cc); -+} ---- a/drivers/ssb/driver_chipcommon.c -+++ b/drivers/ssb/driver_chipcommon.c -@@ -26,19 +26,6 @@ enum ssb_clksrc { - }; - - --static inline u32 chipco_read32(struct ssb_chipcommon *cc, -- u16 offset) --{ -- return ssb_read32(cc->dev, offset); --} -- --static inline void chipco_write32(struct ssb_chipcommon *cc, -- u16 offset, -- u32 value) --{ -- ssb_write32(cc->dev, offset, value); --} -- - static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, - u32 mask, u32 value) - { -@@ -246,6 +233,7 @@ void ssb_chipcommon_init(struct ssb_chip - { - if (!cc->dev) - return; /* We don't have a ChipCommon */ -+ ssb_pmu_init(cc); - chipco_powercontrol_init(cc); - ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); - calc_fast_powerup_delay(cc); ---- a/include/linux/ssb/ssb_driver_chipcommon.h -+++ b/include/linux/ssb/ssb_driver_chipcommon.h -@@ -181,6 +181,16 @@ - #define SSB_CHIPCO_PROG_WAITCNT 0x0124 - #define SSB_CHIPCO_FLASH_CFG 0x0128 - #define SSB_CHIPCO_FLASH_WAITCNT 0x012C -+#define SSB_CHIPCO_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ -+#define SSB_CHIPCO_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ -+#define SSB_CHIPCO_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ -+#define SSB_CHIPCO_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ -+#define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ -+#define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ -+#define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ -+#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ -+#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ -+#define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ - #define SSB_CHIPCO_UART0_DATA 0x0300 - #define SSB_CHIPCO_UART0_IMR 0x0304 - #define SSB_CHIPCO_UART0_FCR 0x0308 -@@ -197,6 +207,196 @@ - #define SSB_CHIPCO_UART1_LSR 0x0414 - #define SSB_CHIPCO_UART1_MSR 0x0418 - #define SSB_CHIPCO_UART1_SCRATCH 0x041C -+/* PMU registers (rev >= 20) */ -+#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ -+#define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ -+#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 -+#define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ -+#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ -+#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ -+#define SSB_CHIPCO_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */ -+#define SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT 2 -+#define SSB_CHIPCO_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */ -+#define SSB_CHIPCO_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */ -+#define SSB_CHIPCO_PMU_CAP 0x0604 /* PMU capabilities */ -+#define SSB_CHIPCO_PMU_CAP_REVISION 0x000000FF /* Revision mask */ -+#define SSB_CHIPCO_PMU_STAT 0x0608 /* PMU status */ -+#define SSB_CHIPCO_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ -+#define SSB_CHIPCO_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ -+#define SSB_CHIPCO_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ -+#define SSB_CHIPCO_PMU_STAT_HAVEHT 0x00000004 /* HT available */ -+#define SSB_CHIPCO_PMU_STAT_RESINIT 0x00000003 /* Res init */ -+#define SSB_CHIPCO_PMU_RES_STAT 0x060C /* PMU res status */ -+#define SSB_CHIPCO_PMU_RES_PEND 0x0610 /* PMU res pending */ -+#define SSB_CHIPCO_PMU_TIMER 0x0614 /* PMU timer */ -+#define SSB_CHIPCO_PMU_MINRES_MSK 0x0618 /* PMU min res mask */ -+#define SSB_CHIPCO_PMU_MAXRES_MSK 0x061C /* PMU max res mask */ -+#define SSB_CHIPCO_PMU_RES_TABSEL 0x0620 /* PMU res table sel */ -+#define SSB_CHIPCO_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */ -+#define SSB_CHIPCO_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */ -+#define SSB_CHIPCO_PMU_RES_TIMER 0x062C /* PMU res timer */ -+#define SSB_CHIPCO_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */ -+#define SSB_CHIPCO_PMU_WATCHDOG 0x0634 /* PMU watchdog */ -+#define SSB_CHIPCO_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ -+#define SSB_CHIPCO_PMU_RES_REQT 0x0644 /* PMU res req timer */ -+#define SSB_CHIPCO_PMU_RES_REQM 0x0648 /* PMU res req mask */ -+#define SSB_CHIPCO_CHIPCTL_ADDR 0x0650 -+#define SSB_CHIPCO_CHIPCTL_DATA 0x0654 -+#define SSB_CHIPCO_REGCTL_ADDR 0x0658 -+#define SSB_CHIPCO_REGCTL_DATA 0x065C -+#define SSB_CHIPCO_PLLCTL_ADDR 0x0660 -+#define SSB_CHIPCO_PLLCTL_DATA 0x0664 -+ -+ -+ -+/** PMU PLL registers */ -+ -+/* PMU rev 0 PLL registers */ -+#define SSB_PMU0_PLLCTL0 0 -+#define SSB_PMU0_PLLCTL0_PDIV_MSK 0x00000001 -+#define SSB_PMU0_PLLCTL0_PDIV_FREQ 25000 /* kHz */ -+#define SSB_PMU0_PLLCTL1 1 -+#define SSB_PMU0_PLLCTL1_WILD_IMSK 0xF0000000 /* Wild int mask (low nibble) */ -+#define SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT 28 -+#define SSB_PMU0_PLLCTL1_WILD_FMSK 0x0FFFFF00 /* Wild frac mask */ -+#define SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT 8 -+#define SSB_PMU0_PLLCTL1_STOPMOD 0x00000040 /* Stop mod */ -+#define SSB_PMU0_PLLCTL2 2 -+#define SSB_PMU0_PLLCTL2_WILD_IMSKHI 0x0000000F /* Wild int mask (high nibble) */ -+#define SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT 0 -+ -+/* PMU rev 1 PLL registers */ -+#define SSB_PMU1_PLLCTL0 0 -+#define SSB_PMU1_PLLCTL0_P1DIV 0x00F00000 /* P1 div */ -+#define SSB_PMU1_PLLCTL0_P1DIV_SHIFT 20 -+#define SSB_PMU1_PLLCTL0_P2DIV 0x0F000000 /* P2 div */ -+#define SSB_PMU1_PLLCTL0_P2DIV_SHIFT 24 -+#define SSB_PMU1_PLLCTL1 1 -+#define SSB_PMU1_PLLCTL1_M1DIV 0x000000FF /* M1 div */ -+#define SSB_PMU1_PLLCTL1_M1DIV_SHIFT 0 -+#define SSB_PMU1_PLLCTL1_M2DIV 0x0000FF00 /* M2 div */ -+#define SSB_PMU1_PLLCTL1_M2DIV_SHIFT 8 -+#define SSB_PMU1_PLLCTL1_M3DIV 0x00FF0000 /* M3 div */ -+#define SSB_PMU1_PLLCTL1_M3DIV_SHIFT 16 -+#define SSB_PMU1_PLLCTL1_M4DIV 0xFF000000 /* M4 div */ -+#define SSB_PMU1_PLLCTL1_M4DIV_SHIFT 24 -+#define SSB_PMU1_PLLCTL2 2 -+#define SSB_PMU1_PLLCTL2_M5DIV 0x000000FF /* M5 div */ -+#define SSB_PMU1_PLLCTL2_M5DIV_SHIFT 0 -+#define SSB_PMU1_PLLCTL2_M6DIV 0x0000FF00 /* M6 div */ -+#define SSB_PMU1_PLLCTL2_M6DIV_SHIFT 8 -+#define SSB_PMU1_PLLCTL2_NDIVMODE 0x000E0000 /* NDIV mode */ -+#define SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT 17 -+#define SSB_PMU1_PLLCTL2_NDIVINT 0x1FF00000 /* NDIV int */ -+#define SSB_PMU1_PLLCTL2_NDIVINT_SHIFT 20 -+#define SSB_PMU1_PLLCTL3 3 -+#define SSB_PMU1_PLLCTL3_NDIVFRAC 0x00FFFFFF /* NDIV frac */ -+#define SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT 0 -+#define SSB_PMU1_PLLCTL4 4 -+#define SSB_PMU1_PLLCTL5 5 -+#define SSB_PMU1_PLLCTL5_CLKDRV 0xFFFFFF00 /* clk drv */ -+#define SSB_PMU1_PLLCTL5_CLKDRV_SHIFT 8 -+ -+/* BCM4312 PLL resource numbers. */ -+#define SSB_PMURES_4312_SWITCHER_BURST 0 -+#define SSB_PMURES_4312_SWITCHER_PWM 1 -+#define SSB_PMURES_4312_PA_REF_LDO 2 -+#define SSB_PMURES_4312_CORE_LDO_BURST 3 -+#define SSB_PMURES_4312_CORE_LDO_PWM 4 -+#define SSB_PMURES_4312_RADIO_LDO 5 -+#define SSB_PMURES_4312_ILP_REQUEST 6 -+#define SSB_PMURES_4312_BG_FILTBYP 7 -+#define SSB_PMURES_4312_TX_FILTBYP 8 -+#define SSB_PMURES_4312_RX_FILTBYP 9 -+#define SSB_PMURES_4312_XTAL_PU 10 -+#define SSB_PMURES_4312_ALP_AVAIL 11 -+#define SSB_PMURES_4312_BB_PLL_FILTBYP 12 -+#define SSB_PMURES_4312_RF_PLL_FILTBYP 13 -+#define SSB_PMURES_4312_HT_AVAIL 14 -+ -+/* BCM4325 PLL resource numbers. */ -+#define SSB_PMURES_4325_BUCK_BOOST_BURST 0 -+#define SSB_PMURES_4325_CBUCK_BURST 1 -+#define SSB_PMURES_4325_CBUCK_PWM 2 -+#define SSB_PMURES_4325_CLDO_CBUCK_BURST 3 -+#define SSB_PMURES_4325_CLDO_CBUCK_PWM 4 -+#define SSB_PMURES_4325_BUCK_BOOST_PWM 5 -+#define SSB_PMURES_4325_ILP_REQUEST 6 -+#define SSB_PMURES_4325_ABUCK_BURST 7 -+#define SSB_PMURES_4325_ABUCK_PWM 8 -+#define SSB_PMURES_4325_LNLDO1_PU 9 -+#define SSB_PMURES_4325_LNLDO2_PU 10 -+#define SSB_PMURES_4325_LNLDO3_PU 11 -+#define SSB_PMURES_4325_LNLDO4_PU 12 -+#define SSB_PMURES_4325_XTAL_PU 13 -+#define SSB_PMURES_4325_ALP_AVAIL 14 -+#define SSB_PMURES_4325_RX_PWRSW_PU 15 -+#define SSB_PMURES_4325_TX_PWRSW_PU 16 -+#define SSB_PMURES_4325_RFPLL_PWRSW_PU 17 -+#define SSB_PMURES_4325_LOGEN_PWRSW_PU 18 -+#define SSB_PMURES_4325_AFE_PWRSW_PU 19 -+#define SSB_PMURES_4325_BBPLL_PWRSW_PU 20 -+#define SSB_PMURES_4325_HT_AVAIL 21 -+ -+/* BCM4328 PLL resource numbers. */ -+#define SSB_PMURES_4328_EXT_SWITCHER_PWM 0 -+#define SSB_PMURES_4328_BB_SWITCHER_PWM 1 -+#define SSB_PMURES_4328_BB_SWITCHER_BURST 2 -+#define SSB_PMURES_4328_BB_EXT_SWITCHER_BURST 3 -+#define SSB_PMURES_4328_ILP_REQUEST 4 -+#define SSB_PMURES_4328_RADIO_SWITCHER_PWM 5 -+#define SSB_PMURES_4328_RADIO_SWITCHER_BURST 6 -+#define SSB_PMURES_4328_ROM_SWITCH 7 -+#define SSB_PMURES_4328_PA_REF_LDO 8 -+#define SSB_PMURES_4328_RADIO_LDO 9 -+#define SSB_PMURES_4328_AFE_LDO 10 -+#define SSB_PMURES_4328_PLL_LDO 11 -+#define SSB_PMURES_4328_BG_FILTBYP 12 -+#define SSB_PMURES_4328_TX_FILTBYP 13 -+#define SSB_PMURES_4328_RX_FILTBYP 14 -+#define SSB_PMURES_4328_XTAL_PU 15 -+#define SSB_PMURES_4328_XTAL_EN 16 -+#define SSB_PMURES_4328_BB_PLL_FILTBYP 17 -+#define SSB_PMURES_4328_RF_PLL_FILTBYP 18 -+#define SSB_PMURES_4328_BB_PLL_PU 19 -+ -+/* BCM5354 PLL resource numbers. */ -+#define SSB_PMURES_5354_EXT_SWITCHER_PWM 0 -+#define SSB_PMURES_5354_BB_SWITCHER_PWM 1 -+#define SSB_PMURES_5354_BB_SWITCHER_BURST 2 -+#define SSB_PMURES_5354_BB_EXT_SWITCHER_BURST 3 -+#define SSB_PMURES_5354_ILP_REQUEST 4 -+#define SSB_PMURES_5354_RADIO_SWITCHER_PWM 5 -+#define SSB_PMURES_5354_RADIO_SWITCHER_BURST 6 -+#define SSB_PMURES_5354_ROM_SWITCH 7 -+#define SSB_PMURES_5354_PA_REF_LDO 8 -+#define SSB_PMURES_5354_RADIO_LDO 9 -+#define SSB_PMURES_5354_AFE_LDO 10 -+#define SSB_PMURES_5354_PLL_LDO 11 -+#define SSB_PMURES_5354_BG_FILTBYP 12 -+#define SSB_PMURES_5354_TX_FILTBYP 13 -+#define SSB_PMURES_5354_RX_FILTBYP 14 -+#define SSB_PMURES_5354_XTAL_PU 15 -+#define SSB_PMURES_5354_XTAL_EN 16 -+#define SSB_PMURES_5354_BB_PLL_FILTBYP 17 -+#define SSB_PMURES_5354_RF_PLL_FILTBYP 18 -+#define SSB_PMURES_5354_BB_PLL_PU 19 -+ -+ -+ -+/** Chip specific Chip-Status register contents. */ -+#define SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL 0x00000003 -+#define SSB_CHIPCO_CHST_4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ -+#define SSB_CHIPCO_CHST_4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ -+#define SSB_CHIPCO_CHST_4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ -+#define SSB_CHIPCO_CHST_4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ -+#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE 0x00000004 -+#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE_SHIFT 2 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALID 0x00000008 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALID_SHIFT 3 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALUE 0x000001F0 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALUE_SHIFT 4 -+#define SSB_CHIPCO_CHST_4325_PMUTOP_2B 0x00000200 /* 1 for 2b, 0 for to 2a */ - - - -@@ -353,11 +553,20 @@ - struct ssb_device; - struct ssb_serial_port; - -+/* Data for the PMU, if available. -+ * Check availability with ((struct ssb_chipcommon)->capabilities & SSB_CHIPCO_CAP_PMU) -+ */ -+struct ssb_chipcommon_pmu { -+ u8 rev; /* PMU revision */ -+ u32 crystalfreq; /* The active crystal frequency (in kHz) */ -+}; -+ - struct ssb_chipcommon { - struct ssb_device *dev; - u32 capabilities; - /* Fast Powerup Delay constant */ - u16 fast_pwrup_delay; -+ struct ssb_chipcommon_pmu pmu; - }; - - static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) -@@ -365,6 +574,17 @@ static inline bool ssb_chipco_available( - return (cc->dev != NULL); - } - -+/* Register access */ -+#define chipco_read32(cc, offset) ssb_read32((cc)->dev, offset) -+#define chipco_write32(cc, offset, val) ssb_write32((cc)->dev, offset, val) -+ -+#define chipco_mask32(cc, offset, mask) \ -+ chipco_write32(cc, offset, chipco_read32(cc, offset) & (mask)) -+#define chipco_set32(cc, offset, set) \ -+ chipco_write32(cc, offset, chipco_read32(cc, offset) | (set)) -+#define chipco_maskset32(cc, offset, mask, set) \ -+ chipco_write32(cc, offset, (chipco_read32(cc, offset) & (mask)) | (set)) -+ - extern void ssb_chipcommon_init(struct ssb_chipcommon *cc); - - extern void ssb_chipco_suspend(struct ssb_chipcommon *cc); -@@ -406,4 +626,8 @@ extern int ssb_chipco_serial_init(struct - struct ssb_serial_port *ports); - #endif /* CONFIG_SSB_SERIAL */ - -+/* PMU support */ -+extern void ssb_pmu_init(struct ssb_chipcommon *cc); -+ -+ - #endif /* LINUX_SSB_CHIPCO_H_ */ |