summaryrefslogtreecommitdiff
path: root/zephyr/shim/include/zephyr_gpio_signal.h
blob: 894982698701e39ea1d0c5983b94d73b56f5f67b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* Copyright 2020 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.
 */

#if !defined(__CROS_EC_GPIO_SIGNAL_H) || defined(__CROS_EC_ZEPHYR_GPIO_SIGNAL_H)
#error "This file must only be included from gpio_signal.h. Include gpio_signal.h directly."
#endif
#define __CROS_EC_ZEPHYR_GPIO_SIGNAL_H

#include <zephyr/devicetree.h>
#include <zephyr/toolchain.h>

/** @brief Returns the enum-name property as a token
 *
 * Returns the enum-name property for this node as an upper case token
 * suitable for use as a GPIO signal name.
 * The enum-name property must exist, so this macro should only
 * be called conditionally upon checking the property exists.
 */
#define GPIO_SIGNAL_NAME_FROM_ENUM(id) DT_STRING_UPPER_TOKEN(id, enum_name)

/** @brief Creates a GPIO signal name using the DTS ordinal number
 *
 * Create a GPIO signal name for a GPIO that does not contain
 * the enum-name property. The DTS ordinal number is used
 * to generate a unique name for this GPIO.
 */
#define GPIO_SIGNAL_NAME_FROM_ORD(ord) DT_CAT(GPIO_ORD_, ord)

/** @brief Generate a GPIO signal name for this id
 *
 * Depending on whether the enum-name property exists, create
 * a GPIO signal name from either the enum-name or a
 * unique name generated using the DTS ordinal.
 */
#define GPIO_SIGNAL_NAME(id)					\
	COND_CODE_1(DT_NODE_HAS_PROP(id, enum_name),		\
		(GPIO_SIGNAL_NAME_FROM_ENUM(id)),		\
		(GPIO_SIGNAL_NAME_FROM_ORD(id ## _ORD)))

#define GPIO_SIGNAL(id)		GPIO_SIGNAL_NAME(id)
#define GPIO_SIGNAL_WITH_COMMA(id) \
	GPIO_SIGNAL(id),
enum gpio_signal {
	GPIO_UNIMPLEMENTED = -1,
#if DT_NODE_EXISTS(DT_PATH(named_gpios))
	DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_SIGNAL_WITH_COMMA)
#endif
	GPIO_COUNT,
	GPIO_LIMIT = 0x0FFF,

	IOEX_SIGNAL_START = GPIO_LIMIT + 1,
	IOEX_SIGNAL_END = IOEX_SIGNAL_START,
	IOEX_LIMIT = 0x1FFF,
};
#undef GPIO_SIGNAL_WITH_COMMA

BUILD_ASSERT(GPIO_COUNT < GPIO_LIMIT);

/** @brief Converts a node identifier under named gpios to enum
 *
 * Converts the specified node identifier name, which should be nested under
 * the named_gpios node, into the correct enum gpio_signal that can be used
 * with platform/ec gpio API
 */
#define NAMED_GPIO(name) GPIO_SIGNAL(DT_PATH(named_gpios, name))

/** @brief Obtain a named gpio enum from a label and property
 *
 * Obtains a valid enum gpio_signal that can be used with platform/ec gpio API
 * from the property of a labeled node. The property has to point to a
 * named_gpios node.
 */
#define NAMED_GPIO_NODELABEL(label, prop) \
	GPIO_SIGNAL(DT_PHANDLE(DT_NODELABEL(label), prop))

/** @brief Converts a signal to a gpio_dt_spec pointer name.
 *
 * Prepend "DT_" to the the gpio_signal name to create a name that
 * can be used as a pointer to gpio_dt_spec.
 *
 * For example, given the DTS node under "named-gpios":
 *
 * gpio_ec_wp_l: ec_wp_l {
 *	gpio = <&gpioe 5 GPIO_INPUT>;
 *	enum-name = "GPIO_WP_L";
 * };
 *
 * aliases {
 *	other_name = &gpio_ec_wp_l;
 * };
 *
 * The following methods can all be used to access the GPIO:
 *
 * inp = gpio_get_level(GPIO_WP_L); // Legacy access
 * inp = gpio_pin_get_dt(DT_GPIO_LID_OPEN); // Zephyr API
 * inp = gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_ec_wp_l)); // Zephyr API
 * inp = gpio_pin_get_dt(GPIO_DT_FROM_ALIAS(other_name));
 * enum gpio_signal sig = GPIO_WP_L;
 * inp = gpio_pin_get_dt(gpio_get_dt_spec(sig)); // Zephyr API
 *
 * DT_GPIO_LID_OPEN, GPIO_DT_FROM_NODELABEL and GPIO_DT_FROM_ALIAS will
 * resolve at build time, whereas gpio_get_dt_spec() will resolve at run-time.
 */
#define GPIO_DT_NAME(signal) DT_CAT(DT_, signal)

#define GPIO_DT_FROM_NODE(id) GPIO_DT_NAME(GPIO_SIGNAL(id))

#define GPIO_DT_FROM_ALIAS(id) GPIO_DT_FROM_NODE(DT_ALIAS(id))

#define GPIO_DT_FROM_NODELABEL(label) GPIO_DT_FROM_NODE(DT_NODELABEL(label))

#if DT_NODE_EXISTS(DT_PATH(named_gpios))
/*
 * Declare the pointers that refer to the gpio_dt_spec entries
 * for each GPIO.
 */
struct gpio_dt_spec;

#define GPIO_DT_PTR_DECL(id) extern const struct gpio_dt_spec * const \
	GPIO_DT_NAME(GPIO_SIGNAL(id));

DT_FOREACH_CHILD(DT_PATH(named_gpios), GPIO_DT_PTR_DECL)

#undef GPIO_DT_PTR_DECL

#endif /* DT_NODE_EXISTS(DT_PATH(named_gpios)) */


#define IOEXPANDER_ID_EXPAND(id) ioex_chip_##id
#define IOEXPANDER_ID(id) IOEXPANDER_ID_EXPAND(id)
#define IOEXPANDER_ID_FROM_INST_WITH_COMMA(id) IOEXPANDER_ID(id),
enum ioexpander_id {
	DT_FOREACH_STATUS_OKAY(cros_ioex_chip,
		IOEXPANDER_ID_FROM_INST_WITH_COMMA)
	CONFIG_IO_EXPANDER_PORT_COUNT
};

/**
 * Obtain the gpio_dt_spec structure associated with
 * this gpio signal.
 *
 * @param signal	GPIO signal to get gpio_dt_spec for
 * @returns		gpio_dt_spec associated with signal, or 0 if invalid
 */
const struct gpio_dt_spec *gpio_get_dt_spec(enum gpio_signal signal);

#undef IOEXPANDER_ID_FROM_INST_WITH_COMMA