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", ®Pbase, 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