diff options
author | Parth Malkan <parthmalkan@google.com> | 2022-04-27 16:15:38 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-29 00:14:28 +0000 |
commit | a570c080fbb8729176f09c42b3c8fd5abee84b24 (patch) | |
tree | ac727575c38a0722244dcc698d7934cd959cc664 /zephyr/shim/src | |
parent | 16e2c38adce1cc009d558da75b581275ecc2a9f3 (diff) | |
download | chrome-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>
Diffstat (limited to 'zephyr/shim/src')
-rw-r--r-- | zephyr/shim/src/led_driver/led.c | 75 | ||||
-rw-r--r-- | zephyr/shim/src/led_driver/led.h | 24 | ||||
-rw-r--r-- | zephyr/shim/src/led_driver/led_gpio.c | 14 | ||||
-rw-r--r-- | zephyr/shim/src/led_driver/led_pwm.c | 16 |
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; } |