drivers/pwm/pwm-meson.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-meson.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-meson.c- Extension
.c- Size
- 19247 bytes
- Lines
- 693
- 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/bits.hlinux/clk.hlinux/clk-provider.hlinux/err.hlinux/io.hlinux/kernel.hlinux/math64.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pwm.hlinux/slab.hlinux/spinlock.h
Detected Declarations
struct meson_pwm_channelstruct meson_pwm_datastruct meson_pwmfunction meson_pwm_requestfunction meson_pwm_freefunction meson_pwm_calcfunction meson_pwm_enablefunction meson_pwm_disablefunction meson_pwm_applyfunction meson_pwm_cnt_to_nsfunction meson_pwm_get_statefunction meson_pwm_init_clocks_meson8bfunction meson_pwm_init_channels_meson8b_legacyfunction meson_pwm_init_channels_meson8b_v2function meson_pwm_s4_put_clkfunction meson_pwm_init_channels_s4function meson_pwm_probe
Annotated Snippet
struct meson_pwm_channel {
unsigned long rate;
unsigned int hi;
unsigned int lo;
bool constant;
bool inverted;
struct clk_mux mux;
struct clk_divider div;
struct clk_gate gate;
struct clk *clk;
};
struct meson_pwm_data {
const char *const parent_names[MESON_NUM_MUX_PARENTS];
int (*channels_init)(struct pwm_chip *chip);
bool has_constant;
bool has_polarity;
};
struct meson_pwm {
const struct meson_pwm_data *data;
struct meson_pwm_channel channels[MESON_NUM_PWMS];
void __iomem *base;
/*
* Protects register (write) access to the REG_MISC_AB register
* that is shared between the two PWMs.
*/
spinlock_t lock;
};
static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
{
return pwmchip_get_drvdata(chip);
}
static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
struct device *dev = pwmchip_parent(chip);
int err;
err = clk_prepare_enable(channel->clk);
if (err < 0) {
dev_err(dev, "failed to enable clock %s: %d\n",
__clk_get_name(channel->clk), err);
return err;
}
return 0;
}
static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
clk_disable_unprepare(channel->clk);
}
static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
unsigned int cnt, duty_cnt;
long fin_freq;
u64 duty, period, freq;
duty = state->duty_cycle;
period = state->period;
/*
* Note this is wrong. The result is an output wave that isn't really
* inverted and so is wrongly identified by .get_state as normal.
* Fixing this needs some care however as some machines might rely on
* this.
*/
if (state->polarity == PWM_POLARITY_INVERSED && !meson->data->has_polarity)
duty = period - duty;
freq = div64_u64(NSEC_PER_SEC * 0xffffULL, period);
if (freq > ULONG_MAX)
freq = ULONG_MAX;
fin_freq = clk_round_rate(channel->clk, freq);
if (fin_freq <= 0) {
dev_err(pwmchip_parent(chip),
"invalid source clock frequency %llu\n", freq);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bits.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/err.h`, `linux/io.h`, `linux/kernel.h`, `linux/math64.h`.
- Detected declarations: `struct meson_pwm_channel`, `struct meson_pwm_data`, `struct meson_pwm`, `function meson_pwm_request`, `function meson_pwm_free`, `function meson_pwm_calc`, `function meson_pwm_enable`, `function meson_pwm_disable`, `function meson_pwm_apply`, `function meson_pwm_cnt_to_ns`.
- 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.