tree: Remove unused <assert.h>
[coreboot.git] / src / soc / mediatek / common / gpio.c
blob3dfdf92da07a1bfaef96febd169a0585c5c9b353
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <assert.h>
4 #include <device/mmio.h>
5 #include <gpio.h>
7 enum {
8 GPIO_DIRECTION_IN = 0,
9 GPIO_DIRECTION_OUT = 1,
12 enum {
13 GPIO_MODE = 0,
16 static void pos_bit_calc(gpio_t gpio, u32 *pos, u32 *bit)
18 *pos = gpio.id / MAX_GPIO_REG_BITS;
19 *bit = gpio.id % MAX_GPIO_REG_BITS;
22 static void pos_bit_calc_for_mode(gpio_t gpio, u32 *pos, u32 *bit)
24 *pos = gpio.id / MAX_GPIO_MODE_PER_REG;
25 *bit = (gpio.id % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
28 static s32 gpio_set_dir(gpio_t gpio, u32 dir)
30 u32 pos;
31 u32 bit;
32 u32 *reg;
34 pos_bit_calc(gpio, &pos, &bit);
36 if (dir == GPIO_DIRECTION_IN)
37 reg = &mtk_gpio->dir[pos].rst;
38 else
39 reg = &mtk_gpio->dir[pos].set;
41 write32(reg, 1L << bit);
43 return 0;
46 void gpio_set_mode(gpio_t gpio, int mode)
48 u32 pos;
49 u32 bit;
50 u32 mask = (1L << GPIO_MODE_BITS) - 1;
52 pos_bit_calc_for_mode(gpio, &pos, &bit);
54 clrsetbits32(&mtk_gpio->mode[pos].val, mask << bit, mode << bit);
57 int gpio_get(gpio_t gpio)
59 u32 pos;
60 u32 bit;
61 u32 *reg;
62 u32 data;
64 pos_bit_calc(gpio, &pos, &bit);
66 reg = &mtk_gpio->din[pos].val;
67 data = read32(reg);
69 return (data & (1L << bit)) ? 1 : 0;
72 void gpio_set(gpio_t gpio, int output)
74 u32 pos;
75 u32 bit;
76 u32 *reg;
78 pos_bit_calc(gpio, &pos, &bit);
80 if (output == 0)
81 reg = &mtk_gpio->dout[pos].rst;
82 else
83 reg = &mtk_gpio->dout[pos].set;
85 write32(reg, 1L << bit);
88 void gpio_input_pulldown(gpio_t gpio)
90 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_DOWN);
91 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
92 gpio_set_mode(gpio, GPIO_MODE);
95 void gpio_input_pullup(gpio_t gpio)
97 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_UP);
98 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
99 gpio_set_mode(gpio, GPIO_MODE);
102 void gpio_input(gpio_t gpio)
104 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
105 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
106 gpio_set_mode(gpio, GPIO_MODE);
109 void gpio_output(gpio_t gpio, int value)
111 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
112 gpio_set(gpio, value);
113 gpio_set_dir(gpio, GPIO_DIRECTION_OUT);
114 gpio_set_mode(gpio, GPIO_MODE);
117 int gpio_eint_poll(gpio_t gpio)
119 u32 pos;
120 u32 bit;
121 u32 status;
122 struct eint_regs *mtk_eint;
124 gpio_calc_eint_pos_bit(gpio, &pos, &bit);
125 mtk_eint = gpio_get_eint_reg(gpio);
126 assert(mtk_eint);
128 status = (read32(&mtk_eint->sta.regs[pos]) >> bit) & 0x1;
130 if (status)
131 write32(&mtk_eint->ack.regs[pos], 1 << bit);
133 return status;
136 void gpio_eint_configure(gpio_t gpio, enum gpio_irq_type type)
138 u32 pos;
139 u32 bit, mask;
140 struct eint_regs *mtk_eint;
142 gpio_calc_eint_pos_bit(gpio, &pos, &bit);
143 mtk_eint = gpio_get_eint_reg(gpio);
144 assert(mtk_eint);
146 mask = 1 << bit;
148 /* Make it an input first. */
149 gpio_input_pullup(gpio);
151 write32(&mtk_eint->d0en[pos], mask);
153 switch (type) {
154 case IRQ_TYPE_EDGE_FALLING:
155 write32(&mtk_eint->sens_clr.regs[pos], mask);
156 write32(&mtk_eint->pol_clr.regs[pos], mask);
157 break;
158 case IRQ_TYPE_EDGE_RISING:
159 write32(&mtk_eint->sens_clr.regs[pos], mask);
160 write32(&mtk_eint->pol_set.regs[pos], mask);
161 break;
162 case IRQ_TYPE_LEVEL_LOW:
163 write32(&mtk_eint->sens_set.regs[pos], mask);
164 write32(&mtk_eint->pol_clr.regs[pos], mask);
165 break;
166 case IRQ_TYPE_LEVEL_HIGH:
167 write32(&mtk_eint->sens_set.regs[pos], mask);
168 write32(&mtk_eint->pol_set.regs[pos], mask);
169 break;
172 write32(&mtk_eint->mask_clr.regs[pos], mask);
175 static inline bool is_valid_drv(uint8_t drv)
177 return drv <= GPIO_DRV_16_MA;
180 static inline bool is_valid_drv_adv(enum gpio_drv_adv drv)
182 return drv <= GPIO_DRV_ADV_1_MA && drv >= GPIO_DRV_ADV_125_UA;
185 int gpio_set_driving(gpio_t gpio, uint8_t drv)
187 uint32_t mask;
188 const struct gpio_drv_info *info = get_gpio_driving_info(gpio.id);
189 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
190 void *reg, *reg_adv, *reg_addr;
192 if (!info) {
193 printk(BIOS_ERR, "%s: raw_id %u is out of range\n", __func__, gpio.id);
194 return -1;
197 if (!is_valid_drv(drv))
198 return -1;
200 if (info->width == 0)
201 return -1;
203 mask = BIT(info->width) - 1;
204 /* Check setting value is not beyond width */
205 if ((uint32_t)drv > mask)
206 return -1;
208 reg_addr = gpio_find_reg_addr(gpio);
209 reg = reg_addr + info->offset;
210 clrsetbits32(reg, mask << info->shift, drv << info->shift);
212 /* Disable EH if supported */
213 if (adv_info && adv_info->width != 0) {
214 reg_adv = reg_addr + adv_info->offset;
215 clrbits32(reg_adv, BIT(adv_info->shift));
218 return 0;
221 int gpio_get_driving(gpio_t gpio)
223 const struct gpio_drv_info *info = get_gpio_driving_info(gpio.id);
224 void *reg;
226 if (!info) {
227 printk(BIOS_ERR, "%s: raw_id %u is out of range\n", __func__, gpio.id);
228 return -1;
231 if (info->width == 0)
232 return -1;
234 reg = gpio_find_reg_addr(gpio) + info->offset;
235 return (read32(reg) >> info->shift) & (BIT(info->width) - 1);
238 int gpio_set_driving_adv(gpio_t gpio, enum gpio_drv_adv drv)
240 uint32_t mask;
241 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
242 void *reg_adv;
244 if (!adv_info) {
245 printk(BIOS_ERR, "%s: raw_id %u is out of range\n", __func__, gpio.id);
246 return -1;
249 if (!is_valid_drv_adv(drv))
250 return -1;
252 if (adv_info->width == 0)
253 return -1;
255 /* Not include EH bit (the lowest bit) */
256 if ((uint32_t)drv > (BIT(adv_info->width - 1) - 1))
257 return -1;
259 reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
260 mask = BIT(adv_info->width) - 1;
261 /* EH enable */
262 drv = (drv << 1) | BIT(0);
264 clrsetbits32(reg_adv, mask << adv_info->shift, drv << adv_info->shift);
266 return 0;
269 int gpio_get_driving_adv(gpio_t gpio)
271 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
272 void *reg_adv;
273 uint32_t drv;
275 if (!adv_info) {
276 printk(BIOS_ERR, "%s: raw_id %u is out of range\n", __func__, gpio.id);
277 return -1;
280 if (adv_info->width == 0)
281 return -1;
283 reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
284 drv = (read32(reg_adv) >> adv_info->shift) & (BIT(adv_info->width) - 1);
286 /* Drop EH bit */
287 return drv >> 1;