drivers/devfreq/sun8i-a33-mbus.c
Source file repositories/reference/linux-study-clean/drivers/devfreq/sun8i-a33-mbus.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/devfreq/sun8i-a33-mbus.c- Extension
.c- Size
- 14453 bytes
- Lines
- 490
- Domain
- Driver Families
- Bucket
- drivers/devfreq
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/devfreq.hlinux/err.hlinux/io.hlinux/iopoll.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/property.h
Detected Declarations
struct sun8i_a33_mbus_variantstruct sun8i_a33_mbusfunction sun8i_a33_mbus_get_peak_bwfunction sun8i_a33_mbus_restart_pmu_countersfunction sun8i_a33_mbus_update_nominal_bwfunction sun8i_a33_mbus_set_dram_freqfunction sun8i_a33_mbus_set_dram_targetfunction sun8i_a33_mbus_get_dram_statusfunction sun8i_a33_mbus_hw_initfunction sun8i_a33_mbus_suspendfunction sun8i_a33_mbus_resumefunction sun8i_a33_mbus_probefunction sun8i_a33_mbus_remove
Annotated Snippet
struct sun8i_a33_mbus_variant {
u32 min_dram_divider;
u32 max_dram_divider;
u32 odt_freq_mhz;
};
struct sun8i_a33_mbus {
const struct sun8i_a33_mbus_variant *variant;
void __iomem *reg_dram;
void __iomem *reg_mbus;
struct clk *clk_bus;
struct clk *clk_dram;
struct clk *clk_mbus;
struct devfreq *devfreq_dram;
struct devfreq_simple_ondemand_data gov_data;
struct devfreq_dev_profile profile;
u32 data_width;
u32 nominal_bw;
u32 odtmap;
u32 tREFI_ns;
u32 tRFC_ns;
unsigned long freq_table[];
};
/*
* The unit for this value is (MBUS clock cycles / MBUS_TMR_PERIOD). When
* MBUS_TMR_PERIOD is programmed to match the MBUS clock frequency in MHz, as
* it is during DRAM init and during probe, the resulting unit is microseconds.
*/
static int pmu_period = 50000;
module_param(pmu_period, int, 0644);
MODULE_PARM_DESC(pmu_period, "Bandwidth measurement period (microseconds)");
static u32 sun8i_a33_mbus_get_peak_bw(struct sun8i_a33_mbus *priv)
{
/* Returns the peak transfer (in KiB) during any single PMU period. */
return readl_relaxed(priv->reg_mbus + MBUS_TOTAL_BWCR);
}
static void sun8i_a33_mbus_restart_pmu_counters(struct sun8i_a33_mbus *priv)
{
u32 pmu_cfg = MBUS_PMU_CFG_PERIOD(pmu_period) | MBUS_PMU_CFG_UNIT_KB;
/* All PMU counters are cleared on a disable->enable transition. */
writel_relaxed(pmu_cfg,
priv->reg_mbus + MBUS_PMU_CFG);
writel_relaxed(pmu_cfg | MBUS_PMU_CFG_ENABLE,
priv->reg_mbus + MBUS_PMU_CFG);
}
static void sun8i_a33_mbus_update_nominal_bw(struct sun8i_a33_mbus *priv,
u32 ddr_freq_mhz)
{
/*
* Nominal bandwidth (KiB per PMU period):
*
* DDR transfers microseconds KiB
* ------------- * ------------ * --------
* microsecond PMU period transfer
*/
priv->nominal_bw = ddr_freq_mhz * pmu_period * priv->data_width / 1024;
}
static int sun8i_a33_mbus_set_dram_freq(struct sun8i_a33_mbus *priv,
unsigned long freq)
{
u32 ddr_freq_mhz = freq / USEC_PER_SEC; /* DDR */
u32 dram_freq_mhz = ddr_freq_mhz / 2; /* SDR */
u32 mctl_freq_mhz = dram_freq_mhz / 2; /* HDR */
u32 dxodt, mdfscr, pwrctl, vtfcr;
u32 i, tREFI_32ck, tRFC_ck;
int ret;
/* The rate change is not effective until the MDFS process runs. */
ret = clk_set_rate(priv->clk_dram, freq);
if (ret)
return ret;
/* Disable automatic self-refesh and VTF before starting MDFS. */
pwrctl = readl_relaxed(priv->reg_dram + DRAM_PWRCTL) &
~DRAM_PWRCTL_SELFREF_EN;
writel_relaxed(pwrctl, priv->reg_dram + DRAM_PWRCTL);
vtfcr = readl_relaxed(priv->reg_dram + DRAM_VTFCR);
writel_relaxed(vtfcr & ~DRAM_VTFCR_VTF_ENABLE,
priv->reg_dram + DRAM_VTFCR);
/* Set up MDFS and enable double buffering for timing registers. */
mdfscr = MBUS_MDFSCR_MODE_DFS |
MBUS_MDFSCR_BYPASS |
Annotation
- Immediate include surface: `linux/clk.h`, `linux/devfreq.h`, `linux/err.h`, `linux/io.h`, `linux/iopoll.h`, `linux/module.h`, `linux/of.h`, `linux/platform_device.h`.
- Detected declarations: `struct sun8i_a33_mbus_variant`, `struct sun8i_a33_mbus`, `function sun8i_a33_mbus_get_peak_bw`, `function sun8i_a33_mbus_restart_pmu_counters`, `function sun8i_a33_mbus_update_nominal_bw`, `function sun8i_a33_mbus_set_dram_freq`, `function sun8i_a33_mbus_set_dram_target`, `function sun8i_a33_mbus_get_dram_status`, `function sun8i_a33_mbus_hw_init`, `function sun8i_a33_mbus_suspend`.
- Atlas domain: Driver Families / drivers/devfreq.
- Implementation status: source 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.