mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-08-28 04:59:54 -04:00
Executable
+38
@@ -0,0 +1,38 @@
|
||||
root {
|
||||
device_info {
|
||||
platform :: host {
|
||||
hostName = "platform_host";
|
||||
priority = 50;
|
||||
device_gpio :: device {
|
||||
device1 :: deviceNode {
|
||||
policy = 2;
|
||||
priority = 10;
|
||||
permission = 0660;
|
||||
moduleName = "GPIO_SAMPLE";
|
||||
serviceName = "GPIO_SAMPLE";
|
||||
deviceMatchAttr = "sample_gpio";
|
||||
}
|
||||
}
|
||||
device_uart :: device {
|
||||
device5 :: deviceNode {
|
||||
policy = 2;
|
||||
priority = 10;
|
||||
permission = 0660;
|
||||
moduleName = "UART_SAMPLE";
|
||||
serviceName = "HDF_PLATFORM_UART_5";
|
||||
deviceMatchAttr = "sample_uart_5";
|
||||
}
|
||||
}
|
||||
device_spi :: device {
|
||||
device3 :: deviceNode {
|
||||
policy = 2;
|
||||
priority = 60;
|
||||
permission = 0660;
|
||||
moduleName = "SPI_SAMPLE";
|
||||
serviceName = "HDF_PLATFORM_SPI_3";
|
||||
deviceMatchAttr = "sample_spi_3";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
root {
|
||||
platform {
|
||||
gpio_config {
|
||||
gpio_sample {
|
||||
match_attr = "sample_gpio";
|
||||
groupNum = 12;
|
||||
bitNum = 8;
|
||||
regBase = 0x120d0000;
|
||||
regStep = 0x1000;
|
||||
irqStart = 48;
|
||||
irqShare = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
root {
|
||||
platform {
|
||||
spi_config {
|
||||
spi_sample {
|
||||
serviceName = "SPI_SAMPLE";
|
||||
match_attr = "sample_spi_3";
|
||||
transferMode = 0;
|
||||
busNum = 0;
|
||||
clkRate = 100000000;
|
||||
bitsPerWord = 8;
|
||||
mode = 19;
|
||||
speed = 2000000;
|
||||
fifoSize = 256;
|
||||
numCs = 1;
|
||||
regBase = 0x120c0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+15
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
# 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_gpio_sample") {
|
||||
features = [ "dispatch:hello_gpio_dispatch" ]
|
||||
}
|
||||
Executable
+12
@@ -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_GPIO_SAMPLE
|
||||
bool "Enable HDF platform gpio sample driver"
|
||||
default n
|
||||
depends on DRIVERS_HDF_PLATFORM
|
||||
help
|
||||
Answer Y to enable HDF platform gpio sample driver.
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
# 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_gpio_dispatch") {
|
||||
sources = [
|
||||
"gpio_if.c",
|
||||
"hello_gpio_dispatch.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",
|
||||
"//drivers/framework/support/platform/include/gpio",
|
||||
]
|
||||
|
||||
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",
|
||||
]
|
||||
}
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 "gpio_if.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_io_service_if.h"
|
||||
|
||||
#define HDF_LOG_TAG gpio_if
|
||||
|
||||
static struct HdfIoService *GetIoService()
|
||||
{
|
||||
static struct HdfIoService *ioService = NULL;
|
||||
if (ioService != NULL) {
|
||||
return ioService;
|
||||
}
|
||||
|
||||
ioService = HdfIoServiceBind(GPIO_SERVICE_NAME);
|
||||
if (ioService == NULL) {
|
||||
HDF_LOGE("Failed to get service %s", GPIO_SERVICE_NAME);
|
||||
}
|
||||
return ioService;
|
||||
}
|
||||
|
||||
static int32_t GpioOperate(enum GpioOps ops, uint16_t gpio, uint16_t val)
|
||||
{
|
||||
int ret = HDF_FAILURE;
|
||||
struct HdfIoService *service = GetIoService();
|
||||
if (service == NULL) {
|
||||
return ret;
|
||||
}
|
||||
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
|
||||
if (data == NULL) {
|
||||
HDF_LOGE("Failed to obtain sBuf");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!HdfSbufWriteUint16(data, gpio) || !HdfSbufWriteUint16(data, val)) {
|
||||
HDF_LOGE("Failed to write sBuf");
|
||||
HdfSBufRecycle(data);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
ret = service->dispatcher->Dispatch(&service->object, ops, data, NULL);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("Failed to send service call, ret: %d", ret);
|
||||
}
|
||||
HdfSBufRecycle(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t GpioQuery(enum GpioOps ops, uint16_t gpio, uint16_t *val)
|
||||
{
|
||||
int ret = HDF_FAILURE;
|
||||
struct HdfIoService *service = GetIoService();
|
||||
if (service == NULL) {
|
||||
return ret;
|
||||
}
|
||||
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
|
||||
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
|
||||
if (data == NULL || reply == NULL) {
|
||||
HDF_LOGE("Failed to obtain sBuf");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!HdfSbufWriteUint16(data, gpio)) {
|
||||
HDF_LOGE("Failed to write data sBuf");
|
||||
goto __ERR__;
|
||||
}
|
||||
ret = service->dispatcher->Dispatch(&service->object, ops, data, reply);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("Failed to send service call");
|
||||
goto __ERR__;
|
||||
|
||||
}
|
||||
if (!HdfSbufReadUint16(reply, val)) {
|
||||
HDF_LOGE("Failed to read reply sBuf");
|
||||
goto __ERR__;
|
||||
}
|
||||
goto __ERR__;
|
||||
|
||||
__ERR__:
|
||||
HdfSBufRecycle(data);
|
||||
HdfSBufRecycle(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t GpioOpen()
|
||||
{
|
||||
struct HdfIoService *ioService = GetIoService();
|
||||
if (ioService == NULL) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t GpioSetDir(uint16_t gpio, uint16_t dir)
|
||||
{
|
||||
return GpioOperate(GPIO_OPS_SET_DIR, gpio, dir);
|
||||
}
|
||||
|
||||
int32_t GpioGetDir(uint16_t gpio, uint16_t *dir)
|
||||
{
|
||||
return GpioQuery(GPIO_OPS_GET_DIR, gpio, dir);
|
||||
}
|
||||
|
||||
int32_t GpioWrite(uint16_t gpio, uint16_t val)
|
||||
{
|
||||
return GpioOperate(GPIO_OPS_WRITE, gpio, val);
|
||||
}
|
||||
|
||||
int32_t GpioRead(uint16_t gpio, uint16_t *val)
|
||||
{
|
||||
return GpioQuery(GPIO_OPS_READ, gpio, val);
|
||||
}
|
||||
|
||||
int32_t GpioClose()
|
||||
{
|
||||
struct HdfIoService *ioService = GetIoService();
|
||||
if (ioService == NULL) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
HdfIoServiceRecycle(ioService);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 GPIO_IF_H
|
||||
#define GPIO_IF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GPIO_SERVICE_NAME "GPIO_SAMPLE"
|
||||
|
||||
enum GpioValue {
|
||||
GPIO_VAL_LOW = 0,
|
||||
GPIO_VAL_HIGH = 1,
|
||||
GPIO_VAL_ERR,
|
||||
};
|
||||
|
||||
enum GpioDirType {
|
||||
GPIO_DIR_IN = 0,
|
||||
GPIO_DIR_OUT = 1,
|
||||
GPIO_DIR_ERR,
|
||||
};
|
||||
|
||||
enum GpioOps {
|
||||
GPIO_OPS_SET_DIR = 1,
|
||||
GPIO_OPS_GET_DIR,
|
||||
GPIO_OPS_WRITE,
|
||||
GPIO_OPS_READ
|
||||
};
|
||||
|
||||
int32_t GpioOpen();
|
||||
int32_t GpioClose();
|
||||
int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
|
||||
int32_t GpioGetDir(uint16_t gpio, uint16_t *dir);
|
||||
int32_t GpioWrite(uint16_t gpio, uint16_t val);
|
||||
int32_t GpioRead(uint16_t gpio, uint16_t *val);
|
||||
|
||||
#endif // GPIO_IF_H
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 "gpio_if.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_base.h"
|
||||
|
||||
#define HDF_LOG_TAG hello_gpio_dispatch
|
||||
#define GPIO_PIN 11
|
||||
|
||||
int main()
|
||||
{
|
||||
uint16_t dir;
|
||||
uint16_t val;
|
||||
if (GpioOpen() != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioOpen failed", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (GpioSetDir(GPIO_PIN, GPIO_DIR_IN) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioSetDir failed, gpio %u, dir %u", __func__, GPIO_PIN, GPIO_DIR_IN);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (GpioWrite(GPIO_PIN, GPIO_VAL_HIGH) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioWrite failed, gpio %u, val %u", __func__, GPIO_PIN, GPIO_VAL_HIGH);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (GpioGetDir(GPIO_PIN, &dir) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioGetDir failed, gpio %u", __func__, GPIO_PIN);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (GpioRead(GPIO_PIN, &val) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioRead failed, gpio %u", __func__, GPIO_PIN);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (GpioClose() != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: GpioClose failed", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
HDF_LOGD("GPIO %u direction is set to %u, value is set to %u", GPIO_PIN, dir, val);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 GPIO_DISPATCH_SAMPLE_H
|
||||
#define GPIO_DISPATCH_SAMPLE_H
|
||||
|
||||
#include "gpio_pl061_sample.h"
|
||||
|
||||
enum GpioOps {
|
||||
GPIO_OPS_SET_DIR = 1,
|
||||
GPIO_OPS_GET_DIR,
|
||||
GPIO_OPS_WRITE,
|
||||
GPIO_OPS_READ
|
||||
};
|
||||
|
||||
int32_t SampleGpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply);
|
||||
|
||||
#endif // GPIO_DISPATCH_SAMPLE_H
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 GPIO_PL061_SAMPLE_H
|
||||
#define GPIO_PL061_SAMPLE_H
|
||||
|
||||
#include "gpio_core.h"
|
||||
#include "gpio_if.h"
|
||||
#include "osal.h"
|
||||
|
||||
#define GROUP_MAX 32
|
||||
#define BIT_MAX 16
|
||||
|
||||
#define GPIO_DATA(base, bit) ((base) + 0x000 + (1 << ((bit) + 2)))
|
||||
#define GPIO_DIR(base) ((base) + 0x400)
|
||||
#define GPIO_IS(base) ((base) + 0x404)
|
||||
#define GPIO_IBE(base) ((base) + 0x408)
|
||||
#define GPIO_IEV(base) ((base) + 0x40C)
|
||||
#define GPIO_IE(base) ((base) + 0x410)
|
||||
#define GPIO_RIS(base) ((base) + 0x414)
|
||||
#define GPIO_MIS(base) ((base) + 0x418)
|
||||
#define GPIO_IC(base) ((base) + 0x41C)
|
||||
|
||||
struct GpioGroup {
|
||||
volatile unsigned char *regBase;
|
||||
unsigned int index;
|
||||
OsalSpinlock lock;
|
||||
};
|
||||
|
||||
struct Pl061GpioCntlr {
|
||||
struct GpioCntlr cntlr;
|
||||
volatile unsigned char *regBase;
|
||||
uint32_t phyBase;
|
||||
uint32_t regStep;
|
||||
uint32_t irqStart;
|
||||
uint16_t groupNum;
|
||||
uint16_t bitNum;
|
||||
uint8_t irqShare;
|
||||
struct GpioGroup *groups;
|
||||
};
|
||||
|
||||
static struct Pl061GpioCntlr g_samplePl061GpioCntlr = {
|
||||
.groups = NULL,
|
||||
.groupNum = GROUP_MAX,
|
||||
.bitNum = BIT_MAX,
|
||||
};
|
||||
|
||||
static inline struct Pl061GpioCntlr *ToPl061GpioCntlr(struct GpioCntlr *cntlr)
|
||||
{
|
||||
return (struct Pl061GpioCntlr *)cntlr;
|
||||
}
|
||||
|
||||
static inline uint16_t Pl061ToGroupNum(uint16_t gpio)
|
||||
{
|
||||
return (uint16_t)(gpio / g_samplePl061GpioCntlr.bitNum);
|
||||
}
|
||||
|
||||
static inline uint16_t Pl061ToBitNum(uint16_t gpio)
|
||||
{
|
||||
return (uint16_t)(gpio % g_samplePl061GpioCntlr.bitNum);
|
||||
}
|
||||
|
||||
static inline uint16_t Pl061ToGpioNum(uint16_t group, uint16_t bit)
|
||||
{
|
||||
return (uint16_t)(group * g_samplePl061GpioCntlr.bitNum + bit);
|
||||
}
|
||||
|
||||
int32_t Pl061GetGroupByGpioNum(struct GpioCntlr *cntlr, uint16_t gpio,
|
||||
struct GpioGroup **group);
|
||||
#endif // GPIO_PL061_SAMPLE_H
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
# 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_GPIO_SAMPLE)
|
||||
module_name = "hdf_gpio_sample"
|
||||
hdf_driver(module_name) {
|
||||
FRAMEWORK_GPIO_ROOT = "//drivers/framework/sample/platform/gpio/src"
|
||||
sources = [
|
||||
"$FRAMEWORK_GPIO_ROOT/gpio_dispatch_sample.c",
|
||||
"$FRAMEWORK_GPIO_ROOT/gpio_pl061_sample.c",
|
||||
"$FRAMEWORK_GPIO_ROOT/gpio_sample.c",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"//drivers/framework/sample/platform/gpio/include/",
|
||||
"//drivers/framework/support/platform/include/gpio",
|
||||
]
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 "gpio_dispatch_sample.h"
|
||||
|
||||
#define HDF_LOG_TAG gpio_dispatch_sample
|
||||
|
||||
static int32_t SampleGpioSetDir(struct GpioCntlr *cntlr, struct HdfSBuf *data)
|
||||
{
|
||||
uint16_t gpio;
|
||||
uint16_t dir;
|
||||
if (!HdfSbufReadUint16(data, &gpio) || !HdfSbufReadUint16(data, &dir)) {
|
||||
HDF_LOGE("%s: HdfSbufReadUint16 failed", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (cntlr->ops->setDir == NULL) {
|
||||
HDF_LOGE("%s: cntlr->ops->setDir is NULL", __func__);
|
||||
return HDF_DEV_ERR_OP;
|
||||
}
|
||||
return cntlr->ops->setDir(cntlr, gpio, dir);
|
||||
}
|
||||
|
||||
static int32_t SampleGpioGetDir(struct GpioCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
uint16_t gpio;
|
||||
uint16_t dir;
|
||||
if (!HdfSbufReadUint16(data, &gpio)) {
|
||||
HDF_LOGE("%s: HdfSbufReadUint16 failed", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (cntlr->ops->getDir == NULL) {
|
||||
HDF_LOGE("%s: cntlr->ops->getDir is NULL", __func__);
|
||||
return HDF_DEV_ERR_OP;
|
||||
}
|
||||
ret = cntlr->ops->getDir(cntlr, gpio, &dir);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: cntlr->ops->getDir failed, ret: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
if (!HdfSbufWriteUint16(reply, dir)) {
|
||||
HDF_LOGE("%s: HdfSbufWriteUint16 failed", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleGpioWrite(struct GpioCntlr *cntlr, struct HdfSBuf *data)
|
||||
{
|
||||
uint16_t gpio;
|
||||
uint16_t val;
|
||||
if (!HdfSbufReadUint16(data, &gpio) || !HdfSbufReadUint16(data, &val)) {
|
||||
HDF_LOGE("%s: HdfSbufReadUint16 failed", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (cntlr->ops->write == NULL) {
|
||||
HDF_LOGE("%s: cntlr->ops->read is NULL", __func__);
|
||||
return HDF_DEV_ERR_OP;
|
||||
}
|
||||
return cntlr->ops->write(cntlr, gpio, val);
|
||||
}
|
||||
|
||||
static int32_t SampleGpioRead(struct GpioCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
uint16_t gpio;
|
||||
uint16_t val;
|
||||
if (!HdfSbufReadUint16(data, &gpio)) {
|
||||
HDF_LOGE("%s: HdfSbufReadUint16 failed", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (cntlr->ops->read == NULL) {
|
||||
HDF_LOGE("%s: cntlr->ops->read is NULL", __func__);
|
||||
return HDF_DEV_ERR_OP;
|
||||
}
|
||||
ret = cntlr->ops->read(cntlr, gpio, &val);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: cntlr->ops->read failed, ret: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
if (!HdfSbufWriteUint16(reply, val)) {
|
||||
HDF_LOGE("%s: HdfSbufWriteUint16 failed", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SampleGpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
if (client == NULL || client->device == NULL) {
|
||||
HDF_LOGE("%s: client or client->device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
struct GpioCntlr *cntlr = (struct GpioCntlr *)client->device->service;
|
||||
if (cntlr == NULL || cntlr->ops == NULL) {
|
||||
HDF_LOGE("%s: cntlr or cntlr->ops is NULL", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
switch (cmdId) {
|
||||
case GPIO_OPS_SET_DIR:
|
||||
return SampleGpioSetDir(cntlr, data);
|
||||
case GPIO_OPS_GET_DIR:
|
||||
return SampleGpioGetDir(cntlr, data, reply);
|
||||
case GPIO_OPS_WRITE:
|
||||
return SampleGpioWrite(cntlr, data);
|
||||
case GPIO_OPS_READ:
|
||||
return SampleGpioRead(cntlr, data, reply);
|
||||
default:
|
||||
HDF_LOGE("%s: invalid cmdId %d", __func__, cmdId);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 "gpio_pl061_sample.h"
|
||||
#include "osal_irq.h"
|
||||
|
||||
#define HDF_LOG_TAG gpio_pl061_sample
|
||||
|
||||
int32_t Pl061GetGroupByGpioNum(struct GpioCntlr *cntlr, uint16_t gpio, struct GpioGroup **group)
|
||||
{
|
||||
struct Pl061GpioCntlr *pl061 = NULL;
|
||||
uint16_t groupIndex = Pl061ToGroupNum(gpio);
|
||||
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("%s: cntlr is NULL", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
pl061 = ToPl061GpioCntlr(cntlr);
|
||||
if (groupIndex >= pl061->groupNum) {
|
||||
HDF_LOGE("%s: err group index:%u", __func__, groupIndex);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
*group = &pl061->groups[groupIndex];
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
Executable
+359
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* 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 "gpio_dispatch_sample.h"
|
||||
#include "gpio_pl061_sample.h"
|
||||
#include "device_resource_if.h"
|
||||
#include "hdf_device_desc.h"
|
||||
#include "gpio_if.h"
|
||||
#include "osal.h"
|
||||
#include "osal_io.h"
|
||||
#include "gpio_core.h"
|
||||
|
||||
#define HDF_LOG_TAG gpio_sample
|
||||
|
||||
/* HdfDriverEntry hook function prototypes */
|
||||
static int32_t SampleGpioDriverBind(struct HdfDeviceObject *device);
|
||||
static int32_t SampleGpioDriverInit(struct HdfDeviceObject *device);
|
||||
static void SampleGpioDriverRelease(struct HdfDeviceObject *device);
|
||||
|
||||
/* HdfDriverEntry definition */
|
||||
struct HdfDriverEntry g_sampleGpioDriverEntry = {
|
||||
.moduleVersion = 1,
|
||||
.moduleName = "GPIO_SAMPLE",
|
||||
.Bind = SampleGpioDriverBind,
|
||||
.Init = SampleGpioDriverInit,
|
||||
.Release = SampleGpioDriverRelease,
|
||||
};
|
||||
|
||||
/* Init HdfDriverEntry */
|
||||
HDF_INIT(g_sampleGpioDriverEntry);
|
||||
|
||||
/* GPIO function prototypes */
|
||||
static int32_t SampleGpioWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val);
|
||||
static int32_t SampleGpioRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val);
|
||||
static int32_t SampleGpioSetDirection(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir);
|
||||
static int32_t SampleGpioGetDirection(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir);
|
||||
|
||||
/* GpioMethod definition */
|
||||
struct GpioMethod g_sampleGpioMethod = {
|
||||
.request = NULL,
|
||||
.release = NULL,
|
||||
.write = SampleGpioWrite,
|
||||
.read = SampleGpioRead,
|
||||
.setDir = SampleGpioSetDirection,
|
||||
.getDir = SampleGpioGetDirection,
|
||||
.toIrq = NULL,
|
||||
.setIrq = NULL,
|
||||
.unsetIrq = NULL,
|
||||
.enableIrq = NULL,
|
||||
.disableIrq = NULL,
|
||||
};
|
||||
|
||||
/* Private function prototypes */
|
||||
/* Read GPIO device resource */
|
||||
static int32_t GetGpioDeviceResource(struct Pl061GpioCntlr *cntlr, const struct DeviceResourceNode *node);
|
||||
/* Init GPIO controller memory */
|
||||
static int32_t InitGpioCntlrMem(struct Pl061GpioCntlr *cntlr);
|
||||
/* Release GPIO controller memory */
|
||||
static void ReleaseGpioCntlrMem(struct Pl061GpioCntlr *cntlr);
|
||||
|
||||
/* HdfDriverEntry hook function implementations */
|
||||
static int32_t SampleGpioDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
struct Pl061GpioCntlr *pl061Cntlr = &g_samplePl061GpioCntlr;
|
||||
pl061Cntlr->cntlr.device = device;
|
||||
device->service = &(pl061Cntlr->cntlr.service);
|
||||
pl061Cntlr->cntlr.device->service->Dispatch = SampleGpioDispatch;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleGpioDriverInit(struct HdfDeviceObject *device)
|
||||
{
|
||||
int32_t ret;
|
||||
struct Pl061GpioCntlr *pl061Cntlr = &g_samplePl061GpioCntlr;
|
||||
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
if (device == NULL || device->property == NULL) {
|
||||
HDF_LOGE("%s: device or property NULL!", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
ret = GetGpioDeviceResource(pl061Cntlr, device->property);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: get gpio device resource fail:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pl061Cntlr->groupNum > GROUP_MAX || pl061Cntlr->groupNum <= 0 || pl061Cntlr->bitNum > BIT_MAX ||
|
||||
pl061Cntlr->bitNum <= 0) {
|
||||
HDF_LOGE("%s: invalid groupNum:%u or bitNum:%u", __func__, pl061Cntlr->groupNum,
|
||||
pl061Cntlr->bitNum);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
pl061Cntlr->regBase = OsalIoRemap(pl061Cntlr->phyBase, pl061Cntlr->groupNum * pl061Cntlr->regStep);
|
||||
if (pl061Cntlr->regBase == NULL) {
|
||||
HDF_LOGE("%s: err remap phy:0x%x", __func__, pl061Cntlr->phyBase);
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
|
||||
ret = InitGpioCntlrMem(pl061Cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: err init cntlr mem:%d", __func__, ret);
|
||||
OsalIoUnmap((void *)pl061Cntlr->regBase);
|
||||
pl061Cntlr->regBase = NULL;
|
||||
return ret;
|
||||
}
|
||||
pl061Cntlr->cntlr.count = pl061Cntlr->groupNum * pl061Cntlr->bitNum;
|
||||
pl061Cntlr->cntlr.priv = (void *)device->property;
|
||||
pl061Cntlr->cntlr.ops = &g_sampleGpioMethod;
|
||||
ret = GpioCntlrAdd(&pl061Cntlr->cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: err add controller: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
HDF_LOGI("%s: dev service:%s init success!", __func__, HdfDeviceGetServiceName(device));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SampleGpioDriverRelease(struct HdfDeviceObject *device)
|
||||
{
|
||||
struct GpioCntlr *gpioCntlr = NULL;
|
||||
struct Pl061GpioCntlr *pl061GpioCntlr = NULL;
|
||||
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is null!", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
gpioCntlr = GpioCntlrFromDevice(device);
|
||||
if (gpioCntlr == NULL) {
|
||||
HDF_LOGE("%s: no service bound!", __func__);
|
||||
return;
|
||||
}
|
||||
GpioCntlrRemove(gpioCntlr);
|
||||
|
||||
pl061GpioCntlr = (struct Pl061GpioCntlr *)gpioCntlr;
|
||||
ReleaseGpioCntlrMem(pl061GpioCntlr);
|
||||
OsalIoUnmap((void *)pl061GpioCntlr->regBase);
|
||||
pl061GpioCntlr->regBase = NULL;
|
||||
}
|
||||
|
||||
/* Private function implementations */
|
||||
static int32_t GetGpioDeviceResource(struct Pl061GpioCntlr *cntlr, const struct DeviceResourceNode *node)
|
||||
{
|
||||
int32_t ret;
|
||||
struct DeviceResourceIface *dri = NULL;
|
||||
|
||||
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (dri == NULL || dri->GetUint8 == NULL || dri->GetUint16 == NULL || dri->GetUint32 == NULL) {
|
||||
HDF_LOGE("%s: invalid dri ops fail!", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
ret = dri->GetUint32(node, "regBase", &cntlr->phyBase, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read regBase fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dri->GetUint32(node, "regStep", &cntlr->regStep, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read regStep fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dri->GetUint16(node, "groupNum", &cntlr->groupNum, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read groupNum fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dri->GetUint16(node, "bitNum", &cntlr->bitNum, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read bitNum fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dri->GetUint32(node, "irqStart", &cntlr->irqStart, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read irqStart fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dri->GetUint8(node, "irqShare", &cntlr->irqShare, 0);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read irqShare fail!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t InitGpioCntlrMem(struct Pl061GpioCntlr *cntlr)
|
||||
{
|
||||
size_t groupMemSize;
|
||||
struct GpioGroup *groups = NULL;
|
||||
|
||||
if (cntlr == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
groupMemSize = sizeof(struct GpioGroup) * cntlr->groupNum;
|
||||
groups = (struct GpioGroup *)OsalMemCalloc(groupMemSize);
|
||||
if (groups == NULL) {
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
cntlr->groups = groups;
|
||||
|
||||
for (uint16_t i = 0; i < cntlr->groupNum; i++) {
|
||||
groups[i].index = i;
|
||||
groups[i].regBase = cntlr->regBase + (i * cntlr->regStep);
|
||||
if (OsalSpinInit(&groups[i].lock) != HDF_SUCCESS) {
|
||||
for (; i > 0; i--) {
|
||||
(void)OsalSpinDestroy(&groups[i - 1].lock);
|
||||
}
|
||||
OsalMemFree(groups);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void ReleaseGpioCntlrMem(struct Pl061GpioCntlr *cntlr)
|
||||
{
|
||||
if (cntlr == NULL) {
|
||||
return;
|
||||
}
|
||||
if (cntlr->groups != NULL) {
|
||||
for (uint16_t i = 0; i < cntlr->groupNum; i++) {
|
||||
(void)OsalSpinDestroy(&cntlr->groups[i].lock);
|
||||
}
|
||||
OsalMemFree(cntlr->groups);
|
||||
cntlr->groups = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* GPIO function implementations */
|
||||
static int32_t SampleGpioWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
int32_t ret;
|
||||
uint32_t irqSave;
|
||||
unsigned int valCur;
|
||||
unsigned int bitNum = Pl061ToBitNum(gpio);
|
||||
volatile unsigned char *addr = NULL;
|
||||
struct GpioGroup *group = NULL;
|
||||
|
||||
ret = Pl061GetGroupByGpioNum(cntlr, gpio, &group);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
addr = GPIO_DATA(group->regBase, bitNum);
|
||||
if (OsalSpinLockIrqSave(&group->lock, &irqSave) != HDF_SUCCESS) {
|
||||
return HDF_ERR_DEVICE_BUSY;
|
||||
}
|
||||
valCur = OSAL_READL(addr);
|
||||
if (val == GPIO_VAL_LOW) {
|
||||
valCur &= ~(1 << bitNum);
|
||||
} else {
|
||||
valCur |= (1 << bitNum);
|
||||
}
|
||||
OSAL_WRITEL(valCur, addr);
|
||||
(void)OsalSpinUnlockIrqRestore(&group->lock, &irqSave);
|
||||
HDF_LOGD("%s: gpio:%u, val:%u", __func__, gpio, val);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleGpioRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
int32_t ret;
|
||||
unsigned int valCur;
|
||||
volatile unsigned char *addr = NULL;
|
||||
unsigned int bitNum = Pl061ToBitNum(gpio);
|
||||
struct GpioGroup *group = NULL;
|
||||
|
||||
ret = Pl061GetGroupByGpioNum(cntlr, gpio, &group);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
addr = GPIO_DATA(group->regBase, bitNum);
|
||||
valCur = OSAL_READL(addr);
|
||||
if (valCur & (1 << bitNum)) {
|
||||
*val = GPIO_VAL_HIGH;
|
||||
} else {
|
||||
*val = GPIO_VAL_LOW;
|
||||
}
|
||||
HDF_LOGD("%s: gpio:%u, val:%u", __func__, gpio, *val);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleGpioSetDirection(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
int32_t ret;
|
||||
uint32_t irqSave;
|
||||
unsigned int val;
|
||||
volatile unsigned char *addr = NULL;
|
||||
unsigned int bitNum = Pl061ToBitNum(gpio);
|
||||
struct GpioGroup *group = NULL;
|
||||
|
||||
HDF_LOGD("%s: gpio:%u, dir:%d", __func__, gpio, dir);
|
||||
ret = Pl061GetGroupByGpioNum(cntlr, gpio, &group);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
addr = GPIO_DIR(group->regBase);
|
||||
if (OsalSpinLockIrqSave(&group->lock, &irqSave) != HDF_SUCCESS) {
|
||||
return HDF_ERR_DEVICE_BUSY;
|
||||
}
|
||||
val = OSAL_READL(addr);
|
||||
if (dir == GPIO_DIR_IN) {
|
||||
val &= ~(1 << bitNum);
|
||||
} else if (dir == GPIO_DIR_OUT) {
|
||||
val |= 1 << bitNum;
|
||||
}
|
||||
OSAL_WRITEL(val, addr);
|
||||
(void)OsalSpinUnlockIrqRestore(&group->lock, &irqSave);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
static int32_t SampleGpioGetDirection(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
|
||||
int32_t ret;
|
||||
unsigned int val;
|
||||
volatile unsigned char *addr = NULL;
|
||||
unsigned int bitNum = Pl061ToBitNum(gpio);
|
||||
struct GpioGroup *group = NULL;
|
||||
|
||||
HDF_LOGD("%s: gpio:%u, dir:%p", __func__, gpio, dir);
|
||||
ret = Pl061GetGroupByGpioNum(cntlr, gpio, &group);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
addr = GPIO_DIR(group->regBase);
|
||||
val = OSAL_READL(addr);
|
||||
if (val & (1 << bitNum)) {
|
||||
*dir = GPIO_DIR_OUT;
|
||||
} else {
|
||||
*dir = GPIO_DIR_IN;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
# 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_spi_sample") {
|
||||
features = [ "dispatch:hello_spi_dispatch" ]
|
||||
}
|
||||
Executable
+12
@@ -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_SPI_SAMPLE
|
||||
bool "Enable HDF platform spi sample driver"
|
||||
default n
|
||||
depends on DRIVERS_HDF_PLATFORM
|
||||
help
|
||||
Answer Y to enable HDF platform spi sample driver.
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
# 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_spi_dispatch") {
|
||||
sources = [
|
||||
"hello_spi_dispatch.c",
|
||||
"spi_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/platform",
|
||||
"$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",
|
||||
]
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 "spi_if.h"
|
||||
#include "hdf_log.h"
|
||||
|
||||
#define HDF_LOG_TAG hello_spi_dispatch
|
||||
|
||||
int main()
|
||||
{
|
||||
int32_t ret;
|
||||
struct SpiDevInfo spiDevInfo; /* SPI device descriptor */
|
||||
struct DevHandle *spiHandle = NULL; /* SPI device handle */
|
||||
spiDevInfo.busNum = 3; /* SPI device bus number */
|
||||
spiDevInfo.csNum = 0; /* SPI device CS number */
|
||||
spiHandle = SpiOpen(&spiDevInfo);
|
||||
if (spiHandle == NULL) {
|
||||
HDF_LOGE("SpiOpen failed");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
uint8_t wbuff[1] = {0x12};
|
||||
uint8_t rbuff[1] = {0};
|
||||
struct SpiMsg msg; /* Custom message to be transferred */
|
||||
msg.wbuf = wbuff; /* Pointer to the data to write */
|
||||
msg.rbuf = rbuff; /* Pointer to the data to read */
|
||||
msg.len = 1; /* The length of the data to be read or written is 1 bits. */
|
||||
msg.csChange = 1; /* Disable the CS before the next transfer. */
|
||||
msg.delayUs = 0; /* No delay before the next transfer */
|
||||
msg.speed = 115200; /* Speed of this transfer */
|
||||
ret = SpiTransfer(spiHandle, &msg);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SpiTransfer failed, ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
SpiClose(spiHandle);
|
||||
return ret;
|
||||
}
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 "spi_if.h"
|
||||
#include "osal_mem.h"
|
||||
#include "hdf_io_service_if.h"
|
||||
#include "hdf_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HDF_LOG_TAG spi_if
|
||||
|
||||
DevHandle SpiOpen(const struct SpiDevInfo *info)
|
||||
{
|
||||
int32_t ret;
|
||||
void *devHandle = NULL;
|
||||
uint32_t port;
|
||||
char *serviceName = NULL;
|
||||
|
||||
if (info == NULL) {
|
||||
HDF_LOGW("info is NULL");
|
||||
return NULL;
|
||||
}
|
||||
port = info->busNum;
|
||||
|
||||
serviceName = (char *)OsalMemCalloc(MAX_DEV_NAME_SIZE + 1);
|
||||
if (serviceName == NULL) {
|
||||
HDF_LOGE("Failed to OsalMemCalloc serviceName");
|
||||
return NULL;
|
||||
}
|
||||
ret = snprintf_s(serviceName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, SPI_DEV_SERVICE_NAME_PREFIX, port);
|
||||
if (ret < 0) {
|
||||
HDF_LOGE("Failed to snprintf_s");
|
||||
OsalMemFree(serviceName);
|
||||
return NULL;
|
||||
}
|
||||
devHandle = (void *)HdfIoServiceBind(serviceName);
|
||||
OsalMemFree(serviceName);
|
||||
return devHandle;
|
||||
}
|
||||
|
||||
void SpiClose(DevHandle handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
HDF_LOGW("handle is NULL");
|
||||
return;
|
||||
}
|
||||
struct HdfIoService *service = (struct HdfIoService *)handle;
|
||||
HdfIoServiceRecycle(service);
|
||||
OsalMemFree(handle);
|
||||
}
|
||||
|
||||
int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs)
|
||||
{
|
||||
int32_t ret;
|
||||
if (handle == NULL || msgs == NULL) {
|
||||
HDF_LOGW("handle or msgs is NULL");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
struct HdfIoService *service = (struct HdfIoService *)handle;
|
||||
if (service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
|
||||
HDF_LOGE("service->dispatcher or service->dispatcher->Dispatch is NULL");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
struct HdfSBuf *sBuf = HdfSBufObtainDefaultSize();
|
||||
if (sBuf == NULL) {
|
||||
HDF_LOGE("Failed to obtain sBuf");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
if (!HdfSbufWriteBuffer(sBuf, msgs, sizeof(struct SpiMsg))) {
|
||||
HDF_LOGE("Failed to write sbuf");
|
||||
HdfSBufRecycle(sBuf);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
ret = service->dispatcher->Dispatch(&service->object, SPI_TRANSFER, sBuf, NULL);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("Failed to send service call");
|
||||
}
|
||||
HdfSBufRecycle(sBuf);
|
||||
return ret;
|
||||
}
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 SPI_IF_H
|
||||
#define SPI_IF_H
|
||||
|
||||
#include "hdf_platform.h"
|
||||
|
||||
#define SPI_DEV_SERVICE_NAME_PREFIX "HDF_PLATFORM_SPI_%u"
|
||||
#define MAX_DEV_NAME_SIZE 32
|
||||
|
||||
struct SpiDevInfo {
|
||||
uint32_t busNum;
|
||||
uint32_t csNum;
|
||||
};
|
||||
|
||||
struct SpiMsg {
|
||||
uint8_t *wbuf;
|
||||
uint8_t *rbuf;
|
||||
uint32_t len;
|
||||
uint32_t speed;
|
||||
uint16_t delayUs;
|
||||
uint8_t csChange;
|
||||
};
|
||||
|
||||
enum {
|
||||
SPI_TRANSFER = 1
|
||||
};
|
||||
|
||||
DevHandle SpiOpen(const struct SpiDevInfo *info);
|
||||
void SpiClose(DevHandle handle);
|
||||
int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs);
|
||||
|
||||
#endif // SPI_IF_H
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 SPI_DISPATCH_SAMPLE_H
|
||||
#define SPI_DISPATCH_SAMPLE_H
|
||||
|
||||
#include "spi_pl022_sample.h"
|
||||
#include "spi_core.h"
|
||||
|
||||
enum {
|
||||
SPI_TRANSFER = 1
|
||||
};
|
||||
|
||||
int32_t SampleSpiDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply);
|
||||
|
||||
#endif // SPI_DISPATCH_SAMPLE_H
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 SPI_PL022_SAMPLE_H
|
||||
#define SPI_PL022_SAMPLE_H
|
||||
|
||||
#include "spi_if.h"
|
||||
#include "osal.h"
|
||||
|
||||
/* ********** spi reg offset define start *************** */
|
||||
#define REG_SPI_PL022_CR0 0x00
|
||||
#define SPI_PL022_CR0_SCR_SHIFT 8
|
||||
#define SPI_PL022_CR0_SPH_SHIFT 7
|
||||
#define SPI_PL022_CR0_SPO_SHIFT 6
|
||||
#define SPI_PL022_CR0_FRF_SHIFT 4
|
||||
#define SPI_PL022_CR0_DSS_SHIFT 0
|
||||
#define SPI_PL022_CR0_SCR (0xff << 8) /* clkout=clk/(cpsdvsr*(scr+1)) */
|
||||
#define SPI_PL022_CR0_SPH (0x1 << 7) /* spi phase */
|
||||
#define SPI_PL022_CR0_SPO (0x1 << 6) /* spi clk polarity */
|
||||
#define SPI_PL022_CR0_FRF (0x3 << 4) /* frame format set */
|
||||
#define SPI_PL022_CR0_DSS (0xf << 0) /* data bits width */
|
||||
|
||||
#define REG_SPI_PL022_CR1 0x04
|
||||
#define SPI_PL022_CR1_WAIT_EN_SHIFT 15
|
||||
#define SPI_PL022_CR1_WAIT_VAL_SHIFT 8
|
||||
#define SPI_PL022_CR1_ALT_SHIFT 6
|
||||
#define SPI_PL022_CR1_BIG_END_SHIFT 4
|
||||
#define SPI_PL022_CR1_MS_SHIFT 2
|
||||
#define SPI_PL022_CR1_SSE_SHIFT 1
|
||||
#define SPI_PL022_CR1_LBN_SHIFT 0
|
||||
#define SPI_PL022_CR1_WAIT_EN (0x1 << 15)
|
||||
#define SPI_PL022_CR1_WAIT_VAL (0x7f << 8)
|
||||
|
||||
/* alt mode:spi enable csn is select; spi disable csn is cancel */
|
||||
#define SPI_PL022_CR1_ALT (0x1 << 6)
|
||||
#define SPI_PL022_CR1_BIG_END (0x1 << 4) /* big end or little */
|
||||
#define SPI_PL022_CR1_MS (0x1 << 2) /* cntlr-device mode */
|
||||
#define SPI_PL022_CR1_SSE (0x1 << 1) /* spi enable set */
|
||||
#define SPI_PL022_CR1_LBM (0x1 << 0) /* loopback mode */
|
||||
|
||||
#define REG_SPI_PL022_DR 0x08
|
||||
|
||||
#define REG_SPI_PL022_SR 0x0c
|
||||
#define SPI_PL022_SR_BSY_SHIFT 4
|
||||
#define SPI_PL022_SR_RFF_SHIFT 3
|
||||
#define SPI_PL022_SR_RNE_SHIFT 2
|
||||
#define SPI_PL022_SR_TNF_SHIFT 1
|
||||
#define SPI_PL022_SR_TFE_SHIFT 0
|
||||
#define SPI_PL022_SR_BSY (0x1 << 4) /* spi busy flag */
|
||||
#define SPI_PL022_SR_RFF (0x1 << 3) /* Whether to send fifo is full */
|
||||
#define SPI_PL022_SR_RNE (0x1 << 2) /* Whether to send fifo is no empty */
|
||||
#define SPI_PL022_SR_TNF (0x1 << 1) /* Whether to send fifo is no full */
|
||||
#define SPI_PL022_SR_TFE (0x1 << 0) /* Whether to send fifo is empty */
|
||||
|
||||
#define REG_SPI_PL022_CPSR 0x10
|
||||
#define SPI_PL022_CPSR_CPSDVSR_SHIFT 0
|
||||
#define SPI_PL022_CPSR_CPSDVSR (0xff << 0) /* even 2~254 */
|
||||
|
||||
#define REG_SPI_PL022_IMSC 0x14
|
||||
#define REG_SPI_PL022_RIS 0x18
|
||||
#define REG_SPI_PL022_MIS 0x1c
|
||||
#define REG_SPI_PL022_ICR 0x20
|
||||
|
||||
#define REG_SPI_CRG 0x120100e4 /* CRG_REG_BASE(0x12010000) + 0x0e4 */
|
||||
#define SPI_CRG_CLK_EN 0
|
||||
#define SPI_CRG_CLK_RST 0
|
||||
|
||||
#define REG_SPI_MISC_CTRL 0x12030024 /* MISC_REG_BASE(0x12030000) + 0x24 */
|
||||
#define SPI_MISC_CTRL_CS 0
|
||||
#define SPI_MISC_CTRL_CS_SHIFT 0
|
||||
/* ********** spi reg offset define end *************** */
|
||||
|
||||
#define MAX_WAIT 5000
|
||||
#define DEFAULT_SPEED 2000000
|
||||
|
||||
#define SCR_MAX 255
|
||||
#define SCR_MIN 0
|
||||
#define CPSDVSR_MAX 254
|
||||
#define CPSDVSR_MIN 2
|
||||
#define SPI_CS_ACTIVE 0
|
||||
#define SPI_CS_INACTIVE 1
|
||||
#define TWO_BYTES 2
|
||||
#define BITS_PER_WORD_MIN 4
|
||||
#define BITS_PER_WORD_DEFAULT 8
|
||||
#define BITS_PER_WORD_MAX 16
|
||||
|
||||
struct Pl022SpiCntlr {
|
||||
struct SpiCntlr *cntlr;
|
||||
struct DListHead deviceList;
|
||||
volatile unsigned char *regBase;
|
||||
uint32_t busNum;
|
||||
uint32_t numCs;
|
||||
uint32_t curCs;
|
||||
uint32_t speed;
|
||||
uint32_t fifoSize;
|
||||
uint32_t clkRate;
|
||||
uint32_t maxSpeedHz;
|
||||
uint32_t minSpeedHz;
|
||||
uint32_t regCrg;
|
||||
uint32_t clkEnBit;
|
||||
uint32_t clkRstBit;
|
||||
uint32_t regMiscCtrl;
|
||||
uint32_t miscCtrlCsShift;
|
||||
uint32_t miscCtrlCs;
|
||||
uint16_t mode;
|
||||
uint8_t bitsPerWord;
|
||||
uint8_t transferMode;
|
||||
};
|
||||
|
||||
int ConfigPl022SpiCntlr(struct Pl022SpiCntlr *cntlr);
|
||||
int32_t TransferOneMessage(struct Pl022SpiCntlr *cntlr, struct SpiMsg *msg);
|
||||
|
||||
#endif // SPI_PL022_SAMPLE_H
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 SPI_SAMPLE_H
|
||||
#define SPI_SAMPLE_H
|
||||
|
||||
#include "spi_core.h"
|
||||
|
||||
int32_t SampleSpiCntlrTransfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count);
|
||||
int32_t SampleSpiCntlrSetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg);
|
||||
int32_t SampleSpiCntlrGetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg);
|
||||
|
||||
#endif // SPI_SAMPLE_H
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
# 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_SPI_SAMPLE)
|
||||
module_name = "hdf_spi_sample"
|
||||
hdf_driver(module_name) {
|
||||
FRAMEWORK_SPI_ROOT = "//drivers/framework/sample/platform/spi/src"
|
||||
sources = [
|
||||
"$FRAMEWORK_SPI_ROOT/spi_dispatch_sample.c",
|
||||
"$FRAMEWORK_SPI_ROOT/spi_pl022_sample.c",
|
||||
"$FRAMEWORK_SPI_ROOT/spi_sample.c",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"//drivers/framework/sample/platform/spi/include/",
|
||||
"//drivers/framework/support/platform/include/spi",
|
||||
]
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 "spi_dispatch_sample.h"
|
||||
#include "spi_sample.h"
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_sbuf.h"
|
||||
|
||||
#define HDF_LOG_TAG spi_dispatch_sample
|
||||
|
||||
static int32_t SampleSpiTransfer(struct SpiCntlr *cntlr, struct HdfSBuf *txBuf)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
uint32_t readSize = sizeof(struct SpiMsg);
|
||||
struct SpiMsg *msg = NULL;
|
||||
|
||||
if (cntlr == NULL || cntlr->priv == NULL || txBuf == NULL) {
|
||||
HDF_LOGE("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (!HdfSbufReadBuffer(txBuf, (const void **)&msg, &readSize)) {
|
||||
HDF_LOGE("%s: Failed to read sbuf", __func__);
|
||||
return HDF_DEV_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (SampleSpiCntlrTransfer(cntlr, msg, msg->len) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: SampleSpiCntlrTransfer error", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SampleSpiDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
if (client == NULL || client->device == NULL) {
|
||||
HDF_LOGE("%s: client or client->device is NULL", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
struct SpiCntlr *cntlr = (struct SpiCntlr *)client->device->service;
|
||||
if (cntlr == NULL || cntlr->method == NULL) {
|
||||
HDF_LOGE("%s: cntlr or cntlr->method is NULL", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
switch (cmdId) {
|
||||
case SPI_TRANSFER:
|
||||
return SampleSpiTransfer(cntlr, data);
|
||||
default:
|
||||
HDF_LOGE("%s: invalid cmdId %d", __func__, cmdId);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
}
|
||||
Executable
+338
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* 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 "spi_pl022_sample.h"
|
||||
#include "osal_io.h"
|
||||
|
||||
#define HDF_LOG_TAG spi_pl022_sample
|
||||
|
||||
/* Private function prototypes */
|
||||
static int Pl022SampleSetCs(struct Pl022SpiCntlr *cntlr, uint32_t cs, uint32_t flag);
|
||||
static int Pl022SampleFlushFifo(const struct Pl022SpiCntlr *cntlr);
|
||||
static int Pl022SampleTxRx8(const struct Pl022SpiCntlr *cntlr, const struct SpiMsg *msg);
|
||||
static int Pl022SampleTxRx16(const struct Pl022SpiCntlr *cntlr, const struct SpiMsg *msg);
|
||||
static void Pl022SampleEnableCntlr(const struct Pl022SpiCntlr *cntlr);
|
||||
static void Pl022SampleConfigCPSR(const struct Pl022SpiCntlr *cntlr, uint32_t cpsdvsr);
|
||||
static void Pl022SampleConfigCR0(const struct Pl022SpiCntlr *cntlr, uint32_t scr);
|
||||
static void Pl022SampleConfigCR1(const struct Pl022SpiCntlr *cntlr);
|
||||
static int32_t Pl022SampleCfgCs(struct Pl022SpiCntlr *cntlr, uint32_t cs);
|
||||
static void Pl022SampleDisableCntlr(const struct Pl022SpiCntlr *cntlr);
|
||||
static int Pl022SampleCheckTimeout(const struct Pl022SpiCntlr *cntlr);
|
||||
|
||||
int ConfigPl022SpiCntlr(struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t scr;
|
||||
uint32_t cpsdvsr;
|
||||
|
||||
Pl022SampleEnableCntlr(cntlr);
|
||||
/* Check if we can provide the requested rate */
|
||||
if (cntlr->speed > cntlr->maxSpeedHz) {
|
||||
cntlr->speed = cntlr->maxSpeedHz;
|
||||
}
|
||||
/* Min possible */
|
||||
if ((cntlr->speed < cntlr->minSpeedHz) || (cntlr->speed == 0)) {
|
||||
HDF_LOGE("%s: cntlr->speed is %u not support, max %u, min %u", __func__,
|
||||
cntlr->speed, cntlr->maxSpeedHz, cntlr->minSpeedHz);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
/* Check if we can provide the requested bits_per_word */
|
||||
if ((cntlr->bitsPerWord < BITS_PER_WORD_MIN) || (cntlr->bitsPerWord > BITS_PER_WORD_MAX)) {
|
||||
HDF_LOGE("%s: cntlr->bitsPerWord is %u not support", __func__, cntlr->bitsPerWord);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
/* compute spi speed, speed=clk/(cpsdvsr*(scr+1)) */
|
||||
tmp = (cntlr->clkRate) / (cntlr->speed);
|
||||
if (tmp < CPSDVSR_MIN) {
|
||||
cpsdvsr = CPSDVSR_MIN;
|
||||
scr = 0;
|
||||
} else if (tmp <= CPSDVSR_MAX) {
|
||||
cpsdvsr = tmp & (~0x1);
|
||||
scr = (tmp / cpsdvsr) - 1;
|
||||
} else {
|
||||
cpsdvsr = CPSDVSR_MAX;
|
||||
scr = (tmp / cpsdvsr) - 1;
|
||||
}
|
||||
/* config SPICPSR register */
|
||||
Pl022SampleConfigCPSR(cntlr, cpsdvsr);
|
||||
/* config SPICR0 register */
|
||||
Pl022SampleConfigCR0(cntlr, scr);
|
||||
/* config SPICR1 register */
|
||||
Pl022SampleConfigCR1(cntlr);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t TransferOneMessage(struct Pl022SpiCntlr *cntlr, struct SpiMsg *msg)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (msg->speed != 0) {
|
||||
cntlr->speed = msg->speed;
|
||||
}
|
||||
ret = ConfigPl022SpiCntlr(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = Pl022SampleSetCs(cntlr, cntlr->curCs, SPI_CS_ACTIVE);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = Pl022SampleFlushFifo(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if (cntlr->bitsPerWord <= BITS_PER_WORD_DEFAULT) {
|
||||
ret = Pl022SampleTxRx8(cntlr, msg);
|
||||
} else {
|
||||
ret = Pl022SampleTxRx16(cntlr, msg);
|
||||
}
|
||||
if (ret || msg->csChange) {
|
||||
Pl022SampleSetCs(cntlr, cntlr->curCs, SPI_CS_INACTIVE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private function implementations */
|
||||
static int Pl022SampleSetCs(struct Pl022SpiCntlr *cntlr, uint32_t cs, uint32_t flag)
|
||||
{
|
||||
if (Pl022SampleCfgCs(cntlr, cs) != HDF_SUCCESS) {
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (flag == SPI_CS_ACTIVE) {
|
||||
Pl022SampleEnableCntlr(cntlr);
|
||||
} else {
|
||||
Pl022SampleDisableCntlr(cntlr);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int Pl022SampleFlushFifo(const struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t ret;
|
||||
uint32_t tmp = 0;
|
||||
|
||||
ret = Pl022SampleCheckTimeout(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
while (true) {
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_SR);
|
||||
if (!(value & SPI_PL022_SR_RNE)) {
|
||||
break;
|
||||
}
|
||||
if (tmp++ > cntlr->fifoSize) {
|
||||
HDF_LOGE("%s: spi transfer check rx fifo wait timeout", __func__);
|
||||
return HDF_ERR_TIMEOUT;
|
||||
}
|
||||
OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_DR);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int Pl022SampleTxRx8(const struct Pl022SpiCntlr *cntlr, const struct SpiMsg *msg)
|
||||
{
|
||||
uint32_t len = msg->len;
|
||||
uint32_t tmpLen;
|
||||
uint32_t count;
|
||||
const uint8_t *tx = (const uint8_t *)(msg->wbuf);
|
||||
uint8_t *rx = (uint8_t *)(msg->rbuf);
|
||||
uint8_t value;
|
||||
uint32_t ret;
|
||||
|
||||
if (tx == NULL && rx == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
while (len > 0) {
|
||||
if (len > cntlr->fifoSize) {
|
||||
tmpLen = cntlr->fifoSize;
|
||||
} else {
|
||||
tmpLen = len;
|
||||
}
|
||||
len -= tmpLen;
|
||||
/* write fifo */
|
||||
count = tmpLen;
|
||||
value = 0;
|
||||
while (count > 0) {
|
||||
if (tx != NULL) {
|
||||
value = *tx++;
|
||||
}
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_DR);
|
||||
count -= 1;
|
||||
OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_SR);
|
||||
}
|
||||
ret = Pl022SampleCheckTimeout(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
/* read fifo */
|
||||
count = tmpLen;
|
||||
while (count > 0) {
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_DR);
|
||||
if (rx != NULL) {
|
||||
*rx++ = value;
|
||||
}
|
||||
count -= 1;
|
||||
OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_SR);
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int Pl022SampleTxRx16(const struct Pl022SpiCntlr *cntlr, const struct SpiMsg *msg)
|
||||
{
|
||||
uint32_t len = msg->len;
|
||||
uint32_t tmpLen;
|
||||
uint32_t count;
|
||||
const uint16_t *tx = (const uint16_t *)(msg->wbuf);
|
||||
uint16_t *rx = (uint16_t *)(msg->rbuf);
|
||||
uint16_t value;
|
||||
uint32_t ret;
|
||||
|
||||
if (tx == NULL && rx == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
while (len > 0) {
|
||||
ret = cntlr->fifoSize * TWO_BYTES;
|
||||
if (len > ret) {
|
||||
tmpLen = ret;
|
||||
} else {
|
||||
tmpLen = len;
|
||||
}
|
||||
len -= tmpLen;
|
||||
/* write fifo */
|
||||
count = tmpLen;
|
||||
value = 0;
|
||||
while (count >= TWO_BYTES) {
|
||||
if (tx != NULL) {
|
||||
value = *tx++;
|
||||
}
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_DR);
|
||||
count -= TWO_BYTES;
|
||||
}
|
||||
ret = Pl022SampleCheckTimeout(cntlr);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
/* read fifo */
|
||||
count = tmpLen;
|
||||
while (count >= TWO_BYTES) {
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_DR);
|
||||
if (rx != NULL) {
|
||||
*rx++ = value;
|
||||
}
|
||||
count -= TWO_BYTES;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Pl022SampleEnableCntlr(const struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
value |= SPI_PL022_CR1_SSE;
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
}
|
||||
|
||||
static void Pl022SampleConfigCPSR(const struct Pl022SpiCntlr *cntlr, uint32_t cpsdvsr)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CPSR);
|
||||
value &= ~SPI_PL022_CPSR_CPSDVSR;
|
||||
value |= cpsdvsr << SPI_PL022_CPSR_CPSDVSR_SHIFT;
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CPSR);
|
||||
}
|
||||
|
||||
static void Pl022SampleConfigCR0(const struct Pl022SpiCntlr *cntlr, uint32_t scr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t value;
|
||||
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR0);
|
||||
value &= ~SPI_PL022_CR0_DSS;
|
||||
value |= (cntlr->bitsPerWord - 1) << SPI_PL022_CR0_DSS_SHIFT;
|
||||
value &= ~SPI_PL022_CR0_FRF;
|
||||
value &= ~SPI_PL022_CR0_SPO;
|
||||
tmp = (!!(cntlr->mode & SPI_CLK_POLARITY)) ? (1 << SPI_PL022_CR0_SPO_SHIFT) : 0;
|
||||
value |= tmp;
|
||||
value &= ~SPI_PL022_CR0_SPH;
|
||||
tmp = (!!(cntlr->mode & SPI_CLK_PHASE)) ? (1 << SPI_PL022_CR0_SPH_SHIFT) : 0;
|
||||
value |= tmp;
|
||||
value &= ~SPI_PL022_CR0_SCR;
|
||||
value |= (scr << SPI_PL022_CR0_SCR_SHIFT);
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR0);
|
||||
}
|
||||
|
||||
static void Pl022SampleConfigCR1(const struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t value;
|
||||
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
value &= ~SPI_PL022_CR1_LBM;
|
||||
tmp = (!!(cntlr->mode & SPI_MODE_LOOP)) ? (1 << SPI_PL022_CR1_LBN_SHIFT) : 0;
|
||||
value |= tmp;
|
||||
value &= ~SPI_PL022_CR1_MS;
|
||||
value &= ~SPI_PL022_CR1_BIG_END;
|
||||
tmp = (!!(cntlr->mode & SPI_MODE_LSBFE)) ? (1 << SPI_PL022_CR1_BIG_END_SHIFT) : 0;
|
||||
value |= tmp;
|
||||
value &= ~SPI_PL022_CR1_ALT;
|
||||
value |= 0x1 << SPI_PL022_CR1_ALT_SHIFT;
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
}
|
||||
|
||||
static int32_t Pl022SampleCfgCs(struct Pl022SpiCntlr *cntlr, uint32_t cs)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t miscCtrlCs;
|
||||
|
||||
if ((cs + 1) > cntlr->numCs) {
|
||||
HDF_LOGE("%s: cs %u is big than cntlr csNum %u", __func__, cs, cntlr->numCs);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (cntlr->numCs == 1) {
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
miscCtrlCs = (UINTPTR)(cntlr->regBase) + REG_SPI_MISC_CTRL;
|
||||
value = OSAL_READL(miscCtrlCs);
|
||||
value &= ~miscCtrlCs;
|
||||
value |= (cs << cntlr->miscCtrlCsShift);
|
||||
OSAL_WRITEL(value, miscCtrlCs);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void Pl022SampleDisableCntlr(const struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
value &= ~SPI_PL022_CR1_SSE;
|
||||
OSAL_WRITEL(value, (UINTPTR)(cntlr->regBase) + REG_SPI_PL022_CR1);
|
||||
}
|
||||
|
||||
static int Pl022SampleCheckTimeout(const struct Pl022SpiCntlr *cntlr)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t tmp = 0;
|
||||
|
||||
while (true) {
|
||||
value = OSAL_READL((UINTPTR)(cntlr->regBase) + REG_SPI_PL022_SR);
|
||||
if ((value & SPI_PL022_SR_TFE) && (!(value & SPI_PL022_SR_BSY))) {
|
||||
break;
|
||||
}
|
||||
if (tmp++ > MAX_WAIT) {
|
||||
HDF_LOGE("%s: spi transfer wait timeout", __func__);
|
||||
return HDF_ERR_TIMEOUT;
|
||||
}
|
||||
OsalUDelay(1);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
Executable
+355
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* 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 "spi_sample.h"
|
||||
#include "spi_pl022_sample.h"
|
||||
#include "spi_dispatch_sample.h"
|
||||
#include "device_resource_if.h"
|
||||
#include "hdf_base.h"
|
||||
#include "osal_mem.h"
|
||||
#include "hdf_log.h"
|
||||
#include "spi_core.h"
|
||||
#include "los_vm_zone.h"
|
||||
|
||||
#define HDF_LOG_TAG spi_sample
|
||||
|
||||
/* HdfDriverEntry hook function prototypes */
|
||||
static int32_t SampleSpiDriverBind(struct HdfDeviceObject *device);
|
||||
static int32_t SampleSpiDriverInit(struct HdfDeviceObject *device);
|
||||
static void SampleSpiDriverRelease(struct HdfDeviceObject *device);
|
||||
|
||||
/* SpiCntlrMethod definition */
|
||||
struct SpiCntlrMethod g_sampleSpiMethod = {
|
||||
.Transfer = SampleSpiCntlrTransfer,
|
||||
.SetCfg = SampleSpiCntlrSetCfg,
|
||||
.GetCfg = SampleSpiCntlrGetCfg,
|
||||
};
|
||||
|
||||
/* HdfDriverEntry definition */
|
||||
struct HdfDriverEntry g_sampleSpiDriverEntry = {
|
||||
.moduleVersion = 1,
|
||||
.moduleName = "SPI_SAMPLE",
|
||||
.Bind = SampleSpiDriverBind,
|
||||
.Init = SampleSpiDriverInit,
|
||||
.Release = SampleSpiDriverRelease,
|
||||
};
|
||||
|
||||
/* Init HdfDriverEntry */
|
||||
HDF_INIT(g_sampleSpiDriverEntry);
|
||||
|
||||
/* Private function prototypes */
|
||||
static int InitSpiDevice(struct SpiCntlr *cntlr, const struct DeviceResourceNode *property);
|
||||
static int ConfigSpiDevice(struct Pl022SpiCntlr *pl022Cntlr);
|
||||
static int32_t InitSpiDeviceResource(struct Pl022SpiCntlr *pl022Cntlr, const struct DeviceResourceNode *node);
|
||||
static int32_t CreateSpiDev(struct Pl022SpiCntlr *pl022Cntlr);
|
||||
static void ReleaseSpiDev(struct Pl022SpiCntlr *pl022Cntlr);
|
||||
static struct SpiDev *FindDeviceByCsNum(const struct Pl022SpiCntlr *pl022Cntlr, uint32_t cs);
|
||||
|
||||
/* HdfDriverEntry hook function implementations */
|
||||
static int32_t SampleSpiDriverBind(struct HdfDeviceObject *device)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
struct SpiCntlr *cntlr = NULL;
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is NULL", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = SpiCntlrCreate(device);
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("%s: cntlr is NULL", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
cntlr->service.Dispatch = SampleSpiDispatch;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SampleSpiDriverInit(struct HdfDeviceObject *device)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
int ret;
|
||||
struct SpiCntlr *cntlr = NULL;
|
||||
if (device == NULL || device->property == NULL) {
|
||||
HDF_LOGE("%s: device or device->property is null", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
cntlr = SpiCntlrFromDevice(device);
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("%s: cntlr is null", __func__);
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
ret = InitSpiDevice(cntlr, device->property);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: InitSpiDevice failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
ret = ConfigSpiDevice(cntlr->priv);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: ConfigSpiDevice failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SampleSpiDriverRelease(struct HdfDeviceObject *device)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
struct SpiCntlr *cntlr = NULL;
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: device is null", __func__);
|
||||
return;
|
||||
}
|
||||
cntlr = SpiCntlrFromDevice(device);
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("%s: cntlr is null", __func__);
|
||||
return;
|
||||
}
|
||||
if (cntlr->priv != NULL) {
|
||||
ReleaseSpiDev((struct Pl022SpiCntlr *)cntlr->priv);
|
||||
}
|
||||
SpiCntlrDestroy(cntlr);
|
||||
}
|
||||
|
||||
/* SPI function implementations */
|
||||
int32_t SampleSpiCntlrTransfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
int ret;
|
||||
struct Pl022SpiCntlr *pl022Cntlr = NULL;
|
||||
struct SpiDev *spiDev = NULL;
|
||||
|
||||
if (cntlr == NULL || cntlr->priv == NULL || msg == NULL || count == 0) {
|
||||
HDF_LOGE("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
pl022Cntlr = (struct Pl022SpiCntlr *)cntlr->priv;
|
||||
spiDev = FindDeviceByCsNum(pl022Cntlr, cntlr->curCs);
|
||||
if (spiDev == NULL) {
|
||||
HDF_LOGE("%s: spiDev is null, curCs %u", __func__, cntlr->curCs);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pl022Cntlr->mode = spiDev->cfg.mode;
|
||||
pl022Cntlr->transferMode = spiDev->cfg.transferMode;
|
||||
pl022Cntlr->bitsPerWord = spiDev->cfg.bitsPerWord;
|
||||
pl022Cntlr->maxSpeedHz = spiDev->cfg.maxSpeedHz;
|
||||
pl022Cntlr->curCs = spiDev->csNum;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
ret = TransferOneMessage(pl022Cntlr, &(msg[i]));
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: transfer error", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SampleSpiCntlrSetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
struct Pl022SpiCntlr *pl022Cntlr = NULL;
|
||||
struct SpiDev *spiDev = NULL;
|
||||
|
||||
if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
|
||||
HDF_LOGE("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
pl022Cntlr = (struct Pl022SpiCntlr *)cntlr->priv;
|
||||
spiDev = FindDeviceByCsNum(pl022Cntlr, cntlr->curCs);
|
||||
if (spiDev == NULL) {
|
||||
HDF_LOGE("%s: spiDev is null, curCs %u", __func__, cntlr->curCs);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
spiDev->cfg.mode = cfg->mode;
|
||||
spiDev->cfg.transferMode = cfg->transferMode;
|
||||
spiDev->cfg.bitsPerWord = cfg->bitsPerWord;
|
||||
if ((cfg->bitsPerWord < BITS_PER_WORD_MIN) || (cfg->bitsPerWord > BITS_PER_WORD_MAX)) {
|
||||
HDF_LOGE("%s: bitsPerWord %u not support, use default bitsPerWord %u",
|
||||
__func__, cfg->bitsPerWord, BITS_PER_WORD_DEFAULT);
|
||||
spiDev->cfg.bitsPerWord = BITS_PER_WORD_DEFAULT;
|
||||
}
|
||||
if (cfg->maxSpeedHz != 0) {
|
||||
spiDev->cfg.maxSpeedHz = cfg->maxSpeedHz;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SampleSpiCntlrGetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
|
||||
{
|
||||
HDF_LOGD("%s: Enter", __func__);
|
||||
struct Pl022SpiCntlr *pl022Cntlr = NULL;
|
||||
struct SpiDev *spiDev = NULL;
|
||||
|
||||
if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
|
||||
HDF_LOGE("%s: invalid parameter", __func__);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
pl022Cntlr = (struct Pl022SpiCntlr *)cntlr->priv;
|
||||
spiDev = FindDeviceByCsNum(pl022Cntlr, cntlr->curCs);
|
||||
if (spiDev == NULL) {
|
||||
HDF_LOGE("%s: spiDev is null, curCs %u", __func__, cntlr->curCs);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
cfg->mode = spiDev->cfg.mode;
|
||||
cfg->transferMode = spiDev->cfg.transferMode;
|
||||
cfg->bitsPerWord = spiDev->cfg.bitsPerWord;
|
||||
cfg->maxSpeedHz = spiDev->cfg.maxSpeedHz;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
/* Private function implementations */
|
||||
static int InitSpiDevice(struct SpiCntlr *cntlr, const struct DeviceResourceNode *property)
|
||||
{
|
||||
int ret;
|
||||
struct Pl022SpiCntlr *pl022Cntlr = NULL;
|
||||
|
||||
pl022Cntlr = (struct Pl022SpiCntlr *)OsalMemCalloc(sizeof(*pl022Cntlr));
|
||||
if (pl022Cntlr == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc error", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
ret = InitSpiDeviceResource(pl022Cntlr, property);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: InitSpiDeviceResource error", __func__);
|
||||
OsalMemFree(pl022Cntlr);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pl022Cntlr->maxSpeedHz = (pl022Cntlr->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN);
|
||||
pl022Cntlr->minSpeedHz = (pl022Cntlr->clkRate) / ((SCR_MAX + 1) * CPSDVSR_MAX);
|
||||
DListHeadInit(&pl022Cntlr->deviceList);
|
||||
pl022Cntlr->cntlr = cntlr;
|
||||
cntlr->priv = pl022Cntlr;
|
||||
cntlr->busNum = pl022Cntlr->busNum;
|
||||
cntlr->method = &g_sampleSpiMethod;
|
||||
ret = CreateSpiDev(pl022Cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
ReleaseSpiDev(pl022Cntlr);
|
||||
return ret;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int ConfigSpiDevice(struct Pl022SpiCntlr *pl022Cntlr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ConfigPl022SpiCntlr(pl022Cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: HiPl022Config error", __func__);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t InitSpiDeviceResource(struct Pl022SpiCntlr *pl022Cntlr, const struct DeviceResourceNode *node)
|
||||
{
|
||||
uint32_t tmp;
|
||||
struct DeviceResourceIface *resIf = NULL;
|
||||
|
||||
resIf = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
|
||||
if (resIf == NULL || resIf->GetUint8 == NULL || resIf->GetUint16 == NULL || resIf->GetUint32 == NULL) {
|
||||
HDF_LOGE("%s: resource is invalid", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint32(node, "regBase", &tmp, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read regBase fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pl022Cntlr->regBase = (void *)(uintptr_t)(IO_DEVICE_ADDR(tmp));
|
||||
if (resIf->GetUint32(node, "busNum", &pl022Cntlr->busNum, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read busNum fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint32(node, "numCs", &pl022Cntlr->numCs, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read numCs fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint32(node, "speed", &pl022Cntlr->speed, DEFAULT_SPEED) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read speed fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint32(node, "fifoSize", &pl022Cntlr->fifoSize, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read fifoSize fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint32(node, "clkRate", &pl022Cntlr->clkRate, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read clkRate fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint16(node, "mode", &pl022Cntlr->mode, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read mode fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint8(node, "bitsPerWord", &pl022Cntlr->bitsPerWord, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read bitsPerWord fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
if (resIf->GetUint8(node, "transferMode", &pl022Cntlr->transferMode, 0) != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read comMode fail", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
pl022Cntlr->regCrg = REG_SPI_CRG;
|
||||
pl022Cntlr->clkEnBit = SPI_CRG_CLK_EN;
|
||||
pl022Cntlr->clkRstBit = SPI_CRG_CLK_RST;
|
||||
pl022Cntlr->regMiscCtrl = REG_SPI_MISC_CTRL;
|
||||
pl022Cntlr->miscCtrlCs = SPI_MISC_CTRL_CS;
|
||||
pl022Cntlr->miscCtrlCsShift = SPI_MISC_CTRL_CS_SHIFT;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t CreateSpiDev(struct Pl022SpiCntlr *pl022Cntlr)
|
||||
{
|
||||
uint32_t i;
|
||||
struct SpiDev *device = NULL;
|
||||
|
||||
for (i = 0; i < pl022Cntlr->numCs; i++) {
|
||||
device = (struct SpiDev *)OsalMemCalloc(sizeof(*device));
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("%s: OsalMemCalloc error", __func__);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
device->cntlr = pl022Cntlr->cntlr;
|
||||
device->csNum = i;
|
||||
device->cfg.bitsPerWord = pl022Cntlr->bitsPerWord;
|
||||
device->cfg.transferMode = pl022Cntlr->transferMode;
|
||||
device->cfg.maxSpeedHz = pl022Cntlr->maxSpeedHz;
|
||||
device->cfg.mode = pl022Cntlr->mode;
|
||||
DListHeadInit(&device->list);
|
||||
DListInsertTail(&device->list, &pl022Cntlr->deviceList);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void ReleaseSpiDev(struct Pl022SpiCntlr *pl022Cntlr)
|
||||
{
|
||||
struct SpiDev *dev = NULL;
|
||||
struct SpiDev *tmpDev = NULL;
|
||||
|
||||
DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(pl022Cntlr->deviceList), struct SpiDev, list) {
|
||||
if (dev != NULL) {
|
||||
DListRemove(&(dev->list));
|
||||
OsalMemFree(dev);
|
||||
}
|
||||
}
|
||||
OsalMemFree(pl022Cntlr);
|
||||
}
|
||||
|
||||
static struct SpiDev *FindDeviceByCsNum(const struct Pl022SpiCntlr *pl022Cntlr, uint32_t cs)
|
||||
{
|
||||
struct SpiDev *dev = NULL;
|
||||
struct SpiDev *tmpDev = NULL;
|
||||
|
||||
if (pl022Cntlr == NULL || pl022Cntlr->numCs <= cs) {
|
||||
return NULL;
|
||||
}
|
||||
DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(pl022Cntlr->deviceList), struct SpiDev, list) {
|
||||
if (dev->csNum == cs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
Executable
+14
@@ -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",
|
||||
]
|
||||
}
|
||||
Executable
+12
@@ -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.
|
||||
Executable
+41
@@ -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",
|
||||
]
|
||||
}
|
||||
Executable
+38
@@ -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;
|
||||
}
|
||||
Executable
+44
@@ -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
@@ -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;
|
||||
}
|
||||
Executable
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 "securec.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);
|
||||
}
|
||||
Executable
+29
@@ -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
|
||||
Executable
+36
@@ -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
@@ -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
@@ -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
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
Executable
+22
@@ -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/" ]
|
||||
}
|
||||
Executable
+24
@@ -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;
|
||||
}
|
||||
Executable
+191
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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 = HDF_FAILURE;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 "osal_mem.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;
|
||||
}
|
||||
Executable
+90
@@ -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;
|
||||
}
|
||||
|
||||
Executable
+344
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user