* [PATCH v5 1/4] gpio: mvebu: fix pwm get_state period calculation
2021-01-05 12:42 [PATCH v5 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
@ 2021-01-05 12:42 ` Baruch Siach
2021-01-05 12:49 ` Russell King - ARM Linux admin
2021-01-05 12:42 ` [PATCH v5 2/4] gpio: mvebu: add pwm support for Armada 8K/7K Baruch Siach
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Baruch Siach @ 2021-01-05 12:42 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>
---
drivers/gpio/gpio-mvebu.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 672681a976f5..ac7cb6d3702e 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -679,17 +679,13 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
val = (unsigned long long) u * NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
- if (val < state->duty_cycle) {
+ 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] 6+ messages in thread
* Re: [PATCH v5 1/4] gpio: mvebu: fix pwm get_state period calculation
2021-01-05 12:42 ` [PATCH v5 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
@ 2021-01-05 12:49 ` Russell King - ARM Linux admin
0 siblings, 0 replies; 6+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-05 12:49 UTC (permalink / raw)
To: Baruch Siach
Cc: Thierry Reding, Uwe Kleine-König, Lee Jones, Linus Walleij,
Bartosz Golaszewski, Rob Herring, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth, Thomas Petazzoni, Chris Packham,
Sascha Hauer, Ralph Sennhauser, linux-pwm, linux-gpio,
linux-arm-kernel, devicetree
On Tue, Jan 05, 2021 at 02:42:28PM +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>
> ---
> drivers/gpio/gpio-mvebu.c | 16 ++++++----------
> 1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
> index 672681a976f5..ac7cb6d3702e 100644
> --- a/drivers/gpio/gpio-mvebu.c
> +++ b/drivers/gpio/gpio-mvebu.c
> @@ -679,17 +679,13 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
> regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
> val = (unsigned long long) u * NSEC_PER_SEC;
> do_div(val, mvpwm->clk_rate);
> - if (val < state->duty_cycle) {
> + val += state->duty_cycle;
> + if (val > UINT_MAX)
> + state->period = UINT_MAX;
> + else if (val)
> + state->period = val;
> + else
> state->period = 1;
Are you sure this is the correct solution? Aren't you introducing
rounding errors?
The hardware will count to (on + off) clock ticks, so the right way
to convert that is to add the two together and then convert to
nanoseconds, which may result in a single rounding error. If you
convert each individually to nanoseconds, then you can end up with
two sets of rounding errors.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v5 2/4] gpio: mvebu: add pwm support for Armada 8K/7K
2021-01-05 12:42 [PATCH v5 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
2021-01-05 12:42 ` [PATCH v5 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
@ 2021-01-05 12:42 ` Baruch Siach
2021-01-05 12:42 ` [PATCH v5 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios Baruch Siach
2021-01-05 12:42 ` [PATCH v5 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property Baruch Siach
3 siblings, 0 replies; 6+ messages in thread
From: Baruch Siach @ 2021-01-05 12:42 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 ac7cb6d3702e..1a8259efd5e5 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;
}
/*
@@ -777,51 +783,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] 6+ messages in thread
* [PATCH v5 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios
2021-01-05 12:42 [PATCH v5 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
2021-01-05 12:42 ` [PATCH v5 1/4] gpio: mvebu: fix pwm get_state period calculation Baruch Siach
2021-01-05 12:42 ` [PATCH v5 2/4] gpio: mvebu: add pwm support for Armada 8K/7K Baruch Siach
@ 2021-01-05 12:42 ` Baruch Siach
2021-01-05 12:42 ` [PATCH v5 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property Baruch Siach
3 siblings, 0 replies; 6+ messages in thread
From: Baruch Siach @ 2021-01-05 12:42 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] 6+ messages in thread
* [PATCH v5 4/4] dt-bindings: ap806: document gpio marvell,pwm-offset property
2021-01-05 12:42 [PATCH v5 0/4] gpio: mvebu: Armada 8K/7K PWM support Baruch Siach
` (2 preceding siblings ...)
2021-01-05 12:42 ` [PATCH v5 3/4] arm64: dts: armada: add pwm offsets for ap/cp gpios Baruch Siach
@ 2021-01-05 12:42 ` Baruch Siach
3 siblings, 0 replies; 6+ messages in thread
From: Baruch Siach @ 2021-01-05 12:42 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] 6+ messages in thread