<commit_before>/* 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.
 *
 * Power and battery LED control.
 */

#include <zephyr/drivers/gpio.h>

#include "battery.h"
#include "charge_manager.h"
#include "charge_state.h"
#include "chipset.h"
#include "ec_commands.h"
#include "hooks.h"
#include "host_command.h"
#include "led.h"
#include "led_common.h"
#include "power.h"
#include "system.h"
#include "util.h"

#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(led, LOG_LEVEL_ERR);

#define LED_COLOR_NODE  DT_PATH(led_colors)

struct led_color_node_t {
	struct led_pins_node_t *pins_node;
	int acc_period;
};

enum led_extra_flag_t {
	NONE = 0,
	LED_CHFLAG_FORCE_IDLE,
	LED_CHFLAG_DEFAULT,
};

#define DECLARE_PINS_NODE(id)						\
extern struct led_pins_node_t PINS_NODE(id);

#if DT_HAS_COMPAT_STATUS_OKAY(COMPAT_PWM_LED)
DT_FOREACH_CHILD(PWM_LED_PINS_NODE, DECLARE_PINS_NODE)
#elif DT_HAS_COMPAT_STATUS_OKAY(COMPAT_GPIO_LED)
DT_FOREACH_CHILD(GPIO_LED_PINS_NODE, DECLARE_PINS_NODE)
#endif

/*
 * Currently 4 different colors are supported for blinking LED, each of which
 * can have different periods. Each period slot is the accumulation of previous
 * periods as described below. Last slot is the total accumulation which is
 * used as a dividing factor to calculate ticks to switch color
 * Eg LED_COLOR_1 1 sec, LED_COLOR_2 2 sec, LED_COLOR_3 3 sec, LED_COLOR_4 3 sec
 * period_1 = 1, period_2 = 1 + 2, period_3 = 1 + 2 + 3, period_4 =1 + 2 + 3 + 3
 * ticks -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2 and so on (ticks % 9)
 * 0 < period_1 -> LED_COLOR_1 for 1 sec
 * 1, 2 < period_2 -> LED_COLOR_2 for 2 secs
 * 3, 4, 5 < period_3 -> LED_COLOR_3 for 3 secs
 * 6, 7, 8 < period_4 -> LED_COLOR_4 for 3 secs
 */
#define MAX_COLOR	4

struct node_prop_t {
	enum charge_state pwr_state;
	enum power_state chipset_state;
	enum led_extra_flag_t led_extra_flag;
	int8_t batt_lvl[2];
	int8_t charge_port;
	struct led_color_node_t led_colors[MAX_COLOR];
};

/*
 * acc_period is the accumulated period value of all color-x children
 * led_colors[0].acc_period = period value of color-0 node
 * led_colors[1].acc_period = period value of color-0 + color-1 nodes
 * led_colors[2].acc_period = period value of color-0 + color-1 + color-2 nodes
 * and so on. If period prop or color node doesn't exist, period val is 0
 * It is stored in terms of number of ticks by dividing it with
 * HOOT_TICK_INTERVAL_MS
 */

#define PERIOD_VAL(id) COND_CODE_1(DT_NODE_HAS_PROP(id, period_ms),	\
		(DT_PROP(id, period_ms) / HOOK_TICK_INTERVAL_MS), (0))

#define LED_PERIOD(color_num, state_id)					\
	PERIOD_VAL(DT_CHILD(state_id, color_##color_num))

#define LED_PLUS_PERIOD(color_num, state_id)				\
	+ LED_PERIOD(color_num, state_id)

#define ACC_PERIOD(color_num, state_id)					\
	(0 LISTIFY(color_num, LED_PLUS_PERIOD, (), state_id))

#define PINS_NODE_ADDR(id)	DT_PHANDLE(id, led_color)
#define LED_COLOR_INIT(color_num, color_num_plus_one, state_id)		\
{									\
	.pins_node = COND_CODE_1(					\
		DT_NODE_EXISTS(DT_CHILD(state_id, color_##color_num)),	\
		(&PINS_NODE(PINS_NODE_ADDR(				\
			DT_CHILD(state_id, color_##color_num)))),	\
		(NULL)),						\
	.acc_period = ACC_PERIOD(color_num_plus_one, state_id)		\
}

/*
 * Initialize node_array struct with prop listed in dts
 */
#define SET_LED_VALUES(state_id)					\
{									\
	.pwr_state = GET_PROP(state_id, charge_state),			\
	.chipset_state = GET_PROP(state_id, chipset_state),		\
	.led_extra_flag = GET_PROP(state_id, extra_flag),		\
	.batt_lvl = COND_CODE_1(					\
			DT_NODE_HAS_PROP(state_id, batt_lvl),		\
			(DT_PROP(state_id, batt_lvl)), ({-1, -1})),	\
	.charge_port = COND_CODE_1(					\
			DT_NODE_HAS_PROP(state_id, charge_port),	\
			(DT_PROP(state_id, charge_port)), (-1)),	\
	.led_colors = {LED_COLOR_INIT(0, 1, state_id),			\
		       LED_COLOR_INIT(1, 2, state_id),			\
		       LED_COLOR_INIT(2, 3, state_id),			\
		       LED_COLOR_INIT(3, 4, state_id),			\
		      }							\
},

static const struct node_prop_t node_array[] = {
	DT_FOREACH_CHILD(LED_COLOR_NODE, SET_LED_VALUES)
};

static enum power_state get_chipset_state(void)
{
	enum power_state chipset_state = 0;

	/*
	 * Only covers subset of power states as other states don't
	 * alter LED behavior
	 */
	if (chipset_in_state(CHIPSET_STATE_ON))
		/* S0 */
		chipset_state = POWER_S0;
	else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
		/* S3 */
		chipset_state = POWER_S3;
	else if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
		/* S5 */
		chipset_state = POWER_S5;

	return chipset_state;
}

static bool find_node_with_extra_flag(int i)
{
	uint32_t chflags = charge_get_flags();
	bool found_node = false;

	switch (node_array[i].led_extra_flag) {
	case LED_CHFLAG_FORCE_IDLE:
	case LED_CHFLAG_DEFAULT:
		if (chflags & CHARGE_FLAG_FORCE_IDLE) {
			if (node_array[i].led_extra_flag ==
					LED_CHFLAG_FORCE_IDLE)
				found_node = true;
		} else {
			if (node_array[i].led_extra_flag == LED_CHFLAG_DEFAULT)
				found_node = true;
		}
		break;
	default:
		LOG_ERR("Invalid led extra flag %d",
				node_array[i].led_extra_flag);
		break;
	}

	return found_node;
}

#define GET_PERIOD(n_idx, c_idx)  node_array[n_idx].led_colors[c_idx].acc_period
#define GET_PIN_NODE(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].pins_node
<commit_msg>zephyr/shim/src/led_driver/led.c: Format with clang-format<commit_after>/* 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.
 *
 * Power and battery LED control.
 */

#include <zephyr/drivers/gpio.h>

#include "battery.h"
#include "charge_manager.h"
#include "charge_state.h"
#include "chipset.h"
#include "ec_commands.h"
#include "hooks.h"
#include "host_command.h"
#include "led.h"
#include "led_common.h"
#include "power.h"
#include "system.h"
#include "util.h"

#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(led, LOG_LEVEL_ERR);

#define LED_COLOR_NODE DT_PATH(led_colors)

struct led_color_node_t {
	struct led_pins_node_t *pins_node;
	int acc_period;
};

enum led_extra_flag_t {
	NONE = 0,
	LED_CHFLAG_FORCE_IDLE,
	LED_CHFLAG_DEFAULT,
};

#define DECLARE_PINS_NODE(id) extern struct led_pins_node_t PINS_NODE(id);

#if DT_HAS_COMPAT_STATUS_OKAY(COMPAT_PWM_LED)
DT_FOREACH_CHILD(PWM_LED_PINS_NODE, DECLARE_PINS_NODE)
#elif DT_HAS_COMPAT_STATUS_OKAY(COMPAT_GPIO_LED)
DT_FOREACH_CHILD(GPIO_LED_PINS_NODE, DECLARE_PINS_NODE)
#endif

/*
 * Currently 4 different colors are supported for blinking LED, each of which
 * can have different periods. Each period slot is the accumulation of previous
 * periods as described below. Last slot is the total accumulation which is
 * used as a dividing factor to calculate ticks to switch color
 * Eg LED_COLOR_1 1 sec, LED_COLOR_2 2 sec, LED_COLOR_3 3 sec, LED_COLOR_4 3 sec
 * period_1 = 1, period_2 = 1 + 2, period_3 = 1 + 2 + 3, period_4 =1 + 2 + 3 + 3
 * ticks -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2 and so on (ticks % 9)
 * 0 < period_1 -> LED_COLOR_1 for 1 sec
 * 1, 2 < period_2 -> LED_COLOR_2 for 2 secs
 * 3, 4, 5 < period_3 -> LED_COLOR_3 for 3 secs
 * 6, 7, 8 < period_4 -> LED_COLOR_4 for 3 secs
 */
#define MAX_COLOR 4

struct node_prop_t {
	enum charge_state pwr_state;
	enum power_state chipset_state;
	enum led_extra_flag_t led_extra_flag;
	int8_t batt_lvl[2];
	int8_t charge_port;
	struct led_color_node_t led_colors[MAX_COLOR];
};

/*
 * acc_period is the accumulated period value of all color-x children
 * led_colors[0].acc_period = period value of color-0 node
 * led_colors[1].acc_period = period value of color-0 + color-1 nodes
 * led_colors[2].acc_period = period value of color-0 + color-1 + color-2 nodes
 * and so on. If period prop or color node doesn't exist, period val is 0
 * It is stored in terms of number of ticks by dividing it with
 * HOOT_TICK_INTERVAL_MS
 */

#define PERIOD_VAL(id)                               \
	COND_CODE_1(DT_NODE_HAS_PROP(id, period_ms), \
		    (DT_PROP(id, period_ms) / HOOK_TICK_INTERVAL_MS), (0))

#define LED_PERIOD(color_num, state_id) \
	PERIOD_VAL(DT_CHILD(state_id, color_##color_num))

#define LED_PLUS_PERIOD(color_num, state_id) +LED_PERIOD(color_num, state_id)

#define ACC_PERIOD(color_num, state_id) \
	(0 LISTIFY(color_num, LED_PLUS_PERIOD, (), state_id))

#define PINS_NODE_ADDR(id) DT_PHANDLE(id, led_color)
#define LED_COLOR_INIT(color_num, color_num_plus_one, state_id)                \
	{                                                                      \
		.pins_node = COND_CODE_1(                                      \
			DT_NODE_EXISTS(DT_CHILD(state_id, color_##color_num)), \
			(&PINS_NODE(PINS_NODE_ADDR(                            \
				DT_CHILD(state_id, color_##color_num)))),      \
			(NULL)),                                               \
		.acc_period = ACC_PERIOD(color_num_plus_one, state_id)         \
	}

/*
 * Initialize node_array struct with prop listed in dts
 */
#define SET_LED_VALUES(state_id)                                              \
	{ .pwr_state = GET_PROP(state_id, charge_state),                      \
	  .chipset_state = GET_PROP(state_id, chipset_state),                 \
	  .led_extra_flag = GET_PROP(state_id, extra_flag),                   \
	  .batt_lvl = COND_CODE_1(DT_NODE_HAS_PROP(state_id, batt_lvl),       \
				  (DT_PROP(state_id, batt_lvl)),              \
				  ({ -1, -1 })),                              \
	  .charge_port = COND_CODE_1(DT_NODE_HAS_PROP(state_id, charge_port), \
				     (DT_PROP(state_id, charge_port)), (-1)), \
	  .led_colors = {                                                     \
		  LED_COLOR_INIT(0, 1, state_id),                             \
		  LED_COLOR_INIT(1, 2, state_id),                             \
		  LED_COLOR_INIT(2, 3, state_id),                             \
		  LED_COLOR_INIT(3, 4, state_id),                             \
	  } },

static const struct node_prop_t node_array[] = { DT_FOREACH_CHILD(
	LED_COLOR_NODE, SET_LED_VALUES) };

static enum power_state get_chipset_state(void)
{
	enum power_state chipset_state = 0;

	/*
	 * Only covers subset of power states as other states don't
	 * alter LED behavior
	 */
	if (chipset_in_state(CHIPSET_STATE_ON))
		/* S0 */
		chipset_state = POWER_S0;
	else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
		/* S3 */
		chipset_state = POWER_S3;
	else if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
		/* S5 */
		chipset_state = POWER_S5;

	return chipset_state;
}

static bool find_node_with_extra_flag(int i)
{
	uint32_t chflags = charge_get_flags();
	bool found_node = false;

	switch (node_array[i].led_extra_flag) {
	case LED_CHFLAG_FORCE_IDLE:
	case LED_CHFLAG_DEFAULT:
		if (chflags & CHARGE_FLAG_FORCE_IDLE) {
			if (node_array[i].led_extra_flag ==
			    LED_CHFLAG_FORCE_IDLE)
				found_node = true;
		} else {
			if (node_array[i].led_extra_flag == LED_CHFLAG_DEFAULT)
				found_node = true;
		}
		break;
	default:
		LOG_ERR("Invalid led extra flag %d",
			node_array[i].led_extra_flag);
		break;
	}

	return found_node;
}

#define GET_PERIOD(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].acc_period
#define GET_PIN_NODE(n_idx, c_idx) node_array[n_idx].led_colors[c_idx].pins_node

{'fraction_non_alphanumeric': 0.10386857445680975, 'fraction_numerical': 0.018018018018018018, 'mean_word_length': 3.495037713378325, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2469622', 'n_tokens_mistral': 4682, 'n_tokens_neox': 4347, 'n_words': 974}