drivers/pwm/pwm-lpc18xx-sct.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-lpc18xx-sct.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-lpc18xx-sct.c- Extension
.c- Size
- 13310 bytes
- Lines
- 442
- 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/mod_devicetable.hlinux/module.hlinux/platform_device.hlinux/pwm.h
Detected Declarations
struct lpc18xx_pwm_datastruct lpc18xx_pwm_chipenum lpc18xx_pwm_res_actionfunction to_lpc18xx_pwm_chipfunction lpc18xx_pwm_writelfunction lpc18xx_pwm_readlfunction lpc18xx_pwm_set_conflict_resfunction lpc18xx_pwm_config_periodfunction lpc18xx_pwm_config_dutyfunction lpc18xx_pwm_configfunction lpc18xx_pwm_enablefunction lpc18xx_pwm_disablefunction lpc18xx_pwm_requestfunction lpc18xx_pwm_freefunction lpc18xx_pwm_applyfunction lpc18xx_pwm_probefunction lpc18xx_pwm_remove
Annotated Snippet
struct lpc18xx_pwm_data {
unsigned int duty_event;
};
struct lpc18xx_pwm_chip {
void __iomem *base;
struct clk *pwm_clk;
unsigned long clk_rate;
unsigned int period_ns;
unsigned int min_period_ns;
u64 max_period_ns;
unsigned int period_event;
unsigned long event_map;
struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS];
};
static inline struct lpc18xx_pwm_chip *
to_lpc18xx_pwm_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm,
u32 reg, u32 val)
{
writel(val, lpc18xx_pwm->base + reg);
}
static inline u32 lpc18xx_pwm_readl(struct lpc18xx_pwm_chip *lpc18xx_pwm,
u32 reg)
{
return readl(lpc18xx_pwm->base + reg);
}
static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm,
struct pwm_device *pwm,
enum lpc18xx_pwm_res_action action)
{
u32 val;
/*
* Simultaneous set and clear may happen on an output, that is the case
* when duty_ns == period_ns. LPC18xx SCT allows to set a conflict
* resolution action to be taken in such a case.
*/
val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_RES_BASE);
val &= ~LPC18XX_PWM_RES_MASK(pwm->hwpwm);
val |= LPC18XX_PWM_RES(pwm->hwpwm, action);
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_RES_BASE, val);
}
static void lpc18xx_pwm_config_period(struct pwm_chip *chip, u64 period_ns)
{
struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
u32 val;
/*
* With clk_rate < NSEC_PER_SEC this cannot overflow.
* With period_ns < max_period_ns this also fits into an u32.
* As period_ns >= min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, lpc18xx_pwm->clk_rate);
* we have val >= 1.
*/
val = mul_u64_u64_div_u64(period_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
lpc18xx_pwm_writel(lpc18xx_pwm,
LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event),
val - 1);
lpc18xx_pwm_writel(lpc18xx_pwm,
LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event),
val - 1);
}
static void lpc18xx_pwm_config_duty(struct pwm_chip *chip,
struct pwm_device *pwm, u64 duty_ns)
{
struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
u32 val;
/*
* With clk_rate <= NSEC_PER_SEC this cannot overflow.
* With duty_ns <= period_ns < max_period_ns this also fits into an u32.
*/
val = mul_u64_u64_div_u64(duty_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
lpc18xx_pwm_writel(lpc18xx_pwm,
LPC18XX_PWM_MATCH(lpc18xx_data->duty_event),
val);
Annotation
- Immediate include surface: `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/mod_devicetable.h`, `linux/module.h`, `linux/platform_device.h`, `linux/pwm.h`.
- Detected declarations: `struct lpc18xx_pwm_data`, `struct lpc18xx_pwm_chip`, `enum lpc18xx_pwm_res_action`, `function to_lpc18xx_pwm_chip`, `function lpc18xx_pwm_writel`, `function lpc18xx_pwm_readl`, `function lpc18xx_pwm_set_conflict_res`, `function lpc18xx_pwm_config_period`, `function lpc18xx_pwm_config_duty`, `function lpc18xx_pwm_config`.
- 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.