coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
gpio_support.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <gpio.h>
5 #include <console/console.h>
6 #include <soc/gpio.h>
7 
8 /*
9  * Return family number and internal pad number in that community by pad number
10  * and which community it is in.
11  */
13 {
14  /*
15  * Refer to BSW BIOS Writers Guide, Table "Family Number". BSW has 4 GPIO communities.
16  * Each community has up to 7 families and each family contains a range of Pad numbers.
17  * The number in the array is the maximum no. of that range.
18  * For example: East community, family 0, Pad 0~11.
19  */
20  static const uint8_t community_base[GPIO_COMMUNITY_COUNT]
22  {0, 8, 16, 24, 32, 40, 48, 56}, /* Southwest */
23  {0, 9, 22, 34, 46, 59, 59, 59}, /* North */
24  {0, 12, 24, 24, 24, 24, 24, 24}, /* East */
25  {0, 8, 20, 26, 34, 44, 55, 55} /* Southeast */
26  };
27  const uint8_t *base;
28  uint8_t i;
29 
30  /* Validate the pad number */
31  if (pad > community_base[community][7])
32  die("Pad number is out of range!");
33 
34  /* Locate the family number for the pad */
35  base = &community_base[community][0];
36  for (i = 0; i < 7; i++) {
37  if ((pad >= base[0]) && (pad < base[1]))
38  break;
39  base++;
40  }
41 
42  /* Family number in high byte and inner pad number in lowest byte */
43  return (i << 8) + pad - *base;
44 }
45 
46 /*
47  * Return pad configuration register offset by pad number and which community it is in.
48  */
50 {
51  uint16_t fpad;
52  uint32_t *pad_config_reg;
53 
54  /* Get the GPIO family number */
55  fpad = gpio_family_number(community, pad);
56 
57  /*
58  * Refer to BSW BIOS Writers Guide, Table "Per Pad Memory Space Registers Addresses"
59  * for the Pad configuration register calculation.
60  */
61  pad_config_reg = (uint32_t *)(COMMUNITY_BASE(community) + FAMILY_PAD_REGS_OFF +
62  (FAMILY_PAD_REGS_SIZE * (fpad >> 8)) + (GPIO_REGS_SIZE * (fpad & 0xff)));
63 
64  return pad_config_reg;
65 }
66 
67 static int gpio_get_community_num(gpio_t gpio_num, int *pad)
68 {
69  int comm = 0;
70 
71  if (gpio_num >= GP_SW_00 && gpio_num <= GP_SW_97) {
72  comm = GP_SOUTHWEST;
73  *pad = gpio_num % GP_SOUTHWEST_COUNT;
74 
75  } else if (gpio_num >= GP_NC_00 && gpio_num <= GP_NC_72) {
76  comm = GP_NORTH;
77  *pad = gpio_num % GP_SOUTHWEST_COUNT;
78 
79  } else if (gpio_num >= GP_E_00 && gpio_num <= GP_E_26) {
80  comm = GP_EAST;
81  *pad = gpio_num % (GP_SOUTHWEST_COUNT + GP_NORTH_COUNT);
82 
83  } else {
84  comm = GP_SOUTHEAST;
85  *pad = gpio_num % (GP_SOUTHWEST_COUNT + GP_NORTH_COUNT + GP_EAST_COUNT);
86  }
87  return comm;
88 }
89 
90 static void gpio_config_pad(gpio_t gpio_num, const struct soc_gpio_map *cfg)
91 {
92  int comm = 0;
93  int pad_num = 0;
94  uint32_t *pad_config0_reg;
95  uint32_t *pad_config1_reg;
96 
97  if (gpio_num > MAX_GPIO_CNT)
98  return;
99  /* Get GPIO Community based on GPIO_NUMBER */
100  comm = gpio_get_community_num(gpio_num, &pad_num);
101  /* CONF0 */
102  pad_config0_reg = gpio_pad_config_reg(comm, pad_num);
103  /* CONF1 */
104  pad_config1_reg = pad_config0_reg + 1;
105 
106  write32(pad_config0_reg, cfg->pad_conf0);
107  write32(pad_config1_reg, cfg->pad_conf1);
108 }
109 
110 void gpio_input_pullup(gpio_t gpio_num)
111 {
112  struct soc_gpio_map cfg = GPIO_INPUT_PU_20K;
113  gpio_config_pad(gpio_num, &cfg);
114 }
115 
117 {
118  struct soc_gpio_map cfg = GPIO_INPUT_PD_20K;
119  gpio_config_pad(gpio_num, &cfg);
120 }
121 
122 void gpio_input(gpio_t gpio_num)
123 {
124  struct soc_gpio_map cfg = GPIO_INPUT_NO_PULL;
125  gpio_config_pad(gpio_num, &cfg);
126 }
127 
128 int gpio_get(gpio_t gpio_num)
129 {
130  int comm = 0;
131  int pad_num = 0;
132  uint32_t *pad_config0_reg;
133  u32 pad_value;
134 
135  if (gpio_num > MAX_GPIO_CNT)
136  return -1;
137 
138  /* Get GPIO Community based on GPIO_NUMBER */
139  comm = gpio_get_community_num(gpio_num, &pad_num);
140  /* CONF0 */
141  pad_config0_reg = gpio_pad_config_reg(comm, pad_num);
142 
143  pad_value = read32(pad_config0_reg);
144 
145  return pad_value & PAD_RX_BIT;
146 }
147 
148 int get_gpio(int community_base, int pad0_offset)
149 {
150  return (read32((void *)(community_base + pad0_offset))) & PAD_RX_BIT;
151 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void __noreturn die(const char *fmt,...)
Definition: die.c:17
uint16_t gpio_family_number(uint8_t community, uint8_t pad)
Definition: gpio_support.c:12
uint32_t * gpio_pad_config_reg(uint8_t community, uint8_t pad)
Definition: gpio_support.c:49
int gpio_get(gpio_t gpio_num)
Definition: gpio_support.c:128
int get_gpio(int community_base, int pad0_offset)
Definition: gpio_support.c:148
void gpio_input_pullup(gpio_t gpio_num)
Definition: gpio_support.c:110
static int gpio_get_community_num(gpio_t gpio_num, int *pad)
Definition: gpio_support.c:67
static void gpio_config_pad(gpio_t gpio_num, const struct soc_gpio_map *cfg)
Definition: gpio_support.c:90
void gpio_input_pulldown(gpio_t gpio_num)
Definition: gpio_support.c:116
void gpio_input(gpio_t gpio_num)
Definition: gpio_support.c:122
uintptr_t base
Definition: uart.c:17
#define GPIO_INPUT_PD_20K
Definition: gpio.h:165
#define GPIO_INPUT_PU_20K
Definition: gpio.h:151
#define PAD_RX_BIT
Definition: gpio.h:188
#define GPIO_FAMILIES_MAX_PER_COMM
Definition: gpio.h:27
#define FAMILY_PAD_REGS_OFF
Definition: gpio.h:134
#define COMMUNITY_BASE(community)
Definition: gpio.h:33
#define GPIO_COMMUNITY_COUNT
Definition: gpio.h:26
#define GPIO_REGS_SIZE
Definition: gpio.h:126
#define GP_SOUTHEAST
Definition: gpio.h:31
#define GP_EAST_COUNT
Definition: gpio.h:120
#define GPIO_INPUT_NO_PULL
Definition: gpio.h:212
#define GP_SOUTHWEST
Definition: gpio.h:28
#define GP_NORTH_COUNT
Definition: gpio.h:119
#define FAMILY_PAD_REGS_SIZE
Definition: gpio.h:135
#define GP_EAST
Definition: gpio.h:30
#define GP_NORTH
Definition: gpio.h:29
#define MAX_GPIO_CNT
Definition: gpio.h:123
#define GP_SOUTHWEST_COUNT
Definition: gpio.h:118
#define GP_E_26
Definition: gpio_defs.h:147
#define GP_NC_00
Definition: gpio_defs.h:64
#define GP_E_00
Definition: gpio_defs.h:124
#define GP_SW_00
Definition: gpio_defs.h:7
#define GP_SW_97
Definition: gpio_defs.h:62
#define GP_NC_72
Definition: gpio_defs.h:122
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned char uint8_t
Definition: stdint.h:8
u32 pad_conf1
Definition: gpio.h:331
u32 pad_conf0
Definition: gpio.h:330