aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/common/block/include/amdblocks/gpio_banks.h
blob: d5ef5d2bd370265158d6a46890f7417f6ef0dedc (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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __AMDBLOCK_GPIO_BANKS_H__
#define __AMDBLOCK_GPIO_BANKS_H__

#include <types.h>

struct soc_amd_gpio {
	uint8_t gpio;
	uint8_t function;
	uint32_t control;
	uint32_t flags;
};

struct soc_amd_event {
	uint8_t gpio;
	uint8_t event;
};

#define GPIO_MASTER_SWITCH	0xFC
#define   GPIO_MASK_STS_EN	BIT(28)
#define   GPIO_INTERRUPT_EN	BIT(30)
#define   GPIO_WAKE_EN		BIT(31)

#define GPIO_WAKE_STAT_0	0x2F0
#define GPIO_WAKE_STAT_1	0x2F4
struct gpio_wake_state {
	uint32_t control_switch;
	uint32_t wake_stat[2];
	/* Number of wake_gpio with a valid setting. */
	uint32_t num_valid_wake_gpios;
	/* GPIO index number that caused a wake. */
	uint8_t wake_gpios[16];
};

/* Fill gpio_wake_state object for future event reporting. */
void gpio_fill_wake_state(struct gpio_wake_state *state);
/* Add gpio events to the eventlog. */
void gpio_add_events(const struct gpio_wake_state *state);

#define GPIO_PIN_IN		(1 << 0)	/* for byte access */
#define GPIO_PIN_OUT		(1 << 6)	/* for byte access */

/* Pad trigger type - Level or Edge */
#define GPIO_TRIGGER_EDGE	(0 << 8)
#define GPIO_TRIGGER_LEVEL	(1 << 8)
#define GPIO_TRIGGER_MASK	(1 << 8)

/*
 * Pad polarity:
 * Level trigger - High or Low
 * Edge trigger - High (Rising), Low (Falling), Both
 */
#define GPIO_ACTIVE_HIGH	(0 << 9)
#define GPIO_ACTIVE_LOW		(1 << 9)
#define GPIO_ACTIVE_BOTH	(2 << 9)
#define GPIO_ACTIVE_MASK	(3 << 9)

/*
 * Pad trigger and polarity configuration.
 * This determines the filtering applied on the input signal at the pad.
 */
#define GPIO_TRIGGER_EDGE_HIGH		(GPIO_ACTIVE_HIGH | GPIO_TRIGGER_EDGE)
#define GPIO_TRIGGER_EDGE_LOW		(GPIO_ACTIVE_LOW | GPIO_TRIGGER_EDGE)
#define GPIO_TRIGGER_BOTH_EDGES		(GPIO_ACTIVE_BOTH | GPIO_TRIGGER_EDGE)
#define GPIO_TRIGGER_LEVEL_HIGH		(GPIO_ACTIVE_HIGH | GPIO_TRIGGER_LEVEL)
#define GPIO_TRIGGER_LEVEL_LOW		(GPIO_ACTIVE_LOW | GPIO_TRIGGER_LEVEL)

#define GPIO_INT_ENABLE_STATUS		(1 << 11)
#define GPIO_INT_ENABLE_DELIVERY	(1 << 12)
#define GPIO_INT_ENABLE_STATUS_DELIVERY	\
				(GPIO_INT_ENABLE_STATUS | GPIO_INT_ENABLE_DELIVERY)
#define GPIO_INT_ENABLE_MASK		(3 << 11)

#define GPIO_S0I3_WAKE_EN	(1 << 13)
#define GPIO_S3_WAKE_EN		(1 << 14)
#define GPIO_S4_S5_WAKE_EN	(1 << 15)

#define GPIO_PIN_STS		(1 << 16)
#define GPIO_8KPULLUP_SELECT	(1 << 19)
#define GPIO_PULLUP_ENABLE	(1 << 20)
#define GPIO_PULLDOWN_ENABLE	(1 << 21)
#define GPIO_PULL_MASK		(7 << 19)

#define GPIO_OUTPUT_SHIFT	22
#define GPIO_OUTPUT_VALUE	(1 << GPIO_OUTPUT_SHIFT)
#define GPIO_OUTPUT_ENABLE	(1 << 23)
#define GPIO_OUTPUT_MASK	(3 << GPIO_OUTPUT_SHIFT)

#define GPIO_INT_STATUS		(1 << 28)
#define GPIO_WAKE_STATUS	(1 << 29)
#define GPIO_STATUS_MASK	(3 << 28)

enum {
	GEVENT_0,
	GEVENT_1,
	GEVENT_2,
	GEVENT_3,
	GEVENT_4,
	GEVENT_5,
	GEVENT_6,
	GEVENT_7,
	GEVENT_8,
	GEVENT_9,
	GEVENT_10,
	GEVENT_11,
	GEVENT_12,
	GEVENT_13,
	GEVENT_14,
	GEVENT_15,
	GEVENT_16,
	GEVENT_17,
	GEVENT_18,
	GEVENT_19,
	GEVENT_20,
	GEVENT_21,
	GEVENT_22,
	GEVENT_23,
	GEVENT_24,
	GEVENT_25,
	GEVENT_26,
	GEVENT_27,
	GEVENT_28,
	GEVENT_29,
	GEVENT_30,
	GEVENT_31,
};

#define GPIO_OUTPUT_OUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_VALUE)
#define GPIO_OUTPUT_OUT_LOW GPIO_OUTPUT_ENABLE

#define GPIO_PULL_PULL_UP_8K (GPIO_PULLUP_ENABLE | GPIO_8KPULLUP_SELECT)
#define GPIO_PULL_PULL_UP GPIO_PULLUP_ENABLE
#define GPIO_PULL_PULL_DOWN GPIO_PULLDOWN_ENABLE
#define GPIO_PULL_PULL_NONE 0

#define AMD_GPIO_MUX_MASK			0x03

/*
 * Flags used for GPIO configuration. These provide additional information that does not go
 * directly into GPIO control register. These are stored in `flags` field in soc_amd_gpio.
 */
#define GPIO_FLAG_EVENT_TRIGGER_LEVEL	(1 << 0)
#define GPIO_FLAG_EVENT_TRIGGER_EDGE	(0 << 0)
#define GPIO_FLAG_EVENT_TRIGGER_MASK	(1 << 0)
#define GPIO_FLAG_EVENT_ACTIVE_HIGH	(1 << 1)
#define GPIO_FLAG_EVENT_ACTIVE_LOW	(0 << 1)
#define GPIO_FLAG_EVENT_ACTIVE_MASK	(1 << 1)
#define GPIO_FLAG_SCI			(1 << 2)
#define GPIO_FLAG_SMI			(1 << 3)

/* Trigger configuration for GPIO SCI/SMI events. */
#define GPIO_FLAG_EVENT_TRIGGER_LEVEL_HIGH	(GPIO_FLAG_EVENT_TRIGGER_LEVEL | \
						 GPIO_FLAG_EVENT_ACTIVE_HIGH)
#define GPIO_FLAG_EVENT_TRIGGER_LEVEL_LOW	(GPIO_FLAG_EVENT_TRIGGER_LEVEL | \
						 GPIO_FLAG_EVENT_ACTIVE_LOW)
#define GPIO_FLAG_EVENT_TRIGGER_EDGE_HIGH	(GPIO_FLAG_EVENT_TRIGGER_EDGE | \
						 GPIO_FLAG_EVENT_ACTIVE_HIGH)
#define GPIO_FLAG_EVENT_TRIGGER_EDGE_LOW	(GPIO_FLAG_EVENT_TRIGGER_EDGE | \
						 GPIO_FLAG_EVENT_ACTIVE_LOW)

static inline bool is_gpio_event_level_triggered(uint32_t flags)
{
	return (flags & GPIO_FLAG_EVENT_TRIGGER_MASK) == GPIO_FLAG_EVENT_TRIGGER_LEVEL;
}

static inline bool is_gpio_event_edge_triggered(uint32_t flags)
{
	return (flags & GPIO_FLAG_EVENT_TRIGGER_MASK) == GPIO_FLAG_EVENT_TRIGGER_EDGE;
}

static inline bool is_gpio_event_active_high(uint32_t flags)
{
	return (flags & GPIO_FLAG_EVENT_ACTIVE_MASK) == GPIO_FLAG_EVENT_ACTIVE_HIGH;
}

static inline bool is_gpio_event_active_low(uint32_t flags)
{
	return (flags & GPIO_FLAG_EVENT_ACTIVE_MASK) == GPIO_FLAG_EVENT_ACTIVE_LOW;
}

#define DEB_GLITCH_SHIFT		5
#define DEB_GLITCH_LOW			1
#define DEB_GLITCH_HIGH			2
#define DEB_GLITCH_NONE			3
#define GPIO_DEB_PRESERVE_LOW_GLITCH	(DEB_GLITCH_LOW << DEB_GLITCH_SHIFT)
#define GPIO_DEB_PRESERVE_HIGH_GLITCH	(DEB_GLITCH_HIGH << DEB_GLITCH_SHIFT)
#define GPIO_DEB_REMOVE_GLITCH		(DEB_GLITCH_NONE << DEB_GLITCH_SHIFT)

#define GPIO_TIMEBASE_61uS		0
#define GPIO_TIMEBASE_183uS		(1 << 4)
#define GPIO_TIMEBASE_15560uS		(1 << 7)
#define GPIO_TIMEBASE_62440uS		(GPIO_TIMEBASE_183uS | \
					GPIO_TIMEBASE_15560uS)
#define GPIO_DEB_DEBOUNCE_DISABLED	(0 | GPIO_TIMEBASE_61uS)
#define GPIO_DEB_60uS			(1 | GPIO_TIMEBASE_61uS)
#define GPIO_DEB_120uS			(2 | GPIO_TIMEBASE_61uS)
#define GPIO_DEB_200uS			(3 | GPIO_TIMEBASE_61uS)
#define GPIO_DEB_500uS			(8 | GPIO_TIMEBASE_61uS)
#define GPIO_DEB_1mS			(5 | GPIO_TIMEBASE_183uS)
#define GPIO_DEB_2mS			(11 | GPIO_TIMEBASE_183uS)
#define GPIO_DEB_15mS			(1 | GPIO_TIMEBASE_15560uS)
#define GPIO_DEB_50mS			(3 | GPIO_TIMEBASE_15560uS)
#define GPIO_DEB_100mS			(6 | GPIO_TIMEBASE_15560uS)
#define GPIO_DEB_200mS			(13 | GPIO_TIMEBASE_15560uS)
#define GPIO_DEB_500mS			(8 | GPIO_TIMEBASE_62440uS)

#define GPIO_DEB_MASK			0xff

#define GPIO_WAKE_S0i3			(1 << 13)
#define GPIO_WAKE_S3			(1 << 14)
#define GPIO_WAKE_S4_S5			(1 << 15)
#define GPIO_WAKE_S0i3_S4_S5		(GPIO_WAKE_S0i3 | GPIO_WAKE_S4_S5)
#define GPIO_WAKE_S3_S4_S5		(GPIO_WAKE_S3 | GPIO_WAKE_S4_S5)
#define GPIO_WAKE_MASK			(7 << 13)

/*
 * Mask used to reset bits in GPIO control register when configuring pad using `program_gpios()`
 * Bits that are preserved/untouched:
 * - Reserved bits
 * - Drive strength bits
 * - Read only bits
 */
#define PAD_CFG_MASK		(GPIO_DEB_MASK | GPIO_TRIGGER_MASK | GPIO_ACTIVE_MASK | \
				 GPIO_INT_ENABLE_MASK | GPIO_WAKE_MASK | GPIO_PULL_MASK | \
				 GPIO_OUTPUT_MASK | GPIO_STATUS_MASK)

/*
 * Several macros are available to declare programming of GPIO pins. The defined macros and
 * their parameters are:
 * PAD_NF		Define native alternate function for the pin.
 *	pin		the pin to be programmed
 *	function	the native function
 *	pull		pull up, pull down or no pull
 * PAD_GPI		The pin is a GPIO input
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 * PAD_GPO		The pin is a GPIO output
 *	pin		the pin to be programmed
 *	direction	high or low
 * PAD_INT		The pin is regular interrupt that works while booting
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 *	trigger		LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
 *	action		STATUS, DELIVER, STATUS_DELIVER
 * PAD_SCI		The pin is a SCI source
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 *	event trigger		LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH
 * PAD_SMI		The pin is a SMI source
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 *	event trigger		LEVEL_LOW, LEVEL_HIGH
 * PAD_WAKE		The pin can wake, use after PAD_INT or PAD_SCI
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 *	trigger		LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
 *	type		S0i3, S3, S4_S5 or S4_S5 combinations (S0i3_S3 invalid)
 * PAD_DEBOUNCE		The input or interrupt will be debounced
 *	pin		the pin to be programmed
 *	pull		pull up, pull down or no pull
 *	debounce_type	preserve low glitch, preserve high glitch, no glitch
 *	debounce_time	the debounce time
 */

#define PAD_CFG_STRUCT_FLAGS(__pin, __function, __control, __flags)	\
	{								\
		.gpio = __pin,						\
		.function = __function,					\
		.control = __control,					\
		.flags = __flags,					\
	}

#define PAD_CFG_STRUCT(__pin, __function, __control)	\
	PAD_CFG_STRUCT_FLAGS(__pin, __function, __control, 0)

#define PAD_PULL(__pull)		GPIO_PULL_ ## __pull
#define PAD_OUTPUT(__dir)		GPIO_OUTPUT_OUT_ ## __dir
#define PAD_TRIGGER(__trig)		GPIO_TRIGGER_ ## __trig
#define PAD_INT_ENABLE(__action)	GPIO_INT_ENABLE_ ## __action
#define PAD_FLAG_EVENT_TRIGGER(__trig)	GPIO_FLAG_EVENT_TRIGGER_ ## __trig
#define PAD_WAKE_ENABLE(__wake)		GPIO_WAKE_ ## __wake
#define PAD_DEBOUNCE_CONFIG(__deb)	GPIO_DEB_ ## __deb

/* Native function pad configuration */
#define PAD_NF(pin, func, pull)						\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_ ## func, PAD_PULL(pull))

/* General purpose input pad configuration */
#define PAD_GPI(pin, pull)							\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx, PAD_PULL(pull))

/* General purpose output pad configuration */
#define PAD_GPO(pin, direction)			\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx, PAD_OUTPUT(direction))

/* Legacy interrupt pad configuration */
#define PAD_INT(pin, pull, trigger, action)				\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx,			\
		PAD_PULL(pull) | PAD_TRIGGER(trigger) | PAD_INT_ENABLE(action))

/* SCI pad configuration */
#define PAD_SCI(pin, pull, trigger)					\
	PAD_CFG_STRUCT_FLAGS(pin, pin ## _IOMUX_GPIOxx,		\
		PAD_PULL(pull) | PAD_TRIGGER(LEVEL_HIGH),		\
		PAD_FLAG_EVENT_TRIGGER(trigger) | GPIO_FLAG_SCI)

/* SMI pad configuration */
#define PAD_SMI(pin, pull, trigger)					\
	PAD_CFG_STRUCT_FLAGS(pin, pin ## _IOMUX_GPIOxx,		\
		PAD_PULL(pull) | PAD_TRIGGER(LEVEL_HIGH),		\
		PAD_FLAG_EVENT_TRIGGER(trigger) | GPIO_FLAG_SMI)

/* WAKE pad configuration */
#define PAD_WAKE(pin, pull, trigger, type)				\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx,			\
		PAD_PULL(pull) | PAD_TRIGGER(trigger) | PAD_WAKE_ENABLE(type))

/* pin debounce configuration */
#define PAD_DEBOUNCE(pin, pull, type, time)				\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx,			\
		PAD_PULL(pull) | PAD_DEBOUNCE_CONFIG(type) | PAD_DEBOUNCE_CONFIG(time))

/* No-connect pad - configured as input with PULL_DOWN */
#define PAD_NC(pin)							\
	PAD_CFG_STRUCT(pin, pin ## _IOMUX_GPIOxx, PAD_PULL(PULL_DOWN))

typedef uint32_t gpio_t;

/*
 * gpio_configure_pads_with_override accepts as input two GPIO tables:
 * 1. Base config
 * 2. Override config
 *
 * This function configures raw pads in base config and applies override in
 * override config if any. Thus, for every GPIO_x in base config, this function
 * looks up the GPIO in override config and if it is present there, then applies
 * the configuration from override config.
 */
void gpio_configure_pads_with_override(const struct soc_amd_gpio *base_cfg,
					size_t base_num_pads,
					const struct soc_amd_gpio *override_cfg,
					size_t override_num_pads);

/* Get the address of the control register of a particular pin */
uintptr_t gpio_get_address(gpio_t gpio_num);

/**
 * @brief program a particular set of GPIO
 *
 * @param gpio_list_ptr = pointer to array of gpio configurations
 * @param size = number of entries in array
 *
 * @return none
 */
void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size);
/* Return the interrupt status and clear if set. */
int gpio_interrupt_status(gpio_t gpio);
/* Implemented by soc, provides table of available GPIO mapping to Gevents */
void soc_get_gpio_event_table(const struct soc_amd_event **table, size_t *items);
/* May be implemented by soc to handle special cases */
void soc_gpio_hook(uint8_t gpio, uint8_t mux);

#endif /* __AMDBLOCK_GPIO_BANKS_H__ */