diff --git a/khdf/liteos_m/BUILD.gn b/khdf/liteos_m/BUILD.gn index e8fd461c3a2aab890a6fd1ded0aca7584435d9da..37e750b25bb7e6c0c9a4cf4cde657b2831f5845b 100644 --- a/khdf/liteos_m/BUILD.gn +++ b/khdf/liteos_m/BUILD.gn @@ -36,6 +36,7 @@ hdf_driver("hdf_lite") { "osal", "platform", "test", + HDF_ADAPTER_PLATFORM_PATH, ] } diff --git a/khdf/liteos_m/hdf.gni b/khdf/liteos_m/hdf.gni index be238e78478349cec29633975b96458ac3098880..b1b631bff14c4655c0eaa26c8bb78bc334d5c8cd 100644 --- a/khdf/liteos_m/hdf.gni +++ b/khdf/liteos_m/hdf.gni @@ -32,6 +32,7 @@ import("//kernel/liteos_m/liteos.gni") HDF_FRAMEWORKS_PATH = "//drivers/framework" HDF_PERIPHERAL_PATH = "//drivers/peripheral" +HDF_ADAPTER_PLATFORM_PATH = "//drivers/adapter/platform" template("hdf_driver") { if (defined(invoker.module_switch)) { diff --git a/khdf/liteos_m/platform/BUILD.gn b/khdf/liteos_m/platform/BUILD.gn index 91a4b406becf7ac0d7b54e1d4cd1469fa494153d..84c915258f60cf376ded5326e35fd1adbf706e51 100755 --- a/khdf/liteos_m/platform/BUILD.gn +++ b/khdf/liteos_m/platform/BUILD.gn @@ -46,7 +46,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/gpio/gpio_if.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/gpio/gpio_manager.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/gpio" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C)) { @@ -54,7 +53,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/i2c/i2c_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/i2c/i2c_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/i2c" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC)) { @@ -62,12 +60,10 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/adc/adc_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/adc/adc_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/adc" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM)) { sources += [ "$HDF_FRAMEWORKS_PATH/support/platform/src/pwm/pwm_core.c" ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/pwm" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_RTC)) { @@ -76,7 +72,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/rtc/rtc_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/rtc/rtc_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/rtc" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_DSI)) { @@ -84,7 +79,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/mipi/mipi_dsi_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/mipi/mipi_dsi_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/mipi" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_CSI)) { @@ -92,7 +86,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/mipi/mipi_csi_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/mipi/mipi_csi_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/mipi" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI)) { @@ -100,7 +93,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/spi/spi_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/spi/spi_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/spi" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART)) { @@ -108,7 +100,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/uart/uart_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/uart/uart_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/uart" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2S)) { @@ -116,7 +107,6 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/i2s/i2s_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/i2s/i2s_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/i2s" ] } if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_WATCHDOG)) { @@ -124,10 +114,42 @@ hdf_driver("hdf_platform_lite") { "$HDF_FRAMEWORKS_PATH/support/platform/src/watchdog/watchdog_core.c", "$HDF_FRAMEWORKS_PATH/support/platform/src/watchdog/watchdog_if.c", ] - include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/watchdog" ] } } config("public") { include_dirs = [ "$HDF_FRAMEWORKS_PATH/support/platform/include/fwk" ] + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/gpio" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/i2c" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/adc" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/pwm" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_RTC)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/rtc" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_DSI)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/mipi" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_CSI)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/mipi" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/spi" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/uart" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2S)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/i2s" ] + } + if (defined(LOSCFG_DRIVERS_HDF_PLATFORM_WATCHDOG)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/watchdog" ] + } } diff --git a/platform/BUILD.gn b/platform/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..96add7a42256fa72cbaf3045093c4f66a227bafd --- /dev/null +++ b/platform/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_group("platform") { + modules = [ + "gpio", + "i2c", + "pwm", + "spi", + "uart", + "watchdog", + ] +} diff --git a/platform/gpio/BUILD.gn b/platform/gpio/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2484dc929e43e01922c76c59be0e00f90b79a3ac --- /dev/null +++ b/platform/gpio/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "gpio_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/gpio/gpio_bes.c b/platform/gpio/gpio_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..ed4d18b9765dc3a03d97494398aa315114f0db81 --- /dev/null +++ b/platform/gpio/gpio_bes.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "gpio_bes.h" +#include +#include "hal_iomux.h" +#include "gpio_if.h" +#include "device_resource_if.h" +#include "osal_irq.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG gpioDriver +static struct GpioCntlr gpioCntlr; +struct OemGpioIrqHandler { + uint8_t port; + GpioIrqFunc func; + void *arg; +}; + +enum HAL_GPIO_PIN_T g_gpioPinReflectionMap[HAL_GPIO_PIN_LED_NUM] = {0}; +static struct OemGpioIrqHandler g_oemGpioIrqHandler[HAL_GPIO_PIN_LED_NUM] = {0}; +static struct HAL_GPIO_IRQ_CFG_T g_gpioIrqCfg[HAL_GPIO_PIN_LED_NUM] = {0}; + +static struct HAL_GPIO_IRQ_CFG_T HalGpioGetIrqConfig(enum HAL_GPIO_PIN_T pin) +{ + struct HAL_GPIO_IRQ_CFG_T irqCfg; + + irqCfg.irq_enable = g_gpioIrqCfg[pin].irq_enable; + irqCfg.irq_debounce = g_gpioIrqCfg[pin].irq_debounce; + irqCfg.irq_type = g_gpioIrqCfg[pin].irq_type; + irqCfg.irq_polarity = g_gpioIrqCfg[pin].irq_polarity; + + return irqCfg; +} + +static void OemGpioIrqHdl(enum HAL_GPIO_PIN_T pin) +{ + if (pin >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, pin); + return; + } + for (size_t i = 0; i < HAL_GPIO_PIN_LED_NUM; i++) { + if (pin == (enum HAL_GPIO_PIN_T)g_gpioPinReflectionMap[i]) { + GpioCntlrIrqCallback(&gpioCntlr, i); + return; + } + } +} + +/* dispatch */ +int32_t GpioDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + if (client == NULL || client->device == NULL || data == NULL || reply == NULL) { + HDF_LOGE("%s: client or client->device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; +} + +/* HdfDriverEntry method definitions */ +static int32_t GpioDriverBind(struct HdfDeviceObject *device); +static int32_t GpioDriverInit(struct HdfDeviceObject *device); +static void GpioDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_GpioDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_GPIO_MODULE_HDF", + .Bind = GpioDriverBind, + .Init = GpioDriverInit, + .Release = GpioDriverRelease, +}; +HDF_INIT(g_GpioDriverEntry); + +/* GpioMethod method definitions */ +static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val); +static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val); +static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir); +static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir); +static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg); +static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio); +static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio); +static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio); +/* GpioMethod definitions */ +struct GpioMethod g_GpioCntlrMethod = { + .request = NULL, + .release = NULL, + .write = GpioDevWrite, + .read = GpioDevRead, + .setDir = GpioDevSetDir, + .getDir = GpioDevGetDir, + .toIrq = NULL, + .setIrq = GpioDevSetIrq, + .unsetIrq = GpioDevUnSetIrq, + .enableIrq = GpioDevEnableIrq, + .disableIrq = GpioDevDisableIrq, +}; + +static int InitGpioDevice(struct GpioDevice *device) +{ + struct HAL_IOMUX_PIN_FUNCTION_MAP gpioCfg; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + gpioCfg.pin = device->port; + gpioCfg.function = HAL_IOMUX_FUNC_AS_GPIO; + gpioCfg.volt = HAL_IOMUX_PIN_VOLTAGE_VIO; + + if ((device->config == OUTPUT_PUSH_PULL) || (device->config == OUTPUT_OPEN_DRAIN_PULL_UP) + || (device->config == INPUT_PULL_UP) || (device->config == IRQ_MODE)) { + gpioCfg.pull_sel = HAL_IOMUX_PIN_PULLUP_ENABLE; + } else if ((device->config == INPUT_PULL_DOWN)) { + gpioCfg.pull_sel = HAL_IOMUX_PIN_PULLDOWN_ENABLE; + } else { + gpioCfg.pull_sel = HAL_IOMUX_PIN_NOPULL; + } + + hal_iomux_init(&gpioCfg, 1); + + return HDF_SUCCESS; +} + +static uint32_t GetGpioDeviceResource( + struct GpioDevice *device, const struct DeviceResourceNode *resourceNode) +{ + uint32_t relPin; + int32_t ret; + struct GpioResource *resource = NULL; + struct DeviceResourceIface *dri = NULL; + if (device == NULL || resourceNode == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("%s: resource is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid"); + return HDF_ERR_INVALID_OBJECT; + } + + if (dri->GetUint32(resourceNode, "pinNum", &resource->pinNum, 0) != HDF_SUCCESS) { + HDF_LOGE("gpio config read pinNum fail"); + return HDF_FAILURE; + } + + for (size_t i = 0; i < resource->pinNum; i++) { + if (dri->GetUint32ArrayElem(resourceNode, "pin", i, &resource->pin, 0) != HDF_SUCCESS) { + HDF_LOGE("gpio config read pin fail"); + return HDF_FAILURE; + } + + if (dri->GetUint32ArrayElem(resourceNode, "realPin", i, &resource->realPin, 0) != HDF_SUCCESS) { + HDF_LOGE("gpio config read realPin fail"); + return HDF_FAILURE; + } + + if (dri->GetUint32ArrayElem(resourceNode, "config", i, &resource->config, 0) != HDF_SUCCESS) { + HDF_LOGE("gpio config read config fail"); + return HDF_FAILURE; + } + + relPin = resource->realPin / DECIMALNUM * OCTALNUM + resource->realPin % DECIMALNUM; + g_gpioPinReflectionMap[resource->pin] = relPin; + device->config = resource->config; + resource->pin = relPin; + device->port = relPin; + + ret = InitGpioDevice(device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("InitGpioDevice FAIL\r\n"); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} + +static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + + struct GpioDevice *gpioDevice = NULL; + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: property is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + gpioDevice = (struct GpioDevice *)OsalMemAlloc(sizeof(struct GpioDevice)); + if (gpioDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc gpioDevice error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetGpioDeviceResource(gpioDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(gpioDevice); + return HDF_FAILURE; + } + + gpioCntlr->count = gpioDevice->resource.pinNum; + + return HDF_SUCCESS; +} + +static int32_t GpioDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct GpioCntlr *gpioCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + gpioCntlr = GpioCntlrFromDevice(device); + if (gpioCntlr == NULL) { + HDF_LOGE("GpioCntlrFromDevice fail\r\n"); + return HDF_DEV_ERR_NO_DEVICE_SERVICE; + } + + ret = AttachGpioDevice(gpioCntlr, device); // GpioCntlr add GpioDevice to priv + if (ret != HDF_SUCCESS) { + HDF_LOGE("AttachGpioDevice fail\r\n"); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + gpioCntlr->ops = &g_GpioCntlrMethod; // register callback + ret = GpioCntlrAdd(gpioCntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioCntlrAdd fail %d\r\n", gpioCntlr->start); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t GpioDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("Sample device object is null!"); + return HDF_ERR_INVALID_PARAM; + } + + gpioCntlr.device.hdfDev = device; + device->service = gpioCntlr.device.service; + + return HDF_SUCCESS; +} + +static void GpioDriverRelease(struct HdfDeviceObject *device) +{ + struct GpioCntlr *gpioCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + + gpioCntlr = GpioCntlrFromDevice(device); + if (gpioCntlr == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return; + } + + gpioCntlr->ops = NULL; + OsalMemFree(gpioCntlr); +} + +/* dev api */ +static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val) +{ + (void)cntlr; + uint16_t halGpio = g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, halGpio); + return HDF_ERR_NOT_SUPPORT; + } + + hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)halGpio, HAL_GPIO_DIR_OUT, val); + + return HDF_SUCCESS; +} + +static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val) +{ + (void)cntlr; + uint16_t value; + uint16_t halGpio = g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, halGpio); + return HDF_ERR_NOT_SUPPORT; + } + + value = (uint16_t)hal_gpio_pin_get_val((enum HAL_GPIO_PIN_T)halGpio); + *val = value; + + return HDF_SUCCESS; +} + +static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir) +{ + (void)cntlr; + uint16_t halGpio = g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, halGpio); + return HDF_ERR_NOT_SUPPORT; + } + + hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)halGpio, (enum HAL_GPIO_DIR_T)dir, 0); + + return HDF_SUCCESS; +} + +static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir) +{ + (void)cntlr; + uint16_t value; + uint16_t halGpio = g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, gpio); + return HDF_ERR_NOT_SUPPORT; + } + + value = (uint16_t)hal_gpio_pin_get_dir((enum HAL_GPIO_PIN_T)halGpio); + *dir = value; + + return HDF_SUCCESS; +} + +static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg) +{ + (void)cntlr; + enum HAL_GPIO_PIN_T pin = (enum HAL_GPIO_PIN_T)g_gpioPinReflectionMap[gpio]; + if (pin >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, pin); + return HDF_ERR_NOT_SUPPORT; + } + + if ((mode == OSAL_IRQF_TRIGGER_RISING) || (mode == OSAL_IRQF_TRIGGER_FALLING)) { + g_gpioIrqCfg[pin].irq_type = HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE; + } else if ((mode == OSAL_IRQF_TRIGGER_HIGH) || (mode == OSAL_IRQF_TRIGGER_LOW)) { + g_gpioIrqCfg[pin].irq_type = HAL_GPIO_IRQ_TYPE_LEVEL_SENSITIVE; + } else { + HDF_LOGE("%s %d, error mode:%d", __func__, __LINE__, mode); + return HDF_ERR_NOT_SUPPORT; + } + + g_oemGpioIrqHandler[pin].port = gpio; + g_oemGpioIrqHandler[pin].func = func; + g_oemGpioIrqHandler[pin].arg = arg; + + g_gpioIrqCfg[pin].irq_polarity = mode; + + return HDF_SUCCESS; +} + +static int32_t GpioDevUnSetIrq(struct GpioCntlr *cntlr, uint16_t gpio) +{ + (void)cntlr; + enum HAL_GPIO_PIN_T pin = (enum HAL_GPIO_PIN_T)g_gpioPinReflectionMap[gpio]; + if (pin >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, pin); + return HDF_ERR_NOT_SUPPORT; + } + + g_oemGpioIrqHandler[pin].func = NULL; + g_oemGpioIrqHandler[pin].arg = NULL; + + return HDF_SUCCESS; +} + +static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio) +{ + (void)cntlr; + struct HAL_GPIO_IRQ_CFG_T gpioCfg; + uint16_t halGpio = (enum HAL_GPIO_PIN_T)g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, (enum HAL_GPIO_PIN_T)halGpio); + return HDF_ERR_NOT_SUPPORT; + } + + hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)halGpio, HAL_GPIO_DIR_IN, 0); + + gpioCfg.irq_enable = true; + gpioCfg.irq_debounce = true; + gpioCfg.irq_polarity = g_gpioIrqCfg[(enum HAL_GPIO_PIN_T)halGpio].irq_polarity; + gpioCfg.irq_handler = OemGpioIrqHdl; + gpioCfg.irq_type = g_gpioIrqCfg[(enum HAL_GPIO_PIN_T)halGpio].irq_type; + g_gpioIrqCfg[halGpio] = gpioCfg; + + hal_gpio_setup_irq((enum HAL_GPIO_PIN_T)halGpio, &gpioCfg); + + return HDF_SUCCESS; +} + +static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio) +{ + (void)cntlr; + uint16_t halGpio = (enum HAL_GPIO_PIN_T)g_gpioPinReflectionMap[gpio]; + if ((enum HAL_GPIO_PIN_T)halGpio >= HAL_GPIO_PIN_LED_NUM) { + HDF_LOGE("%s %d, error pin:%d", __func__, __LINE__, halGpio); + return HDF_ERR_NOT_SUPPORT; + } + + const struct HAL_GPIO_IRQ_CFG_T gpioCfg = { + .irq_enable = false, + .irq_debounce = false, + .irq_polarity = HAL_GPIO_IRQ_POLARITY_LOW_FALLING, + .irq_handler = NULL, + .irq_type = HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE, + }; + + hal_gpio_setup_irq((enum HAL_GPIO_PIN_T)halGpio, &gpioCfg); + + return HDF_SUCCESS; +} diff --git a/platform/gpio/gpio_bes.h b/platform/gpio/gpio_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..723442fc5751aa84072dcac942c13b75d3c7cd71 --- /dev/null +++ b/platform/gpio/gpio_bes.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __GPIO_BES_H__ +#define __GPIO_BES_H__ + +#include "gpio_core.h" +#include "gpio_if.h" +#include "hal_gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Pin configuration + */ +enum GPIO_CONFIG { + ANALOG_MODE, /* Used as a function pin, input and output analog */ + IRQ_MODE, /* Used to trigger interrupt */ + INPUT_PULL_UP, /* Input with an internal pull-up resistor - use with devices + that actively drive the signal low - e.g. button connected to ground */ + INPUT_PULL_DOWN, /* Input with an internal pull-down resistor - use with devices + that actively drive the signal high - e.g. button connected to a power rail */ + INPUT_HIGH_IMPEDANCE, /* Input - must always be driven, either actively or by an external pullup resistor */ + OUTPUT_PUSH_PULL, /* Output actively driven high and actively driven low - + must not be connected to other active outputs - e.g. LED output */ + OUTPUT_OPEN_DRAIN_NO_PULL, /* Output actively driven low but is high-impedance when set high - + can be connected to other open-drain/open-collector outputs. + Needs an external pull-up resistor */ + OUTPUT_OPEN_DRAIN_PULL_UP, /* Output actively driven low and is pulled high + with an internal resistor when set high - + can be connected to other open-drain/open-collector outputs. */ +}; + +struct GpioResource { + uint32_t pin; + uint32_t realPin; + uint32_t config; + uint32_t pinNum; + uint32_t type; /**< Type of the input event EV_KEY */ + uint32_t code; /**< Specific code item of the input event KEY_POWER*/ + unsigned long physBase; +}; + +enum GpioDeviceState { + GPIO_DEVICE_UNINITIALIZED = 0x0u, + GPIO_DEVICE_INITIALIZED = 0x1u, +}; + +struct GpioDevice { + uint8_t port; /* gpio port */ + struct GpioResource resource; + enum GPIO_CONFIG config; /* gpio config */ +}; + +typedef int32_t (*oem_gpio_irq_handler_t)(uint16_t gpio, void *data); + +#define DECIMALNUM 10 +#define OCTALNUM 8 +#ifdef __cplusplus +} +#endif + +#endif /* __GPIO_H__ */ \ No newline at end of file diff --git a/platform/i2c/BUILD.gn b/platform/i2c/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..bd9def414cb7995801099c00ea3dccea29aeef7e --- /dev/null +++ b/platform/i2c/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "i2c_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/i2c/i2c_bes.c b/platform/i2c/i2c_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..26097edfeeb1b26b94d611d9005038d2de0f8dad --- /dev/null +++ b/platform/i2c/i2c_bes.c @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "i2c_bes.h" +#include +#include +#include "i2c_core.h" +#include "i2c_if.h" +#include "hdf_device_desc.h" +#include "hdf_platform.h" +#include "hdf_log.h" + +#define DEC_NUM 10 +#define GROUP_PIN_NUM 8 +#define I2C_INVALID_ADDR 0xFFFF + +/* HdfDriverEntry method definitions */ +static int32_t i2cDriverBind(struct HdfDeviceObject *device); +static int32_t i2cDriverInit(struct HdfDeviceObject *device); +static void i2cDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_i2cDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_I2C_MODULE_HDF", + .Bind = i2cDriverBind, + .Init = i2cDriverInit, + .Release = i2cDriverRelease, +}; + +// Initialize HdfDriverEntry +HDF_INIT(g_i2cDriverEntry); + +/* I2cHostMethod method definitions */ +static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); + +struct I2cMethod g_i2cHostMethod = { + .transfer = i2cHostTransfer, +}; + +int32_t InitI2cDevice(struct I2cDevice *device) +{ + int32_t ret = -1; + uint32_t i2cPort; + struct I2cResource *resource = NULL; + struct HAL_I2C_CONFIG_T *i2cConfig = NULL; + if (device == NULL) { + HDF_LOGE("device is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + i2cConfig = &device->i2cCfg; + if (i2cConfig == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxI2c[] = { + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENABLE}, + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENABLE}, + }; + + device->port = resource->port; + i2cPort = device->port; + if (i2cPort > HAL_I2C_ID_NUM) { + HDF_LOGE("i2c port %u not support\r\n", i2cPort); + return HDF_ERR_NOT_SUPPORT; + } + + if (i2cPort == 0) { + pinMuxI2c[0].function = HAL_IOMUX_FUNC_I2C_M0_SCL; + pinMuxI2c[1].function = HAL_IOMUX_FUNC_I2C_M0_SDA; + } else { + pinMuxI2c[0].function = HAL_IOMUX_FUNC_I2C_M1_SCL; + pinMuxI2c[1].function = HAL_IOMUX_FUNC_I2C_M1_SDA; + } + + if (OsalMutexInit(&device->mutex) != HDF_SUCCESS) { + HDF_LOGE("%s %d OsalMutexInit fail\r\n", __func__, __LINE__); + return HDF_FAILURE; + } + + if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) { + HDF_LOGE("%s %d osMutexWait fail\r\n", __func__, __LINE__); + return HDF_ERR_TIMEOUT; + } + + pinMuxI2c[0].pin = resource->sclPin; + pinMuxI2c[1].pin = resource->sdaPin; + hal_iomux_init(pinMuxI2c, ARRAY_SIZE(pinMuxI2c)); + + ret = hal_i2c_open(i2cPort, i2cConfig); + if (ret == HDF_SUCCESS) { + HDF_LOGD("open %u i2c succ.\r\n", i2cPort); + } + OsalMutexUnlock(&device->mutex); + return ret; +} + +static int32_t HostRestI2cDevice(struct I2cDevice *device) +{ + int32_t ret = -1; + struct I2cResource *resource = NULL; + struct HAL_I2C_CONFIG_T *i2cConfig = NULL; + uint32_t i2cPort; + if (device == NULL) { + HDF_LOGE("%s %d device is null\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + i2cConfig = &device->i2cCfg; + if (i2cConfig == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + device->port = resource->port; + i2cPort = device->port; + if (i2cPort > HAL_I2C_ID_NUM) { + HDF_LOGE("i2c port %u not support\r\n", i2cPort); + return HDF_ERR_NOT_SUPPORT; + } + + hal_i2c_close(i2cPort); + ret = hal_i2c_open(i2cPort, i2cConfig); + if (ret == HDF_SUCCESS) { + HDF_LOGD("open %u i2c succ.\r\n", i2cPort); + } + return ret; +} + +static uint32_t GetI2cDeviceResource(struct I2cDevice *device, + const struct DeviceResourceNode *resourceNode) +{ + uint32_t tempPin = 0; + struct I2cResource *resource = NULL; + struct DeviceResourceIface *dri = NULL; + if (device == NULL || resourceNode == NULL) { + HDF_LOGE("device or resourceNode is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + if (dri->GetUint32(resourceNode, "port", &resource->port, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config port fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "sclPin", &tempPin, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config sclPin fail\r\n"); + return HDF_FAILURE; + } + resource->sclPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); + + if (dri->GetUint32(resourceNode, "sdaPin", &tempPin, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config sdaPin fail\r\n"); + return HDF_FAILURE; + } + resource->sdaPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); + + if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config speed fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config mode fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "useDma", &resource->useDma, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config useDma fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "useSync", &resource->useSync, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config useSync fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "asMaster", &resource->asMaster, 0) != HDF_SUCCESS) { + HDF_LOGE("i2c config asMaster fail\r\n"); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t AttachI2cDevice(struct I2cCntlr *host, struct HdfDeviceObject *device) +{ + int32_t ret; + struct I2cDevice *i2cDevice = NULL; + struct I2cResource *resource = NULL; + struct HAL_I2C_CONFIG_T *i2cConfig = NULL; + if (device == NULL || host == NULL) { + HDF_LOGE("%s: device or host is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + i2cDevice = (struct I2cDevice *)OsalMemAlloc(sizeof(struct I2cDevice)); + if (i2cDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc i2cDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + (void)memset_s(i2cDevice, sizeof(struct I2cDevice), 0, sizeof(struct I2cDevice)); + ret = GetI2cDeviceResource(i2cDevice, device->property); + if (ret != HDF_SUCCESS) { + OsalMemFree(i2cDevice); + return HDF_FAILURE; + } + resource = &i2cDevice->resource; + if (resource == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + i2cConfig = &i2cDevice->i2cCfg; + if (i2cConfig == NULL) { + HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__); + return HDF_ERR_INVALID_OBJECT; + } + i2cDevice->port = resource->port; + i2cConfig->mode = resource->mode; + i2cConfig->use_sync = resource->useSync; + i2cConfig->use_dma = resource->useDma; + i2cConfig->as_master = resource->asMaster; + i2cConfig->speed = resource->speed; + i2cConfig->addr_as_slave = 0; + i2cConfig->rising_time_ns = 0; + + host->priv = i2cDevice; + host->busId = i2cDevice->port; + + return InitI2cDevice(i2cDevice); +} + +static int32_t i2cDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct I2cCntlr *host = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr)); + if (host == NULL) { + HDF_LOGE("%s: host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr)); + host->ops = &g_i2cHostMethod; + device->priv = (void *)host; + ret = AttachI2cDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error\r\n", __func__); + i2cDriverRelease(device); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + ret = I2cCntlrAdd(host); + if (ret != HDF_SUCCESS) { + i2cDriverRelease(device); + return HDF_FAILURE; + } + return ret; +} + +static int32_t i2cDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("%s: I2c device object is NULL\r\n", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static void i2cDriverRelease(struct HdfDeviceObject *device) +{ + struct I2cCntlr *i2cCntrl = NULL; + struct I2cDevice *i2cDevice = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return; + } + i2cCntrl = device->priv; + if (i2cCntrl == NULL || i2cCntrl->priv == NULL) { + HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__); + return; + } + i2cCntrl->ops = NULL; + i2cDevice = (struct I2cDevice *)i2cCntrl->priv; + OsalMemFree(i2cCntrl); + + if (i2cDevice != NULL) { + OsalMutexDestroy(&i2cDevice->mutex); + OsalMemFree(i2cDevice); + } +} + +static int32_t i2c_transfer(struct I2cDevice *device, struct I2cMsg *msgs, int16_t count) +{ + int ret; + struct I2cMsg *msg = NULL; + struct I2cMsg *msg2 = NULL; + uint32_t i2cPort; + if (device == NULL || msgs == NULL) { + HDF_LOGE("%s: device or msgs is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + i2cPort = (uint32_t)device->port; + if (i2cPort > HAL_I2C_ID_NUM) { + HDF_LOGE("i2c port %u not support\r\n", i2cPort); + return HDF_ERR_NOT_SUPPORT; + } + if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) { + HDF_LOGE("%s %d OsalMutexTimedLock fail\r\n", __func__, __LINE__); + return HDF_ERR_TIMEOUT; + } + for (int32_t i = 0; i < count; i++) { + msg = &msgs[i]; + if (msg->flags == I2C_FLAG_READ) { + ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, 0, msg->buf, msg->len, 0, NULL); + if (ret) { + HDF_LOGE("%s:%d,i2c recev fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret); + OsalMutexUnlock(&device->mutex); + return i; + } + } else if (msg->flags == I2C_FLAG_STOP) { + i++; + msg2 = &msgs[i]; + ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, msg->len, msg2->buf, msg2->len, 0, NULL); + if (ret) { + HDF_LOGE("%s:%d,i2c recev fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret); + OsalMutexUnlock(&device->mutex); + return i; + } + } else { + ret = hal_i2c_task_send(i2cPort, msg->addr, msg->buf, msg->len, 0, NULL); + if (ret) { + HDF_LOGE("%s:%d,i2c send fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret); + OsalMutexUnlock(&device->mutex); + return i; + } + } + } + OsalMutexUnlock(&device->mutex); + return count; +} + +static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) +{ + struct I2cDevice *device = NULL; + if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) { + HDF_LOGE("%s: I2cCntlr or msgs is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + device = (struct I2cDevice *)cntlr->priv; + if (device == NULL) { + HDF_LOGE("%s: I2cDevice is NULL\r\n", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + return i2c_transfer(device, msgs, count); +} diff --git a/platform/i2c/i2c_bes.h b/platform/i2c/i2c_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..b4c59455a21b022010d604a665a381ec7c73507a --- /dev/null +++ b/platform/i2c/i2c_bes.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _I2C_BES_H__ +#define _I2C_BES_H__ + +#include "hal_i2c.h" +#include "hal_iomux.h" +#include "hal_iomux_best2003.h" +#include "device_resource_if.h" +#include "osal_mutex.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct I2cResource { + uint32_t port; + uint32_t mode; + uint32_t sclPin; + uint32_t sdaPin; + uint32_t useSync; + uint32_t useDma; + uint32_t asMaster; + uint32_t speed; + uint32_t addrAsSlave; + uint32_t addressWidth; +}; + +struct I2cDevice { + uint16_t devAddr; /**< slave device addr */ + uint32_t addressWidth; /**< Addressing mode: 7 bit or 10 bit */ + struct OsalMutex mutex; + uint32_t port; + struct HAL_I2C_CONFIG_T i2cCfg; + struct I2cResource resource; +}; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/platform/pwm/BUILD.gn b/platform/pwm/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7967819ec8f49d70044793a24fa0f66894d34841 --- /dev/null +++ b/platform/pwm/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "pwm_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/pwm/pwm_bes.c b/platform/pwm/pwm_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..d42715952d5f82a1c5595172b3dfc38ee0e1effa --- /dev/null +++ b/platform/pwm/pwm_bes.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pwm_bes.h" +#include +#include +#include "device_resource_if.h" +#include "hdf_device_desc.h" +#include "hal_trace.h" +#include "hal_timer.h" +#include "hal_iomux.h" +#include "pwm_core.h" +#include "hdf_log.h" + +#define PWM_MAX_FUNCTION 8 +#define UNTIL_NAN0SECONDS 1000000000 +#define PERCENT 100 +#define DEC_TEN 10 +#define PIN_GROUP_NUM 8 + +static uint32_t g_pwmFunction[PWM_MAX_FUNCTION] = { + HAL_IOMUX_FUNC_PWM0, + HAL_IOMUX_FUNC_PWM1, + HAL_IOMUX_FUNC_PWM2, + HAL_IOMUX_FUNC_PWM3, + HAL_IOMUX_FUNC_PWM4, + HAL_IOMUX_FUNC_PWM5, + HAL_IOMUX_FUNC_PWM6, + HAL_IOMUX_FUNC_PWM7, +}; + +static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config); +static int32_t PwmDevOpen(struct PwmDev *pwm); +static int32_t PwmDevClose(struct PwmDev *pwm); + +struct PwmMethod g_pwmmethod = { + .setConfig = PwmDevSetConfig, + .open = PwmDevOpen, + .close = PwmDevClose, +}; + +static int InitPwmDevice(struct PwmDev *host) +{ + struct PwmDevice *pwmDevice = NULL; + struct PwmResource *resource = NULL; + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invaild parameter\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + pwmDevice = (struct PwmDevice *)host->priv; + if (pwmDevice == NULL) { + HDF_LOGE("pwmDevice is NULL\r\n"); + return HDF_DEV_ERR_NO_DEVICE; + } + + resource = &pwmDevice->resource; + if (resource == NULL) { + HDF_LOGE("resource is NULL\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxPwm[] = { + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL}, + }; + + pinMuxPwm->pin = resource->pwmPin; + pinMuxPwm->function = g_pwmFunction[resource->pwmId]; + + hal_iomux_init(pinMuxPwm, ARRAY_SIZE(pinMuxPwm)); + + return HDF_SUCCESS; +} + +static uint32_t GetPwmDeviceResource( + struct PwmDevice *device, const struct DeviceResourceNode *resourceNode) +{ + uint32_t tempPin = 0; + struct DeviceResourceIface *dri = NULL; + struct PwmResource *resource = NULL; + if (device == NULL || resourceNode == NULL) { + HDF_LOGE("resource or device is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("resource is NULL\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + if (dri->GetUint32(resourceNode, "pwmPin", &tempPin, 0) != HDF_SUCCESS) { + HDF_LOGE("read pwmPin fail\r\n"); + return HDF_FAILURE; + } + resource->pwmPin = ((tempPin / DEC_TEN) * PIN_GROUP_NUM) + (tempPin % DEC_TEN); + + if (dri->GetUint32(resourceNode, "pwmId", &resource->pwmId, 0) != HDF_SUCCESS) { + HDF_LOGE("read pwmId fail\r\n"); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t AttachPwmDevice(struct PwmDev *host, struct HdfDeviceObject *device) +{ + int32_t ret; + struct PwmDevice *pwmDevice = NULL; + if (device == NULL || device->property == NULL || host == NULL) { + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + pwmDevice = (struct PwmDevice *)OsalMemAlloc(sizeof(struct PwmDevice)); + if (pwmDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetPwmDeviceResource(pwmDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(pwmDevice); + return HDF_FAILURE; + } + + host->priv = pwmDevice; + host->num = pwmDevice->resource.pwmId; + + return InitPwmDevice(host); +} +/* HdfDriverEntry method definitions */ +static int32_t PwmDriverBind(struct HdfDeviceObject *device); +static int32_t PwmDriverInit(struct HdfDeviceObject *device); +static void PwmDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_pwmDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_PWM_MODULE_HDF", + .Bind = PwmDriverBind, + .Init = PwmDriverInit, + .Release = PwmDriverRelease, +}; + +// Initialize HdfDriverEntry +HDF_INIT(g_pwmDriverEntry); + +static int32_t PwmDriverBind(struct HdfDeviceObject *device) +{ + static struct PwmDev devService; + + if (device == NULL) { + HDF_LOGE("hdfDevice object is null!\r\n"); + return HDF_FAILURE; + } + + device->service = &devService.service; + devService.device = device; + HDF_LOGI("Enter %s\r\n", __func__); + + return HDF_SUCCESS; +} + +static int32_t PwmDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct PwmDev *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + HDF_LOGI("Enter %s:\r\n", __func__); + + host = (struct PwmDev *)OsalMemAlloc(sizeof(struct PwmDev)); + if (host == NULL) { + HDF_LOGE("%s: host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = AttachPwmDevice(host, device); + if (ret != HDF_SUCCESS) { + OsalMemFree(host); + HDF_LOGE("%s:attach error\r\n", __func__); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + host->method = &g_pwmmethod; + ret = PwmDeviceAdd(device, host); + if (ret != HDF_SUCCESS) { + PwmDeviceRemove(device, host); + OsalMemFree(host->device); + OsalMemFree(host); + return HDF_DEV_ERR_NO_DEVICE; + } + + HDF_LOGI("PwmDriverInit success!\r\n"); + return HDF_SUCCESS; +} + +static void PwmDriverRelease(struct HdfDeviceObject *device) +{ + struct PwmDev *host = NULL; + + if (device == NULL || device->service == NULL) { + HDF_LOGE("device is null\r\n"); + return; + } + + host = (struct PwmDev *)device->service; + if (host != NULL && host->device != NULL) { + host->method = NULL; + OsalMemFree(host->device); + OsalMemFree(host); + host->device = NULL; + host = NULL; + } + + device->service = NULL; + HDF_LOGI("PwmDriverRelease finish!!\r\n"); + return; +} + +static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config) +{ + struct PwmDevice *prvPwm = NULL; + struct HAL_PWM_CFG_T *pwmCfg = NULL; + enum HAL_PWM_ID_T pwmId; + + if (pwm == NULL || config == NULL || (config->period > UNTIL_NAN0SECONDS)) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_FAILURE; + } + + prvPwm = (struct PwmDevice *)PwmGetPriv(pwm); + if (prvPwm == NULL) { + return HDF_FAILURE; + } + pwmCfg = &prvPwm->pwmCfg; + pwmCfg->freq = UNTIL_NAN0SECONDS / config->period; + pwmCfg->ratio = config->duty * PERCENT / config->period; + pwmCfg->inv = false; + pwmCfg->sleep_on = false; + + pwmId = prvPwm->resource.pwmId; + + if (config->status == PWM_ENABLE_STATUS) { + hal_pwm_enable(pwmId, pwmCfg); + } else { + hal_pwm_disable(pwmId); + } + + return HDF_SUCCESS; +} + +static int32_t PwmDevOpen(struct PwmDev *pwm) +{ + if (pwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + + return HDF_SUCCESS; +} + +static int32_t PwmDevClose(struct PwmDev *pwm) +{ + struct PwmDevice *prvPwm = NULL; + enum HAL_PWM_ID_T pwmId = 0; + + if (pwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + + prvPwm = (struct PwmDevice *)PwmGetPriv(pwm); + if (prvPwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_DEV_ERR_NO_DEVICE; + } + + pwmId = prvPwm->resource.pwmId; + + hal_pwm_disable(pwmId); + + return HDF_SUCCESS; +} diff --git a/platform/pwm/pwm_bes.h b/platform/pwm/pwm_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..0bc76f928f65b3594ba71b0c1fdd8822aaf30ab7 --- /dev/null +++ b/platform/pwm/pwm_bes.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __PWM_BES_H__ +#define __PWM_BES_H__ + +#include "hal_pwm.h" +#include "hal_gpio.h" +#include "hal_iomux.h" +#include "pwm_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PwmResource { + uint32_t pwmPin; + uint32_t pwmId; +}; + +struct PwmDevice { + struct IDeviceIoService ioService; + struct HAL_PWM_CFG_T pwmCfg; + struct PwmConfig *cfg; + struct PwmResource resource; +}; + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/platform/spi/BUILD.gn b/platform/spi/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7bca28e414007aa29b41146ca2ada54d5228647e --- /dev/null +++ b/platform/spi/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "spi_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/spi/spi_bes.c b/platform/spi/spi_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..be08d5e8fd2c7272bb9a31091d2863f3000d6ed5 --- /dev/null +++ b/platform/spi/spi_bes.c @@ -0,0 +1,741 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "spi_bes.h" +#include +#include +#include "spi_core.h" +#include "device_resource_if.h" +#include "hal_cache.h" +#include "hal_trace.h" +#include "hdf_log.h" + +#define SPI_DMA_MAX 4095 +#define DEC_NUM 10 +#define GROUP_PIN_NUM 8 +#define TIMEOUT 1000 +#define SPI_PIN_0 0 +#define SPI_PIN_1 1 +#define SPI_PIN_2 2 +#define SPI_PIN_3 3 +#define DRIVER_LEVEL 3 +#define MAX_SPI_NUMBER 2 +#define MAX_SPI_SPEED 26000000 +static void Spi0DmaIrq(int error); +static void Spi1DmaIrq(int error); + +static struct SPI_CTX_OBJ_T spiCtx[MAX_SPI_NUMBER] = { + { + .spiPinCS0 = 0, + .spiFunDI0 = HAL_IOMUX_FUNC_SPI_DI0, + .spiFunCLK = HAL_IOMUX_FUNC_SPI_CLK, + .spiFunCS0 = HAL_IOMUX_FUNC_SPI_CS0, + .spiFunDIO = HAL_IOMUX_FUNC_SPI_DIO, + .sem = { NULL }, + .mutex = { NULL }, + .SpiOpen = hal_spi_open, + .SpiDmaSend = hal_spi_dma_send, + .SpiDmaRecv = hal_spi_dma_recv, + .SpiSend = hal_spi_send, + .SpiRecv = hal_spi_recv, + .SpiDmaIrq = Spi0DmaIrq, + .SpiClose = hal_spi_close + }, + { + .spiPinCS0 = 0, + .spiFunDI0 = HAL_IOMUX_FUNC_SPILCD_DI0, + .spiFunCLK = HAL_IOMUX_FUNC_SPILCD_CLK, + .spiFunCS0 = HAL_IOMUX_FUNC_SPILCD_CS0, + .spiFunDIO = HAL_IOMUX_FUNC_SPILCD_DIO, + .sem = { NULL }, + .mutex = { NULL }, + .SpiOpen = hal_spilcd_open, + .SpiDmaSend = hal_spilcd_dma_send, + .SpiDmaRecv = hal_spilcd_dma_recv, + .SpiSend = hal_spilcd_send, + .SpiRecv = hal_spilcd_recv, + .SpiDmaIrq = Spi1DmaIrq, + .SpiClose = hal_spilcd_close + } +}; + +static struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxSpi[] = { + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL }, + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL }, + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL }, + {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL }, +}; + +void Spi0DmaIrq(int error) +{ + if (HDF_SUCCESS != OsalSemPost(&spiCtx[0].sem)) { + HDF_LOGE("spi0dmairq OsalSemPost failed!\r\n"); + return; + } +} + +void Spi1DmaIrq(int error) +{ + if (HDF_SUCCESS != OsalSemPost(&spiCtx[1].sem)) { + HDF_LOGE("spi1dmairq OsalSemPost failed!\r\n"); + return; + } +} + +static void SpiIomuxInit(struct SpiDevice *spiDevice) +{ + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + struct SpiResource *resource = NULL; + uint32_t spiPort; + HDF_LOGI("%s: Enter\r\n", __func__); + + if (spiDevice == NULL) { + HDF_LOGE("%s: invalid parameter\r\n", __func__); + return; + } + + resource = &spiDevice->resource; + if (resource == NULL) { + HDF_LOGE("resource is null\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + spiDevCfg = &spiDevice->spiDevCfg; + if (spiDevCfg == NULL) { + HDF_LOGE("resource is null\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + spiDevCfg->rate = resource->speed; + + spiPort = spiDevice->spiId; + + pinMuxSpi[SPI_PIN_0].pin = resource->spiMisoPin; + pinMuxSpi[SPI_PIN_1].pin = resource->spiClkPin; + pinMuxSpi[SPI_PIN_2].pin = resource->spiCsPin; + pinMuxSpi[SPI_PIN_3].pin = resource->spiMosiPin; + + spiCtx[spiPort].spiPinCS0 = resource->spiCsPin; + + pinMuxSpi[SPI_PIN_0].function = spiCtx[spiPort].spiFunDI0; + pinMuxSpi[SPI_PIN_1].function = spiCtx[spiPort].spiFunCLK; + + if (resource->spiCsSoft) { + spiCtx[spiPort].spiFunCS0 = HAL_IOMUX_FUNC_AS_GPIO; + } + + pinMuxSpi[SPI_PIN_2].function = spiCtx[spiPort].spiFunCS0; + pinMuxSpi[SPI_PIN_3].function = spiCtx[spiPort].spiFunDIO; + + if (spiDevCfg->rate > MAX_SPI_SPEED) { + hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_1].pin, DRIVER_LEVEL); + hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_3].pin, DRIVER_LEVEL); + } + + hal_iomux_init(pinMuxSpi, ARRAY_SIZE(pinMuxSpi)); +} + +/** + * Spi send + * + * @param[in] spiId the spi bus id + * @param[in] data spi send data + * @param[in] size spi send data size + * @param[in] timeOut timeOut in milisecond, set this value to HAL_WAIT_FOREVER + * if you want to wait forever + * + * @return 0 : on success, EIO : if the SPI device could not be initialised + */ + +#ifdef HalSpiSend +#undef HalSpiSend +#endif +int32_t HalSpiSend(struct SpiDevice *spiDevice, const uint8_t *data, uint16_t size, uint32_t timeOut) +{ + int32_t ret = 0; + uint32_t spiId; + uint32_t len = size; + struct SpiResource *resource = NULL; + int32_t status = HDF_FAILURE; + + if (spiDevice == NULL || data == NULL || size == 0) { + HDF_LOGE("spi input para err\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + spiId = spiDevice->spiId; + resource = &spiDevice->resource; + if (resource == NULL) { + HDF_LOGE("resource is null\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + status = OsalMutexLock(&spiCtx[spiId].mutex); + if (HDF_SUCCESS != status) { + HDF_LOGE("%s spi_mutex wait error = 0x%X!\r\n", __func__, status); + return HDF_ERR_TIMEOUT; + } + + if (resource->transmode == SPI_TRANSFER_DMA) { + ret = spiCtx[spiId].SpiDmaSend(data, len, spiCtx[spiId].SpiDmaIrq); + if (OsalSemWait(&spiCtx[spiId].sem, timeOut) != HDF_SUCCESS) { + HDF_LOGE("spi dma send timeOut\r\n"); + goto OUT; + } + } else { + ret = spiCtx[spiId].SpiSend(data, len); + } + + if (ret) { + HDF_LOGE("spi tail send fail %ld, size %ld\r\n", ret, len); + goto OUT; + } +OUT: + OsalMutexUnlock(&spiCtx[spiId].mutex); + return ret; +} + +#ifdef HalSpiRecv +#undef HalSpiRecv +#endif + +/** + * SpiRecv + * + * @param[in] spiId the spi bus id + * @param[out] data spi recv data + * @param[in] size spi recv data size + * @param[in] timeOut timeOut in milisecond, set this value to HAL_WAIT_FOREVER + * if you want to wait forever + * + * @return 0 : on success, EIO : if the SPI device could not be initialised + */ +int32_t HalSpiRecv(struct SpiDevice *spiDevice, uint8_t *data, uint16_t size, uint32_t timeOut) +{ + int32_t ret = 0; + uint32_t len = size; + uint32_t remainder = 0; + int32_t status = HDF_FAILURE; + uint8_t *cmd = NULL; + uint32_t spiId; + struct SpiResource *resource = NULL; + if (spiDevice == NULL || data == NULL || size == 0) { + HDF_LOGE("spi input para err\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + spiId = spiDevice->spiId; + resource = &spiDevice->resource; + if (resource == NULL) { + HDF_LOGE("resource is null\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + cmd = (uint8_t *)OsalMemAlloc(len); + if (cmd == NULL) { + HDF_LOGE("%s OsalMemAlloc size %ld error\r\n", __FUNCTION__, len); + return HDF_ERR_MALLOC_FAIL; + } + + memset_s(cmd, len, 0, len); + + status = OsalMutexLock(&spiCtx[spiId].mutex); + if (HDF_SUCCESS != status) { + HDF_LOGE("%s spi_mutex wait error = 0x%X!\r\n", __func__, status); + OsalMemFree(cmd); + return HDF_ERR_TIMEOUT; + } + remainder = len <= SPI_DMA_MAX ? len : SPI_DMA_MAX; + + if (resource->transmode == SPI_TRANSFER_DMA) { + ret = spiCtx[spiId].SpiDmaRecv(cmd, data, remainder, spiCtx[spiId].SpiDmaIrq); + if (OsalSemWait(&spiCtx[spiId].sem, timeOut) <= 0) { + HDF_LOGE("SPI Read timeOut!\r\n"); + goto OUT; + } + } else { + ret = spiCtx[spiId].SpiRecv(cmd, data, remainder); + } + + len -= remainder; + data += remainder; + + if (ret) { + HDF_LOGE("spi tail fail %ld, size %ld\r\n", ret, len); + goto OUT; + } +OUT: + OsalMutexUnlock(&spiCtx[spiId].mutex); + OsalMemFree(cmd); + return ret; +} + +#ifdef HalSpiSendRecv +#undef HalSpiSendRecv +#endif +int32_t HalSpiSendRecv(struct SpiDevice *spiDevice, uint8_t *txData, uint16_t txSize, uint8_t *rxData, + uint16_t rxSize, uint32_t timeOut) +{ + int32_t ret; + int32_t status; + uint32_t spiId; + struct SpiResource *resource = NULL; + if (spiDevice == NULL || txData == NULL || txSize == 0 || rxData == NULL || rxSize == 0) { + HDF_LOGE("spi input para err\r\n"); + return HDF_ERR_INVALID_PARAM; + } + spiId = spiDevice->spiId; + resource = &spiDevice->resource; + status = OsalMutexLock(&spiCtx[spiId].mutex); + if (HDF_SUCCESS != status) { + HDF_LOGE("%s spi_mutex wait error = 0x%X!\r\n", __func__, status); + return HDF_ERR_TIMEOUT; + } + + if (resource->transmode == SPI_TRANSFER_DMA) { + ret = spiCtx[spiId].SpiDmaRecv(txData, rxData, rxSize, spiCtx[spiId].SpiDmaIrq); + if (OsalSemWait(&spiCtx[spiId].sem, timeOut) <= 0) { + HDF_LOGE("%s:SPI Read timeOut!\r\n", __func__); + goto OUT; + } + } else { + ret = spiCtx[spiId].SpiRecv(txData, rxData, rxSize); + } + if (ret) { + HDF_LOGE("spi dma tail fail %d\r\n", ret); + goto OUT; + } +OUT: + OsalMutexUnlock(&spiCtx[spiId].mutex); + return ret; +} + +static int32_t InitSpiDevice(struct SpiDevice *spiDevice) +{ + uint32_t spiPort; + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + struct SpiResource *resource = NULL; + if (spiDevice == NULL) { + HDF_LOGE("%s: invalid parameter\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + resource = &spiDevice->resource; + spiDevCfg = &spiDevice->spiDevCfg; + spiPort = spiDevice->spiId; + + SpiIomuxInit(spiDevice); + + switch (resource->mode) { + case SPI_WORK_MODE_0: + spiDevCfg->clk_delay_half = false; + spiDevCfg->clk_polarity = false; + break; + case SPI_WORK_MODE_1: + spiDevCfg->clk_delay_half = true; + spiDevCfg->clk_polarity = false; + break; + case SPI_WORK_MODE_2: + spiDevCfg->clk_delay_half = false; + spiDevCfg->clk_polarity = true; + break; + case SPI_WORK_MODE_3: + spiDevCfg->clk_delay_half = true; + spiDevCfg->clk_polarity = true; + break; + default: + spiDevCfg->clk_delay_half = true; + spiDevCfg->clk_polarity = true; + } + spiDevCfg->slave = 0; + if (resource->transmode == SPI_TRANSFER_DMA) { + spiDevCfg->dma_rx = true; + spiDevCfg->dma_tx = true; + } else { + spiDevCfg->dma_rx = false; + spiDevCfg->dma_tx = false; + } + spiDevCfg->cs = 0; + spiDevCfg->rx_bits = resource->dataSize; + spiDevCfg->tx_bits = resource->dataSize; + spiDevCfg->rx_frame_bits = 0; + /* spi open move to hdf open api */ + /* if cs use as gpio ,pull up at first */ + if (spiCtx[spiPort].spiFunCS0 == HAL_IOMUX_FUNC_AS_GPIO) { + hal_gpio_pin_set_dir(spiCtx[spiPort].spiPinCS0, HAL_GPIO_DIR_OUT, 1); + } + + if (&spiCtx[spiPort].sem == NULL) { + if (OsalSemInit(&spiCtx[spiPort].sem, 0) != HDF_SUCCESS) { + HDF_LOGE("spiDmaSemaphore create failed!\r\n"); + return HDF_FAILURE; + } + } + + if (&spiCtx[spiPort].mutex == NULL) { + if (OsalMutexInit(&spiCtx[spiPort].mutex) != HDF_SUCCESS) { + HDF_LOGE("spi Mutex create failed!\r\n"); + return HDF_FAILURE; + } + } + return HDF_SUCCESS; +} + +/* get spi config from hcs file */ +static int32_t GetSpiDeviceResource(struct SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode) +{ + uint32_t relPin; + struct SpiResource *resource = NULL; + struct DeviceResourceIface *dri = NULL; + if (spiDevice == NULL || resourceNode == NULL) { + HDF_LOGE("%s: PARAM is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + resource = &spiDevice->resource; + if (resource == NULL) { + HDF_LOGE("%s: resource is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); // open HDF + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + if (dri->GetUint32(resourceNode, "busNum", &resource->num, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read num fail\r\n"); + return HDF_FAILURE; + } + + spiDevice->spiId = resource->num; + if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read base fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "transmode", &resource->transmode, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read transmode fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "spiCsSoft", &resource->spiCsSoft, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read spiCsSoft fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read mode fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "dataSize", &resource->dataSize, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read dataSize fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "csNum", &resource->csNum, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read csNum fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "spiClkPin", &resource->spiClkPin, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read spiClkPin fail\r\n"); + return HDF_FAILURE; + } + + relPin = (resource->spiClkPin / DEC_NUM) * GROUP_PIN_NUM + (resource->spiClkPin % DEC_NUM); + resource->spiClkPin = relPin; + + if (dri->GetUint32(resourceNode, "spiMosiPin", &resource->spiMosiPin, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read spiMosiPin fail\r\n"); + return HDF_FAILURE; + } + + relPin = (resource->spiMosiPin / DEC_NUM) * GROUP_PIN_NUM + (resource->spiMosiPin % DEC_NUM); + resource->spiMosiPin = relPin; + if (dri->GetUint32(resourceNode, "spiMisoPin", &resource->spiMisoPin, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read spiMisoPin fail\r\n"); + return HDF_FAILURE; + } + + relPin = ((resource->spiMisoPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->spiMisoPin % DEC_NUM); + resource->spiMisoPin = relPin; + + if (dri->GetUint32(resourceNode, "spiCsPin", &resource->spiCsPin, 0) != HDF_SUCCESS) { + HDF_LOGE("spi config read spiCsPin fail\r\n"); + return HDF_FAILURE; + } + + relPin = ((resource->spiCsPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->spiCsPin % DEC_NUM); + resource->spiCsPin = relPin; + + return HDF_SUCCESS; +} + +int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + struct SpiDevice *spiDevice = NULL; + + if (spiCntlr == NULL || device == NULL || device->property == NULL) { + HDF_LOGE("%s: property is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + spiDevice = (struct SpiDevice *)OsalMemAlloc(sizeof(struct SpiDevice)); + if (spiDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc spiDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetSpiDeviceResource(spiDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(spiDevice); + return HDF_FAILURE; + } + + spiCntlr->priv = spiDevice; + spiCntlr->busNum = spiDevice->spiId; + return InitSpiDevice(spiDevice); +} +/* SPI Method */ +static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg); +static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg); +static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count); +static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr); +static int32_t SpiDevClose(struct SpiCntlr *spiCntlr); + +struct SpiCntlrMethod g_SpiCntlrMethod = { + .GetCfg = SpiDevGetCfg, + .SetCfg = SpiDevSetCfg, + .Transfer = SpiDevTransfer, + .Open = SpiDevOpen, + .Close = SpiDevClose, +}; + +/* HdfDriverEntry method definitions */ +static int32_t SpiDriverBind(struct HdfDeviceObject *device); +static int32_t SpiDriverInit(struct HdfDeviceObject *device); +static void SpiDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_SpiDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_SPI_MODULE_HDF", + .Bind = SpiDriverBind, + .Init = SpiDriverInit, + .Release = SpiDriverRelease, +}; + +HDF_INIT(g_SpiDriverEntry); + +static int32_t SpiDriverBind(struct HdfDeviceObject *device) +{ + struct SpiCntlr *spiCntlr = NULL; + if (device == NULL) { + HDF_LOGE("Sample device object is null!\r\n"); + return HDF_ERR_INVALID_PARAM; + } + HDF_LOGI("Enter %s:\r\n", __func__); + spiCntlr = (struct SpiCntlr *)OsalMemAlloc(sizeof(struct SpiCntlr)); + if (spiCntlr == NULL) { + HDF_LOGE("%s: host is NULL\r\n", __func__); + return HDF_FAILURE; + } + device->service = &spiCntlr->service; + spiCntlr->device = device; + spiCntlr->priv = NULL; + return HDF_SUCCESS; +} + +static int32_t SpiDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct SpiCntlr *spiCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + HDF_LOGI("Enter %s:", __func__); + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + ret = AttachSpiDevice(spiCntlr, device); // SpiCntlr add SpiDevice to priv + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error\r\n", __func__); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + spiCntlr->method = &g_SpiCntlrMethod; // register callback + + return ret; +} + +static void SpiDriverRelease(struct HdfDeviceObject *device) +{ + struct SpiCntlr *spiCntlr = NULL; + struct SpiDevice *spiDevice = NULL; + + HDF_LOGI("Enter %s\r\n", __func__); + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return; + } + + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return; + } + + spiDevice = (struct SpiDevice *)spiCntlr->priv; + if (spiDevice != NULL) { + OsalMemFree(spiDevice); + } + return; +} + +static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr) +{ + HDF_LOGI("Enter %s\r\n", __func__); + int ret; + uint32_t spiPort; + struct SpiDevice *spiDevice = NULL; + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (struct SpiDevice *)spiCntlr->priv; + spiPort = spiDevice->spiId; + spiDevCfg = &spiDevice->spiDevCfg; + if (spiDevCfg == NULL) { + HDF_LOGE("spi %u config is NULL\r\n", spiPort); + return HDF_DEV_ERR_NO_DEVICE; + } + ret = spiCtx[spiPort].SpiOpen(spiDevCfg); + if (ret != 0) { + HDF_LOGE("spi %u open error %d\r\n", spiPort, ret); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t SpiDevClose(struct SpiCntlr *spiCntlr) +{ + int ret; + uint32_t spiPort; + struct SpiDevice *spiDevice = NULL; + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (struct SpiDevice *)spiCntlr->priv; + spiPort = spiDevice->spiId; + spiDevCfg = &spiDevice->spiDevCfg; + if (spiDevCfg == NULL) { + HDF_LOGE("spi %u config is NULL\r\n", spiPort); + return HDF_DEV_ERR_NO_DEVICE; + } + ret = spiCtx[spiPort].SpiClose(spiDevCfg->cs); + if (ret != 0) { + HDF_LOGE("spi %ld open error %d\r\n", spiPort, ret); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + struct SpiDevice *spiDevice = NULL; + if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (struct SpiDevice *)spiCntlr->priv; + if (spiDevice == NULL) { + return HDF_DEV_ERR_NO_DEVICE; + } + spiCfg->maxSpeedHz = spiDevice->resource.speed; + spiCfg->mode = spiDevice->resource.mode; + spiCfg->transferMode = spiDevice->resource.transmode; + spiCfg->bitsPerWord = spiDevice->resource.dataSize; + + return HDF_SUCCESS; +} +static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + struct SpiDevice *spiDevice = NULL; + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (struct SpiDevice *)spiCntlr->priv; + if (spiDevice == NULL) { + return HDF_DEV_ERR_NO_DEVICE; + } + spiDevCfg = &spiDevice->spiDevCfg; + if (spiDevCfg == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + spiDevice->resource.speed = spiCfg->maxSpeedHz; + spiDevice->resource.mode = spiCfg->mode; + spiDevice->resource.transmode = spiCfg->transferMode; + spiDevice->resource.dataSize = spiCfg->bitsPerWord; + spiDevCfg->rate = spiCfg->maxSpeedHz; + return InitSpiDevice(spiDevice); +} + +static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count) +{ + uint32_t spiId; + struct SpiDevice *spiDevice = NULL; + struct HAL_SPI_CFG_T *spiDevCfg = NULL; + struct SpiMsg *msg = NULL; + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + HDF_LOGI("%s: %u Enter\r\n", __func__, spiId); + spiDevice = (struct SpiDevice *)spiCntlr->priv; + spiId = spiDevice->spiId; + for (size_t i = 0; i < count; i++) { + msg = &spiMsg[i]; + /* pull down cs at first */ + if (spiDevice->resource.spiCsSoft) { + hal_gpio_pin_set_dir(spiCtx[spiId].spiPinCS0, HAL_GPIO_DIR_OUT, 0); + } + + if ((msg->wbuf != NULL) && (msg->rbuf == NULL)) { + HalSpiSend(spiDevice, msg->wbuf, msg->len, TIMEOUT); + } + if ((msg->rbuf != NULL) && (msg->wbuf == NULL)) { + HalSpiRecv(spiDevice, msg->rbuf, msg->len, TIMEOUT); + } + if ((msg->wbuf != NULL) && (msg->rbuf != NULL)) { + HalSpiSendRecv(spiDevice, msg->wbuf, msg->len, msg->rbuf, msg->len, TIMEOUT); + } + + /* pull pull up cs at the end */ + if (msg->csChange) { + hal_gpio_pin_set_dir(spiCtx[spiId].spiPinCS0, HAL_GPIO_DIR_OUT, 1); + } + DelayUs(msg->delayUs); + } + return HDF_SUCCESS; +} \ No newline at end of file diff --git a/platform/spi/spi_bes.h b/platform/spi/spi_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..c274f10444b5349c9416b6c12d268264567b2af1 --- /dev/null +++ b/platform/spi/spi_bes.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __SPI_BES_H__ +#define __SPI_BES_H__ + +#include "hal_spi.h" +#include "hal_gpio.h" +#include "hal_iomux.h" +#include "hal_iomux_best2003.h" +#include "osal_mutex.h" +#include "osal_sem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum SPI_WORK_MODE { + SPI_WORK_MODE_0, // CPOL = 0; CPHA = 0 + SPI_WORK_MODE_2, // CPOL = 1; CPHA = 0 + SPI_WORK_MODE_1, // CPOL = 0; CPHA = 1 + SPI_WORK_MODE_3, // CPOL = 1; CPHA = 1 +}; + +enum SPI_TRANSFER_MODE { + SPI_TRANSFER_DMA, + SPI_TRANSFER_NORMAL, +}; + +struct SpiResource { + uint32_t num; + uint32_t speed; + enum SPI_TRANSFER_MODE transmode; + enum SPI_WORK_MODE mode; + uint32_t dataSize; + uint32_t csNum; + uint32_t spiCsSoft; + uint32_t spiClkPin; + uint32_t spiMosiPin; + uint32_t spiMisoPin; + uint32_t spiCsPin; +}; + +struct SPI_CTX_OBJ_T { + enum HAL_IOMUX_PIN_T spiPinCS0; + enum HAL_IOMUX_FUNCTION_T spiFunDI0; + enum HAL_IOMUX_FUNCTION_T spiFunCLK; + enum HAL_IOMUX_FUNCTION_T spiFunCS0; + enum HAL_IOMUX_FUNCTION_T spiFunDIO; + struct OsalSem sem; + struct OsalMutex mutex; + int (*SpiOpen)(const struct HAL_SPI_CFG_T *cfg); + int (*SpiDmaSend)(const void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler); + int (*SpiDmaRecv)(const void *cmd, void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler); + int (*SpiSend)(const void *data, uint32_t len); + int (*SpiRecv)(const void *cmd, void *data, uint32_t len); + void (*SpiDmaIrq)(int error); + int (*SpiClose)(uint32_t cs); +}; + +struct SpiDevice { + uint32_t spiId; + struct SpiResource resource; + struct HAL_SPI_CFG_T spiDevCfg; +}; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/platform/uart/BUILD.gn b/platform/uart/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6e44223f9853cf8dae4ee3831e8df89edc9db3f8 --- /dev/null +++ b/platform/uart/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "uart_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/uart/uart_bes.c b/platform/uart/uart_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..135f170811a2b8534cc66fcc374c3a5fa3649906 --- /dev/null +++ b/platform/uart/uart_bes.c @@ -0,0 +1,893 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "uart_bes.h" +#include +#include +#include "hal_iomux.h" +#include "hal_timer.h" +#include "device_resource_if.h" +#include "hal_trace.h" +#include "hal_cache.h" +#include "hdf_log.h" + +#define HDF_UART_TMO 1000 +#define HDF_LOG_TAG uartDev + +#define UART_FIFO_MAX_BUFFER 2048 +#define UART_DMA_RING_BUFFER_SIZE 256 // mast be 2^n + +static __SRAMBSS unsigned char g_halUartBuf[UART_DMA_RING_BUFFER_SIZE]; +static __SRAMBSS unsigned char g_halUart1Buf[UART_DMA_RING_BUFFER_SIZE]; +static __SRAMBSS unsigned char g_halUart2Buf[UART_DMA_RING_BUFFER_SIZE]; + +static struct UART_CTX_OBJ g_uartCtx[4] = {0}; +static unsigned char *g_uartKfifoBuffer[4] = {NULL, NULL, NULL, NULL}; +struct HAL_UART_CFG_T g_lowUartCfg = { + // used for tgdb cli console + .parity = HAL_UART_PARITY_NONE, + .stop = HAL_UART_STOP_BITS_1, + .data = HAL_UART_DATA_BITS_8, + .flow = HAL_UART_FLOW_CONTROL_NONE, + .tx_level = HAL_UART_FIFO_LEVEL_7_8, + .rx_level = HAL_UART_FIFO_LEVEL_1_8, + .baud = 0, + .dma_rx = false, + .dma_tx = false, + .dma_rx_stop_on_err = false, +}; + +static void HalSetUartIomux(enum HAL_UART_ID_T uartId) +{ + if (uartId == HAL_UART_ID_0) { + hal_iomux_set_uart0(); + } else if (uartId == HAL_UART_ID_1) { + hal_iomux_set_uart1(); + } else if (uartId == HAL_UART_ID_2) { + hal_iomux_set_uart2(); + } else { + hal_iomux_set_uart3(); + } +} + +static void HalUartRxStart(uint32_t uartId) +{ + struct HAL_DMA_DESC_T dmaDescRx; + unsigned int descCnt = 1; + union HAL_UART_IRQ_T mask; + + mask.reg = 0; + mask.BE = 0; + mask.FE = 0; + mask.OE = 0; + mask.PE = 0; + mask.RT = 1; + + hal_uart_dma_recv_mask(uartId, g_uartCtx[uartId].buffer, UART_DMA_RING_BUFFER_SIZE, &dmaDescRx, &descCnt, &mask); +} + +static void UartRxHandler(enum HAL_UART_ID_T id, union HAL_UART_IRQ_T status) +{ + int32_t ret; + + if (status.TX) { + ret = OsalSemPost(&g_uartCtx[id].tx_sem); + ASSERT(ret == HDF_SUCCESS, "%s: Failed to release write_sem: %d", __func__, ret); + } + + if (status.RX || status.RT) { + ret = OsalSemPost(&g_uartCtx[id].rx_sem); + ASSERT(ret == HDF_SUCCESS, "%s: Failed to release read_sem: %d", __func__, ret); + } +} + +static void UartDmaRxHandler(uint32_t xferSize, int dmaError, union HAL_UART_IRQ_T status) +{ + uint32_t len = 0; + uint32_t uartid = 0; + + len = kfifo_put(&g_uartCtx[uartid].fifo, g_uartCtx[uartid].buffer, xferSize); + if (len < xferSize) { + HDF_LOGE("%s ringbuf is full have %d need %d\r", __FUNCTION__, (int)len, (int)xferSize); + return; + } + + memset_s(g_uartCtx[uartid].buffer, UART_DMA_RING_BUFFER_SIZE, 0, UART_DMA_RING_BUFFER_SIZE); + OsalSemPost(&g_uartCtx[uartid].rx_sem); + HalUartRxStart(uartid); +} + +static void UartDmaTxHandler(uint32_t xferSize, int dmaError) +{ + OsalSemPost(&g_uartCtx[0].tx_sem); +} + +static void Uart1DmaRxHandler(uint32_t xferSize, int dmaError, union HAL_UART_IRQ_T status) +{ + uint32_t len = 0; + uint32_t uartid = HAL_UART_ID_1; + len = kfifo_put(&g_uartCtx[uartid].fifo, g_uartCtx[uartid].buffer, xferSize); + if (len < xferSize) { + HDF_LOGE("%s ringbuf is full have %d need %d\r", __FUNCTION__, (int)len, (int)xferSize); + return; + } + memset_s(g_uartCtx[uartid].buffer, UART_DMA_RING_BUFFER_SIZE, 0, UART_DMA_RING_BUFFER_SIZE); + OsalSemPost(&g_uartCtx[uartid].rx_sem); + HalUartRxStart(uartid); +} + +static void Uart1DmaTxHandler(uint32_t xferSize, int dmaError) +{ + OsalSemPost(&g_uartCtx[HAL_UART_ID_1].tx_sem); +} + +/* uart2 */ +static void Uart2DmaRxHandler(uint32_t xferSize, int dmaError, union HAL_UART_IRQ_T status) +{ + uint32_t len = 0; + uint32_t uartid = HAL_UART_ID_2; + len = kfifo_put(&g_uartCtx[uartid].fifo, g_uartCtx[uartid].buffer, xferSize); + if (len < xferSize) { + HDF_LOGE("%s ringbuf is full have %d need %d\r", __FUNCTION__, (int)len, (int)xferSize); + return; + } + + memset_s(g_uartCtx[uartid].buffer, UART_DMA_RING_BUFFER_SIZE, 0, UART_DMA_RING_BUFFER_SIZE); + OsalSemPost(&g_uartCtx[uartid].rx_sem); + HalUartRxStart(uartid); +} + +static void Uart2DmaTxHandler(uint32_t xferSize, int dmaError) +{ + OsalSemPost(&g_uartCtx[HAL_UART_ID_2].tx_sem); +} + +static void HalUartStartRx(uint32_t uartId) +{ + union HAL_UART_IRQ_T mask; + mask.reg = 0; + mask.RT = 1; + mask.RX = 1; + + hal_uart_irq_set_mask(uartId, mask); + hal_uart_irq_set_handler(uartId, UartRxHandler); +} + +static int32_t HalUartSend(uint32_t uartId, const void *data, uint32_t size, uint32_t timeOut) +{ + int32_t ret = HDF_FAILURE; + struct HAL_DMA_DESC_T dmaSescTx; + unsigned int descCnt = 1; + + if (data == NULL || size == 0) { + HDF_LOGE("%s %d Invalid input \r\n", __FILE__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + if (uartId > HAL_UART_ID_2) { + HDF_LOGE("%s %d Invalid input \r\n", __FILE__, __LINE__); + return HDF_ERR_NOT_SUPPORT; + } + + hal_uart_dma_send(uartId, data, size, &dmaSescTx, &descCnt); + OsalSemWait(&g_uartCtx[uartId].tx_sem, timeOut); + + return HDF_SUCCESS; +} + +static int32_t HalUartRecv(uint8_t uartId, void *data, uint32_t expectSize, + uint32_t *recvSize, uint32_t timeOut) +{ + int32_t ret = HDF_FAILURE; + uint32_t beginTime = 0; + uint32_t nowTime = 0; + uint32_t fifoPopLen = 0; + uint32_t recvedLen = 0; + uint32_t expectLen = expectSize; + + if (data == NULL || expectSize == 0 || recvSize == NULL) { + HDF_LOGE("%s %d Invalid input \r\n", __FILE__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + if (uartId > HAL_UART_ID_2) { + HDF_LOGE("%s %d Invalid input \r\n", __FILE__, __LINE__); + return HDF_ERR_NOT_SUPPORT; + } + beginTime = TICKS_TO_MS(hal_sys_timer_get()); + do { + fifoPopLen = kfifo_get(&g_uartCtx[uartId].fifo, (uint8_t *)data + recvedLen, expectLen); + recvedLen += fifoPopLen; + expectLen -= fifoPopLen; + if (recvedLen >= expectSize) { + break; + } + /* haven't get any data from fifo */ + if (recvedLen == 0) { + break; + } + /* if reaches here, it means need to wait for more data come */ + OsalSemWait(&g_uartCtx[uartId].rx_sem, timeOut); + /* time out break */ + nowTime = TICKS_TO_MS(hal_sys_timer_get()); + if ((uint32_t)(nowTime - beginTime) >= timeOut) { + break; + } + } while (1); + + if (recvSize != NULL) { + *recvSize = recvedLen; + } + + return HDF_SUCCESS; +} + +static void HalUartHandlerInit(struct UartDevice *device) +{ + uint32_t uartId; + if (device == NULL) { + HDF_LOGE("%s: INVALID PARAM", __func__); + return HDF_ERR_INVALID_PARAM; + } + uartId = device->uartId; + HDF_LOGI("%s %ld\r\n", __func__, uartId); + if (uartId == HAL_UART_ID_0) { + g_uartCtx[uartId].uartDmaRxHandler = UartDmaRxHandler; + g_uartCtx[uartId].uartDmaTxHandler = UartDmaTxHandler; + g_uartCtx[uartId].buffer = g_halUartBuf; + } + + if (uartId == HAL_UART_ID_1) { + g_uartCtx[uartId].uartDmaRxHandler = Uart1DmaRxHandler; + g_uartCtx[uartId].uartDmaTxHandler = Uart1DmaTxHandler; + g_uartCtx[uartId].buffer = g_halUart1Buf; + } + + if (uartId == HAL_UART_ID_2) { + g_uartCtx[uartId].uartDmaRxHandler = Uart2DmaRxHandler; + g_uartCtx[uartId].uartDmaTxHandler = Uart2DmaTxHandler; + g_uartCtx[uartId].buffer = g_halUart2Buf; + } + + if (!g_uartKfifoBuffer[uartId]) { + g_uartKfifoBuffer[uartId] = (char *)OsalMemAlloc(UART_FIFO_MAX_BUFFER); + if (!g_uartKfifoBuffer[uartId]) { + HDF_LOGE("kfifo OsalMemAlloc failed!"); + return; + } + kfifo_init(&g_uartCtx[uartId].fifo, g_uartKfifoBuffer[uartId], UART_FIFO_MAX_BUFFER); + } + + OsalSemInit(&g_uartCtx[uartId].rx_sem, 0); + OsalSemInit(&g_uartCtx[uartId].tx_sem, 0); + + if (g_uartCtx[uartId].rxDMA) { + HDF_LOGE("uart %ld start dma rx\r\n", uartId); + hal_uart_irq_set_dma_handler(uartId, g_uartCtx[uartId].uartDmaRxHandler, g_uartCtx[uartId].uartDmaTxHandler); + HalUartRxStart(uartId); + } else { + HalUartStartRx(uartId); + } +} + +static void UartStart(struct UartDevice *device) +{ + uint32_t uartId; + struct HAL_UART_CFG_T *uartCfg = NULL; + if (device == NULL || device->config == NULL) { + HDF_LOGE("%s: INVALID PARAM", __func__); + return HDF_ERR_INVALID_PARAM; + } + uartId = device->uart_id; + uartCfg = &device->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + hal_uart_open(uartId, uartCfg); + HDF_LOGI("%s %ld\r\n", __FUNCTION__, uartId); + HalUartHandlerInit(device); +} + +/* HdfDriverEntry method definitions */ +static int32_t UartDriverBind(struct HdfDeviceObject *device); +static int32_t UartDriverInit(struct HdfDeviceObject *device); +static void UartDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_UartDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_UART_MODULE_HDF", + .Bind = UartDriverBind, + .Init = UartDriverInit, + .Release = UartDriverRelease, +}; + +/* Initialize HdfDriverEntry */ +HDF_INIT(g_UartDriverEntry); + +/* UartHostMethod method definitions */ +static int32_t UartHostDevInit(struct UartHost *host); +static int32_t UartHostDevDeinit(struct UartHost *host); +static int32_t UartHostDevWrite(struct UartHost *host, uint8_t *data, uint32_t size); +static int32_t UartHostDevSetBaud(struct UartHost *host, uint32_t baudRate); +static int32_t UartHostDevGetBaud(struct UartHost *host, uint32_t *baudRate); +static int32_t UartHostDevRead(struct UartHost *host, uint8_t *data, uint32_t size); +static int32_t UartHostDevSetAttribute(struct UartHost *host, struct UartAttribute *attribute); +static int32_t UartHostDevGetAttribute(struct UartHost *host, struct UartAttribute *attribute); +static int32_t UartHostDevSetTransMode(struct UartHost *host, enum UartTransMode mode); + +/* UartHostMethod definitions */ +struct UartHostMethod g_uartHostMethod = { + .Init = UartHostDevInit, + .Deinit = UartHostDevDeinit, + .Read = UartHostDevRead, + .Write = UartHostDevWrite, + .SetBaud = UartHostDevSetBaud, + .GetBaud = UartHostDevGetBaud, + .SetAttribute = UartHostDevSetAttribute, + .GetAttribute = UartHostDevGetAttribute, + .SetTransMode = UartHostDevSetTransMode, +}; + +static int InitUartDevice(struct UartHost *host) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + struct HAL_UART_CFG_T *uartCfg = NULL; + struct UartResource *resource = NULL; + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + resource = &uartDevice->resource; + if (resource == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartCfg = &uartDevice->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartDevice->uart_id = resource->num; + uartCfg->parity = resource->parity; + uartCfg->stop = resource->stopBit; + uartCfg->data = resource->wlen; + uartCfg->flow = HAL_UART_FLOW_CONTROL_NONE; + uartCfg->tx_level = HAL_UART_FIFO_LEVEL_1_2; + uartCfg->rx_level = HAL_UART_FIFO_LEVEL_1_2; + uartCfg->baud = resource->baudrate; + uartCfg->dma_rx_stop_on_err = false; + uartCfg->dma_rx = resource->rxDMA; + uartCfg->dma_tx = resource->txDMA; + + g_uartCtx[uartDevice->uart_id].txDMA = resource->txDMA; + g_uartCtx[uartDevice->uart_id].rxDMA = resource->rxDMA; + + if (!uartDevice->init_flag) { + HDF_LOGE("uart %ld device init\r\n", uartDevice->uart_id); + HalSetUartIomux(uartDevice->uart_id); + UartStart(uartDevice); + uartDevice->init_flag = true; + } + + return HDF_SUCCESS; +} + +static uint32_t GetUartDeviceResource( + struct UartDevice *device, const struct DeviceResourceNode *resourceNode) +{ + struct DeviceResourceIface *dri = NULL; + struct UartResource *resource = NULL; + if (device == NULL || resourceNode == NULL) { + HDF_LOGE("%s: INVALID PARAM", __func__); + return HDF_ERR_INVALID_PARAM; + } + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid"); + return HDF_ERR_INVALID_PARAM; + } + if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read num 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, "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, "data", &resource->wlen, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read data fail"); + return HDF_FAILURE; + } + + resource->txDMA = dri->GetBool(resourceNode, "txDMA"); + resource->rxDMA = dri->GetBool(resourceNode, "rxDMA"); + + // copy config + device->uart_id = resource->num; + device->config.baud = resource->baudrate; + device->config.parity = resource->parity; + device->config.stop = resource->stopBit; + device->config.data = resource->wlen; + device->config.dma_rx = resource->rxDMA; + device->config.dma_tx = resource->txDMA; + return HDF_SUCCESS; +} + +static int32_t AttachUartDevice(struct UartHost *uartHost, struct HdfDeviceObject *device) +{ + int32_t ret; + struct UartDevice *uartDevice = NULL; + + if (uartHost == NULL || device == NULL || device->property == NULL) { + HDF_LOGE("%s: property is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)OsalMemAlloc(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; + } + + uartHost->priv = uartDevice; + + return InitUartDevice(uartHost); +} + +static int32_t UartDriverBind(struct HdfDeviceObject *device) +{ + struct UartHost *devService; + if (device == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + devService = (struct UartHost *)OsalMemAlloc(sizeof(*devService)); + if (devService == NULL) { + HDF_LOGE("%s: OsalMemCalloc error", __func__); + return HDF_ERR_INVALID_OBJECT; + } + devService->device = device; + device->service = &(devService->service); + devService->priv = NULL; + devService->method = NULL; + return HDF_SUCCESS; +} + +static void UartDriverRelease(struct HdfDeviceObject *device) +{ + HDF_LOGI("Enter %s:", __func__); + uint32_t uartId; + struct UartHost *host = NULL; + struct UartDevice *uartDevice = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + + host = UartHostFromDevice(device); + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return; + } + uartId = uartDevice->uart_id; + host->method = NULL; + + OsalSemDestroy(&g_uartCtx[uartId].rx_sem); + OsalSemDestroy(&g_uartCtx[uartId].tx_sem); + OsalMemFree(uartDevice); + if (host == NULL) { + return; + } + OsalMemFree(host); +} + +static int32_t UartDriverInit(struct HdfDeviceObject *device) +{ + HDF_LOGI("Enter %s:", __func__); + int32_t ret; + struct UartHost *host = NULL; + + 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_ERR_INVALID_OBJECT; + } + + ret = AttachUartDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error", __func__); + return HDF_FAILURE; + } + + host->method = &g_uartHostMethod; + + return ret; +} + +/* UartHostMethod implementations */ +static int32_t UartHostDevInit(struct UartHost *host) +{ + HDF_LOGI("%s: Enter\r\n", __func__); + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + InitUartDevice(host); + return HDF_SUCCESS; +} + +static int32_t UartHostDevDeinit(struct UartHost *host) +{ + HDF_LOGI("%s: Enter", __func__); + uint32_t uartId; + struct UartDevice *uartDevice = NULL; + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: INVALID OBJECT", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartId = uartDevice->uart_id; + uartDevice->init_flag = false; + + hal_uart_close(uartId); + + return HDF_SUCCESS; +} + +static int32_t UartHostDevWrite(struct UartHost *host, uint8_t *data, uint32_t size) +{ + struct UartDevice *device = NULL; + uint32_t portId; + + if (host == NULL || data == NULL || size == 0 || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + portId = device->uartId; + if (g_uartCtx[portId].txDMA) { + HalUartSend(portId, data, size, HDF_UART_TMO); + } else { + for (uint32_t idx = 0; idx < size; idx++) { + if (!g_uartCtx[portId].isblock) { + hal_uart_blocked_putc(portId, data[idx]); + } else { + hal_uart_putc(portId, data[idx]); + } + } + } + + return HDF_SUCCESS; +} + +static int32_t UartHostDevRead(struct UartHost *host, uint8_t *data, uint32_t size) +{ + uint32_t recvSize = 0; + int32_t ret; + uint32_t uartId; + struct UartDevice *uartDevice = NULL; + if (host == NULL || data == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + uartId = uartDevice->uartId; + if (g_uartCtx[uartId].rxDMA) { + ret = HalUartRecv(uartId, data, size, &recvSize, HDF_UART_TMO); + if (ret != HDF_SUCCESS) { + HDF_LOGE("uart %ld recev error\r\n", uartId); + return ret; + } + ret = recvSize; + } else { + if (!g_uartCtx[uartId].isblock) { + data[0] = hal_uart_blocked_getc(uartId); + } else { + data[0] = hal_uart_getc(uartId); + } + ret = 1; + } + + return ret; +} + +static int32_t UartHostDevSetBaud(struct UartHost *host, uint32_t baudRate) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + struct HAL_UART_CFG_T *uartCfg = NULL; + uint32_t uartId; + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartId = uartDevice->uartId; + + uartCfg = &uartDevice->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: device config is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartCfg->baud = baudRate; + + hal_uart_reopen(uartId, uartCfg); + + return HDF_SUCCESS; +} + +static int32_t UartHostDevGetBaud(struct UartHost *host, uint32_t *baudRate) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + struct HAL_UART_CFG_T *uartCfg = NULL; + uint32_t uartId; + if (host == NULL || baudRate == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartId = uartDevice->uartId; + uartCfg = &uartDevice->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + baudRate = &uartCfg->baud; + if (baudRate == NULL) { + HDF_LOGE("%s: baudRate is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + return HDF_SUCCESS; +} + +static int32_t UartHostDevSetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + struct HAL_UART_CFG_T *uartCfg = NULL; + uint32_t uartId; + if (host == NULL || attribute == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartId = uartDevice->uartId; + uartCfg = &uartDevice->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: config is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + switch (attribute->dataBits) { + case UART_ATTR_DATABIT_8: + uartCfg->data = HAL_UART_DATA_BITS_8; + break; + case UART_ATTR_DATABIT_7: + uartCfg->data = HAL_UART_DATA_BITS_7; + break; + case UART_ATTR_DATABIT_6: + uartCfg->data = HAL_UART_DATA_BITS_6; + break; + case UART_ATTR_DATABIT_5: + uartCfg->data = HAL_UART_DATA_BITS_5; + break; + default: + uartCfg->data = HAL_UART_DATA_BITS_8; + break; + } + + uartCfg->parity = attribute->parity; + + switch (attribute->stopBits) { + case UART_ATTR_STOPBIT_1: + case UART_ATTR_STOPBIT_2: + uartCfg->stop = attribute->stopBits; + break; + default: + uartCfg->stop = UART_ATTR_STOPBIT_1; + break; + } + + if (attribute->rts && attribute->cts) { + uartCfg->flow = HAL_UART_FLOW_CONTROL_RTSCTS; + } else if (attribute->rts && !attribute->cts) { + uartCfg->flow = HAL_UART_FLOW_CONTROL_RTS; + } else if (!attribute->rts && attribute->cts) { + uartCfg->flow = HAL_UART_FLOW_CONTROL_CTS; + } else { + uartCfg->flow = HAL_UART_FLOW_CONTROL_NONE; + } + + hal_uart_reopen(uartId, uartCfg); + + return HDF_SUCCESS; +} + +static int32_t UartHostDevGetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + struct HAL_UART_CFG_T *uartCfg = NULL; + if (host == NULL || attribute == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartCfg = &uartDevice->config; + if (uartCfg == NULL) { + HDF_LOGE("%s: config is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + switch (uartCfg->data) { + case HAL_UART_DATA_BITS_8: + attribute->dataBits = UART_ATTR_DATABIT_8; + break; + case HAL_UART_DATA_BITS_7: + attribute->dataBits = UART_ATTR_DATABIT_7; + break; + case HAL_UART_DATA_BITS_6: + attribute->dataBits = UART_ATTR_DATABIT_6; + break; + case HAL_UART_DATA_BITS_5: + attribute->dataBits = UART_ATTR_DATABIT_5; + break; + default: + attribute->dataBits = UART_ATTR_DATABIT_8; + break; + } + + attribute->parity = uartCfg->parity; + attribute->stopBits = uartCfg->stop; + + switch (uartCfg->flow) { + case HAL_UART_FLOW_CONTROL_NONE: + attribute->rts = 0; + attribute->cts = 0; + break; + case HAL_UART_FLOW_CONTROL_CTS: + attribute->rts = 0; + attribute->cts = 1; + break; + case HAL_UART_FLOW_CONTROL_RTS: + attribute->rts = 1; + attribute->cts = 0; + break; + case HAL_UART_FLOW_CONTROL_RTSCTS: + attribute->rts = 1; + attribute->cts = 1; + break; + default: + attribute->rts = 0; + attribute->cts = 0; + break; + } + + return HDF_SUCCESS; +} + +static int32_t UartHostDevSetTransMode(struct UartHost *host, enum UartTransMode mode) +{ + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *uartDevice = NULL; + uint32_t uartId; + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + uartDevice = (struct UartDevice *)host->priv; + if (uartDevice == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + uartId = uartDevice->uartId; + + if ((UART_MODE_RD_BLOCK & mode) == 0) { + g_uartCtx[uartId].isblock = UART_MODE_RD_BLOCK; + } else { + g_uartCtx[uartId].isblock = UART_MODE_RD_NONBLOCK; + } + + if ((UART_MODE_DMA_RX_EN & mode) == 0) { + g_uartCtx[uartId].rxDMA = UART_MODE_DMA_RX_EN; + } else { + g_uartCtx[uartId].rxDMA = UART_MODE_DMA_RX_DIS; + } + + if ((UART_MODE_DMA_TX_EN & mode) == 0) { + g_uartCtx[uartId].txDMA = UART_MODE_DMA_TX_EN; + } else { + g_uartCtx[uartId].txDMA = UART_MODE_DMA_TX_DIS; + } + + return HDF_SUCCESS; +} diff --git a/platform/uart/uart_bes.h b/platform/uart/uart_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..454e1015e6d8540df0150f61802dfaaf85d210e9 --- /dev/null +++ b/platform/uart/uart_bes.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __UART_BES_H__ +#define __UART_BES_H__ + +#include "uart_if.h" +#include "uart_core.h" +#include "hal_uart.h" +#include "kfifo.h" +#include "osal_sem.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define UART_DEV_SERVICE_NAME_PREFIX "HDF_PLATFORM_UART%d" +#define MAX_DEV_NAME_SIZE 32 + +struct UartResource { + uint32_t num; /* UART port num */ + uint32_t baudRate; /* Default baudrate */ + uint32_t wLen; /* Default word length */ + uint32_t parity; /* Default parity */ + uint32_t stopBit; /* Default stop bits */ + bool txDMA; + bool rxDMA; +}; + +enum UartDeviceState { + UART_DEVICE_UNINITIALIZED = 0x0u, + UART_DEVICE_INITIALIZED = 0x1u, +}; + +struct UART_CTX_OBJ { + uint8_t *buffer; + bool txDMA; + bool rxDMA; + bool isBlock; + struct kfifo fifo; + struct OsalSem rxSem; + struct OsalSem txSem; + void (*UartDmaRxHandler)(uint32_t xferSize, int dmaError, union HAL_UART_IRQ_T status); + void (*UartDmaTxHandler)(uint32_t xferSize, int dmaError); +}; + +struct UartDevice { + struct IDeviceIoService ioService; + struct UartResource resource; + struct HAL_UART_CFG_T config; + uint32_t uartId; + bool initFlag; + uint32_t transMode; +}; + +enum { + UART_READ = 0, + UART_WRITE +}; + +int32_t UartDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/platform/watchdog/BUILD.gn b/platform/watchdog/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1c559dea80fa6765427147b618f417ae6e07e480 --- /dev/null +++ b/platform/watchdog/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//drivers/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_WATCHDOG) +module_name = get_path_info(rebase_path("."), "name") + +hdf_driver(module_name) { + sources = [] + if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { + sources += [ "watchdog_bes.c" ] + } + + include_dirs = [ "." ] +} diff --git a/platform/watchdog/watchdog_bes.c b/platform/watchdog/watchdog_bes.c new file mode 100755 index 0000000000000000000000000000000000000000..d0e22d6ed3bec8093fb5ae46116c487a0a13d2e6 --- /dev/null +++ b/platform/watchdog/watchdog_bes.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "watchdog_bes.h" +#include +#include +#include "device_resource_if.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "hal_trace.h" +#include "hal_sleep.h" +#include "watchdog_if.h" + +static int g_watchdogStart; +static int g_watchdogTimeout; + +static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr); +static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr); +static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds); +static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds); +static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status); +static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr); + +struct WatchdogMethod g_WatchdogCntlrMethod = { + .getStatus = WatchdogDevGetStatus, + .setTimeout = WatchdogDevSetTimeout, + .getTimeout = WatchdogDevGetTimeout, + .start = WatchdogDevStart, + .stop = WatchdogDevStop, + .feed = WatchdogDevFeed, + .getPriv = NULL, // WatchdogDevGetPriv + .releasePriv = NULL, // WatchdogDevReleasePriv +}; + +static void WatchdogIrqHandler(enum HAL_WDT_ID_T id, enum HAL_WDT_EVENT_T event) +{ + HDF_LOGD("%s: id %d event %d\r\n", __func__, id, event); +} + +static int InitWatchdogDevice(struct WatchdogDevice *watchdogDevice) +{ + struct WatchdogResource *resource = NULL; + int32_t watchdogId; + if (watchdogDevice == NULL) { + HDF_LOGE("%s: invaild parameter\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + resource = &watchdogDevice->resource; + if (resource == NULL) { + HDF_LOGE("resource is NULL\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + watchdogId = resource->watchdogId; + hal_wdt_set_irq_callback(watchdogId, WatchdogIrqHandler); + return HDF_SUCCESS; +} + +static uint32_t GetWatchdogDeviceResource( + struct WatchdogDevice *device, const struct DeviceResourceNode *resourceNode) +{ + struct WatchdogResource *resource = NULL; + struct DeviceResourceIface *dri = NULL; + if (device == NULL || resourceNode == NULL) { + HDF_LOGE("resource or device is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + resource = &device->resource; + if (resource == NULL) { + HDF_LOGE("resource is NULL\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + if (dri->GetUint32(resourceNode, "watchdogId", &resource->watchdogId, 0) != HDF_SUCCESS) { + HDF_LOGE("read watchdogId fail\r\n"); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t AttachWatchdogDevice(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device) +{ + int32_t ret; + struct WatchdogDevice *watchdogDevice = NULL; + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_FAILURE; + } + + watchdogDevice = (struct WatchdogDevice *)OsalMemAlloc(sizeof(struct WatchdogDevice)); + if (watchdogDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc watchdogDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = GetWatchdogDeviceResource(watchdogDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(watchdogDevice); + return HDF_FAILURE; + } + + watchdogCntlr->priv = watchdogDevice; + watchdogCntlr->wdtId = watchdogDevice->resource.watchdogId; + + return InitWatchdogDevice(watchdogDevice); +} +/* HdfDriverEntry method definitions */ +static int32_t WatchdogDriverBind(struct HdfDeviceObject *device); +static int32_t WatchdogDriverInit(struct HdfDeviceObject *device); +static void WatchdogDriverRelease(struct HdfDeviceObject *device); + +/* HdfDriverEntry definitions */ +struct HdfDriverEntry g_watchdogDriverEntry = { + .moduleVersion = 1, + .moduleName = "BES_WATCHDOG_MODULE_HDF", + .Bind = WatchdogDriverBind, + .Init = WatchdogDriverInit, + .Release = WatchdogDriverRelease, +}; + +// Initialize HdfDriverEntry +HDF_INIT(g_watchdogDriverEntry); + +static int32_t WatchdogDriverBind(struct HdfDeviceObject *device) +{ + struct WatchdogCntlr *watchdogCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("hdfDevice object is null!\r\n"); + return HDF_FAILURE; + } + + watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr)); + if (watchdogCntlr == NULL) { + HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + HDF_LOGI("Enter %s\r\n", __func__); + device->service = &watchdogCntlr->service; + watchdogCntlr->device = device; + watchdogCntlr->priv = NULL; + return HDF_SUCCESS; +} + +static int32_t WatchdogDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct WatchdogCntlr *watchdogCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + HDF_LOGI("Enter %s:\r\n", __func__); + + watchdogCntlr = WatchdogCntlrFromDevice(device); + if (watchdogCntlr == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = AttachWatchdogDevice(watchdogCntlr, device); + if (ret != HDF_SUCCESS) { + OsalMemFree(watchdogCntlr); + HDF_LOGE("%s:attach error\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogCntlr->ops = &g_WatchdogCntlrMethod; + + HDF_LOGE("WatchdogDriverInit success!\r\n"); + return ret; +} + +static void WatchdogDriverRelease(struct HdfDeviceObject *device) +{ + struct WatchdogCntlr *watchdogCntlr = NULL; + struct WatchdogDevice *watchdogDevice = NULL; + + if (device == NULL) { + HDF_LOGE("device is null\r\n"); + return; + } + + watchdogCntlr = WatchdogCntlrFromDevice(device); + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv; + if (watchdogDevice != NULL) { + OsalMemFree(watchdogDevice); + } + return; +} + +static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr) +{ + struct WatchdogDevice *watchdogDevice = NULL; + int32_t watchdogId; + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv; + if (watchdogDevice == NULL) { + HDF_LOGE("%s: OBJECT is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + watchdogId = watchdogDevice->resource.watchdogId; + + hal_wdt_start(watchdogId); + g_watchdogStart = 1; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr) +{ + int32_t watchdogId; + struct WatchdogDevice *watchdogDevice = NULL; + + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_FAILURE; + } + + watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv; + if (watchdogDevice == NULL) { + HDF_LOGE("%s: OBJECT is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + watchdogId = watchdogDevice->resource.watchdogId; + hal_wdt_stop(watchdogId); + g_watchdogStart = 0; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds) +{ + int32_t watchdogId; + struct WatchdogDevice *watchdogDevice = NULL; + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + g_watchdogTimeout = seconds; + watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv; + if (watchdogDevice == NULL) { + HDF_LOGE("%s: OBJECT is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + watchdogId = watchdogDevice->resource.watchdogId; + hal_wdt_set_timeout(watchdogId, seconds); + return HDF_SUCCESS; +} + +static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds) +{ + if (watchdogCntlr == NULL || seconds == NULL) { + HDF_LOGE("%s: PARAM is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + *seconds = g_watchdogTimeout; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status) +{ + if (watchdogCntlr == NULL || status == NULL) { + HDF_LOGE("%s: PARAM is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (g_watchdogStart == 1) { + *status = WATCHDOG_START; + } else { + *status = WATCHDOG_STOP; + } + return HDF_SUCCESS; +} + +static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr) +{ + struct WatchdogDevice *watchdogDevice = NULL; + + if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) { + HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv; + int32_t watchdogId = watchdogDevice->resource.watchdogId; + hal_wdt_ping(watchdogId); + return HDF_SUCCESS; +} + +static int32_t WatchdogDevGetPriv(struct WatchdogCntlr *watchdogCntlr) +{ + (void)watchdogCntlr; + return HDF_SUCCESS; +} + +static int32_t WatchdogDevReleasePriv(struct WatchdogCntlr *watchdogCntlr) +{ + (void)watchdogCntlr; + return HDF_SUCCESS; +} \ No newline at end of file diff --git a/platform/watchdog/watchdog_bes.h b/platform/watchdog/watchdog_bes.h new file mode 100755 index 0000000000000000000000000000000000000000..2f08bd2c172f8afd359fca3744bd1f6e048ac494 --- /dev/null +++ b/platform/watchdog/watchdog_bes.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BES_WATCHDOG_H +#define BES_WATCHDOG_H + +#include "hal_wdt.h" +#include "watchdog_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct WatchdogResource { + enum HAL_WDT_ID_T watchdogId; +}; + +struct WatchdogDevice { + struct WatchdogResource resource; +}; + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file