^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Sonics Silicon Backplane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Broadcom ChipCommon Power Management Unit driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2009, Michael Buesch <m@bues.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2007, Broadcom Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Licensed under the GNU/GPL. See COPYING for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "ssb_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ssb/ssb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ssb/ssb_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ssb/ssb_driver_chipcommon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_BCM47XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/bcm47xx_nvram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void ssb_chipco_pll_write(struct ssb_chipcommon *cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u32 offset, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 offset, u32 mask, u32 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) value &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) value |= set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct pmu0_plltab_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u16 freq; /* Crystal frequency in kHz.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 xf; /* Crystal frequency value for PMU control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u8 wb_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 wb_frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static const struct pmu0_plltab_entry pmu0_plltab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define SSB_PMU0_DEFAULT_XTALFREQ 20000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const struct pmu0_plltab_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) e = &pmu0_plltab[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (e->freq == crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Tune the PLL to the crystal speed. crystalfreq is in kHz. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const struct pmu0_plltab_entry *e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 pmuctl, tmp, pllctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) e = pmu0_plltab_find_entry(crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) BUG_ON(!e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) crystalfreq = e->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) cc->pmu.crystalfreq = e->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Check if the PLL already is programmed to this frequency. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* We're already there... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) crystalfreq / 1000, crystalfreq % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* First turn the PLL off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case 0x4328:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ~(1 << SSB_PMURES_4328_BB_PLL_PU));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ~(1 << SSB_PMURES_4328_BB_PLL_PU));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ~(1 << SSB_PMURES_5354_BB_PLL_PU));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ~(1 << SSB_PMURES_5354_BB_PLL_PU));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for (i = 1500; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Set PDIV in PLL control 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Set WILD in PLL control 1. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (e->wb_frac == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) pllctl |= SSB_PMU0_PLLCTL1_STOPMOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Set WILD in PLL control 2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Set the crystalfrequency and the divisor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) & SSB_CHIPCO_PMU_CTL_ILP_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pmu1_plltab_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u16 freq; /* Crystal frequency in kHz.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 xf; /* Crystal frequency value for PMU control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u8 ndiv_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 ndiv_frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 p1div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u8 p2div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static const struct pmu1_plltab_entry pmu1_plltab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { .freq = 12000, .xf = 1, .p1div = 3, .p2div = 22, .ndiv_int = 0x9, .ndiv_frac = 0xFFFFEF, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { .freq = 13000, .xf = 2, .p1div = 1, .p2div = 6, .ndiv_int = 0xb, .ndiv_frac = 0x483483, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { .freq = 14400, .xf = 3, .p1div = 1, .p2div = 10, .ndiv_int = 0xa, .ndiv_frac = 0x1C71C7, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { .freq = 15360, .xf = 4, .p1div = 1, .p2div = 5, .ndiv_int = 0xb, .ndiv_frac = 0x755555, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { .freq = 16200, .xf = 5, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x6E9E06, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { .freq = 16800, .xf = 6, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x3CF3CF, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { .freq = 19200, .xf = 7, .p1div = 1, .p2div = 9, .ndiv_int = 0x5, .ndiv_frac = 0x17B425, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { .freq = 19800, .xf = 8, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0xA57EB, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { .freq = 20000, .xf = 9, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int = 0xa, .ndiv_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int = 0xb, .ndiv_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { .freq = 26000, .xf = 12, .p1div = 1, .p2div = 2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { .freq = 30000, .xf = 13, .p1div = 3, .p2div = 8, .ndiv_int = 0xb, .ndiv_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { .freq = 38400, .xf = 14, .p1div = 1, .p2div = 5, .ndiv_int = 0x4, .ndiv_frac = 0x955555, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { .freq = 40000, .xf = 15, .p1div = 1, .p2div = 2, .ndiv_int = 0xb, .ndiv_frac = 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define SSB_PMU1_DEFAULT_XTALFREQ 15360
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const struct pmu1_plltab_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) e = &pmu1_plltab[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (e->freq == crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Tune the PLL to the crystal speed. crystalfreq is in kHz. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u32 crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) const struct pmu1_plltab_entry *e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u32 buffer_strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 tmp, pllctl, pmuctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (bus->chip_id == 0x4312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* We do not touch the BCM4312 PLL and assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * the default crystal settings work out-of-the-box. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cc->pmu.crystalfreq = 20000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (crystalfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) e = pmu1_plltab_find_entry(crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) BUG_ON(!e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) crystalfreq = e->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) cc->pmu.crystalfreq = e->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* Check if the PLL already is programmed to this frequency. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* We're already there... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) crystalfreq / 1000, crystalfreq % 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* First turn the PLL off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 0x4325:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) (1 << SSB_PMURES_4325_HT_AVAIL)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) (1 << SSB_PMURES_4325_HT_AVAIL)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* Adjust the BBPLL to 2 on all channels later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) buffer_strength = 0x222222;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (i = 1500; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* Set p1div and p2div. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* Set ndiv int and ndiv mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* Set ndiv frac */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Change the drive strength, if required. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (buffer_strength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Tune the crystalfreq and the divisor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) & SSB_CHIPCO_PMU_CTL_ILP_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (bus->bustype == SSB_BUSTYPE_SSB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) #ifdef CONFIG_BCM47XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) char buf[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) crystalfreq = simple_strtoul(buf, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case 0x4312:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case 0x4325:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ssb_pmu1_pllinit_r0(cc, crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case 0x4328:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ssb_pmu0_pllinit_r0(cc, crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (crystalfreq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) crystalfreq = 25000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ssb_pmu0_pllinit_r0(cc, crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case 0x4322:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (cc->pmu.rev == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case 43222:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dev_err(cc->dev->dev, "ERROR: PLL init unknown for device %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct pmu_res_updown_tab_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) u8 resource; /* The resource number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u16 updown; /* The updown value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) enum pmu_res_depend_tab_task {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) PMU_RES_DEP_SET = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) PMU_RES_DEP_ADD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) PMU_RES_DEP_REMOVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct pmu_res_depend_tab_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u8 resource; /* The resource number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u8 task; /* SET | ADD | REMOVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u32 depend; /* The depend mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM, .updown = 0x1F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST, .updown = 0x010F, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) { .resource = SSB_PMURES_4328_ILP_REQUEST, .updown = 0x0202, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) { .resource = SSB_PMURES_4328_ROM_SWITCH, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) { .resource = SSB_PMURES_4328_PA_REF_LDO, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) { .resource = SSB_PMURES_4328_RADIO_LDO, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) { .resource = SSB_PMURES_4328_AFE_LDO, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) { .resource = SSB_PMURES_4328_PLL_LDO, .updown = 0x0F01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { .resource = SSB_PMURES_4328_BG_FILTBYP, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) { .resource = SSB_PMURES_4328_TX_FILTBYP, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { .resource = SSB_PMURES_4328_RX_FILTBYP, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) { .resource = SSB_PMURES_4328_XTAL_PU, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) { .resource = SSB_PMURES_4328_XTAL_EN, .updown = 0xA001, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP, .updown = 0x0101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) { .resource = SSB_PMURES_4328_BB_PLL_PU, .updown = 0x0701, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .resource = SSB_PMURES_4328_ILP_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .task = PMU_RES_DEP_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) { .resource = SSB_PMURES_4325_XTAL_PU, .updown = 0x1501, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Adjust HT-Available dependencies. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .resource = SSB_PMURES_4325_HT_AVAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .task = PMU_RES_DEP_ADD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) (1 << SSB_PMURES_4325_TX_PWRSW_PU) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) (1 << SSB_PMURES_4325_AFE_PWRSW_PU)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u32 min_msk = 0, max_msk = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) const struct pmu_res_updown_tab_entry *updown_tab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) unsigned int updown_tab_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) const struct pmu_res_depend_tab_entry *depend_tab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned int depend_tab_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case 0x4312:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) min_msk = 0xCBB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case 0x4322:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) case 43222:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* We keep the default settings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * min_msk = 0xCBB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * max_msk = 0x7FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case 0x4325:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* Power OTP down later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) (1 << SSB_PMURES_4325_LNLDO2_PU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) SSB_CHIPCO_CHST_4325_PMUTOP_2B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* The PLL may turn on, if it decides so. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) max_msk = 0xFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) updown_tab = pmu_res_updown_tab_4325a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) depend_tab = pmu_res_depend_tab_4325a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) case 0x4328:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) (1 << SSB_PMURES_4328_XTAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* The PLL may turn on, if it decides so. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) max_msk = 0xFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) updown_tab = pmu_res_updown_tab_4328a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) depend_tab = pmu_res_depend_tab_4328a0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* The PLL may turn on, if it decides so. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) max_msk = 0xFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dev_err(cc->dev->dev, "ERROR: PMU resource config unknown for device %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (updown_tab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) for (i = 0; i < updown_tab_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) updown_tab[i].resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) updown_tab[i].updown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (depend_tab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) for (i = 0; i < depend_tab_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) depend_tab[i].resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) switch (depend_tab[i].task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case PMU_RES_DEP_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) depend_tab[i].depend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) case PMU_RES_DEP_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) depend_tab[i].depend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case PMU_RES_DEP_REMOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ~(depend_tab[i].depend));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* Set the resource masks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (min_msk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (max_msk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* https://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) void ssb_pmu_init(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u32 pmucap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_dbg(cc->dev->dev, "Found rev %u PMU (capabilities 0x%08X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) cc->pmu.rev, pmucap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (cc->pmu.rev == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ~SSB_CHIPCO_PMU_CTL_NOILPONW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) SSB_CHIPCO_PMU_CTL_NOILPONW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ssb_pmu_pll_init(cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ssb_pmu_resources_init(cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) enum ssb_pmu_ldo_volt_id id, u32 voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) u32 addr, shift, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case 0x4328:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) case LDO_VOLT1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) addr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) shift = 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case LDO_VOLT2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) addr = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) shift = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case LDO_VOLT3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) addr = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) shift = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case LDO_PAREF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) addr = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) shift = 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) mask = 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case 0x4312:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (WARN_ON(id != LDO_PAREF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) shift = 21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) mask = 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) (voltage & mask) << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int ldo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case 0x4312:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) ldo = SSB_PMURES_4312_PA_REF_LDO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) case 0x4328:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ldo = SSB_PMURES_4328_PA_REF_LDO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ldo = SSB_PMURES_5354_PA_REF_LDO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) u32 crystalfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) const struct pmu0_plltab_entry *e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) crystalfreq = (chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) e = pmu0_plltab_find_entry(crystalfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) BUG_ON(!e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return e->freq * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return ssb_pmu_get_alp_clock_clk0(cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dev_err(cc->dev->dev, "ERROR: PMU alp clock unknown for device %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* 5354 chip uses a non programmable PLL of frequency 240MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 240000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) dev_err(cc->dev->dev, "ERROR: PMU cpu clock unknown for device %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct ssb_bus *bus = cc->dev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) switch (bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case 0x5354:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return 120000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) dev_err(cc->dev->dev, "ERROR: PMU controlclock unknown for device %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) u32 pmu_ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) switch (cc->dev->bus->chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) case 0x4322:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (spuravoid == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 43222:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (spuravoid == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11500008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0C000C06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x0F600a08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x2001E920);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888815);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0c000c06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x03000a08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x200005c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888855);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dev_err(cc->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) cc->dev->bus->chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);