1 /*
2  * Copyright (c) 2022 Microchip Technology Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT microchip_mpfs_gpio
8 
9 #include <errno.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/irq.h>
15 
16 #include <zephyr/drivers/gpio/gpio_utils.h>
17 
18 
19 #define MSS_GPIO_INPUT_MODE               0x02
20 #define MSS_GPIO_OUTPUT_MODE              0x05
21 #define MSS_GPIO_INOUT_MODE               0x03
22 #define MSS_GPIO_IRQ_LEVEL_HIGH           0x00
23 #define MSS_GPIO_IRQ_LEVEL_LOW            0x20
24 #define MSS_GPIO_IRQ_EDGE_POSITIVE        0x40
25 #define MSS_GPIO_IRQ_EDGE_NEGATIVE        0x60
26 #define MSS_GPIO_IRQ_EDGE_BOTH            0x80
27 #define MSS_GPIO_INT_ENABLE_MASK          0x08
28 #define MSS_OUTPUT_BUFFER_ENABLE_MASK     0x04
29 
30 struct mss_gpio_t {
31 	uint32_t gpio_cfg[32];
32 	uint32_t gpio_irq;
33 	const uint32_t gpio_in;
34 	uint32_t gpio_out;
35 	uint32_t gpio_cfg_all;
36 	uint32_t gpio_cfg_byte[4];
37 	uint32_t gpio_clr_bits;
38 	uint32_t gpio_set_bits;
39 
40 };
41 
42 typedef void (*mss_gpio_cfg_func_t)(void);
43 
44 
45 struct mss_gpio_config {
46 	/* gpio_driver_config needs to be first */
47 	struct gpio_driver_config common;
48 	uintptr_t            gpio_base_addr;
49 	uint32_t                gpio_irq_base;
50 	mss_gpio_cfg_func_t    gpio_cfg_func;
51 };
52 
53 struct mss_gpio_data {
54 	/* gpio_driver_data needs to be first */
55 	struct gpio_driver_data common;
56 	/* list of callbacks */
57 	sys_slist_t cb;
58 };
59 
60 
61 /* Helper Macros for GPIO */
62 #define DEV_GPIO_CFG(dev)	\
63 	((const struct mss_gpio_config * const)(dev)->config)
64 #define DEV_GPIO(dev)	\
65 	((volatile struct mss_gpio_t *)(DEV_GPIO_CFG(dev))->gpio_base_addr)
66 #define DEV_GPIO_DATA(dev)	\
67 	((struct mss_gpio_data *)(dev)->data)
68 
69 
mss_gpio_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)70 static int mss_gpio_config(const struct device *dev,
71 					gpio_pin_t pin,
72 					gpio_flags_t flags)
73 {
74 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
75 	uint32_t io_flags = flags & (GPIO_INPUT | GPIO_OUTPUT);
76 
77 	if (io_flags == GPIO_DISCONNECTED) {
78 
79 		return -ENOTSUP;
80 	}
81 
82 	if (flags & GPIO_OUTPUT) {
83 
84 		gpio->gpio_cfg[pin] |= MSS_GPIO_OUTPUT_MODE;
85 
86 		if (flags & GPIO_OUTPUT_INIT_HIGH) {
87 			gpio->gpio_out |= BIT(pin);
88 
89 		} else if (flags & GPIO_OUTPUT_INIT_LOW) {
90 			gpio->gpio_out &= ~BIT(pin);
91 
92 		}
93 
94 	} else if (flags & GPIO_INPUT) {
95 		gpio->gpio_cfg[pin] |= MSS_GPIO_INPUT_MODE;
96 
97 	} else {
98 		return -ENOTSUP;
99 	}
100 
101 	return 0;
102 }
103 
mss_gpio_port_toggle_bits(const struct device * dev,gpio_port_pins_t mask)104 static int mss_gpio_port_toggle_bits(const struct device *dev,
105 					gpio_port_pins_t mask)
106 {
107 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
108 
109 	gpio->gpio_out ^= mask;
110 
111 	return 0;
112 }
113 
mss_gpio_port_get_raw(const struct device * dev,gpio_port_value_t * value)114 static int mss_gpio_port_get_raw(const struct device *dev,
115 					gpio_port_value_t *value)
116 {
117 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
118 
119 	*value = gpio->gpio_in;
120 
121 	return 0;
122 }
123 
mss_gpio_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)124 static int mss_gpio_port_set_masked_raw(const struct device *dev,
125 					   gpio_port_pins_t mask,
126 					   gpio_port_value_t value)
127 {
128 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
129 
130 	gpio->gpio_out = (gpio->gpio_out & ~mask) | (value & mask);
131 
132 	return 0;
133 }
134 
mss_gpio_port_set_bits_raw(const struct device * dev,gpio_port_pins_t mask)135 static int mss_gpio_port_set_bits_raw(const struct device *dev,
136 					 gpio_port_pins_t mask)
137 {
138 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
139 
140 	gpio->gpio_out |= mask;
141 
142 	return 0;
143 }
144 
mss_gpio_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t mask)145 static int mss_gpio_port_clear_bits_raw(const struct device *dev,
146 					   gpio_port_pins_t mask)
147 {
148 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
149 
150 	gpio->gpio_out &= ~mask;
151 
152 	return 0;
153 }
154 
mss_gpio_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)155 static int mss_gpio_pin_interrupt_configure(const struct device *dev,
156 						 gpio_pin_t pin,
157 						 enum gpio_int_mode mode,
158 						 enum gpio_int_trig trig)
159 {
160 	ARG_UNUSED(trig);
161 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
162 
163 	gpio->gpio_cfg[pin] |= (MSS_GPIO_INT_ENABLE_MASK);
164 
165 	switch (mode | trig) {
166 	case GPIO_INT_EDGE_BOTH:
167 		gpio->gpio_cfg[pin] |= (MSS_GPIO_IRQ_EDGE_BOTH);
168 		break;
169 	case GPIO_INT_EDGE_RISING:
170 		gpio->gpio_cfg[pin] |= (MSS_GPIO_IRQ_EDGE_POSITIVE);
171 		break;
172 	case GPIO_INT_EDGE_FALLING:
173 		gpio->gpio_cfg[pin] |= (MSS_GPIO_IRQ_EDGE_NEGATIVE);
174 		break;
175 	case GPIO_INT_LEVEL_LOW:
176 		gpio->gpio_cfg[pin] |= (MSS_GPIO_IRQ_LEVEL_LOW);
177 		break;
178 	case GPIO_INT_LEVEL_HIGH:
179 		gpio->gpio_cfg[pin] |= (MSS_GPIO_IRQ_LEVEL_HIGH);
180 		break;
181 	default:
182 		gpio->gpio_cfg[pin] &= ~MSS_GPIO_INT_ENABLE_MASK;
183 		break;
184 	}
185 	return 0;
186 }
187 
188 
mss_gpio_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)189 static int mss_gpio_manage_callback(const struct device *dev,
190 					   struct gpio_callback *callback,
191 					   bool set)
192 {
193 	struct mss_gpio_data *data = dev->data;
194 
195 	return gpio_manage_callback(&data->cb, callback, set);
196 }
197 static const struct gpio_driver_api mss_gpio_driver = {
198 	.pin_configure           = mss_gpio_config,
199 	.port_toggle_bits        = mss_gpio_port_toggle_bits,
200 	.port_get_raw            = mss_gpio_port_get_raw,
201 	.port_set_masked_raw     = mss_gpio_port_set_masked_raw,
202 	.port_set_bits_raw       = mss_gpio_port_set_bits_raw,
203 	.port_clear_bits_raw     = mss_gpio_port_clear_bits_raw,
204 	.pin_interrupt_configure = mss_gpio_pin_interrupt_configure,
205 	.manage_callback         = mss_gpio_manage_callback
206 };
207 
208 
mss_gpio_init(const struct device * dev)209 static int mss_gpio_init(const struct device *dev)
210 {
211 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
212 
213 	gpio->gpio_irq = 0xFFFFFFFFU;
214 
215 	const struct mss_gpio_config *cfg = DEV_GPIO_CFG(dev);
216 	/* Configure GPIO device */
217 	cfg->gpio_cfg_func();
218 	return 0;
219 }
220 
mss_gpio_irq_handler(const struct device * dev)221 static void mss_gpio_irq_handler(const struct device *dev)
222 {
223 	volatile struct mss_gpio_t *gpio = DEV_GPIO(dev);
224 	uint32_t interrupt_status = gpio->gpio_irq;
225 
226 	gpio->gpio_irq = gpio->gpio_irq;
227 	struct mss_gpio_data *data = dev->data;
228 
229 	gpio_fire_callbacks(&data->cb, dev, interrupt_status);
230 }
231 
232 #define MSS_GPIO_INIT(n)	\
233 	static struct mss_gpio_data mss_gpio_data_##n;	\
234 	static void gpio_mss_gpio_cfg_func_##n(void);	\
235 	\
236 	static const struct mss_gpio_config mss_gpio_config_##n = {	\
237 		.common = {	\
238 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
239 		},	\
240 		.gpio_base_addr = DT_INST_REG_ADDR(n),	\
241 		.gpio_irq_base  = DT_INST_IRQN(n),	\
242 		.gpio_cfg_func = gpio_mss_gpio_cfg_func_##n	\
243 	};	\
244 	\
245 	DEVICE_DT_INST_DEFINE(n,	\
246 				mss_gpio_init,	\
247 				NULL,	\
248 				&mss_gpio_data_##n, &mss_gpio_config_##n,	\
249 				PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY,	\
250 				&mss_gpio_driver);	\
251 	\
252 	static void gpio_mss_gpio_cfg_func_##n(void)	\
253 	{	\
254 		IRQ_CONNECT(DT_INST_IRQN(n),	\
255 				DT_INST_IRQ(n, priority),	\
256 				mss_gpio_irq_handler,	\
257 				DEVICE_DT_INST_GET(n),	\
258 				0);	\
259 		irq_enable(DT_INST_IRQN(n));	\
260 	}	\
261 
262 DT_INST_FOREACH_STATUS_OKAY(MSS_GPIO_INIT)
263