drivers/pwm/pwm-sophgo-sg2042.c
Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-sophgo-sg2042.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pwm/pwm-sophgo-sg2042.c- Extension
.c- Size
- 7935 bytes
- Lines
- 302
- 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/err.hlinux/io.hlinux/math64.hlinux/module.hlinux/platform_device.hlinux/pwm.hlinux/reset.h
Detected Declarations
struct sg2042_pwm_ddatastruct sg2042_chip_datafunction pwm_sg2042_configfunction pwm_sg2042_set_dutycyclefunction pwm_sg2042_applyfunction pwm_sg2042_get_statefunction pwm_sg2044_set_outputenfunction pwm_sg2044_set_outputdirfunction pwm_sg2044_set_polarityfunction pwm_sg2044_applyfunction pwm_sg2042_probe
Annotated Snippet
struct sg2042_pwm_ddata {
void __iomem *base;
unsigned long clk_rate_hz;
};
struct sg2042_chip_data {
const struct pwm_ops ops;
};
/*
* period_ticks: PERIOD
* hlperiod_ticks: HLPERIOD
*/
static void pwm_sg2042_config(struct sg2042_pwm_ddata *ddata, unsigned int chan,
u32 period_ticks, u32 hlperiod_ticks)
{
void __iomem *base = ddata->base;
writel(period_ticks, base + SG2042_PWM_PERIOD(chan));
writel(hlperiod_ticks, base + SG2042_PWM_HLPERIOD(chan));
}
static void pwm_sg2042_set_dutycycle(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct sg2042_pwm_ddata *ddata = pwmchip_get_drvdata(chip);
u32 hlperiod_ticks;
u32 period_ticks;
/*
* Duration of High level (duty_cycle) = HLPERIOD x Period_of_input_clk
* Duration of One Cycle (period) = PERIOD x Period_of_input_clk
*/
period_ticks = min(mul_u64_u64_div_u64(ddata->clk_rate_hz, state->period, NSEC_PER_SEC), U32_MAX);
hlperiod_ticks = min(mul_u64_u64_div_u64(ddata->clk_rate_hz, state->duty_cycle, NSEC_PER_SEC), U32_MAX);
dev_dbg(pwmchip_parent(chip), "chan[%u]: ENABLE=%u, PERIOD=%u, HLPERIOD=%u, POLARITY=%u\n",
pwm->hwpwm, state->enabled, period_ticks, hlperiod_ticks, state->polarity);
pwm_sg2042_config(ddata, pwm->hwpwm, period_ticks, hlperiod_ticks);
}
static int pwm_sg2042_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct sg2042_pwm_ddata *ddata = pwmchip_get_drvdata(chip);
if (state->polarity == PWM_POLARITY_INVERSED)
return -EINVAL;
if (!state->enabled) {
pwm_sg2042_config(ddata, pwm->hwpwm, 0, 0);
return 0;
}
pwm_sg2042_set_dutycycle(chip, pwm, state);
return 0;
}
static int pwm_sg2042_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct sg2042_pwm_ddata *ddata = pwmchip_get_drvdata(chip);
unsigned int chan = pwm->hwpwm;
u32 hlperiod_ticks;
u32 period_ticks;
period_ticks = readl(ddata->base + SG2042_PWM_PERIOD(chan));
hlperiod_ticks = readl(ddata->base + SG2042_PWM_HLPERIOD(chan));
if (!period_ticks) {
state->enabled = false;
return 0;
}
if (hlperiod_ticks > period_ticks)
hlperiod_ticks = period_ticks;
state->enabled = true;
state->period = DIV_ROUND_UP_ULL((u64)period_ticks * NSEC_PER_SEC, ddata->clk_rate_hz);
state->duty_cycle = DIV_ROUND_UP_ULL((u64)hlperiod_ticks * NSEC_PER_SEC, ddata->clk_rate_hz);
state->polarity = PWM_POLARITY_NORMAL;
return 0;
}
static void pwm_sg2044_set_outputen(struct sg2042_pwm_ddata *ddata, struct pwm_device *pwm,
bool enabled)
{
Annotation
- Immediate include surface: `linux/clk.h`, `linux/err.h`, `linux/io.h`, `linux/math64.h`, `linux/module.h`, `linux/platform_device.h`, `linux/pwm.h`, `linux/reset.h`.
- Detected declarations: `struct sg2042_pwm_ddata`, `struct sg2042_chip_data`, `function pwm_sg2042_config`, `function pwm_sg2042_set_dutycycle`, `function pwm_sg2042_apply`, `function pwm_sg2042_get_state`, `function pwm_sg2044_set_outputen`, `function pwm_sg2044_set_outputdir`, `function pwm_sg2044_set_polarity`, `function pwm_sg2044_apply`.
- 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.