1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "device_resource_if.h"
10 #include "buf_fifo.h"
11 #include "hdf_device_desc.h"
12 #include "hdf_log.h"
13 #include "hisoc/uart.h"
14 #include "osal_io.h"
15 #include "osal_mem.h"
16 #include "uart_core.h"
17 #include "uart_dev_sample.h"
18 #include "uart_dispatch_sample.h"
19 #include "uart_pl011_sample.h"
20
21 #define HDF_LOG_TAG uart_sample
22 #define UART_RX_FIFO_SIZE 128
23
24 static uint8_t g_fifoBuffer[UART_RX_FIFO_SIZE] = {0};
25
26 /* HdfDriverEntry method definitions */
27 static int32_t SampleUartDriverBind(struct HdfDeviceObject *device);
28 static int32_t SampleUartDriverInit(struct HdfDeviceObject *device);
29 static void SampleUartDriverRelease(struct HdfDeviceObject *device);
30
31 /* HdfDriverEntry definitions */
32 struct HdfDriverEntry g_sampleUartDriverEntry = {
33 .moduleVersion = 1,
34 .moduleName = "UART_SAMPLE",
35 .Bind = SampleUartDriverBind,
36 .Init = SampleUartDriverInit,
37 .Release = SampleUartDriverRelease,
38 };
39
40 // Initialize HdfDriverEntry
41 HDF_INIT(g_sampleUartDriverEntry);
42
43 /* UartHostMethod method definitions */
44 static int32_t SampleUartHostInit(struct UartHost *host);
45 static int32_t SampleUartHostDeinit(struct UartHost *host);
46 static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size);
47 static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate);
48 static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate);
49
50 /* UartHostMethod definitions */
51 struct UartHostMethod g_sampleUartHostMethod = {
52 .Init = SampleUartHostInit,
53 .Deinit = SampleUartHostDeinit,
54 .Read = NULL,
55 .Write = SampleUartHostWrite,
56 .SetBaud = SampleUartHostSetBaud,
57 .GetBaud = SampleUartHostGetBaud,
58 .SetAttribute = NULL,
59 .GetAttribute = NULL,
60 .SetTransMode = NULL,
61 };
62
63 /* UartHostMethod implementations */
SampleUartHostInit(struct UartHost * host)64 static int32_t SampleUartHostInit(struct UartHost *host)
65 {
66 HDF_LOGD("%s: Enter", __func__);
67 if (host == NULL) {
68 HDF_LOGW("%s: invalid parameter", __func__);
69 return HDF_ERR_INVALID_PARAM;
70 }
71 return HDF_SUCCESS;
72 }
73
SampleUartHostDeinit(struct UartHost * host)74 static int32_t SampleUartHostDeinit(struct UartHost *host)
75 {
76 HDF_LOGD("%s: Enter", __func__);
77 if (host == NULL) {
78 HDF_LOGW("%s: invalid parameter", __func__);
79 return HDF_ERR_INVALID_PARAM;
80 }
81 return HDF_SUCCESS;
82 }
83
SampleUartHostWrite(struct UartHost * host,uint8_t * data,uint32_t size)84 static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size)
85 {
86 uint32_t idx;
87 struct UartRegisterMap *regMap = NULL;
88 struct UartDevice *device = NULL;
89 HDF_LOGD("%s: Enter", __func__);
90
91 if (host == NULL || data == NULL || size == 0) {
92 HDF_LOGW("%s: invalid parameter", __func__);
93 return HDF_ERR_INVALID_PARAM;
94 }
95 device = (struct UartDevice *)host->priv;
96 if (device == NULL) {
97 HDF_LOGW("%s: device is NULL", __func__);
98 return HDF_ERR_INVALID_PARAM;
99 }
100 regMap = (struct UartRegisterMap *)device->resource.physBase;
101 for (idx = 0; idx < size; idx++) {
102 UartPl011Write(regMap, data[idx]);
103 }
104 return HDF_SUCCESS;
105 }
106
SampleUartHostSetBaud(struct UartHost * host,uint32_t baudRate)107 static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate)
108 {
109 struct UartDevice *device = NULL;
110 struct UartRegisterMap *regMap = NULL;
111 UartPl011Error err;
112 HDF_LOGD("%s: Enter", __func__);
113
114 if (host == NULL) {
115 HDF_LOGW("%s: invalid parameter", __func__);
116 return HDF_ERR_INVALID_PARAM;
117 }
118 device = (struct UartDevice *)host->priv;
119 if (device == NULL) {
120 HDF_LOGW("%s: device is NULL", __func__);
121 return HDF_ERR_INVALID_PARAM;
122 }
123 regMap = (struct UartRegisterMap *)device->resource.physBase;
124 if (device->state != UART_DEVICE_INITIALIZED) {
125 return UART_PL011_ERR_NOT_INIT;
126 }
127 if (baudRate == 0) {
128 return UART_PL011_ERR_INVALID_BAUD;
129 }
130 err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate);
131 if (err == UART_PL011_ERR_NONE) {
132 device->baudrate = baudRate;
133 }
134 return err;
135 }
136
SampleUartHostGetBaud(struct UartHost * host,uint32_t * baudRate)137 static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate)
138 {
139 struct UartDevice *device = NULL;
140 HDF_LOGD("%s: Enter", __func__);
141
142 if (host == NULL) {
143 HDF_LOGW("%s: invalid parameter", __func__);
144 return HDF_ERR_INVALID_PARAM;
145 }
146 device = (struct UartDevice *)host->priv;
147 if (device == NULL) {
148 HDF_LOGW("%s: device is NULL", __func__);
149 return HDF_ERR_INVALID_PARAM;
150 }
151 *baudRate = device->baudrate;
152 return HDF_SUCCESS;
153 }
154
InitUartDevice(struct UartDevice * device)155 static int InitUartDevice(struct UartDevice *device)
156 {
157 UartPl011Error err;
158 struct UartResource *resource = &device->resource;
159 struct UartRegisterMap *regMap = (struct UartRegisterMap *)resource->physBase;
160 if ((resource->uartClk == 0) || (resource->baudrate == 0)) {
161 return HDF_ERR_INVALID_PARAM;
162 }
163 /* Updating the system clock */
164 device->uartClk = resource->uartClk;
165 uart_clk_cfg(0, true);
166 /* clear and reset registers. */
167 UartPl011ResetRegisters(regMap);
168 /* set baud rate as device config */
169 err = UartPl011SetBaudrate(regMap, resource->uartClk, resource->baudrate);
170 if (err != UART_PL011_ERR_NONE) {
171 return HDF_FAILURE;
172 }
173 /* set the data format as device config */
174 UartPl011SetDataFormat(regMap, resource->wlen, resource->parity, resource->stopBit);
175 /* Enabling the FIFOs */
176 UartPl011EnableFifo(regMap);
177 UartPl011Enable(regMap);
178 BufferFifoInit(&device->rxFifo, g_fifoBuffer, UART_RX_FIFO_SIZE);
179 device->state = UART_DEVICE_INITIALIZED;
180 return HDF_SUCCESS;
181 }
182
GetUartDeviceResource(struct UartDevice * device,const struct DeviceResourceNode * resourceNode)183 static uint32_t GetUartDeviceResource(
184 struct UartDevice *device, const struct DeviceResourceNode *resourceNode)
185 {
186 struct UartResource *resource = &device->resource;
187 struct DeviceResourceIface *dri = NULL;
188 dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
189 if (dri == NULL || dri->GetUint32 == NULL) {
190 HDF_LOGE("DeviceResourceIface is invalid");
191 return HDF_FAILURE;
192 }
193
194 if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {
195 HDF_LOGE("uart config read num fail");
196 return HDF_FAILURE;
197 }
198 if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) {
199 HDF_LOGE("uart config read base fail");
200 return HDF_FAILURE;
201 }
202 resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48);
203 if (resource->physBase == 0) {
204 HDF_LOGE("uart config fail to remap physBase");
205 return HDF_FAILURE;
206 }
207 if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) {
208 HDF_LOGE("uart config read irqNum fail");
209 return HDF_FAILURE;
210 }
211 if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) {
212 HDF_LOGE("uart config read baudrate fail");
213 return HDF_FAILURE;
214 }
215 if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) {
216 HDF_LOGE("uart config read wlen fail");
217 return HDF_FAILURE;
218 }
219 if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) {
220 HDF_LOGE("uart config read parity fail");
221 return HDF_FAILURE;
222 }
223 if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) {
224 HDF_LOGE("uart config read stopBit fail");
225 return HDF_FAILURE;
226 }
227 if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) {
228 HDF_LOGE("uart config read uartClk fail");
229 return HDF_FAILURE;
230 }
231 return HDF_SUCCESS;
232 }
233
AttachUartDevice(struct UartHost * host,struct HdfDeviceObject * device)234 static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device)
235 {
236 int32_t ret;
237 struct UartDevice *uartDevice = NULL;
238 if (device->property == NULL) {
239 HDF_LOGW("%s: property is NULL", __func__);
240 return HDF_FAILURE;
241 }
242 uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice));
243 if (uartDevice == NULL) {
244 HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__);
245 return HDF_ERR_MALLOC_FAIL;
246 }
247 ret = GetUartDeviceResource(uartDevice, device->property);
248 if (ret != HDF_SUCCESS) {
249 (void)OsalMemFree(uartDevice);
250 return HDF_FAILURE;
251 }
252 host->num = uartDevice->resource.num;
253 host->priv = uartDevice;
254 AddUartDevice(host);
255 return InitUartDevice(uartDevice);
256 }
257
DeinitUartDevice(struct UartDevice * device)258 static void DeinitUartDevice(struct UartDevice *device)
259 {
260 struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
261 /* wait for uart enter idle. */
262 while (UartPl011IsBusy(regMap)) { }
263 UartPl011ResetRegisters(regMap);
264 uart_clk_cfg(0, false);
265 OsalIoUnmap((void *)device->resource.physBase);
266 device->state = UART_DEVICE_UNINITIALIZED;
267 }
268
DetachUartDevice(struct UartHost * host)269 static void DetachUartDevice(struct UartHost *host)
270 {
271 struct UartDevice *uartDevice = NULL;
272
273 if (host->priv == NULL) {
274 HDF_LOGW("%s: invalid parameter", __func__);
275 return;
276 }
277 uartDevice = host->priv;
278 DeinitUartDevice(uartDevice);
279 (void)OsalMemFree(uartDevice);
280 host->priv = NULL;
281 }
282
283 /* HdfDriverEntry implementations */
SampleUartDriverBind(struct HdfDeviceObject * device)284 static int32_t SampleUartDriverBind(struct HdfDeviceObject *device)
285 {
286 struct UartHost *uartHost = NULL;
287 HDF_LOGD("%s: Enter", __func__);
288
289 if (device == NULL) {
290 return HDF_ERR_INVALID_OBJECT;
291 }
292
293 uartHost = UartHostCreate(device);
294 if (uartHost == NULL) {
295 HDF_LOGE("%s: UartHostCreate failed", __func__);
296 return HDF_FAILURE;
297 }
298 uartHost->service.Dispatch = SampleDispatch;
299 return HDF_SUCCESS;
300 }
301
SampleUartDriverInit(struct HdfDeviceObject * device)302 static int32_t SampleUartDriverInit(struct HdfDeviceObject *device)
303 {
304 int32_t ret;
305 struct UartHost *host = NULL;
306 HDF_LOGD("%s: Enter", __func__);
307
308 if (device == NULL) {
309 HDF_LOGE("%s: device is NULL", __func__);
310 return HDF_ERR_INVALID_OBJECT;
311 }
312 host = UartHostFromDevice(device);
313 if (host == NULL) {
314 HDF_LOGE("%s: host is NULL", __func__);
315 return HDF_FAILURE;
316 }
317 ret = AttachUartDevice(host, device);
318 if (ret != HDF_SUCCESS) {
319 HDF_LOGE("%s: attach error", __func__);
320 return HDF_FAILURE;
321 }
322 host->method = &g_sampleUartHostMethod;
323 return ret;
324 }
325
SampleUartDriverRelease(struct HdfDeviceObject * device)326 static void SampleUartDriverRelease(struct HdfDeviceObject *device)
327 {
328 struct UartHost *host = NULL;
329 HDF_LOGD("%s: Enter", __func__);
330
331 if (device == NULL) {
332 HDF_LOGE("%s: device is NULL", __func__);
333 return;
334 }
335 host = UartHostFromDevice(device);
336 if (host == NULL) {
337 HDF_LOGE("%s: host is NULL", __func__);
338 return;
339 }
340 if (host->priv != NULL) {
341 DetachUartDevice(host);
342 }
343 UartHostDestroy(host);
344 }
345