diff options
Diffstat (limited to 'drivers/pwm/pwm-tiehrpwm.c')
-rw-r--r-- | drivers/pwm/pwm-tiehrpwm.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index b1996bcd5b78..d3c1dff0a0dc 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c | |||
@@ -81,6 +81,15 @@ | |||
81 | #define AQCTL_ZRO_FRCHIGH BIT(1) | 81 | #define AQCTL_ZRO_FRCHIGH BIT(1) |
82 | #define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) | 82 | #define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) |
83 | 83 | ||
84 | #define AQCTL_CHANA_POLNORMAL (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \ | ||
85 | AQCTL_ZRO_FRCHIGH) | ||
86 | #define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \ | ||
87 | AQCTL_ZRO_FRCLOW) | ||
88 | #define AQCTL_CHANB_POLNORMAL (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \ | ||
89 | AQCTL_ZRO_FRCHIGH) | ||
90 | #define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \ | ||
91 | AQCTL_ZRO_FRCLOW) | ||
92 | |||
84 | #define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) | 93 | #define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) |
85 | #define AQSFRC_RLDCSF_ZRO 0 | 94 | #define AQSFRC_RLDCSF_ZRO 0 |
86 | #define AQSFRC_RLDCSF_PRD BIT(6) | 95 | #define AQSFRC_RLDCSF_PRD BIT(6) |
@@ -105,6 +114,7 @@ struct ehrpwm_pwm_chip { | |||
105 | unsigned int clk_rate; | 114 | unsigned int clk_rate; |
106 | void __iomem *mmio_base; | 115 | void __iomem *mmio_base; |
107 | unsigned long period_cycles[NUM_PWM_CHANNEL]; | 116 | unsigned long period_cycles[NUM_PWM_CHANNEL]; |
117 | enum pwm_polarity polarity[NUM_PWM_CHANNEL]; | ||
108 | }; | 118 | }; |
109 | 119 | ||
110 | static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) | 120 | static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) |
@@ -165,39 +175,37 @@ static int set_prescale_div(unsigned long rqst_prescaler, | |||
165 | return 1; | 175 | return 1; |
166 | } | 176 | } |
167 | 177 | ||
168 | static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, | 178 | static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan) |
169 | unsigned long duty_cycles) | ||
170 | { | 179 | { |
171 | int cmp_reg, aqctl_reg; | 180 | int aqctl_reg; |
172 | unsigned short aqctl_val, aqctl_mask; | 181 | unsigned short aqctl_val, aqctl_mask; |
173 | 182 | ||
174 | /* | 183 | /* |
175 | * Channels can be configured from action qualifier module. | 184 | * Configure PWM output to HIGH/LOW level on counter |
176 | * Channel 0 configured with compare A register and for | 185 | * reaches compare register value and LOW/HIGH level |
177 | * up-counter mode. | 186 | * on counter value reaches period register value and |
178 | * Channel 1 configured with compare B register and for | 187 | * zero value on counter |
179 | * up-counter mode. | ||
180 | */ | 188 | */ |
181 | if (chan == 1) { | 189 | if (chan == 1) { |
182 | aqctl_reg = AQCTLB; | 190 | aqctl_reg = AQCTLB; |
183 | cmp_reg = CMPB; | ||
184 | /* Configure PWM Low from compare B value */ | ||
185 | aqctl_val = AQCTL_CBU_FRCLOW; | ||
186 | aqctl_mask = AQCTL_CBU_MASK; | 191 | aqctl_mask = AQCTL_CBU_MASK; |
192 | |||
193 | if (pc->polarity[chan] == PWM_POLARITY_INVERSED) | ||
194 | aqctl_val = AQCTL_CHANB_POLINVERSED; | ||
195 | else | ||
196 | aqctl_val = AQCTL_CHANB_POLNORMAL; | ||
187 | } else { | 197 | } else { |
188 | cmp_reg = CMPA; | ||
189 | aqctl_reg = AQCTLA; | 198 | aqctl_reg = AQCTLA; |
190 | /* Configure PWM Low from compare A value*/ | ||
191 | aqctl_val = AQCTL_CAU_FRCLOW; | ||
192 | aqctl_mask = AQCTL_CAU_MASK; | 199 | aqctl_mask = AQCTL_CAU_MASK; |
200 | |||
201 | if (pc->polarity[chan] == PWM_POLARITY_INVERSED) | ||
202 | aqctl_val = AQCTL_CHANA_POLINVERSED; | ||
203 | else | ||
204 | aqctl_val = AQCTL_CHANA_POLNORMAL; | ||
193 | } | 205 | } |
194 | 206 | ||
195 | /* Configure PWM High from period value and zero value */ | ||
196 | aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH; | ||
197 | aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; | 207 | aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; |
198 | ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); | 208 | ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); |
199 | |||
200 | ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); | ||
201 | } | 209 | } |
202 | 210 | ||
203 | /* | 211 | /* |
@@ -211,9 +219,9 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
211 | unsigned long long c; | 219 | unsigned long long c; |
212 | unsigned long period_cycles, duty_cycles; | 220 | unsigned long period_cycles, duty_cycles; |
213 | unsigned short ps_divval, tb_divval; | 221 | unsigned short ps_divval, tb_divval; |
214 | int i; | 222 | int i, cmp_reg; |
215 | 223 | ||
216 | if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) | 224 | if (period_ns > NSEC_PER_SEC) |
217 | return -ERANGE; | 225 | return -ERANGE; |
218 | 226 | ||
219 | c = pc->clk_rate; | 227 | c = pc->clk_rate; |
@@ -278,12 +286,29 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
278 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, | 286 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, |
279 | TBCTL_CTRMODE_UP); | 287 | TBCTL_CTRMODE_UP); |
280 | 288 | ||
281 | /* Configure the channel for duty cycle */ | 289 | if (pwm->hwpwm == 1) |
282 | configure_chans(pc, pwm->hwpwm, duty_cycles); | 290 | /* Channel 1 configured with compare B register */ |
291 | cmp_reg = CMPB; | ||
292 | else | ||
293 | /* Channel 0 configured with compare A register */ | ||
294 | cmp_reg = CMPA; | ||
295 | |||
296 | ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); | ||
297 | |||
283 | pm_runtime_put_sync(chip->dev); | 298 | pm_runtime_put_sync(chip->dev); |
284 | return 0; | 299 | return 0; |
285 | } | 300 | } |
286 | 301 | ||
302 | static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip, | ||
303 | struct pwm_device *pwm, enum pwm_polarity polarity) | ||
304 | { | ||
305 | struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); | ||
306 | |||
307 | /* Configuration of polarity in hardware delayed, do at enable */ | ||
308 | pc->polarity[pwm->hwpwm] = polarity; | ||
309 | return 0; | ||
310 | } | ||
311 | |||
287 | static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 312 | static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
288 | { | 313 | { |
289 | struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); | 314 | struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); |
@@ -307,6 +332,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
307 | 332 | ||
308 | ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); | 333 | ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); |
309 | 334 | ||
335 | /* Channels polarity can be configured from action qualifier module */ | ||
336 | configure_polarity(pc, pwm->hwpwm); | ||
337 | |||
310 | /* Enable time counter for free_run */ | 338 | /* Enable time counter for free_run */ |
311 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); | 339 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); |
312 | return 0; | 340 | return 0; |
@@ -358,6 +386,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | |||
358 | static const struct pwm_ops ehrpwm_pwm_ops = { | 386 | static const struct pwm_ops ehrpwm_pwm_ops = { |
359 | .free = ehrpwm_pwm_free, | 387 | .free = ehrpwm_pwm_free, |
360 | .config = ehrpwm_pwm_config, | 388 | .config = ehrpwm_pwm_config, |
389 | .set_polarity = ehrpwm_pwm_set_polarity, | ||
361 | .enable = ehrpwm_pwm_enable, | 390 | .enable = ehrpwm_pwm_enable, |
362 | .disable = ehrpwm_pwm_disable, | 391 | .disable = ehrpwm_pwm_disable, |
363 | .owner = THIS_MODULE, | 392 | .owner = THIS_MODULE, |