[2/2] drivers: pwm: pwm-atmel: implement pwm dead-times

Submitted by Claudiu Beznea on May 8, 2017, 2:24 p.m.

Details

Message ID 1494253463-26993-3-git-send-email-claudiu.beznea@microchip.com
State New
Headers show

Commit Message

Claudiu Beznea May 8, 2017, 2:24 p.m.
Implement PWM dead-times for atmel PWM controllers.
Since this driver is used by PWM controllers which
supports dead-times and PWM controllers which doesn't,
add specific input for dead-time register in atmel
register private data structure.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 drivers/pwm/pwm-atmel.c | 62 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 58 insertions(+), 4 deletions(-)

Comments

kbuild test robot May 8, 2017, 7:09 p.m.
Hi Claudiu,

[auto build test WARNING on pwm/for-next]
[also build test WARNING on next-20170508]
[cannot apply to v4.11]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Claudiu-Beznea/extends-PWM-framework-to-support-PWM-dead-times/20170509-000624
base:   https://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git for-next
config: arm-multi_v5_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings

All warnings (new ones prefixed by >>):

   In file included from include/linux/io.h:25:0,
                    from drivers/pwm/pwm-atmel.c:13:
   drivers/pwm/pwm-atmel.c: In function 'atmel_pwm_apply':
>> arch/arm/include/asm/io.h:100:2: warning: 'dt' may be used uninitialized in this function [-Wmaybe-uninitialized]
     asm volatile("str %1, %0"
     ^~~
   drivers/pwm/pwm-atmel.c:246:28: note: 'dt' was declared here
     unsigned long cprd, cdty, dt;
                               ^~
--
   In file included from include/linux/io.h:25:0,
                    from drivers//pwm/pwm-atmel.c:13:
   drivers//pwm/pwm-atmel.c: In function 'atmel_pwm_apply':
>> arch/arm/include/asm/io.h:100:2: warning: 'dt' may be used uninitialized in this function [-Wmaybe-uninitialized]
     asm volatile("str %1, %0"
     ^~~
   drivers//pwm/pwm-atmel.c:246:28: note: 'dt' was declared here
     unsigned long cprd, cdty, dt;
                               ^~

vim +/dt +100 arch/arm/include/asm/io.h

5bb5d66d8 Peter Hurley   2015-04-13   84  		     : "=r" (val)
5bb5d66d8 Peter Hurley   2015-04-13   85  		     : "Q" (*(volatile u16 __force *)addr));
195bbcac2 Will Deacon    2012-08-24   86  	return val;
195bbcac2 Will Deacon    2012-08-24   87  }
195bbcac2 Will Deacon    2012-08-24   88  #endif
195bbcac2 Will Deacon    2012-08-24   89  
84c4d3a6d Thierry Reding 2014-07-28   90  #define __raw_writeb __raw_writeb
195bbcac2 Will Deacon    2012-08-24   91  static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
195bbcac2 Will Deacon    2012-08-24   92  {
195bbcac2 Will Deacon    2012-08-24   93  	asm volatile("strb %1, %0"
5bb5d66d8 Peter Hurley   2015-04-13   94  		     : : "Qo" (*(volatile u8 __force *)addr), "r" (val));
195bbcac2 Will Deacon    2012-08-24   95  }
195bbcac2 Will Deacon    2012-08-24   96  
84c4d3a6d Thierry Reding 2014-07-28   97  #define __raw_writel __raw_writel
195bbcac2 Will Deacon    2012-08-24   98  static inline void __raw_writel(u32 val, volatile void __iomem *addr)
195bbcac2 Will Deacon    2012-08-24   99  {
195bbcac2 Will Deacon    2012-08-24 @100  	asm volatile("str %1, %0"
5bb5d66d8 Peter Hurley   2015-04-13  101  		     : : "Qo" (*(volatile u32 __force *)addr), "r" (val));
195bbcac2 Will Deacon    2012-08-24  102  }
195bbcac2 Will Deacon    2012-08-24  103  
84c4d3a6d Thierry Reding 2014-07-28  104  #define __raw_readb __raw_readb
195bbcac2 Will Deacon    2012-08-24  105  static inline u8 __raw_readb(const volatile void __iomem *addr)
195bbcac2 Will Deacon    2012-08-24  106  {
195bbcac2 Will Deacon    2012-08-24  107  	u8 val;
5bb5d66d8 Peter Hurley   2015-04-13  108  	asm volatile("ldrb %0, %1"

:::::: The code at line 100 was first introduced by commit
:::::: 195bbcac2e5c12f7fb99cdcc492c3000c5537f4a ARM: 7500/1: io: avoid writeback addressing modes for __raw_ accessors

:::::: TO: Will Deacon <will.deacon@arm.com>
:::::: CC: Russell King <rmk+kernel@arm.linux.org.uk>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch hide | download patch | download mbox

diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 530d7dc..4fba167 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -33,8 +33,9 @@ 
 
 #define PWM_CMR			0x0
 /* Bit field in CMR */
-#define PWM_CMR_CPOL		(1 << 9)
-#define PWM_CMR_UPD_CDTY	(1 << 10)
+#define PWM_CMR_CPOL		BIT(9)
+#define PWM_CMR_UPD_CDTY	BIT(10)
+#define PWM_CMR_DTE		BIT(16)
 #define PWM_CMR_CPRE_MSK	0xF
 
 /* The following registers for PWM v1 */
@@ -47,6 +48,7 @@ 
 #define PWMV2_CDTYUPD		0x08
 #define PWMV2_CPRD		0x0C
 #define PWMV2_CPRDUPD		0x10
+#define PWMV2_DT		0x18
 
 /*
  * Max value for duty and period
@@ -63,6 +65,7 @@  struct atmel_pwm_registers {
 	u8 period_upd;
 	u8 duty;
 	u8 duty_upd;
+	u8 dt;
 };
 
 struct atmel_pwm_chip {
@@ -161,6 +164,32 @@  static void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm,
 			    atmel_pwm->regs->duty_upd, cdty);
 }
 
+static int atmel_pwm_calculate_deadtime(struct pwm_chip *chip,
+					struct pwm_state *state,
+					unsigned long cprd, unsigned long *dt)
+{
+	unsigned long long cycles;
+
+	if (state->deadtime_fe > state->duty_cycle ||
+	    state->deadtime_re > state->period - state->duty_cycle)
+		return -EINVAL;
+
+	*dt = 0;
+	if (state->deadtime_fe) {
+		cycles = (unsigned long long)state->deadtime_fe * cprd;
+		do_div(cycles, state->period);
+		*dt = (cycles << 16);
+	}
+
+	if (state->deadtime_re) {
+		cycles = (unsigned long long)state->deadtime_re * cprd;
+		do_div(cycles, state->period);
+		*dt |= cycles;
+	}
+
+	return 0;
+}
+
 static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip,
 				    struct pwm_device *pwm,
 				    unsigned long cprd, unsigned long cdty)
@@ -214,7 +243,7 @@  static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 {
 	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 	struct pwm_state cstate;
-	unsigned long cprd, cdty;
+	unsigned long cprd, cdty, dt;
 	u32 pres, val;
 	int ret;
 
@@ -223,7 +252,9 @@  static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (state->enabled) {
 		if (cstate.enabled &&
 		    cstate.polarity == state->polarity &&
-		    cstate.period == state->period) {
+		    cstate.period == state->period &&
+		    cstate.deadtime_re == state->deadtime_re &&
+		    cstate.deadtime_fe == state->deadtime_fe) {
 			cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
 						  atmel_pwm->regs->period);
 			atmel_pwm_calculate_cdty(state, cprd, &cdty);
@@ -239,6 +270,16 @@  static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			return ret;
 		}
 
+		if (atmel_pwm->regs->dt) {
+			ret = atmel_pwm_calculate_deadtime(chip, state, cprd,
+							   &dt);
+			if (ret) {
+				dev_err(chip->dev,
+					"failed to calculate dead-time\n");
+				return ret;
+			}
+		}
+
 		atmel_pwm_calculate_cdty(state, cprd, &cdty);
 
 		if (cstate.enabled) {
@@ -258,8 +299,19 @@  static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			val &= ~PWM_CMR_CPOL;
 		else
 			val |= PWM_CMR_CPOL;
+
+		if (atmel_pwm->regs->dt) {
+			if (dt)
+				val |= PWM_CMR_DTE;
+			else
+				val &= ~PWM_CMR_DTE;
+		}
+
 		atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
 		atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty);
+		if (atmel_pwm->regs->dt)
+			atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
+					    atmel_pwm->regs->dt, dt);
 		mutex_lock(&atmel_pwm->isr_lock);
 		atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
 		atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
@@ -282,6 +334,7 @@  static const struct atmel_pwm_registers atmel_pwm_regs_v1 = {
 	.period_upd	= PWMV1_CUPD,
 	.duty		= PWMV1_CDTY,
 	.duty_upd	= PWMV1_CUPD,
+	.dt		= 0,
 };
 
 static const struct atmel_pwm_registers atmel_pwm_regs_v2 = {
@@ -289,6 +342,7 @@  static const struct atmel_pwm_registers atmel_pwm_regs_v2 = {
 	.period_upd	= PWMV2_CPRDUPD,
 	.duty		= PWMV2_CDTY,
 	.duty_upd	= PWMV2_CDTYUPD,
+	.dt		= PWMV2_DT,
 };
 
 static const struct platform_device_id atmel_pwm_devtypes[] = {