drivers/pwm/pwm-img.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-img.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-img.c- Extension
.c- Size
- 10723 bytes
- Lines
- 424
- Domain
- Driver Families
- Bucket
- drivers/pwm
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/err.hlinux/io.hlinux/mfd/syscon.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_runtime.hlinux/property.hlinux/pwm.hlinux/regmap.hlinux/slab.h
Detected Declarations
struct img_pwm_soc_datastruct img_pwm_chipfunction img_pwm_writelfunction img_pwm_readlfunction img_pwm_configfunction img_pwm_enablefunction img_pwm_disablefunction img_pwm_applyfunction img_pwm_runtime_suspendfunction img_pwm_runtime_resumefunction img_pwm_probefunction img_pwm_removefunction img_pwm_suspendfunction img_pwm_resume
Annotated Snippet
struct img_pwm_soc_data {
u32 max_timebase;
};
struct img_pwm_chip {
struct clk *pwm_clk;
struct clk *sys_clk;
void __iomem *base;
struct regmap *periph_regs;
int max_period_ns;
int min_period_ns;
const struct img_pwm_soc_data *data;
u32 suspend_ctrl_cfg;
u32 suspend_ch_cfg[IMG_PWM_NPWM];
};
static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static inline void img_pwm_writel(struct img_pwm_chip *imgchip,
u32 reg, u32 val)
{
writel(val, imgchip->base + reg);
}
static inline u32 img_pwm_readl(struct img_pwm_chip *imgchip, u32 reg)
{
return readl(imgchip->base + reg);
}
static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
u32 val, div, duty, timebase;
unsigned long mul, output_clk_hz, input_clk_hz;
struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
unsigned int max_timebase = imgchip->data->max_timebase;
int ret;
if (period_ns < imgchip->min_period_ns ||
period_ns > imgchip->max_period_ns) {
dev_err(pwmchip_parent(chip), "configured period not in range\n");
return -ERANGE;
}
input_clk_hz = clk_get_rate(imgchip->pwm_clk);
output_clk_hz = DIV_ROUND_UP(NSEC_PER_SEC, period_ns);
mul = DIV_ROUND_UP(input_clk_hz, output_clk_hz);
if (mul <= max_timebase) {
div = PWM_CTRL_CFG_NO_SUB_DIV;
timebase = DIV_ROUND_UP(mul, 1);
} else if (mul <= max_timebase * 8) {
div = PWM_CTRL_CFG_SUB_DIV0;
timebase = DIV_ROUND_UP(mul, 8);
} else if (mul <= max_timebase * 64) {
div = PWM_CTRL_CFG_SUB_DIV1;
timebase = DIV_ROUND_UP(mul, 64);
} else if (mul <= max_timebase * 512) {
div = PWM_CTRL_CFG_SUB_DIV0_DIV1;
timebase = DIV_ROUND_UP(mul, 512);
} else {
dev_err(pwmchip_parent(chip),
"failed to configure timebase steps/divider value\n");
return -EINVAL;
}
duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);
ret = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (ret < 0)
return ret;
val = img_pwm_readl(imgchip, PWM_CTRL_CFG);
val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm));
val |= (div & PWM_CTRL_CFG_DIV_MASK) <<
PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm);
img_pwm_writel(imgchip, PWM_CTRL_CFG, val);
val = (duty << PWM_CH_CFG_DUTY_SHIFT) |
(timebase << PWM_CH_CFG_TMBASE_SHIFT);
img_pwm_writel(imgchip, PWM_CH_CFG(pwm->hwpwm), val);
pm_runtime_put_autosuspend(pwmchip_parent(chip));
return 0;
}
Annotation
- Immediate include surface: `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/mfd/syscon.h`, `linux/module.h`, `linux/of.h`, `linux/platform_device.h`, `linux/pm_runtime.h`.
- Detected declarations: `struct img_pwm_soc_data`, `struct img_pwm_chip`, `function img_pwm_writel`, `function img_pwm_readl`, `function img_pwm_config`, `function img_pwm_enable`, `function img_pwm_disable`, `function img_pwm_apply`, `function img_pwm_runtime_suspend`, `function img_pwm_runtime_resume`.
- Atlas domain: Driver Families / drivers/pwm.
- 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.