1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/mmio.h>
5 #include <device/pci.h>
6 #include <console/console.h>
11 /* GPIO-to-Pad LUTs */
12 static const u8 gpncore_gpio_to_pad
[GPNCORE_COUNT
] =
13 { 19, 18, 17, 20, 21, 22, 24, 25, /* [ 0: 7] */
14 23, 16, 14, 15, 12, 26, 27, 1, /* [ 8:15] */
15 4, 8, 11, 0, 3, 6, 10, 13, /* [16:23] */
16 2, 5, 9 }; /* [24:26] */
18 static const u8 gpscore_gpio_to_pad
[GPSCORE_COUNT
] =
19 { 85, 89, 93, 96, 99, 102, 98, 101, /* [ 0: 7] */
20 34, 37, 36, 38, 39, 35, 40, 84, /* [ 8: 15] */
21 62, 61, 64, 59, 54, 56, 60, 55, /* [16: 23] */
22 63, 57, 51, 50, 53, 47, 52, 49, /* [24: 31] */
23 48, 43, 46, 41, 45, 42, 58, 44, /* [32: 39] */
24 95, 105, 70, 68, 67, 66, 69, 71, /* [40: 47] */
25 65, 72, 86, 90, 88, 92, 103, 77, /* [48: 55] */
26 79, 83, 78, 81, 80, 82, 13, 12, /* [56: 63] */
27 15, 14, 17, 18, 19, 16, 2, 1, /* [64: 71] */
28 0, 4, 6, 7, 9, 8, 33, 32, /* [72: 79] */
29 31, 30, 29, 27, 25, 28, 26, 23, /* [80: 87] */
30 21, 20, 24, 22, 5, 3, 10, 11, /* [88: 95] */
31 106, 87, 91, 104, 97, 100 }; /* [96:101] */
33 static const u8 gpssus_gpio_to_pad
[GPSSUS_COUNT
] =
34 { 29, 33, 30, 31, 32, 34, 36, 35, /* [ 0: 7] */
35 38, 37, 18, 7, 11, 20, 17, 1, /* [ 8:15] */
36 8, 10, 19, 12, 0, 2, 23, 39, /* [16:23] */
37 28, 27, 22, 21, 24, 25, 26, 51, /* [24:31] */
38 56, 54, 49, 55, 48, 57, 50, 58, /* [32:39] */
39 52, 53, 59, 40 }; /* [40:43] */
41 /* GPIO bank descriptions */
42 static const struct gpio_bank gpncore_bank
= {
43 .gpio_count
= GPNCORE_COUNT
,
44 .gpio_to_pad
= gpncore_gpio_to_pad
,
45 .legacy_base
= GP_LEGACY_BASE_NONE
,
46 .pad_base
= GPNCORE_PAD_BASE
,
48 .gpio_f1_range_start
= GPNCORE_GPIO_F1_RANGE_START
,
49 .gpio_f1_range_end
= GPNCORE_GPIO_F1_RANGE_END
,
52 static const struct gpio_bank gpscore_bank
= {
53 .gpio_count
= GPSCORE_COUNT
,
54 .gpio_to_pad
= gpscore_gpio_to_pad
,
55 .legacy_base
= GPSCORE_LEGACY_BASE
,
56 .pad_base
= GPSCORE_PAD_BASE
,
58 .gpio_f1_range_start
= GPSCORE_GPIO_F1_RANGE_START
,
59 .gpio_f1_range_end
= GPSCORE_GPIO_F1_RANGE_END
,
62 static const struct gpio_bank gpssus_bank
= {
63 .gpio_count
= GPSSUS_COUNT
,
64 .gpio_to_pad
= gpssus_gpio_to_pad
,
65 .legacy_base
= GPSSUS_LEGACY_BASE
,
66 .pad_base
= GPSSUS_PAD_BASE
,
68 .gpio_f1_range_start
= GPSSUS_GPIO_F1_RANGE_START
,
69 .gpio_f1_range_end
= GPSSUS_GPIO_F1_RANGE_END
,
72 static void setup_gpios(const struct soc_gpio_map
*gpios
,
73 const struct gpio_bank
*bank
)
75 const struct soc_gpio_map
*config
;
90 for (config
= gpios
; config
->pad_conf0
!= GPIO_LIST_END
;
92 if (gpio
> bank
->gpio_count
)
98 if (bank
->legacy_base
!= GP_LEGACY_BASE_NONE
) {
99 /* Legacy IO configuration */
100 use_sel
[set
] |= config
->use_sel
<< bit
;
101 io_sel
[set
] |= config
->io_sel
<< bit
;
102 gp_lvl
[set
] |= config
->gp_lvl
<< bit
;
103 tpe
[set
] |= config
->tpe
<< bit
;
104 tne
[set
] |= config
->tne
<< bit
;
106 /* Some banks do not have wake_en ability */
107 if (bank
->has_wake_en
)
108 wake_en
[set
] |= config
->wake_en
<< bit
;
111 /* Pad configuration registers */
112 reg
= bank
->pad_base
+ 16 * bank
->gpio_to_pad
[gpio
];
114 /* Add correct func to GPIO pad config */
115 pad_conf0
= config
->pad_conf0
;
118 if (gpio
>= bank
->gpio_f1_range_start
&&
119 gpio
<= bank
->gpio_f1_range_end
)
120 pad_conf0
|= PAD_FUNC1
;
122 pad_conf0
|= PAD_FUNC0
;
126 printk(BIOS_DEBUG
, "Write Pad: Base(%x) - %x %x %x\n",
127 reg
, pad_conf0
, config
->pad_conf1
, config
->pad_val
);
130 write32((u32
*)(reg
+ PAD_CONF0_REG
), pad_conf0
);
131 write32((u32
*)(reg
+ PAD_CONF1_REG
), config
->pad_conf1
);
132 write32((u32
*)(reg
+ PAD_VAL_REG
), config
->pad_val
);
135 if (bank
->legacy_base
!= GP_LEGACY_BASE_NONE
)
136 for (set
= 0; set
<= (bank
->gpio_count
- 1) / 32; ++set
) {
137 reg
= bank
->legacy_base
+ 0x20 * set
;
141 "Write GPIO: Reg(%x) - %x %x %x %x %x\n",
142 reg
, use_sel
[set
], io_sel
[set
], gp_lvl
[set
],
146 outl(use_sel
[set
], reg
+ LEGACY_USE_SEL_REG
);
147 outl(io_sel
[set
], reg
+ LEGACY_IO_SEL_REG
);
148 outl(gp_lvl
[set
], reg
+ LEGACY_GP_LVL_REG
);
149 outl(tpe
[set
], reg
+ LEGACY_TPE_REG
);
150 outl(tne
[set
], reg
+ LEGACY_TNE_REG
);
152 /* TS registers are WOC */
153 outl(0, reg
+ LEGACY_TS_REG
);
155 if (bank
->has_wake_en
)
156 outl(wake_en
[set
], reg
+ LEGACY_WAKE_EN_REG
);
160 static void setup_gpio_route(const struct soc_gpio_map
*sus
,
161 const struct soc_gpio_map
*core
)
163 uint32_t route_reg
= 0;
166 for (i
= 0; i
< 8; i
++) {
167 /* SMI takes precedence and wake_en implies SCI. */
169 route_reg
|= ROUTE_SMI
<< (2 * i
);
170 } else if (sus
[i
].sci
) {
171 route_reg
|= ROUTE_SCI
<< (2 * i
);
175 route_reg
|= ROUTE_SMI
<< (2 * (i
+ 8));
176 } else if (core
[i
].sci
) {
177 route_reg
|= ROUTE_SCI
<< (2 * (i
+ 8));
180 smm_southcluster_save_param(SMM_SAVE_PARAM_GPIO_ROUTE
, route_reg
);
183 static void setup_dirqs(const u8 dirq
[GPIO_MAX_DIRQS
],
184 const struct gpio_bank
*bank
)
186 u32
*reg
= (u32
*)(bank
->pad_base
+ PAD_BASE_DIRQ_OFFSET
);
190 /* Write all four DIRQ registers */
191 for (i
=0; i
<4; ++i
) {
192 val
= dirq
[i
* 4 + 3] << 24 | dirq
[i
* 4 + 2] << 16 |
193 dirq
[i
* 4 + 1] << 8 | dirq
[i
* 4];
194 write32(reg
+ i
, val
);
196 printk(BIOS_DEBUG
, "Write DIRQ reg(%x) - %x\n",
202 void setup_soc_gpios(struct soc_gpio_config
*config
, u8 enable_xdp_tap
)
205 setup_gpios(config
->ncore
, &gpncore_bank
);
206 setup_gpios(config
->score
, &gpscore_bank
);
207 setup_gpios(config
->ssus
, &gpssus_bank
);
208 setup_gpio_route(config
->ssus
, config
->score
);
210 if (config
->core_dirq
)
211 setup_dirqs(*config
->core_dirq
, &gpscore_bank
);
212 if (config
->sus_dirq
)
213 setup_dirqs(*config
->sus_dirq
, &gpssus_bank
);
216 /* Set on die termination feature with pull up value and
217 * drive the pad high for TAP_TDO and TAP_TMS
219 if (!enable_xdp_tap
) {
220 printk(BIOS_DEBUG
, "Tri-state TDO and TMS\n");
221 write32((u32
*)(GPSSUS_PAD_BASE
+ 0x2fc), 0xc);
222 write32((u32
*)(GPSSUS_PAD_BASE
+ 0x2cc), 0xc);
226 struct soc_gpio_config
* __weak
mainboard_get_gpios(void)
228 printk(BIOS_DEBUG
, "Default/empty GPIO config\n");