diff options
author | Mulin Chao <mlchao@nuvoton.com> | 2019-02-14 21:19:52 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-07 20:21:58 -0800 |
commit | e5d249549b0cfc761fd81d8eb596bc05da629e1f (patch) | |
tree | 0e3eba13f3f50ff1fec3cbec6f03cd42e72621aa | |
parent | 1283fc7316d211853f7293f1dae83be44e7fb82e (diff) | |
download | chrome-ec-e5d249549b0cfc761fd81d8eb596bc05da629e1f.tar.gz |
Reland "npcx: pwm: Use DCRn greater than CTRn to present its duty cycle is zero."
This is a reland of 93d7bcea8121869520b0d02bf94f95eb261bee05 with a fix
for fan_is_stalled.
Original change's description:
> npcx: pwm: Use DCRn greater than CTRn to present its duty cycle is zero.
>
> In npcx pwm driver, it turns off pwm module directly when its duty cycle
> is set to zero. But we saw pwm signal isn't turned off by the following
> sequence:
> 1. pwm_set_raw_duty(ch, 0);
> 2. pwm_enable(ch, 1);
>
> Please notice setting zero in DCRn doesn't mean duty cycle is zero.
> (NPCX duty cycle: ( (DCRn+1) / (CTRn+1) ) x 100). Hence in step 2, we
> can observe a very low duty cycle once the driver enables pwm module.
>
> According to figure. 24 in npcx5's datasheet, setting DCRn greater than
> CTRn means that the result of 16-bits comparator is always false. It
> equals the duty cycle is zero. This CL adopts this method to present it
> and removes the dependency between pwm_enable()/ pwm_get_enabled() and
> pwm_set_raw_duty()/pwm_get_duty().
>
> In order to make sure DCRn can be greater than CTRn, we also defined
> the PWN maximum duty cycle is (0xFFFF -1) since both DCR and CTR are
> 16-bits registers.
>
> BRANCH=none
> BUG=b:123552920
> TEST=No build errors for npcx5/7 series.
>
> Test pwm console command on npcx5/7 evbs by the following sequence.
> 1. pwm_set_raw_duty(ch, 0);
> 2. pwm_enable(ch, 1);
> And no symptoms are observed. PWM_CONFIG_ACTIVE_LOW flag is tested also
> and no symptom occurred.
>
> Test fan control by faninfo & fanset console commands. Connect Sunon
> 4-pins PWM fan and evb by following steps:
> 1. Connect PWM0 to PWM pin of fan.
> 2. Connect TA1_TACH1 and 3.3 PU on Tacho pin of fan.
> 3. Connect 5V and GND pins of fan to power supply.
> No symptoms are observed.
>
> Change-Id: I92517ff0bf3e027ae191be00112cd71ec4b55a2b
> Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
> Reviewed-on: https://chromium-review.googlesource.com/1475096
> Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Bug: b:123552920
Change-Id: I4ea76c51811507ee4a35e5c0edfb70e9fb6c4c8b
Reviewed-on: https://chromium-review.googlesource.com/1506115
Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | chip/npcx/fan.c | 7 | ||||
-rw-r--r-- | chip/npcx/pwm.c | 24 | ||||
-rw-r--r-- | chip/npcx/pwm_chip.h | 3 | ||||
-rw-r--r-- | include/pwm.h | 6 |
4 files changed, 14 insertions, 26 deletions
diff --git a/chip/npcx/fan.c b/chip/npcx/fan.c index c49707592b..e6280c97db 100644 --- a/chip/npcx/fan.c +++ b/chip/npcx/fan.c @@ -519,11 +519,8 @@ enum fan_status fan_get_status(int ch) */ int fan_is_stalled(int ch) { - /* if fan is enabled but we didn't detect any tacho */ - if (fan_get_enabled(ch) && fan_status[ch].cur_state == TACHO_UNDERFLOW) - return 1; - else - return 0; + return fan_get_enabled(ch) && fan_get_duty(ch) && + fan_status[ch].cur_state == TACHO_UNDERFLOW; } /** diff --git a/chip/npcx/pwm.c b/chip/npcx/pwm.c index b5ff0da835..eb743b3db4 100644 --- a/chip/npcx/pwm.c +++ b/chip/npcx/pwm.c @@ -54,7 +54,7 @@ enum npcx_pwm_heartbeat_mode { * @param freq desired PWM frequency * @notes changed when initialization */ -void pwm_set_freq(enum pwm_channel ch, uint32_t freq) +static void pwm_set_freq(enum pwm_channel ch, uint32_t freq) { int mdl = pwm_channels[ch].channel; uint32_t clock; @@ -77,8 +77,11 @@ void pwm_set_freq(enum pwm_channel ch, uint32_t freq) /* Calculate prescaler */ pre = DIV_ROUND_UP(clock, (0xffff * freq)); - /* Calculate maximum resolution for the given freq. and prescaler */ - pwm_res[ch] = (clock / pre) / freq; + /* + * Calculate maximum resolution for the given freq. and prescaler. And + * prevent it exceed the resolution of CTR/DCR registers. + */ + pwm_res[ch] = MIN((clock / pre) / freq, NPCX_PWM_MAX_RAW_DUTY); /* Set PWM prescaler. */ NPCX_PRSC(mdl) = pre - 1; @@ -95,7 +98,6 @@ void pwm_set_freq(enum pwm_channel ch, uint32_t freq) * * @param ch operation channel * @param enabled enabled flag - * @return none */ void pwm_enable(enum pwm_channel ch, int enabled) { @@ -122,7 +124,6 @@ int pwm_get_enabled(enum pwm_channel ch) * * @param ch operation channel * @param percent duty cycle percent - * @return none */ void pwm_set_duty(enum pwm_channel ch, int percent) { @@ -135,7 +136,6 @@ void pwm_set_duty(enum pwm_channel ch, int percent) * * @param ch operation channel * @param duty cycle duty - * @return none */ void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) { @@ -154,10 +154,8 @@ void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) /* duty ranges from 0 - 0xffff, so scale down to 0 - pwm_res[ch] */ sd = DIV_ROUND_NEAREST(duty * pwm_res[ch], EC_PWM_MAX_DUTY); - /* Set the duty cycle */ - NPCX_DCR(mdl) = (uint16_t)sd; - - pwm_enable(ch, !!duty); + /* Set the duty cycle. If it is zero, set DCR > CTR */ + NPCX_DCR(mdl) = sd ? sd : NPCX_PWM_MAX_RAW_DUTY + 1; } /** @@ -183,7 +181,7 @@ uint16_t pwm_get_raw_duty(enum pwm_channel ch) int mdl = pwm_channels[ch].channel; /* Return duty */ - if (!pwm_get_enabled(ch)) + if (NPCX_DCR(mdl) > NPCX_CTR(mdl)) return 0; else /* @@ -198,7 +196,6 @@ uint16_t pwm_get_raw_duty(enum pwm_channel ch) * PWM configuration. * * @param ch operation channel - * @return none */ void pwm_config(enum pwm_channel ch) { @@ -232,9 +229,6 @@ void pwm_config(enum pwm_channel ch) /** * PWM initial. - * - * @param none - * @return none */ static void pwm_init(void) { diff --git a/chip/npcx/pwm_chip.h b/chip/npcx/pwm_chip.h index c73855916f..3a658f5d62 100644 --- a/chip/npcx/pwm_chip.h +++ b/chip/npcx/pwm_chip.h @@ -21,4 +21,7 @@ struct pwm_t { extern const struct pwm_t pwm_channels[]; void pwm_config(enum pwm_channel ch); +/* Npcx PWM maximum duty cycle value */ +#define NPCX_PWM_MAX_RAW_DUTY (UINT16_MAX - 1) + #endif /* __CROS_EC_PWM_CHIP_H */ diff --git a/include/pwm.h b/include/pwm.h index 24b89332fc..15413c537c 100644 --- a/include/pwm.h +++ b/include/pwm.h @@ -20,12 +20,6 @@ void pwm_enable(enum pwm_channel ch, int enabled); int pwm_get_enabled(enum pwm_channel ch); /** - * Set PWM channel frequency (Hz). - * PWM will be disabled until the duty is set. - */ -void pwm_set_freq(enum pwm_channel ch, uint32_t freq); - -/** * Set PWM channel duty cycle (0-65535). */ void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty); |