summaryrefslogtreecommitdiff
path: root/zephyr/shim/src
diff options
context:
space:
mode:
authorParth Malkan <parthmalkan@google.com>2022-04-03 08:27:09 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-05 21:28:54 +0000
commit0e81f9208fcf5384c9ac3eecced97a4b513d6d26 (patch)
tree06c4079fe71a1c4d726f2b0ae779bb5a738fa16b /zephyr/shim/src
parent30f227a029a62515051a1d41402577a9090e1e5e (diff)
downloadchrome-ec-0e81f9208fcf5384c9ac3eecced97a4b513d6d26.tar.gz
zephyr: LED: Add single PWM LED support
This patch adds single PWM LED support to the common LED layer. BUG=b:227755022, b:194430340 TEST=manual LED test on Lazor BRANCH=none Signed-off-by: Parth Malkan <parthmalkan@google.com> Cq-Depend: chromium:3564077 Change-Id: Ib5070b8afb94d4771e753394f0495fe7a6811612 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3567463 Reviewed-by: Wai-Hong Tam <waihong@google.com>
Diffstat (limited to 'zephyr/shim/src')
-rw-r--r--zephyr/shim/src/led_driver/CMakeLists.txt1
-rw-r--r--zephyr/shim/src/led_driver/led.c3
-rw-r--r--zephyr/shim/src/led_driver/led.h3
-rw-r--r--zephyr/shim/src/led_driver/led_gpio.c3
-rw-r--r--zephyr/shim/src/led_driver/led_pwm.c102
5 files changed, 111 insertions, 1 deletions
diff --git a/zephyr/shim/src/led_driver/CMakeLists.txt b/zephyr/shim/src/led_driver/CMakeLists.txt
index 20c49cce6c..7c21d6827e 100644
--- a/zephyr/shim/src/led_driver/CMakeLists.txt
+++ b/zephyr/shim/src/led_driver/CMakeLists.txt
@@ -4,3 +4,4 @@
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_DT led.c)
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_DT led_gpio.c)
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_LED_DT led_pwm.c)
diff --git a/zephyr/shim/src/led_driver/led.c b/zephyr/shim/src/led_driver/led.c
index 5adbffaa23..1e97c98a86 100644
--- a/zephyr/shim/src/led_driver/led.c
+++ b/zephyr/shim/src/led_driver/led.c
@@ -245,7 +245,8 @@ static int find_color(int node_idx, int ticks)
/* If period value at index 0 is not 0, it's a blinking LED */
if (GET_PERIOD(node_idx, 0) != 0) {
/* Period is accumulated at the last index */
- ticks = ticks % GET_PERIOD(node_idx, MAX_COLOR - 1);
+ ticks = (ticks * LED_ONE_SEC) %
+ GET_PERIOD(node_idx, MAX_COLOR - 1);
for (color_idx = 0; color_idx < MAX_COLOR; color_idx++) {
if (ticks < GET_PERIOD(node_idx, color_idx))
diff --git a/zephyr/shim/src/led_driver/led.h b/zephyr/shim/src/led_driver/led.h
index 5eadb61680..4354df5125 100644
--- a/zephyr/shim/src/led_driver/led.h
+++ b/zephyr/shim/src/led_driver/led.h
@@ -6,6 +6,9 @@
#ifndef __CROS_EC_LED_H__
#define __CROS_EC_LED_H__
+#define COMPAT_GPIO_LED cros_ec_gpio_led_pins
+#define COMPAT_PWM_LED cros_ec_pwm_led_pins
+
#define GET_PROP(id, prop) \
COND_CODE_1(DT_NODE_HAS_PROP(id, prop), \
(DT_STRING_UPPER_TOKEN(id, prop)), \
diff --git a/zephyr/shim/src/led_driver/led_gpio.c b/zephyr/shim/src/led_driver/led_gpio.c
index cdc465eafb..46d94db4dc 100644
--- a/zephyr/shim/src/led_driver/led_gpio.c
+++ b/zephyr/shim/src/led_driver/led_gpio.c
@@ -12,6 +12,8 @@
#include <drivers/gpio.h>
#include <logging/log.h>
+#if DT_HAS_COMPAT_STATUS_OKAY(COMPAT_GPIO_LED)
+
LOG_MODULE_REGISTER(gpio_led, LOG_LEVEL_ERR);
#define GPIO_LED_PINS_NODE DT_PATH(gpio_led_pins)
@@ -72,3 +74,4 @@ void led_set_color(enum led_color color)
}
}
}
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(COMPAT_GPIO_LED) */
diff --git a/zephyr/shim/src/led_driver/led_pwm.c b/zephyr/shim/src/led_driver/led_pwm.c
new file mode 100644
index 0000000000..57cd6eb92f
--- /dev/null
+++ b/zephyr/shim/src/led_driver/led_pwm.c
@@ -0,0 +1,102 @@
+/* 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.
+ *
+ * PWM LED control.
+ */
+
+#include "led.h"
+#include "util.h"
+
+#include <devicetree.h>
+#include <drivers/pwm.h>
+#include <logging/log.h>
+
+#if DT_HAS_COMPAT_STATUS_OKAY(COMPAT_PWM_LED)
+
+LOG_MODULE_REGISTER(pwm_led, LOG_LEVEL_ERR);
+
+#define PWM_LED_PINS_NODE DT_PATH(pwm_led_pins)
+#define LED_PIN_COUNT (LED_COLOR_COUNT - 1)
+
+/*
+ * Struct defining LED PWM pin and duty cycle to set.
+ */
+struct pwm_pin_t {
+ const struct device *pwm;
+ uint8_t channel;
+ pwm_flags_t flags;
+ uint32_t pulse_us; /* PWM Duty cycle us */
+};
+
+/*
+ * Pin node contains LED color and array of PWM channels
+ * to alter in order to enable the given color.
+ */
+struct led_pins_node_t {
+ int led_color;
+ struct pwm_pin_t pwm_pins[LED_PIN_COUNT];
+};
+
+/*
+ * Period in us from frequency(Hz) defined in pins node
+ * period in sec = 1/freq
+ * period in usec = (1*usec_per_sec)/freq
+ * 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
+ * duty_cycle = 50 %, pulse_us = (2000*50)/100 = 1000us
+ */
+const uint32_t period_us =
+ (USEC_PER_SEC / DT_PROP(PWM_LED_PINS_NODE, pwm_frequency));
+
+#define SET_PIN(node_id, prop, i) \
+{ \
+ .pwm = DEVICE_DT_GET( \
+ DT_PWMS_CTLR(DT_PHANDLE_BY_IDX(node_id, prop, i))), \
+ .channel = DT_PWMS_CHANNEL( \
+ DT_PHANDLE_BY_IDX(node_id, prop, i)), \
+ .flags = DT_PWMS_FLAGS(DT_PHANDLE_BY_IDX(node_id, prop, i)), \
+ .pulse_us = DIV_ROUND_NEAREST( \
+ period_us * DT_PHA_BY_IDX(node_id, prop, i, value), 100), \
+},
+
+#define SET_PWM_PIN(node_id) \
+{ \
+ DT_FOREACH_PROP_ELEM(node_id, led_pins, SET_PIN) \
+}
+
+#define SET_PIN_NODE(node_id) \
+{ \
+ .led_color = GET_PROP(node_id, led_color), \
+ .pwm_pins = SET_PWM_PIN(node_id) \
+},
+
+struct led_pins_node_t pins_node[LED_COLOR_COUNT] = {
+ DT_FOREACH_CHILD(PWM_LED_PINS_NODE, SET_PIN_NODE)
+};
+
+/*
+ * Iterate through LED pins nodes to find the color matching node.
+ * Set all the PWM channels defined in the node to the defined value,
+ * 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)
+{
+ for (int i = 0; i < LED_COLOR_COUNT; i++) {
+ if (pins_node[i].led_color == color) {
+ for (int j = 0; j < LED_PIN_COUNT; j++) {
+ pwm_pin_set_usec(
+ pins_node[i].pwm_pins[j].pwm,
+ pins_node[i].pwm_pins[j].channel,
+ period_us,
+ pins_node[i].pwm_pins[j].pulse_us,
+ pins_node[i].pwm_pins[j].flags);
+ }
+ break; /* Found the matching pin node, break here */
+ }
+ }
+}
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(COMPAT_PWM_LED) */