1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "sedi_driver_pm.h"
8 #include <sedi_gpio_regs.h>
9 #include <sedi_driver_gpio.h>
10 
11 /* driver version */
12 #define SEDI_GPIO_DRIVER_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(0, 1)
13 
14 /* GPIO port pin number */
15 #define GPIO_PORT_PIN_NUM (32U)
16 #define GPIO_PORT_SHIFT_BITS (5U)
17 #define GPIO_PORT_MASK (0x1FU)
18 /* GPIO port access offset unit */
19 #define GPIO_8_BITS_OFFSET (8U)
20 #define GPIO_16_BITS_OFFSET (16U)
21 #define GPIO_32_BITS_OFFSET (32U)
22 
23 /* Access the correct register */
24 #define GPIO_SET_BIT(base, reg, index, bit) ((base->reg[index]) |= SET_MASK(bit))
25 #define GPIO_CLEAR_BIT(base, reg, index, bit) ((base->reg[index]) &= CLEAR_MASK(bit))
26 
27 #define GPIO_FLAG_INIT (1UL << 0)
28 
29 /* GPIO runtime context information */
30 typedef struct {
31 	sedi_gpio_event_cb_t cb_event;
32 	void *callback_param;
33 	uint8_t flag;
34 	uint32_t outpin_state[SEDI_GPIO_SOC_PORT_NUM];
35 } gpio_context_t;
36 
37 /* resource data structure */
38 typedef struct {
39 	sedi_gpio_regs_t *reg;
40 } gpio_resources_t;
41 
42 typedef enum {
43 	SEDI_GPIO_32BITS_ACCESS,
44 	SEDI_GPIO_16BITS_ACCESS,
45 	SEDI_GPIO_8BITS_ACCESS
46 } gpio_port_access_t;
47 
48 static const uint32_t gpio_port_access_mask[] = { 0xFFFFFFFFU, 0xFFFFU, 0xFFU };
49 
50 /* driver version */
51 static const sedi_driver_version_t driver_version = { SEDI_GPIO_API_VERSION,
52 						      SEDI_GPIO_DRIVER_VERSION };
53 
54 /* driver capabilities */
55 static sedi_gpio_capabilities_t driver_capabilities[SEDI_GPIO_NUM] = {
56 	{.support_pins_map = 0x3FFFFFFF},
57 };
58 
59 /* gpio instance to source mapping*/
60 static gpio_resources_t resources_map[SEDI_GPIO_NUM] = {
61 	{ .reg = (sedi_gpio_regs_t *)SEDI_IREG_BASE(GPIO, 0) },
62 };
63 
64 /* gpio context array */
65 static gpio_context_t gpio_context[SEDI_GPIO_NUM] = { 0 };
66 
gpio_set_power(IN sedi_gpio_t gpio_device,IN sedi_power_state_t state)67 static int32_t gpio_set_power(IN sedi_gpio_t gpio_device, IN sedi_power_state_t state)
68 {
69 	sedi_devid_t devid = SEDI_DEVID_GPIO0 + gpio_device;
70 	int32_t ret = SEDI_DRIVER_OK;
71 
72 	DBG_CHECK(gpio_device < SEDI_GPIO_NUM, SEDI_DRIVER_ERROR_PARAMETER);
73 
74 	switch (state) {
75 	case SEDI_POWER_FULL:
76 		sedi_pm_set_device_power(devid, SEDI_POWER_FULL);
77 		break;
78 	case SEDI_POWER_LOW:
79 	case SEDI_POWER_SUSPEND:
80 	case SEDI_POWER_FORCE_SUSPEND:
81 		/* Do nothing now, need to use gpio as wake up */
82 		break;
83 	case SEDI_POWER_OFF:
84 	default:
85 		ret = SEDI_DRIVER_ERROR_UNSUPPORTED;
86 		break;
87 	}
88 
89 	return ret;
90 }
91 
gpio_reset_register(IN sedi_gpio_t gpio_device)92 static void gpio_reset_register(IN sedi_gpio_t gpio_device)
93 {
94 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
95 	uint8_t i;
96 
97 	for (i = 0; i < SEDI_GPIO_SOC_PORT_NUM; i++) {
98 		reg->gpdr[i] = 0;
99 		reg->grer[i] = 0;
100 		reg->gfer[i] = 0;
101 		reg->gfbr[i] = 0;
102 		reg->gimr[i] = 0;
103 		/* Clear all status bits */
104 		reg->gisr[i] = 0xFFFFFFFF;
105 		reg->gwmr[i] = 0;
106 		/* Clear all status bits */
107 		reg->gwsr[i] = 0xFFFFFFFF;
108 	}
109 }
110 
gpio_write_pin_port(IN sedi_gpio_t gpio_device,IN gpio_port_access_t access_type,IN uint8_t group,IN sedi_gpio_pin_state_t state)111 static void gpio_write_pin_port(IN sedi_gpio_t gpio_device, IN gpio_port_access_t access_type,
112 				IN uint8_t group, IN sedi_gpio_pin_state_t state)
113 {
114 	uint8_t port = (group >> access_type);
115 	uint8_t offset_unit, offset;
116 	uint32_t pin_bit;
117 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
118 	gpio_context_t *context = &(gpio_context[gpio_device]);
119 
120 	if (access_type == SEDI_GPIO_8BITS_ACCESS) {
121 		offset_unit = GPIO_8_BITS_OFFSET;
122 	} else if (access_type == SEDI_GPIO_16BITS_ACCESS) {
123 		offset_unit = GPIO_16_BITS_OFFSET;
124 	} else {
125 		offset_unit = GPIO_32_BITS_OFFSET;
126 	}
127 
128 	offset = (group & (uint32_t)((1U << access_type) - 1U)) * offset_unit;
129 	pin_bit = (gpio_port_access_mask[access_type] << offset);
130 
131 	if (state == SEDI_GPIO_STATE_HIGH) {
132 		reg->gpsr[port] = pin_bit;
133 		context->outpin_state[port] |= pin_bit;
134 	} else {
135 		reg->gpcr[port] = pin_bit;
136 		context->outpin_state[port] &= (~pin_bit);
137 	}
138 }
139 
gpio_read_pin_port(IN sedi_gpio_t gpio_device,IN gpio_port_access_t access_type,IN uint8_t group)140 static uint32_t gpio_read_pin_port(IN sedi_gpio_t gpio_device, IN gpio_port_access_t access_type,
141 				   IN uint8_t group)
142 {
143 	uint8_t port = (group >> access_type);
144 	uint8_t offset_unit, offset;
145 	uint32_t pin_bit;
146 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
147 	sedi_gpio_capabilities_t cap;
148 
149 	/* The port return value will mask the pin maps */
150 	sedi_gpio_get_capabilities(gpio_device, &cap);
151 	if (access_type == SEDI_GPIO_8BITS_ACCESS) {
152 		offset_unit = GPIO_8_BITS_OFFSET;
153 	} else if (access_type == SEDI_GPIO_16BITS_ACCESS) {
154 		offset_unit = GPIO_16_BITS_OFFSET;
155 	} else {
156 		offset_unit = GPIO_32_BITS_OFFSET;
157 	}
158 
159 	offset = (group & (uint32_t)((1U << access_type) - 1U)) * offset_unit;
160 	pin_bit = (gpio_port_access_mask[access_type] << offset);
161 
162 	return (((reg->gplr[port] & pin_bit) >> offset) & cap.support_pins_map);
163 }
164 
gpio_isr(IN sedi_gpio_t gpio_device)165 void gpio_isr(IN sedi_gpio_t gpio_device)
166 {
167 	sedi_gpio_regs_t *gpio = resources_map[gpio_device].reg;
168 	gpio_context_t *context = &(gpio_context[gpio_device]);
169 	uint8_t i;
170 	uint32_t gisr;
171 	uint32_t gimr;
172 
173 	for (i = 0; i < SEDI_GPIO_SOC_PORT_NUM; i++) {
174 		gisr = gpio->gisr[i];
175 		gimr = gpio->gimr[i];
176 
177 		gisr &= gimr;
178 
179 		/* Clear the interrupts */
180 		gpio->gisr[i] = gisr;
181 
182 		if ((context->cb_event) && (gisr != 0)) {
183 			(context->cb_event)(gisr, i, context->callback_param);
184 		}
185 	}
186 }
187 
sedi_gpio_get_version(void)188 sedi_driver_version_t sedi_gpio_get_version(void)
189 {
190 	return driver_version;
191 }
192 
sedi_gpio_get_capabilities(IN sedi_gpio_t gpio_device,OUT sedi_gpio_capabilities_t * cap)193 int32_t sedi_gpio_get_capabilities(IN sedi_gpio_t gpio_device, OUT sedi_gpio_capabilities_t *cap)
194 {
195 	DBG_CHECK(gpio_device < SEDI_GPIO_NUM, SEDI_DRIVER_ERROR_PARAMETER);
196 
197 	if (sedi_dev_is_self_owned(SEDI_DEVID_GPIO0 + gpio_device)) {
198 		driver_capabilities[gpio_device].is_available = 1;
199 	} else {
200 		driver_capabilities[gpio_device].is_available = 0;
201 	}
202 
203 	*cap = driver_capabilities[gpio_device];
204 
205 	return SEDI_DRIVER_OK;
206 }
207 
sedi_gpio_init(IN sedi_gpio_t gpio_device,IN sedi_gpio_event_cb_t cb,INOUT void * param)208 int32_t sedi_gpio_init(IN sedi_gpio_t gpio_device, IN sedi_gpio_event_cb_t cb, INOUT void *param)
209 {
210 	DBG_CHECK(gpio_device < SEDI_GPIO_NUM, SEDI_DRIVER_ERROR_PARAMETER);
211 
212 	if (!sedi_dev_is_self_owned(SEDI_DEVID_GPIO0 + gpio_device)) {
213 		return SEDI_DRIVER_ERROR_NO_DEV;
214 	}
215 
216 	if (gpio_context[gpio_device].flag == GPIO_FLAG_INIT)
217 		return SEDI_DRIVER_ERROR_BUSY;
218 
219 	/* Set all registers to default state */
220 	gpio_reset_register(gpio_device);
221 
222 	/* Register callback for GPIO */
223 	gpio_context[gpio_device].cb_event = cb;
224 	gpio_context[gpio_device].callback_param = param;
225 
226 	/* Set flag to init */
227 	gpio_context[gpio_device].flag = GPIO_FLAG_INIT;
228 
229 	return SEDI_DRIVER_OK;
230 }
231 
sedi_gpio_uninit(IN sedi_gpio_t gpio_device)232 int32_t sedi_gpio_uninit(IN sedi_gpio_t gpio_device)
233 {
234 	DBG_CHECK(gpio_device < SEDI_GPIO_NUM, SEDI_DRIVER_ERROR_PARAMETER);
235 
236 	gpio_context_t *context = &(gpio_context[gpio_device]);
237 	uint8_t i;
238 
239 	/* Clear the internal context */
240 	context->cb_event = NULL;
241 	context->callback_param = NULL;
242 	context->flag = 0;
243 	for (i = 0; i < SEDI_GPIO_SOC_PORT_NUM; i++) {
244 		context->outpin_state[i] = 0;
245 	}
246 
247 	/* Set all registers to default state */
248 	gpio_reset_register(gpio_device);
249 
250 	return SEDI_DRIVER_OK;
251 }
252 
sedi_gpio_set_power(IN sedi_gpio_t gpio_device,IN sedi_power_state_t state)253 int32_t sedi_gpio_set_power(IN sedi_gpio_t gpio_device, IN sedi_power_state_t state)
254 {
255 	DBG_CHECK(gpio_device < SEDI_GPIO_NUM, SEDI_DRIVER_ERROR_PARAMETER);
256 
257 	return gpio_set_power(gpio_device, state);
258 }
259 
sedi_gpio_config_pin(IN sedi_gpio_t gpio_device,IN uint32_t pin,IN sedi_gpio_pin_config_t pin_config)260 void sedi_gpio_config_pin(IN sedi_gpio_t gpio_device, IN uint32_t pin,
261 			  IN sedi_gpio_pin_config_t pin_config)
262 {
263 	sedi_gpio_regs_t *base = resources_map[gpio_device].reg;
264 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
265 	uint8_t offset = pin & GPIO_PORT_MASK;
266 
267 	if (pin_config.direction == SEDI_GPIO_DIR_MODE_OUTPUT) {
268 		GPIO_SET_BIT(base, gpdr, port, offset);
269 	} else {
270 		GPIO_CLEAR_BIT(base, gpdr, port, offset);
271 
272 		/* Clear the interrupt mode first */
273 		GPIO_CLEAR_BIT(base, gfer, port, offset);
274 		GPIO_CLEAR_BIT(base, grer, port, offset);
275 
276 		if (pin_config.interrupt_mode & SEDI_GPIO_INT_MODE_FALLING_EDGE) {
277 			GPIO_SET_BIT(base, gfer, port, offset);
278 		}
279 
280 		if (pin_config.interrupt_mode & SEDI_GPIO_INT_MODE_RISING_EDGE) {
281 			GPIO_SET_BIT(base, grer, port, offset);
282 		}
283 
284 		if (pin_config.enable_interrupt) {
285 			GPIO_SET_BIT(base, gimr, port, offset);
286 		} else {
287 			GPIO_CLEAR_BIT(base, gimr, port, offset);
288 		}
289 
290 		if (pin_config.enable_wakeup) {
291 			GPIO_SET_BIT(base, gwmr, port, offset);
292 		} else {
293 			GPIO_CLEAR_BIT(base, gwmr, port, offset);
294 		}
295 	}
296 }
297 
sedi_gpio_write_pin(IN sedi_gpio_t gpio_device,IN uint32_t pin,IN sedi_gpio_pin_state_t pin_state)298 void sedi_gpio_write_pin(IN sedi_gpio_t gpio_device, IN uint32_t pin,
299 			 IN sedi_gpio_pin_state_t pin_state)
300 {
301 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
302 	uint8_t offset = pin & GPIO_PORT_MASK;
303 	uint32_t pin_bit = SET_MASK(offset);
304 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
305 	gpio_context_t *context = &(gpio_context[gpio_device]);
306 
307 	if (pin_state == SEDI_GPIO_STATE_HIGH) {
308 		reg->gpsr[port] = pin_bit;
309 		context->outpin_state[port] |= pin_bit;
310 	} else {
311 		reg->gpcr[port] = pin_bit;
312 		context->outpin_state[port] &= (~pin_bit);
313 	}
314 }
315 
sedi_gpio_write_pin_8bits(IN sedi_gpio_t gpio_device,IN uint8_t group,IN sedi_gpio_pin_state_t pin_state)316 void sedi_gpio_write_pin_8bits(IN sedi_gpio_t gpio_device, IN uint8_t group,
317 			       IN sedi_gpio_pin_state_t pin_state)
318 {
319 	gpio_write_pin_port(gpio_device, SEDI_GPIO_8BITS_ACCESS, group, pin_state);
320 }
321 
sedi_gpio_write_pin_16bits(IN sedi_gpio_t gpio_device,IN uint8_t group,IN sedi_gpio_pin_state_t pin_state)322 void sedi_gpio_write_pin_16bits(IN sedi_gpio_t gpio_device, IN uint8_t group,
323 				IN sedi_gpio_pin_state_t pin_state)
324 {
325 	gpio_write_pin_port(gpio_device, SEDI_GPIO_16BITS_ACCESS, group, pin_state);
326 }
327 
sedi_gpio_write_pin_32bits(IN sedi_gpio_t gpio_device,IN uint8_t group,IN sedi_gpio_pin_state_t pin_state)328 void sedi_gpio_write_pin_32bits(IN sedi_gpio_t gpio_device, IN uint8_t group,
329 				IN sedi_gpio_pin_state_t pin_state)
330 {
331 	gpio_write_pin_port(gpio_device, SEDI_GPIO_32BITS_ACCESS, group, pin_state);
332 }
333 
sedi_gpio_read_pin(IN sedi_gpio_t gpio_device,IN uint32_t pin)334 sedi_gpio_pin_state_t sedi_gpio_read_pin(IN sedi_gpio_t gpio_device, IN uint32_t pin)
335 {
336 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
337 	uint8_t offset = pin & GPIO_PORT_MASK;
338 	uint32_t pin_bit = SET_MASK(offset);
339 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
340 
341 	uint32_t pin_val = ((pin_bit & reg->gplr[port]) == pin_bit);
342 
343 	return pin_val ? SEDI_GPIO_STATE_HIGH : SEDI_GPIO_STATE_LOW;
344 }
345 
sedi_gpio_read_pin_8bits(IN sedi_gpio_t gpio_device,IN uint8_t group)346 uint8_t sedi_gpio_read_pin_8bits(IN sedi_gpio_t gpio_device, IN uint8_t group)
347 {
348 	return gpio_read_pin_port(gpio_device, SEDI_GPIO_8BITS_ACCESS, group);
349 }
350 
sedi_gpio_read_pin_16bits(IN sedi_gpio_t gpio_device,IN uint8_t group)351 uint16_t sedi_gpio_read_pin_16bits(IN sedi_gpio_t gpio_device, IN uint8_t group)
352 {
353 	return gpio_read_pin_port(gpio_device, SEDI_GPIO_16BITS_ACCESS, group);
354 }
355 
sedi_gpio_read_pin_32bits(IN sedi_gpio_t gpio_device,IN uint8_t group)356 uint32_t sedi_gpio_read_pin_32bits(IN sedi_gpio_t gpio_device, IN uint8_t group)
357 {
358 	return gpio_read_pin_port(gpio_device, SEDI_GPIO_32BITS_ACCESS, group);
359 }
360 
sedi_gpio_toggle_pin(IN sedi_gpio_t gpio_device,IN uint32_t pin)361 void sedi_gpio_toggle_pin(IN sedi_gpio_t gpio_device, IN uint32_t pin)
362 {
363 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
364 	uint8_t offset = pin & GPIO_PORT_MASK;
365 	uint32_t pin_bit = SET_MASK(offset);
366 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
367 	gpio_context_t *context = &(gpio_context[gpio_device]);
368 
369 	if (context->outpin_state[port] & pin_bit) {
370 		reg->gpcr[port] = pin_bit;
371 		context->outpin_state[port] &= ~pin_bit;
372 	} else {
373 		reg->gpsr[port] = pin_bit;
374 		context->outpin_state[port] |= pin_bit;
375 	}
376 }
377 
sedi_gpio_get_gisr(IN sedi_gpio_t gpio_device,IN sedi_gpio_port_t port)378 uint32_t sedi_gpio_get_gisr(IN sedi_gpio_t gpio_device, IN sedi_gpio_port_t port)
379 {
380 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
381 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
382 
383 	return reg->gisr[port];
384 }
385 
sedi_gpio_get_gwsr(IN sedi_gpio_t gpio_device,IN sedi_gpio_port_t port)386 uint32_t sedi_gpio_get_gwsr(IN sedi_gpio_t gpio_device, IN sedi_gpio_port_t port)
387 {
388 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
389 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
390 
391 	return reg->gwsr[port];
392 }
393 
sedi_gpio_clear_gisr(IN sedi_gpio_t gpio_device,IN sedi_gpio_port_t port,IN uint32_t val)394 void sedi_gpio_clear_gisr(IN sedi_gpio_t gpio_device, IN sedi_gpio_port_t port, IN uint32_t val)
395 {
396 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
397 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
398 
399 	/* The register is w1c */
400 	reg->gisr[port] = val;
401 }
402 
sedi_gpio_clear_gwsr(IN sedi_gpio_t gpio_device,IN sedi_gpio_port_t port,IN uint32_t val)403 void sedi_gpio_clear_gwsr(IN sedi_gpio_t gpio_device, IN sedi_gpio_port_t port, IN uint32_t val)
404 {
405 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
406 	sedi_gpio_regs_t *reg = resources_map[gpio_device].reg;
407 
408 	/* The register is w1c */
409 	reg->gwsr[port] = val;
410 }
411 
sedi_gpio_enable_interrupt(IN sedi_gpio_t gpio_device,IN uint32_t pin,bool enable)412 void sedi_gpio_enable_interrupt(IN sedi_gpio_t gpio_device, IN uint32_t pin, bool enable)
413 {
414 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
415 	sedi_gpio_regs_t *base = resources_map[gpio_device].reg;
416 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
417 	uint8_t offset = pin & GPIO_PORT_MASK;
418 
419 	if (enable) {
420 		GPIO_SET_BIT(base, gimr, port, offset);
421 	} else {
422 		GPIO_CLEAR_BIT(base, gimr, port, offset);
423 	}
424 }
425 
sedi_gpio_enable_wakeup(IN sedi_gpio_t gpio_device,IN uint32_t pin,bool enable)426 void sedi_gpio_enable_wakeup(IN sedi_gpio_t gpio_device, IN uint32_t pin, bool enable)
427 {
428 	SEDI_ASSERT(gpio_device < SEDI_GPIO_NUM);
429 	sedi_gpio_regs_t *base = resources_map[gpio_device].reg;
430 	uint8_t port = pin >> GPIO_PORT_SHIFT_BITS;
431 	uint8_t offset = pin & GPIO_PORT_MASK;
432 
433 	if (enable) {
434 		GPIO_SET_BIT(base, gwmr, port, offset);
435 	} else {
436 		GPIO_CLEAR_BIT(base, gwmr, port, offset);
437 	}
438 }
439