• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);