summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajesh Kumar <rajesh3.kumar@intel.com>2022-05-18 13:11:42 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-06-01 05:06:10 +0000
commit547cc27939e1fbde183c4b9ea5b60f10a6b719e1 (patch)
treec97712d1385675b790e714c2056c6cc3eb2244c7
parente0d93f1445125cb4c2fd4042e24a0385768c3b53 (diff)
downloadchrome-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.py1
-rw-r--r--zephyr/projects/intelrvp/CMakeLists.txt3
-rw-r--r--zephyr/projects/intelrvp/adlrvp/adlrvp_npcx/pwm_leds.dts58
-rw-r--r--zephyr/projects/intelrvp/adlrvp/prj.conf2
-rw-r--r--zephyr/projects/intelrvp/led.md44
-rw-r--r--zephyr/projects/intelrvp/src/intel_rvp_led.c168
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);