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
|
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
* Copyright (C) 2015 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.
*/
#ifndef _SOC_GPIO_H_
#define _SOC_GPIO_H_
#include <stdint.h>
#include <stddef.h>
#include <soc/gpio_defs.h>
#include <soc/gpio_fsp.h>
/* SOC has 8 GPIO communities GPP A~G, GPD */
#define GPIO_COMMUNITY_MAX 8
typedef uint32_t gpio_t;
/* Clear GPIO SMI Status */
void gpio_clear_all_smi(void);
/* Get GPIO SMI Status */
void gpio_get_smi_status(u32 status[GPIO_COMMUNITY_MAX]);
/* Enable GPIO SMI */
void gpio_enable_all_smi(void);
/*
* Set the GPIO groups for the GPE blocks. The gpe0_route is interpreted
* as the packed configuration for GPE0_DW[2:0]:
* dw0 = gpe0_route[3:0]
* dw1 = gpe0_route[7:4]
* dw2 = gpe0_route[11:8].
*/
void gpio_route_gpe(uint16_t gpe0_route);
/* Configure the pads according to the pad_config array. */
struct pad_config;
void gpio_configure_pads(const struct pad_config *cfgs, size_t num);
#define PAD_FIELD_VAL(field_, val_) \
(((val_) & field_ ## _MASK) << field_ ## _SHIFT)
#define PAD_FIELD(field_, setting_) \
PAD_FIELD_VAL(field_, field_ ## _ ## setting_)
/*
* This encodes all the fields found within the dw0 register for each
* pad. It directly follows the register specification:
* rst - reset type when pad configuration is reset
* rxst - native function routing: raw buffer or internal buffer
* rxraw1 - drive fixed '1' for Rx buffer
* rxev - event filtering for pad value: level, edge, drive '0'
* rxgf - glitch filter enable
* rxinv - invert the internal pad state
* gpiioapic - route to IOxAPIC
* gpisci - route for SCI
* gpismi - route for SMI
* gpinmi - route for NMI
* mode - GPIO vs native function
* rxdis - disable Rx buffer
* txdis - disable Tx buffer
*/
#define _DW0_VALS(rst, rxst, rxraw1, rxev, rxgf, rxinv, gpiioapic, gpisci, \
gpismi, gpinmi, mode, rxdis, txdis) \
(PAD_FIELD(PADRSTCFG, rst) | \
PAD_FIELD(RXPADSTSEL, rxst) | \
PAD_FIELD(RXRAW1, rxraw1) | \
PAD_FIELD(RXEVCFG, rxev) | \
PAD_FIELD(PREGFRXSEL, rxgf) | \
PAD_FIELD(RXINV, rxinv) | \
PAD_FIELD(GPIROUTIOXAPIC, gpiioapic) | \
PAD_FIELD(GPIROUTSCI, gpisci) | \
PAD_FIELD(GPIROUTSMI, gpismi) | \
PAD_FIELD(GPIROUTNMI, gpinmi) | \
PAD_FIELD(PMODE, mode) | \
PAD_FIELD(GPIORXDIS, rxdis) | \
PAD_FIELD(GPIOTXDIS, txdis))
#define _PAD_CFG_ATTRS(pad_, term_, dw0_, attrs_) \
{ \
.pad = pad_, \
.attrs = PAD_FIELD(PAD_TERM, term_) | attrs_, \
.dw0 = dw0_, \
}
#define _PAD_CFG(pad_, term_, dw0_) _PAD_CFG_ATTRS(pad_, term_, dw0_, 0)
/* Native Function - No Rx buffer manipulation */
#define PAD_CFG_NF(pad_, term_, rst_, func_) \
_PAD_CFG(pad_, term_, \
_DW0_VALS(rst_, RAW, NO, LEVEL, NO, NO, NO, NO, NO, NO, func_, NO, NO))
/* General purpose output. By default no termination. */
#define PAD_CFG_GPO(pad_, val_, rst_) \
_PAD_CFG(pad_, NONE, \
_DW0_VALS(rst_, RAW, NO, LEVEL, NO, NO, NO, NO, NO, NO, GPIO, YES, NO) \
| PAD_FIELD_VAL(GPIOTXSTATE, val_))
/* General purpose input with no special IRQ routing. */
#define PAD_CFG_GPI(pad_, term_, rst_) \
_PAD_CFG(pad_, term_, \
_DW0_VALS(rst_, RAW, NO, LEVEL, NO, NO, NO, NO, NO, NO, GPIO, NO, YES))
/* General purpose input passed through to IOxAPIC. Assume APIC logic can
* handle polarity/edge/level constraints. */
#define PAD_CFG_GPI_APIC(pad_, term_, rst_) \
_PAD_CFG(pad_, term_, \
_DW0_VALS(rst_, RAW, NO, LEVEL, NO, NO, YES, NO, NO, NO, GPIO, NO, YES))
/* General purpose input routed to SCI. This assumes edge triggered events. */
#define PAD_CFG_GPI_ACPI_SCI(pad_, term_, rst_, inv_) \
_PAD_CFG_ATTRS(pad_, term_, \
_DW0_VALS(rst_, RAW, NO, EDGE, NO, inv_, \
NO, YES, NO, NO, GPIO, NO, YES), PAD_FIELD(HOSTSW, ACPI))
/* General purpose input routed to SMI. This assumes edge triggered events. */
#define PAD_CFG_GPI_ACPI_SMI(pad_, term_, rst_, inv_) \
_PAD_CFG(pad_, term_, \
_DW0_VALS(rst_, RAW, NO, EDGE, NO, inv_, \
NO, NO, YES, NO, GPIO, NO, YES), PAD_FIELD(HOSTSW, ACPI))
/*
* The 'attrs' field carries the termination in bits 13:10 to match up with
* thd DW1 pad configuration register. Additionally, other attributes can
* be applied such as the ones below. Bit allocation matters.
*/
#define HOSTSW_SHIFT 0
#define HOSTSW_MASK 1
#define HOSTSW_ACPI HOSTSW_OWN_ACPI
#define HOSTSW_GPIO HOSTSW_OWN_GPIO
struct pad_config {
uint16_t pad;
uint16_t attrs;
uint32_t dw0;
};
#endif
|