summaryrefslogtreecommitdiff
path: root/include/gpio.wrap
blob: 84055d3ba36a73c7d0c33379e04e13bd2a3b63fc (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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* -*- mode:c -*-
 *
 * Copyright 2014 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @file gpio.wrap
 * @brief Include the board specific *gpio.inc* file.
 *
 * This file is included in many different contexts.
 * The macros defined outside of the file (before including)
 * determine what parts of *gpio.inc* will be emitted.
 *
 * The following macros are available:
 * - GPIO_INT
 * - GPIO
 * - IOEX_INT
 * - IOEX
 * - UNIMPLEMENTED
 * - ALTERNATE
 * - UNUSED
 *
 * @note You cannot have dependencies between these macros. For example,
 *       you cannot define GPIO_INT in terms of GPIO. All macros must be
 *       independently evaluable.
 *       This is due to the reorganization mechanism at the bottom of this file.
 *
 * @see include/gpio_list.h
 * @see common/gpio.c
 * @see include/gpio_signal.h
 */

#ifndef GPIO_PIN
#error "Your architecture must define GPIO_PIN and it did not."
#endif

#ifndef GPIO_PIN_MASK
#error "Your architecture must define GPIO_PIN_MASK and it did not."
#endif

/**
 * @def GPIO
 * @brief The GPIO macro defines a GPIO pin name and function.
 *
 * The name is used to populate the gpio_signal enum by first
 * prepending GPIO_ to the name.  It is also used to construct the
 * string name that is presented in the shell interface.  The pin
 * parameter should use PIN macro and will be expand to GPIO_PIN
 * defined on each board.  The flags parameter is passed on to the
 * gpio_info directly.
 */
#ifndef GPIO
#define GPIO(name, pin, flags)
#endif

/**
 * @def GPIO_INT
 * @brief The GPIO_INT macro defines a GPIO that has an IRQ handler.
 *
 * The IRQ handler pointers are stored as elements in the gpio_irq_handlers
 * array.
 */
#ifndef GPIO_INT
#define GPIO_INT(name, pin, flags, signal)
#endif

/**
 * @def ALTERNATE
 * @brief The ALTERNATE macro associates a GPIO with an alternate function.
 *
 * Alternate functions allow hardware peripherals access to GPIO pins.
 * Modules use gpio_config_module to enable and disable the alternate functions
 * of GPIOs assigned to that module.  So if the module parameter is MODULE_UART
 * then when the uart_init function is called the GPIO will be switched to its
 * alternate function mode.  The function parameter is chip/variant specific
 * and will usually need to be looked up in the datasheet.  The flags parameter
 * has the same meaning as in the GPIO macro above.  This macro can assign
 * multiple pins on the same port to a module, pinmasks should use PIN_MASK
 * and will be expanded as GPIO_PIN_MASK defined in each config_chip.h.
 */
#ifndef ALTERNATE
#define ALTERNATE(pinmask, function, module, flags)
#endif

/**
 * @def UNIMPLEMENTED
 * @brief The UNIMPLEMENTED macro defines a GPIO that doesn't actually exist.
 *
 * Some GPIO names are well known and used by generic code, ENTERING_RW and WP_L
 * are examples.  If a particular board doesn't have a GPIO assigned to such a
 * function/name then it should specify that that GPIO is not implemented using
 * the UNIMPLEMENTED macro below in the board gpio.inc file.  This macro creates
 * an entry in the gpio_signal enum and the gpio_list array that is initialized
 * to use the UNIMPLEMENTED_GPIO_BANK and a bitmask of zero.  The chip GPIO
 * layer is implemented such that writes to and reads from
 * UNIMPLEMENTED_GPIO_BANK with a bitmask of zero are harmless.
 *
 * This allows common code that expects these GPIOs to exist to compile and have
 * some reduced functionality.
 */
#ifndef UNIMPLEMENTED
#define UNIMPLEMENTED(name)
#endif

/**
 * @def UNUSED
 * @brief The UNUSED macro defines a pin as unused.
 *
 * This allows the chip specific code to provision these pins for
 * the lowest power state.
 * We don't want to automatically provision all unreferenced pins/ports
 * as unused, since this may alter the behavior of existing firmwares in
 * ways that may not be obvious to the developer.
 */
#ifndef UNUSED
#define UNUSED(pin)
#endif

/**
 * @def IOEX
 * @brief The IOEX macro defines an IO Expander GPIO.
 *
 * The name is used to populate enum ioex_signal by prepending "IOEX_".
 */
#ifndef IOEX
#define IOEX(name, expin, flags)
#endif

/**
 * @def IOEX_INT
 * @brief The IOEX_INT macro defines an IO Expander GPIO that has an IRQ handler.
 *
 * The IRQ handler pointers are stored as elements in the ioex_irq_handlers
 * array.
 */
#ifndef IOEX_INT
#define IOEX_INT(name, expin, flags, handler)
#endif

/*
 * RO/RW pin macro.
 *
 * Some boards may have very different pin configurations between RO and RW, and
 * also may vary from revision to revision. The RO/RW pin macros can ease the
 * maintenance effort.
 */

#ifdef SECTION_IS_RO
#define GPIO_RO(name, pin, flags) GPIO(name, pin, flags)
#define GPIO_RW(name, pin, flags)
#define GPIO_INT_RO(name, pin, flags, signal) GPIO_INT(name, pin, flags, signal)
#define GPIO_INT_RW(name, pin, flags, signal)
#define ALTERNATE_RO(pinmask, function, module, flags) \
		ALTERNATE(pinmask, function, module, flags)
#define ALTERNATE_RW(pinmask, function, module, flags)
#define UNIMPLEMENTED_RO(name) UNIMPLEMENTED(name)
#define UNIMPLEMENTED_RW(name)
#define UNUSED_RO(name) UNUSED(name)
#define UNUSED_RW(name)
#elif defined(SECTION_IS_RW)
#define GPIO_RO(name, pin, flags)
#define GPIO_RW(name, pin, flags) GPIO(name, pin, flags)
#define GPIO_INT_RO(name, pin, flags, signal)
#define GPIO_INT_RW(name, pin, flags, signal) GPIO_INT(name, pin, flags, signal)
#define ALTERNATE_RO(pinmask, function, module, flags)
#define ALTERNATE_RW(pinmask, function, module, flags) \
		ALTERNATE(pinmask, function, module, flags)
#define UNIMPLEMENTED_RO(name)
#define UNIMPLEMENTED_RW(name) UNIMPLEMENTED(name)
#define UNUSED_RO(name)
#define UNUSED_RW(name) UNUSED(name)
#else
#define GPIO_RO(name, pin, flags) GPIO(name, pin, flags)
#define GPIO_RW(name, pin, flags) GPIO(name, pin, flags)
#define GPIO_INT_RO(name, pin, flags, signal) GPIO_INT(name, pin, flags, signal)
#define GPIO_INT_RW(name, pin, flags, signal) GPIO_INT(name, pin, flags, signal)
#define ALTERNATE_RO(pinmask, function, module, flags) \
		ALTERNATE(pinmask, function, module, flags)
#define ALTERNATE_RW(pinmask, function, module, flags) \
		ALTERNATE(pinmask, function, module, flags)
#define UNIMPLEMENTED_RO(name) UNIMPLEMENTED(name)
#define UNIMPLEMENTED_RW(name) UNIMPLEMENTED(name)
#define UNUSED_RO(name) UNUSED(name)
#define UNUSED_RW(name) UNUSED(name)
#endif


/**
 * Rearrange the gpio.inc declarations, such that we have the following order:
 * - GPIO_INTs
 * - GPIOs
 * - IOEX_INTs
 * - IOEXs
 * - UNIMPLEMENTEDs
 * - ALTERNATEs
 * - UNUSEDs
 *
 * This allows the board to define these declaration in any way that is
 * makes logical sense, while maintaining the following existing
 * order invariants:
 *
 * - GPIO_INTs must be before GPIOs in gpio.inc. This is because their
 *   enum values from gpio_signal.h are used as the index to the
 *   gpio_irq_handlers table.
 *   See crrev.com/c/263973 (gpio: Refactor IRQ handler pointer out of gpio_list)
 * - IOEX_INTs must be before IOEXs in gpio.inc. This is because their
 *   enum values from gpio_signal.h are used as the index to the
 *   ioex_irq_handlers table.
 *
 * We want to rearrange the entres early in the gpio.inc process to ensure
 * that all includers (gpio_signal.h and gpio_list.h) see the same ordering,
 * since there is an implicit dependency.
 *
 * Note that this mechanism cannot handle dependencies between the provided
 * macros. See the file header comment for more information.
 */

/* Stash away all macros and define to "blank" */
#pragma push_macro("GPIO_INT")
#pragma push_macro("GPIO")
#pragma push_macro("IOEX_INT")
#pragma push_macro("IOEX")
#pragma push_macro("UNIMPLEMENTED")
#pragma push_macro("ALTERNATE")
#pragma push_macro("UNUSED")
#undef GPIO_INT
#undef GPIO
#undef IOEX_INT
#undef IOEX
#undef UNIMPLEMENTED
#undef ALTERNATE
#undef UNUSED
#define GPIO_INT(...)
#define GPIO(...)
#define IOEX_INT(...)
#define IOEX(...)
#define UNIMPLEMENTED(...)
#define ALTERNATE(...)
#define UNUSED(...)

/* Capture GPIO_INTs */
#pragma pop_macro("GPIO_INT")
#include "gpio.inc"
#undef GPIO_INT
#define GPIO_INT(...)

/* Capture GPIOs */
#pragma pop_macro("GPIO")
#include "gpio.inc"
#undef GPIO
#define GPIO(...)

/* Capture IOEX_INTs */
#pragma pop_macro("IOEX_INT")
#include "gpio.inc"
#undef IOEX_INT
#define IOEX_INT(...)

/* Capture IOEXs */
#pragma pop_macro("IOEX")
#include "gpio.inc"
#undef IOEX
#define IOEX(...)

/* Capture UNIMPLEMENTEDs */
#pragma pop_macro("UNIMPLEMENTED")
#include "gpio.inc"
#undef UNIMPLEMENTED
#define UNIMPLEMENTED(...)

/* Capture ALTERNATEs */
#pragma pop_macro("ALTERNATE")
#include "gpio.inc"
#undef ALTERNATE
#define ALTERNATE(...)

/* Capture UNUSEDs */
#pragma pop_macro("UNUSED")
#include "gpio.inc"
#undef UNUSED
#define UNUSED(...)


/*
 * Once the gpio.inc file has been included these macros are no longer needed.
 * This allows the includer to redefine these macros and include this file
 * again, within the same file.
 */
#undef GPIO
#undef GPIO_RO
#undef GPIO_RW
#undef GPIO_INT
#undef GPIO_INT_RO
#undef GPIO_INT_RW
#undef IOEX
#undef IOEX_INT
#undef ALTERNATE
#undef ALTERNATE_RO
#undef ALTERNATE_RW
#undef UNIMPLEMENTED
#undef UNIMPLEMENTED_RO
#undef UNIMPLEMENTED_RW
#undef UNUSED
#undef UNUSED_RO
#undef UNUSED_RW