drivers/pwm/pwm-rcar.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-rcar.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-rcar.c- Extension
.c- Size
- 6391 bytes
- Lines
- 270
- 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/bitfield.hlinux/clk.hlinux/err.hlinux/io.hlinux/log2.hlinux/math64.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_runtime.hlinux/pwm.hlinux/slab.h
Detected Declarations
struct rcar_pwm_chipfunction rcar_pwm_writefunction rcar_pwm_readfunction rcar_pwm_updatefunction rcar_pwm_get_clock_divisionfunction rcar_pwm_set_clock_controlfunction rcar_pwm_set_counterfunction rcar_pwm_requestfunction rcar_pwm_freefunction rcar_pwm_enablefunction rcar_pwm_disablefunction rcar_pwm_applyfunction rcar_pwm_probefunction rcar_pwm_remove
Annotated Snippet
struct rcar_pwm_chip {
void __iomem *base;
struct clk *clk;
};
static inline struct rcar_pwm_chip *to_rcar_pwm_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static void rcar_pwm_write(struct rcar_pwm_chip *rp, u32 data,
unsigned int offset)
{
writel(data, rp->base + offset);
}
static u32 rcar_pwm_read(struct rcar_pwm_chip *rp, unsigned int offset)
{
return readl(rp->base + offset);
}
static void rcar_pwm_update(struct rcar_pwm_chip *rp, u32 mask, u32 data,
unsigned int offset)
{
u32 value;
value = rcar_pwm_read(rp, offset);
value &= ~mask;
value |= data & mask;
rcar_pwm_write(rp, value, offset);
}
static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
{
unsigned long clk_rate = clk_get_rate(rp->clk);
u64 div, tmp;
if (clk_rate == 0)
return -EINVAL;
div = (u64)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE;
tmp = (u64)period_ns * clk_rate + div - 1;
tmp = div64_u64(tmp, div);
div = ilog2(tmp - 1) + 1;
return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE;
}
static void rcar_pwm_set_clock_control(struct rcar_pwm_chip *rp,
unsigned int div)
{
u32 value;
value = rcar_pwm_read(rp, RCAR_PWMCR);
value &= ~(RCAR_PWMCR_CCMD | RCAR_PWMCR_CC0_MASK);
if (div & 1)
value |= RCAR_PWMCR_CCMD;
div >>= 1;
value |= div << RCAR_PWMCR_CC0_SHIFT;
rcar_pwm_write(rp, value, RCAR_PWMCR);
}
static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, u64 duty_ns,
u64 period_ns)
{
unsigned long long tmp;
unsigned long clk_rate = clk_get_rate(rp->clk);
u32 cyc, ph;
/* div <= 24 == RCAR_PWM_MAX_DIVISION, so the shift doesn't overflow. */
tmp = mul_u64_u64_div_u64(period_ns, clk_rate, (u64)NSEC_PER_SEC << div);
if (tmp > FIELD_MAX(RCAR_PWMCNT_CYC0_MASK))
tmp = FIELD_MAX(RCAR_PWMCNT_CYC0_MASK);
cyc = FIELD_PREP(RCAR_PWMCNT_CYC0_MASK, tmp);
tmp = mul_u64_u64_div_u64(duty_ns, clk_rate, (u64)NSEC_PER_SEC << div);
if (tmp > FIELD_MAX(RCAR_PWMCNT_PH0_MASK))
tmp = FIELD_MAX(RCAR_PWMCNT_PH0_MASK);
ph = FIELD_PREP(RCAR_PWMCNT_PH0_MASK, tmp);
/* Avoid prohibited setting */
if (cyc == 0 || ph == 0)
return -EINVAL;
rcar_pwm_write(rp, cyc | ph, RCAR_PWMCNT);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/log2.h`, `linux/math64.h`, `linux/module.h`, `linux/of.h`.
- Detected declarations: `struct rcar_pwm_chip`, `function rcar_pwm_write`, `function rcar_pwm_read`, `function rcar_pwm_update`, `function rcar_pwm_get_clock_division`, `function rcar_pwm_set_clock_control`, `function rcar_pwm_set_counter`, `function rcar_pwm_request`, `function rcar_pwm_free`, `function rcar_pwm_enable`.
- 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.