summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2019-02-14 21:19:52 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-07 20:21:58 -0800
commite5d249549b0cfc761fd81d8eb596bc05da629e1f (patch)
tree0e3eba13f3f50ff1fec3cbec6f03cd42e72621aa
parent1283fc7316d211853f7293f1dae83be44e7fb82e (diff)
downloadchrome-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.c7
-rw-r--r--chip/npcx/pwm.c24
-rw-r--r--chip/npcx/pwm_chip.h3
-rw-r--r--include/pwm.h6
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);