[linux-sunxi] [PATCH 6/6] pwm: sun4i: don't delay if the PWM is already off

2021-05-30 Thread Roman Beranek
Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 6ab06b9749d0..88bd90498d1f 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -304,7 +304,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
 
-   if (state->enabled) {
+   if (state->enabled || !cstate.enabled) {
mutex_unlock(_pwm->ctrl_lock);
return 0;
}
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-7-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 5/6] pwm: sun4i: shorten the delay to 2 cycles

2021-05-30 Thread Roman Beranek
As Emil Lenngren has previously shown, actually only 1-2 cycles of
the prescaler-divided clock are necessary to pass before the PWM turns
off (instead of a full period). I was able to reproduce his observation
on a A64 using a logic analyzer.

Suggested-by: Emil Lenngren 
Suggested-by: Pascal Roeleven 
Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 8218173ce3f6..6ab06b9749d0 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -71,7 +71,7 @@ static const u32 prescaler_table[] = {
72000,
0,
0,
-   0, /* Actually 1 but tested separately */
+   1, /* Tested separately */
 };
 
 struct sun4i_pwm_data {
@@ -240,7 +240,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
struct pwm_state cstate;
u32 ctrl, duty = 0, period = 0, val;
int ret;
-   unsigned int prescaler = 0;
+   unsigned int cycle_ns, current_prescaler, prescaler = 0;
bool bypass;
 
pwm_get_state(pwm, );
@@ -277,7 +277,8 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
ctrl &= ~BIT_CH(PWM_BYPASS, pwm->hwpwm);
}
 
-   if (PWM_REG_PRESCAL(ctrl, pwm->hwpwm) != prescaler) {
+   current_prescaler = PWM_REG_PRESCAL(ctrl, pwm->hwpwm);
+   if (current_prescaler != prescaler) {
/* Prescaler changed, the clock has to be gated */
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
@@ -308,8 +309,10 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
return 0;
}
 
-   /* We need a full period to elapse before disabling the channel. */
-   fsleep(cstate.period / NSEC_PER_USEC + 1);
+   /* We need to wait 1-2 cycles before disabling the channel. */
+   cycle_ns = DIV_ROUND_UP(NSEC_PER_SEC, clk_get_rate(sun4i_pwm->clk))
+  * prescaler_table[current_prescaler];
+   fsleep(DIV_ROUND_UP(cycle_ns * 2, NSEC_PER_USEC));
 
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-6-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 2/6] pwm: sun4i: disable EN bit prior to the delay

2021-05-30 Thread Roman Beranek
The reason why we wait before gating the clock is to allow for the PWM
to finish its cycle and stop. But it won't stop unless the EN bit is
disabled.

Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 3721b9894cf6..2777abe66f79 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -303,6 +303,8 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
if (state->enabled)
ctrl |= BIT_CH(PWM_EN, pwm->hwpwm);
+   else
+   ctrl &= ~BIT_CH(PWM_EN, pwm->hwpwm);
 
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
 
@@ -325,7 +327,6 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
spin_lock(_pwm->ctrl_lock);
ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
-   ctrl &= ~BIT_CH(PWM_EN, pwm->hwpwm);
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
spin_unlock(_pwm->ctrl_lock);
 
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-3-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 4/6] pwm: sun4i: simplify calculation of the delay time

2021-05-30 Thread Roman Beranek
There's no reason to expect a single jiffy has passed since writing
the CTRL register except if a preemption has occured in the meantime.
Avoid introducing unnecessary complexity and simply wait for the whole
period.

Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 17 ++---
 1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index b3ec59a83d00..8218173ce3f6 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -89,7 +88,6 @@ struct sun4i_pwm_chip {
void __iomem *base;
struct mutex ctrl_lock;
const struct sun4i_pwm_data *data;
-   unsigned long next_period[2];
 };
 
 static inline struct sun4i_pwm_chip *to_sun4i_pwm_chip(struct pwm_chip *chip)
@@ -242,8 +240,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
struct pwm_state cstate;
u32 ctrl, duty = 0, period = 0, val;
int ret;
-   unsigned int delay_us, prescaler = 0;
-   unsigned long now;
+   unsigned int prescaler = 0;
bool bypass;
 
pwm_get_state(pwm, );
@@ -291,8 +288,6 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
val = (duty & PWM_DTY_MASK) | PWM_PRD(period);
sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm));
-   sun4i_pwm->next_period[pwm->hwpwm] = jiffies +
-   nsecs_to_jiffies(cstate.period + 1000);
 
if (state->polarity != PWM_POLARITY_NORMAL)
ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
@@ -314,15 +309,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
}
 
/* We need a full period to elapse before disabling the channel. */
-   now = jiffies;
-   if (time_before(now, sun4i_pwm->next_period[pwm->hwpwm])) {
-   delay_us = jiffies_to_usecs(sun4i_pwm->next_period[pwm->hwpwm] -
-  now);
-   if ((delay_us / 500) > MAX_UDELAY_MS)
-   msleep(delay_us / 1000 + 1);
-   else
-   usleep_range(delay_us, delay_us * 2);
-   }
+   fsleep(cstate.period / NSEC_PER_USEC + 1);
 
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-5-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 3/6] pwm: sun4i: replace spinlock with a mutex

2021-05-30 Thread Roman Beranek
Releasing ctrl_lock for the duration of the delay is not desirable as it
allows re-enabling the PWM before the delay is over. Instead, substitute
the spinlock with a mutex so that we can sleep while holding it.

Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 2777abe66f79..b3ec59a83d00 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -16,13 +16,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #define PWM_CTRL_REG   0x0
@@ -87,7 +87,7 @@ struct sun4i_pwm_chip {
struct clk *clk;
struct reset_control *rst;
void __iomem *base;
-   spinlock_t ctrl_lock;
+   struct mutex ctrl_lock;
const struct sun4i_pwm_data *data;
unsigned long next_period[2];
 };
@@ -265,7 +265,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
return ret;
}
 
-   spin_lock(_pwm->ctrl_lock);
+   mutex_lock(_pwm->ctrl_lock);
ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
 
if (sun4i_pwm->data->has_direct_mod_clk_output) {
@@ -273,7 +273,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
ctrl |= BIT_CH(PWM_BYPASS, pwm->hwpwm);
/* We can skip other parameter */
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
-   spin_unlock(_pwm->ctrl_lock);
+   mutex_unlock(_pwm->ctrl_lock);
return 0;
}
 
@@ -308,10 +308,10 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
 
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
 
-   spin_unlock(_pwm->ctrl_lock);
-
-   if (state->enabled)
+   if (state->enabled) {
+   mutex_unlock(_pwm->ctrl_lock);
return 0;
+   }
 
/* We need a full period to elapse before disabling the channel. */
now = jiffies;
@@ -324,11 +324,9 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct 
pwm_device *pwm,
usleep_range(delay_us, delay_us * 2);
}
 
-   spin_lock(_pwm->ctrl_lock);
-   ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
-   spin_unlock(_pwm->ctrl_lock);
+   mutex_unlock(_pwm->ctrl_lock);
 
clk_disable_unprepare(sun4i_pwm->clk);
 
@@ -471,7 +469,7 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
pwm->chip.of_xlate = of_pwm_xlate_with_flags;
pwm->chip.of_pwm_n_cells = 3;
 
-   spin_lock_init(>ctrl_lock);
+   mutex_init(>ctrl_lock);
 
ret = pwmchip_add(>chip);
if (ret < 0) {
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-4-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 1/6] pwm: sun4i: enable clk prior to getting its rate

2021-05-30 Thread Roman Beranek
Ensure the PWM clock is enabled prior to retrieving its rate, as is
already being done in sun4i_pwm_apply.

Signed-off-by: Roman Beranek 
---
 drivers/pwm/pwm-sun4i.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index e01becd102c0..3721b9894cf6 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -117,8 +117,15 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
u64 clk_rate, tmp;
u32 val;
unsigned int prescaler;
+   int ret;
 
+   ret = clk_prepare_enable(sun4i_pwm->clk);
+   if (ret) {
+   dev_err(chip->dev, "failed to enable PWM clock\n");
+   return;
+   }
clk_rate = clk_get_rate(sun4i_pwm->clk);
+   clk_disable_unprepare(sun4i_pwm->clk);
 
val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
 
-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-2-roman.beranek%40prusa3d.com.


[linux-sunxi] [PATCH 0/6] pwm: sun4i: only wait 2 cycles prior to disabling

2021-05-30 Thread Roman Beranek
As Emil Lenngren has previously shown [1], actually only 1-2 cycles of
the prescaler-divided clock are necessary to pass before the PWM turns
off, not a full period.

To avoid having the PWM re-enabled from another thread while asleep,
ctrl_lock spinlock was converted to a mutex so that it can be released
only after the clock gate has finally been turned on.

[1] https://linux-sunxi.org/PWM_Controller_Register_Guide

Roman Beranek (6):
  pwm: sun4i: enable clk prior to getting its rate
  pwm: sun4i: disable EN bit prior to the delay
  pwm: sun4i: replace spinlock with a mutex
  pwm: sun4i: simplify calculation of the delay time
  pwm: sun4i: shorten the delay to 2 cycles
  pwm: sun4i: don't delay if the PWM is already off

 drivers/pwm/pwm-sun4i.c | 56 +++--
 1 file changed, 26 insertions(+), 30 deletions(-)

-- 
2.31.1

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531044608.1006024-1-roman.beranek%40prusa3d.com.


[linux-sunxi] Pull request: u-boot-sunxi/master for v2021.07

2021-05-30 Thread Andre Przywara
Hi Tom,

please pull the master branch from u-boot-sunxi, containing the fix
to bring back the SD card as MMC0. In the long run we are looking into a
more robust solution, but for now we need to fix this, as this breaks
the user experience left, right, and centre.
Also add the one MAINTAINERS path addition from Samuel.

Thanks,
Andre

==
The following changes since commit ffd810487ec2ff6095edf3f3d058d7ed6eb85ff3:

  Merge tag 'u-boot-stm32-20210528' of 
https://source.denx.de/u-boot/custodians/u-boot-stm (2021-05-28 14:11:06 -0400)

are available in the Git repository at:

  https://source.denx.de/u-boot/custodians/u-boot-sunxi.git master

for you to fetch changes up to f264e796c06d7ce6c039bfc7255390309cbc5191:

  MAINTAINERS: Add allwinner/sunxi driver directories (2021-05-31 00:39:54 
+0100)


Andre Przywara (1):
  sunxi: Bring back SD card as MMC device 0

Samuel Holland (1):
  MAINTAINERS: Add allwinner/sunxi driver directories

 MAINTAINERS| 3 +++
 arch/arm/dts/sunxi-u-boot.dtsi | 1 +
 2 files changed, 4 insertions(+)

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20210531002345.1335-1-andre.przywara%40arm.com.