1 /*
2 * Copyright (c) 2022 HPMicro
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "device_resource_if.h"
19 #include "hdf_device_desc.h"
20 #include "osal_sem.h"
21 #include "osal_mem.h"
22 #include "hdf_log.h"
23 #include "uart_if.h"
24 #include "uart_core.h"
25 #include "hpm_uart_drv.h"
26 #include <los_interrupt.h>
27
28 #define HDF_LOG_TAG HPMICRO_UART_HDF
29 #define HPM_QUEUE_SIZE 64
30
31 struct UartQueue {
32 uint8_t buf[HPM_QUEUE_SIZE];
33 uint16_t wr;
34 uint16_t rd;
35 };
36
37 struct HPMUartDevice {
38 struct OsalSem rxSem;
39 struct UartQueue rxQueue;
40 uint32_t id;
41 uint32_t base;
42 uint32_t irq;
43 uint32_t clkFreq;
44 struct UartAttribute attribute;
45 uint32_t baudRate;
46 uint8_t isRxBlock;
47 uint8_t isRxDmaEn;
48 uint8_t isTxDmaEn;
49 };
50
queue_get_cnt(struct UartQueue * q)51 static uint32_t queue_get_cnt(struct UartQueue *q)
52 {
53 return (q->wr + HPM_QUEUE_SIZE - q->rd) % HPM_QUEUE_SIZE;
54 }
55
queue_push(struct UartQueue * q,uint8_t * data,uint16_t len)56 static int queue_push(struct UartQueue *q, uint8_t *data, uint16_t len)
57 {
58 uint32_t save = LOS_IntLock();
59 for (int i = 0; i < len; i++) {
60 q->buf[q->wr] = data[i];
61 q->wr++;
62 q->wr %= HPM_QUEUE_SIZE;
63
64 /* overflow */
65 if (q->wr == q->rd) {
66 q->rd++;
67 q->wr %= HPM_QUEUE_SIZE;
68 }
69 }
70 LOS_IntRestore(save);
71
72 return 0;
73 }
74
queue_pop(struct UartQueue * q,uint8_t * data,uint16_t len)75 static uint16_t queue_pop(struct UartQueue *q, uint8_t *data, uint16_t len)
76 {
77 uint32_t save = LOS_IntLock();
78 uint32_t max = queue_get_cnt(q);
79
80 max = max > len? len : max;
81
82 for (int i = 0; i < max; i++) {
83 data[i] = q->buf[q->rd];
84 q->rd++;
85 q->rd %= HPM_QUEUE_SIZE;
86 }
87
88 LOS_IntRestore(save);
89 return max;
90 }
91
HpmUartIsr(VOID * parm)92 static __attribute__((section(".interrupt.text"))) VOID HpmUartIsr(VOID *parm)
93 {
94 struct UartHost *host = (struct UartHost *)parm;
95 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
96 UART_Type *base = (UART_Type *)hpmUartDev->base;
97
98 if (uart_get_irq_id(base) & uart_intr_id_rx_data_avail) {
99 uint8_t c;
100 if (status_success == uart_receive_byte(base, &c)) {
101 queue_push(&hpmUartDev->rxQueue, &c, 1);
102 OsalSemPost(&hpmUartDev->rxSem);
103 }
104 }
105 }
106
UartConfig(struct UartHost * host)107 static void UartConfig(struct UartHost *host)
108 {
109 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
110 UART_Type *base = (UART_Type *)hpmUartDev->base;
111 uart_disable_irq(base, uart_intr_rx_data_avail_or_timeout);
112
113 uart_config_t config = {0};
114
115 uart_default_config(base, &config);
116 config.src_freq_in_hz = hpmUartDev->clkFreq; /* IP freq in HZ*/
117 config.baudrate = hpmUartDev->baudRate;
118
119 if (hpmUartDev->attribute.dataBits == UART_ATTR_DATABIT_7) {
120 config.word_length = word_length_7_bits;
121 } else if (hpmUartDev->attribute.dataBits == UART_ATTR_DATABIT_6) {
122 config.word_length = word_length_6_bits;
123 } else if (hpmUartDev->attribute.dataBits == UART_ATTR_DATABIT_5) {
124 config.word_length = word_length_5_bits;
125 } else {
126 config.word_length = word_length_8_bits;
127 }
128
129 if (hpmUartDev->attribute.stopBits == UART_ATTR_STOPBIT_1P5) {
130 config.num_of_stop_bits = stop_bits_1_5;
131 } else if (hpmUartDev->attribute.stopBits == UART_ATTR_STOPBIT_2) {
132 config.num_of_stop_bits = stop_bits_2;
133 } else {
134 config.num_of_stop_bits = stop_bits_1;
135 }
136
137 if (hpmUartDev->attribute.parity == UART_ATTR_PARITY_ODD) {
138 config.parity = parity_odd;
139 } else if (hpmUartDev->attribute.parity == UART_ATTR_PARITY_EVEN) {
140 config.parity = parity_even;
141 } else if (hpmUartDev->attribute.parity == UART_ATTR_PARITY_MARK) {
142 config.parity = parity_always_1;
143 } else if (hpmUartDev->attribute.parity == UART_ATTR_PARITY_SPACE) {
144 config.parity = parity_always_0;
145 } else {
146 config.parity = parity_none;
147 }
148
149 uart_init(base, &config);
150 uart_enable_irq(base, uart_intr_rx_data_avail_or_timeout);
151 }
152
Init(struct UartHost * host)153 static int32_t Init(struct UartHost *host)
154 {
155 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
156
157 hpmUartDev->baudRate = 115200;
158 hpmUartDev->isRxBlock = 1;
159 hpmUartDev->isRxDmaEn = 0;
160 hpmUartDev->isTxDmaEn = 0;
161 hpmUartDev->rxQueue.rd = 0;
162 hpmUartDev->rxQueue.wr = 0;
163 hpmUartDev->attribute.dataBits = UART_ATTR_DATABIT_8;
164 hpmUartDev->attribute.parity = UART_ATTR_PARITY_NONE;
165 hpmUartDev->attribute.stopBits = UART_ATTR_STOPBIT_1;
166 hpmUartDev->attribute.rts = UART_ATTR_RTS_DIS;
167 hpmUartDev->attribute.cts = UART_ATTR_CTS_DIS;
168
169 UartConfig(host);
170
171 return 0;
172 }
173
Deinit(struct UartHost * host)174 static int32_t Deinit(struct UartHost *host)
175 {
176 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
177 UART_Type *base = (UART_Type *)hpmUartDev->base;
178 uart_disable_irq(base, uart_intr_rx_data_avail_or_timeout);
179
180 return 0;
181 }
182
Read(struct UartHost * host,uint8_t * data,uint32_t size)183 static int32_t Read(struct UartHost *host, uint8_t *data, uint32_t size)
184 {
185 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
186
187 if (hpmUartDev->isRxBlock) {
188 while (queue_get_cnt(&hpmUartDev->rxQueue) < size) {
189 OsalSemWait(&hpmUartDev->rxSem, 10000);
190 }
191 }
192
193 return queue_pop(&hpmUartDev->rxQueue, data, size);
194 }
195
Write(struct UartHost * host,uint8_t * data,uint32_t size)196 static int32_t Write(struct UartHost *host, uint8_t *data, uint32_t size)
197 {
198 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
199 UART_Type *base = (UART_Type *)hpmUartDev->base;
200
201 uart_send_data(base, data, size);
202
203 return size;
204 }
205
GetBaud(struct UartHost * host,uint32_t * baudRate)206 static int32_t GetBaud(struct UartHost *host, uint32_t *baudRate)
207 {
208 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
209 *baudRate = hpmUartDev->baudRate;
210
211 return 0;
212 }
213
SetBaud(struct UartHost * host,uint32_t baudRate)214 static int32_t SetBaud(struct UartHost *host, uint32_t baudRate)
215 {
216 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
217 hpmUartDev->baudRate = baudRate;
218 UartConfig(host);
219
220 return 0;
221 }
222
GetAttribute(struct UartHost * host,struct UartAttribute * attribute)223 static int32_t GetAttribute(struct UartHost *host, struct UartAttribute *attribute)
224 {
225 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
226 *attribute = hpmUartDev->attribute;
227
228 return 0;
229 }
230
SetAttribute(struct UartHost * host,struct UartAttribute * attribute)231 static int32_t SetAttribute(struct UartHost *host, struct UartAttribute *attribute)
232 {
233 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
234 hpmUartDev->attribute = *attribute;
235 UartConfig(host);
236
237 return 0;
238 }
239
SetTransMode(struct UartHost * host,enum UartTransMode mode)240 static int32_t SetTransMode(struct UartHost *host, enum UartTransMode mode)
241 {
242 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
243
244 if (mode == UART_MODE_RD_BLOCK) {
245 hpmUartDev->isRxBlock = 1;
246 } else if (mode == UART_MODE_RD_NONBLOCK) {
247 hpmUartDev->isRxBlock = 0;
248 } else if (mode == UART_MODE_DMA_RX_EN) {
249 hpmUartDev->isRxDmaEn = 1;
250 } else if (mode == UART_MODE_DMA_RX_DIS) {
251 hpmUartDev->isRxDmaEn = 0;
252 } else if (mode == UART_MODE_DMA_TX_EN) {
253 hpmUartDev->isTxDmaEn = 1;
254 } else if (mode == UART_MODE_DMA_TX_DIS) {
255 hpmUartDev->isTxDmaEn = 0;
256 }
257
258 UartConfig(host);
259
260 return 0;
261 }
262
263 static struct UartHostMethod uartHostMethod = {
264 .Init = Init,
265 .Deinit = Deinit,
266 .Read = Read,
267 .Write = Write,
268 .GetBaud = GetBaud,
269 .SetBaud = SetBaud,
270 .GetAttribute = GetAttribute,
271 .SetAttribute = SetAttribute,
272 .SetTransMode = SetTransMode,
273 };
274
UartDriverBind(struct HdfDeviceObject * device)275 static int32_t UartDriverBind(struct HdfDeviceObject *device)
276 {
277 int32_t ret = HDF_SUCCESS;
278
279 struct UartHost *host = UartHostCreate(device);
280 if (host == NULL) {
281 ret = HDF_FAILURE;
282 HDF_LOGE("Bind: UartHostCreate null\n");
283 return ret;
284 }
285
286 HDF_LOGI("Bind: successed\n");
287 return ret;
288 }
289
UartDriverInit(struct HdfDeviceObject * device)290 static int32_t UartDriverInit(struct HdfDeviceObject *device)
291 {
292 int32_t ret = HDF_SUCCESS;
293
294 struct UartHost *host = UartHostFromDevice(device);
295 if (host == NULL) {
296 ret = HDF_FAILURE;
297 HDF_LOGE("Init: UartHostFromDevice null\n");
298 return ret;
299 }
300
301 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)OsalMemCalloc(
302 sizeof(struct HPMUartDevice));
303 if (hpmUartDev == NULL) {
304 ret = HDF_ERR_MALLOC_FAIL;
305 HDF_LOGE("Init: HPMUartDevice malloc Failed!!!\n");
306 goto ERROR1;
307 }
308
309 OsalSemInit(&hpmUartDev->rxSem, 0);
310
311 struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
312 if (dri == NULL) {
313 ret = HDF_FAILURE;
314 HDF_LOGE("Init: get DeviceResourceIface Failed!!!\n");
315 goto ERROR2;
316 }
317
318 dri->GetUint32(device->property, "id", &hpmUartDev->id, 0);
319 dri->GetUint32(device->property, "base", &hpmUartDev->base, 0);
320 dri->GetUint32(device->property, "irq_num", &hpmUartDev->irq, 0);
321 dri->GetUint32(device->property, "clk_freq", &hpmUartDev->clkFreq, 0);
322 HDF_LOGI("Init: hpmUartDev->id: %u\n", hpmUartDev->id);
323 HDF_LOGI("Init: hpmUartDev->base: 0x%X\n", hpmUartDev->base);
324 HDF_LOGI("Init: hpmUartDev->irq: %u\n", hpmUartDev->irq);
325 HDF_LOGI("Init: hpmUartDev->clkFreq: %u\n", hpmUartDev->clkFreq);
326
327 host->num = hpmUartDev->id;
328 host->priv = hpmUartDev;
329 host->method = &uartHostMethod;
330
331 HwiIrqParam irqParam;
332 irqParam.pDevId = host;
333 LOS_HwiCreate(HPM2LITEOS_IRQ(hpmUartDev->irq), 1, 0, (HWI_PROC_FUNC)HpmUartIsr, &irqParam);
334 LOS_HwiEnable(HPM2LITEOS_IRQ(hpmUartDev->irq));
335
336 return ret;
337
338 ERROR2:
339 OsalSemDestroy(&hpmUartDev->rxSem);
340 OsalMemFree(hpmUartDev);
341 ERROR1:
342 return ret;
343 }
344
UartDriverRelease(struct HdfDeviceObject * device)345 static void UartDriverRelease(struct HdfDeviceObject *device)
346 {
347 if (device == NULL) {
348 return;
349 }
350
351 struct UartHost *host = UartHostFromDevice(device);
352 if (host == NULL) {
353 HDF_LOGE("Release: UartHostFromDevice null\n");
354 return;
355 }
356
357 struct HPMUartDevice *hpmUartDev = (struct HPMUartDevice *)host->priv;
358
359 if (hpmUartDev) {
360 OsalSemDestroy(&hpmUartDev->rxSem);
361 OsalMemFree(hpmUartDev);
362 }
363
364 UartHostDestroy(host);
365
366 HDF_LOGI("Release");
367 return;
368 }
369
370
371 struct HdfDriverEntry g_uartDriverEntry = {
372 .moduleVersion = 1,
373 .moduleName = "HPMICRO_UART_MODULE_HDF",
374 .Bind = UartDriverBind,
375 .Init = UartDriverInit,
376 .Release = UartDriverRelease,
377 };
378
379 HDF_INIT(g_uartDriverEntry);