/** * PWM configuration. * * @param ch operation channel * @return none */ void pwm_config(enum pwm_channel ch) { int mdl = pwm_channels[ch].channel; /* Disable PWM for module configuration */ pwm_enable(mdl, 0); /* Set PWM heartbeat mode is no heartbeat */ SET_FIELD(NPCX_PWMCTL(mdl), NPCX_PWMCTL_HB_DC_CTL_FIELD, NPCX_PWM_HBM_NORMAL); /* Select default CLK or LFCLK clock input to PWM module */ SET_FIELD(NPCX_PWMCTLEX(mdl), NPCX_PWMCTLEX_FCK_SEL_FIELD, NPCX_PWM_CLOCK_APB2_LFCLK); /* Set PWM polarity normal first */ CLEAR_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_INVP); /* Select PWM clock source */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_CKSEL, (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP_CLK)); /* Set PWM operation frequency */ pwm_set_freq(ch, pwm_channels[ch].freq, DUTY_CYCLE_RESOLUTION); }
/** * Set PWM enabled. * * @param ch operation channel * @param enabled enabled flag * @return none */ void pwm_enable(enum pwm_channel ch, int enabled) { /* Start or close PWM module */ if (enabled) SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_PWR); else CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_PWR); }
/** * PWM configuration. * * @param ch operation channel * @return none */ void pwm_config(enum pwm_channel ch) { pwm_init_ch = ch; /* Configure pins from GPIOs to PWM */ if (ch == PWM_CH_FAN) gpio_config_module(MODULE_PWM_FAN, 1); else gpio_config_module(MODULE_PWM_KBLIGHT, 1); /* Disable PWM for module configuration */ pwm_enable(ch, 0); /* Set PWM heartbeat mode is no heartbeat*/ NPCX_PWMCTL(pwm_channels[ch].channel) = (NPCX_PWMCTL(pwm_channels[ch].channel) &(~(((1<<2)-1)<<NPCX_PWMCTL_HB_DC_CTL))) |(NPCX_PWM_HBM_NORMAL<<NPCX_PWMCTL_HB_DC_CTL); /* Set PWM operation frequence */ pwm_freq_changed(); /* Set PWM cycle time */ NPCX_CTR(pwm_channels[ch].channel) = (pwm_channels[ch].cycle_pulses - 1); /* Set the duty cycle */ NPCX_DCR(pwm_channels[ch].channel) = 0; /* Set PWM polarity is normal*/ CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP); /* Set PWM open drain output is push-pull type*/ CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTLEX_OD_OUT); /* Select default CLK or LFCLK clock input to PWM module */ NPCX_PWMCTLEX(pwm_channels[ch].channel) = (NPCX_PWMCTLEX(pwm_channels[ch].channel) & (~(((1<<2)-1)<<NPCX_PWMCTLEX_FCK_SEL))) | (NPCX_PWM_CLOCK_APB2_LFCLK<<NPCX_PWMCTLEX_FCK_SEL); if (ch == PWM_CH_FAN) { #ifdef CONFIG_PWM_INPUT_LFCLK /* Select default LFCLK clock input to PWM module */ SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_CKSEL); #else /* Select default core clock input to PWM module */ CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_CKSEL); #endif } else { /* Select default core clock input to PWM module */ CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_CKSEL); } }
/** * Set PWM duty cycle. * * @param ch operation channel * @param percent duty cycle percent * @return none */ void pwm_set_duty(enum pwm_channel ch, int percent) { uint32_t resolution = 0; uint16_t duty_cycle = 0; CPRINTS("pwm0=%d", percent); /* Assume the fan control is active high and invert it ourselves */ if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP); else CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP); if (percent < 0) percent = 0; /* (Benson_TBD_14) if 100% make mft cannot get TCRB, * it will need to change to 99% */ else if (percent > 100) percent = 100; CPRINTS("pwm1duty=%d", percent); resolution = NPCX_CTR(pwm_channels[ch].channel) + 1; duty_cycle = percent*resolution/100; CPRINTS("freq=0x%x", pwm_channels[ch].freq); CPRINTS("resolution=%d", resolution); CPRINTS("duty_cycle=%d", duty_cycle); /* Set the duty cycle */ /* (Benson_TBD_14) Always enable the fan channel or not */ if (percent) { NPCX_DCR(pwm_channels[ch].channel) = (duty_cycle - 1); pwm_enable(ch, 1); } else { NPCX_DCR(pwm_channels[ch].channel) = 0; pwm_enable(ch, 0); } }
/** * Set PWM duty cycle. * * @param ch operation channel * @param percent duty cycle percent * @return none */ void pwm_set_duty(enum pwm_channel ch, int percent) { int mdl = pwm_channels[ch].channel; uint32_t dc_res = 0; uint16_t dc_cnt = 0; /* Checking duty value first */ if (percent < 0) percent = 0; else if (percent > 100) percent = 100; CPRINTS("pwm%d, set duty=%d", mdl, percent); /* Assume the fan control is active high and invert it ourselves */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_INVP, (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)); dc_res = NPCX_CTR(mdl) + 1; dc_cnt = (percent*dc_res)/100; CPRINTS("freq=0x%x", pwm_channels[ch].freq); CPRINTS("duty_cycle_res=%d", dc_res); CPRINTS("duty_cycle_cnt=%d", dc_cnt); /* Set the duty cycle */ if (percent > 0) { if (percent == 100) NPCX_DCR(mdl) = NPCX_CTR(mdl); else NPCX_DCR(mdl) = (dc_cnt - 1); pwm_enable(ch, 1); } else { /* Output low since DCR > CTR */ NPCX_DCR(mdl) = NPCX_CTR(mdl) + 1; pwm_enable(ch, 0); } }
/** * Check PWM enabled. * * @param ch operation channel * @return enabled or not */ int pwm_get_enabled(enum pwm_channel ch) { return IS_BIT_SET(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_PWR); }
/** * Set PWM enabled. * * @param ch operation channel * @param enabled enabled flag * @return none */ void pwm_enable(enum pwm_channel ch, int enabled) { int mdl = pwm_channels[ch].channel; /* Start or close PWM module */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_PWR, enabled); }