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-05 12:58:23 -0800
commit93d7bcea8121869520b0d02bf94f95eb261bee05 (patch)
tree0adf2218cc096497573adcd4db06a1bc09f193a0
parent5210e2f5ed1e33b158bcdb15364fcae476bb8077 (diff)
downloadchrome-ec-93d7bcea8121869520b0d02bf94f95eb261bee05.tar.gz
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>
-rw-r--r--chip/npcx/pwm.c24
-rw-r--r--chip/npcx/pwm_chip.h3
-rw-r--r--include/pwm.h6
3 files changed, 12 insertions, 21 deletions
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);