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 b1996bc..d3c1dff 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -81,6 +81,15 @@ #define AQCTL_ZRO_FRCHIGH BIT(1) #define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) +#define AQCTL_CHANA_POLNORMAL (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \ + AQCTL_ZRO_FRCHIGH) +#define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \ + AQCTL_ZRO_FRCLOW) +#define AQCTL_CHANB_POLNORMAL (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \ + AQCTL_ZRO_FRCHIGH) +#define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \ + AQCTL_ZRO_FRCLOW) + #define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) #define AQSFRC_RLDCSF_ZRO 0 #define AQSFRC_RLDCSF_PRD BIT(6) @@ -105,6 +114,7 @@ struct ehrpwm_pwm_chip { unsigned int clk_rate; void __iomem *mmio_base; unsigned long period_cycles[NUM_PWM_CHANNEL]; + enum pwm_polarity polarity[NUM_PWM_CHANNEL]; }; 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, return 1; } -static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, - unsigned long duty_cycles) +static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan) { - int cmp_reg, aqctl_reg; + int aqctl_reg; unsigned short aqctl_val, aqctl_mask; /* - * Channels can be configured from action qualifier module. - * Channel 0 configured with compare A register and for - * up-counter mode. - * Channel 1 configured with compare B register and for - * up-counter mode. + * Configure PWM output to HIGH/LOW level on counter + * reaches compare register value and LOW/HIGH level + * on counter value reaches period register value and + * zero value on counter */ if (chan == 1) { aqctl_reg = AQCTLB; - cmp_reg = CMPB; - /* Configure PWM Low from compare B value */ - aqctl_val = AQCTL_CBU_FRCLOW; aqctl_mask = AQCTL_CBU_MASK; + + if (pc->polarity[chan] == PWM_POLARITY_INVERSED) + aqctl_val = AQCTL_CHANB_POLINVERSED; + else + aqctl_val = AQCTL_CHANB_POLNORMAL; } else { - cmp_reg = CMPA; aqctl_reg = AQCTLA; - /* Configure PWM Low from compare A value*/ - aqctl_val = AQCTL_CAU_FRCLOW; aqctl_mask = AQCTL_CAU_MASK; + + if (pc->polarity[chan] == PWM_POLARITY_INVERSED) + aqctl_val = AQCTL_CHANA_POLINVERSED; + else + aqctl_val = AQCTL_CHANA_POLNORMAL; } - /* Configure PWM High from period value and zero value */ - aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH; aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; - ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); - - ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); + ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); } /* @@ -211,9 +219,9 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; - int i; + int i, cmp_reg; - if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) + if (period_ns > NSEC_PER_SEC) return -ERANGE; c = pc->clk_rate; @@ -278,12 +286,29 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, TBCTL_CTRMODE_UP); - /* Configure the channel for duty cycle */ - configure_chans(pc, pwm->hwpwm, duty_cycles); + if (pwm->hwpwm == 1) + /* Channel 1 configured with compare B register */ + cmp_reg = CMPB; + else + /* Channel 0 configured with compare A register */ + cmp_reg = CMPA; + + ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); + pm_runtime_put_sync(chip->dev); return 0; } +static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip, + struct pwm_device *pwm, enum pwm_polarity polarity) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + + /* Configuration of polarity in hardware delayed, do at enable */ + pc->polarity[pwm->hwpwm] = polarity; + return 0; +} + static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { 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) ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); + /* Channels polarity can be configured from action qualifier module */ + configure_polarity(pc, pwm->hwpwm); + /* Enable time counter for free_run */ ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); return 0; @@ -358,6 +386,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) static const struct pwm_ops ehrpwm_pwm_ops = { .free = ehrpwm_pwm_free, .config = ehrpwm_pwm_config, + .set_polarity = ehrpwm_pwm_set_polarity, .enable = ehrpwm_pwm_enable, .disable = ehrpwm_pwm_disable, .owner = THIS_MODULE, |