Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Sonics Silicon Backplane
0003  * Broadcom ChipCommon Power Management Unit driver
0004  *
0005  * Copyright 2009, Michael Buesch <m@bues.ch>
0006  * Copyright 2007, Broadcom Corporation
0007  *
0008  * Licensed under the GNU/GPL. See COPYING for details.
0009  */
0010 
0011 #include "ssb_private.h"
0012 
0013 #include <linux/ssb/ssb.h>
0014 #include <linux/ssb/ssb_regs.h>
0015 #include <linux/ssb/ssb_driver_chipcommon.h>
0016 #include <linux/delay.h>
0017 #include <linux/export.h>
0018 #ifdef CONFIG_BCM47XX
0019 #include <linux/bcm47xx_nvram.h>
0020 #endif
0021 
0022 static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset)
0023 {
0024     chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset);
0025     return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA);
0026 }
0027 
0028 static void ssb_chipco_pll_write(struct ssb_chipcommon *cc,
0029                  u32 offset, u32 value)
0030 {
0031     chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset);
0032     chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
0033 }
0034 
0035 static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
0036                    u32 offset, u32 mask, u32 set)
0037 {
0038     u32 value;
0039 
0040     chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
0041     chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
0042     chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
0043     value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
0044     value &= mask;
0045     value |= set;
0046     chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
0047     chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
0048 }
0049 
0050 struct pmu0_plltab_entry {
0051     u16 freq;   /* Crystal frequency in kHz.*/
0052     u8 xf;      /* Crystal frequency value for PMU control */
0053     u8 wb_int;
0054     u32 wb_frac;
0055 };
0056 
0057 static const struct pmu0_plltab_entry pmu0_plltab[] = {
0058     { .freq = 12000, .xf =  1, .wb_int = 73, .wb_frac = 349525, },
0059     { .freq = 13000, .xf =  2, .wb_int = 67, .wb_frac = 725937, },
0060     { .freq = 14400, .xf =  3, .wb_int = 61, .wb_frac = 116508, },
0061     { .freq = 15360, .xf =  4, .wb_int = 57, .wb_frac = 305834, },
0062     { .freq = 16200, .xf =  5, .wb_int = 54, .wb_frac = 336579, },
0063     { .freq = 16800, .xf =  6, .wb_int = 52, .wb_frac = 399457, },
0064     { .freq = 19200, .xf =  7, .wb_int = 45, .wb_frac = 873813, },
0065     { .freq = 19800, .xf =  8, .wb_int = 44, .wb_frac = 466033, },
0066     { .freq = 20000, .xf =  9, .wb_int = 44, .wb_frac = 0,      },
0067     { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, },
0068     { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, },
0069     { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, },
0070     { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, },
0071     { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0,      },
0072 };
0073 #define SSB_PMU0_DEFAULT_XTALFREQ   20000
0074 
0075 static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq)
0076 {
0077     const struct pmu0_plltab_entry *e;
0078     unsigned int i;
0079 
0080     for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) {
0081         e = &pmu0_plltab[i];
0082         if (e->freq == crystalfreq)
0083             return e;
0084     }
0085 
0086     return NULL;
0087 }
0088 
0089 /* Tune the PLL to the crystal speed. crystalfreq is in kHz. */
0090 static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
0091                 u32 crystalfreq)
0092 {
0093     struct ssb_bus *bus = cc->dev->bus;
0094     const struct pmu0_plltab_entry *e = NULL;
0095     u32 pmuctl, tmp, pllctl;
0096     unsigned int i;
0097 
0098     if (crystalfreq)
0099         e = pmu0_plltab_find_entry(crystalfreq);
0100     if (!e)
0101         e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ);
0102     BUG_ON(!e);
0103     crystalfreq = e->freq;
0104     cc->pmu.crystalfreq = e->freq;
0105 
0106     /* Check if the PLL already is programmed to this frequency. */
0107     pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
0108     if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) {
0109         /* We're already there... */
0110         return;
0111     }
0112 
0113     dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n",
0114          crystalfreq / 1000, crystalfreq % 1000);
0115 
0116     /* First turn the PLL off. */
0117     switch (bus->chip_id) {
0118     case 0x4328:
0119         chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
0120                   ~(1 << SSB_PMURES_4328_BB_PLL_PU));
0121         chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
0122                   ~(1 << SSB_PMURES_4328_BB_PLL_PU));
0123         break;
0124     case 0x5354:
0125         chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
0126                   ~(1 << SSB_PMURES_5354_BB_PLL_PU));
0127         chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
0128                   ~(1 << SSB_PMURES_5354_BB_PLL_PU));
0129         break;
0130     default:
0131         WARN_ON(1);
0132     }
0133     for (i = 1500; i; i--) {
0134         tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
0135         if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT))
0136             break;
0137         udelay(10);
0138     }
0139     tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
0140     if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
0141         dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n");
0142 
0143     /* Set PDIV in PLL control 0. */
0144     pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0);
0145     if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ)
0146         pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK;
0147     else
0148         pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK;
0149     ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl);
0150 
0151     /* Set WILD in PLL control 1. */
0152     pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1);
0153     pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD;
0154     pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK);
0155     pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK;
0156     pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK;
0157     if (e->wb_frac == 0)
0158         pllctl |= SSB_PMU0_PLLCTL1_STOPMOD;
0159     ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl);
0160 
0161     /* Set WILD in PLL control 2. */
0162     pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2);
0163     pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI;
0164     pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI;
0165     ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl);
0166 
0167     /* Set the crystalfrequency and the divisor. */
0168     pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
0169     pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV;
0170     pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT)
0171             & SSB_CHIPCO_PMU_CTL_ILP_DIV;
0172     pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ;
0173     pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ;
0174     chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl);
0175 }
0176 
0177 struct pmu1_plltab_entry {
0178     u16 freq;   /* Crystal frequency in kHz.*/
0179     u8 xf;      /* Crystal frequency value for PMU control */
0180     u8 ndiv_int;
0181     u32 ndiv_frac;
0182     u8 p1div;
0183     u8 p2div;
0184 };
0185 
0186 static const struct pmu1_plltab_entry pmu1_plltab[] = {
0187     { .freq = 12000, .xf =  1, .p1div = 3, .p2div = 22, .ndiv_int =  0x9, .ndiv_frac = 0xFFFFEF, },
0188     { .freq = 13000, .xf =  2, .p1div = 1, .p2div =  6, .ndiv_int =  0xb, .ndiv_frac = 0x483483, },
0189     { .freq = 14400, .xf =  3, .p1div = 1, .p2div = 10, .ndiv_int =  0xa, .ndiv_frac = 0x1C71C7, },
0190     { .freq = 15360, .xf =  4, .p1div = 1, .p2div =  5, .ndiv_int =  0xb, .ndiv_frac = 0x755555, },
0191     { .freq = 16200, .xf =  5, .p1div = 1, .p2div = 10, .ndiv_int =  0x5, .ndiv_frac = 0x6E9E06, },
0192     { .freq = 16800, .xf =  6, .p1div = 1, .p2div = 10, .ndiv_int =  0x5, .ndiv_frac = 0x3CF3CF, },
0193     { .freq = 19200, .xf =  7, .p1div = 1, .p2div =  9, .ndiv_int =  0x5, .ndiv_frac = 0x17B425, },
0194     { .freq = 19800, .xf =  8, .p1div = 1, .p2div = 11, .ndiv_int =  0x4, .ndiv_frac = 0xA57EB,  },
0195     { .freq = 20000, .xf =  9, .p1div = 1, .p2div = 11, .ndiv_int =  0x4, .ndiv_frac = 0,        },
0196     { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int =  0xa, .ndiv_frac = 0,        },
0197     { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int =  0xb, .ndiv_frac = 0,        },
0198     { .freq = 26000, .xf = 12, .p1div = 1, .p2div =  2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, },
0199     { .freq = 30000, .xf = 13, .p1div = 3, .p2div =  8, .ndiv_int =  0xb, .ndiv_frac = 0,        },
0200     { .freq = 38400, .xf = 14, .p1div = 1, .p2div =  5, .ndiv_int =  0x4, .ndiv_frac = 0x955555, },
0201     { .freq = 40000, .xf = 15, .p1div = 1, .p2div =  2, .ndiv_int =  0xb, .ndiv_frac = 0,        },
0202 };
0203 
0204 #define SSB_PMU1_DEFAULT_XTALFREQ   15360
0205 
0206 static const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq)
0207 {
0208     const struct pmu1_plltab_entry *e;
0209     unsigned int i;
0210 
0211     for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) {
0212         e = &pmu1_plltab[i];
0213         if (e->freq == crystalfreq)
0214             return e;
0215     }
0216 
0217     return NULL;
0218 }
0219 
0220 /* Tune the PLL to the crystal speed. crystalfreq is in kHz. */
0221 static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
0222                 u32 crystalfreq)
0223 {
0224     struct ssb_bus *bus = cc->dev->bus;
0225     const struct pmu1_plltab_entry *e = NULL;
0226     u32 buffer_strength = 0;
0227     u32 tmp, pllctl, pmuctl;
0228     unsigned int i;
0229 
0230     if (bus->chip_id == 0x4312) {
0231         /* We do not touch the BCM4312 PLL and assume
0232          * the default crystal settings work out-of-the-box. */
0233         cc->pmu.crystalfreq = 20000;
0234         return;
0235     }
0236 
0237     if (crystalfreq)
0238         e = pmu1_plltab_find_entry(crystalfreq);
0239     if (!e)
0240         e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ);
0241     BUG_ON(!e);
0242     crystalfreq = e->freq;
0243     cc->pmu.crystalfreq = e->freq;
0244 
0245     /* Check if the PLL already is programmed to this frequency. */
0246     pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
0247     if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) {
0248         /* We're already there... */
0249         return;
0250     }
0251 
0252     dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n",
0253          crystalfreq / 1000, crystalfreq % 1000);
0254 
0255     /* First turn the PLL off. */
0256     switch (bus->chip_id) {
0257     case 0x4325:
0258         chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
0259                   ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) |
0260                 (1 << SSB_PMURES_4325_HT_AVAIL)));
0261         chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
0262                   ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) |
0263                 (1 << SSB_PMURES_4325_HT_AVAIL)));
0264         /* Adjust the BBPLL to 2 on all channels later. */
0265         buffer_strength = 0x222222;
0266         break;
0267     default:
0268         WARN_ON(1);
0269     }
0270     for (i = 1500; i; i--) {
0271         tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
0272         if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT))
0273             break;
0274         udelay(10);
0275     }
0276     tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
0277     if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
0278         dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n");
0279 
0280     /* Set p1div and p2div. */
0281     pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0);
0282     pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV);
0283     pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV;
0284     pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV;
0285     ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl);
0286 
0287     /* Set ndiv int and ndiv mode */
0288     pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2);
0289     pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE);
0290     pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT;
0291     pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE;
0292     ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl);
0293 
0294     /* Set ndiv frac */
0295     pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3);
0296     pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC;
0297     pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC;
0298     ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl);
0299 
0300     /* Change the drive strength, if required. */
0301     if (buffer_strength) {
0302         pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5);
0303         pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV;
0304         pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV;
0305         ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl);
0306     }
0307 
0308     /* Tune the crystalfreq and the divisor. */
0309     pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
0310     pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ);
0311     pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT)
0312             & SSB_CHIPCO_PMU_CTL_ILP_DIV;
0313     pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ;
0314     chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl);
0315 }
0316 
0317 static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
0318 {
0319     struct ssb_bus *bus = cc->dev->bus;
0320     u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
0321 
0322     if (bus->bustype == SSB_BUSTYPE_SSB) {
0323 #ifdef CONFIG_BCM47XX
0324         char buf[20];
0325         if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
0326             crystalfreq = simple_strtoul(buf, NULL, 0);
0327 #endif
0328     }
0329 
0330     switch (bus->chip_id) {
0331     case 0x4312:
0332     case 0x4325:
0333         ssb_pmu1_pllinit_r0(cc, crystalfreq);
0334         break;
0335     case 0x4328:
0336         ssb_pmu0_pllinit_r0(cc, crystalfreq);
0337         break;
0338     case 0x5354:
0339         if (crystalfreq == 0)
0340             crystalfreq = 25000;
0341         ssb_pmu0_pllinit_r0(cc, crystalfreq);
0342         break;
0343     case 0x4322:
0344         if (cc->pmu.rev == 2) {
0345             chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A);
0346             chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
0347         }
0348         break;
0349     case 43222:
0350         break;
0351     default:
0352         dev_err(cc->dev->dev, "ERROR: PLL init unknown for device %04X\n",
0353             bus->chip_id);
0354     }
0355 }
0356 
0357 struct pmu_res_updown_tab_entry {
0358     u8 resource;    /* The resource number */
0359     u16 updown; /* The updown value */
0360 };
0361 
0362 enum pmu_res_depend_tab_task {
0363     PMU_RES_DEP_SET = 1,
0364     PMU_RES_DEP_ADD,
0365     PMU_RES_DEP_REMOVE,
0366 };
0367 
0368 struct pmu_res_depend_tab_entry {
0369     u8 resource;    /* The resource number */
0370     u8 task;    /* SET | ADD | REMOVE */
0371     u32 depend; /* The depend mask */
0372 };
0373 
0374 static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = {
0375     { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM,     .updown = 0x0101, },
0376     { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM,      .updown = 0x1F01, },
0377     { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST,    .updown = 0x010F, },
0378     { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST,    .updown = 0x0101, },
0379     { .resource = SSB_PMURES_4328_ILP_REQUEST,      .updown = 0x0202, },
0380     { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM,   .updown = 0x0F01, },
0381     { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, },
0382     { .resource = SSB_PMURES_4328_ROM_SWITCH,       .updown = 0x0101, },
0383     { .resource = SSB_PMURES_4328_PA_REF_LDO,       .updown = 0x0F01, },
0384     { .resource = SSB_PMURES_4328_RADIO_LDO,        .updown = 0x0F01, },
0385     { .resource = SSB_PMURES_4328_AFE_LDO,          .updown = 0x0F01, },
0386     { .resource = SSB_PMURES_4328_PLL_LDO,          .updown = 0x0F01, },
0387     { .resource = SSB_PMURES_4328_BG_FILTBYP,       .updown = 0x0101, },
0388     { .resource = SSB_PMURES_4328_TX_FILTBYP,       .updown = 0x0101, },
0389     { .resource = SSB_PMURES_4328_RX_FILTBYP,       .updown = 0x0101, },
0390     { .resource = SSB_PMURES_4328_XTAL_PU,          .updown = 0x0101, },
0391     { .resource = SSB_PMURES_4328_XTAL_EN,          .updown = 0xA001, },
0392     { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP,       .updown = 0x0101, },
0393     { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP,       .updown = 0x0101, },
0394     { .resource = SSB_PMURES_4328_BB_PLL_PU,        .updown = 0x0701, },
0395 };
0396 
0397 static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = {
0398     {
0399         /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */
0400         .resource = SSB_PMURES_4328_ILP_REQUEST,
0401         .task = PMU_RES_DEP_SET,
0402         .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) |
0403                (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)),
0404     },
0405 };
0406 
0407 static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = {
0408     { .resource = SSB_PMURES_4325_XTAL_PU,          .updown = 0x1501, },
0409 };
0410 
0411 static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = {
0412     {
0413         /* Adjust HT-Available dependencies. */
0414         .resource = SSB_PMURES_4325_HT_AVAIL,
0415         .task = PMU_RES_DEP_ADD,
0416         .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) |
0417                (1 << SSB_PMURES_4325_TX_PWRSW_PU) |
0418                (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) |
0419                (1 << SSB_PMURES_4325_AFE_PWRSW_PU)),
0420     },
0421 };
0422 
0423 static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
0424 {
0425     struct ssb_bus *bus = cc->dev->bus;
0426     u32 min_msk = 0, max_msk = 0;
0427     unsigned int i;
0428     const struct pmu_res_updown_tab_entry *updown_tab = NULL;
0429     unsigned int updown_tab_size = 0;
0430     const struct pmu_res_depend_tab_entry *depend_tab = NULL;
0431     unsigned int depend_tab_size = 0;
0432 
0433     switch (bus->chip_id) {
0434     case 0x4312:
0435          min_msk = 0xCBB;
0436          break;
0437     case 0x4322:
0438     case 43222:
0439         /* We keep the default settings:
0440          * min_msk = 0xCBB
0441          * max_msk = 0x7FFFF
0442          */
0443         break;
0444     case 0x4325:
0445         /* Power OTP down later. */
0446         min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) |
0447               (1 << SSB_PMURES_4325_LNLDO2_PU);
0448         if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) &
0449             SSB_CHIPCO_CHST_4325_PMUTOP_2B)
0450             min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST);
0451         /* The PLL may turn on, if it decides so. */
0452         max_msk = 0xFFFFF;
0453         updown_tab = pmu_res_updown_tab_4325a0;
0454         updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0);
0455         depend_tab = pmu_res_depend_tab_4325a0;
0456         depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0);
0457         break;
0458     case 0x4328:
0459         min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) |
0460               (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) |
0461               (1 << SSB_PMURES_4328_XTAL_EN);
0462         /* The PLL may turn on, if it decides so. */
0463         max_msk = 0xFFFFF;
0464         updown_tab = pmu_res_updown_tab_4328a0;
0465         updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0);
0466         depend_tab = pmu_res_depend_tab_4328a0;
0467         depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0);
0468         break;
0469     case 0x5354:
0470         /* The PLL may turn on, if it decides so. */
0471         max_msk = 0xFFFFF;
0472         break;
0473     default:
0474         dev_err(cc->dev->dev, "ERROR: PMU resource config unknown for device %04X\n",
0475             bus->chip_id);
0476     }
0477 
0478     if (updown_tab) {
0479         for (i = 0; i < updown_tab_size; i++) {
0480             chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL,
0481                        updown_tab[i].resource);
0482             chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM,
0483                        updown_tab[i].updown);
0484         }
0485     }
0486     if (depend_tab) {
0487         for (i = 0; i < depend_tab_size; i++) {
0488             chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL,
0489                        depend_tab[i].resource);
0490             switch (depend_tab[i].task) {
0491             case PMU_RES_DEP_SET:
0492                 chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
0493                            depend_tab[i].depend);
0494                 break;
0495             case PMU_RES_DEP_ADD:
0496                 chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
0497                          depend_tab[i].depend);
0498                 break;
0499             case PMU_RES_DEP_REMOVE:
0500                 chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
0501                           ~(depend_tab[i].depend));
0502                 break;
0503             default:
0504                 WARN_ON(1);
0505             }
0506         }
0507     }
0508 
0509     /* Set the resource masks. */
0510     if (min_msk)
0511         chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk);
0512     if (max_msk)
0513         chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
0514 }
0515 
0516 /* https://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
0517 void ssb_pmu_init(struct ssb_chipcommon *cc)
0518 {
0519     u32 pmucap;
0520 
0521     if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
0522         return;
0523 
0524     pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP);
0525     cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION);
0526 
0527     dev_dbg(cc->dev->dev, "Found rev %u PMU (capabilities 0x%08X)\n",
0528         cc->pmu.rev, pmucap);
0529 
0530     if (cc->pmu.rev == 1)
0531         chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
0532                   ~SSB_CHIPCO_PMU_CTL_NOILPONW);
0533     else
0534         chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
0535                  SSB_CHIPCO_PMU_CTL_NOILPONW);
0536     ssb_pmu_pll_init(cc);
0537     ssb_pmu_resources_init(cc);
0538 }
0539 
0540 void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
0541                  enum ssb_pmu_ldo_volt_id id, u32 voltage)
0542 {
0543     struct ssb_bus *bus = cc->dev->bus;
0544     u32 addr, shift, mask;
0545 
0546     switch (bus->chip_id) {
0547     case 0x4328:
0548     case 0x5354:
0549         switch (id) {
0550         case LDO_VOLT1:
0551             addr = 2;
0552             shift = 25;
0553             mask = 0xF;
0554             break;
0555         case LDO_VOLT2:
0556             addr = 3;
0557             shift = 1;
0558             mask = 0xF;
0559             break;
0560         case LDO_VOLT3:
0561             addr = 3;
0562             shift = 9;
0563             mask = 0xF;
0564             break;
0565         case LDO_PAREF:
0566             addr = 3;
0567             shift = 17;
0568             mask = 0x3F;
0569             break;
0570         default:
0571             WARN_ON(1);
0572             return;
0573         }
0574         break;
0575     case 0x4312:
0576         if (WARN_ON(id != LDO_PAREF))
0577             return;
0578         addr = 0;
0579         shift = 21;
0580         mask = 0x3F;
0581         break;
0582     default:
0583         return;
0584     }
0585 
0586     ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
0587                   (voltage & mask) << shift);
0588 }
0589 
0590 void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
0591 {
0592     struct ssb_bus *bus = cc->dev->bus;
0593     int ldo;
0594 
0595     switch (bus->chip_id) {
0596     case 0x4312:
0597         ldo = SSB_PMURES_4312_PA_REF_LDO;
0598         break;
0599     case 0x4328:
0600         ldo = SSB_PMURES_4328_PA_REF_LDO;
0601         break;
0602     case 0x5354:
0603         ldo = SSB_PMURES_5354_PA_REF_LDO;
0604         break;
0605     default:
0606         return;
0607     }
0608 
0609     if (on)
0610         chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
0611     else
0612         chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
0613     chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
0614 }
0615 
0616 EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
0617 EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
0618 
0619 static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
0620 {
0621     u32 crystalfreq;
0622     const struct pmu0_plltab_entry *e = NULL;
0623 
0624     crystalfreq = (chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
0625                SSB_CHIPCO_PMU_CTL_XTALFREQ)  >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
0626     e = pmu0_plltab_find_entry(crystalfreq);
0627     BUG_ON(!e);
0628     return e->freq * 1000;
0629 }
0630 
0631 u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
0632 {
0633     struct ssb_bus *bus = cc->dev->bus;
0634 
0635     switch (bus->chip_id) {
0636     case 0x5354:
0637         return ssb_pmu_get_alp_clock_clk0(cc);
0638     default:
0639         dev_err(cc->dev->dev, "ERROR: PMU alp clock unknown for device %04X\n",
0640             bus->chip_id);
0641         return 0;
0642     }
0643 }
0644 
0645 u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
0646 {
0647     struct ssb_bus *bus = cc->dev->bus;
0648 
0649     switch (bus->chip_id) {
0650     case 0x5354:
0651         /* 5354 chip uses a non programmable PLL of frequency 240MHz */
0652         return 240000000;
0653     default:
0654         dev_err(cc->dev->dev, "ERROR: PMU cpu clock unknown for device %04X\n",
0655             bus->chip_id);
0656         return 0;
0657     }
0658 }
0659 
0660 u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
0661 {
0662     struct ssb_bus *bus = cc->dev->bus;
0663 
0664     switch (bus->chip_id) {
0665     case 0x5354:
0666         return 120000000;
0667     default:
0668         dev_err(cc->dev->dev, "ERROR: PMU controlclock unknown for device %04X\n",
0669             bus->chip_id);
0670         return 0;
0671     }
0672 }
0673 
0674 void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
0675 {
0676     u32 pmu_ctl = 0;
0677 
0678     switch (cc->dev->bus->chip_id) {
0679     case 0x4322:
0680         ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
0681         ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
0682         ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
0683         if (spuravoid == 1)
0684             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
0685         else
0686             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
0687         pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
0688         break;
0689     case 43222:
0690         if (spuravoid == 1) {
0691             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11500008);
0692             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0C000C06);
0693             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x0F600a08);
0694             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
0695             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x2001E920);
0696             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888815);
0697         } else {
0698             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100008);
0699             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0c000c06);
0700             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x03000a08);
0701             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
0702             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x200005c0);
0703             ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888855);
0704         }
0705         pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
0706         break;
0707     default:
0708         dev_err(cc->dev->dev,
0709             "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
0710             cc->dev->bus->chip_id);
0711         return;
0712     }
0713 
0714     chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
0715 }
0716 EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);