drivers/pwm/pwm-sun4i.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-sun4i.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-sun4i.c- Extension
.c- Size
- 12899 bytes
- Lines
- 494
- 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/bitops.hlinux/clk.hlinux/delay.hlinux/err.hlinux/io.hlinux/jiffies.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pwm.hlinux/reset.hlinux/slab.hlinux/time.h
Detected Declarations
struct sun4i_pwm_datastruct sun4i_pwm_chipfunction sun4i_pwm_readlfunction sun4i_pwm_writelfunction sun4i_pwm_get_statefunction sun4i_pwm_calculatefunction sun4i_pwm_applyfunction sun4i_pwm_probefunction sun4i_pwm_remove
Annotated Snippet
struct sun4i_pwm_data {
bool has_prescaler_bypass;
bool has_direct_mod_clk_output;
unsigned int npwm;
};
struct sun4i_pwm_chip {
struct clk *bus_clk;
struct clk *clk;
struct reset_control *rst;
void __iomem *base;
const struct sun4i_pwm_data *data;
};
static inline struct sun4i_pwm_chip *to_sun4i_pwm_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static inline u32 sun4i_pwm_readl(struct sun4i_pwm_chip *sun4ichip,
unsigned long offset)
{
return readl(sun4ichip->base + offset);
}
static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *sun4ichip,
u32 val, unsigned long offset)
{
writel(val, sun4ichip->base + offset);
}
static int sun4i_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state)
{
struct sun4i_pwm_chip *sun4ichip = to_sun4i_pwm_chip(chip);
u64 clk_rate, tmp;
u32 val;
unsigned int prescaler;
clk_rate = clk_get_rate(sun4ichip->clk);
if (!clk_rate)
return -EINVAL;
val = sun4i_pwm_readl(sun4ichip, PWM_CTRL_REG);
/*
* PWM chapter in H6 manual has a diagram which explains that if bypass
* bit is set, no other setting has any meaning. Even more, experiment
* proved that also enable bit is ignored in this case.
*/
if ((val & BIT_CH(PWM_BYPASS, pwm->hwpwm)) &&
sun4ichip->data->has_direct_mod_clk_output) {
state->period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, clk_rate);
state->duty_cycle = DIV_ROUND_UP_ULL(state->period, 2);
state->polarity = PWM_POLARITY_NORMAL;
state->enabled = true;
return 0;
}
if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) &&
sun4ichip->data->has_prescaler_bypass)
prescaler = 1;
else
prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)];
if (prescaler == 0)
return -EINVAL;
if (val & BIT_CH(PWM_ACT_STATE, pwm->hwpwm))
state->polarity = PWM_POLARITY_NORMAL;
else
state->polarity = PWM_POLARITY_INVERSED;
if ((val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) ==
BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm))
state->enabled = true;
else
state->enabled = false;
val = sun4i_pwm_readl(sun4ichip, PWM_CH_PRD(pwm->hwpwm));
tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_DTY(val);
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_PRD(val);
state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
return 0;
}
Annotation
- Immediate include surface: `linux/bitops.h`, `linux/clk.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/jiffies.h`, `linux/module.h`, `linux/of.h`.
- Detected declarations: `struct sun4i_pwm_data`, `struct sun4i_pwm_chip`, `function sun4i_pwm_readl`, `function sun4i_pwm_writel`, `function sun4i_pwm_get_state`, `function sun4i_pwm_calculate`, `function sun4i_pwm_apply`, `function sun4i_pwm_probe`, `function sun4i_pwm_remove`.
- 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.