drivers/ssb/driver_chipcommon_pmu.c
Source file repositories/reference/linux-study-clean/drivers/ssb/driver_chipcommon_pmu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/ssb/driver_chipcommon_pmu.c- Extension
.c- Size
- 22521 bytes
- Lines
- 717
- Domain
- Driver Families
- Bucket
- drivers/ssb
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
ssb_private.hlinux/ssb/ssb.hlinux/ssb/ssb_regs.hlinux/ssb/ssb_driver_chipcommon.hlinux/delay.hlinux/export.hlinux/bcm47xx_nvram.h
Detected Declarations
struct pmu0_plltab_entrystruct pmu1_plltab_entrystruct pmu_res_updown_tab_entrystruct pmu_res_depend_tab_entryenum pmu_res_depend_tab_taskfunction ssb_chipco_pll_readfunction ssb_chipco_pll_writefunction ssb_chipco_regctl_masksetfunction pmu0_plltab_find_entryfunction ssb_pmu0_pllinit_r0function pmu1_plltab_find_entryfunction ssb_pmu1_pllinit_r0function ssb_pmu_pll_initfunction ssb_pmu_resources_initfunction ssb_pmu_initfunction ssb_pmu_set_ldo_voltagefunction ssb_pmu_set_ldo_pareffunction ssb_pmu_get_alp_clock_clk0function ssb_pmu_get_alp_clockfunction ssb_pmu_get_cpu_clockfunction ssb_pmu_get_controlclockfunction ssb_pmu_spuravoid_pllupdateexport ssb_pmu_set_ldo_voltageexport ssb_pmu_set_ldo_parefexport ssb_pmu_spuravoid_pllupdate
Annotated Snippet
struct pmu0_plltab_entry {
u16 freq; /* Crystal frequency in kHz.*/
u8 xf; /* Crystal frequency value for PMU control */
u8 wb_int;
u32 wb_frac;
};
static const struct pmu0_plltab_entry pmu0_plltab[] = {
{ .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, },
{ .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, },
{ .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, },
{ .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, },
{ .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, },
{ .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, },
{ .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, },
{ .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, },
{ .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, },
{ .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, },
{ .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, },
{ .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, },
{ .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, },
{ .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, },
};
#define SSB_PMU0_DEFAULT_XTALFREQ 20000
static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq)
{
const struct pmu0_plltab_entry *e;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) {
e = &pmu0_plltab[i];
if (e->freq == crystalfreq)
return e;
}
return NULL;
}
/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */
static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
u32 crystalfreq)
{
struct ssb_bus *bus = cc->dev->bus;
const struct pmu0_plltab_entry *e = NULL;
u32 pmuctl, tmp, pllctl;
unsigned int i;
if (crystalfreq)
e = pmu0_plltab_find_entry(crystalfreq);
if (!e)
e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ);
BUG_ON(!e);
crystalfreq = e->freq;
cc->pmu.crystalfreq = e->freq;
/* Check if the PLL already is programmed to this frequency. */
pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL);
if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) {
/* We're already there... */
return;
}
dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n",
crystalfreq / 1000, crystalfreq % 1000);
/* First turn the PLL off. */
switch (bus->chip_id) {
case 0x4328:
chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
~(1 << SSB_PMURES_4328_BB_PLL_PU));
chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
~(1 << SSB_PMURES_4328_BB_PLL_PU));
break;
case 0x5354:
chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK,
~(1 << SSB_PMURES_5354_BB_PLL_PU));
chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK,
~(1 << SSB_PMURES_5354_BB_PLL_PU));
break;
default:
WARN_ON(1);
}
for (i = 1500; i; i--) {
tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT))
break;
udelay(10);
}
tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
Annotation
- Immediate include surface: `ssb_private.h`, `linux/ssb/ssb.h`, `linux/ssb/ssb_regs.h`, `linux/ssb/ssb_driver_chipcommon.h`, `linux/delay.h`, `linux/export.h`, `linux/bcm47xx_nvram.h`.
- Detected declarations: `struct pmu0_plltab_entry`, `struct pmu1_plltab_entry`, `struct pmu_res_updown_tab_entry`, `struct pmu_res_depend_tab_entry`, `enum pmu_res_depend_tab_task`, `function ssb_chipco_pll_read`, `function ssb_chipco_pll_write`, `function ssb_chipco_regctl_maskset`, `function pmu0_plltab_find_entry`, `function ssb_pmu0_pllinit_r0`.
- Atlas domain: Driver Families / drivers/ssb.
- Implementation status: integration implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.