drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a_devfreq.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a_devfreq.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a_devfreq.c- Extension
.c- Size
- 9910 bytes
- Lines
- 321
- Domain
- Driver Families
- Bucket
- drivers/gpu
- 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/math64.hlinux/platform_device.hlinux/pm_opp.hdrm/drm_managed.hsubdev/clk.hnouveau_drv.hnouveau_chan.hpriv.hgk20a_devfreq.hgk20a.hgp10b.h
Detected Declarations
struct gk20a_devfreqfunction gk20a_pmu_init_perfmon_counterfunction gk20a_pmu_read_idle_counterfunction gk20a_pmu_reset_idle_counterfunction gk20a_pmu_read_idle_intr_statusfunction gk20a_pmu_clear_idle_intr_statusfunction gk20a_devfreq_update_utilizationfunction gk20a_devfreq_targetfunction gk20a_devfreq_get_cur_freqfunction gk20a_devfreq_resetfunction gk20a_devfreq_get_dev_statusfunction gk20a_devfreq_initfunction gk20a_devfreq_resumefunction gk20a_devfreq_suspend
Annotated Snippet
struct gk20a_devfreq {
/** @devfreq: devfreq device. */
struct devfreq *devfreq;
/** @regs: Device registers. */
void __iomem *regs;
/** @gov_data: Governor data. */
struct devfreq_simple_ondemand_data gov_data;
/** @busy_time: Busy time. */
ktime_t busy_time;
/** @total_time: Total time. */
ktime_t total_time;
/** @time_last_update: Last update time. */
ktime_t time_last_update;
};
static struct gk20a_devfreq *dev_to_gk20a_devfreq(struct device *dev)
{
struct nouveau_drm *drm = dev_get_drvdata(dev);
struct nvkm_subdev *subdev = nvkm_device_subdev(drm->nvkm, NVKM_SUBDEV_CLK, 0);
struct nvkm_clk *base = nvkm_clk(subdev);
switch (drm->nvkm->chipset) {
case 0x13b: return gp10b_clk(base)->devfreq; break;
default: return gk20a_clk(base)->devfreq; break;
}
}
static void gk20a_pmu_init_perfmon_counter(struct gk20a_devfreq *gdevfreq)
{
u32 data;
// Set pmu idle intr status bit on total counter overflow
writel(PWR_PMU_IDLE_INTR_ENABLE_VALUE,
gdevfreq->regs + PWR_PMU_IDLE_INTR_REG_OFFSET);
writel(PWR_PMU_IDLE_THRESHOLD_MAX_VALUE,
gdevfreq->regs + PWR_PMU_IDLE_THRESHOLD_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_TOTAL * PWR_PMU_IDLE_THRESHOLD_REG_SIZE));
// Setup counter for total cycles
data = readl(gdevfreq->regs + PWR_PMU_IDLE_CTRL_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_TOTAL * PWR_PMU_IDLE_CTRL_REG_SIZE));
data &= ~(PWR_PMU_IDLE_CTRL_VALUE_MASK | PWR_PMU_IDLE_CTRL_FILTER_MASK);
data |= PWR_PMU_IDLE_CTRL_VALUE_ALWAYS | PWR_PMU_IDLE_CTRL_FILTER_DISABLED;
writel(data, gdevfreq->regs + PWR_PMU_IDLE_CTRL_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_TOTAL * PWR_PMU_IDLE_CTRL_REG_SIZE));
// Setup counter for busy cycles
writel(PWM_PMU_IDLE_MASK_GR_ENABLED | PWM_PMU_IDLE_MASK_CE_2_ENABLED,
gdevfreq->regs + PWR_PMU_IDLE_MASK_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_BUSY * PWR_PMU_IDLE_MASK_REG_SIZE));
data = readl(gdevfreq->regs + PWR_PMU_IDLE_CTRL_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_BUSY * PWR_PMU_IDLE_CTRL_REG_SIZE));
data &= ~(PWR_PMU_IDLE_CTRL_VALUE_MASK | PWR_PMU_IDLE_CTRL_FILTER_MASK);
data |= PWR_PMU_IDLE_CTRL_VALUE_BUSY | PWR_PMU_IDLE_CTRL_FILTER_DISABLED;
writel(data, gdevfreq->regs + PWR_PMU_IDLE_CTRL_REG_OFFSET +
(PWR_PMU_IDLE_COUNTER_BUSY * PWR_PMU_IDLE_CTRL_REG_SIZE));
}
static u32 gk20a_pmu_read_idle_counter(struct gk20a_devfreq *gdevfreq, u32 counter_id)
{
u32 ret;
ret = readl(gdevfreq->regs + PWR_PMU_IDLE_COUNT_REG_OFFSET +
(counter_id * PWR_PMU_IDLE_COUNT_REG_SIZE));
return ret & PWR_PMU_IDLE_COUNT_MASK;
}
static void gk20a_pmu_reset_idle_counter(struct gk20a_devfreq *gdevfreq, u32 counter_id)
{
writel(PWR_PMU_IDLE_COUNT_RESET_VALUE, gdevfreq->regs + PWR_PMU_IDLE_COUNT_REG_OFFSET +
(counter_id * PWR_PMU_IDLE_COUNT_REG_SIZE));
}
static u32 gk20a_pmu_read_idle_intr_status(struct gk20a_devfreq *gdevfreq)
{
u32 ret;
ret = readl(gdevfreq->regs + PWR_PMU_IDLE_INTR_STATUS_REG_OFFSET);
return ret & PWR_PMU_IDLE_INTR_STATUS_MASK;
}
Annotation
- Immediate include surface: `linux/clk.h`, `linux/math64.h`, `linux/platform_device.h`, `linux/pm_opp.h`, `drm/drm_managed.h`, `subdev/clk.h`, `nouveau_drv.h`, `nouveau_chan.h`.
- Detected declarations: `struct gk20a_devfreq`, `function gk20a_pmu_init_perfmon_counter`, `function gk20a_pmu_read_idle_counter`, `function gk20a_pmu_reset_idle_counter`, `function gk20a_pmu_read_idle_intr_status`, `function gk20a_pmu_clear_idle_intr_status`, `function gk20a_devfreq_update_utilization`, `function gk20a_devfreq_target`, `function gk20a_devfreq_get_cur_freq`, `function gk20a_devfreq_reset`.
- Atlas domain: Driver Families / drivers/gpu.
- 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.