linux-pwm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support
@ 2021-01-06  7:37 Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Baruch Siach @ 2021-01-06  7:37 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Rob Herring
  Cc: Baruch Siach, Andrew Lunn, Gregory Clement, Russell King,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

Changes in v6:

  * Reduce rounding error in the get_state fix (RMK)

Changes in v5:

  * Add a fix for get_state

  * Fix typo in patch #4 subject line

  * Add Rob's review tag on the binding documentation patch

Changes in v4:

  * Remove patches that are in LinusW linux-gpio for-next and fixes

  * Rename the 'pwm-offset' property to 'marvell,pwm-offset' as suggested by 
    Rob Herring

The original cover letter follows (with DT property name updated).

The gpio-mvebu driver supports the PWM functionality of the GPIO block for
earlier Armada variants like XP, 370 and 38x. This series extends support to
newer Armada variants that use CP11x and AP80x, like Armada 8K and 7K.

This series adds adds the 'marvell,pwm-offset' property to DT binding. 
'marvell,pwm-offset' points to the base of A/B counter registers that 
determine the PWM period and duty cycle.

The existing PWM DT binding reflects an arbitrary decision to allocate the A
counter to the first GPIO block, and B counter to the other one. In attempt to
provide better future flexibility, the new 'marvell,pwm-offset' property 
always points to the base address of both A/B counters. The driver code still 
allocates the counters in the same way, but this might change in the future 
with no change to the DT.

Tested AP806 and CP110 (both) on Armada 8040 based system.

Baruch Siach (4):
  gpio: mvebu: fix pwm get_state period calculation
  gpio: mvebu: add pwm support for Armada 8K/7K
  arm64: dts: armada: add pwm offsets for ap/cp gpios
  dt-bindings: ap806: document gpio marvell,pwm-offset property

 .../arm/marvell/ap80x-system-controller.txt   |   8 ++
 arch/arm64/boot/dts/marvell/armada-ap80x.dtsi |   3 +
 arch/arm64/boot/dts/marvell/armada-cp11x.dtsi |  10 ++
 drivers/gpio/gpio-mvebu.c                     | 120 +++++++++++-------
 4 files changed, 97 insertions(+), 44 deletions(-)

-- 
2.29.2


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

* [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation
  2021-01-06  7:37 [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
@ 2021-01-06  7:37 ` Baruch Siach
  2021-01-07 14:29   ` Uwe Kleine-König
  2021-01-06  7:37 ` [PATCH v6 2/4] gpio: mvebu: add pwm support for Armada 8K/7K Baruch Siach
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Baruch Siach @ 2021-01-06  7:37 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Rob Herring
  Cc: Baruch Siach, Russell King, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

The period is the sum of on and off values.

Reported-by: Russell King <linux@armlinux.org.uk>
Fixes: 757642f9a584e ("gpio: mvebu: Add limited PWM support")
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
v6: divide (on + off) sum to reduce rounding error (RMK)
---
 drivers/gpio/gpio-mvebu.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 672681a976f5..a912a8fed197 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
 	else
 		state->duty_cycle = 1;
 
+	val = (unsigned long long) u; /* on duration */
 	regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
-	val = (unsigned long long) u * NSEC_PER_SEC;
+	val += (unsigned long long) u; /* period = on + off duration */
+	val *= NSEC_PER_SEC;
 	do_div(val, mvpwm->clk_rate);
-	if (val < state->duty_cycle) {
+	if (val > UINT_MAX)
+		state->period = UINT_MAX;
+	else if (val)
+		state->period = val;
+	else
 		state->period = 1;
-	} else {
-		val -= state->duty_cycle;
-		if (val > UINT_MAX)
-			state->period = UINT_MAX;
-		else if (val)
-			state->period = val;
-		else
-			state->period = 1;
-	}
 
 	regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
 	if (u)
-- 
2.29.2


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

* [PATCH v6 2/4] gpio: mvebu: add pwm support for Armada 8K/7K
  2021-01-06  7:37 [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
@ 2021-01-06  7:37 ` Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property Baruch Siach
  3 siblings, 0 replies; 8+ messages in thread
From: Baruch Siach @ 2021-01-06  7:37 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Rob Herring
  Cc: Baruch Siach, Andrew Lunn, Gregory Clement, Russell King,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

Use the marvell,pwm-offset DT property to store the location of PWM
signal duration registers.

Since we have more than two GPIO chips per system, we can't use the
alias id to differentiate between them. Use the offset value for that.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
v3: Split mvebu_pwm_probe() move out of this patch into a separate fix
    (Andrew Lunn)
---
 drivers/gpio/gpio-mvebu.c | 101 +++++++++++++++++++++++++-------------
 1 file changed, 68 insertions(+), 33 deletions(-)

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index a912a8fed197..daf2fd8acb21 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -70,7 +70,12 @@
  */
 #define PWM_BLINK_ON_DURATION_OFF	0x0
 #define PWM_BLINK_OFF_DURATION_OFF	0x4
+#define PWM_BLINK_COUNTER_B_OFF		0x8
 
+/* Armada 8k variant gpios register offsets */
+#define AP80X_GPIO0_OFF_A8K		0x1040
+#define CP11X_GPIO0_OFF_A8K		0x100
+#define CP11X_GPIO1_OFF_A8K		0x140
 
 /* The MV78200 has per-CPU registers for edge mask and level mask */
 #define GPIO_EDGE_MASK_MV78200_OFF(cpu)	  ((cpu) ? 0x30 : 0x18)
@@ -93,6 +98,7 @@
 
 struct mvebu_pwm {
 	struct regmap		*regs;
+	u32			 offset;
 	unsigned long		 clk_rate;
 	struct gpio_desc	*gpiod;
 	struct pwm_chip		 chip;
@@ -283,12 +289,12 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val)
  */
 static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
 {
-	return PWM_BLINK_ON_DURATION_OFF;
+	return mvpwm->offset + PWM_BLINK_ON_DURATION_OFF;
 }
 
 static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
 {
-	return PWM_BLINK_OFF_DURATION_OFF;
+	return mvpwm->offset + PWM_BLINK_OFF_DURATION_OFF;
 }
 
 /*
@@ -778,51 +784,80 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
 	struct device *dev = &pdev->dev;
 	struct mvebu_pwm *mvpwm;
 	void __iomem *base;
+	u32 offset;
 	u32 set;
 
-	if (!of_device_is_compatible(mvchip->chip.of_node,
-				     "marvell,armada-370-gpio"))
-		return 0;
-
-	/*
-	 * There are only two sets of PWM configuration registers for
-	 * all the GPIO lines on those SoCs which this driver reserves
-	 * for the first two GPIO chips. So if the resource is missing
-	 * we can't treat it as an error.
-	 */
-	if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"))
+	if (of_device_is_compatible(mvchip->chip.of_node,
+				    "marvell,armada-370-gpio")) {
+		/*
+		 * There are only two sets of PWM configuration registers for
+		 * all the GPIO lines on those SoCs which this driver reserves
+		 * for the first two GPIO chips. So if the resource is missing
+		 * we can't treat it as an error.
+		 */
+		if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"))
+			return 0;
+		offset = 0;
+	} else if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
+		int ret = of_property_read_u32(dev->of_node,
+					       "marvell,pwm-offset", &offset);
+		if (ret < 0)
+			return 0;
+	} else {
 		return 0;
+	}
 
 	if (IS_ERR(mvchip->clk))
 		return PTR_ERR(mvchip->clk);
 
-	/*
-	 * Use set A for lines of GPIO chip with id 0, B for GPIO chip
-	 * with id 1. Don't allow further GPIO chips to be used for PWM.
-	 */
-	if (id == 0)
-		set = 0;
-	else if (id == 1)
-		set = U32_MAX;
-	else
-		return -EINVAL;
-	regmap_write(mvchip->regs,
-		     GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set);
-
 	mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
 	if (!mvpwm)
 		return -ENOMEM;
 	mvchip->mvpwm = mvpwm;
 	mvpwm->mvchip = mvchip;
+	mvpwm->offset = offset;
+
+	if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
+		mvpwm->regs = mvchip->regs;
+
+		switch (mvchip->offset) {
+		case AP80X_GPIO0_OFF_A8K:
+		case CP11X_GPIO0_OFF_A8K:
+			/* Blink counter A */
+			set = 0;
+			break;
+		case CP11X_GPIO1_OFF_A8K:
+			/* Blink counter B */
+			set = U32_MAX;
+			mvpwm->offset += PWM_BLINK_COUNTER_B_OFF;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		base = devm_platform_ioremap_resource_byname(pdev, "pwm");
+		if (IS_ERR(base))
+			return PTR_ERR(base);
 
-	base = devm_platform_ioremap_resource_byname(pdev, "pwm");
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+		mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base,
+						    &mvebu_gpio_regmap_config);
+		if (IS_ERR(mvpwm->regs))
+			return PTR_ERR(mvpwm->regs);
 
-	mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base,
-					    &mvebu_gpio_regmap_config);
-	if (IS_ERR(mvpwm->regs))
-		return PTR_ERR(mvpwm->regs);
+		/*
+		 * Use set A for lines of GPIO chip with id 0, B for GPIO chip
+		 * with id 1. Don't allow further GPIO chips to be used for PWM.
+		 */
+		if (id == 0)
+			set = 0;
+		else if (id == 1)
+			set = U32_MAX;
+		else
+			return -EINVAL;
+	}
+
+	regmap_write(mvchip->regs,
+		     GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set);
 
 	mvpwm->clk_rate = clk_get_rate(mvchip->clk);
 	if (!mvpwm->clk_rate) {
-- 
2.29.2


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

* [PATCH v6 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios
  2021-01-06  7:37 [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 2/4] gpio: mvebu: add pwm support for Armada 8K/7K Baruch Siach
@ 2021-01-06  7:37 ` Baruch Siach
  2021-01-06  7:37 ` [PATCH v6 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property Baruch Siach
  3 siblings, 0 replies; 8+ messages in thread
From: Baruch Siach @ 2021-01-06  7:37 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Rob Herring
  Cc: Baruch Siach, Andrew Lunn, Gregory Clement, Russell King,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

The 'marvell,pwm-offset' property of both GPIO blocks (per CP component)
point to the same counter registers offset. The driver will decide how
to use counters A/B.

This is different from the convention of pwm on earlier Armada series
(370/38x). On those systems the assignment of A/B counters to GPIO
blocks is coded in both DT and the driver. The actual behaviour of the
current driver on Armada 8K/7K is the same as earlier systems.

Add also clock properties for base pwm frequency reference.

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
 arch/arm64/boot/dts/marvell/armada-ap80x.dtsi |  3 +++
 arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 10 ++++++++++
 2 files changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi b/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
index 12e477f1aeb9..6614472100c2 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
@@ -281,6 +281,9 @@ ap_gpio: gpio@1040 {
 					gpio-controller;
 					#gpio-cells = <2>;
 					gpio-ranges = <&ap_pinctrl 0 0 20>;
+					marvell,pwm-offset = <0x10c0>;
+					#pwm-cells = <2>;
+					clocks = <&ap_clk 3>;
 				};
 			};
 
diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
index 994a2fce449a..d774a39334d9 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
@@ -234,12 +234,17 @@ CP11X_LABEL(gpio1): gpio@100 {
 				gpio-controller;
 				#gpio-cells = <2>;
 				gpio-ranges = <&CP11X_LABEL(pinctrl) 0 0 32>;
+				marvell,pwm-offset = <0x1f0>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				interrupts = <86 IRQ_TYPE_LEVEL_HIGH>,
 					<85 IRQ_TYPE_LEVEL_HIGH>,
 					<84 IRQ_TYPE_LEVEL_HIGH>,
 					<83 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <2>;
+				clock-names = "core", "axi";
+				clocks = <&CP11X_LABEL(clk) 1 21>,
+					 <&CP11X_LABEL(clk) 1 17>;
 				status = "disabled";
 			};
 
@@ -250,12 +255,17 @@ CP11X_LABEL(gpio2): gpio@140 {
 				gpio-controller;
 				#gpio-cells = <2>;
 				gpio-ranges = <&CP11X_LABEL(pinctrl) 0 32 31>;
+				marvell,pwm-offset = <0x1f0>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				interrupts = <82 IRQ_TYPE_LEVEL_HIGH>,
 					<81 IRQ_TYPE_LEVEL_HIGH>,
 					<80 IRQ_TYPE_LEVEL_HIGH>,
 					<79 IRQ_TYPE_LEVEL_HIGH>;
 				#interrupt-cells = <2>;
+				clock-names = "core", "axi";
+				clocks = <&CP11X_LABEL(clk) 1 21>,
+					 <&CP11X_LABEL(clk) 1 17>;
 				status = "disabled";
 			};
 		};
-- 
2.29.2


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

* [PATCH v6 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property
  2021-01-06  7:37 [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
                   ` (2 preceding siblings ...)
  2021-01-06  7:37 ` [PATCH v6 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios Baruch Siach
@ 2021-01-06  7:37 ` Baruch Siach
  3 siblings, 0 replies; 8+ messages in thread
From: Baruch Siach @ 2021-01-06  7:37 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
	Bartosz Golaszewski, Rob Herring
  Cc: Baruch Siach, Rob Herring, Andrew Lunn, Gregory Clement,
	Russell King, Sebastian Hesselbarth, Thomas Petazzoni,
	Chris Packham, Sascha Hauer, Ralph Sennhauser, linux-pwm,
	linux-gpio, linux-arm-kernel, devicetree

Update the example as well. Add the '#pwm-cells' and 'clocks' properties
for a complete working example.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
 .../bindings/arm/marvell/ap80x-system-controller.txt      | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt
index e31511255d8e..052a967c1f28 100644
--- a/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt
@@ -80,6 +80,11 @@ Required properties:
 
 - offset: offset address inside the syscon block
 
+Optional properties:
+
+- marvell,pwm-offset: offset address of PWM duration control registers inside
+  the syscon block
+
 Example:
 ap_syscon: system-controller@6f4000 {
 	compatible = "syscon", "simple-mfd";
@@ -101,6 +106,9 @@ ap_syscon: system-controller@6f4000 {
 		gpio-controller;
 		#gpio-cells = <2>;
 		gpio-ranges = <&ap_pinctrl 0 0 19>;
+		marvell,pwm-offset = <0x10c0>;
+		#pwm-cells = <2>;
+		clocks = <&ap_clk 3>;
 	};
 };
 
-- 
2.29.2


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

* Re: [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation
  2021-01-06  7:37 ` [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
@ 2021-01-07 14:29   ` Uwe Kleine-König
  2021-01-10 17:14     ` Baruch Siach
  0 siblings, 1 reply; 8+ messages in thread
From: Uwe Kleine-König @ 2021-01-07 14:29 UTC (permalink / raw)
  To: Baruch Siach
  Cc: Thierry Reding, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Rob Herring, Russell King, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

[-- Attachment #1: Type: text/plain, Size: 2387 bytes --]

On Wed, Jan 06, 2021 at 09:37:37AM +0200, Baruch Siach wrote:
> The period is the sum of on and off values.
> 
> Reported-by: Russell King <linux@armlinux.org.uk>
> Fixes: 757642f9a584e ("gpio: mvebu: Add limited PWM support")
> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> ---
> v6: divide (on + off) sum to reduce rounding error (RMK)
> ---
>  drivers/gpio/gpio-mvebu.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
> index 672681a976f5..a912a8fed197 100644
> --- a/drivers/gpio/gpio-mvebu.c
> +++ b/drivers/gpio/gpio-mvebu.c
> @@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
>  	else
>  		state->duty_cycle = 1;
>  
> +	val = (unsigned long long) u; /* on duration */
>  	regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
> -	val = (unsigned long long) u * NSEC_PER_SEC;
> +	val += (unsigned long long) u; /* period = on + off duration */
> +	val *= NSEC_PER_SEC;
>  	do_div(val, mvpwm->clk_rate);
> -	if (val < state->duty_cycle) {
> +	if (val > UINT_MAX)
> +		state->period = UINT_MAX;

state->period is an u64, so there is no reason to not use values greater
than UINT_MAX.

> +	else if (val)
> +		state->period = val;
> +	else
>  		state->period = 1;

This case assigning 1 looks strange. An explanation in a comment would
be great. I wonder if this is a hardware property or if it is only used
to not report 0 in case that mvpwm->clk_rate is high.

I found a few further shortcommings in the mvebu_pwm implementation while
looking through it:

 a) The rounding problem that RMK found is also present in .apply

    There we have:

    	val = clk_rate * (period - duty_cycle) / NSEC_PER_SEC

    while

    	val = clk_rate * period / NSEC_PER_SEC - on

    would be more exact.

 b) To make

 	pwm_get_state(pwm, &state);
	pwm_apply_state(pwm, &state);

    idempotent .get_state should round up the division results.

 c) .apply also has a check for val being zero and configures at least 1
    cycle for the on and off intervals. Is this a hardware imposed
    limitation? 

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation
  2021-01-07 14:29   ` Uwe Kleine-König
@ 2021-01-10 17:14     ` Baruch Siach
  2021-01-11  8:10       ` Uwe Kleine-König
  0 siblings, 1 reply; 8+ messages in thread
From: Baruch Siach @ 2021-01-10 17:14 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Thierry Reding, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Rob Herring, Russell King, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree

Hi Uwe,

Thanks for your review comments.

On Thu, Jan 07 2021, Uwe Kleine-König wrote:
> On Wed, Jan 06, 2021 at 09:37:37AM +0200, Baruch Siach wrote:
>> The period is the sum of on and off values.
>> 
>> Reported-by: Russell King <linux@armlinux.org.uk>
>> Fixes: 757642f9a584e ("gpio: mvebu: Add limited PWM support")
>> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
>> ---
>> v6: divide (on + off) sum to reduce rounding error (RMK)
>> ---
>>  drivers/gpio/gpio-mvebu.c | 19 ++++++++-----------
>>  1 file changed, 8 insertions(+), 11 deletions(-)
>> 
>> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
>> index 672681a976f5..a912a8fed197 100644
>> --- a/drivers/gpio/gpio-mvebu.c
>> +++ b/drivers/gpio/gpio-mvebu.c
>> @@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
>>  	else
>>  		state->duty_cycle = 1;
>>  
>> +	val = (unsigned long long) u; /* on duration */
>>  	regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
>> -	val = (unsigned long long) u * NSEC_PER_SEC;
>> +	val += (unsigned long long) u; /* period = on + off duration */
>> +	val *= NSEC_PER_SEC;
>>  	do_div(val, mvpwm->clk_rate);
>> -	if (val < state->duty_cycle) {
>> +	if (val > UINT_MAX)
>> +		state->period = UINT_MAX;
>
> state->period is an u64, so there is no reason to not use values greater
> than UINT_MAX.

I'll post a patch for that.

>> +	else if (val)
>> +		state->period = val;
>> +	else
>>  		state->period = 1;
>
> This case assigning 1 looks strange. An explanation in a comment would
> be great. I wonder if this is a hardware property or if it is only used
> to not report 0 in case that mvpwm->clk_rate is high.

I guess that this is because 0 period does not make sense for pwm. It is
like a zero divisor. What is the common behavior?

> I found a few further shortcommings in the mvebu_pwm implementation while
> looking through it:
>
>  a) The rounding problem that RMK found is also present in .apply
>
>     There we have:
>
>     	val = clk_rate * (period - duty_cycle) / NSEC_PER_SEC
>
>     while
>
>     	val = clk_rate * period / NSEC_PER_SEC - on
>
>     would be more exact.

I'll post a patch for that.

>  b) To make
>
>  	pwm_get_state(pwm, &state);
> 	pwm_apply_state(pwm, &state);
>
>     idempotent .get_state should round up the division results.

I'll post a patch for that as well.

>  c) .apply also has a check for val being zero and configures at least 1
>     cycle for the on and off intervals. Is this a hardware imposed
>     limitation? 

Not sure what was the original intention. Maybe Andrew can explain.

On my hardware (Armada 8040), zero 'on' value does not work as
expected. There is a blink once in a long while. Maybe this is the
reason?

As I understand, all these issues should not block this patch, right?

BTW, the key you used to sign your message is expired since 2020-01-10
on the key server I use (keys.gnupg.net). Where can I find your updated
key?

Thanks,
baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch@tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -

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

* Re: [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation
  2021-01-10 17:14     ` Baruch Siach
@ 2021-01-11  8:10       ` Uwe Kleine-König
  0 siblings, 0 replies; 8+ messages in thread
From: Uwe Kleine-König @ 2021-01-11  8:10 UTC (permalink / raw)
  To: Baruch Siach
  Cc: Thierry Reding, Lee Jones, Linus Walleij, Bartosz Golaszewski,
	Rob Herring, Russell King, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
	Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
	linux-arm-kernel, devicetree, kernel

[-- Attachment #1: Type: text/plain, Size: 4178 bytes --]

On Sun, Jan 10, 2021 at 07:14:17PM +0200, Baruch Siach wrote:
> Hi Uwe,
> 
> Thanks for your review comments.
> 
> On Thu, Jan 07 2021, Uwe Kleine-König wrote:
> > On Wed, Jan 06, 2021 at 09:37:37AM +0200, Baruch Siach wrote:
> >> The period is the sum of on and off values.
> >> 
> >> Reported-by: Russell King <linux@armlinux.org.uk>
> >> Fixes: 757642f9a584e ("gpio: mvebu: Add limited PWM support")
> >> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> >> ---
> >> v6: divide (on + off) sum to reduce rounding error (RMK)
> >> ---
> >>  drivers/gpio/gpio-mvebu.c | 19 ++++++++-----------
> >>  1 file changed, 8 insertions(+), 11 deletions(-)
> >> 
> >> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
> >> index 672681a976f5..a912a8fed197 100644
> >> --- a/drivers/gpio/gpio-mvebu.c
> >> +++ b/drivers/gpio/gpio-mvebu.c
> >> @@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
> >>  	else
> >>  		state->duty_cycle = 1;
> >>  
> >> +	val = (unsigned long long) u; /* on duration */
> >>  	regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
> >> -	val = (unsigned long long) u * NSEC_PER_SEC;
> >> +	val += (unsigned long long) u; /* period = on + off duration */
> >> +	val *= NSEC_PER_SEC;
> >>  	do_div(val, mvpwm->clk_rate);
> >> -	if (val < state->duty_cycle) {
> >> +	if (val > UINT_MAX)
> >> +		state->period = UINT_MAX;
> >
> > state->period is an u64, so there is no reason to not use values greater
> > than UINT_MAX.
> 
> I'll post a patch for that.
> 
> >> +	else if (val)
> >> +		state->period = val;
> >> +	else
> >>  		state->period = 1;
> >
> > This case assigning 1 looks strange. An explanation in a comment would
> > be great. I wonder if this is a hardware property or if it is only used
> > to not report 0 in case that mvpwm->clk_rate is high.
> 
> I guess that this is because 0 period does not make sense for pwm. It is
> like a zero divisor. What is the common behavior?

It depends on how the hardware behaves in this case. One measure is to
use round-up (in .get_state) for the divisions -- as I already pointed
out. Then the problem only triggers if both on and off registers are
zero.

> > I found a few further shortcommings in the mvebu_pwm implementation while
> > looking through it:
> >
> >  a) The rounding problem that RMK found is also present in .apply
> >
> >     There we have:
> >
> >     	val = clk_rate * (period - duty_cycle) / NSEC_PER_SEC
> >
> >     while
> >
> >     	val = clk_rate * period / NSEC_PER_SEC - on
> >
> >     would be more exact.
> 
> I'll post a patch for that.
> 
> >  b) To make
> >
> >  	pwm_get_state(pwm, &state);
> > 	pwm_apply_state(pwm, &state);
> >
> >     idempotent .get_state should round up the division results.
> 
> I'll post a patch for that as well.
> 
> >  c) .apply also has a check for val being zero and configures at least 1
> >     cycle for the on and off intervals. Is this a hardware imposed
> >     limitation? 
> 
> Not sure what was the original intention. Maybe Andrew can explain.
> 
> On my hardware (Armada 8040), zero 'on' value does not work as
> expected. There is a blink once in a long while. Maybe this is the
> reason?

It would be good to understand and document this. Hardware PWMs not
supporting a zero duty cycle are always a surprise for me and probably
also others.

> As I understand, all these issues should not block this patch, right?

Yes, having this patch in a series fixing all the stuff I pointed out
would still be very welcome :-)

> BTW, the key you used to sign your message is expired since 2020-01-10
> on the key server I use (keys.gnupg.net). Where can I find your updated
> key?

Hmm, I thought keyservers are out of fashion. Anyhow, I updated my key
there. There is no WKD for @pengutronix.de addresses, but

	gpg --locate-external-keys uwe@kleine-koenig.org

should work just fine, too.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

end of thread, other threads:[~2021-01-11  8:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-06  7:37 [PATCH v6 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
2021-01-06  7:37 ` [PATCH v6 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
2021-01-07 14:29   ` Uwe Kleine-König
2021-01-10 17:14     ` Baruch Siach
2021-01-11  8:10       ` Uwe Kleine-König
2021-01-06  7:37 ` [PATCH v6 2/4] gpio: mvebu: add pwm support for Armada 8K/7K Baruch Siach
2021-01-06  7:37 ` [PATCH v6 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios Baruch Siach
2021-01-06  7:37 ` [PATCH v6 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property Baruch Siach

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).