diff options
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r-- | drivers/pwm/pwm-imx.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index 5449d9150d40..f8b5f109c1ab 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/delay.h> | ||
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
18 | #include <linux/pwm.h> | 19 | #include <linux/pwm.h> |
19 | #include <linux/of.h> | 20 | #include <linux/of.h> |
@@ -21,24 +22,30 @@ | |||
21 | 22 | ||
22 | /* i.MX1 and i.MX21 share the same PWM function block: */ | 23 | /* i.MX1 and i.MX21 share the same PWM function block: */ |
23 | 24 | ||
24 | #define MX1_PWMC 0x00 /* PWM Control Register */ | 25 | #define MX1_PWMC 0x00 /* PWM Control Register */ |
25 | #define MX1_PWMS 0x04 /* PWM Sample Register */ | 26 | #define MX1_PWMS 0x04 /* PWM Sample Register */ |
26 | #define MX1_PWMP 0x08 /* PWM Period Register */ | 27 | #define MX1_PWMP 0x08 /* PWM Period Register */ |
27 | 28 | ||
28 | #define MX1_PWMC_EN (1 << 4) | 29 | #define MX1_PWMC_EN (1 << 4) |
29 | 30 | ||
30 | /* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ | 31 | /* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ |
31 | 32 | ||
32 | #define MX3_PWMCR 0x00 /* PWM Control Register */ | 33 | #define MX3_PWMCR 0x00 /* PWM Control Register */ |
33 | #define MX3_PWMSAR 0x0C /* PWM Sample Register */ | 34 | #define MX3_PWMSR 0x04 /* PWM Status Register */ |
34 | #define MX3_PWMPR 0x10 /* PWM Period Register */ | 35 | #define MX3_PWMSAR 0x0C /* PWM Sample Register */ |
35 | #define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4) | 36 | #define MX3_PWMPR 0x10 /* PWM Period Register */ |
36 | #define MX3_PWMCR_DOZEEN (1 << 24) | 37 | #define MX3_PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4) |
37 | #define MX3_PWMCR_WAITEN (1 << 23) | 38 | #define MX3_PWMCR_DOZEEN (1 << 24) |
39 | #define MX3_PWMCR_WAITEN (1 << 23) | ||
38 | #define MX3_PWMCR_DBGEN (1 << 22) | 40 | #define MX3_PWMCR_DBGEN (1 << 22) |
39 | #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) | 41 | #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) |
40 | #define MX3_PWMCR_CLKSRC_IPG (1 << 16) | 42 | #define MX3_PWMCR_CLKSRC_IPG (1 << 16) |
41 | #define MX3_PWMCR_EN (1 << 0) | 43 | #define MX3_PWMCR_SWR (1 << 3) |
44 | #define MX3_PWMCR_EN (1 << 0) | ||
45 | #define MX3_PWMSR_FIFOAV_4WORDS 0x4 | ||
46 | #define MX3_PWMSR_FIFOAV_MASK 0x7 | ||
47 | |||
48 | #define MX3_PWM_SWR_LOOP 5 | ||
42 | 49 | ||
43 | struct imx_chip { | 50 | struct imx_chip { |
44 | struct clk *clk_per; | 51 | struct clk *clk_per; |
@@ -103,9 +110,43 @@ static int imx_pwm_config_v2(struct pwm_chip *chip, | |||
103 | struct pwm_device *pwm, int duty_ns, int period_ns) | 110 | struct pwm_device *pwm, int duty_ns, int period_ns) |
104 | { | 111 | { |
105 | struct imx_chip *imx = to_imx_chip(chip); | 112 | struct imx_chip *imx = to_imx_chip(chip); |
113 | struct device *dev = chip->dev; | ||
106 | unsigned long long c; | 114 | unsigned long long c; |
107 | unsigned long period_cycles, duty_cycles, prescale; | 115 | unsigned long period_cycles, duty_cycles, prescale; |
108 | u32 cr; | 116 | unsigned int period_ms; |
117 | bool enable = test_bit(PWMF_ENABLED, &pwm->flags); | ||
118 | int wait_count = 0, fifoav; | ||
119 | u32 cr, sr; | ||
120 | |||
121 | /* | ||
122 | * i.MX PWMv2 has a 4-word sample FIFO. | ||
123 | * In order to avoid FIFO overflow issue, we do software reset | ||
124 | * to clear all sample FIFO if the controller is disabled or | ||
125 | * wait for a full PWM cycle to get a relinquished FIFO slot | ||
126 | * when the controller is enabled and the FIFO is fully loaded. | ||
127 | */ | ||
128 | if (enable) { | ||
129 | sr = readl(imx->mmio_base + MX3_PWMSR); | ||
130 | fifoav = sr & MX3_PWMSR_FIFOAV_MASK; | ||
131 | if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { | ||
132 | period_ms = DIV_ROUND_UP(pwm->period, NSEC_PER_MSEC); | ||
133 | msleep(period_ms); | ||
134 | |||
135 | sr = readl(imx->mmio_base + MX3_PWMSR); | ||
136 | if (fifoav == (sr & MX3_PWMSR_FIFOAV_MASK)) | ||
137 | dev_warn(dev, "there is no free FIFO slot\n"); | ||
138 | } | ||
139 | } else { | ||
140 | writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR); | ||
141 | do { | ||
142 | usleep_range(200, 1000); | ||
143 | cr = readl(imx->mmio_base + MX3_PWMCR); | ||
144 | } while ((cr & MX3_PWMCR_SWR) && | ||
145 | (wait_count++ < MX3_PWM_SWR_LOOP)); | ||
146 | |||
147 | if (cr & MX3_PWMCR_SWR) | ||
148 | dev_warn(dev, "software reset timeout\n"); | ||
149 | } | ||
109 | 150 | ||
110 | c = clk_get_rate(imx->clk_per); | 151 | c = clk_get_rate(imx->clk_per); |
111 | c = c * period_ns; | 152 | c = c * period_ns; |
@@ -135,7 +176,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip, | |||
135 | MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | | 176 | MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | |
136 | MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH; | 177 | MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH; |
137 | 178 | ||
138 | if (test_bit(PWMF_ENABLED, &pwm->flags)) | 179 | if (enable) |
139 | cr |= MX3_PWMCR_EN; | 180 | cr |= MX3_PWMCR_EN; |
140 | 181 | ||
141 | writel(cr, imx->mmio_base + MX3_PWMCR); | 182 | writel(cr, imx->mmio_base + MX3_PWMCR); |