1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/mmio.h>
4 #include <gpio.h>
5
6 enum {
7 GPIO_DIRECTION_IN = 0,
8 GPIO_DIRECTION_OUT = 1,
9 };
10
11 enum {
12 GPIO_MODE = 0,
13 };
14
pos_bit_calc(gpio_t gpio,u32 * pos,u32 * bit)15 static void pos_bit_calc(gpio_t gpio, u32 *pos, u32 *bit)
16 {
17 *pos = gpio.id / MAX_GPIO_REG_BITS;
18 *bit = gpio.id % MAX_GPIO_REG_BITS;
19 }
20
pos_bit_calc_for_mode(gpio_t gpio,u32 * pos,u32 * bit)21 static void pos_bit_calc_for_mode(gpio_t gpio, u32 *pos, u32 *bit)
22 {
23 *pos = gpio.id / MAX_GPIO_MODE_PER_REG;
24 *bit = (gpio.id % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
25 }
26
gpio_set_dir(gpio_t gpio,u32 dir)27 static s32 gpio_set_dir(gpio_t gpio, u32 dir)
28 {
29 u32 pos;
30 u32 bit;
31 u32 *reg;
32
33 pos_bit_calc(gpio, &pos, &bit);
34
35 if (dir == GPIO_DIRECTION_IN)
36 reg = &mtk_gpio->dir[pos].rst;
37 else
38 reg = &mtk_gpio->dir[pos].set;
39
40 write32(reg, 1L << bit);
41
42 return 0;
43 }
44
gpio_set_mode(gpio_t gpio,int mode)45 void gpio_set_mode(gpio_t gpio, int mode)
46 {
47 u32 pos;
48 u32 bit;
49 u32 mask = (1L << GPIO_MODE_BITS) - 1;
50
51 pos_bit_calc_for_mode(gpio, &pos, &bit);
52
53 clrsetbits32(&mtk_gpio->mode[pos].val, mask << bit, mode << bit);
54 }
55
gpio_get(gpio_t gpio)56 int gpio_get(gpio_t gpio)
57 {
58 u32 pos;
59 u32 bit;
60 u32 *reg;
61 u32 data;
62
63 pos_bit_calc(gpio, &pos, &bit);
64
65 reg = &mtk_gpio->din[pos].val;
66 data = read32(reg);
67
68 return (data & (1L << bit)) ? 1 : 0;
69 }
70
gpio_set(gpio_t gpio,int output)71 void gpio_set(gpio_t gpio, int output)
72 {
73 u32 pos;
74 u32 bit;
75 u32 *reg;
76
77 pos_bit_calc(gpio, &pos, &bit);
78
79 if (output == 0)
80 reg = &mtk_gpio->dout[pos].rst;
81 else
82 reg = &mtk_gpio->dout[pos].set;
83
84 write32(reg, 1L << bit);
85 }
86
gpio_input_pulldown(gpio_t gpio)87 void gpio_input_pulldown(gpio_t gpio)
88 {
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);
92 }
93
gpio_input_pullup(gpio_t gpio)94 void gpio_input_pullup(gpio_t gpio)
95 {
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);
99 }
100
gpio_input(gpio_t gpio)101 void gpio_input(gpio_t gpio)
102 {
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);
106 }
107
gpio_output(gpio_t gpio,int value)108 void gpio_output(gpio_t gpio, int value)
109 {
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);
114 }
115
116 enum {
117 MAX_EINT_REG_BITS = 32,
118 };
119
pos_bit_calc_for_eint(gpio_t gpio,u32 * pos,u32 * bit)120 static void pos_bit_calc_for_eint(gpio_t gpio, u32 *pos, u32 *bit)
121 {
122 *pos = gpio.id / MAX_EINT_REG_BITS;
123 *bit = gpio.id % MAX_EINT_REG_BITS;
124 }
125
gpio_eint_poll(gpio_t gpio)126 int gpio_eint_poll(gpio_t gpio)
127 {
128 u32 pos;
129 u32 bit;
130 u32 status;
131
132 pos_bit_calc_for_eint(gpio, &pos, &bit);
133
134 status = (read32(&mtk_eint->sta.regs[pos]) >> bit) & 0x1;
135
136 if (status)
137 write32(&mtk_eint->ack.regs[pos], 1 << bit);
138
139 return status;
140 }
141
gpio_eint_configure(gpio_t gpio,enum gpio_irq_type type)142 void gpio_eint_configure(gpio_t gpio, enum gpio_irq_type type)
143 {
144 u32 pos;
145 u32 bit, mask;
146
147 pos_bit_calc_for_eint(gpio, &pos, &bit);
148 mask = 1 << bit;
149
150 /* Make it an input first. */
151 gpio_input_pullup(gpio);
152
153 write32(&mtk_eint->d0en[pos], mask);
154
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;
172 }
173
174 write32(&mtk_eint->mask_clr.regs[pos], mask);
175 }
176
is_valid_drv(uint8_t drv)177 static inline bool is_valid_drv(uint8_t drv)
178 {
179 return drv <= GPIO_DRV_16_MA;
180 }
181
is_valid_drv_adv(enum gpio_drv_adv drv)182 static inline bool is_valid_drv_adv(enum gpio_drv_adv drv)
183 {
184 return drv <= GPIO_DRV_ADV_1_MA && drv >= GPIO_DRV_ADV_125_UA;
185 }
186
gpio_set_driving(gpio_t gpio,uint8_t drv)187 int gpio_set_driving(gpio_t gpio, uint8_t drv)
188 {
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;
193
194 if (!info)
195 return -1;
196
197 if (!is_valid_drv(drv))
198 return -1;
199
200 if (info->width == 0)
201 return -1;
202
203 mask = BIT(info->width) - 1;
204 /* Check setting value is not beyond width */
205 if ((uint32_t)drv > mask)
206 return -1;
207
208 reg_addr = gpio_find_reg_addr(gpio);
209 reg = reg_addr + info->offset;
210 clrsetbits32(reg, mask << info->shift, drv << info->shift);
211
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));
216 }
217
218 return 0;
219 }
220
gpio_get_driving(gpio_t gpio)221 int gpio_get_driving(gpio_t gpio)
222 {
223 const struct gpio_drv_info *info = get_gpio_driving_info(gpio.id);
224 void *reg;
225
226 if (!info)
227 return -1;
228
229 if (info->width == 0)
230 return -1;
231
232 reg = gpio_find_reg_addr(gpio) + info->offset;
233 return (read32(reg) >> info->shift) & (BIT(info->width) - 1);
234 }
235
gpio_set_driving_adv(gpio_t gpio,enum gpio_drv_adv drv)236 int gpio_set_driving_adv(gpio_t gpio, enum gpio_drv_adv drv)
237 {
238 uint32_t mask;
239 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
240 void *reg_adv;
241
242 if (!adv_info)
243 return -1;
244
245 if (!is_valid_drv_adv(drv))
246 return -1;
247
248 if (adv_info->width == 0)
249 return -1;
250
251 /* Not include EH bit (the lowest bit) */
252 if ((uint32_t)drv > (BIT(adv_info->width - 1) - 1))
253 return -1;
254
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);
259
260 clrsetbits32(reg_adv, mask << adv_info->shift, drv << adv_info->shift);
261
262 return 0;
263 }
264
gpio_get_driving_adv(gpio_t gpio)265 int gpio_get_driving_adv(gpio_t gpio)
266 {
267 const struct gpio_drv_info *adv_info = get_gpio_driving_adv_info(gpio.id);
268 void *reg_adv;
269 uint32_t drv;
270
271 if (!adv_info)
272 return -1;
273
274 if (adv_info->width == 0)
275 return -1;
276
277 reg_adv = gpio_find_reg_addr(gpio) + adv_info->offset;
278 drv = (read32(reg_adv) >> adv_info->shift) & (BIT(adv_info->width) - 1);
279
280 /* Drop EH bit */
281 return drv >> 1;
282 }
283