drivers/pwm/pwm-bcm-kona.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-bcm-kona.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-bcm-kona.c- Extension
.c- Size
- 9312 bytes
- Lines
- 339
- 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/delay.hlinux/err.hlinux/io.hlinux/ioport.hlinux/math64.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pwm.hlinux/slab.hlinux/types.h
Detected Declarations
struct kona_pwmcfunction kona_pwmc_prepare_for_settingsfunction kona_pwmc_apply_settingsfunction kona_pwmc_configfunction kona_pwmc_set_polarityfunction kona_pwmc_enablefunction kona_pwmc_disablefunction kona_pwmc_applyfunction kona_pwmc_probe
Annotated Snippet
struct kona_pwmc {
void __iomem *base;
struct clk *clk;
};
static inline struct kona_pwmc *to_kona_pwmc(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
/*
* Clear trigger bit but set smooth bit to maintain old output.
*/
static void kona_pwmc_prepare_for_settings(struct kona_pwmc *kp,
unsigned int chan)
{
unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET);
value |= 1 << PWM_CONTROL_SMOOTH_SHIFT(chan);
value &= ~(1 << PWM_CONTROL_TRIGGER_SHIFT(chan));
writel(value, kp->base + PWM_CONTROL_OFFSET);
/*
* There must be a min 400ns delay between clearing trigger and setting
* it. Failing to do this may result in no PWM signal.
*/
ndelay(400);
}
static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan)
{
unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET);
/* Set trigger bit and clear smooth bit to apply new settings */
value &= ~(1 << PWM_CONTROL_SMOOTH_SHIFT(chan));
value |= 1 << PWM_CONTROL_TRIGGER_SHIFT(chan);
writel(value, kp->base + PWM_CONTROL_OFFSET);
/* Trigger bit must be held high for at least 400 ns. */
ndelay(400);
}
static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
u64 duty_ns, u64 period_ns)
{
struct kona_pwmc *kp = to_kona_pwmc(chip);
u64 div, rate;
unsigned long prescale = PRESCALE_MIN, pc, dc;
unsigned int value, chan = pwm->hwpwm;
/*
* Find period count, duty count and prescale to suit duty_ns and
* period_ns. This is done according to formulas described below:
*
* period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
* duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
*
* PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
* DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
*/
rate = clk_get_rate(kp->clk);
while (1) {
div = 1000000000;
div *= 1 + prescale;
pc = mul_u64_u64_div_u64(rate, period_ns, div);
dc = mul_u64_u64_div_u64(rate, duty_ns, div);
/* If duty_ns or period_ns are not achievable then return */
if (pc < PERIOD_COUNT_MIN)
return -EINVAL;
/* If pc and dc are in bounds, the calculation is done */
if (pc <= PERIOD_COUNT_MAX && dc <= DUTY_CYCLE_HIGH_MAX)
break;
/* Otherwise, increase prescale and recalculate pc and dc */
if (++prescale > PRESCALE_MAX)
return -EINVAL;
}
kona_pwmc_prepare_for_settings(kp, chan);
value = readl(kp->base + PRESCALE_OFFSET);
value &= ~PRESCALE_MASK(chan);
value |= prescale << PRESCALE_SHIFT(chan);
writel(value, kp->base + PRESCALE_OFFSET);
writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan));
Annotation
- Immediate include surface: `linux/clk.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/ioport.h`, `linux/math64.h`, `linux/module.h`, `linux/of.h`.
- Detected declarations: `struct kona_pwmc`, `function kona_pwmc_prepare_for_settings`, `function kona_pwmc_apply_settings`, `function kona_pwmc_config`, `function kona_pwmc_set_polarity`, `function kona_pwmc_enable`, `function kona_pwmc_disable`, `function kona_pwmc_apply`, `function kona_pwmc_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.