Lines Matching +full:sophgo +full:- +full:doc
1 // SPDX-License-Identifier: GPL-2.0
3 * Sophgo SG2042 PWM Controller Driver
5 * Copyright (C) 2024 Sophgo Technology Inc.
9 * - After reset, the output of the PWM channel is always high.
11 * - When HLPERIOD or PERIOD is reconfigured, PWM will start to
14 * - When PERIOD and HLPERIOD is set to 0, the PWM wave output will
16 * - SG2044 supports both polarities, SG2042 only normal polarity.
18 * [1]:https://github.com/sophgo/sophgo-doc/tree/main/SG2042/TRM
52 * struct sg2042_pwm_ddata - private driver data
72 void __iomem *base = ddata->base; in pwm_sg2042_config()
89 period_ticks = min(mul_u64_u64_div_u64(ddata->clk_rate_hz, state->period, NSEC_PER_SEC), U32_MAX); in pwm_sg2042_set_dutycycle()
90 …hlperiod_ticks = min(mul_u64_u64_div_u64(ddata->clk_rate_hz, state->duty_cycle, NSEC_PER_SEC), U32… in pwm_sg2042_set_dutycycle()
93 pwm->hwpwm, state->enabled, period_ticks, hlperiod_ticks, state->polarity); in pwm_sg2042_set_dutycycle()
95 pwm_sg2042_config(ddata, pwm->hwpwm, period_ticks, hlperiod_ticks); in pwm_sg2042_set_dutycycle()
103 if (state->polarity == PWM_POLARITY_INVERSED) in pwm_sg2042_apply()
104 return -EINVAL; in pwm_sg2042_apply()
106 if (!state->enabled) { in pwm_sg2042_apply()
107 pwm_sg2042_config(ddata, pwm->hwpwm, 0, 0); in pwm_sg2042_apply()
120 unsigned int chan = pwm->hwpwm; in pwm_sg2042_get_state()
124 period_ticks = readl(ddata->base + SG2042_PWM_PERIOD(chan)); in pwm_sg2042_get_state()
125 hlperiod_ticks = readl(ddata->base + SG2042_PWM_HLPERIOD(chan)); in pwm_sg2042_get_state()
128 state->enabled = false; in pwm_sg2042_get_state()
135 state->enabled = true; in pwm_sg2042_get_state()
136 state->period = DIV_ROUND_UP_ULL((u64)period_ticks * NSEC_PER_SEC, ddata->clk_rate_hz); in pwm_sg2042_get_state()
137 state->duty_cycle = DIV_ROUND_UP_ULL((u64)hlperiod_ticks * NSEC_PER_SEC, ddata->clk_rate_hz); in pwm_sg2042_get_state()
138 state->polarity = PWM_POLARITY_NORMAL; in pwm_sg2042_get_state()
148 pwmstart = readl(ddata->base + SG2044_PWM_PWMSTART); in pwm_sg2044_set_outputen()
151 pwmstart |= BIT(pwm->hwpwm); in pwm_sg2044_set_outputen()
153 pwmstart &= ~BIT(pwm->hwpwm); in pwm_sg2044_set_outputen()
155 writel(pwmstart, ddata->base + SG2044_PWM_PWMSTART); in pwm_sg2044_set_outputen()
163 pwm_oe = readl(ddata->base + SG2044_PWM_OE); in pwm_sg2044_set_outputdir()
166 pwm_oe |= BIT(pwm->hwpwm); in pwm_sg2044_set_outputdir()
168 pwm_oe &= ~BIT(pwm->hwpwm); in pwm_sg2044_set_outputdir()
170 writel(pwm_oe, ddata->base + SG2044_PWM_OE); in pwm_sg2044_set_outputdir()
178 pwm_polarity = readl(ddata->base + SG2044_PWM_POLARITY); in pwm_sg2044_set_polarity()
180 if (state->polarity == PWM_POLARITY_NORMAL) in pwm_sg2044_set_polarity()
181 pwm_polarity &= ~BIT(pwm->hwpwm); in pwm_sg2044_set_polarity()
183 pwm_polarity |= BIT(pwm->hwpwm); in pwm_sg2044_set_polarity()
185 writel(pwm_polarity, ddata->base + SG2044_PWM_POLARITY); in pwm_sg2044_set_polarity()
198 * re-enable PWMSTART to refresh the register period in pwm_sg2044_apply()
202 if (!state->enabled) in pwm_sg2044_apply()
227 .compatible = "sophgo,sg2042-pwm",
231 .compatible = "sophgo,sg2044-pwm",
240 struct device *dev = &pdev->dev; in pwm_sg2042_probe()
250 return -ENODEV; in pwm_sg2042_probe()
257 ddata->base = devm_platform_ioremap_resource(pdev, 0); in pwm_sg2042_probe()
258 if (IS_ERR(ddata->base)) in pwm_sg2042_probe()
259 return PTR_ERR(ddata->base); in pwm_sg2042_probe()
269 ddata->clk_rate_hz = clk_get_rate(clk); in pwm_sg2042_probe()
271 if (!ddata->clk_rate_hz || ddata->clk_rate_hz > NSEC_PER_SEC) in pwm_sg2042_probe()
272 return dev_err_probe(dev, -EINVAL, in pwm_sg2042_probe()
273 "Invalid clock rate: %lu\n", ddata->clk_rate_hz); in pwm_sg2042_probe()
279 chip->ops = &chip_data->ops; in pwm_sg2042_probe()
280 chip->atomic = true; in pwm_sg2042_probe()
291 .name = "sg2042-pwm",
300 MODULE_DESCRIPTION("Sophgo SG2042 PWM driver");