Re: [U-Boot] [PATCH] pwm: rk_pwm: Make PWM driver to support all Rockchip Socs

2019-11-26 Thread Kever Yang

Hi David,

On 2019/11/25 下午3:38, David Wu wrote:

The new PWM driver supports PWM polarity, lock and more functions.


Please add a little bit more info about the patch, eg. the difference 
for pwm v1 vs v2 vs v3.



Thanks,

- Kever



Signed-off-by: David Wu 
---
  arch/arm/include/asm/arch-rockchip/pwm.h |  17 ++-
  drivers/pwm/rk_pwm.c | 139 +++
  2 files changed, 131 insertions(+), 25 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h 
b/arch/arm/include/asm/arch-rockchip/pwm.h
index b5178db394..e8594055cd 100644
--- a/arch/arm/include/asm/arch-rockchip/pwm.h
+++ b/arch/arm/include/asm/arch-rockchip/pwm.h
@@ -7,13 +7,15 @@
  #ifndef _ASM_ARCH_PWM_H
  #define _ASM_ARCH_PWM_H
  
-struct rk3288_pwm {

-   u32 cnt;
-   u32 period_hpr;
-   u32 duty_lpr;
-   u32 ctrl;
+struct rockchip_pwm_regs {
+   unsigned long duty;
+   unsigned long period;
+   unsigned long cntr;
+   unsigned long ctrl;
  };
-check_member(rk3288_pwm, ctrl, 0xc);
+
+#define PWM_CTRL_TIMER_EN  (1 << 0)
+#define PWM_CTRL_OUTPUT_EN (1 << 3)
  
  #define RK_PWM_DISABLE  (0 << 0)

  #define RK_PWM_ENABLE   (1 << 0)
@@ -33,6 +35,9 @@ check_member(rk3288_pwm, ctrl, 0xc);
  #define PWM_OUTPUT_LEFT (0 << 5)
  #define PWM_OUTPUT_CENTER   (1 << 5)
  
+#define PWM_LOCK			(1 << 6)

+#define PWM_UNLOCK (0 << 6)
+
  #define PWM_LP_ENABLE   (1 << 8)
  #define PWM_LP_DISABLE  (0 << 8)
  
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c

index 88db294cf1..c9d9b7c11b 100644
--- a/drivers/pwm/rk_pwm.c
+++ b/drivers/pwm/rk_pwm.c
@@ -15,22 +15,38 @@
  #include 
  #include 
  
+DECLARE_GLOBAL_DATA_PTR;

+
+struct rockchip_pwm_data {
+   struct rockchip_pwm_regs regs;
+   unsigned int prescaler;
+   bool supports_polarity;
+   bool supports_lock;
+   u32 enable_conf;
+   u32 enable_conf_mask;
+};
+
  struct rk_pwm_priv {
-   struct rk3288_pwm *regs;
+   fdt_addr_t base;
ulong freq;
-   uint enable_conf;
+   u32 conf_polarity;
+   const struct rockchip_pwm_data *data;
  };
  
  static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity)

  {
struct rk_pwm_priv *priv = dev_get_priv(dev);
  
+	if (!priv->data->supports_polarity) {

+   debug("%s: Do not support polarity\n", __func__);
+   return 0;
+   }
+
debug("%s: polarity=%u\n", __func__, polarity);
-   priv->enable_conf &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK);
if (polarity)
-   priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
+   priv->conf_polarity = PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
else
-   priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
+   priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
  
  	return 0;

  }
@@ -39,20 +55,44 @@ static int rk_pwm_set_config(struct udevice *dev, uint 
channel, uint period_ns,
 uint duty_ns)
  {
struct rk_pwm_priv *priv = dev_get_priv(dev);
-   struct rk3288_pwm *regs = priv->regs;
+   const struct rockchip_pwm_regs *regs = >data->regs;
unsigned long period, duty;
+   u32 ctrl;
  
  	debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);

-   writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
-   PWM_CONTINUOUS | priv->enable_conf |
-   RK_PWM_DISABLE,
-   >ctrl);
  
-	period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 100);

-   duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 100);
+   ctrl = readl(priv->base + regs->ctrl);
+   /*
+* Lock the period and duty of previous configuration, then
+* change the duty and period, that would not be effective.
+*/
+   if (priv->data->supports_lock) {
+   ctrl |= PWM_LOCK;
+   writel(ctrl, priv->base + regs->ctrl);
+   }
+
+   period = lldiv((uint64_t)priv->freq * period_ns,
+  priv->data->prescaler * 10);
+   duty = lldiv((uint64_t)priv->freq * duty_ns,
+priv->data->prescaler * 10);
+
+   writel(period, priv->base + regs->period);
+   writel(duty, priv->base + regs->duty);
+
+   if (priv->data->supports_polarity) {
+   ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK);
+   ctrl |= priv->conf_polarity;
+   }
+
+   /*
+* Unlock and set polarity at the same time,
+* the configuration of duty, period and polarity
+* would be effective together at next period.
+*/
+   if (priv->data->supports_lock)
+   ctrl &= ~PWM_LOCK;
+   writel(ctrl, priv->base + regs->ctrl);
  
-	writel(period, >period_hpr);

-   writel(duty, 

[U-Boot] [PATCH] pwm: rk_pwm: Make PWM driver to support all Rockchip Socs

2019-11-24 Thread David Wu
The new PWM driver supports PWM polarity, lock and more functions.

Signed-off-by: David Wu 
---
 arch/arm/include/asm/arch-rockchip/pwm.h |  17 ++-
 drivers/pwm/rk_pwm.c | 139 +++
 2 files changed, 131 insertions(+), 25 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h 
b/arch/arm/include/asm/arch-rockchip/pwm.h
index b5178db394..e8594055cd 100644
--- a/arch/arm/include/asm/arch-rockchip/pwm.h
+++ b/arch/arm/include/asm/arch-rockchip/pwm.h
@@ -7,13 +7,15 @@
 #ifndef _ASM_ARCH_PWM_H
 #define _ASM_ARCH_PWM_H
 
-struct rk3288_pwm {
-   u32 cnt;
-   u32 period_hpr;
-   u32 duty_lpr;
-   u32 ctrl;
+struct rockchip_pwm_regs {
+   unsigned long duty;
+   unsigned long period;
+   unsigned long cntr;
+   unsigned long ctrl;
 };
-check_member(rk3288_pwm, ctrl, 0xc);
+
+#define PWM_CTRL_TIMER_EN  (1 << 0)
+#define PWM_CTRL_OUTPUT_EN (1 << 3)
 
 #define RK_PWM_DISABLE  (0 << 0)
 #define RK_PWM_ENABLE   (1 << 0)
@@ -33,6 +35,9 @@ check_member(rk3288_pwm, ctrl, 0xc);
 #define PWM_OUTPUT_LEFT (0 << 5)
 #define PWM_OUTPUT_CENTER   (1 << 5)
 
+#define PWM_LOCK   (1 << 6)
+#define PWM_UNLOCK (0 << 6)
+
 #define PWM_LP_ENABLE   (1 << 8)
 #define PWM_LP_DISABLE  (0 << 8)
 
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c
index 88db294cf1..c9d9b7c11b 100644
--- a/drivers/pwm/rk_pwm.c
+++ b/drivers/pwm/rk_pwm.c
@@ -15,22 +15,38 @@
 #include 
 #include 
 
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rockchip_pwm_data {
+   struct rockchip_pwm_regs regs;
+   unsigned int prescaler;
+   bool supports_polarity;
+   bool supports_lock;
+   u32 enable_conf;
+   u32 enable_conf_mask;
+};
+
 struct rk_pwm_priv {
-   struct rk3288_pwm *regs;
+   fdt_addr_t base;
ulong freq;
-   uint enable_conf;
+   u32 conf_polarity;
+   const struct rockchip_pwm_data *data;
 };
 
 static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity)
 {
struct rk_pwm_priv *priv = dev_get_priv(dev);
 
+   if (!priv->data->supports_polarity) {
+   debug("%s: Do not support polarity\n", __func__);
+   return 0;
+   }
+
debug("%s: polarity=%u\n", __func__, polarity);
-   priv->enable_conf &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK);
if (polarity)
-   priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
+   priv->conf_polarity = PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
else
-   priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
+   priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
 
return 0;
 }
@@ -39,20 +55,44 @@ static int rk_pwm_set_config(struct udevice *dev, uint 
channel, uint period_ns,
 uint duty_ns)
 {
struct rk_pwm_priv *priv = dev_get_priv(dev);
-   struct rk3288_pwm *regs = priv->regs;
+   const struct rockchip_pwm_regs *regs = >data->regs;
unsigned long period, duty;
+   u32 ctrl;
 
debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
-   writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
-   PWM_CONTINUOUS | priv->enable_conf |
-   RK_PWM_DISABLE,
-   >ctrl);
 
-   period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 100);
-   duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 100);
+   ctrl = readl(priv->base + regs->ctrl);
+   /*
+* Lock the period and duty of previous configuration, then
+* change the duty and period, that would not be effective.
+*/
+   if (priv->data->supports_lock) {
+   ctrl |= PWM_LOCK;
+   writel(ctrl, priv->base + regs->ctrl);
+   }
+
+   period = lldiv((uint64_t)priv->freq * period_ns,
+  priv->data->prescaler * 10);
+   duty = lldiv((uint64_t)priv->freq * duty_ns,
+priv->data->prescaler * 10);
+
+   writel(period, priv->base + regs->period);
+   writel(duty, priv->base + regs->duty);
+
+   if (priv->data->supports_polarity) {
+   ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK);
+   ctrl |= priv->conf_polarity;
+   }
+
+   /*
+* Unlock and set polarity at the same time,
+* the configuration of duty, period and polarity
+* would be effective together at next period.
+*/
+   if (priv->data->supports_lock)
+   ctrl &= ~PWM_LOCK;
+   writel(ctrl, priv->base + regs->ctrl);
 
-   writel(period, >period_hpr);
-   writel(duty, >duty_lpr);
debug("%s: period=%lu, duty=%lu\n", __func__, period, duty);
 
return 0;
@@ -61,10 +101,20 @@ static int rk_pwm_set_config(struct udevice