1 /*
2 * SPDX-License-Identifier: Apache-2.0
3 * Copyright (c) 2024 sensry.io
4 */
5
6 #include "soc.h"
7 #include "udma.h"
8
9 #define SY1XX_UDMA_CTRL_PER_CG (SY1XX_ARCHI_UDMA_ADDR + SY1XX_UDMA_CONF_OFFSET)
10
11 #define SY1XX_MAX_UART_COUNT 3
12 #define SY1XX_MAX_I2C_COUNT 4
13 #define SY1XX_MAX_SPI_COUNT 7
14 #define SY1XX_MAX_ETH_COUNT 1
15
sy1xx_udma_enable_clock(sy1xx_udma_module_t module,uint32_t instance)16 void sy1xx_udma_enable_clock(sy1xx_udma_module_t module, uint32_t instance)
17 {
18
19 uint32_t udma_ctrl_per_cg = sys_read32(SY1XX_UDMA_CTRL_PER_CG);
20
21 switch (module) {
22
23 case SY1XX_UDMA_MODULE_UART:
24 if (instance >= SY1XX_MAX_UART_COUNT) {
25 return;
26 }
27 udma_ctrl_per_cg |= 1 << (instance + 0);
28 break;
29
30 case SY1XX_UDMA_MODULE_I2C:
31 if (instance >= SY1XX_MAX_I2C_COUNT) {
32 return;
33 }
34 udma_ctrl_per_cg |= 1 << (instance + 10);
35 break;
36
37 case SY1XX_UDMA_MODULE_SPI:
38 if (instance >= SY1XX_MAX_SPI_COUNT) {
39 return;
40 }
41 udma_ctrl_per_cg |= 1 << (instance + 3);
42 break;
43
44 case SY1XX_UDMA_MODULE_MAC:
45 if (instance >= SY1XX_MAX_ETH_COUNT) {
46 return;
47 }
48 udma_ctrl_per_cg |= 1 << (instance + 20);
49 break;
50
51 case SY1XX_UDMA_MAX_MODULE_COUNT:
52 break;
53 }
54
55 sys_write32(udma_ctrl_per_cg, SY1XX_UDMA_CTRL_PER_CG);
56 }
57
sy1xx_udma_disable_clock(sy1xx_udma_module_t module,uint32_t instance)58 void sy1xx_udma_disable_clock(sy1xx_udma_module_t module, uint32_t instance)
59 {
60
61 uint32_t udma_ctrl_per_cg = sys_read32(SY1XX_UDMA_CTRL_PER_CG);
62
63 switch (module) {
64
65 case SY1XX_UDMA_MODULE_UART:
66 if (instance >= SY1XX_MAX_UART_COUNT) {
67 return;
68 }
69 udma_ctrl_per_cg &= ~(1 << (instance + 0));
70 break;
71
72 case SY1XX_UDMA_MODULE_I2C:
73 if (instance >= SY1XX_MAX_I2C_COUNT) {
74 return;
75 }
76 udma_ctrl_per_cg &= ~(1 << (instance + 10));
77 break;
78
79 case SY1XX_UDMA_MODULE_SPI:
80 if (instance >= SY1XX_MAX_SPI_COUNT) {
81 return;
82 }
83 udma_ctrl_per_cg &= ~(1 << (instance + 3));
84 break;
85
86 case SY1XX_UDMA_MODULE_MAC:
87 if (instance >= SY1XX_MAX_ETH_COUNT) {
88 return;
89 }
90 udma_ctrl_per_cg &= ~(1 << (instance + 20));
91 break;
92
93 case SY1XX_UDMA_MAX_MODULE_COUNT:
94 break;
95 }
96
97 sys_write32(udma_ctrl_per_cg, SY1XX_UDMA_CTRL_PER_CG);
98 }
99
sy1xx_udma_busy_delay(uint32_t msec)100 void sy1xx_udma_busy_delay(uint32_t msec)
101 {
102 uint32_t sec = 250000000;
103 uint32_t millis = (sec / 1000) * msec;
104
105 for (uint32_t i = 0; i < millis; i++) {
106 __asm__("nop");
107 }
108 }
109
sy1xx_udma_cancel(uint32_t base,uint32_t channel)110 int32_t sy1xx_udma_cancel(uint32_t base, uint32_t channel)
111 {
112 uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
113
114 /* clear existing */
115 SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_CFG_REG + channel_offset,
116 SY1XX_UDMA_CHANNEL_CFG_CLEAR);
117 return 0;
118 }
119
sy1xx_udma_is_ready(uint32_t base,uint32_t channel)120 int32_t sy1xx_udma_is_ready(uint32_t base, uint32_t channel)
121 {
122 uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
123
124 int32_t isBusy = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + channel_offset) &
125 (SY1XX_UDMA_CHANNEL_CFG_EN);
126
127 return isBusy ? 0 : 1;
128 }
129
sy1xx_udma_wait_for_finished(uint32_t base,uint32_t channel)130 int32_t sy1xx_udma_wait_for_finished(uint32_t base, uint32_t channel)
131 {
132 uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
133
134 volatile uint32_t timeout = 200;
135
136 while (SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + channel_offset) &
137 (SY1XX_UDMA_CHANNEL_CFG_EN)) {
138 sy1xx_udma_busy_delay(1);
139 timeout--;
140 if (timeout == 0) {
141 return -1;
142 }
143 }
144
145 return 0;
146 }
147
sy1xx_udma_wait_for_status(uint32_t base)148 int32_t sy1xx_udma_wait_for_status(uint32_t base)
149 {
150
151 volatile uint32_t timeout = 200;
152
153 while (SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_STATUS) & (0x3)) {
154 sy1xx_udma_busy_delay(1);
155 timeout--;
156 if (timeout == 0) {
157 return -1;
158 }
159 }
160
161 return 0;
162 }
163
sy1xx_udma_start(uint32_t base,uint32_t channel,uint32_t saddr,uint32_t size,uint32_t optional_cfg)164 int32_t sy1xx_udma_start(uint32_t base, uint32_t channel, uint32_t saddr, uint32_t size,
165 uint32_t optional_cfg)
166 {
167 uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
168
169 SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_SADDR_REG + channel_offset, saddr);
170 SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_SIZE_REG + channel_offset, size);
171 SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_CFG_REG + channel_offset,
172 SY1XX_UDMA_CHANNEL_CFG_EN | optional_cfg);
173
174 return 0;
175 }
176
sy1xx_udma_get_remaining(uint32_t base,uint32_t channel)177 int32_t sy1xx_udma_get_remaining(uint32_t base, uint32_t channel)
178 {
179 uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
180
181 int32_t size = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_SIZE_REG + channel_offset);
182
183 return size;
184 }
185