]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.c
Retarget Softconsole RISC-V demo from IGLOO2 to Renode as it can have more RAM and...
[freertos] / FreeRTOS / Demo / RISC-V_Renode_Emulator_SoftConsole / Microsemi_Code / drivers / CoreGPIO / core_gpio.c
1 /*******************************************************************************\r
2  * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.\r
3  * \r
4  * CoreGPIO bare metal driver implementation.\r
5  *\r
6  * SVN $Revision: 7964 $\r
7  * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $\r
8  */\r
9 #include "core_gpio.h"\r
10 #include "hal.h"\r
11 #include "hal_assert.h"\r
12 #include "coregpio_regs.h"\r
13 \r
14 /*-------------------------------------------------------------------------*//**\r
15  *\r
16  */\r
17 #define GPIO_INT_ENABLE_MASK        (uint32_t)0x00000008UL\r
18 #define OUTPUT_BUFFER_ENABLE_MASK   0x00000004UL\r
19 \r
20 \r
21 #define NB_OF_GPIO  32\r
22 \r
23 #define CLEAR_ALL_IRQ32     (uint32_t)0xFFFFFFFF\r
24 #define CLEAR_ALL_IRQ16     (uint16_t)0xFFFF\r
25 #define CLEAR_ALL_IRQ8      (uint8_t)0xFF\r
26 \r
27 /*-------------------------------------------------------------------------*//**\r
28  * GPIO_init()\r
29  * See "core_gpio.h" for details of how to use this function.\r
30  */\r
31 void GPIO_init\r
32 (\r
33     gpio_instance_t *   this_gpio,\r
34     addr_t              base_addr,\r
35     gpio_apb_width_t    bus_width\r
36 )\r
37 {\r
38     uint8_t i = 0;\r
39     addr_t cfg_reg_addr = base_addr;\r
40     \r
41     this_gpio->base_addr = base_addr;\r
42     this_gpio->apb_bus_width = bus_width;\r
43     \r
44     /* Clear configuration. */\r
45     for( i = 0, cfg_reg_addr = base_addr; i < NB_OF_GPIO; ++i )\r
46     {\r
47         HW_set_8bit_reg( cfg_reg_addr, 0 );\r
48         cfg_reg_addr += 4;\r
49     }\r
50     /* Clear any pending interrupts */\r
51     switch( this_gpio->apb_bus_width )\r
52     {\r
53         case GPIO_APB_32_BITS_BUS:\r
54             HAL_set_32bit_reg( this_gpio->base_addr, IRQ, CLEAR_ALL_IRQ32 );\r
55             break;\r
56             \r
57         case GPIO_APB_16_BITS_BUS:\r
58             HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, (uint16_t)CLEAR_ALL_IRQ16 );\r
59             HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, (uint16_t)CLEAR_ALL_IRQ16 );\r
60             break;\r
61             \r
62         case GPIO_APB_8_BITS_BUS:\r
63             HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, (uint8_t)CLEAR_ALL_IRQ8 );\r
64             HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, (uint8_t)CLEAR_ALL_IRQ8 );\r
65             HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, (uint8_t)CLEAR_ALL_IRQ8 );\r
66             HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, (uint8_t)CLEAR_ALL_IRQ8 );\r
67             break;\r
68             \r
69         default:\r
70             HAL_ASSERT(0);\r
71             break;\r
72     }\r
73 }\r
74 \r
75 /*-------------------------------------------------------------------------*//**\r
76  * GPIO_config\r
77  * See "core_gpio.h" for details of how to use this function.\r
78  */\r
79 void GPIO_config\r
80 (\r
81     gpio_instance_t *   this_gpio,\r
82     gpio_id_t           port_id,\r
83     uint32_t            config\r
84 )\r
85 {\r
86     HAL_ASSERT( port_id < NB_OF_GPIO );\r
87     \r
88     if ( port_id < NB_OF_GPIO )\r
89     {\r
90         uint32_t cfg_reg_addr = this_gpio->base_addr;\r
91         cfg_reg_addr += (port_id * 4);\r
92         HW_set_32bit_reg( cfg_reg_addr, config );\r
93         \r
94         /*\r
95          * Verify that the configuration was correctly written. Failure to read\r
96          * back the expected value may indicate that the GPIO port was configured\r
97          * as part of the hardware flow and cannot be modified through software.\r
98          * It may also indicate that the base address passed as parameter to\r
99          * GPIO_init() was incorrect.\r
100          */\r
101         HAL_ASSERT( HW_get_32bit_reg( cfg_reg_addr ) == config );\r
102     }\r
103 }\r
104 \r
105 /*-------------------------------------------------------------------------*//**\r
106  * GPIO_set_outputs\r
107  * See "core_gpio.h" for details of how to use this function.\r
108  */\r
109 void GPIO_set_outputs\r
110 (\r
111     gpio_instance_t *   this_gpio,\r
112     uint32_t            value\r
113 )\r
114 {\r
115     switch( this_gpio->apb_bus_width )\r
116     {\r
117         case GPIO_APB_32_BITS_BUS:\r
118             HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, value );\r
119             break;\r
120             \r
121         case GPIO_APB_16_BITS_BUS:\r
122             HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint16_t)value );\r
123             HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint16_t)(value >> 16) );\r
124             break;\r
125             \r
126         case GPIO_APB_8_BITS_BUS:\r
127             HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint8_t)value );\r
128             HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint8_t)(value >> 8) );\r
129             HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT2, (uint8_t)(value >> 16) );\r
130             HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT3, (uint8_t)(value >> 24) );\r
131             break;\r
132             \r
133         default:\r
134             HAL_ASSERT(0);\r
135             break;\r
136     }\r
137     \r
138     /*\r
139      * Verify that the output register was correctly written. Failure to read back\r
140      * the expected value may indicate that some of the GPIOs may not exist due to\r
141      * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
142      * It may also indicate that the base address or APB bus width passed as\r
143      * parameter to the GPIO_init() function do not match the hardware design.\r
144      */\r
145     HAL_ASSERT( GPIO_get_outputs( this_gpio ) == value );\r
146 }\r
147 \r
148 /*-------------------------------------------------------------------------*//**\r
149  * GPIO_get_inputs\r
150  * See "core_gpio.h" for details of how to use this function.\r
151  */\r
152 uint32_t GPIO_get_inputs\r
153 (\r
154     gpio_instance_t *   this_gpio\r
155 )\r
156 {\r
157     uint32_t gpio_in = 0;\r
158     \r
159     switch( this_gpio->apb_bus_width )\r
160     {\r
161         case GPIO_APB_32_BITS_BUS:\r
162             gpio_in = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_IN );\r
163             break;\r
164             \r
165         case GPIO_APB_16_BITS_BUS:\r
166             gpio_in |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN0 );\r
167             gpio_in |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 16);\r
168             break;\r
169             \r
170         case GPIO_APB_8_BITS_BUS:\r
171             gpio_in |= HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN0 );\r
172             gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 8);\r
173             gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN2 ) << 16);\r
174             gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN3 ) << 24);\r
175             break;\r
176             \r
177         default:\r
178             HAL_ASSERT(0);\r
179             break;\r
180     }\r
181     \r
182     return gpio_in;\r
183 }\r
184 \r
185 /*-------------------------------------------------------------------------*//**\r
186  * GPIO_get_outputs\r
187  * See "core_gpio.h" for details of how to use this function.\r
188  */\r
189 uint32_t GPIO_get_outputs\r
190 (\r
191     gpio_instance_t *   this_gpio\r
192 )\r
193 {\r
194     uint32_t gpio_out = 0;\r
195     \r
196     switch( this_gpio->apb_bus_width )\r
197     {\r
198         case GPIO_APB_32_BITS_BUS:\r
199             gpio_out = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );\r
200             break;\r
201             \r
202         case GPIO_APB_16_BITS_BUS:\r
203             gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );\r
204             gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 16);\r
205             break;\r
206             \r
207         case GPIO_APB_8_BITS_BUS:\r
208             gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );\r
209             gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 8);\r
210             gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT2 ) << 16);\r
211             gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT3 ) << 24);\r
212             break;\r
213             \r
214         default:\r
215             HAL_ASSERT(0);\r
216             break;\r
217     }\r
218     \r
219     return gpio_out;\r
220 }\r
221 \r
222 /*-------------------------------------------------------------------------*//**\r
223  * GPIO_set_output\r
224  * See "core_gpio.h" for details of how to use this function.\r
225  */\r
226 void GPIO_set_output\r
227 (\r
228     gpio_instance_t *   this_gpio,\r
229     gpio_id_t           port_id,\r
230     uint8_t             value\r
231 )\r
232 {\r
233     HAL_ASSERT( port_id < NB_OF_GPIO );\r
234     \r
235             \r
236     switch( this_gpio->apb_bus_width )\r
237     {\r
238         case GPIO_APB_32_BITS_BUS:\r
239             {\r
240                 uint32_t outputs_state;\r
241                 \r
242                 outputs_state = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );\r
243                 if ( 0 == value )\r
244                 {\r
245                     outputs_state &= ~(1 << port_id);\r
246                 }\r
247                 else\r
248                 {\r
249                     outputs_state |= 1 << port_id;\r
250                 }\r
251                 HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, outputs_state );\r
252                 \r
253                 /*\r
254                  * Verify that the output register was correctly written. Failure to read back\r
255                  * the expected value may indicate that some of the GPIOs may not exist due to\r
256                  * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
257                  * It may also indicate that the base address or APB bus width passed as\r
258                  * parameter to the GPIO_init() function do not match the hardware design.\r
259                  */\r
260                 HAL_ASSERT( HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT ) == outputs_state );\r
261             }\r
262             break;\r
263             \r
264         case GPIO_APB_16_BITS_BUS:\r
265             {\r
266                 uint16_t outputs_state;\r
267                 uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 4) * 4);\r
268                 \r
269                 outputs_state = HW_get_16bit_reg( gpio_out_reg_addr );\r
270                 if ( 0 == value )\r
271                 {\r
272                     outputs_state &= ~(1 << (port_id & 0x0F));\r
273                 }\r
274                 else\r
275                 {\r
276                     outputs_state |= 1 << (port_id & 0x0F);\r
277                 }\r
278                 HW_set_16bit_reg( gpio_out_reg_addr, outputs_state );\r
279                 \r
280                 /*\r
281                  * Verify that the output register was correctly written. Failure to read back\r
282                  * the expected value may indicate that some of the GPIOs may not exist due to\r
283                  * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
284                  * It may also indicate that the base address or APB bus width passed as\r
285                  * parameter to the GPIO_init() function do not match the hardware design.\r
286                  */\r
287                 HAL_ASSERT( HW_get_16bit_reg( gpio_out_reg_addr ) == outputs_state );\r
288             }\r
289             break;\r
290             \r
291         case GPIO_APB_8_BITS_BUS:\r
292             {\r
293                 uint8_t outputs_state;\r
294                 uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 3) * 4);\r
295                 \r
296                 outputs_state = HW_get_8bit_reg( gpio_out_reg_addr );\r
297                 if ( 0 == value )\r
298                 {\r
299                     outputs_state &= ~(1 << (port_id & 0x07));\r
300                 }\r
301                 else\r
302                 {\r
303                     outputs_state |= 1 << (port_id & 0x07);\r
304                 }\r
305                 HW_set_8bit_reg( gpio_out_reg_addr, outputs_state );\r
306                 \r
307                 /*\r
308                  * Verify that the output register was correctly written. Failure to read back\r
309                  * the expected value may indicate that some of the GPIOs may not exist due to\r
310                  * the number of GPIOs selected in the CoreGPIO hardware flow configuration.\r
311                  * It may also indicate that the base address or APB bus width passed as\r
312                  * parameter to the GPIO_init() function do not match the hardware design.\r
313                  */\r
314                 HAL_ASSERT( HW_get_8bit_reg( gpio_out_reg_addr ) == outputs_state );\r
315             }\r
316             break;\r
317             \r
318         default:\r
319             HAL_ASSERT(0);\r
320             break;\r
321     }\r
322 }\r
323 \r
324 /*-------------------------------------------------------------------------*//**\r
325  * GPIO_drive_inout\r
326  * See "core_gpio.h" for details of how to use this function.\r
327  */\r
328 void GPIO_drive_inout\r
329 (\r
330     gpio_instance_t *   this_gpio,\r
331     gpio_id_t           port_id,\r
332     gpio_inout_state_t  inout_state\r
333 )\r
334 {\r
335     uint32_t config;\r
336     uint32_t cfg_reg_addr = this_gpio->base_addr;\r
337     \r
338     HAL_ASSERT( port_id < NB_OF_GPIO );\r
339 \r
340     switch( inout_state )\r
341     {\r
342         case GPIO_DRIVE_HIGH:\r
343             /* Set output high */\r
344             GPIO_set_output( this_gpio, port_id, 1 );\r
345             \r
346             /* Enable output buffer */\r
347             cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
348             config = HW_get_8bit_reg( cfg_reg_addr );\r
349             config |= OUTPUT_BUFFER_ENABLE_MASK;\r
350             HW_set_8bit_reg( cfg_reg_addr, config );\r
351             break;\r
352             \r
353         case GPIO_DRIVE_LOW:\r
354             /* Set output low */\r
355             GPIO_set_output( this_gpio, port_id, 0 );\r
356             \r
357             /* Enable output buffer */\r
358             cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
359             config = HW_get_8bit_reg( cfg_reg_addr );\r
360             config |= OUTPUT_BUFFER_ENABLE_MASK;\r
361             HW_set_8bit_reg( cfg_reg_addr, config );\r
362             break;\r
363             \r
364         case GPIO_HIGH_Z:\r
365             /* Disable output buffer */\r
366             cfg_reg_addr = this_gpio->base_addr + (port_id * 4);\r
367             config = HW_get_8bit_reg( cfg_reg_addr );\r
368             config &= ~OUTPUT_BUFFER_ENABLE_MASK;\r
369             HW_set_8bit_reg( cfg_reg_addr, config );\r
370             break;\r
371             \r
372         default:\r
373             HAL_ASSERT(0);\r
374             break;\r
375     }\r
376 }\r
377 \r
378 /*-------------------------------------------------------------------------*//**\r
379  * GPIO_enable_irq\r
380  * See "core_gpio.h" for details of how to use this function.\r
381  */\r
382 void GPIO_enable_irq\r
383 (\r
384     gpio_instance_t *   this_gpio,\r
385     gpio_id_t           port_id\r
386 )\r
387 {\r
388     uint32_t cfg_value;\r
389     uint32_t cfg_reg_addr = this_gpio->base_addr;\r
390    \r
391     HAL_ASSERT( port_id < NB_OF_GPIO );\r
392     \r
393     if ( port_id < NB_OF_GPIO )\r
394     {\r
395         cfg_reg_addr += (port_id * 4);\r
396         cfg_value = HW_get_8bit_reg( cfg_reg_addr );\r
397         cfg_value |= GPIO_INT_ENABLE_MASK;\r
398         HW_set_8bit_reg( cfg_reg_addr, cfg_value );\r
399     }\r
400 }\r
401 \r
402 /*-------------------------------------------------------------------------*//**\r
403  * GPIO_disable_irq\r
404  * See "core_gpio.h" for details of how to use this function.\r
405  */\r
406 void GPIO_disable_irq\r
407 (\r
408     gpio_instance_t *   this_gpio,\r
409     gpio_id_t           port_id\r
410 )\r
411 {\r
412     uint32_t cfg_value;\r
413     uint32_t cfg_reg_addr = this_gpio->base_addr;\r
414    \r
415     HAL_ASSERT( port_id < NB_OF_GPIO );\r
416     \r
417     if ( port_id < NB_OF_GPIO )\r
418     {\r
419         cfg_reg_addr += (port_id * 4);\r
420         cfg_value = HW_get_8bit_reg( cfg_reg_addr );\r
421         cfg_value &= ~GPIO_INT_ENABLE_MASK;\r
422         HW_set_8bit_reg( cfg_reg_addr, cfg_value );\r
423     }\r
424 }\r
425 \r
426 /*-------------------------------------------------------------------------*//**\r
427  * GPIO_clear_irq\r
428  * See "core_gpio.h" for details of how to use this function.\r
429  */\r
430 void GPIO_clear_irq\r
431 (\r
432     gpio_instance_t *   this_gpio,\r
433     gpio_id_t           port_id\r
434 )\r
435 {\r
436     uint32_t irq_clr_value = ((uint32_t)1) << ((uint32_t)port_id);\r
437     \r
438     switch( this_gpio->apb_bus_width )\r
439     {\r
440         case GPIO_APB_32_BITS_BUS:\r
441             HAL_set_32bit_reg( this_gpio->base_addr, IRQ, irq_clr_value );\r
442             break;\r
443             \r
444         case GPIO_APB_16_BITS_BUS:\r
445             HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );\r
446             HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 16 );\r
447             break;\r
448             \r
449         case GPIO_APB_8_BITS_BUS:\r
450             HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );\r
451             HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 8 );\r
452             HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, irq_clr_value >> 16 );\r
453             HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, irq_clr_value >> 24 );\r
454             break;\r
455             \r
456         default:\r
457             HAL_ASSERT(0);\r
458             break;\r
459     }\r
460 }\r
461 \r