1c9703146158c0415a60799570397e488bc982af5Michael Buesch/* 2c9703146158c0415a60799570397e488bc982af5Michael Buesch * Sonics Silicon Backplane 3c9703146158c0415a60799570397e488bc982af5Michael Buesch * Broadcom ChipCommon Power Management Unit driver 4c9703146158c0415a60799570397e488bc982af5Michael Buesch * 5eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch * Copyright 2009, Michael Buesch <m@bues.ch> 6c9703146158c0415a60799570397e488bc982af5Michael Buesch * Copyright 2007, Broadcom Corporation 7c9703146158c0415a60799570397e488bc982af5Michael Buesch * 8c9703146158c0415a60799570397e488bc982af5Michael Buesch * Licensed under the GNU/GPL. See COPYING for details. 9c9703146158c0415a60799570397e488bc982af5Michael Buesch */ 10c9703146158c0415a60799570397e488bc982af5Michael Buesch 11c9703146158c0415a60799570397e488bc982af5Michael Buesch#include <linux/ssb/ssb.h> 12c9703146158c0415a60799570397e488bc982af5Michael Buesch#include <linux/ssb/ssb_regs.h> 13c9703146158c0415a60799570397e488bc982af5Michael Buesch#include <linux/ssb/ssb_driver_chipcommon.h> 14c9703146158c0415a60799570397e488bc982af5Michael Buesch#include <linux/delay.h> 151014c22e42a6692660d1a77888d07f4811b2914dPaul Gortmaker#include <linux/export.h> 16d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens#ifdef CONFIG_BCM47XX 17d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens#include <asm/mach-bcm47xx/nvram.h> 18d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens#endif 19c9703146158c0415a60799570397e488bc982af5Michael Buesch 20c9703146158c0415a60799570397e488bc982af5Michael Buesch#include "ssb_private.h" 21c9703146158c0415a60799570397e488bc982af5Michael Buesch 22c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) 23c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 24c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); 25c9703146158c0415a60799570397e488bc982af5Michael Buesch return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA); 26c9703146158c0415a60799570397e488bc982af5Michael Buesch} 27c9703146158c0415a60799570397e488bc982af5Michael Buesch 28c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic void ssb_chipco_pll_write(struct ssb_chipcommon *cc, 29c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 offset, u32 value) 30c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 31c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); 32c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); 33c9703146158c0415a60799570397e488bc982af5Michael Buesch} 34c9703146158c0415a60799570397e488bc982af5Michael Buesch 3506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanikstatic void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc, 3606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik u32 offset, u32 mask, u32 set) 3706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik{ 3806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik u32 value; 3906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 4006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); 4106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset); 4206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); 4306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); 4406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik value &= mask; 4506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik value |= set; 4606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value); 4706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); 4806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik} 4906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 50c9703146158c0415a60799570397e488bc982af5Michael Bueschstruct pmu0_plltab_entry { 51c9703146158c0415a60799570397e488bc982af5Michael Buesch u16 freq; /* Crystal frequency in kHz.*/ 52c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 xf; /* Crystal frequency value for PMU control */ 53c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 wb_int; 54c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 wb_frac; 55c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 56c9703146158c0415a60799570397e488bc982af5Michael Buesch 57c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu0_plltab_entry pmu0_plltab[] = { 58c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, }, 59c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, }, 60c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, }, 61c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, }, 62c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, }, 63c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, }, 64c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, }, 65c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, }, 66c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, }, 67c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, }, 68c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, }, 69c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, }, 70c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, }, 71c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, }, 72c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 73c9703146158c0415a60799570397e488bc982af5Michael Buesch#define SSB_PMU0_DEFAULT_XTALFREQ 20000 74c9703146158c0415a60799570397e488bc982af5Michael Buesch 75c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq) 76c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 77c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu0_plltab_entry *e; 78c9703146158c0415a60799570397e488bc982af5Michael Buesch unsigned int i; 79c9703146158c0415a60799570397e488bc982af5Michael Buesch 80c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) { 81c9703146158c0415a60799570397e488bc982af5Michael Buesch e = &pmu0_plltab[i]; 82c9703146158c0415a60799570397e488bc982af5Michael Buesch if (e->freq == crystalfreq) 83c9703146158c0415a60799570397e488bc982af5Michael Buesch return e; 84c9703146158c0415a60799570397e488bc982af5Michael Buesch } 85c9703146158c0415a60799570397e488bc982af5Michael Buesch 86c9703146158c0415a60799570397e488bc982af5Michael Buesch return NULL; 87c9703146158c0415a60799570397e488bc982af5Michael Buesch} 88c9703146158c0415a60799570397e488bc982af5Michael Buesch 89c9703146158c0415a60799570397e488bc982af5Michael Buesch/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ 90c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, 91c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 crystalfreq) 92c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 93c9703146158c0415a60799570397e488bc982af5Michael Buesch struct ssb_bus *bus = cc->dev->bus; 94c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu0_plltab_entry *e = NULL; 95c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 pmuctl, tmp, pllctl; 96c9703146158c0415a60799570397e488bc982af5Michael Buesch unsigned int i; 97c9703146158c0415a60799570397e488bc982af5Michael Buesch 98c9703146158c0415a60799570397e488bc982af5Michael Buesch if (crystalfreq) 99c9703146158c0415a60799570397e488bc982af5Michael Buesch e = pmu0_plltab_find_entry(crystalfreq); 100c9703146158c0415a60799570397e488bc982af5Michael Buesch if (!e) 101c9703146158c0415a60799570397e488bc982af5Michael Buesch e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ); 102c9703146158c0415a60799570397e488bc982af5Michael Buesch BUG_ON(!e); 103c9703146158c0415a60799570397e488bc982af5Michael Buesch crystalfreq = e->freq; 104c9703146158c0415a60799570397e488bc982af5Michael Buesch cc->pmu.crystalfreq = e->freq; 105c9703146158c0415a60799570397e488bc982af5Michael Buesch 106c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Check if the PLL already is programmed to this frequency. */ 107c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); 108c9703146158c0415a60799570397e488bc982af5Michael Buesch if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { 109c9703146158c0415a60799570397e488bc982af5Michael Buesch /* We're already there... */ 110c9703146158c0415a60799570397e488bc982af5Michael Buesch return; 111c9703146158c0415a60799570397e488bc982af5Michael Buesch } 112c9703146158c0415a60799570397e488bc982af5Michael Buesch 113c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", 114c9703146158c0415a60799570397e488bc982af5Michael Buesch (crystalfreq / 1000), (crystalfreq % 1000)); 115c9703146158c0415a60799570397e488bc982af5Michael Buesch 116c9703146158c0415a60799570397e488bc982af5Michael Buesch /* First turn the PLL off. */ 117c9703146158c0415a60799570397e488bc982af5Michael Buesch switch (bus->chip_id) { 118c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4328: 119c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 120c9703146158c0415a60799570397e488bc982af5Michael Buesch ~(1 << SSB_PMURES_4328_BB_PLL_PU)); 121c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, 122c9703146158c0415a60799570397e488bc982af5Michael Buesch ~(1 << SSB_PMURES_4328_BB_PLL_PU)); 123c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 124c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x5354: 125c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 126c9703146158c0415a60799570397e488bc982af5Michael Buesch ~(1 << SSB_PMURES_5354_BB_PLL_PU)); 127c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, 128c9703146158c0415a60799570397e488bc982af5Michael Buesch ~(1 << SSB_PMURES_5354_BB_PLL_PU)); 129c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 130c9703146158c0415a60799570397e488bc982af5Michael Buesch default: 131c9703146158c0415a60799570397e488bc982af5Michael Buesch SSB_WARN_ON(1); 132c9703146158c0415a60799570397e488bc982af5Michael Buesch } 133c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 1500; i; i--) { 134c9703146158c0415a60799570397e488bc982af5Michael Buesch tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); 135c9703146158c0415a60799570397e488bc982af5Michael Buesch if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) 136c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 137c9703146158c0415a60799570397e488bc982af5Michael Buesch udelay(10); 138c9703146158c0415a60799570397e488bc982af5Michael Buesch } 139c9703146158c0415a60799570397e488bc982af5Michael Buesch tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); 140c9703146158c0415a60799570397e488bc982af5Michael Buesch if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) 141c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); 142c9703146158c0415a60799570397e488bc982af5Michael Buesch 143c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set PDIV in PLL control 0. */ 144c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); 145c9703146158c0415a60799570397e488bc982af5Michael Buesch if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ) 146c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK; 147c9703146158c0415a60799570397e488bc982af5Michael Buesch else 148c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK; 149c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl); 150c9703146158c0415a60799570397e488bc982af5Michael Buesch 151c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set WILD in PLL control 1. */ 152c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1); 153c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD; 154c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK); 155c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK; 156c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK; 157c9703146158c0415a60799570397e488bc982af5Michael Buesch if (e->wb_frac == 0) 158c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= SSB_PMU0_PLLCTL1_STOPMOD; 159c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl); 160c9703146158c0415a60799570397e488bc982af5Michael Buesch 161c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set WILD in PLL control 2. */ 162c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2); 163c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI; 164c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI; 165c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl); 166c9703146158c0415a60799570397e488bc982af5Michael Buesch 167c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set the crystalfrequency and the divisor. */ 168c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); 169c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV; 170c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) 171c9703146158c0415a60799570397e488bc982af5Michael Buesch & SSB_CHIPCO_PMU_CTL_ILP_DIV; 172c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ; 173c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; 174c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); 175c9703146158c0415a60799570397e488bc982af5Michael Buesch} 176c9703146158c0415a60799570397e488bc982af5Michael Buesch 177c9703146158c0415a60799570397e488bc982af5Michael Bueschstruct pmu1_plltab_entry { 178c9703146158c0415a60799570397e488bc982af5Michael Buesch u16 freq; /* Crystal frequency in kHz.*/ 179c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 xf; /* Crystal frequency value for PMU control */ 180c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 ndiv_int; 181c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 ndiv_frac; 182c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 p1div; 183c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 p2div; 184c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 185c9703146158c0415a60799570397e488bc982af5Michael Buesch 186c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu1_plltab_entry pmu1_plltab[] = { 187c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 12000, .xf = 1, .p1div = 3, .p2div = 22, .ndiv_int = 0x9, .ndiv_frac = 0xFFFFEF, }, 188c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 13000, .xf = 2, .p1div = 1, .p2div = 6, .ndiv_int = 0xb, .ndiv_frac = 0x483483, }, 189c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 14400, .xf = 3, .p1div = 1, .p2div = 10, .ndiv_int = 0xa, .ndiv_frac = 0x1C71C7, }, 190c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 15360, .xf = 4, .p1div = 1, .p2div = 5, .ndiv_int = 0xb, .ndiv_frac = 0x755555, }, 191c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 16200, .xf = 5, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x6E9E06, }, 192c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 16800, .xf = 6, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x3CF3CF, }, 193c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 19200, .xf = 7, .p1div = 1, .p2div = 9, .ndiv_int = 0x5, .ndiv_frac = 0x17B425, }, 194c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 19800, .xf = 8, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0xA57EB, }, 195c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 20000, .xf = 9, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0, }, 196c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int = 0xa, .ndiv_frac = 0, }, 197c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int = 0xb, .ndiv_frac = 0, }, 198c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 26000, .xf = 12, .p1div = 1, .p2div = 2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, }, 199c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 30000, .xf = 13, .p1div = 3, .p2div = 8, .ndiv_int = 0xb, .ndiv_frac = 0, }, 200c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 38400, .xf = 14, .p1div = 1, .p2div = 5, .ndiv_int = 0x4, .ndiv_frac = 0x955555, }, 201c9703146158c0415a60799570397e488bc982af5Michael Buesch { .freq = 40000, .xf = 15, .p1div = 1, .p2div = 2, .ndiv_int = 0xb, .ndiv_frac = 0, }, 202c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 203c9703146158c0415a60799570397e488bc982af5Michael Buesch 204c9703146158c0415a60799570397e488bc982af5Michael Buesch#define SSB_PMU1_DEFAULT_XTALFREQ 15360 205c9703146158c0415a60799570397e488bc982af5Michael Buesch 206c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq) 207c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 208c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu1_plltab_entry *e; 209c9703146158c0415a60799570397e488bc982af5Michael Buesch unsigned int i; 210c9703146158c0415a60799570397e488bc982af5Michael Buesch 211c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) { 212c9703146158c0415a60799570397e488bc982af5Michael Buesch e = &pmu1_plltab[i]; 213c9703146158c0415a60799570397e488bc982af5Michael Buesch if (e->freq == crystalfreq) 214c9703146158c0415a60799570397e488bc982af5Michael Buesch return e; 215c9703146158c0415a60799570397e488bc982af5Michael Buesch } 216c9703146158c0415a60799570397e488bc982af5Michael Buesch 217c9703146158c0415a60799570397e488bc982af5Michael Buesch return NULL; 218c9703146158c0415a60799570397e488bc982af5Michael Buesch} 219c9703146158c0415a60799570397e488bc982af5Michael Buesch 220c9703146158c0415a60799570397e488bc982af5Michael Buesch/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ 221c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, 222c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 crystalfreq) 223c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 224c9703146158c0415a60799570397e488bc982af5Michael Buesch struct ssb_bus *bus = cc->dev->bus; 225c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu1_plltab_entry *e = NULL; 226c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 buffer_strength = 0; 227c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 tmp, pllctl, pmuctl; 228c9703146158c0415a60799570397e488bc982af5Michael Buesch unsigned int i; 229c9703146158c0415a60799570397e488bc982af5Michael Buesch 230c9703146158c0415a60799570397e488bc982af5Michael Buesch if (bus->chip_id == 0x4312) { 231c9703146158c0415a60799570397e488bc982af5Michael Buesch /* We do not touch the BCM4312 PLL and assume 232c9703146158c0415a60799570397e488bc982af5Michael Buesch * the default crystal settings work out-of-the-box. */ 233c9703146158c0415a60799570397e488bc982af5Michael Buesch cc->pmu.crystalfreq = 20000; 234c9703146158c0415a60799570397e488bc982af5Michael Buesch return; 235c9703146158c0415a60799570397e488bc982af5Michael Buesch } 236c9703146158c0415a60799570397e488bc982af5Michael Buesch 237c9703146158c0415a60799570397e488bc982af5Michael Buesch if (crystalfreq) 238c9703146158c0415a60799570397e488bc982af5Michael Buesch e = pmu1_plltab_find_entry(crystalfreq); 239c9703146158c0415a60799570397e488bc982af5Michael Buesch if (!e) 240c9703146158c0415a60799570397e488bc982af5Michael Buesch e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ); 241c9703146158c0415a60799570397e488bc982af5Michael Buesch BUG_ON(!e); 242c9703146158c0415a60799570397e488bc982af5Michael Buesch crystalfreq = e->freq; 243c9703146158c0415a60799570397e488bc982af5Michael Buesch cc->pmu.crystalfreq = e->freq; 244c9703146158c0415a60799570397e488bc982af5Michael Buesch 245c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Check if the PLL already is programmed to this frequency. */ 246c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); 247c9703146158c0415a60799570397e488bc982af5Michael Buesch if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { 248c9703146158c0415a60799570397e488bc982af5Michael Buesch /* We're already there... */ 249c9703146158c0415a60799570397e488bc982af5Michael Buesch return; 250c9703146158c0415a60799570397e488bc982af5Michael Buesch } 251c9703146158c0415a60799570397e488bc982af5Michael Buesch 252c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", 253c9703146158c0415a60799570397e488bc982af5Michael Buesch (crystalfreq / 1000), (crystalfreq % 1000)); 254c9703146158c0415a60799570397e488bc982af5Michael Buesch 255c9703146158c0415a60799570397e488bc982af5Michael Buesch /* First turn the PLL off. */ 256c9703146158c0415a60799570397e488bc982af5Michael Buesch switch (bus->chip_id) { 257c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4325: 258c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 259c9703146158c0415a60799570397e488bc982af5Michael Buesch ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | 260c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_HT_AVAIL))); 261c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, 262c9703146158c0415a60799570397e488bc982af5Michael Buesch ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | 263c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_HT_AVAIL))); 264c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Adjust the BBPLL to 2 on all channels later. */ 265c9703146158c0415a60799570397e488bc982af5Michael Buesch buffer_strength = 0x222222; 266c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 267c9703146158c0415a60799570397e488bc982af5Michael Buesch default: 268c9703146158c0415a60799570397e488bc982af5Michael Buesch SSB_WARN_ON(1); 269c9703146158c0415a60799570397e488bc982af5Michael Buesch } 270c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 1500; i; i--) { 271c9703146158c0415a60799570397e488bc982af5Michael Buesch tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); 272c9703146158c0415a60799570397e488bc982af5Michael Buesch if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) 273c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 274c9703146158c0415a60799570397e488bc982af5Michael Buesch udelay(10); 275c9703146158c0415a60799570397e488bc982af5Michael Buesch } 276c9703146158c0415a60799570397e488bc982af5Michael Buesch tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); 277c9703146158c0415a60799570397e488bc982af5Michael Buesch if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) 278c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); 279c9703146158c0415a60799570397e488bc982af5Michael Buesch 280c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set p1div and p2div. */ 281c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); 282c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV); 283c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV; 284c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV; 285c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl); 286c9703146158c0415a60799570397e488bc982af5Michael Buesch 287c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set ndiv int and ndiv mode */ 288c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2); 289c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE); 290c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT; 291c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE; 292c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl); 293c9703146158c0415a60799570397e488bc982af5Michael Buesch 294c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set ndiv frac */ 295c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3); 296c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC; 297c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC; 298c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl); 299c9703146158c0415a60799570397e488bc982af5Michael Buesch 300c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Change the drive strength, if required. */ 301c9703146158c0415a60799570397e488bc982af5Michael Buesch if (buffer_strength) { 302c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5); 303c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV; 304c9703146158c0415a60799570397e488bc982af5Michael Buesch pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV; 305c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl); 306c9703146158c0415a60799570397e488bc982af5Michael Buesch } 307c9703146158c0415a60799570397e488bc982af5Michael Buesch 308c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Tune the crystalfreq and the divisor. */ 309c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); 310c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ); 311c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) 312c9703146158c0415a60799570397e488bc982af5Michael Buesch & SSB_CHIPCO_PMU_CTL_ILP_DIV; 313c9703146158c0415a60799570397e488bc982af5Michael Buesch pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; 314c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); 315c9703146158c0415a60799570397e488bc982af5Michael Buesch} 316c9703146158c0415a60799570397e488bc982af5Michael Buesch 317c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic void ssb_pmu_pll_init(struct ssb_chipcommon *cc) 318c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 319c9703146158c0415a60799570397e488bc982af5Michael Buesch struct ssb_bus *bus = cc->dev->bus; 320c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ 321c9703146158c0415a60799570397e488bc982af5Michael Buesch 322c9703146158c0415a60799570397e488bc982af5Michael Buesch if (bus->bustype == SSB_BUSTYPE_SSB) { 323d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens#ifdef CONFIG_BCM47XX 324d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens char buf[20]; 325d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) 326d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens crystalfreq = simple_strtoul(buf, NULL, 0); 327d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens#endif 328c9703146158c0415a60799570397e488bc982af5Michael Buesch } 329c9703146158c0415a60799570397e488bc982af5Michael Buesch 330c9703146158c0415a60799570397e488bc982af5Michael Buesch switch (bus->chip_id) { 331c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4312: 332c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4325: 333c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_pmu1_pllinit_r0(cc, crystalfreq); 334c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 335c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4328: 336d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens ssb_pmu0_pllinit_r0(cc, crystalfreq); 337d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens break; 338c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x5354: 339d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens if (crystalfreq == 0) 340d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens crystalfreq = 25000; 341c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_pmu0_pllinit_r0(cc, crystalfreq); 342c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 343ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger case 0x4322: 344ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger if (cc->pmu.rev == 2) { 345ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A); 346ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); 347ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger } 348ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger break; 349c9703146158c0415a60799570397e488bc982af5Michael Buesch default: 350c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_ERR PFX 351c9703146158c0415a60799570397e488bc982af5Michael Buesch "ERROR: PLL init unknown for device %04X\n", 352c9703146158c0415a60799570397e488bc982af5Michael Buesch bus->chip_id); 353c9703146158c0415a60799570397e488bc982af5Michael Buesch } 354c9703146158c0415a60799570397e488bc982af5Michael Buesch} 355c9703146158c0415a60799570397e488bc982af5Michael Buesch 356c9703146158c0415a60799570397e488bc982af5Michael Bueschstruct pmu_res_updown_tab_entry { 357c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 resource; /* The resource number */ 358c9703146158c0415a60799570397e488bc982af5Michael Buesch u16 updown; /* The updown value */ 359c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 360c9703146158c0415a60799570397e488bc982af5Michael Buesch 361c9703146158c0415a60799570397e488bc982af5Michael Bueschenum pmu_res_depend_tab_task { 362c9703146158c0415a60799570397e488bc982af5Michael Buesch PMU_RES_DEP_SET = 1, 363c9703146158c0415a60799570397e488bc982af5Michael Buesch PMU_RES_DEP_ADD, 364c9703146158c0415a60799570397e488bc982af5Michael Buesch PMU_RES_DEP_REMOVE, 365c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 366c9703146158c0415a60799570397e488bc982af5Michael Buesch 367c9703146158c0415a60799570397e488bc982af5Michael Bueschstruct pmu_res_depend_tab_entry { 368c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 resource; /* The resource number */ 369c9703146158c0415a60799570397e488bc982af5Michael Buesch u8 task; /* SET | ADD | REMOVE */ 370c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 depend; /* The depend mask */ 371c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 372c9703146158c0415a60799570397e488bc982af5Michael Buesch 373c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = { 374c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM, .updown = 0x0101, }, 375c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM, .updown = 0x1F01, }, 376c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST, .updown = 0x010F, }, 377c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST, .updown = 0x0101, }, 378c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_ILP_REQUEST, .updown = 0x0202, }, 379c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM, .updown = 0x0F01, }, 380c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, }, 381c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_ROM_SWITCH, .updown = 0x0101, }, 382c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_PA_REF_LDO, .updown = 0x0F01, }, 383c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_RADIO_LDO, .updown = 0x0F01, }, 384c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_AFE_LDO, .updown = 0x0F01, }, 385c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_PLL_LDO, .updown = 0x0F01, }, 386c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BG_FILTBYP, .updown = 0x0101, }, 387c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_TX_FILTBYP, .updown = 0x0101, }, 388c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_RX_FILTBYP, .updown = 0x0101, }, 389c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_XTAL_PU, .updown = 0x0101, }, 390c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_XTAL_EN, .updown = 0xA001, }, 391c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP, .updown = 0x0101, }, 392c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP, .updown = 0x0101, }, 393c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4328_BB_PLL_PU, .updown = 0x0701, }, 394c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 395c9703146158c0415a60799570397e488bc982af5Michael Buesch 396c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = { 397c9703146158c0415a60799570397e488bc982af5Michael Buesch { 398c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */ 399c9703146158c0415a60799570397e488bc982af5Michael Buesch .resource = SSB_PMURES_4328_ILP_REQUEST, 400c9703146158c0415a60799570397e488bc982af5Michael Buesch .task = PMU_RES_DEP_SET, 401c9703146158c0415a60799570397e488bc982af5Michael Buesch .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | 402c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)), 403c9703146158c0415a60799570397e488bc982af5Michael Buesch }, 404c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 405c9703146158c0415a60799570397e488bc982af5Michael Buesch 406c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = { 407c9703146158c0415a60799570397e488bc982af5Michael Buesch { .resource = SSB_PMURES_4325_XTAL_PU, .updown = 0x1501, }, 408c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 409c9703146158c0415a60799570397e488bc982af5Michael Buesch 410c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = { 411c9703146158c0415a60799570397e488bc982af5Michael Buesch { 412c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Adjust HT-Available dependencies. */ 413c9703146158c0415a60799570397e488bc982af5Michael Buesch .resource = SSB_PMURES_4325_HT_AVAIL, 414c9703146158c0415a60799570397e488bc982af5Michael Buesch .task = PMU_RES_DEP_ADD, 415c9703146158c0415a60799570397e488bc982af5Michael Buesch .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) | 416c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_TX_PWRSW_PU) | 417c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) | 418c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_AFE_PWRSW_PU)), 419c9703146158c0415a60799570397e488bc982af5Michael Buesch }, 420c9703146158c0415a60799570397e488bc982af5Michael Buesch}; 421c9703146158c0415a60799570397e488bc982af5Michael Buesch 422c9703146158c0415a60799570397e488bc982af5Michael Bueschstatic void ssb_pmu_resources_init(struct ssb_chipcommon *cc) 423c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 424c9703146158c0415a60799570397e488bc982af5Michael Buesch struct ssb_bus *bus = cc->dev->bus; 425c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 min_msk = 0, max_msk = 0; 426c9703146158c0415a60799570397e488bc982af5Michael Buesch unsigned int i; 427c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu_res_updown_tab_entry *updown_tab = NULL; 428eb40e3e8bb453519ae17d42e7cab6bdd2b4b9fc5Connor Hansen unsigned int updown_tab_size = 0; 429c9703146158c0415a60799570397e488bc982af5Michael Buesch const struct pmu_res_depend_tab_entry *depend_tab = NULL; 430eb40e3e8bb453519ae17d42e7cab6bdd2b4b9fc5Connor Hansen unsigned int depend_tab_size = 0; 431c9703146158c0415a60799570397e488bc982af5Michael Buesch 432c9703146158c0415a60799570397e488bc982af5Michael Buesch switch (bus->chip_id) { 433c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4312: 4343c35c84a70fc7d76cf7d975481fcb30468c68818Rafał Miłecki min_msk = 0xCBB; 4353c35c84a70fc7d76cf7d975481fcb30468c68818Rafał Miłecki break; 436ac5b4e168ebd9046a6cd066d50b3341353f2f309Larry Finger case 0x4322: 437c9703146158c0415a60799570397e488bc982af5Michael Buesch /* We keep the default settings: 438c9703146158c0415a60799570397e488bc982af5Michael Buesch * min_msk = 0xCBB 439c9703146158c0415a60799570397e488bc982af5Michael Buesch * max_msk = 0x7FFFF 440c9703146158c0415a60799570397e488bc982af5Michael Buesch */ 441c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 442c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4325: 443c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Power OTP down later. */ 444c9703146158c0415a60799570397e488bc982af5Michael Buesch min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) | 445c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4325_LNLDO2_PU); 446c9703146158c0415a60799570397e488bc982af5Michael Buesch if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) & 447c9703146158c0415a60799570397e488bc982af5Michael Buesch SSB_CHIPCO_CHST_4325_PMUTOP_2B) 448c9703146158c0415a60799570397e488bc982af5Michael Buesch min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST); 449c9703146158c0415a60799570397e488bc982af5Michael Buesch /* The PLL may turn on, if it decides so. */ 450c9703146158c0415a60799570397e488bc982af5Michael Buesch max_msk = 0xFFFFF; 451c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab = pmu_res_updown_tab_4325a0; 452c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0); 453c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab = pmu_res_depend_tab_4325a0; 454c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0); 455c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 456c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x4328: 457c9703146158c0415a60799570397e488bc982af5Michael Buesch min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | 458c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) | 459c9703146158c0415a60799570397e488bc982af5Michael Buesch (1 << SSB_PMURES_4328_XTAL_EN); 460c9703146158c0415a60799570397e488bc982af5Michael Buesch /* The PLL may turn on, if it decides so. */ 461c9703146158c0415a60799570397e488bc982af5Michael Buesch max_msk = 0xFFFFF; 462c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab = pmu_res_updown_tab_4328a0; 463c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0); 464c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab = pmu_res_depend_tab_4328a0; 465c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0); 466c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 467c9703146158c0415a60799570397e488bc982af5Michael Buesch case 0x5354: 468c9703146158c0415a60799570397e488bc982af5Michael Buesch /* The PLL may turn on, if it decides so. */ 469c9703146158c0415a60799570397e488bc982af5Michael Buesch max_msk = 0xFFFFF; 470c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 471c9703146158c0415a60799570397e488bc982af5Michael Buesch default: 472c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_printk(KERN_ERR PFX 473c9703146158c0415a60799570397e488bc982af5Michael Buesch "ERROR: PMU resource config unknown for device %04X\n", 474c9703146158c0415a60799570397e488bc982af5Michael Buesch bus->chip_id); 475c9703146158c0415a60799570397e488bc982af5Michael Buesch } 476c9703146158c0415a60799570397e488bc982af5Michael Buesch 477c9703146158c0415a60799570397e488bc982af5Michael Buesch if (updown_tab) { 478c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 0; i < updown_tab_size; i++) { 479c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, 480c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab[i].resource); 481c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM, 482c9703146158c0415a60799570397e488bc982af5Michael Buesch updown_tab[i].updown); 483c9703146158c0415a60799570397e488bc982af5Michael Buesch } 484c9703146158c0415a60799570397e488bc982af5Michael Buesch } 485c9703146158c0415a60799570397e488bc982af5Michael Buesch if (depend_tab) { 486c9703146158c0415a60799570397e488bc982af5Michael Buesch for (i = 0; i < depend_tab_size; i++) { 487c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, 488c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab[i].resource); 489c9703146158c0415a60799570397e488bc982af5Michael Buesch switch (depend_tab[i].task) { 490c9703146158c0415a60799570397e488bc982af5Michael Buesch case PMU_RES_DEP_SET: 491c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, 492c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab[i].depend); 493c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 494c9703146158c0415a60799570397e488bc982af5Michael Buesch case PMU_RES_DEP_ADD: 495c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, 496c9703146158c0415a60799570397e488bc982af5Michael Buesch depend_tab[i].depend); 497c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 498c9703146158c0415a60799570397e488bc982af5Michael Buesch case PMU_RES_DEP_REMOVE: 499c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, 500c9703146158c0415a60799570397e488bc982af5Michael Buesch ~(depend_tab[i].depend)); 501c9703146158c0415a60799570397e488bc982af5Michael Buesch break; 502c9703146158c0415a60799570397e488bc982af5Michael Buesch default: 503c9703146158c0415a60799570397e488bc982af5Michael Buesch SSB_WARN_ON(1); 504c9703146158c0415a60799570397e488bc982af5Michael Buesch } 505c9703146158c0415a60799570397e488bc982af5Michael Buesch } 506c9703146158c0415a60799570397e488bc982af5Michael Buesch } 507c9703146158c0415a60799570397e488bc982af5Michael Buesch 508c9703146158c0415a60799570397e488bc982af5Michael Buesch /* Set the resource masks. */ 509c9703146158c0415a60799570397e488bc982af5Michael Buesch if (min_msk) 510c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk); 511c9703146158c0415a60799570397e488bc982af5Michael Buesch if (max_msk) 512c9703146158c0415a60799570397e488bc982af5Michael Buesch chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); 513c9703146158c0415a60799570397e488bc982af5Michael Buesch} 514c9703146158c0415a60799570397e488bc982af5Michael Buesch 515c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */ 516c9703146158c0415a60799570397e488bc982af5Michael Bueschvoid ssb_pmu_init(struct ssb_chipcommon *cc) 517c9703146158c0415a60799570397e488bc982af5Michael Buesch{ 518c9703146158c0415a60799570397e488bc982af5Michael Buesch u32 pmucap; 519c9703146158c0415a60799570397e488bc982af5Michael Buesch 520c9703146158c0415a60799570397e488bc982af5Michael Buesch if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) 521c9703146158c0415a60799570397e488bc982af5Michael Buesch return; 522c9703146158c0415a60799570397e488bc982af5Michael Buesch 523c9703146158c0415a60799570397e488bc982af5Michael Buesch pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); 524c9703146158c0415a60799570397e488bc982af5Michael Buesch cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); 525c9703146158c0415a60799570397e488bc982af5Michael Buesch 526c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", 527c9703146158c0415a60799570397e488bc982af5Michael Buesch cc->pmu.rev, pmucap); 528c9703146158c0415a60799570397e488bc982af5Michael Buesch 529c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki if (cc->pmu.rev == 1) 530c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, 531c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki ~SSB_CHIPCO_PMU_CTL_NOILPONW); 532c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki else 533c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki chipco_set32(cc, SSB_CHIPCO_PMU_CTL, 534c35deb4e70d52ed564c58569fe059dd7ca5f4eecRafał Miłecki SSB_CHIPCO_PMU_CTL_NOILPONW); 535c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_pmu_pll_init(cc); 536c9703146158c0415a60799570397e488bc982af5Michael Buesch ssb_pmu_resources_init(cc); 537c9703146158c0415a60799570397e488bc982af5Michael Buesch} 53806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 53906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanikvoid ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, 54006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik enum ssb_pmu_ldo_volt_id id, u32 voltage) 54106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik{ 54206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik struct ssb_bus *bus = cc->dev->bus; 54306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik u32 addr, shift, mask; 54406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 54506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik switch (bus->chip_id) { 54606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x4328: 54706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x5354: 54806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik switch (id) { 54906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case LDO_VOLT1: 55006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik addr = 2; 55106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik shift = 25; 55206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik mask = 0xF; 55306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 55406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case LDO_VOLT2: 55506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik addr = 3; 55606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik shift = 1; 55706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik mask = 0xF; 55806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 55906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case LDO_VOLT3: 56006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik addr = 3; 56106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik shift = 9; 56206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik mask = 0xF; 56306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 56406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case LDO_PAREF: 56506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik addr = 3; 56606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik shift = 17; 56706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik mask = 0x3F; 56806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 56906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik default: 57006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik SSB_WARN_ON(1); 57106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik return; 57206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik } 57306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 57406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x4312: 57506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik if (SSB_WARN_ON(id != LDO_PAREF)) 57606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik return; 57706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik addr = 0; 57806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik shift = 21; 57906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik mask = 0x3F; 58006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 58106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik default: 58206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik return; 58306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik } 58406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 58506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift), 58606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik (voltage & mask) << shift); 58706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik} 58806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 58906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanikvoid ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) 59006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik{ 59106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik struct ssb_bus *bus = cc->dev->bus; 59206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik int ldo; 59306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 59406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik switch (bus->chip_id) { 59506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x4312: 59606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik ldo = SSB_PMURES_4312_PA_REF_LDO; 59706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 59806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x4328: 59906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik ldo = SSB_PMURES_4328_PA_REF_LDO; 60006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 60106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik case 0x5354: 60206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik ldo = SSB_PMURES_5354_PA_REF_LDO; 60306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik break; 60406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik default: 60506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik return; 60606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik } 60706e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 60806e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik if (on) 60906e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo); 61006e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik else 61106e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo)); 61206e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read? 61306e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik} 61406e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor Stefanik 61506e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor StefanikEXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); 61606e4da268c0e8f3b8408403d65e47d2885a78ff2Gábor StefanikEXPORT_SYMBOL(ssb_pmu_set_ldo_paref); 617d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens 618d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtensu32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) 619d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens{ 620d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens struct ssb_bus *bus = cc->dev->bus; 621d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens 622d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens switch (bus->chip_id) { 623d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens case 0x5354: 624d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens /* 5354 chip uses a non programmable PLL of frequency 240MHz */ 625d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens return 240000000; 626d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens default: 627d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens ssb_printk(KERN_ERR PFX 628d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens "ERROR: PMU cpu clock unknown for device %04X\n", 629d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens bus->chip_id); 630d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens return 0; 631d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens } 632d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens} 633d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens 634d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtensu32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) 635d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens{ 636d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens struct ssb_bus *bus = cc->dev->bus; 637d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens 638d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens switch (bus->chip_id) { 639d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens case 0x5354: 640d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens return 120000000; 641d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens default: 642d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens ssb_printk(KERN_ERR PFX 643d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens "ERROR: PMU controlclock unknown for device %04X\n", 644d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens bus->chip_id); 645d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens return 0; 646d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens } 647d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens} 648