drivers/pwm/pwm-imx27.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-imx27.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-imx27.c- Extension
.c- Size
- 12518 bytes
- Lines
- 439
- 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/bitops.hlinux/clk.hlinux/delay.hlinux/err.hlinux/io.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pwm.hlinux/slab.h
Detected Declarations
struct pwm_imx27_chipfunction pwm_imx27_get_statefunction pwm_imx27_sw_resetfunction pwm_imx27_wait_fifo_slotfunction pwm_imx27_applyfunction pwm_imx27_probe
Annotated Snippet
struct pwm_imx27_chip {
struct clk_bulk_data clks[ARRAY_SIZE(pwm_imx27_clks)];
int clks_cnt;
void __iomem *mmio_base;
/*
* The driver cannot read the current duty cycle from the hardware if
* the hardware is disabled. Cache the last programmed duty cycle
* value to return in that case.
*/
unsigned int duty_cycle;
};
static inline struct pwm_imx27_chip *to_pwm_imx27_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static int pwm_imx27_get_state(struct pwm_chip *chip,
struct pwm_device *pwm, struct pwm_state *state)
{
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
u32 period, prescaler, pwm_clk, val;
u64 tmp;
int ret;
ret = clk_bulk_prepare_enable(imx->clks_cnt, imx->clks);
if (ret < 0)
return ret;
val = readl(imx->mmio_base + MX3_PWMCR);
if (val & MX3_PWMCR_EN)
state->enabled = true;
else
state->enabled = false;
switch (FIELD_GET(MX3_PWMCR_POUTC, val)) {
case MX3_PWMCR_POUTC_NORMAL:
state->polarity = PWM_POLARITY_NORMAL;
break;
case MX3_PWMCR_POUTC_INVERTED:
state->polarity = PWM_POLARITY_INVERSED;
break;
default:
dev_warn(pwmchip_parent(chip), "can't set polarity, output disconnected");
}
prescaler = MX3_PWMCR_PRESCALER_GET(val);
pwm_clk = clk_get_rate(imx->clks[PWM_IMX27_PER].clk);
val = readl(imx->mmio_base + MX3_PWMPR);
period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
/* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */
tmp = NSEC_PER_SEC * (u64)(period + 2) * prescaler;
state->period = DIV_ROUND_UP_ULL(tmp, pwm_clk);
/*
* PWMSAR can be read only if PWM is enabled. If the PWM is disabled,
* use the cached value.
*/
if (state->enabled)
val = readl(imx->mmio_base + MX3_PWMSAR);
else
val = imx->duty_cycle;
tmp = NSEC_PER_SEC * (u64)(val) * prescaler;
state->duty_cycle = DIV_ROUND_UP_ULL(tmp, pwm_clk);
clk_bulk_disable_unprepare(imx->clks_cnt, imx->clks);
return 0;
}
static void pwm_imx27_sw_reset(struct pwm_chip *chip)
{
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
struct device *dev = pwmchip_parent(chip);
int wait_count = 0;
u32 cr;
writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
do {
usleep_range(200, 1000);
cr = readl(imx->mmio_base + MX3_PWMCR);
} while ((cr & MX3_PWMCR_SWR) &&
(wait_count++ < MX3_PWM_SWR_LOOP));
if (cr & MX3_PWMCR_SWR)
dev_warn(dev, "software reset timeout\n");
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bitops.h`, `linux/clk.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/kernel.h`, `linux/module.h`.
- Detected declarations: `struct pwm_imx27_chip`, `function pwm_imx27_get_state`, `function pwm_imx27_sw_reset`, `function pwm_imx27_wait_fifo_slot`, `function pwm_imx27_apply`, `function pwm_imx27_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.