drivers/pwm/pwm-imx-tpm.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-imx-tpm.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-imx-tpm.c- Extension
.c- Size
- 12442 bytes
- Lines
- 463
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/bitops.hlinux/clk.hlinux/err.hlinux/io.hlinux/module.hlinux/of.hlinux/pinctrl/consumer.hlinux/platform_device.hlinux/pwm.hlinux/slab.h
Detected Declarations
struct imx_tpm_pwm_chipstruct imx_tpm_pwm_paramfunction to_imx_tpm_pwm_chipfunction valuesfunction pwm_imx_tpm_get_statefunction pwm_imx_tpm_apply_hwfunction pwm_imx_tpm_applyfunction pwm_imx_tpm_requestfunction pwm_imx_tpm_freefunction pwm_imx_tpm_probefunction pwm_imx_tpm_suspendfunction pwm_imx_tpm_resume
Annotated Snippet
struct imx_tpm_pwm_chip {
struct clk *clk;
void __iomem *base;
struct mutex lock;
u32 user_count;
u32 enable_count;
u32 real_period;
};
struct imx_tpm_pwm_param {
u8 prescale;
u32 mod;
u32 val;
};
static inline struct imx_tpm_pwm_chip *
to_imx_tpm_pwm_chip(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
/*
* This function determines for a given pwm_state *state that a consumer
* might request the pwm_state *real_state that eventually is implemented
* by the hardware and the necessary register values (in *p) to achieve
* this.
*/
static int pwm_imx_tpm_round_state(struct pwm_chip *chip,
struct imx_tpm_pwm_param *p,
struct pwm_state *real_state,
const struct pwm_state *state)
{
struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
u32 rate, prescale, period_count, clock_unit;
u64 tmp;
rate = clk_get_rate(tpm->clk);
tmp = (u64)state->period * rate;
clock_unit = DIV_ROUND_CLOSEST_ULL(tmp, NSEC_PER_SEC);
if (clock_unit <= PWM_IMX_TPM_MOD_MOD)
prescale = 0;
else
prescale = ilog2(clock_unit) + 1 - PWM_IMX_TPM_MOD_WIDTH;
if ((!FIELD_FIT(PWM_IMX_TPM_SC_PS, prescale)))
return -ERANGE;
p->prescale = prescale;
period_count = (clock_unit + ((1 << prescale) >> 1)) >> prescale;
if (period_count == 0)
return -EINVAL;
p->mod = period_count - 1;
/* calculate real period HW can support */
tmp = (u64)period_count << prescale;
tmp *= NSEC_PER_SEC;
real_state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
/*
* if eventually the PWM output is inactive, either
* duty cycle is 0 or status is disabled, need to
* make sure the output pin is inactive.
*/
if (!state->enabled)
real_state->duty_cycle = 0;
else
real_state->duty_cycle = state->duty_cycle;
tmp = (u64)p->mod * real_state->duty_cycle;
p->val = DIV64_U64_ROUND_CLOSEST(tmp, real_state->period);
real_state->polarity = state->polarity;
real_state->enabled = state->enabled;
return 0;
}
static int pwm_imx_tpm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state)
{
struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
u32 rate, val, prescale;
u64 tmp;
/* get period */
state->period = tpm->real_period;
/* get duty cycle */
rate = clk_get_rate(tpm->clk);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bitops.h`, `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/module.h`, `linux/of.h`, `linux/pinctrl/consumer.h`.
- Detected declarations: `struct imx_tpm_pwm_chip`, `struct imx_tpm_pwm_param`, `function to_imx_tpm_pwm_chip`, `function values`, `function pwm_imx_tpm_get_state`, `function pwm_imx_tpm_apply_hw`, `function pwm_imx_tpm_apply`, `function pwm_imx_tpm_request`, `function pwm_imx_tpm_free`, `function pwm_imx_tpm_probe`.
- Atlas domain: Driver Families / drivers/pwm.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.