drivers/devfreq/rk3399_dmc.c
Source file repositories/reference/linux-study-clean/drivers/devfreq/rk3399_dmc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/devfreq/rk3399_dmc.c- Extension
.c- Size
- 13643 bytes
- Lines
- 489
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/arm-smccc.hlinux/bitfield.hlinux/clk.hlinux/delay.hlinux/devfreq.hlinux/devfreq-event.hlinux/interrupt.hlinux/mfd/syscon.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_opp.hlinux/regmap.hlinux/regulator/consumer.hlinux/rwsem.hlinux/suspend.hsoc/rockchip/pm_domains.hsoc/rockchip/rockchip_grf.hsoc/rockchip/rk3399_grf.hsoc/rockchip/rockchip_sip.h
Detected Declarations
struct rk3399_dmcfreqfunction rk3399_dmcfreq_targetfunction rk3399_dmcfreq_get_dev_statusfunction rk3399_dmcfreq_get_cur_freqfunction rk3399_dmcfreq_suspendfunction rk3399_dmcfreq_resumefunction rk3399_dmcfreq_of_propsfunction rk3399_dmcfreq_probefunction rk3399_dmcfreq_remove
Annotated Snippet
struct rk3399_dmcfreq {
struct device *dev;
struct devfreq *devfreq;
struct devfreq_dev_profile profile;
struct devfreq_simple_ondemand_data ondemand_data;
struct clk *dmc_clk;
struct devfreq_event_dev *edev;
struct mutex lock;
struct regulator *vdd_center;
struct regmap *regmap_pmu;
unsigned long rate, target_rate;
unsigned long volt, target_volt;
unsigned int odt_dis_freq;
unsigned int pd_idle_ns;
unsigned int sr_idle_ns;
unsigned int sr_mc_gate_idle_ns;
unsigned int srpd_lite_idle_ns;
unsigned int standby_idle_ns;
unsigned int ddr3_odt_dis_freq;
unsigned int lpddr3_odt_dis_freq;
unsigned int lpddr4_odt_dis_freq;
unsigned int pd_idle_dis_freq;
unsigned int sr_idle_dis_freq;
unsigned int sr_mc_gate_idle_dis_freq;
unsigned int srpd_lite_idle_dis_freq;
unsigned int standby_idle_dis_freq;
};
static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
struct dev_pm_opp *opp;
unsigned long old_clk_rate = dmcfreq->rate;
unsigned long target_volt, target_rate;
unsigned int ddrcon_mhz;
struct arm_smccc_res res;
int err;
u32 odt_pd_arg0 = 0;
u32 odt_pd_arg1 = 0;
u32 odt_pd_arg2 = 0;
opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp))
return PTR_ERR(opp);
target_rate = dev_pm_opp_get_freq(opp);
target_volt = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
if (dmcfreq->rate == target_rate)
return 0;
mutex_lock(&dmcfreq->lock);
/*
* Ensure power-domain transitions don't interfere with ARM Trusted
* Firmware power-domain idling.
*/
err = rockchip_pmu_block();
if (err) {
dev_err(dev, "Failed to block PMU: %d\n", err);
goto out_unlock;
}
/*
* Some idle parameters may be based on the DDR controller clock, which
* is half of the DDR frequency.
* pd_idle and standby_idle are based on the controller clock cycle.
* sr_idle_cycle, sr_mc_gate_idle_cycle, and srpd_lite_idle_cycle
* are based on the 1024 controller clock cycle
*/
ddrcon_mhz = target_rate / USEC_PER_SEC / 2;
u32p_replace_bits(&odt_pd_arg1,
NS_TO_CYCLE(dmcfreq->pd_idle_ns, ddrcon_mhz),
RK3399_SET_ODT_PD_1_PD_IDLE);
u32p_replace_bits(&odt_pd_arg0,
NS_TO_CYCLE(dmcfreq->standby_idle_ns, ddrcon_mhz),
RK3399_SET_ODT_PD_0_STANDBY_IDLE);
u32p_replace_bits(&odt_pd_arg0,
DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_idle_ns,
ddrcon_mhz), 1024),
RK3399_SET_ODT_PD_0_SR_IDLE);
u32p_replace_bits(&odt_pd_arg0,
DIV_ROUND_UP(NS_TO_CYCLE(dmcfreq->sr_mc_gate_idle_ns,
ddrcon_mhz), 1024),
Annotation
- Immediate include surface: `linux/arm-smccc.h`, `linux/bitfield.h`, `linux/clk.h`, `linux/delay.h`, `linux/devfreq.h`, `linux/devfreq-event.h`, `linux/interrupt.h`, `linux/mfd/syscon.h`.
- Detected declarations: `struct rk3399_dmcfreq`, `function rk3399_dmcfreq_target`, `function rk3399_dmcfreq_get_dev_status`, `function rk3399_dmcfreq_get_cur_freq`, `function rk3399_dmcfreq_suspend`, `function rk3399_dmcfreq_resume`, `function rk3399_dmcfreq_of_props`, `function rk3399_dmcfreq_probe`, `function rk3399_dmcfreq_remove`.
- Atlas domain: Driver Families / drivers/devfreq.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.