devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Add the Allwinner A31/A31s PWM driver
@ 2017-02-07 17:50 lis8215-Re5JQEeQqe8AvxtiuMwx3w
  2017-02-07 17:50 ` [PATCH v2 2/4] ARM: pwm: sun4i: selectable prescaler table for support sun6i lis8215
       [not found] ` <1486489846-662-1-git-send-email-lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 2 replies; 11+ messages in thread
From: lis8215-Re5JQEeQqe8AvxtiuMwx3w @ 2017-02-07 17:50 UTC (permalink / raw)
  To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
  Cc: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Siarhei Volkau

From: Siarhei Volkau <lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

First of all im sorry for accidentally sent old patch,
please ignore them.

This is the second version of the sun6i PWM patchset.
 - added missing documentation changes
 - dts changes in separate patch

Thanks to Julian Calaby for tips.

--------------------------
This series of patches introduces support for Allwinner A31 PWM, which
is significantly differ from PWM founded in other Allwinner SoCs.
Patches 1/4 and 2/4 refactors existing code for easier A31 PWM integration.
Patch 3/4 adds support for A31 PWM on top of existing Allwinner PWM driver.
Patch 4/4 adds the PWM block to A31/A31s device tree.

Siarhei Volkau (4):
  ARM: pwm: sun4i: unification of register operations for support sun6i.
  ARM: pwm: sun4i: selectable prescaler table for support sun6i.
  ARM: pwm: sun6i: add support the Allwinner A31 PWM.
  ARM: dts: sun6i: Add the PWM block to the A31/A31s.

 .../devicetree/bindings/pwm/pwm-sun4i.txt          |   3 +-
 arch/arm/boot/dts/sun6i-a31.dtsi                   |   8 +
 drivers/pwm/pwm-sun4i.c                            | 193 ++++++++++++++++++---
 3 files changed, 176 insertions(+), 28 deletions(-)

-- 
2.4.11

^ permalink raw reply	[flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/4] ARM: pwm: sun4i: unification of register operations for support sun6i.
@ 2017-02-07 18:45 Icenowy Zheng
  0 siblings, 0 replies; 11+ messages in thread
From: Icenowy Zheng @ 2017-02-07 18:45 UTC (permalink / raw)
  To: lis8215-Re5JQEeQqe8AvxtiuMwx3w
  Cc: Thierry Reding, linux-kernel, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	wens-jdAy2FN1RRM, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A

I think the ARM: cap is not needed for the 3 PWM driver patch.

2017年2月8日 01:50于 lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org写道:
>
> From: Siarhei Volkau <lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 
>
> This patch not introduce new features, just prepare code for 
> adding sun6i PWM driver in next commits. 
>
> A31 SoC have a different map of PWM registers than others ASoCs, 
> but register bits purposes are very similar. 
>
> This patch introduce set of register access routines, which 
> are common for existing in driver ASoCs: 
> - ctl_rdy   - checks the ready bit of specified PWM channel, 
> - ctl_read  - reads value from control register of specified PWM channel, 
> - ctl_write - writes significant bits to control register of specified PWM channel, 
> - prd_read  - reads value from period register of specified PWM channel, 
> - prd_write - writes value to period register of specified PWM channel. 
> Driver code redesigned to use the new routines. 
>
> Signed-off-by: Siarhei Volkau <lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 
> --- 
> drivers/pwm/pwm-sun4i.c | 113 +++++++++++++++++++++++++++++++++++++----------- 
> 1 file changed, 87 insertions(+), 26 deletions(-) 
>
> diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c 
> index b0803f6..04ad3b4 100644 
> --- a/drivers/pwm/pwm-sun4i.c 
> +++ b/drivers/pwm/pwm-sun4i.c 
> @@ -34,6 +34,7 @@ 
> #define PWM_MODE BIT(7) 
> #define PWM_PULSE BIT(8) 
> #define PWM_BYPASS BIT(9) 
> +#define PWM_CHCTL_MASK GENMASK(9, 0) 
>
> #define PWM_RDY_BASE 28 
> #define PWM_RDY_OFFSET 1 
> @@ -46,6 +47,8 @@ 
>
> #define BIT_CH(bit, chan) ((bit) << ((chan) * PWMCH_OFFSET)) 
>
> +struct sun4i_pwm_chip; 
> + 
> static const u32 prescaler_table[] = { 
> 120, 
> 180, 
> @@ -65,10 +68,19 @@ static const u32 prescaler_table[] = { 
> 0, /* Actually 1 but tested separately */ 
> }; 
>
> +struct sunxi_reg_ops { 
> + int (*ctl_rdy)(struct sun4i_pwm_chip *chip, int npwm); 
> + u32 (*ctl_read)(struct sun4i_pwm_chip *chip, int npwm); 
> + void (*ctl_write)(struct sun4i_pwm_chip *chip, int npwm, u32 val); 
> + u32 (*prd_read)(struct sun4i_pwm_chip *chip, int npwm); 
> + void (*prd_write)(struct sun4i_pwm_chip *chip, int npwm, u32 val); 
> +}; 
> + 
> struct sun4i_pwm_data { 
> bool has_prescaler_bypass; 
> bool has_rdy; 
> unsigned int npwm; 
> + const struct sunxi_reg_ops *ops; 
> }; 
>
> struct sun4i_pwm_chip { 
> @@ -96,10 +108,42 @@ static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip, 
> writel(val, chip->base + offset); 
> } 
>
> +static int sun4i_reg_ctl_rdy(struct sun4i_pwm_chip *chip, int npwm) 
> +{ 
> + return PWM_RDY(npwm) & sun4i_pwm_readl(chip, PWM_CTRL_REG); 
> +} 
> + 
> +static u32 sun4i_reg_ctl_read(struct sun4i_pwm_chip *chip, int npwm) 
> +{ 
> + u32 val = sun4i_pwm_readl(chip, PWM_CTRL_REG); 
> + 
> + return val >> (PWMCH_OFFSET * (npwm)); 
> +} 
> + 
> +static void sun4i_reg_ctl_write(struct sun4i_pwm_chip *chip, int npwm, u32 val) 
> +{ 
> + u32 rd = sun4i_pwm_readl(chip, PWM_CTRL_REG); 
> + 
> + rd &= ~(PWM_CHCTL_MASK << (PWMCH_OFFSET * npwm)); 
> + val &= (PWM_CHCTL_MASK << (PWMCH_OFFSET * npwm)); 
> + sun4i_pwm_writel(chip, rd | val, PWM_CTRL_REG); 
> +} 
> + 
> +static u32 sun4i_reg_prd_read(struct sun4i_pwm_chip *chip, int npwm) 
> +{ 
> + return sun4i_pwm_readl(chip, PWM_CH_PRD(npwm)); 
> +} 
> + 
> +static void sun4i_reg_prd_write(struct sun4i_pwm_chip *chip, int npwm, u32 val) 
> +{ 
> + sun4i_pwm_writel(chip, val, PWM_CH_PRD(npwm)); 
> +} 
> + 
> static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 
>     int duty_ns, int period_ns) 
> { 
> struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); 
> + const struct sunxi_reg_ops *reg_ops = sun4i_pwm->data->ops; 
> u32 prd, dty, val, clk_gate; 
> u64 clk_rate, div = 0; 
> unsigned int prescaler = 0; 
> @@ -152,32 +196,31 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 
> } 
>
> spin_lock(&sun4i_pwm->ctrl_lock); 
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
>
> - if (sun4i_pwm->data->has_rdy && (val & PWM_RDY(pwm->hwpwm))) { 
> + if (sun4i_pwm->data->has_rdy && 
> +     reg_ops->ctl_rdy(sun4i_pwm, pwm->hwpwm)) { 
> spin_unlock(&sun4i_pwm->ctrl_lock); 
> clk_disable_unprepare(sun4i_pwm->clk); 
> return -EBUSY; 
> } 
>
> - clk_gate = val & BIT_CH(PWM_CLK_GATING, pwm->hwpwm); 
> + val = reg_ops->ctl_read(sun4i_pwm, pwm->hwpwm); 
> + clk_gate = val & PWM_CLK_GATING; 
> if (clk_gate) { 
> - val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + val &= ~PWM_CLK_GATING; 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
> } 
>
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
> val &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm); 
> val |= BIT_CH(prescaler, pwm->hwpwm); 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
>
> - val = (dty & PWM_DTY_MASK) | PWM_PRD(prd); 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm)); 
> + reg_ops->prd_write(sun4i_pwm, pwm->hwpwm, 
> +    (dty & PWM_DTY_MASK) | PWM_PRD(prd)); 
>
> if (clk_gate) { 
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
> val |= clk_gate; 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
> } 
>
> spin_unlock(&sun4i_pwm->ctrl_lock); 
> @@ -190,6 +233,7 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, 
>   enum pwm_polarity polarity) 
> { 
> struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); 
> + const struct sunxi_reg_ops *reg_ops = sun4i_pwm->data->ops; 
> u32 val; 
> int ret; 
>
> @@ -200,14 +244,14 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, 
> } 
>
> spin_lock(&sun4i_pwm->ctrl_lock); 
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
> + val = reg_ops->ctl_read(sun4i_pwm, pwm->hwpwm); 
>
> if (polarity != PWM_POLARITY_NORMAL) 
> - val &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm); 
> + val &= ~PWM_ACT_STATE; 
> else 
> - val |= BIT_CH(PWM_ACT_STATE, pwm->hwpwm); 
> + val |= PWM_ACT_STATE; 
>
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
>
> spin_unlock(&sun4i_pwm->ctrl_lock); 
> clk_disable_unprepare(sun4i_pwm->clk); 
> @@ -218,6 +262,7 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, 
> static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 
> { 
> struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); 
> + const struct sunxi_reg_ops *reg_ops = sun4i_pwm->data->ops; 
> u32 val; 
> int ret; 
>
> @@ -228,10 +273,9 @@ static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 
> } 
>
> spin_lock(&sun4i_pwm->ctrl_lock); 
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
> - val |= BIT_CH(PWM_EN, pwm->hwpwm); 
> - val |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + val = reg_ops->ctl_rdy(sun4i_pwm, pwm->hwpwm); 
> + val |= PWM_EN | PWM_CLK_GATING; 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
> spin_unlock(&sun4i_pwm->ctrl_lock); 
>
> return 0; 
> @@ -240,18 +284,26 @@ static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 
> static void sun4i_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 
> { 
> struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); 
> + const struct sunxi_reg_ops *reg_ops = sun4i_pwm->data->ops; 
> u32 val; 
>
> spin_lock(&sun4i_pwm->ctrl_lock); 
> - val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); 
> - val &= ~BIT_CH(PWM_EN, pwm->hwpwm); 
> - val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); 
> - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); 
> + val = reg_ops->ctl_rdy(sun4i_pwm, pwm->hwpwm); 
> + val &= ~(PWM_EN | PWM_CLK_GATING); 
> + reg_ops->ctl_write(sun4i_pwm, pwm->hwpwm, val); 
> spin_unlock(&sun4i_pwm->ctrl_lock); 
>
> clk_disable_unprepare(sun4i_pwm->clk); 
> } 
>
> +static const struct sunxi_reg_ops sun4i_reg_ops = { 
> + .ctl_rdy   = sun4i_reg_ctl_rdy, 
> + .ctl_read  = sun4i_reg_ctl_read, 
> + .ctl_write = sun4i_reg_ctl_write, 
> + .prd_read  = sun4i_reg_prd_read, 
> + .prd_write = sun4i_reg_prd_write, 
> +}; 
> + 
> static const struct pwm_ops sun4i_pwm_ops = { 
> .config = sun4i_pwm_config, 
> .set_polarity = sun4i_pwm_set_polarity, 
> @@ -264,30 +316,35 @@ static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { 
> .has_prescaler_bypass = false, 
> .has_rdy = false, 
> .npwm = 2, 
> + .ops = &sun4i_reg_ops, 
> }; 
>
> static const struct sun4i_pwm_data sun4i_pwm_data_a10s = { 
> .has_prescaler_bypass = true, 
> .has_rdy = true, 
> .npwm = 2, 
> + .ops = &sun4i_reg_ops, 
> }; 
>
> static const struct sun4i_pwm_data sun4i_pwm_data_a13 = { 
> .has_prescaler_bypass = true, 
> .has_rdy = true, 
> .npwm = 1, 
> + .ops = &sun4i_reg_ops, 
> }; 
>
> static const struct sun4i_pwm_data sun4i_pwm_data_a20 = { 
> .has_prescaler_bypass = true, 
> .has_rdy = true, 
> .npwm = 2, 
> + .ops = &sun4i_reg_ops, 
> }; 
>
> static const struct sun4i_pwm_data sun4i_pwm_data_h3 = { 
> .has_prescaler_bypass = true, 
> .has_rdy = true, 
> .npwm = 1, 
> + .ops = &sun4i_reg_ops, 
> }; 
>
> static const struct of_device_id sun4i_pwm_dt_ids[] = { 
> @@ -319,6 +376,7 @@ static int sun4i_pwm_probe(struct platform_device *pdev) 
> u32 val; 
> int i, ret; 
> const struct of_device_id *match; 
> + const struct sunxi_reg_ops *reg_ops; 
>
> match = of_match_device(sun4i_pwm_dt_ids, &pdev->dev); 
>
> @@ -360,11 +418,14 @@ static int sun4i_pwm_probe(struct platform_device *pdev) 
> goto clk_error; 
> } 
>
> - val = sun4i_pwm_readl(pwm, PWM_CTRL_REG); 
> - for (i = 0; i < pwm->chip.npwm; i++) 
> - if (!(val & BIT_CH(PWM_ACT_STATE, i))) 
> + reg_ops = pwm->data->ops; 
> + 
> + for (i = 0; i < pwm->chip.npwm; i++) { 
> + val = reg_ops->ctl_read(pwm, i); 
> + if (!(val & PWM_ACT_STATE)) 
> pwm_set_polarity(&pwm->chip.pwms[i], 
> PWM_POLARITY_INVERSED); 
> + } 
> clk_disable_unprepare(pwm->clk); 
>
> return 0; 
> -- 
> 2.4.11 
>
> -- 
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group. 
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 
> For more options, visit https://groups.google.com/d/optout. 

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-02-15 22:16 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-07 17:50 [PATCH v2 0/4] Add the Allwinner A31/A31s PWM driver lis8215-Re5JQEeQqe8AvxtiuMwx3w
2017-02-07 17:50 ` [PATCH v2 2/4] ARM: pwm: sun4i: selectable prescaler table for support sun6i lis8215
     [not found] ` <1486489846-662-1-git-send-email-lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-02-07 17:50   ` [PATCH v2 1/4] ARM: pwm: sun4i: unification of register operations " lis8215-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1486489846-662-2-git-send-email-lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-02-08  7:52       ` Maxime Ripard
2017-02-08 16:41         ` Волков Сергей
     [not found]           ` <CAKNVLfaYoPf-b-mGc0eSmmAk0QPhMCRt5aT5Z3JBcfKhridWDA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-02-10  8:38             ` Maxime Ripard
2017-02-07 17:50   ` [PATCH v2 3/4] ARM: pwm: sun6i: add support the Allwinner A31 PWM lis8215-Re5JQEeQqe8AvxtiuMwx3w
     [not found]     ` <1486489846-662-4-git-send-email-lis8215-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-02-08  7:53       ` Maxime Ripard
2017-02-15 22:16     ` Rob Herring
2017-02-07 17:50   ` [PATCH v2 4/4] ARM: dts: sun6i: Add the PWM block to the A31/A31s lis8215-Re5JQEeQqe8AvxtiuMwx3w
  -- strict thread matches above, loose matches on Subject: below --
2017-02-07 18:45 [PATCH v2 1/4] ARM: pwm: sun4i: unification of register operations for support sun6i Icenowy Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).