summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParth Malkan <parthmalkan@google.com>2022-04-27 16:15:38 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-29 00:14:28 +0000
commita570c080fbb8729176f09c42b3c8fd5abee84b24 (patch)
treeac727575c38a0722244dcc698d7934cd959cc664
parent16e2c38adce1cc009d558da75b581275ecc2a9f3 (diff)
downloadchrome-ec-a570c080fbb8729176f09c42b3c8fd5abee84b24.tar.gz
zephyr: LED: Enable multi LED support
Enable variants with multiple LEDs (power LEDs, dual port battery LEDs) to define policy using devicetree and use common LED driver for execution. BUG=b:227528898 TEST=zmake build lazor, configured blue and amber LEDs of Lazor as left and right and tested dual port battery LED behavior. crrev.com/c/3612713 BRANCH=none Cq-Depend: chromium:3609114, chromium:3609113, chromium:3609112 Signed-off-by: Parth Malkan <parthmalkan@google.com> Change-Id: I52d69a6e6c30cf5a8f99fff623fe342e0aba3863 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3612219 Reviewed-by: Wai-Hong Tam <waihong@google.com>
-rw-r--r--zephyr/shim/src/led_driver/led.c75
-rw-r--r--zephyr/shim/src/led_driver/led.h24
-rw-r--r--zephyr/shim/src/led_driver/led_gpio.c14
-rw-r--r--zephyr/shim/src/led_driver/led_pwm.c16
4 files changed, 88 insertions, 41 deletions
diff --git a/zephyr/shim/src/led_driver/led.c b/zephyr/shim/src/led_driver/led.c
index b72fd8cb3e..b48641bc8f 100644
--- a/zephyr/shim/src/led_driver/led.c
+++ b/zephyr/shim/src/led_driver/led.c
@@ -27,7 +27,8 @@ LOG_MODULE_REGISTER(gpio_led, LOG_LEVEL_ERR);
#define LED_COLOR_NODE DT_PATH(led_colors)
struct led_color_node_t {
- int led_color;
+ enum led_color color;
+ enum ec_led_id led_id;
int acc_period;
};
@@ -58,6 +59,7 @@ struct node_prop_t {
enum charge_state pwr_state;
enum power_state chipset_state;
enum led_extra_flag_t led_extra_flag;
+ int charge_port;
struct led_color_node_t led_colors[MAX_COLOR];
};
@@ -85,8 +87,10 @@ struct node_prop_t {
#define LED_COLOR_INIT(color_num, color_num_plus_one, state_id) \
{ \
- .led_color = GET_PROP(DT_CHILD(state_id, color_##color_num), \
+ .color = GET_PROP(DT_CHILD(state_id, color_##color_num), \
led_color), \
+ .led_id = GET_PROP_NVE(DT_CHILD(state_id, color_##color_num), \
+ led_id), \
.acc_period = ACC_PERIOD(color_num_plus_one, state_id) \
}
@@ -97,6 +101,9 @@ struct node_prop_t {
{ \
.pwr_state = GET_PROP(state_id, charge_state), \
.chipset_state = GET_PROP(state_id, chipset_state), \
+ .charge_port = COND_CODE_1( \
+ DT_NODE_HAS_PROP(state_id, charge_port), \
+ (DT_PROP(state_id, charge_port)), (-1)), \
.led_extra_flag = GET_PROP(state_id, extra_flag), \
.led_colors = {LED_COLOR_INIT(0, 1, state_id), \
LED_COLOR_INIT(1, 2, state_id), \
@@ -169,28 +176,52 @@ static bool find_node_with_extra_flag(int i)
}
#define GET_PERIOD(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].acc_period
-#define GET_COLOR(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].led_color
+#define GET_COLOR(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].color
+#define GET_ID(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].led_id
static void set_color(int node_idx, uint32_t ticks)
{
int color_idx = 0;
- /* If period value at index 0 is not 0, it's a blinking LED */
- if (GET_PERIOD(node_idx, 0) != 0) {
+ /* If accumulated period value is not 0, it's a blinking LED */
+ if (GET_PERIOD(node_idx, MAX_COLOR - 1) != 0) {
/* Period is accumulated at the last index */
ticks = ticks % GET_PERIOD(node_idx, MAX_COLOR - 1);
+ }
- for (color_idx = 0; color_idx < MAX_COLOR; color_idx++) {
- /*
- * Period value that we use here is in terms of number
- * of ticks stored during initialization of the struct
- */
- if (ticks < GET_PERIOD(node_idx, color_idx))
- break;
+ /*
+ * Period value of 0 indicates solid LED color (non-blinking)
+ * In case of dual port battery LEDs, period value of 0 is
+ * also used to turn-off non-active port LED
+ * Nodes with period value of 0 strictly need to be listed before
+ * nodes with non-zero period values as we are accumulating the
+ * period at each node.
+ *
+ * TODO: Remove the strict sequence requirement for listing the
+ * zero-period value nodes.
+ */
+ for (color_idx = 0; color_idx < MAX_COLOR; color_idx++) {
+ enum ec_led_id led_id = GET_ID(node_idx, color_idx);
+ enum led_color color = GET_COLOR(node_idx, color_idx);
+ int period = GET_PERIOD(node_idx, color_idx);
+
+ if (led_id == 0xFF)
+ break; /* No more valid color nodes, break here */
+
+ if (!led_auto_control_is_enabled(led_id))
+ break; /* Auto control is disabled */
+
+ /*
+ * Period value that we use here is in terms of number
+ * of ticks stored during initialization of the struct
+ */
+ if (period == 0)
+ led_set_color(color, led_id);
+ else if (ticks < period) {
+ led_set_color(color, led_id);
+ break;
}
}
-
- led_set_color(GET_COLOR(node_idx, color_idx));
}
static int match_node(int node_idx)
@@ -201,12 +232,19 @@ static int match_node(int node_idx)
if (node_array[node_idx].pwr_state != pwr_state)
return -1;
+
+ /* Check if this node depends on charge port */
+ if (node_array[node_idx].charge_port != -1) {
+ int port = charge_manager_get_active_charge_port();
+
+ if (node_array[node_idx].charge_port != port)
+ return -1;
+ }
}
/* Check if this node depends on chipset state */
if (node_array[node_idx].chipset_state != 0) {
- enum power_state chipset_state =
- get_chipset_state();
+ enum power_state chipset_state = get_chipset_state();
if (node_array[node_idx].chipset_state != chipset_state)
return -1;
@@ -250,8 +288,7 @@ static void board_led_set_color(void)
/* Called by hook task every HOOK_TICK_INTERVAL_MS */
static void led_tick(void)
{
- if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
- board_led_set_color();
+ board_led_set_color();
}
DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT);
@@ -273,5 +310,5 @@ void led_control(enum ec_led_id led_id, enum ec_led_state state)
led_auto_control(EC_LED_ID_BATTERY_LED, 0);
- led_set_color(color);
+ led_set_color(color, led_id);
}
diff --git a/zephyr/shim/src/led_driver/led.h b/zephyr/shim/src/led_driver/led.h
index 6a03f7ba78..f802142c18 100644
--- a/zephyr/shim/src/led_driver/led.h
+++ b/zephyr/shim/src/led_driver/led.h
@@ -13,12 +13,18 @@
#define PINS_ARRAY(id) DT_CAT(PINS_ARRAY_, id)
+/*
+ * Return string-token if the property exists, otherwise return 0
+ */
#define GET_PROP(id, prop) \
COND_CODE_1(DT_NODE_HAS_PROP(id, prop), \
(DT_STRING_UPPER_TOKEN(id, prop)), \
(0))
-#define GET_BR_COLOR(id, prop) \
+/*
+ * Return string-token if the property exists, otherwise return -1
+ */
+#define GET_PROP_NVE(id, prop) \
COND_CODE_1(DT_NODE_HAS_PROP(id, prop), \
(DT_STRING_UPPER_TOKEN(id, prop)), \
(-1))
@@ -32,13 +38,13 @@
#define PWM_LED_PINS_NODE DT_PATH(pwm_led_pins)
enum led_color {
-#if DT_NODE_EXISTS(GPIO_LED_PINS_NODE)
- DT_FOREACH_CHILD_VARGS(GPIO_LED_PINS_NODE,
- LED_ENUM_WITH_COMMA, led_color)
-#elif DT_NODE_EXISTS(PWM_LED_PINS_NODE)
- DT_FOREACH_CHILD_VARGS(PWM_LED_PINS_NODE,
- LED_ENUM_WITH_COMMA, led_color)
-#endif
+ LED_OFF,
+ LED_RED,
+ LED_GREEN,
+ LED_BLUE,
+ LED_YELLOW,
+ LED_WHITE,
+ LED_AMBER,
LED_COLOR_COUNT /* Number of colors, not a color itself */
};
@@ -47,6 +53,6 @@ enum led_color {
*
* @param color LED Color to enable
*/
-void led_set_color(enum led_color color);
+void led_set_color(enum led_color color, enum ec_led_id led_id);
#endif /* __CROS_EC_LED_H__ */
diff --git a/zephyr/shim/src/led_driver/led_gpio.c b/zephyr/shim/src/led_driver/led_gpio.c
index 80714e30ad..2395e4b510 100644
--- a/zephyr/shim/src/led_driver/led_gpio.c
+++ b/zephyr/shim/src/led_driver/led_gpio.c
@@ -69,7 +69,7 @@ DT_FOREACH_CHILD(GPIO_LED_PINS_NODE, GEN_PINS_ARRAY)
{ \
.led_color = GET_PROP(node_id, led_color), \
.led_id = GET_PROP(node_id, led_id), \
- .br_color = GET_BR_COLOR(node_id, br_color), \
+ .br_color = GET_PROP_NVE(node_id, br_color), \
.gpio_pins = PINS_ARRAY(node_id), \
.pins_count = DT_PROP_LEN(node_id, led_pins) \
},
@@ -83,15 +83,17 @@ struct led_pins_node_t pins_node[] = {
* Set all the GPIO pins defined in the node to the defined value,
* to enable the color.
*/
-void led_set_color(enum led_color color)
+void led_set_color(enum led_color color, enum ec_led_id led_id)
{
- for (int i = 0; i < LED_COLOR_COUNT; i++) {
- if (pins_node[i].led_color == color) {
+ for (int i = 0; i < ARRAY_SIZE(pins_node); i++) {
+ if ((pins_node[i].led_color == color) &&
+ (pins_node[i].led_id == led_id)) {
for (int j = 0; j < pins_node[i].pins_count; j++) {
gpio_pin_set_dt(gpio_get_dt_spec(
pins_node[i].gpio_pins[j].signal),
pins_node[i].gpio_pins[j].val);
}
+ break; /* Found the matching pin node, break here */
}
}
}
@@ -115,13 +117,13 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
if ((br_color != -1) && (brightness[br_color] != 0)) {
color_set = true;
- led_set_color(pins_node[i].led_color);
+ led_set_color(pins_node[i].led_color, led_id);
}
}
/* If no color was set, turn off the LED */
if (!color_set)
- led_set_color(LED_OFF);
+ led_set_color(LED_OFF, led_id);
return EC_SUCCESS;
}
diff --git a/zephyr/shim/src/led_driver/led_pwm.c b/zephyr/shim/src/led_driver/led_pwm.c
index a668d40c4e..81e5e78f77 100644
--- a/zephyr/shim/src/led_driver/led_pwm.c
+++ b/zephyr/shim/src/led_driver/led_pwm.c
@@ -58,7 +58,7 @@ struct led_pins_node_t {
* This value is also used calculate duty_cycle in us (pulse_us below).
* Duty cycle in perct defined in pin node is used to calculate pulse_us
* pulse_us = (period_us*duty_cycle_in_perct)/100
- * Eg. freq = 500 Hz, period_us = 1000000/500 = 2000us
+ * e.g. freq = 500 Hz, period_us = 1000000/500 = 2000us
* duty_cycle = 50 %, pulse_us = (2000*50)/100 = 1000us
*/
const uint32_t period_us =
@@ -88,7 +88,8 @@ DT_FOREACH_CHILD(PWM_LED_PINS_NODE, GEN_PINS_ARRAY)
#define SET_PIN_NODE(node_id) \
{ \
.led_color = GET_PROP(node_id, led_color), \
- .br_color = GET_BR_COLOR(node_id, br_color), \
+ .led_id = GET_PROP(node_id, led_id), \
+ .br_color = GET_PROP_NVE(node_id, br_color), \
.pwm_pins = PINS_ARRAY(node_id), \
.pins_count = DT_PROP_LEN(node_id, led_pins) \
},
@@ -103,10 +104,11 @@ struct led_pins_node_t pins_node[] = {
* to enable the color. Defined value is duty cycle in percentage
* converted to duty cycle in us (pulse_us)
*/
-void led_set_color(enum led_color color)
+void led_set_color(enum led_color color, enum ec_led_id led_id)
{
- for (int i = 0; i < LED_COLOR_COUNT; i++) {
- if (pins_node[i].led_color == color) {
+ for (int i = 0; i < ARRAY_SIZE(pins_node); i++) {
+ if ((pins_node[i].led_color == color) &&
+ (pins_node[i].led_id == led_id)) {
for (int j = 0; j < pins_node[i].pins_count; j++) {
pwm_pin_set_usec(
pins_node[i].pwm_pins[j].pwm,
@@ -139,13 +141,13 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
if ((br_color != -1) && (brightness[br_color] != 0)) {
color_set = true;
- led_set_color(pins_node[i].led_color);
+ led_set_color(pins_node[i].led_color, led_id);
}
}
/* If no color was set, turn off the LED */
if (!color_set)
- led_set_color(LED_OFF);
+ led_set_color(LED_OFF, led_id);
return EC_SUCCESS;
}