!605 feat: Relocate driver sample code

Merge pull request !605 from 郭东奇/OpenHarmony-3.0-LTS
This commit is contained in:
openharmony_ci
2022-02-09 02:07:14 +00:00
committed by Gitee
20 changed files with 1412 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_uart :: device {
device5 :: deviceNode {
policy = 2;
priority = 10;
permission = 0660;
moduleName = "UART_SAMPLE";
serviceName = "HDF_PLATFORM_UART_5";
deviceMatchAttr = "sample_uart_5";
}
}
}
}
}
+15
View File
@@ -0,0 +1,15 @@
root {
platform {
uart_sample {
num = 5;
base = 0x120a0000; // UART base register address
irqNum = 38;
baudrate = 115200;
uartClk = 24000000; // 24 M
wlen = 0x60; // 8 bit width
parity = 0;
stopBit = 0;
match_attr = "sample_uart_5";
}
}
}
+14
View File
@@ -0,0 +1,14 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
#
# HDF is dual licensed: you can use it either under the terms of
# the GPL, or the BSD license, at your option.
# See the LICENSE file in the root of this repository for complete details.
import("//build/lite/config/component/lite_component.gni")
lite_component("hello_uart_sample") {
features = [
"dev:hello_uart",
"dispatch:hello_uart_dispatch",
]
}
+12
View File
@@ -0,0 +1,12 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
#
# HDF is dual licensed: you can use it either under the terms of
# the GPL, or the BSD license, at your option.
# See the LICENSE file in the root of this repository for complete details.
config DRIVERS_HDF_PLATFORM_UART_SAMPLE
bool "Enable HDF platform uart sample driver"
default n
depends on DRIVERS_HDF_PLATFORM
help
Answer Y to enable HDF platform uart sample driver.
+41
View File
@@ -0,0 +1,41 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
#
# HDF is dual licensed: you can use it either under the terms of
# the GPL, or the BSD license, at your option.
# See the LICENSE file in the root of this repository for complete details.
HDF_FRAMEWORKS = "//drivers/framework"
executable("hello_uart") {
sources = [ "hello_uart_dev.c" ]
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//drivers/adapter/uhdf/posix/include",
"//third_party/bounds_checking_function/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
deps = [
"//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
"//drivers/adapter/uhdf/manager:hdf_core",
"//drivers/adapter/uhdf/posix:hdf_posix_osal",
]
public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
defines = [ "__USER__" ]
cflags = [
"-Wall",
"-Wextra",
"-Wno-format",
"-Wno-format-extra-args",
]
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "hdf_log.h"
#define HDF_LOG_TAG hello_uart
#define INFO_SIZE 16
int main(void)
{
int ret;
int fd;
const char info[INFO_SIZE] = {" HELLO UART! "};
fd = open("/dev/uartdev-5", O_RDWR);
if (fd < 0) {
HDF_LOGE("uartdev-5 open failed %d", fd);
return -1;
}
ret = write(fd, info, INFO_SIZE);
if (ret != 0) {
HDF_LOGE("write uartdev-5 ret is %d", ret);
}
ret = close(fd);
if (ret != 0) {
HDF_LOGE("uartdev-5 close failed %d", fd);
return -1;
}
return ret;
}
+44
View File
@@ -0,0 +1,44 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
#
# HDF is dual licensed: you can use it either under the terms of
# the GPL, or the BSD license, at your option.
# See the LICENSE file in the root of this repository for complete details.
HDF_FRAMEWORKS = "//drivers/framework"
executable("hello_uart_dispatch") {
sources = [
"hello_uart_dispatch.c",
"uart_if.c",
]
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//drivers/adapter/uhdf/posix/include",
"//third_party/bounds_checking_function/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
deps = [
"//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
"//drivers/adapter/uhdf/manager:hdf_core",
"//drivers/adapter/uhdf/posix:hdf_posix_osal",
]
public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
defines = [ "__USER__" ]
cflags = [
"-Wall",
"-Wextra",
"-Wno-format",
"-Wno-format-extra-args",
]
}
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include <string.h>
#include "hdf_log.h"
#include "osal_mem.h"
#include "uart_if.h"
#define HDF_LOG_TAG hello_uart_dispatch
#define UART_PORT 5
int main()
{
const char *info = " HELLO UART! ";
struct DevHandle *handle = UartOpen(UART_PORT);
if (handle == NULL) {
HDF_LOGE("Failed to open uart %d", UART_PORT);
return HDF_FAILURE;
}
int ret = UartWrite(handle, (uint8_t *)info, strlen(info));
if (ret != HDF_SUCCESS) {
HDF_LOGE("Failed to send data to uart");
}
UartClose(handle);
return ret;
}
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "uart_if.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "hdf_io_service_if.h"
#define HDF_LOG_TAG uart_if
struct DevHandle *UartOpen(uint32_t port)
{
int32_t ret;
struct DevHandle *handle = NULL;
char *serviceName = NULL;
handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle));
if (handle == NULL) {
HDF_LOGE("Failed to OsalMemCalloc handle");
return NULL;
}
serviceName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
if (serviceName == NULL) {
HDF_LOGE("Failed to OsalMemCalloc serviceName");
OsalMemFree(handle);
return NULL;
}
ret = snprintf_s(serviceName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, UART_DEV_SERVICE_NAME_PREFIX, port);
if (ret < 0) {
HDF_LOGE("Failed to snprintf_s");
OsalMemFree(handle);
OsalMemFree(serviceName);
return NULL;
}
struct HdfIoService *service = HdfIoServiceBind(serviceName);
if (service == NULL) {
HDF_LOGE("Failed to get service %s", serviceName);
OsalMemFree(handle);
OsalMemFree(serviceName);
return NULL;
}
OsalMemFree(serviceName);
handle->object = service;
return handle;
}
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size)
{
int ret;
struct HdfIoService *service = NULL;
if (handle == NULL || handle->object == NULL) {
HDF_LOGE("handle or handle->object is NULL");
return HDF_FAILURE;
}
struct HdfSBuf *sBuf = HdfSBufObtainDefaultSize();
if (sBuf == NULL) {
HDF_LOGE("Failed to obtain sBuf");
return HDF_FAILURE;
}
if (!HdfSbufWriteBuffer(sBuf, data, size)) {
HDF_LOGE("Failed to write sbuf");
HdfSBufRecycle(sBuf);
return HDF_FAILURE;
}
service = (struct HdfIoService *)handle->object;
ret = service->dispatcher->Dispatch(&service->object, UART_WRITE, sBuf, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("Failed to send service call");
}
HdfSBufRecycle(sBuf);
return ret;
}
void UartClose(struct DevHandle *handle)
{
struct HdfIoService *service = NULL;
if (handle == NULL || handle->object == NULL) {
HDF_LOGE("handle or handle->object is NULL");
return;
}
service = (struct HdfIoService *)handle->object;
HdfIoServiceRecycle(service);
OsalMemFree(handle);
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef UART_IF_H
#define UART_IF_H
#include <stdint.h>
#define UART_DEV_SERVICE_NAME_PREFIX "HDF_PLATFORM_UART_%d"
#define MAX_DEV_NAME_SIZE 32
enum {
UART_WRITE = 1
};
struct DevHandle {
void *object;
};
struct DevHandle *UartOpen(uint32_t port);
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size);
void UartClose(struct DevHandle *handle);
#endif // UART_IF_H
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef BUF_FIFO_H
#define BUF_FIFO_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
struct BufferFifo {
volatile uint32_t readPosition;
volatile uint32_t writePosition;
uint16_t bufSizeMask;
uint8_t *buffer;
};
static inline uint16_t BufferFifoGetDataSize(struct BufferFifo *fifo)
{
return (fifo->writePosition - fifo->readPosition);
}
static inline bool IsPowerOfTwo(int num)
{
return (num > 0) && (num & (num - 1)) == 0;
}
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *buf, uint16_t bufSize);
#endif // BUF_FIFO_H
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef UART_DEV_SAMPLE_H
#define UART_DEV_SAMPLE_H
#include "sys/ioctl.h"
#include "uart_core.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define UART_IOC_MAGIC 'u'
/* baudrate config */
#define UART_CFG_BAUDRATE _IO(UART_IOC_MAGIC, 1)
void AddUartDevice(struct UartHost *host);
void RemoveUartDevice(struct UartHost *host);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* UART_DEV_SAMPLE_H */
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef UART_DISPATCH_SAMPLE_H
#define UART_DISPATCH_SAMPLE_H
#include "uart_pl011_sample.h"
enum {
UART_WRITE = 1
};
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply);
#endif // UART_DISPATCH_SAMPLE_H
+242
View File
@@ -0,0 +1,242 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef UART_PL011_SAMPLE_H
#define UART_PL011_SAMPLE_H
#include <stdint.h>
#include <stdbool.h>
#include "hdf_device_desc.h"
#include "buf_fifo.h"
#ifdef __cplusplus
extern "C" {
#endif
struct UartRegisterMap {
volatile uint32_t dr; /* Offset: 0x000 TYPE: (RW) Data register */
union {
volatile uint32_t rsr; /* Offset: 0x004 TYPE: (RO) Receive status register */
volatile uint32_t ecr; /* Offset: 0x004 TYPE: (WO) Error clear register */
};
volatile uint32_t reserved0[4]; /* Offset: 0x008-0x014 Reserved */
volatile uint32_t fr; /* Offset: 0x018 TYPE: (RO) Flag register */
volatile uint32_t reserved1; /* Offset: 0x01C Reserved */
volatile uint32_t ilpr; /* Offset: 0x020 TYPE: (RW) IrDA low-power counter register */
volatile uint32_t ibrd; /* Offset: 0x024 TYPE: (RW) Integer baud rate register */
volatile uint32_t fbrd; /* Offset: 0x028 TYPE: (RW) Fractional baud rate register */
volatile uint32_t lcr; /* Offset: 0x02C TYPE: (RW) Line control register */
volatile uint32_t cr; /* Offset: 0x030 TYPE: (RW) Control register */
volatile uint32_t ifls; /* Offset: 0x034 TYPE: (RW) Interrupt FIFO level select register */
volatile uint32_t imsc; /* Offset: 0x038 TYPE: (RW) Interrupt mask set/clear register */
volatile uint32_t ris; /* Offset: 0x03C TYPE: (RO) Raw interrupt status register */
volatile uint32_t mis; /* Offset: 0x040 TYPE: (RO) Masked interrupt status register */
volatile uint32_t icr; /* Offset: 0x044 TYPE: (WO) Interrupt clear register */
volatile uint32_t dmacr; /* Offset: 0x048 TYPE: (RW) DMA control register */
};
struct UartResource {
uint32_t num; /* UART port num */
uint32_t base; /* UART PL011 base address */
uint32_t irqNum; /* UART PL011 IRQ num */
uint32_t baudrate; /* Default baudrate */
uint32_t wlen; /* Default word length */
uint32_t parity; /* Default parity */
uint32_t stopBit; /* Default stop bits */
uint32_t uartClk; /* UART clock */
unsigned long physBase;
};
enum UartDeviceState {
UART_DEVICE_UNINITIALIZED = 0x0u,
UART_DEVICE_INITIALIZED = 0x1u,
};
struct UartDevice {
struct IDeviceIoService ioService;
struct UartResource resource;
enum UartDeviceState state; /* UART State */
uint32_t uartClk; /* UART clock */
uint32_t baudrate; /* Baudrate */
struct BufferFifo rxFifo;
};
/* Receive Status Register/Error Clear Register data */
#define UART_PL011_RSR_FRAMING_ERROR_MASK (1 << 0x0u) /* Framing error bit mask */
#define UART_PL011_RSR_PARITY_ERROR_MASK (1 << 0x1u) /* Parity error bit mask */
#define UART_PL011_RSR_BREAK_ERROR_MASK (1 << 0x2u) /* Break error bit mask */
#define UART_PL011_RSR_OVERRUN_ERROR_MASK (1 << 0x3u) /* Overrun error bit mask */
/* Receive Status Register Error Mask */
#define UART_PL011_RSR_RX_ERROR_MASK ( \
UART_PL011_RSR_FRAMING_ERROR_MASK \
| UART_PL011_RSR_PARITY_ERROR_MASK \
| UART_PL011_RSR_BREAK_ERROR_MASK \
| UART_PL011_RSR_OVERRUN_ERROR_MASK)
#define UART_PL011_FR_CTS_MASK (1 << 0x0u) /* Clear to send bit mask */
#define UART_PL011_FR_DSR_MASK (1 << 0x1u) /* Data set ready bit mask */
#define UART_PL011_FR_DCD_MASK (1 << 0x2u) /* Data carrier detect bit mask */
#define UART_PL011_FR_BUSY_MASK (1 << 0x3u) /* UART busy bit mask */
#define UART_PL011_FR_RX_FIFO_EMPTY_MASK (1 << 0x4u) /* Receive FIFO empty bit mask */
#define UART_PL011_FR_TX_FIFO_FULL_MASK (1 << 0x5u) /* Transmit FIFO full bit mask */
#define UART_PL011_FR_RX_FIFO_FULL_MASK (1 << 0x6u) /* Receive FIFO full bit mask */
#define UART_PL011_FR_TX_FIFO_EMPTY_MASK (1 << 0x7u) /* Transmit FIFO empty. bit mask */
#define UART_PL011_FR_RI_MASK (1 << 0x8u) /* Ring indicator bit mask */
/* PL011 Line Control Register Data bits */
#define UART_PL011_LCR_H_BRK_MASK (1 << 0x0u) /* Send Break bit mask */
#define UART_PL011_LCR_H_PEN_MASK (1 << 0x1u) /* Parity enable bit mask */
#define UART_PL011_LCR_H_EPS_MASK (1 << 0x2u) /* Even parity select bit mask . */
#define UART_PL011_LCR_H_FEN_MASK (1 << 0x4u) /* Enable FIFOs bit mask */
#define UART_PL011_LCR_H_SPS_MASK (1 << 0x7u) /* Stick parity select bit mask */
#define UART_PL011_LCR_H_WLEN_BIT_OFFSET 0x5u /* Word length bit offset */
#define UART_PL011_LCR_H_WLEN_MASK ( \
0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_5BITS (0x0u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_6BITS (0x1u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_7BITS (0x2u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_8BITS (0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_NONE_PARITY_CHECKED 0
#define UART_PL011_LCR_H_STP2_BIT_OFFSET 0x3u /* Two stop bits select */
#define UART_PL011_STOPBIT_1 (0x0u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_STOPBIT_2 (0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_LCR_H_PARITY_MASK ( \
UART_PL011_LCR_H_PEN_MASK \
| UART_PL011_LCR_H_EPS_MASK \
| UART_PL011_LCR_H_SPS_MASK)
#define UART_PL011_LCR_H_STOPBIT_MASK (0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_DATA_FORMAT_MASK ( \
UART_PL011_LCR_H_PARITY_MASK \
| UART_PL011_LCR_H_STOPBIT_MASK \
| UART_PL011_LCR_H_WLEN_MASK)
/* Control Register */
#define UART_PL011_CR_UARTEN_MASK (0x1u << 0x0u) /* Uart enable bit mask */
#define UART_PL011_CR_SIREN_MASK (0x1u << 0x1u) /* Sir enable bit mask */
#define UART_PL011_CR_SIRLP_MASK (0x1u << 0x2u) /* SIR low-power IrDA mode bit mask */
#define UART_PL011_CR_LBE_MASK (0x1u << 0x7u) /* Loopback enable bit mask */
#define UART_PL011_CR_TXE_MASK (0x1u << 0x8u) /* Transmit enable bit mask */
#define UART_PL011_CR_RXE_MASK (0x1u << 0x9u) /* Receive enable bit mask */
#define UART_PL011_CR_DTR_MASK (0x1u << 0xAu) /* Data transmit ready.bit mask */
#define UART_PL011_CR_RTS_MASK (0x1u << 0xBu) /* Request to send bit mask */
#define UART_PL011_CR_OUT1_MASK (0x1u << 0xCu) /* Out1 bit field mask */
#define UART_PL011_CR_OUT2_MASK (0x1u << 0xDu) /* Out2 bit field mask */
#define UART_PL011_CR_RTSE_MASK (0x1u << 0xEu) /* RTS hardware flow control enable bit mask */
#define UART_PL011_CR_CTSE_MASK (0x1u << 0xFu) /* CTS hardware flow control enable bit mask */
/* Interrupt FIFO Level Select Register Transmit bit offset */
#define UART_PL011_IFLS_TX_BIT_OFFSET 0x0u
/* Interrupt FIFO Level Select Register Receive bit offset */
#define UART_PL011_IFLS_RX_BIT_OFFSET 0x3u
#define UART_PL011_RX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_TX_BIT_OFFSET)
/* Default register values of UART PL011 */
#define UART_PL011_DEFAULT_DATA_REG_VALUE (0x0u)
#define UART_PL011_DEFAULT_ECR_VALUE (0xFFu)
#define UART_PL011_DEFAULT_ILPR_VALUE (0x0u)
#define UART_PL011_DEFAULT_IBRD_REG_VALUE (0x0u)
#define UART_PL011_DEFAULT_FBRD_REG_VALUE (0x0u)
/* Clear UARTLCR */
#define UART_PL011_DEFAULT_LCR_H_VALUE (0x0u)
#define UART_PL011_DEFAULT_CTRL_REG_VALUE (0x0300u)
#define UART_PL011_DEFAULT_IFLS_REG_VALUE ( \
UART_PL011_RX_FIFO_LVL_1_2 \
| UART_PL011_TX_FIFO_LVL_7_8)
/* Clear interrupt mask */
#define UART_PL011_DEFAULT_IMSC_REG_VALUE (0x0u)
/* Clear interrupt */
#define UART_PL011_DEFAULT_ICR_VALUE (0x7FFu)
#define UART_PL011_DEFAULT_DMACR_VALUE (0x0u)
#define FREQ_IRLPBAUD16_MIN (1420000u) /* 1.42 MHz */
#define FREQ_IRLPBAUD16_MAX (2120000u) /* 2.12 MHz */
#define SAMPLING_FACTOR (16u)
#define UART_PL011_FBRD_WIDTH (6u)
/**
* \brief ARM UART PL011 error enumeration types
*/
typedef enum UartPl011Error {
UART_PL011_ERR_NONE = (0x0u),
UART_PL011_ERR_RX_FRAME = UART_PL011_RSR_FRAMING_ERROR_MASK,
UART_PL011_ERR_RX_PARITY = UART_PL011_RSR_PARITY_ERROR_MASK,
UART_PL011_ERR_RX_BREAK = UART_PL011_RSR_BREAK_ERROR_MASK,
UART_PL011_ERR_RX_OVERFLOW = UART_PL011_RSR_OVERRUN_ERROR_MASK,
UART_PL011_ERR_INVALID_ARG = (UART_PL011_RSR_RX_ERROR_MASK + 1),
UART_PL011_ERR_NOT_READY,
UART_PL011_ERR_INVALID_BAUD,
UART_PL011_ERR_NOT_INIT,
} UartPl011Error;
static inline void UartPl011Enable(struct UartRegisterMap *regMap)
{
regMap->cr |= UART_PL011_CR_UARTEN_MASK;
}
static inline void UartPl011Disable(struct UartRegisterMap *regMap)
{
regMap->cr &= ~UART_PL011_CR_UARTEN_MASK;
}
static inline bool UartPl011IsEnabled(struct UartRegisterMap *regMap)
{
return (bool)(regMap->cr & UART_PL011_CR_UARTEN_MASK);
}
static inline bool UartPl011IsBusy(struct UartRegisterMap *regMap)
{
return (bool)(regMap->fr & UART_PL011_FR_BUSY_MASK);
}
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits);
static inline void UartPl011Write(struct UartRegisterMap *regMap, uint8_t byte)
{
while (UartPl011IsBusy(regMap));
regMap->dr = byte;
}
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate);
void UartPl011SetDataFormat(struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits);
void UartPl011ResetRegisters(struct UartRegisterMap *regMap);
static inline void UartPl011EnableFifo(struct UartRegisterMap *regMap)
{
UartPl011SetLcrBits(regMap, UART_PL011_LCR_H_FEN_MASK);
}
#ifdef __cplusplus
}
#endif
#endif /* UART_PL011_SAMPLE_H */
+22
View File
@@ -0,0 +1,22 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
#
# HDF is dual licensed: you can use it either under the terms of
# the GPL, or the BSD license, at your option.
# See the LICENSE file in the root of this repository for complete details.
import("//drivers/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART_SAMPLE)
module_name = "hdf_uart_sample"
hdf_driver(module_name) {
FRAMEWORK_UART_ROOT = "//drivers/framework/sample/platform/uart/src"
sources = [
"$FRAMEWORK_UART_ROOT/buf_fifo.c",
"$FRAMEWORK_UART_ROOT/uart_dev_sample.c",
"$FRAMEWORK_UART_ROOT/uart_dispatch_sample.c",
"$FRAMEWORK_UART_ROOT/uart_pl011_sample.c",
"$FRAMEWORK_UART_ROOT/uart_sample.c",
]
include_dirs = [ "//drivers/framework/sample/platform/uart/include/" ]
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "buf_fifo.h"
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *fifoBuffer, uint16_t fifoSize)
{
if (fifoBuffer == NULL) {
return false;
}
if (!IsPowerOfTwo(fifoSize)) {
return false;
}
fifo->buffer = fifoBuffer;
fifo->bufSizeMask = fifoSize - 1;
fifo->readPosition = 0;
fifo->writePosition = 0;
return true;
}
+192
View File
@@ -0,0 +1,192 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "uart_dev_sample.h"
#include "fs/fs.h"
#include "securec.h"
#include "user_copy.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG uart_dev_sample
#define HDF_UART_FS_MODE 0660
static int32_t UartSampleDevOpen(struct file *filep)
{
struct UartHost *host = NULL;
if (filep == NULL || filep->f_vnode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
host = (struct UartHost *)drv->priv;
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGI("%s: open uart%d success", __func__, host->num);
return HDF_SUCCESS;
}
static int32_t UartSampleRelease(struct file *filep)
{
struct UartHost *host = NULL;
if (filep == NULL || filep->f_vnode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
host = (struct UartHost *)drv->priv;
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGI("%s: close uart%d success", __func__, host->num);
return HDF_SUCCESS;
}
static ssize_t UartSampleRead(struct file *filep, char *buf, size_t count)
{
int32_t ret;
uint8_t *tmpBuf = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_vnode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
host = (struct UartHost *)drv->priv;
if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
tmpBuf = (uint8_t *)OsalMemCalloc(count);
if (tmpBuf == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = UartHostRead(host, tmpBuf, count);
if (ret == HDF_SUCCESS) {
ret = LOS_ArchCopyToUser(buf, tmpBuf, count);
}
OsalMemFree(tmpBuf);
return ret;
} else {
return UartHostRead(host, (uint8_t *)buf, count);
}
}
static ssize_t UartSampleWrite(struct file *filep, const char *buf, size_t count)
{
int32_t ret;
uint8_t *tmpBuf = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_vnode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
host = (struct UartHost *)drv->priv;
if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
tmpBuf = (uint8_t *)OsalMemCalloc(count);
if (tmpBuf == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = LOS_ArchCopyFromUser(tmpBuf, buf, count);
if (ret != LOS_OK) {
OsalMemFree(tmpBuf);
return ret;
}
ret = UartHostWrite(host, tmpBuf, count);
OsalMemFree(tmpBuf);
return ret;
} else {
return UartHostWrite(host, (uint8_t *)buf, count);
}
}
static int32_t UartSampleDevIoctl(struct file *filep, int32_t cmd, unsigned long arg)
{
int32_t ret;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_vnode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
host = (struct UartHost *)drv->priv;
if (host->priv == NULL) {
return HDF_ERR_INVALID_PARAM;
}
ret = HDF_FAILURE;
switch (cmd) {
case UART_CFG_BAUDRATE:
ret = UartHostSetBaud(host, arg);
break;
default:
HDF_LOGE("%s cmd %d not support", __func__, cmd);
ret = HDF_ERR_NOT_SUPPORT;
break;
}
return ret;
}
const struct file_operations_vfs g_uartSampleDevFops = {
.open = UartSampleDevOpen,
.close = UartSampleRelease,
.read = UartSampleRead,
.write = UartSampleWrite,
.ioctl = UartSampleDevIoctl,
};
#define MAX_DEV_NAME_SIZE 32
static void AddRemoveUartDev(struct UartHost *host, bool add)
{
int32_t ret;
char *devName = NULL;
if (host == NULL || host->priv == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return;
}
devName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
if (devName == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return;
}
ret = snprintf_s(devName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, "/dev/uartdev-%d", host->num);
if (ret < 0) {
HDF_LOGE("%s: snprintf_s failed", __func__);
OsalMemFree(devName);
return;
}
if (add) {
if (register_driver(devName, &g_uartSampleDevFops, HDF_UART_FS_MODE, host)) {
HDF_LOGE("%s: gen /dev/uartdev-%d fail!", __func__, host->num);
OsalMemFree(devName);
return;
}
} else {
if (unregister_driver(devName)) {
HDF_LOGE("%s: remove /dev/uartdev-%d fail!", __func__, host->num);
OsalMemFree(devName);
return;
}
}
OsalMemFree(devName);
}
void AddUartDevice(struct UartHost *host)
{
AddRemoveUartDev(host, true);
}
void RemoveUartDevice(struct UartHost *host)
{
AddRemoveUartDev(host, false);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "uart_core.h"
#include "uart_dispatch_sample.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG uart_dispatch_sample
static int32_t SampleDispatchWrite(struct UartDevice *device, struct HdfSBuf *txBuf)
{
uint32_t idx;
uint32_t dataSize = 0;
const uint8_t *data = NULL;
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
if (regMap == NULL) {
HDF_LOGE("%s: regMap is NULL", __func__);
return HDF_FAILURE;
}
if (!HdfSbufReadBuffer(txBuf, (const void **)&data, &dataSize)) {
HDF_LOGE("%s: Failed to read sbuf", __func__);
return HDF_FAILURE;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
for (idx = 0; idx < dataSize; idx++) {
UartPl011Write(regMap, data[idx]);
}
return HDF_SUCCESS;
}
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t result = HDF_FAILURE;
if (client == NULL || client->device == NULL) {
HDF_LOGE("%s: client or client->device is NULL", __func__);
return result;
}
struct UartHost *uartHost = (struct UartHost *)client->device->service;
if (uartHost == NULL) {
HDF_LOGE("%s: uartHost is NULL", __func__);
return result;
}
struct UartDevice *uartDevice = (struct UartDevice *)uartHost->priv;
if (uartDevice == NULL) {
HDF_LOGE("%s: uartDevice is NULL", __func__);
return result;
}
switch (cmdId) {
case UART_WRITE: {
result = SampleDispatchWrite(uartDevice, data);
break;
}
default:
break;
}
return result;
}
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "uart_pl011_sample.h"
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr |= (bits);
/* Restore uart enable state */
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
void UartPl011UpdateLcr(struct UartRegisterMap *regMap)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr = regMap->lcr;
/* restore uart enable state */
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate)
{
if (baudrate == 0) {
return UART_PL011_ERR_INVALID_ARG;
}
uint32_t value = SAMPLING_FACTOR * baudrate;
uint32_t divider = clk / value;
uint32_t remainder = clk % value;
uint32_t fraction;
value = (SAMPLING_FACTOR * remainder) / baudrate;
fraction = (value >> 1) + (value & 1);
regMap->ibrd = divider;
regMap->fbrd = fraction;
/* to internally update the contents of UARTIBRD or
* UARTFBRD, a UARTLCR_H write must always be performed at the end.
*/
UartPl011UpdateLcr(regMap);
return UART_PL011_ERR_NONE;
}
void UartPl011SetDataFormat(
struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
uint32_t lcr = regMap->lcr & (~UART_PL011_DATA_FORMAT_MASK);
lcr |= wordLen & UART_PL011_LCR_H_WLEN_MASK;
lcr |= parity & UART_PL011_LCR_H_PARITY_MASK;
lcr |= stopBits & UART_PL011_LCR_H_STOPBIT_MASK;
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr = lcr;
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
void UartPl011ResetRegisters(struct UartRegisterMap *regMap)
{
regMap->cr = UART_PL011_DEFAULT_CTRL_REG_VALUE;
regMap->dr = UART_PL011_DEFAULT_DATA_REG_VALUE;
/* Clear all the errors */
regMap->ecr = UART_PL011_DEFAULT_ECR_VALUE;
regMap->ilpr = UART_PL011_DEFAULT_ILPR_VALUE;
regMap->ibrd = UART_PL011_DEFAULT_IBRD_REG_VALUE;
regMap->fbrd = UART_PL011_DEFAULT_FBRD_REG_VALUE;
regMap->lcr = UART_PL011_DEFAULT_LCR_H_VALUE;
regMap->ifls = UART_PL011_DEFAULT_IFLS_REG_VALUE;
/* Clear all interrupt mask */
regMap->imsc = UART_PL011_DEFAULT_IMSC_REG_VALUE;
/* Clear all interrupts */
regMap->icr = UART_PL011_DEFAULT_ICR_VALUE;
regMap->dmacr = UART_PL011_DEFAULT_DMACR_VALUE;
}
+344
View File
@@ -0,0 +1,344 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "device_resource_if.h"
#include "buf_fifo.h"
#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "hisoc/uart.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "uart_core.h"
#include "uart_dev_sample.h"
#include "uart_dispatch_sample.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG uart_sample
#define UART_RX_FIFO_SIZE 128
static uint8_t g_fifoBuffer[UART_RX_FIFO_SIZE] = {0};
/* HdfDriverEntry method definitions */
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device);
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device);
static void SampleUartDriverRelease(struct HdfDeviceObject *device);
/* HdfDriverEntry definitions */
struct HdfDriverEntry g_sampleUartDriverEntry = {
.moduleVersion = 1,
.moduleName = "UART_SAMPLE",
.Bind = SampleUartDriverBind,
.Init = SampleUartDriverInit,
.Release = SampleUartDriverRelease,
};
// Initialize HdfDriverEntry
HDF_INIT(g_sampleUartDriverEntry);
/* UartHostMethod method definitions */
static int32_t SampleUartHostInit(struct UartHost *host);
static int32_t SampleUartHostDeinit(struct UartHost *host);
static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size);
static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate);
static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate);
/* UartHostMethod definitions */
struct UartHostMethod g_sampleUartHostMethod = {
.Init = SampleUartHostInit,
.Deinit = SampleUartHostDeinit,
.Read = NULL,
.Write = SampleUartHostWrite,
.SetBaud = SampleUartHostSetBaud,
.GetBaud = SampleUartHostGetBaud,
.SetAttribute = NULL,
.GetAttribute = NULL,
.SetTransMode = NULL,
};
/* UartHostMethod implementations */
static int32_t SampleUartHostInit(struct UartHost *host)
{
HDF_LOGD("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
static int32_t SampleUartHostDeinit(struct UartHost *host)
{
HDF_LOGD("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size)
{
uint32_t idx;
struct UartRegisterMap *regMap = NULL;
struct UartDevice *device = NULL;
HDF_LOGD("%s: Enter", __func__);
if (host == NULL || data == NULL || size == 0) {
HDF_LOGW("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGW("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
for (idx = 0; idx < size; idx++) {
UartPl011Write(regMap, data[idx]);
}
return HDF_SUCCESS;
}
static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate)
{
struct UartDevice *device = NULL;
struct UartRegisterMap *regMap = NULL;
UartPl011Error err;
HDF_LOGD("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGW("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
if (device->state != UART_DEVICE_INITIALIZED) {
return UART_PL011_ERR_NOT_INIT;
}
if (baudRate == 0) {
return UART_PL011_ERR_INVALID_BAUD;
}
err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate);
if (err == UART_PL011_ERR_NONE) {
device->baudrate = baudRate;
}
return err;
}
static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate)
{
struct UartDevice *device = NULL;
HDF_LOGD("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGW("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
*baudRate = device->baudrate;
return HDF_SUCCESS;
}
static int InitUartDevice(struct UartDevice *device)
{
UartPl011Error err;
struct UartResource *resource = &device->resource;
struct UartRegisterMap *regMap = (struct UartRegisterMap *)resource->physBase;
if ((resource->uartClk == 0) || (resource->baudrate == 0)) {
return HDF_ERR_INVALID_PARAM;
}
/* Updating the system clock */
device->uartClk = resource->uartClk;
uart_clk_cfg(0, true);
/* clear and reset registers. */
UartPl011ResetRegisters(regMap);
/* set baud rate as device config */
err = UartPl011SetBaudrate(regMap, resource->uartClk, resource->baudrate);
if (err != UART_PL011_ERR_NONE) {
return HDF_FAILURE;
}
/* set the data format as device config */
UartPl011SetDataFormat(regMap, resource->wlen, resource->parity, resource->stopBit);
/* Enabling the FIFOs */
UartPl011EnableFifo(regMap);
UartPl011Enable(regMap);
BufferFifoInit(&device->rxFifo, g_fifoBuffer, UART_RX_FIFO_SIZE);
device->state = UART_DEVICE_INITIALIZED;
return HDF_SUCCESS;
}
static uint32_t GetUartDeviceResource(
struct UartDevice *device, const struct DeviceResourceNode *resourceNode)
{
struct UartResource *resource = &device->resource;
struct DeviceResourceIface *dri = NULL;
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (dri == NULL || dri->GetUint32 == NULL) {
HDF_LOGE("DeviceResourceIface is invalid");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read num fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read base fail");
return HDF_FAILURE;
}
resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48);
if (resource->physBase == 0) {
HDF_LOGE("uart config fail to remap physBase");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read irqNum fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read baudrate fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read wlen fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read parity fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read stopBit fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read uartClk fail");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device)
{
int32_t ret;
struct UartDevice *uartDevice = NULL;
if (device->property == NULL) {
HDF_LOGW("%s: property is NULL", __func__);
return HDF_FAILURE;
}
uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice));
if (uartDevice == NULL) {
HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = GetUartDeviceResource(uartDevice, device->property);
if (ret != HDF_SUCCESS) {
(void)OsalMemFree(uartDevice);
return HDF_FAILURE;
}
host->num = uartDevice->resource.num;
host->priv = uartDevice;
AddUartDevice(host);
return InitUartDevice(uartDevice);
}
static void DeinitUartDevice(struct UartDevice *device)
{
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
/* wait for uart enter idle. */
while (UartPl011IsBusy(regMap)) { }
UartPl011ResetRegisters(regMap);
uart_clk_cfg(0, false);
OsalIoUnmap((void *)device->resource.physBase);
device->state = UART_DEVICE_UNINITIALIZED;
}
static void DetachUartDevice(struct UartHost *host)
{
struct UartDevice *uartDevice = NULL;
if (host->priv == NULL) {
HDF_LOGW("%s: invalid parameter", __func__);
return;
}
uartDevice = host->priv;
DeinitUartDevice(uartDevice);
(void)OsalMemFree(uartDevice);
host->priv = NULL;
}
/* HdfDriverEntry implementations */
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device)
{
struct UartHost *uartHost = NULL;
HDF_LOGD("%s: Enter", __func__);
if (device == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
uartHost = UartHostCreate(device);
if (uartHost == NULL) {
HDF_LOGE("%s: UartHostCreate failed", __func__);
return HDF_FAILURE;
}
uartHost->service.Dispatch = SampleDispatch;
return HDF_SUCCESS;
}
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct UartHost *host = NULL;
HDF_LOGD("%s: Enter", __func__);
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_OBJECT;
}
host = UartHostFromDevice(device);
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_FAILURE;
}
ret = AttachUartDevice(host, device);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: attach error", __func__);
return HDF_FAILURE;
}
host->method = &g_sampleUartHostMethod;
return ret;
}
static void SampleUartDriverRelease(struct HdfDeviceObject *device)
{
struct UartHost *host = NULL;
HDF_LOGD("%s: Enter", __func__);
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return;
}
host = UartHostFromDevice(device);
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return;
}
if (host->priv != NULL) {
DetachUartDevice(host);
}
UartHostDestroy(host);
}