aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-tiehrpwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-tiehrpwm.c')
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c75
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
110static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) 120static 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
168static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, 178static 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
302static 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
287static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 312static 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)
358static const struct pwm_ops ehrpwm_pwm_ops = { 386static 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,