xref: /device/qemu/drivers/uart/uart.c (revision d6aed566)
1/*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 "los_event.h"
17#include "device_resource_if.h"
18#include "hdf_base.h"
19#include "hdf_log.h"
20#include "osal_io.h"
21#include "osal_mem.h"
22#include "osal_time.h"
23#include "uart_core.h"
24#include "uart_dev.h"
25#include "uart_if.h"
26#include "uart_pl011.h"
27
28#define HDF_LOG_TAG uart_hi35xx
29
30static int32_t Hi35xxRead(struct UartHost *host, uint8_t *data, uint32_t size)
31{
32    int32_t ret;
33    struct UartDriverData *udd = NULL;
34
35    if (host == NULL || host->priv == NULL) {
36        HDF_LOGE("%s: invalid parameter", __func__);
37        return HDF_ERR_INVALID_PARAM;
38    }
39    udd = (struct UartDriverData *)host->priv;
40    if (udd->state != UART_STATE_USEABLE) {
41        return HDF_FAILURE;
42    }
43    if ((udd->flags & UART_FLG_RD_BLOCK) && (PL011UartRxBufEmpty(udd))) {
44        (void)LOS_EventRead(&udd->wait.stEvent, 0x1, LOS_WAITMODE_OR, LOS_WAIT_FOREVER);
45    }
46    ret = Pl011Read(udd, (char *)data, size);
47    if ((udd->flags & UART_FLG_RD_BLOCK) && (PL011UartRxBufEmpty(udd))) {
48        (void)LOS_EventClear(&udd->wait.stEvent, ~(0x1));
49    }
50    return ret;
51}
52
53static int32_t Hi35xxWrite(struct UartHost *host, uint8_t *data, uint32_t size)
54{
55    int32_t ret;
56    struct UartDriverData *udd = NULL;
57
58    if (host == NULL || host->priv == NULL) {
59        HDF_LOGE("%s: invalid parameter", __func__);
60        return HDF_ERR_INVALID_PARAM;
61    }
62    udd = (struct UartDriverData *)host->priv;
63    if (udd->state != UART_STATE_USEABLE) {
64        return HDF_FAILURE;
65    }
66    if (udd->ops->StartTx != NULL) {
67        ret = udd->ops->StartTx(udd, (char *)data, size);
68    } else {
69        ret = HDF_ERR_NOT_SUPPORT;
70        HDF_LOGE("%s: not support", __func__);
71    }
72    return ret;
73}
74
75static int32_t Hi35xxGetBaud(struct UartHost *host, uint32_t *baudRate)
76{
77    struct UartDriverData *udd = NULL;
78
79    if (host == NULL || host->priv == NULL || baudRate == NULL) {
80        HDF_LOGE("%s: invalid parameter", __func__);
81        return HDF_ERR_INVALID_PARAM;
82    }
83
84    udd = (struct UartDriverData *)host->priv;
85    if (udd->state != UART_STATE_USEABLE) {
86        return HDF_FAILURE;
87    }
88    *baudRate = udd->baudrate;
89    return HDF_SUCCESS;
90}
91
92static int32_t Hi35xxSetBaud(struct UartHost *host, uint32_t baudRate)
93{
94    struct UartDriverData *udd = NULL;
95
96    if (host == NULL || host->priv == NULL) {
97        HDF_LOGE("%s: invalid parameter", __func__);
98        return HDF_ERR_INVALID_PARAM;
99    }
100
101    udd = (struct UartDriverData *)host->priv;
102    if (udd->state != UART_STATE_USEABLE) {
103        return HDF_FAILURE;
104    }
105    if ((baudRate > 0) && (baudRate <= CONFIG_MAX_BAUDRATE)) {
106        udd->baudrate = baudRate;
107        if (udd->ops->Config == NULL) {
108            HDF_LOGE("%s: not support", __func__);
109            return HDF_ERR_NOT_SUPPORT;
110        }
111        if (udd->ops->Config(udd) != HDF_SUCCESS) {
112            HDF_LOGE("%s: config baudrate %d failed", __func__, baudRate);
113            return HDF_FAILURE;
114        }
115    } else {
116        HDF_LOGE("%s: invalid baudrate, which is:%d", __func__, baudRate);
117        return HDF_FAILURE;
118    }
119    return HDF_SUCCESS;
120}
121
122static int32_t Hi35xxGetAttribute(struct UartHost *host, struct UartAttribute *attribute)
123{
124    struct UartDriverData *udd = NULL;
125
126    if (host == NULL || host->priv == NULL || attribute == NULL) {
127        HDF_LOGE("%s: invalid parameter", __func__);
128        return HDF_ERR_INVALID_PARAM;
129    }
130    udd = (struct UartDriverData *)host->priv;
131    if (udd->state != UART_STATE_USEABLE) {
132        return HDF_FAILURE;
133    }
134    attribute->cts = udd->attr.cts;
135    attribute->dataBits = udd->attr.dataBits;
136    attribute->fifoRxEn = udd->attr.fifoRxEn;
137    attribute->fifoTxEn = udd->attr.fifoTxEn;
138    attribute->parity = udd->attr.parity;
139    attribute->rts = udd->attr.rts;
140    attribute->stopBits = udd->attr.stopBits;
141    return HDF_SUCCESS;
142}
143
144static int32_t Hi35xxSetAttribute(struct UartHost *host, struct UartAttribute *attribute)
145{
146    struct UartDriverData *udd = NULL;
147
148    if (host == NULL || host->priv == NULL || attribute == NULL) {
149        HDF_LOGE("%s: invalid parameter", __func__);
150        return HDF_ERR_INVALID_PARAM;
151    }
152    udd = (struct UartDriverData *)host->priv;
153    if (udd->state != UART_STATE_USEABLE) {
154        return HDF_FAILURE;
155    }
156    udd->attr.cts = attribute->cts;
157    udd->attr.dataBits = attribute->dataBits;
158    udd->attr.fifoRxEn = attribute->fifoRxEn;
159    udd->attr.fifoTxEn = attribute->fifoTxEn;
160    udd->attr.parity = attribute->parity;
161    udd->attr.rts = attribute->rts;
162    udd->attr.stopBits = attribute->stopBits;
163    if (udd->ops->Config == NULL) {
164        HDF_LOGE("%s: not support", __func__);
165        return HDF_ERR_NOT_SUPPORT;
166    }
167    if (udd->ops->Config(udd) != HDF_SUCCESS) {
168        HDF_LOGE("%s: config failed", __func__);
169        return HDF_FAILURE;
170    }
171    return HDF_SUCCESS;
172}
173
174static int32_t Hi35xxSetTransMode(struct UartHost *host, enum UartTransMode mode)
175{
176    struct UartDriverData *udd = NULL;
177
178    if (host == NULL || host->priv == NULL) {
179        HDF_LOGE("%s: invalid parameter", __func__);
180        return HDF_ERR_INVALID_PARAM;
181    }
182    udd = (struct UartDriverData *)host->priv;
183    if (udd->state != UART_STATE_USEABLE) {
184        return HDF_FAILURE;
185    }
186    if (mode == UART_MODE_RD_BLOCK) {
187        udd->flags |= UART_FLG_RD_BLOCK;
188    } else if (mode == UART_MODE_RD_NONBLOCK) {
189        udd->flags &= ~UART_FLG_RD_BLOCK;
190        (void)LOS_EventWrite(&udd->wait.stEvent, 0x1);
191    }
192    return HDF_SUCCESS;
193}
194
195static int32_t Hi35xxInit(struct UartHost *host)
196{
197    int32_t ret = 0;
198    struct UartDriverData *udd = NULL;
199    struct wait_queue_head *wait = NULL;
200    if (host == NULL || host->priv == NULL) {
201        HDF_LOGE("%s: invalid parameter", __func__);
202        return HDF_ERR_INVALID_PARAM;
203    }
204
205    udd = (struct UartDriverData *)host->priv;
206    wait = &udd->wait;
207    if (udd->state == UART_STATE_NOT_OPENED) {
208        udd->state = UART_STATE_OPENING;
209        (void)LOS_EventInit(&wait->stEvent);
210        spin_lock_init(&wait->lock);
211        LOS_ListInit(&wait->poll_queue);
212        udd->rxTransfer = (struct UartTransfer *)OsalMemCalloc(sizeof(struct UartTransfer));
213        if (udd->rxTransfer == NULL) {
214            HDF_LOGE("%s: alloc transfer failed", __func__);
215            return HDF_ERR_MALLOC_FAIL;
216        }
217        if (udd->ops->StartUp == NULL) {
218            HDF_LOGE("%s: not support", __func__);
219            ret = HDF_ERR_NOT_SUPPORT;
220            goto FREE_TRANSFER;
221        }
222        if (udd->ops->StartUp(udd) != HDF_SUCCESS) {
223            HDF_LOGE("%s: StartUp failed", __func__);
224            ret = HDF_FAILURE;
225            goto FREE_TRANSFER;
226        }
227    }
228    udd->state = UART_STATE_USEABLE;
229    udd->count++;
230    return HDF_SUCCESS;
231
232FREE_TRANSFER:
233    (void)OsalMemFree(udd->rxTransfer);
234    udd->rxTransfer = NULL;
235    return ret;
236}
237
238static int32_t Hi35xxDeinit(struct UartHost *host)
239{
240    struct wait_queue_head *wait = NULL;
241    struct UartDriverData *udd = NULL;
242    if (host == NULL || host->priv == NULL) {
243        HDF_LOGE("%s: invalid parameter", __func__);
244        return HDF_ERR_INVALID_PARAM;
245    }
246
247    udd = (struct UartDriverData *)host->priv;
248    if ((--udd->count) != 0) {
249        return HDF_SUCCESS;
250    }
251    wait = &udd->wait;
252    if (udd->flags & UART_FLG_DMA_RX) {
253        if (udd->ops->DmaShutDown != NULL) {
254            udd->ops->DmaShutDown(udd, UART_DMA_DIR_RX);
255        }
256    }
257    if (udd->flags & UART_FLG_DMA_TX) {
258        if (udd->ops->DmaShutDown != NULL) {
259            udd->ops->DmaShutDown(udd, UART_DMA_DIR_TX);
260        }
261    }
262    LOS_ListDelete(&wait->poll_queue);
263    LOS_EventDestroy(&wait->stEvent);
264    if (udd->ops->ShutDown != NULL) {
265        udd->ops->ShutDown(udd);
266    }
267    if (udd->rxTransfer != NULL) {
268        (void)OsalMemFree(udd->rxTransfer);
269        udd->rxTransfer = NULL;
270    }
271    udd->state = UART_STATE_NOT_OPENED;
272    return HDF_SUCCESS;
273}
274
275static int32_t Hi35xxPollEvent(struct UartHost *host, void *filep, void *table)
276{
277    struct UartDriverData *udd = NULL;
278
279    if (host == NULL || host->priv == NULL) {
280        HDF_LOGE("%s: host is NULL", __func__);
281        return HDF_FAILURE;
282    }
283    udd = (struct UartDriverData *)host->priv;
284    if (UART_STATE_USEABLE != udd->state) {
285        return -EFAULT;
286    }
287
288    poll_wait((struct file *)filep, &udd->wait, (poll_table *)table);
289
290    if (!PL011UartRxBufEmpty(udd)) {
291        return POLLIN | POLLRDNORM;
292    }
293    return 0;
294}
295
296struct UartHostMethod g_uartHostMethod = {
297    .Init = Hi35xxInit,
298    .Deinit = Hi35xxDeinit,
299    .Read = Hi35xxRead,
300    .Write = Hi35xxWrite,
301    .SetBaud = Hi35xxSetBaud,
302    .GetBaud = Hi35xxGetBaud,
303    .SetAttribute = Hi35xxSetAttribute,
304    .GetAttribute = Hi35xxGetAttribute,
305    .SetTransMode = Hi35xxSetTransMode,
306    .pollEvent = Hi35xxPollEvent,
307};
308
309static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node)
310{
311    uint32_t tmp, regPbase, iomemCount;
312    struct UartDriverData *udd = port->udd;
313    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
314    if (iface == NULL || iface->GetUint32 == NULL) {
315        HDF_LOGE("%s: face is invalid", __func__);
316        return HDF_FAILURE;
317    }
318    if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) {
319        HDF_LOGE("%s: read busNum fail", __func__);
320        return HDF_FAILURE;
321    }
322    if (iface->GetUint32(node, "baudrate", &udd->baudrate, 0) != HDF_SUCCESS) {
323        HDF_LOGE("%s: read numCs fail", __func__);
324        return HDF_FAILURE;
325    }
326    if (iface->GetUint32(node, "fifoRxEn", &tmp, 0) != HDF_SUCCESS) {
327        HDF_LOGE("%s: read speed fail", __func__);
328        return HDF_FAILURE;
329    }
330    udd->attr.fifoRxEn = tmp;
331    if (iface->GetUint32(node, "fifoTxEn", &tmp, 0) != HDF_SUCCESS) {
332        HDF_LOGE("%s: read fifoSize fail", __func__);
333        return HDF_FAILURE;
334    }
335    udd->attr.fifoTxEn = tmp;
336    if (iface->GetUint32(node, "flags", &udd->flags, 0) != HDF_SUCCESS) {
337        HDF_LOGE("%s: read clkRate fail", __func__);
338        return HDF_FAILURE;
339    }
340    if (iface->GetUint32(node, "regPbase", &regPbase, 0) != HDF_SUCCESS) {
341        HDF_LOGE("%s: read mode fail", __func__);
342        return HDF_FAILURE;
343    }
344    if (iface->GetUint32(node, "iomemCount", &iomemCount, 0) != HDF_SUCCESS) {
345        HDF_LOGE("%s: read bitsPerWord fail", __func__);
346        return HDF_FAILURE;
347    }
348    port->physBase = (unsigned long)OsalIoRemap(regPbase, iomemCount);
349    if (iface->GetUint32(node, "interrupt", &port->irqNum, 0) != HDF_SUCCESS) {
350        HDF_LOGE("%s: read comMode fail", __func__);
351        return HDF_FAILURE;
352    }
353    return 0;
354}
355
356static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device)
357{
358    int32_t ret;
359    struct UartDriverData *udd = NULL;
360    struct UartPl011Port *port = NULL;
361
362    if (device->property == NULL) {
363        HDF_LOGE("%s: property is null", __func__);
364        return HDF_FAILURE;
365    }
366    udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));
367    if (udd == NULL) {
368        HDF_LOGE("%s: OsalMemCalloc udd error", __func__);
369        return HDF_ERR_MALLOC_FAIL;
370    }
371    port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));
372    if (port == NULL) {
373        HDF_LOGE("%s: OsalMemCalloc port error", __func__);
374        (void)OsalMemFree(udd);
375        return HDF_ERR_MALLOC_FAIL;
376    }
377    udd->ops = Pl011GetOps();
378    udd->recv = PL011UartRecvNotify;
379    udd->count = 0;
380    port->udd = udd;
381    ret = UartGetConfigFromHcs(port, device->property);
382    if (ret != 0 || port->physBase == 0) {
383        (void)OsalMemFree(port);
384        (void)OsalMemFree(udd);
385        return HDF_FAILURE;
386    }
387    udd->private = port;
388    host->priv = udd;
389    host->num = udd->num;
390    UartAddDev(host);
391    return HDF_SUCCESS;
392}
393
394static void Hi35xxDetach(struct UartHost *host)
395{
396    struct UartDriverData *udd = NULL;
397    struct UartPl011Port *port = NULL;
398
399    if (host->priv == NULL) {
400        HDF_LOGE("%s: invalid parameter", __func__);
401        return;
402    }
403    udd = host->priv;
404    if (udd->state != UART_STATE_NOT_OPENED) {
405        HDF_LOGE("%s: uart driver data state invalid", __func__);
406        return;
407    }
408    UartRemoveDev(host);
409    port = udd->private;
410    if (port != NULL) {
411        if (port->physBase != 0) {
412            OsalIoUnmap((void *)port->physBase);
413        }
414        (void)OsalMemFree(port);
415        udd->private = NULL;
416    }
417    (void)OsalMemFree(udd);
418    host->priv = NULL;
419}
420
421static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)
422{
423    HDF_LOGI("%s: entry", __func__);
424    if (device == NULL) {
425        return HDF_ERR_INVALID_OBJECT;
426    }
427    return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
428}
429
430int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)
431{
432    int32_t ret;
433    struct UartHost *host = NULL;
434
435    HDF_LOGI("%s: entry", __func__);
436    if (device == NULL) {
437        HDF_LOGE("%s: device is null", __func__);
438        return HDF_ERR_INVALID_OBJECT;
439    }
440    host = UartHostFromDevice(device);
441    if (host == NULL) {
442        HDF_LOGE("%s: host is null", __func__);
443        return HDF_FAILURE;
444    }
445    ret = Hi35xxAttach(host, device);
446    if (ret != HDF_SUCCESS) {
447        HDF_LOGE("%s: attach error", __func__);
448        return HDF_FAILURE;
449    }
450    host->method = &g_uartHostMethod;
451    return ret;
452}
453
454void HdfUartDeviceRelease(struct HdfDeviceObject *device)
455{
456    struct UartHost *host = NULL;
457
458    HDF_LOGI("%s: entry", __func__);
459    if (device == NULL) {
460        HDF_LOGE("%s: device is null", __func__);
461        return;
462    }
463    host = UartHostFromDevice(device);
464    if (host == NULL) {
465        HDF_LOGE("%s: host is null", __func__);
466        return;
467    }
468    if (host->priv != NULL) {
469        Hi35xxDetach(host);
470    }
471    UartHostDestroy(host);
472}
473
474struct HdfDriverEntry g_hdfUartDevice = {
475    .moduleVersion = 1,
476    .moduleName = "HDF_PLATFORM_UART",
477    .Bind = HdfUartDeviceBind,
478    .Init = HdfUartDeviceInit,
479    .Release = HdfUartDeviceRelease,
480};
481
482HDF_INIT(g_hdfUartDevice);
483