aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorPhilip, Avinash <avinashphilip@ti.com>2012-09-06 01:10:03 -0400
committerThierry Reding <thierry.reding@avionic-design.de>2012-09-10 11:05:53 -0400
commitdaa5629b21a1e59ed0ef9515a9e791d2f75cc5ca (patch)
tree84a99183412d95253d77cf4f6d25e7f05677a94a /drivers/pwm
parent454870a44b0687675180506b7774fb559d610675 (diff)
pwm: pwm-tiehrpwm: Add support for configuring polarity of PWM
EHRPWM hardware supports polarity configuration of PWM output. However configuration of polarity done in hardware only in .enable() to ensure PWM output present only after enabling PWM. This commit adds support for polarity configuration for EHRPWM. When being here, remove configuring of polarity during .config() and do it explicitly from .set_polarity(). Signed-off-by: Philip, Avinash <avinashphilip@ti.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c73
1 files changed, 51 insertions, 22 deletions
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index b1996bcd5b78..caf00feadc66 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,7 +219,7 @@ 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 < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
217 return -ERANGE; 225 return -ERANGE;
@@ -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,