aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2014-04-15 01:45:31 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:21 -0400
commit545c7383dfba874180b394f8b00b563a6541e158 (patch)
treee9872ddf79a70abcf8a4324f37211f41b3a03dd7
parent3bdf0aba14c68bbef6a5f758c186b0065ab51a7d (diff)
ENGR00308394 pwm: i.MX: Avoid sample fifo overflow for i.MX pwm version2
The i.MX pwm version2 is embedded in several i.MX SoCs, such as i.MX27, i.MX51 and i.MX6SL. There are four 16bit sample fifos in this IP, each of which determines the duty period of a PWM waveform in one full cycle. The IP spec mentions that we should not write a fourth sample because the fifo will become full and trigger a fifo write error(FWE) which will prevent the PWM from starting once it is enabled. In order to avoid any sample fifo overflow issue, this patch does software reset to clear all the sample fifos in the very beginning of the pwm configuration function. The fifo overflow issue can be reproduced by the following commands on the i.MX6SL evk platform, assuming we use pwm2 for the debug LED which is driven by the pin HSIC_STROBE and the maximal brightness is 255. echo 0 > /sys/class/leds/user/brightness echo 0 > /sys/class/leds/user/brightness echo 0 > /sys/class/leds/user/brightness echo 0 > /sys/class/leds/user/brightness echo 255 > /sys/class/leds/user/brightness Here, FWE happens(PWMSR register reads 0x58) and the LED can not be lighten. Acked-by: Shawn Guo <shawn.guo@freescale.com> Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
-rw-r--r--drivers/pwm/pwm-imx.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 45ad14896af5..0b59694a2f01 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/delay.h>
18#include <linux/io.h> 19#include <linux/io.h>
19#include <linux/pwm.h> 20#include <linux/pwm.h>
20#include <linux/of_device.h> 21#include <linux/of_device.h>
@@ -38,8 +39,11 @@
38#define MX3_PWMCR_DBGEN (1 << 22) 39#define MX3_PWMCR_DBGEN (1 << 22)
39#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) 40#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
40#define MX3_PWMCR_CLKSRC_IPG (1 << 16) 41#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
42#define MX3_PWMCR_SWR (1 << 3)
41#define MX3_PWMCR_EN (1 << 0) 43#define MX3_PWMCR_EN (1 << 0)
42 44
45#define MX3_PWM_SWR_LOOP 5
46
43struct imx_chip { 47struct imx_chip {
44 struct clk *clk_per; 48 struct clk *clk_per;
45 struct clk *clk_ipg; 49 struct clk *clk_ipg;
@@ -103,10 +107,23 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
103 struct pwm_device *pwm, int duty_ns, int period_ns) 107 struct pwm_device *pwm, int duty_ns, int period_ns)
104{ 108{
105 struct imx_chip *imx = to_imx_chip(chip); 109 struct imx_chip *imx = to_imx_chip(chip);
110 struct device *dev = chip->dev;
106 unsigned long long c; 111 unsigned long long c;
107 unsigned long period_cycles, duty_cycles, prescale; 112 unsigned long period_cycles, duty_cycles, prescale;
113 int wait_count = 0;
108 u32 cr; 114 u32 cr;
109 115
116 /* do software reset in case fifo overflows */
117 writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
118 do {
119 usleep_range(200, 1000);
120 cr = readl(imx->mmio_base + MX3_PWMCR);
121 } while ((cr & MX3_PWMCR_SWR) &&
122 (wait_count++ < MX3_PWM_SWR_LOOP));
123
124 if (cr & MX3_PWMCR_SWR)
125 dev_warn(dev, "software reset timeout\n");
126
110 c = clk_get_rate(imx->clk_per); 127 c = clk_get_rate(imx->clk_per);
111 c = c * period_ns; 128 c = c * period_ns;
112 do_div(c, 1000000000); 129 do_div(c, 1000000000);