coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
gpio.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * This file is created based on MT8186 Functional Specification
5  * Chapter number: 5.1
6  */
7 
8 #include <device/mmio.h>
9 #include <gpio.h>
10 
11 static const struct gpio_drv_info gpio_driving_info[] = {
12  [0] = { 0x0, 27, 3, },
13  [1] = { 0x0, 27, 3, },
14  [2] = { 0x0, 27, 3, },
15  [3] = { 0x0, 27, 3, },
16  [4] = { 0x10, 0, 3, },
17  [5] = { 0x10, 0, 3, },
18  [6] = { 0x0, 9, 3, },
19  [7] = { 0x0, 9, 3, },
20  [8] = { 0x0, 9, 3, },
21  [9] = { 0x0, 12, 3, },
22  [10] = { 0x0, 0, 3, },
23  [11] = { 0x0, 3, 3, },
24  [12] = { 0x0, 6, 3, },
25  [13] = { 0x0, 0, 3, },
26  [14] = { 0x0, 3, 3, },
27  [15] = { 0x10, 3, 3, },
28  [16] = { 0x10, 3, 3, },
29  [17] = { 0x0, 21, 3, },
30  [18] = { 0x10, 0, 3, },
31  [19] = { 0x0, 27, 3, },
32  [20] = { 0x0, 24, 3, },
33  [21] = { 0x0, 27, 3, },
34  [22] = { 0x0, 24, 3, },
35  [23] = { 0x10, 0, 3, },
36  [24] = { 0x10, 9, 3, },
37  [25] = { 0x10, 0, 3, },
38  [26] = { 0x0, 27, 3, },
39  [27] = { 0x0, 27, 3, },
40  [28] = { 0x10, 0, 3, },
41  [29] = { 0x10, 0, 3, },
42  [30] = { 0x10, 0, 3, },
43  [31] = { 0x10, 3, 3, },
44  [32] = { 0x0, 6, 3, },
45  [33] = { 0x0, 6, 3, },
46  [34] = { 0x0, 3, 3, },
47  [35] = { 0x0, 3, 3, },
48  [36] = { 0x0, 9, 3, },
49  [37] = { 0x0, 9, 3, },
50  [38] = { 0x0, 12, 3, },
51  [39] = { 0x0, 9, 3, },
52  [40] = { 0x0, 15, 3, },
53  [41] = { 0x0, 12, 3, },
54  [42] = { 0x0, 12, 3, },
55  [43] = { 0x0, 12, 3, },
56  [44] = { 0x10, 6, 3, },
57  [45] = { 0x10, 3, 3, },
58  [46] = { 0x10, 3, 3, },
59  [47] = { 0x10, 6, 3, },
60  [48] = { 0x0, 15, 3, },
61  [49] = { 0x0, 15, 3, },
62  [50] = { 0x0, 15, 3, },
63  [51] = { 0x0, 18, 3, },
64  [52] = { 0x10, 3, 3, },
65  [53] = { 0x10, 6, 3, },
66  [54] = { 0x10, 3, 3, },
67  [55] = { 0x10, 3, 3, },
68  [56] = { 0x10, 3, 3, },
69  [57] = { 0x10, 6, 3, },
70  [58] = { 0x10, 6, 3, },
71  [59] = { 0x10, 3, 3, },
72  [60] = { 0x0, 24, 3, },
73  [61] = { 0x0, 24, 3, },
74  [62] = { 0x0, 24, 3, },
75  [63] = { 0x0, 24, 3, },
76  [64] = { 0x0, 27, 3, },
77  [65] = { 0x0, 27, 3, },
78  [66] = { 0x0, 27, 3, },
79  [67] = { 0x10, 0, 3, },
80  [68] = { 0x0, 0, 3, },
81  [69] = { 0x0, 3, 3, },
82  [70] = { 0x10, 3, 3, },
83  [71] = { 0x0, 6, 3, },
84  [72] = { 0x0, 9, 3, },
85  [73] = { 0x0, 12, 3, },
86  [74] = { 0x0, 15, 3, },
87  [75] = { 0x0, 18, 3, },
88  [76] = { 0x0, 21, 3, },
89  [77] = { 0x0, 24, 3, },
90  [78] = { 0x0, 27, 3, },
91  [79] = { 0x0, 24, 3, },
92  [80] = { 0x0, 24, 3, },
93  [81] = { 0x0, 21, 3, },
94  [82] = { 0x0, 21, 3, },
95  [83] = { 0x10, 3, 3, },
96  [84] = { 0x0, 6, 3, },
97  [85] = { 0x0, 9, 3, },
98  [86] = { 0x0, 12, 3, },
99  [87] = { 0x0, 15, 3, },
100  [88] = { 0x0, 18, 3, },
101  [89] = { 0x0, 21, 3, },
102  [90] = { 0x0, 27, 3, },
103  [91] = { 0x10, 0, 3, },
104  [92] = { 0x10, 0, 3, },
105  [93] = { 0x10, 0, 3, },
106  [94] = { 0x10, 0, 3, },
107  [95] = { 0x10, 3, 3, },
108  [96] = { 0x0, 9, 3, },
109  [97] = { 0x0, 6, 3, },
110  [98] = { 0x0, 3, 3, },
111  [99] = { 0x0, 18, 3, },
112  [100] = { 0x0, 18, 3, },
113  [101] = { 0x0, 21, 3, },
114  [102] = { 0x0, 21, 3, },
115  [103] = { 0x0, 21, 3, },
116  [104] = { 0x0, 21, 3, },
117  [105] = { 0x0, 24, 3, },
118  [106] = { 0x0, 24, 3, },
119  [107] = { 0x0, 24, 3, },
120  [108] = { 0x0, 24, 3, },
121  [109] = { 0x0, 27, 3, },
122  [110] = { 0x0, 27, 3, },
123  [111] = { 0x0, 27, 3, },
124  [112] = { 0x0, 27, 3, },
125  [113] = { 0x10, 0, 3, },
126  [114] = { 0x10, 0, 3, },
127  [115] = { 0x10, 6, 3, },
128  [116] = { 0x10, 9, 3, },
129  [117] = { 0x10, 6, 3, },
130  [118] = { 0x10, 6, 3, },
131  [119] = { 0x0, 18, 3, },
132  [120] = { 0x0, 9, 3, },
133  [121] = { 0x0, 12, 3, },
134  [122] = { 0x0, 15, 3, },
135  [123] = { 0x0, 21, 3, },
136  [124] = { 0x0, 0, 3, },
137  [125] = { 0x0, 3, 3, },
138  [126] = { 0x0, 6, 3, },
139  [127] = { 0x10, 12, 3, },
140  [128] = { 0x10, 18, 3, },
141  [129] = { 0x10, 12, 3, },
142  [130] = { 0x10, 18, 3, },
143  [131] = { 0x10, 15, 3, },
144  [132] = { 0x10, 21, 3, },
145  [133] = { 0x10, 15, 3, },
146  [134] = { 0x10, 21, 3, },
147  [135] = { 0x10, 6, 3, },
148  [136] = { 0x10, 15, 3, },
149  [137] = { 0x10, 18, 3, },
150  [138] = { 0x10, 24, 3, },
151  [139] = { 0x0, 21, 3, },
152  [140] = { 0x0, 24, 3, },
153  [141] = { 0x10, 15, 3, },
154  [142] = { 0x10, 21, 3, },
155  [143] = { 0x10, 9, 3, },
156  [144] = { 0x10, 18, 3, },
157  [145] = { 0x10, 12, 3, },
158  [146] = { 0x10, 21, 3, },
159  [147] = { 0x0, 12, 3, },
160  [148] = { 0x0, 12, 3, },
161  [149] = { 0x0, 12, 3, },
162  [150] = { 0x0, 15, 3, },
163  [151] = { 0x0, 15, 3, },
164  [152] = { 0x0, 9, 3, },
165  [153] = { 0x0, 15, 3, },
166  [154] = { 0x0, 15, 3, },
167  [155] = { 0x0, 18, 3, },
168  [156] = { 0x0, 18, 3, },
169  [157] = { 0x0, 0, 3, },
170  [158] = { 0x0, 0, 3, },
171  [159] = { 0x0, 0, 3, },
172  [160] = { 0x0, 0, 3, },
173  [161] = { 0x0, 6, 3, },
174  [162] = { 0x0, 3, 3, },
175  [163] = { 0x10, 12, 3, },
176  /* 164 is unimplemented */
177  [165] = { 0x10, 6, 3, },
178  [166] = { 0x10, 6, 3, },
179  [167] = { 0x10, 9, 3, },
180  [168] = { 0x10, 6, 3, },
181  [169] = { 0x10, 12, 3, },
182  [170] = { 0x10, 9, 3, },
183  [171] = { 0x10, 9, 3, },
184  [172] = { 0x10, 9, 3, },
185  [173] = { 0x10, 6, 3, },
186  [174] = { 0x0, 9, 3, },
187  [175] = { 0x0, 12, 3, },
188  [176] = { 0x0, 0, 3, },
189  [177] = { 0x0, 3, 3, },
190  [178] = { 0x0, 6, 3, },
191  [179] = { 0x0, 15, 3, },
192  [180] = { 0x0, 18, 3, },
193  [181] = { 0x0, 21, 3, },
194  [182] = { 0x0, 24, 3, },
195  [183] = { 0x0, 27, 3, },
196  [184] = { 0x10, 0, 3, },
197 };
198 
200  "gpio_driving_info array size not match");
201 
202 /* Unimplemented GPIOs are intentionally omitted here with width=0 */
203 static const struct gpio_drv_info gpio_driving_adv_info[GPIO_NUM] = {
204  [127] = { 0x30, 0, 3, },
205  [128] = { 0x30, 6, 3, },
206  [129] = { 0x30, 0, 3, },
207  [130] = { 0x30, 6, 3, },
208  [131] = { 0x30, 3, 3, },
209  [132] = { 0x30, 9, 3, },
210  [133] = { 0x30, 0, 3, },
211  [134] = { 0x30, 6, 3, },
212  [135] = { 0x20, 0, 3, },
213  [136] = { 0x20, 9, 3, },
214  [137] = { 0x30, 3, 3, },
215  [138] = { 0x30, 9, 3, },
216  [139] = { 0x20, 0, 3, },
217  [140] = { 0x20, 3, 3, },
218  [141] = { 0x30, 3, 3, },
219  [142] = { 0x30, 9, 3, },
220  [143] = { 0x20, 3, 3, },
221  [144] = { 0x20, 12, 3, },
222  [145] = { 0x20, 6, 3, },
223  [146] = { 0x20, 15, 3, },
224 };
225 
227 {
228  void *reg_addr;
229  switch (gpio.base & 0x0f) {
230  case 1:
231  reg_addr = (void *)IOCFG_LT_BASE;
232  break;
233  case 2:
234  reg_addr = (void *)IOCFG_LM_BASE;
235  break;
236  case 3:
237  reg_addr = (void *)IOCFG_LB_BASE;
238  break;
239  case 4:
240  reg_addr = (void *)IOCFG_BL_BASE;
241  break;
242  case 5:
243  reg_addr = (void *)IOCFG_RB_BASE;
244  break;
245  case 6:
246  reg_addr = (void *)IOCFG_RT_BASE;
247  break;
248  default:
249  reg_addr = NULL;
250  break;
251  }
252 
253  return reg_addr;
254 }
255 
257  enum pull_select select)
258 {
259  void *reg1;
260  void *reg2;
261  int bit = gpio.bit;
262 
263  reg1 = gpio_find_reg_addr(gpio) + gpio.offset;
264  reg2 = reg1 + (gpio.base & 0xf0);
265 
266  if (enable == GPIO_PULL_ENABLE) {
267  if (select == GPIO_PULL_DOWN)
268  setbits32(reg1, BIT(bit));
269  else
270  clrbits32(reg1, BIT(bit));
271  }
272 
273  if (enable == GPIO_PULL_ENABLE) {
274  setbits32(reg2, 1 << bit);
275  } else {
276  clrbits32(reg2, 1 << bit);
277  clrbits32(reg2 + 0x010, BIT(bit));
278  }
279 }
280 
281 static void gpio_set_pull_pu_pd(gpio_t gpio, enum pull_enable enable,
282  enum pull_select select)
283 {
284  void *reg1;
285  void *reg2;
286  int bit = gpio.bit;
287 
288  reg1 = gpio_find_reg_addr(gpio) + gpio.offset;
289  reg2 = reg1 - (gpio.base & 0xf0);
290 
291  if (enable == GPIO_PULL_ENABLE) {
292  if (select == GPIO_PULL_DOWN) {
293  clrbits32(reg1, BIT(bit));
294  setbits32(reg2, BIT(bit));
295  } else {
296  clrbits32(reg2, BIT(bit));
297  setbits32(reg1, BIT(bit));
298  }
299  } else {
300  clrbits32(reg1, BIT(bit));
301  clrbits32(reg2, BIT(bit));
302  }
303 }
304 
306  enum pull_select select)
307 {
308  if (gpio.flag)
309  gpio_set_spec_pull_pupd(gpio, enable, select);
310  else
311  gpio_set_pull_pu_pd(gpio, enable, select);
312 }
313 
314 static inline bool is_valid_drv(uint8_t drv)
315 {
316  return drv <= GPIO_DRV_16_MA;
317 }
318 
319 static inline bool is_valid_drv_adv(enum gpio_drv_adv drv)
320 {
321  return drv <= GPIO_DRV_ADV_1_MA && drv >= GPIO_DRV_ADV_125_UA;
322 }
323 
325 {
326  uint32_t mask;
327  const struct gpio_drv_info *info = &gpio_driving_info[gpio.id];
328  const struct gpio_drv_info *adv_info = &gpio_driving_adv_info[gpio.id];
329  void *reg, *reg_adv;
330 
331  if (!is_valid_drv(drv))
332  return -1;
333 
334  reg = gpio_find_reg_addr(gpio) + info->offset;
335  reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
336 
337  if (info->width == 0)
338  return -1;
339 
340  mask = BIT(info->width) - 1;
341  /* Check setting value is not beyond width */
342  if ((uint32_t)drv > mask)
343  return -1;
344 
345  clrsetbits32(reg, mask << info->shift, drv << info->shift);
346 
347  /* Disable EH if supported */
348  if (adv_info->width != 0)
349  clrbits32(reg_adv, BIT(adv_info->shift));
350 
351  return 0;
352 }
353 
355 {
356  const struct gpio_drv_info *info = &gpio_driving_info[gpio.id];
357  void *reg;
358 
359  reg = gpio_find_reg_addr(gpio) + info->offset;
360  if (info->width == 0)
361  return -1;
362 
363  return (read32(reg) >> info->shift) & (BIT(info->width) - 1);
364 }
365 
367 {
368  uint32_t mask;
369  const struct gpio_drv_info *adv_info = &gpio_driving_adv_info[gpio.id];
370  void *reg_adv;
371 
372  if (!is_valid_drv_adv(drv))
373  return -1;
374 
375  reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
376 
377  if (adv_info->width == 0)
378  return -1;
379 
380  /* Not include EH bit (the lowest bit) */
381  if ((uint32_t)drv > (BIT(adv_info->width - 1) - 1))
382  return -1;
383 
384  mask = BIT(adv_info->width) - 1;
385  /* EH enable */
386  drv = (drv << 1) | BIT(0);
387 
388  clrsetbits32(reg_adv, mask << adv_info->shift, drv << adv_info->shift);
389 
390  return 0;
391 }
392 
394 {
395  const struct gpio_drv_info *adv_info = &gpio_driving_adv_info[gpio.id];
396  void *reg_adv;
397  uint32_t drv;
398 
399  reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
400  if (adv_info->width == 0)
401  return -1;
402 
403  drv = (read32(reg_adv) >> adv_info->shift) & (BIT(adv_info->width) - 1);
404 
405  /* Drop EH bit */
406  return drv >> 1;
407 }
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
static struct smmstore_params_info info
Definition: ramstage.c:12
#define BIT(nr)
Definition: ec_commands.h:45
#define setbits32(addr, set)
Definition: mmio.h:21
#define clrsetbits32(addr, clear, set)
Definition: mmio.h:16
#define clrbits32(addr, clear)
Definition: mmio.h:26
pull_enable
Definition: gpio_common.h:11
@ GPIO_PULL_ENABLE
Definition: gpio_common.h:13
gpio_drv_adv
Definition: gpio_common.h:29
@ GPIO_DRV_ADV_125_UA
Definition: gpio_common.h:30
pull_select
Definition: gpio_common.h:16
static const int mask[4]
Definition: gpio.c:308
void gpio_set_pull(gpio_t gpio, enum pull_enable enable, enum pull_select select)
Definition: gpio.c:17
@ IOCFG_LT_BASE
Definition: addressmap.h:46
@ IOCFG_LM_BASE
Definition: addressmap.h:43
@ IOCFG_RB_BASE
Definition: addressmap.h:40
@ IOCFG_BL_BASE
Definition: addressmap.h:44
@ IOCFG_RT_BASE
Definition: addressmap.h:38
@ IOCFG_LB_BASE
Definition: addressmap.h:42
_Static_assert(ARRAY_SIZE(gpio_driving_info)==GPIO_NUM, "gpio_driving_info array size not match")
int gpio_set_driving(gpio_t gpio, uint8_t drv)
Definition: gpio.c:324
static void * gpio_find_reg_addr(gpio_t gpio)
Definition: gpio.c:226
static const struct gpio_drv_info gpio_driving_adv_info[GPIO_NUM]
Definition: gpio.c:203
int gpio_get_driving(gpio_t gpio)
Definition: gpio.c:354
static bool is_valid_drv_adv(enum gpio_drv_adv drv)
Definition: gpio.c:319
int gpio_get_driving_adv(gpio_t gpio)
Definition: gpio.c:393
int gpio_set_driving_adv(gpio_t gpio, enum gpio_drv_adv drv)
Definition: gpio.c:366
static bool is_valid_drv(uint8_t drv)
Definition: gpio.c:314
static void gpio_set_pull_pu_pd(gpio_t gpio, enum pull_enable enable, enum pull_select select)
Definition: gpio.c:281
static void gpio_set_spec_pull_pupd(gpio_t gpio, enum pull_enable enable, enum pull_select select)
Definition: gpio.c:256
static const struct gpio_drv_info gpio_driving_info[]
Definition: gpio.c:11
@ GPIO_DRV_16_MA
Definition: gpio.h:31
#define GPIO_NUM
Definition: gpio.h:15
#define GPIO_PULL_DOWN
Definition: gpio.h:23
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
uint32_t offset
Definition: gpio_common.h:37
uint8_t width
Definition: gpio_common.h:39
uint8_t shift
Definition: gpio_common.h:38
Definition: pinmux.c:36