riscv: pwm: sophgo: add pwm support for SG2044
Subsystems (4)
v2 cover riscv: pwm: sophgo: add pwm support for SG2044
This patch adds PWM controller support for four independent PWM channel outputs.
---
Changes in v2:
- Modify variable naming and code logic.
- update "MODULE_AUTHOR".
Changes in v1:
You can simply review or test the patches at the link [1].
---
Longbin Li (3):
pwm: sophgo: reorganize the code structure
pwm: sophgo: add driver for SG2044
dt-bindings: pwm: sophgo: add pwm controller for SG2044
.../bindings/pwm/sophgo,sg2042-pwm.yaml | 4 +- drivers/pwm/pwm-sophgo-sg2042.c | 151 ++++++++++++++---- 2 files changed, 125 insertions(+), 30 deletions(-)
--
2.49.0
PATCH v2 1/3 dt-bindings: pwm: sophgo: add pwm controller for SG2044
Add compatible string for PWM controller on SG2044.
--- Documentation/devicetree/bindings/pwm/sophgo,sg2042-pwm.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/pwm/sophgo,sg2042-pwm.yaml +3 -1
@@ -17,7 +17,9 @@ allOf: properties: compatible: - const: sophgo,sg2042-pwm + enum: + - sophgo,sg2042-pwm + - sophgo,sg2044-pwm reg: maxItems: 1
--
2.49.0
Re: [PATCH v2 1/3] dt-bindings: pwm: sophgo: add pwm controller for SG2044
Quoted 23 lines · Longbin Li
Add compatible string for PWM controller on SG2044.
Signed-off-by Longbin Li <[email protected]>--- Documentation/devicetree/bindings/pwm/sophgo,sg2042-pwm.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)Documentation/devicetree/bindings/pwm/sophgo,sg2042-pwm.yaml +3
-2@@ -17,7 +17,9 @@ allOf: properties: compatible: - const: sophgo,sg2042-pwm + enum: + - sophgo,sg2042-pwm + - sophgo,sg2044-pwm reg: maxItems: 1 --
Quoted 1 line
2.49.0
Thanks,
Chen
Re: [PATCH v2 1/3] dt-bindings: pwm: sophgo: add pwm controller for SG2044
In reply to Longbin LiQuoted 1 line · Longbin Li
Add compatible string for PWM controller on SG2044.
That is clear from reading the diff. What would be useful is details on how the h/w is different from SG2042 (and hence not compatible with it).
Quoted 5 lines
Signed-off-by Longbin Li <[email protected]>--- Documentation/devicetree/bindings/pwm/sophgo,sg2042-pwm.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
PATCH v2 2/3 pwm: sophgo: reorganize the code structure
In reply to Longbin LiAs the driver logic can be used in both SG2042 and SG2044, it will be better to reorganize the code structure.
--- drivers/pwm/pwm-sophgo-sg2042.c | 62 +++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-)
drivers/pwm/pwm-sophgo-sg2042.c +35 -27
@@ -26,18 +26,6 @@#include <linux/pwm.h> #include <linux/reset.h> -/* -* Offset RegisterName -* 0x0000 HLPERIOD0 -* 0x0004 PERIOD0 -* 0x0008 HLPERIOD1 -* 0x000C PERIOD1 -* 0x0010 HLPERIOD2 -* 0x0014 PERIOD2 -* 0x0018 HLPERIOD3 -* 0x001C PERIOD3 -* Four groups and every group is composed of HLPERIOD & PERIOD -*/ #define SG2042_PWM_HLPERIOD (chan) ((chan) * 8 + 0)#define SG2042_PWM_PERIOD (chan) ((chan) * 8 + 4)
@@ -53,6 +41,10 @@ struct sg2042_pwm_ddata {unsigned long clk_rate_hz; }; +struct sg2042_chip_data { +const struct pwm_ops ops; +}; +/* * period_ticks: PERIOD * hlperiod_ticks: HLPERIOD
@@ -66,21 +58,13 @@ static void pwm_sg2042_config(struct sg2042_pwm_ddata *ddata, unsigned int chan,writel (hlperiod_ticks, base +SG2042_PWM_HLPERIOD (chan)); } -static int pwm_sg2042_apply (struct pwm_chip *chip,struct pwm_device *pwm, -const struct pwm_state *state) +static void pwm_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; -if (state->polarity ==PWM_POLARITY_INVERSED ) -return -EINVAL ; - -if (!state->enabled) { -pwm_sg2042_config (ddata, pwm->hwpwm,0 ,0 ); -return 0 ; - } -/* * Duration of High level (duty_cycle) = HLPERIOD x Period_of_input_clk * Duration of One Cycle (period) = PERIOD x Period_of_input_clk
@@ -92,6 +76,22 @@ static int pwm_sg2042_apply(struct pwm_chip *chip, struct pwm_device *pwm, pwm->hwpwm, period_ticks, hlperiod_ticks);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_set_dutycycle (chip, pwm, state);return 0 ; }
@@ -123,13 +123,16 @@ static int pwm_sg2042_get_state(struct pwm_chip *chip, struct pwm_device *pwm,return 0 ; } -static const struct pwm_ops pwm_sg2042_ops = { - .apply = pwm_sg2042_apply, - .get_state = pwm_sg2042_get_state, +static const struct sg2042_chip_data sg2042_chip_data = { + .ops = { + .apply = pwm_sg2042_apply, + .get_state = pwm_sg2042_get_state, + } };static const struct of_device_id sg2042_pwm_ids[] = { - { .compatible ="sophgo,sg2042-pwm" }, + { .compatible ="sophgo,sg2042-pwm" , + .data = &sg2042_chip_data }, { } };MODULE_DEVICE_TABLE (of, sg2042_pwm_ids);
@@ -137,12 +140,17 @@ MODULE_DEVICE_TABLE(of, sg2042_pwm_ids);static int pwm_sg2042_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev; +const struct sg2042_chip_data *chip_data;struct sg2042_pwm_ddata *ddata;struct reset_control *rst;struct pwm_chip *chip;struct clk *clk;int ret; + chip_data =device_get_match_data (dev); +if (!chip_data) +return -ENODEV ; + chip =devm_pwmchip_alloc (dev,SG2042_PWM_CHANNELNUM ,sizeof (*ddata));if (IS_ERR (chip))return PTR_ERR (chip);
@@ -170,7 +178,7 @@ static int pwm_sg2042_probe(struct platform_device *pdev)if (IS_ERR (rst))return dev_err_probe (dev,PTR_ERR (rst),"Failed to get reset\n" ); - chip->ops = &pwm_sg2042_ops; + chip->ops = &chip_data->ops; chip->atomic = true; ret =devm_pwmchip_add (dev, chip);
--
2.49.0
Re: [PATCH v2 2/3] pwm: sophgo: reorganize the code structure
Quoted 4 lines · Longbin Li
As the driver logic can be used in both SG2042 and SG2044, it will be better to reorganize the code structure.
Signed-off-by Longbin Li <[email protected]>
Thanks,
Chen
Quoted 135 lines
--- drivers/pwm/pwm-sophgo-sg2042.c | 62 +++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-)drivers/pwm/pwm-sophgo-sg2042.c +35
-28@@ -26,18 +26,6 @@#include <linux/pwm.h> #include <linux/reset.h> -/* -* Offset RegisterName -* 0x0000 HLPERIOD0 -* 0x0004 PERIOD0 -* 0x0008 HLPERIOD1 -* 0x000C PERIOD1 -* 0x0010 HLPERIOD2 -* 0x0014 PERIOD2 -* 0x0018 HLPERIOD3 -* 0x001C PERIOD3 -* Four groups and every group is composed of HLPERIOD & PERIOD -*/ #define SG2042_PWM_HLPERIOD (chan) ((chan) * 8 + 0)#define SG2042_PWM_PERIOD (chan) ((chan) * 8 + 4)@@ -53,6 +41,10 @@ struct sg2042_pwm_ddata {unsigned long clk_rate_hz; }; +struct sg2042_chip_data { +const struct pwm_ops ops; +}; +/* * period_ticks: PERIOD * hlperiod_ticks: HLPERIOD @@ -66,21 +58,13 @@ static void pwm_sg2042_config(struct sg2042_pwm_ddata *ddata, unsigned int chan,writel (hlperiod_ticks, base +SG2042_PWM_HLPERIOD (chan)); } -static int pwm_sg2042_apply (struct pwm_chip *chip,struct pwm_device *pwm, -const struct pwm_state *state) +static void pwm_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; -if (state->polarity ==PWM_POLARITY_INVERSED ) -return -EINVAL ; - -if (!state->enabled) { -pwm_sg2042_config (ddata, pwm->hwpwm,0 ,0 ); -return 0 ; - } -/* * Duration of High level (duty_cycle) = HLPERIOD x Period_of_input_clk * Duration of One Cycle (period) = PERIOD x Period_of_input_clk @@ -92,6 +76,22 @@ static int pwm_sg2042_apply(struct pwm_chip *chip, struct pwm_device *pwm, pwm->hwpwm, period_ticks, hlperiod_ticks);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_set_dutycycle (chip, pwm, state);return 0 ; }@@ -123,13 +123,16 @@ static int pwm_sg2042_get_state(struct pwm_chip *chip, struct pwm_device *pwm,return 0 ; } -static const struct pwm_ops pwm_sg2042_ops = { - .apply = pwm_sg2042_apply, - .get_state = pwm_sg2042_get_state, +static const struct sg2042_chip_data sg2042_chip_data = { + .ops = { + .apply = pwm_sg2042_apply, + .get_state = pwm_sg2042_get_state, + } };static const struct of_device_id sg2042_pwm_ids[] = { - { .compatible ="sophgo,sg2042-pwm" }, + { .compatible ="sophgo,sg2042-pwm" , + .data = &sg2042_chip_data }, { } };MODULE_DEVICE_TABLE (of, sg2042_pwm_ids);@@ -137,12 +140,17 @@ MODULE_DEVICE_TABLE(of, sg2042_pwm_ids);static int pwm_sg2042_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev; +const struct sg2042_chip_data *chip_data;struct sg2042_pwm_ddata *ddata;struct reset_control *rst;struct pwm_chip *chip;struct clk *clk;int ret; + chip_data =device_get_match_data (dev); +if (!chip_data) +return -ENODEV ; + chip =devm_pwmchip_alloc (dev,SG2042_PWM_CHANNELNUM ,sizeof (*ddata));if (IS_ERR (chip))return PTR_ERR (chip);@@ -170,7 +178,7 @@ static int pwm_sg2042_probe(struct platform_device *pdev)if (IS_ERR (rst))return dev_err_probe (dev,PTR_ERR (rst),"Failed to get reset\n" ); - chip->ops = &pwm_sg2042_ops; + chip->ops = &chip_data->ops; chip->atomic = true; ret =devm_pwmchip_add (dev, chip); --2.49.0
PATCH v2 3/3 pwm: sophgo: add driver for SG2044
In reply to Longbin LiAdd PWM controller for SG2044 on base of SG2042.
--- drivers/pwm/pwm-sophgo-sg2042.c | 89 ++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-)
drivers/pwm/pwm-sophgo-sg2042.c +87 -2
@@ -13,6 +13,9 @@* the running period. * - When PERIOD and HLPERIOD is set to 0, the PWM wave output will * be stopped and the output is pulled to high. +* - SG2044 support polarity while SG2042 does not. When PWMSTART is +* false, POLARITY being NORMAL will make output being low, +* POLARITY being INVERSED will make output being high. * See the datasheet [1] for more details. * [1]:https://github.com/sophgo/sophgo-doc/tree/main/SG2042/TRM */
@@ -26,6 +29,10 @@#include <linux/pwm.h> #include <linux/reset.h> +#define SG2044_REG_POLARITY 0x40 +#define SG2044_REG_PWMSTART 0x44 +#define SG2044_REG_PWM_OE 0xD0 +#define SG2042_PWM_HLPERIOD (chan) ((chan) * 8 + 0)#define SG2042_PWM_PERIOD (chan) ((chan) * 8 + 4)
@@ -72,8 +79,8 @@ static void pwm_set_dutycycle(struct pwm_chip *chip, struct pwm_device *pwm, 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]: PERIOD=%u, HLPERIOD=%u\n" , - pwm->hwpwm, period_ticks, hlperiod_ticks); +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); }
@@ -123,6 +130,74 @@ static int pwm_sg2042_get_state(struct pwm_chip *chip, struct pwm_device *pwm,return 0 ; } +static void pwm_sg2044_set_start (struct sg2042_pwm_ddata *ddata,struct pwm_device *pwm, +bool enabled) +{ +u32 pwm_value; + + pwm_value =readl (ddata->base +SG2044_REG_PWMSTART ); + +if (enabled) + pwm_value |=BIT (pwm->hwpwm); +else + pwm_value &= ~BIT (pwm->hwpwm); + +writel (pwm_value, ddata->base +SG2044_REG_PWMSTART ); +} + +static void pwm_sg2044_set_outputdir (struct sg2042_pwm_ddata *ddata,struct pwm_device *pwm, +bool enabled) +{ +u32 pwm_value; + + pwm_value =readl (ddata->base +SG2044_REG_PWM_OE ); + +if (enabled) + pwm_value |=BIT (pwm->hwpwm); +else + pwm_value &= ~BIT (pwm->hwpwm); + +writel (pwm_value, ddata->base +SG2044_REG_PWM_OE ); +} + +static void pwm_sg2044_set_polarity (struct sg2042_pwm_ddata *ddata,struct pwm_device *pwm, +const struct pwm_state *state) +{ +u32 pwm_value; + + pwm_value =readl (ddata->base +SG2044_REG_POLARITY ); + +if (state->polarity ==PWM_POLARITY_NORMAL ) + pwm_value &= ~BIT (pwm->hwpwm); +else + pwm_value |=BIT (pwm->hwpwm); + +writel (pwm_value, ddata->base +SG2044_REG_POLARITY ); +} + +static int pwm_sg2044_apply (struct pwm_chip *chip,struct pwm_device *pwm, +const struct pwm_state *state) +{ +struct sg2042_pwm_ddata *ddata =pwmchip_get_drvdata (chip); + +pwm_sg2044_set_polarity (ddata, pwm, state); + +pwm_set_dutycycle (chip, pwm, state); + +/* +* re-enable PWMSTART to refresh the register period +*/ +pwm_sg2044_set_start (ddata, pwm, false); + +if (!state->enabled) +return 0 ; + +pwm_sg2044_set_outputdir (ddata, pwm, true); +pwm_sg2044_set_start (ddata, pwm, true); + +return 0 ; +} +static const struct sg2042_chip_data sg2042_chip_data = { .ops = { .apply = pwm_sg2042_apply,
@@ -130,9 +205,18 @@ static const struct sg2042_chip_data sg2042_chip_data = { } }; +static const struct sg2042_chip_data sg2044_chip_data = { + .ops = { + .apply = pwm_sg2044_apply, + .get_state = pwm_sg2042_get_state, + } +}; +static const struct of_device_id sg2042_pwm_ids[] = { { .compatible ="sophgo,sg2042-pwm" , .data = &sg2042_chip_data }, + { .compatible ="sophgo,sg2044-pwm" , + .data = &sg2044_chip_data }, { } };MODULE_DEVICE_TABLE (of, sg2042_pwm_ids);
@@ -198,5 +282,6 @@ static struct platform_driver pwm_sg2042_driver = {module_platform_driver (pwm_sg2042_driver);MODULE_AUTHOR ("Chen Wang" ); +MODULE_AUTHOR ("Longbin Li <[email protected]>" );MODULE_DESCRIPTION ("Sophgo SG2042 PWM driver" );MODULE_LICENSE ("GPL" );
--
2.49.0
Re: [External] : [PATCH v2 3/3] pwm: sophgo: add driver for SG2044
drivers/pwm/pwm-sophgo-sg2042.c line 35
Quoted 4 lines · Longbin Li
drivers/pwm/pwm-sophgo-sg2042.c +4
-0+#define SG2044_REG_POLARITY 0x40 +#define SG2044_REG_PWMSTART 0x44 +#define SG2044_REG_PWM_OE 0xD0 +
please use lowercase 0xd0
Quoted 2 lines
#define SG2042_PWM_HLPERIOD(chan) ((chan) * 8 + 0) #define SG2042_PWM_PERIOD(chan) ((chan) * 8 + 4)
Thanks,
Alok
Re: [External] : [PATCH v2 3/3] pwm: sophgo: add driver for SG2044
Quoted 10 lines · ALOK TIWARI
drivers/pwm/pwm-sophgo-sg2042.c line 35
Quoted 4 lines · Longbin Li
drivers/pwm/pwm-sophgo-sg2042.c +4
-0+#define SG2044_REG_POLARITY 0x40 +#define SG2044_REG_PWMSTART 0x44 +#define SG2044_REG_PWM_OE 0xD0 +please use lowercase
0xd0
I will correct it, thanks.
Quoted 6 lines
Quoted 2 lines
#define SG2042_PWM_HLPERIOD(chan) ((chan) * 8 + 0) #define SG2042_PWM_PERIOD(chan) ((chan) * 8 + 4)Thanks,
Alok
Re: [PATCH v2 3/3] pwm: sophgo: add driver for SG2044
In reply to Longbin LiQuoted 22 lines · Longbin Li
Add PWM controller for SG2044 on base of SG2042.
Signed-off-by Longbin Li <[email protected]>--- drivers/pwm/pwm-sophgo-sg2042.c | 89 ++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-)drivers/pwm/pwm-sophgo-sg2042.c +3
-0@@ -13,6 +13,9 @@* the running period. * - When PERIOD and HLPERIOD is set to 0, the PWM wave output will * be stopped and the output is pulled to high. +* - SG2044 support polarity while SG2042 does not. When PWMSTART is +* false, POLARITY being NORMAL will make output being low, +* POLARITY being INVERSED will make output being high. * See the datasheet [1] for more details. * [1]:https://github.com/sophgo/sophgo-doc/tree/main/SG2042/TRM */
drivers/pwm/pwm-sophgo-sg2042.c line 34
Quoted 6 lines
drivers/pwm/pwm-sophgo-sg2042.c +3
-0@@ -26,6 +29,10 @@#include <linux/pwm.h> #include <linux/reset.h> +#define SG2044_REG_POLARITY 0x40 +#define SG2044_REG_PWMSTART 0x44 +#define SG2044_REG_PWM_OE 0xD0
SG2044_REG_xxx, the prefix looks inconsistent with SG2042_PWM_HLPERIOD/SG2042_PWM_PERIOD. Can it be unified?
The others look fine.
[......]
Re: [PATCH v2 3/3] pwm: sophgo: add driver for SG2044
Quoted 34 lines · Chen Wang
Quoted 22 lines · Longbin Li
Add PWM controller for SG2044 on base of SG2042.
Signed-off-by Longbin Li <[email protected]>--- drivers/pwm/pwm-sophgo-sg2042.c | 89 ++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-)drivers/pwm/pwm-sophgo-sg2042.c +3
-0@@ -13,6 +13,9 @@* the running period. * - When PERIOD and HLPERIOD is set to 0, the PWM wave output will * be stopped and the output is pulled to high. +* - SG2044 support polarity while SG2042 does not. When PWMSTART is +* false, POLARITY being NORMAL will make output being low, +* POLARITY being INVERSED will make output being high. * See the datasheet [1] for more details. * [1]:https://github.com/sophgo/sophgo-doc/tree/main/SG2042/TRM */ drivers/pwm/pwm-sophgo-sg2042.c line 34
Quoted 6 lines
drivers/pwm/pwm-sophgo-sg2042.c +3
-0@@ -26,6 +29,10 @@#include <linux/pwm.h> #include <linux/reset.h> +#define SG2044_REG_POLARITY 0x40 +#define SG2044_REG_PWMSTART 0x44 +#define SG2044_REG_PWM_OE 0xD0
SG2044_REG_xxx, the prefix looks inconsistent with SG2042_PWM_HLPERIOD/SG2042_PWM_PERIOD. Can it be unified?
Quoted 7 lines
The others look fine.
Reviewed-by Chen Wang <[email protected]>[......]
I will rename it to unify, thanks.
Best regards,
Longbin Li
Quoted 21 lines · Longbin Li
This patch adds PWM controller support for four independent PWM channel outputs.
---
Changes in v2:
- Modify variable naming and code logic.
- update "MODULE_AUTHOR".Changes in v1:
You can simply review or test the patches at the link [1].---
Longbin Li (3):
pwm: sophgo: reorganize the code structure
pwm: sophgo: add driver for SG2044
dt-bindings: pwm: sophgo: add pwm controller for SG2044
Quoted 6 lines
.../bindings/pwm/sophgo,sg2042-pwm.yaml | 4 +- drivers/pwm/pwm-sophgo-sg2042.c | 151 ++++++++++++++---- 2 files changed, 125 insertions(+), 30 deletions(-)--
2.49.0
Only test with Pioneerbox/SG2042 and it works well, I don't have sg2044 board in hand.
Chen