mb/system76/cml-u/dt: Make use of chipset devicetree
[coreboot.git] / src / soc / mediatek / common / gpio.c
blobe8a50b2b181192900dc1fab07c8b53acafd13f08
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <gpio.h>
6 enum {
7 GPIO_DIRECTION_IN = 0,
8 GPIO_DIRECTION_OUT = 1,
9 };
11 enum {
12 GPIO_MODE = 0,
15 static void pos_bit_calc(gpio_t gpio, u32 *pos, u32 *bit)
17 *pos = gpio.id / MAX_GPIO_REG_BITS;
18 *bit = gpio.id % MAX_GPIO_REG_BITS;
21 static void pos_bit_calc_for_mode(gpio_t gpio, u32 *pos, u32 *bit)
23 *pos = gpio.id / MAX_GPIO_MODE_PER_REG;
24 *bit = (gpio.id % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
27 static s32 gpio_set_dir(gpio_t gpio, u32 dir)
29 u32 pos;
30 u32 bit;
31 u32 *reg;
33 pos_bit_calc(gpio, &pos, &bit);
35 if (dir == GPIO_DIRECTION_IN)
36 reg = &mtk_gpio->dir[pos].rst;
37 else
38 reg = &mtk_gpio->dir[pos].set;
40 write32(reg, 1L << bit);
42 return 0;
45 void gpio_set_mode(gpio_t gpio, int mode)
47 u32 pos;
48 u32 bit;
49 u32 mask = (1L << GPIO_MODE_BITS) - 1;
51 pos_bit_calc_for_mode(gpio, &pos, &bit);
53 clrsetbits32(&mtk_gpio->mode[pos].val, mask << bit, mode << bit);
56 int gpio_get(gpio_t gpio)
58 u32 pos;
59 u32 bit;
60 u32 *reg;
61 u32 data;
63 pos_bit_calc(gpio, &pos, &bit);
65 reg = &mtk_gpio->din[pos].val;
66 data = read32(reg);
68 return (data & (1L << bit)) ? 1 : 0;
71 void gpio_set(gpio_t gpio, int output)
73 u32 pos;
74 u32 bit;
75 u32 *reg;
77 pos_bit_calc(gpio, &pos, &bit);
79 if (output == 0)
80 reg = &mtk_gpio->dout[pos].rst;
81 else
82 reg = &mtk_gpio->dout[pos].set;
84 write32(reg, 1L << bit);
87 void gpio_input_pulldown(gpio_t gpio)
89 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_DOWN);
90 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
91 gpio_set_mode(gpio, GPIO_MODE);
94 void gpio_input_pullup(gpio_t gpio)
96 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_UP);
97 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
98 gpio_set_mode(gpio, GPIO_MODE);
101 void gpio_input(gpio_t gpio)
103 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
104 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
105 gpio_set_mode(gpio, GPIO_MODE);
108 void gpio_output(gpio_t gpio, int value)
110 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
111 gpio_set(gpio, value);
112 gpio_set_dir(gpio, GPIO_DIRECTION_OUT);
113 gpio_set_mode(gpio, GPIO_MODE);
116 enum {
117 MAX_EINT_REG_BITS = 32,
120 static void pos_bit_calc_for_eint(gpio_t gpio, u32 *pos, u32 *bit)
122 *pos = gpio.id / MAX_EINT_REG_BITS;
123 *bit = gpio.id % MAX_EINT_REG_BITS;
126 int gpio_eint_poll(gpio_t gpio)
128 u32 pos;
129 u32 bit;
130 u32 status;
132 pos_bit_calc_for_eint(gpio, &pos, &bit);
134 status = (read32(&mtk_eint->sta.regs[pos]) >> bit) & 0x1;
136 if (status)
137 write32(&mtk_eint->ack.regs[pos], 1 << bit);
139 return status;
142 void gpio_eint_configure(gpio_t gpio, enum gpio_irq_type type)
144 u32 pos;
145 u32 bit, mask;
147 pos_bit_calc_for_eint(gpio, &pos, &bit);
148 mask = 1 << bit;
150 /* Make it an input first. */
151 gpio_input_pullup(gpio);
153 write32(&mtk_eint->d0en[pos], mask);
155 switch (type) {
156 case IRQ_TYPE_EDGE_FALLING:
157 write32(&mtk_eint->sens_clr.regs[pos], mask);
158 write32(&mtk_eint->pol_clr.regs[pos], mask);
159 break;
160 case IRQ_TYPE_EDGE_RISING:
161 write32(&mtk_eint->sens_clr.regs[pos], mask);
162 write32(&mtk_eint->pol_set.regs[pos], mask);
163 break;
164 case IRQ_TYPE_LEVEL_LOW:
165 write32(&mtk_eint->sens_set.regs[pos], mask);
166 write32(&mtk_eint->pol_clr.regs[pos], mask);
167 break;
168 case IRQ_TYPE_LEVEL_HIGH:
169 write32(&mtk_eint->sens_set.regs[pos], mask);
170 write32(&mtk_eint->pol_set.regs[pos], mask);
171 break;
174 write32(&mtk_eint->mask_clr.regs[pos], mask);
177 static inline bool is_valid_drv(uint8_t drv)
179 return drv <= GPIO_DRV_16_MA;
182 static inline bool is_valid_drv_adv(enum gpio_drv_adv drv)
184 return drv <= GPIO_DRV_ADV_1_MA && drv >= GPIO_DRV_ADV_125_UA;
187 int gpio_set_driving(gpio_t gpio, uint8_t drv)
189 uint32_t mask;
190 const struct gpio_drv_info *info = get_gpio_driving_info(gpio.id);
191 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
192 void *reg, *reg_adv, *reg_addr;
194 if (!info)
195 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 return -1;
229 if (info->width == 0)
230 return -1;
232 reg = gpio_find_reg_addr(gpio) + info->offset;
233 return (read32(reg) >> info->shift) & (BIT(info->width) - 1);
236 int gpio_set_driving_adv(gpio_t gpio, enum gpio_drv_adv drv)
238 uint32_t mask;
239 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
240 void *reg_adv;
242 if (!adv_info)
243 return -1;
245 if (!is_valid_drv_adv(drv))
246 return -1;
248 if (adv_info->width == 0)
249 return -1;
251 /* Not include EH bit (the lowest bit) */
252 if ((uint32_t)drv > (BIT(adv_info->width - 1) - 1))
253 return -1;
255 reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
256 mask = BIT(adv_info->width) - 1;
257 /* EH enable */
258 drv = (drv << 1) | BIT(0);
260 clrsetbits32(reg_adv, mask << adv_info->shift, drv << adv_info->shift);
262 return 0;
265 int gpio_get_driving_adv(gpio_t gpio)
267 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
268 void *reg_adv;
269 uint32_t drv;
271 if (!adv_info)
272 return -1;
274 if (adv_info->width == 0)
275 return -1;
277 reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
278 drv = (read32(reg_adv) >> adv_info->shift) & (BIT(adv_info->width) - 1);
280 /* Drop EH bit */
281 return drv >> 1;