drivers/pwm/pwm-ep93xx.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-ep93xx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-ep93xx.c- Extension
.c- Size
- 4671 bytes
- Lines
- 194
- 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/module.hlinux/mod_devicetable.hlinux/platform_device.hlinux/slab.hlinux/clk.hlinux/err.hlinux/io.hlinux/pwm.hasm/div64.h
Detected Declarations
struct ep93xx_pwmfunction ep93xx_pwm_applyfunction ep93xx_pwm_probe
Annotated Snippet
struct ep93xx_pwm {
void __iomem *base;
struct clk *clk;
};
static inline struct ep93xx_pwm *to_ep93xx_pwm(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static int ep93xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
int ret;
struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
bool enabled = state->enabled;
void __iomem *base = ep93xx_pwm->base;
unsigned long long c;
unsigned long period_cycles;
unsigned long duty_cycles;
unsigned long term;
if (state->polarity != pwm->state.polarity) {
if (enabled) {
writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
clk_disable_unprepare(ep93xx_pwm->clk);
enabled = false;
}
/*
* The clock needs to be enabled to access the PWM registers.
* Polarity can only be changed when the PWM is disabled.
*/
ret = clk_prepare_enable(ep93xx_pwm->clk);
if (ret)
return ret;
if (state->polarity == PWM_POLARITY_INVERSED)
writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
else
writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
clk_disable_unprepare(ep93xx_pwm->clk);
}
if (!state->enabled) {
if (enabled) {
writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
clk_disable_unprepare(ep93xx_pwm->clk);
}
return 0;
}
/*
* The clock needs to be enabled to access the PWM registers.
* Configuration can be changed at any time.
*/
if (!pwm_is_enabled(pwm)) {
ret = clk_prepare_enable(ep93xx_pwm->clk);
if (ret)
return ret;
}
c = clk_get_rate(ep93xx_pwm->clk);
c *= state->period;
do_div(c, 1000000000);
period_cycles = c;
c = period_cycles;
c *= state->duty_cycle;
do_div(c, state->period);
duty_cycles = c;
if (period_cycles < 0x10000 && duty_cycles < 0x10000) {
term = readw(base + EP93XX_PWMx_TERM_COUNT);
/* Order is important if PWM is running */
if (period_cycles > term) {
writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
} else {
writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
}
ret = 0;
} else {
ret = -EINVAL;
}
Annotation
- Immediate include surface: `linux/module.h`, `linux/mod_devicetable.h`, `linux/platform_device.h`, `linux/slab.h`, `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/pwm.h`.
- Detected declarations: `struct ep93xx_pwm`, `function ep93xx_pwm_apply`, `function ep93xx_pwm_probe`.
- 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.