diff options
author | Rajesh Kumar <rajesh3.kumar@intel.com> | 2022-05-18 13:11:42 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-06-01 05:06:10 +0000 |
commit | 547cc27939e1fbde183c4b9ea5b60f10a6b719e1 (patch) | |
tree | c97712d1385675b790e714c2056c6cc3eb2244c7 | |
parent | e0d93f1445125cb4c2fd4042e24a0385768c3b53 (diff) | |
download | chrome-ec-547cc27939e1fbde183c4b9ea5b60f10a6b719e1.tar.gz |
Zephyr: adlrvp: Implement custom LED behavior
Implemented custom LED behavior for Intel RVP using PWM.
BUG=none
BRANCH=None
TEST=zmake build adlrvp_npcx
Observed LED behviour
Signed-off-by: Rajesh Kumar <rajesh3.kumar@intel.com>
Change-Id: Ieb391dfe0c23e7b27211f23485f2720f7ac40a73
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3654481
Reviewed-by: Sam Hurst <shurst@google.com>
Reviewed-by: Vijay P Hiremath <vijay.p.hiremath@intel.com>
-rw-r--r-- | zephyr/projects/intelrvp/BUILD.py | 1 | ||||
-rw-r--r-- | zephyr/projects/intelrvp/CMakeLists.txt | 3 | ||||
-rw-r--r-- | zephyr/projects/intelrvp/adlrvp/adlrvp_npcx/pwm_leds.dts | 58 | ||||
-rw-r--r-- | zephyr/projects/intelrvp/adlrvp/prj.conf | 2 | ||||
-rw-r--r-- | zephyr/projects/intelrvp/led.md | 44 | ||||
-rw-r--r-- | zephyr/projects/intelrvp/src/intel_rvp_led.c | 168 |
6 files changed, 274 insertions, 2 deletions
diff --git a/zephyr/projects/intelrvp/BUILD.py b/zephyr/projects/intelrvp/BUILD.py index 20fc331b46..97956b9e2d 100644 --- a/zephyr/projects/intelrvp/BUILD.py +++ b/zephyr/projects/intelrvp/BUILD.py @@ -51,6 +51,7 @@ register_intelrvp_project( here / "adlrvp/adlrvp_npcx/keyboard.dts", here / "adlrvp/adlrvp_npcx/temp_sensor.dts", here / "adlrvp/adlrvp_npcx/usbc.dts", + here / "adlrvp/adlrvp_npcx/pwm_leds.dts", ], extra_kconfig_files=[ here / "legacy_ec_pwrseq.conf", diff --git a/zephyr/projects/intelrvp/CMakeLists.txt b/zephyr/projects/intelrvp/CMakeLists.txt index 43a5877cd3..f8a76be55d 100644 --- a/zephyr/projects/intelrvp/CMakeLists.txt +++ b/zephyr/projects/intelrvp/CMakeLists.txt @@ -20,8 +20,7 @@ if(DEFINED CONFIG_BOARD_ADLRVP_NPCX) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC "${PLATFORM_EC}/baseboard/intelrvp/usb_pd_policy_mecc_1_0.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC "${PLATFORM_EC}/baseboard/intelrvp/chg_usb_pd_mecc_1_0.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC "${PLATFORM_EC}/baseboard/intelrvp/chg_usb_pd.c") - zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_COMMON "${PLATFORM_EC}/baseboard/intelrvp/led.c") - zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_COMMON "${PLATFORM_EC}/baseboard/intelrvp/led_states.c") + zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_PWM "src/intel_rvp_led.c") endif() if(DEFINED CONFIG_BOARD_MTLRVP_NPCX) diff --git a/zephyr/projects/intelrvp/adlrvp/adlrvp_npcx/pwm_leds.dts b/zephyr/projects/intelrvp/adlrvp/adlrvp_npcx/pwm_leds.dts new file mode 100644 index 0000000000..50a08a300e --- /dev/null +++ b/zephyr/projects/intelrvp/adlrvp/adlrvp_npcx/pwm_leds.dts @@ -0,0 +1,58 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/ { + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm4 0 0 PWM_POLARITY_INVERTED>; + }; + pwm_led1: pwm_led_1 { + pwms = <&pwm5 0 0 PWM_POLARITY_INVERTED>; + }; + }; + + cros-pwmleds { + compatible = "cros-ec,pwm-leds"; + + leds = <&pwm_led0 &pwm_led1>; + frequency = <4800>; + + color-map-green = <100>; + + /* brightness-range = <red green blue yellow white amber> */ + brightness-range = <0 100 0 0 0 0>; + + + #address-cells = <1>; + #size-cells = <0>; + + pwm_led_0@0 { + reg = <0>; + ec-led-name = "EC_LED_ID_BATTERY_LED"; + }; + + pwm_led_1@1 { + reg = <1>; + ec-led-name = "EC_LED_ID_POWER_LED"; + }; + }; +}; + +/* LED1 */ +&pwm4 { + status = "okay"; + clock-bus = "NPCX_CLOCK_BUS_LFCLK"; + pinctrl-0 = <&pwm4_gpb6>; + pinctrl-names = "default"; +}; + +/* LED2 */ +&pwm5 { + status = "okay"; + clock-bus = "NPCX_CLOCK_BUS_LFCLK"; + pinctrl-0 = <&pwm5_gpb7>; + pinctrl-names = "default"; +}; diff --git a/zephyr/projects/intelrvp/adlrvp/prj.conf b/zephyr/projects/intelrvp/adlrvp/prj.conf index 5b1a47ebf0..357b0bee66 100644 --- a/zephyr/projects/intelrvp/adlrvp/prj.conf +++ b/zephyr/projects/intelrvp/adlrvp/prj.conf @@ -35,6 +35,8 @@ CONFIG_PLATFORM_EC_CHARGER_RUNTIME_CONFIG=y # LED CONFIG_PLATFORM_EC_LED_COMMON=y +CONFIG_PLATFORM_EC_LED_PWM=y +CONFIG_PLATFORM_EC_LED_PWM_TASK_DISABLED=y # Temperature sensors CONFIG_PLATFORM_EC_TEMP_SENSOR=y diff --git a/zephyr/projects/intelrvp/led.md b/zephyr/projects/intelrvp/led.md new file mode 100644 index 0000000000..c36bc6b36c --- /dev/null +++ b/zephyr/projects/intelrvp/led.md @@ -0,0 +1,44 @@ +## LED behavior on Intel RVP + +There are two LEDs on RVP, they represent battery and charger status +respectively. + +LED | Description +------------|------------------------ +CHARGER_LED | Represent charger state +BATTERY_LED | Represent battery state + +LEDs on RVP emit a single color (green). Rather than just using the on and off +state of the LED, PWM is used to blink the LED to represent multiple states and +the below table represents the multiple LED states. + +LED State | Description +---------------|------------------------------ +LED_ON | Switch On using gpio/pwmduty +LED_OFF | Switch Off using gpio/pwmduty +LED_FLASH_SLOW | Flashing with 2 sec period +LED_FLASH_FAST | Flashing with 250ms period + +### LED Behavior : Charger + +CHARGER_LED is dedicated to represent Charger status and the below table +represents the LED states for the Charger. + +Charger Status | LED States +---------------------|--------------- +Charging | LED_ON +Discharging | LED_FLASH_SLOW +Charging error | LED_FLASH_FAST +No Charger Connected | LED_OFF + +### LED Behavior : Battery + +BATTERY_LED is dedicated to represent Battery status and the below table +represents the LED states for the Battery. + +Battery Status | LED States +----------------------------|--------------- +Battery Low (<10%) | LED_FLASH_FAST +Battery Normal (10% to 90%) | LED_FLASH_SLOW +Battery Full (>90%) | LED_ON +Battery Not Present | LED_OFF diff --git a/zephyr/projects/intelrvp/src/intel_rvp_led.c b/zephyr/projects/intelrvp/src/intel_rvp_led.c new file mode 100644 index 0000000000..b382dcc485 --- /dev/null +++ b/zephyr/projects/intelrvp/src/intel_rvp_led.c @@ -0,0 +1,168 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "extpower.h" +#include "hooks.h" +#include "led_common.h" +#include "led_pwm.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +/* Battery percentage thresholds to blink at different rates. */ +#define LOW_BATTERY_PERCENTAGE 10 +#define NORMAL_BATTERY_PERCENTAGE 90 + +#define LED_OFF -1 + +#define LED_PULSE_TICK (125 * MSEC) + +#define LED_FAST_PULSE_PERIOD (250 / 125) /* 250 ms */ +#define LED_SLOW_PULSE_PERIOD ((2 * MSEC) / 125) /* 2 sec */ + +struct led_pulse_data { + bool led_is_pulsing; + uint8_t led_pulse_period; + uint8_t led_tick_count; +}; + +static struct led_pulse_data rvp_led[CONFIG_LED_PWM_COUNT]; + +static void pulse_led_deferred(void); +DECLARE_DEFERRED(pulse_led_deferred); + +static void pulse_led_deferred(void) +{ + int i = 0; + bool call_deferred = false; + + for (i = 0; i < CONFIG_LED_PWM_COUNT; i++) { + if (!rvp_led[i].led_is_pulsing) { + rvp_led[i].led_tick_count = 0; + continue; + } + + /* + * LED will be in ON state first half of the pulse period + * and in OFF state in second half of the pulse period. + */ + if (rvp_led[i].led_tick_count < + (rvp_led[i].led_pulse_period >> 1)) + set_pwm_led_color(i, EC_LED_COLOR_GREEN); + else + set_pwm_led_color(i, LED_OFF); + + rvp_led[i].led_tick_count = (rvp_led[i].led_tick_count + 1) % + rvp_led[i].led_pulse_period; + call_deferred = true; + } + + if (call_deferred) + hook_call_deferred(&pulse_led_deferred_data, LED_PULSE_TICK); +} + +static void pulse_leds(enum pwm_led_id id, int period) +{ + rvp_led[id].led_pulse_period = period; + rvp_led[id].led_is_pulsing = true; + + pulse_led_deferred(); +} + +static void update_charger_led(enum pwm_led_id id) +{ + enum charge_state chg_st = charge_get_state(); + + /* + * The colors listed below are the default, but can be overridden. + * + * Fast Flash = Charging error + * Slow Flash = Discharging + * LED on = Charging + * LED off = No Charger connected + */ + if (chg_st == PWR_STATE_CHARGE || + chg_st == PWR_STATE_CHARGE_NEAR_FULL) { + /* Charging: LED ON */ + rvp_led[id].led_is_pulsing = false; + set_pwm_led_color(id, EC_LED_COLOR_GREEN); + } else if (chg_st == PWR_STATE_DISCHARGE || + chg_st == PWR_STATE_DISCHARGE_FULL) { + if (extpower_is_present()) { + /* Discharging: + * Flash slower (2 second period, 100% duty cycle) + */ + pulse_leds(id, LED_SLOW_PULSE_PERIOD); + } else { + /* No Charger connected: LED OFF */ + rvp_led[id].led_is_pulsing = false; + set_pwm_led_color(id, LED_OFF); + } + } else if (chg_st == PWR_STATE_ERROR) { + /* Charging error: + * Flash faster (250 ms period, 100% duty cycle) + */ + pulse_leds(id, LED_FAST_PULSE_PERIOD); + } else { + /* LED OFF */ + rvp_led[id].led_is_pulsing = false; + set_pwm_led_color(id, LED_OFF); + } +} + +static void update_battery_led(enum pwm_led_id id) +{ + /* + * Fast Flash = Low Battery + * Slow Flash = Normal Battery + * LED on = Full Battery + * LED off = No Battery + */ + if (battery_is_present() == BP_YES) { + int batt_percentage = charge_get_percent(); + + if (batt_percentage < LOW_BATTERY_PERCENTAGE) { + /* Low Battery: + * Flash faster (250 ms period, 100% duty cycle) + */ + pulse_leds(id, LED_FAST_PULSE_PERIOD); + } else if (batt_percentage < NORMAL_BATTERY_PERCENTAGE) { + /* Normal Battery: + * Flash slower (2 second period, 100% duty cycle) + */ + pulse_leds(id, LED_SLOW_PULSE_PERIOD); + } else { + /* Full Battery: LED ON */ + rvp_led[id].led_is_pulsing = false; + set_pwm_led_color(id, EC_LED_COLOR_GREEN); + } + } else { + /* No Battery: LED OFF */ + rvp_led[id].led_is_pulsing = false; + set_pwm_led_color(id, LED_OFF); + } +} + +static void init_rvp_leds_off(void) +{ + /* Turn off LEDs such that they are in a known state with zero duty. */ + set_pwm_led_color(PWM_LED0, LED_OFF); + set_pwm_led_color(PWM_LED1, LED_OFF); +} +DECLARE_HOOK(HOOK_INIT, init_rvp_leds_off, HOOK_PRIO_POST_PWM); + +static void update_led(void) +{ + update_battery_led(PWM_LED0); + update_charger_led(PWM_LED1); +} +DECLARE_HOOK(HOOK_SECOND, update_led, HOOK_PRIO_DEFAULT); |