13d0407baSopenharmony_ci/*
23d0407baSopenharmony_ci * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
33d0407baSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43d0407baSopenharmony_ci * you may not use this file except in compliance with the License.
53d0407baSopenharmony_ci * You may obtain a copy of the License at
63d0407baSopenharmony_ci *
73d0407baSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83d0407baSopenharmony_ci *
93d0407baSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103d0407baSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113d0407baSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123d0407baSopenharmony_ci * See the License for the specific language governing permissions and
133d0407baSopenharmony_ci * limitations under the License.
143d0407baSopenharmony_ci */
153d0407baSopenharmony_ci#include <stdio.h>
163d0407baSopenharmony_ci#include <stdint.h>
173d0407baSopenharmony_ci
183d0407baSopenharmony_ci#include "gpio/gpio_core.h"
193d0407baSopenharmony_ci#include "device_resource_if.h"
203d0407baSopenharmony_ci#include "hdf_device_desc.h"
213d0407baSopenharmony_ci#include "hdf_log.h"
223d0407baSopenharmony_ci#include "stdio.h"
233d0407baSopenharmony_ci
243d0407baSopenharmony_ci#include "lz_hardware.h"
253d0407baSopenharmony_ci
263d0407baSopenharmony_ci#define PRINT_ERR(fmt, args...)     do { \
273d0407baSopenharmony_ci    if (1) printf("%s, %d, error: "fmt, __func__, __LINE__, ##args); \
283d0407baSopenharmony_ci} while (0)
293d0407baSopenharmony_ci
303d0407baSopenharmony_ci#define PRINT_WARR(fmt, args...)    do { \
313d0407baSopenharmony_ci    if (1) printf("%s, %d, warr: "fmt, __func__, __LINE__, ##args); \
323d0407baSopenharmony_ci} while (0)
333d0407baSopenharmony_ci
343d0407baSopenharmony_ci#define PRINT_LOG(fmt, args...)    do { \
353d0407baSopenharmony_ci    if (1) printf("%s, %d, log: "fmt, __func__, __LINE__, ##args); \
363d0407baSopenharmony_ci} while (0)
373d0407baSopenharmony_ci
383d0407baSopenharmony_ci#define RK2206_GPIO_NAME            "rk2206_gpio"
393d0407baSopenharmony_ci
403d0407baSopenharmony_cistatic struct GpioCntlr m_gpioCntlr;
413d0407baSopenharmony_cistatic struct GpioInfo *m_gpioInfo = NULL;
423d0407baSopenharmony_cistatic int32_t m_groupNum = 0;
433d0407baSopenharmony_cistatic int32_t m_bitNum = 0;
443d0407baSopenharmony_ci#define GPIO_MAXSIZE            256
453d0407baSopenharmony_cistatic uint8_t m_gpio_init_flag[GPIO_MAXSIZE];
463d0407baSopenharmony_ci
473d0407baSopenharmony_cistatic int32_t iodrv_initgpio(uint16_t gpio)
483d0407baSopenharmony_ci{
493d0407baSopenharmony_ci    GpioID gpio_id = (GpioID)(gpio);
503d0407baSopenharmony_ci
513d0407baSopenharmony_ci    if (gpio >= GPIO_MAXSIZE) {
523d0407baSopenharmony_ci        PRINT_ERR("%s: gpio(%d) >= GPIO_MAXSIZE(%d)", __func__, gpio, GPIO_MAXSIZE);
533d0407baSopenharmony_ci        return HDF_FAILURE;
543d0407baSopenharmony_ci    }
553d0407baSopenharmony_ci
563d0407baSopenharmony_ci    if (m_gpio_init_flag[gpio] == 1) {
573d0407baSopenharmony_ci        return HDF_SUCCESS;
583d0407baSopenharmony_ci    }
593d0407baSopenharmony_ci
603d0407baSopenharmony_ci    PinctrlSet(gpio_id, MUX_FUNC0, PULL_KEEP, DRIVE_LEVEL0);
613d0407baSopenharmony_ci    LzGpioInit(gpio_id);
623d0407baSopenharmony_ci    m_gpio_init_flag[gpio] = 1;
633d0407baSopenharmony_ci
643d0407baSopenharmony_ci    return HDF_SUCCESS;
653d0407baSopenharmony_ci}
663d0407baSopenharmony_ci
673d0407baSopenharmony_cistatic int32_t iodrv_setdir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
683d0407baSopenharmony_ci{
693d0407baSopenharmony_ci    if (cntlr == NULL) {
703d0407baSopenharmony_ci        PRINT_ERR("%s: cntlr is null", __func__);
713d0407baSopenharmony_ci        return HDF_FAILURE;
723d0407baSopenharmony_ci    }
733d0407baSopenharmony_ci    if (gpio >= cntlr->count) {
743d0407baSopenharmony_ci        PRINT_ERR("%s: gpio(%d) >= cntlr->count(%d)", __func__, gpio, cntlr->count);
753d0407baSopenharmony_ci        return HDF_FAILURE;
763d0407baSopenharmony_ci    }
773d0407baSopenharmony_ci    if ((dir != GPIO_DIR_IN) && (dir != GPIO_DIR_OUT)) {
783d0407baSopenharmony_ci        PRINT_ERR("%s: dir(%d) out of the range", __func__, dir);
793d0407baSopenharmony_ci        return HDF_FAILURE;
803d0407baSopenharmony_ci    }
813d0407baSopenharmony_ci
823d0407baSopenharmony_ci    GpioID gpio_id = (GpioID)(gpio);
833d0407baSopenharmony_ci    LzGpioDir gpio_dir = (dir == GPIO_DIR_IN) ? (LZGPIO_DIR_IN) : (LZGPIO_DIR_OUT);
843d0407baSopenharmony_ci
853d0407baSopenharmony_ci    iodrv_initgpio(gpio);
863d0407baSopenharmony_ci    LzGpioSetDir(gpio_id, gpio_dir);
873d0407baSopenharmony_ci
883d0407baSopenharmony_ci    return HDF_SUCCESS;
893d0407baSopenharmony_ci}
903d0407baSopenharmony_ci
913d0407baSopenharmony_cistatic int32_t iodrv_getdir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
923d0407baSopenharmony_ci{
933d0407baSopenharmony_ci    if (cntlr == NULL) {
943d0407baSopenharmony_ci        PRINT_ERR("%s: cntlr is null", __func__);
953d0407baSopenharmony_ci        return HDF_FAILURE;
963d0407baSopenharmony_ci    }
973d0407baSopenharmony_ci    if (gpio >= cntlr->count) {
983d0407baSopenharmony_ci        PRINT_ERR("%s: gpio(%d) >= cntlr->count(%d)", __func__, gpio, cntlr->count);
993d0407baSopenharmony_ci        return HDF_FAILURE;
1003d0407baSopenharmony_ci    }
1013d0407baSopenharmony_ci    if (dir == NULL) {
1023d0407baSopenharmony_ci        PRINT_ERR("%s: dir is null", __func__);
1033d0407baSopenharmony_ci        return HDF_FAILURE;
1043d0407baSopenharmony_ci    }
1053d0407baSopenharmony_ci
1063d0407baSopenharmony_ci    GpioID gpio_id = (GpioID)(gpio);
1073d0407baSopenharmony_ci    LzGpioDir gpio_dir;
1083d0407baSopenharmony_ci    unsigned int ret;
1093d0407baSopenharmony_ci
1103d0407baSopenharmony_ci    iodrv_initgpio(gpio);
1113d0407baSopenharmony_ci
1123d0407baSopenharmony_ci    ret = LzGpioGetDir(gpio_id, &gpio_dir);
1133d0407baSopenharmony_ci    if (ret != LZ_HARDWARE_SUCCESS) {
1143d0407baSopenharmony_ci        PRINT_ERR("%s: LzGpioGetDir error", __func__);
1153d0407baSopenharmony_ci        return HDF_FAILURE;
1163d0407baSopenharmony_ci    }
1173d0407baSopenharmony_ci
1183d0407baSopenharmony_ci    *dir = (gpio_dir == LZGPIO_DIR_IN) ? (GPIO_DIR_IN) : (GPIO_DIR_OUT);
1193d0407baSopenharmony_ci
1203d0407baSopenharmony_ci    return HDF_SUCCESS;
1213d0407baSopenharmony_ci}
1223d0407baSopenharmony_ci
1233d0407baSopenharmony_cistatic int32_t iodrv_write(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t value)
1243d0407baSopenharmony_ci{
1253d0407baSopenharmony_ci    if (cntlr == NULL) {
1263d0407baSopenharmony_ci        PRINT_ERR("%s: cntlr is null", __func__);
1273d0407baSopenharmony_ci        return HDF_FAILURE;
1283d0407baSopenharmony_ci    }
1293d0407baSopenharmony_ci    if (gpio >= cntlr->count) {
1303d0407baSopenharmony_ci        PRINT_ERR("%s: gpio(%d) >= cntlr->count(%d)", __func__, gpio, cntlr->count);
1313d0407baSopenharmony_ci        return HDF_FAILURE;
1323d0407baSopenharmony_ci    }
1333d0407baSopenharmony_ci
1343d0407baSopenharmony_ci    GpioID gpio_id = (GpioID)(gpio);
1353d0407baSopenharmony_ci    LzGpioValue gpio_value = (value == 0) ? (LZGPIO_LEVEL_LOW) : (LZGPIO_LEVEL_HIGH);
1363d0407baSopenharmony_ci
1373d0407baSopenharmony_ci    iodrv_initgpio(gpio);
1383d0407baSopenharmony_ci    LzGpioSetDir(gpio_id, LZGPIO_DIR_OUT);
1393d0407baSopenharmony_ci    LzGpioSetVal(gpio_id, gpio_value);
1403d0407baSopenharmony_ci
1413d0407baSopenharmony_ci    return HDF_SUCCESS;
1423d0407baSopenharmony_ci}
1433d0407baSopenharmony_ci
1443d0407baSopenharmony_cistatic int32_t iodrv_read(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *value)
1453d0407baSopenharmony_ci{
1463d0407baSopenharmony_ci    if (cntlr == NULL) {
1473d0407baSopenharmony_ci        PRINT_ERR("%s: cntlr is null", __func__);
1483d0407baSopenharmony_ci        return HDF_FAILURE;
1493d0407baSopenharmony_ci    }
1503d0407baSopenharmony_ci    if (gpio >= cntlr->count) {
1513d0407baSopenharmony_ci        PRINT_ERR("%s: gpio(%d) >= cntlr->count(%d)", __func__, gpio, cntlr->count);
1523d0407baSopenharmony_ci        return HDF_FAILURE;
1533d0407baSopenharmony_ci    }
1543d0407baSopenharmony_ci    if (value == NULL) {
1553d0407baSopenharmony_ci        PRINT_ERR("%s: value is null", __func__);
1563d0407baSopenharmony_ci        return HDF_FAILURE;
1573d0407baSopenharmony_ci    }
1583d0407baSopenharmony_ci
1593d0407baSopenharmony_ci    GpioID gpio_id = (GpioID)(gpio);
1603d0407baSopenharmony_ci    LzGpioValue gpio_value;
1613d0407baSopenharmony_ci    unsigned int ret;
1623d0407baSopenharmony_ci
1633d0407baSopenharmony_ci    iodrv_initgpio(gpio);
1643d0407baSopenharmony_ci
1653d0407baSopenharmony_ci    ret = LzGpioGetVal(gpio_id, &gpio_value);
1663d0407baSopenharmony_ci    if (ret != LZ_HARDWARE_SUCCESS) {
1673d0407baSopenharmony_ci        PRINT_ERR("%s: LzGpioGetVal error", __func__);
1683d0407baSopenharmony_ci        return HDF_FAILURE;
1693d0407baSopenharmony_ci    }
1703d0407baSopenharmony_ci
1713d0407baSopenharmony_ci    *value = (gpio_value == LZGPIO_LEVEL_LOW) ? (0) : (1);
1723d0407baSopenharmony_ci
1733d0407baSopenharmony_ci    return HDF_SUCCESS;
1743d0407baSopenharmony_ci}
1753d0407baSopenharmony_ci
1763d0407baSopenharmony_cistatic int32_t iodrv_readdrs(struct DeviceResourceNode *node, uint32_t *groupNum, uint32_t *bitNum)
1773d0407baSopenharmony_ci{
1783d0407baSopenharmony_ci    int32_t ret;
1793d0407baSopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
1803d0407baSopenharmony_ci
1813d0407baSopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
1823d0407baSopenharmony_ci    if (drsOps == NULL) {
1833d0407baSopenharmony_ci        PRINT_ERR("%s: invalid drs ops!", __func__);
1843d0407baSopenharmony_ci        return HDF_FAILURE;
1853d0407baSopenharmony_ci    }
1863d0407baSopenharmony_ci    if (drsOps->GetUint32 == NULL) {
1873d0407baSopenharmony_ci        PRINT_ERR("%s: GetUint32 failed!", __func__);
1883d0407baSopenharmony_ci        return HDF_FAILURE;
1893d0407baSopenharmony_ci    }
1903d0407baSopenharmony_ci    if (groupNum == NULL) {
1913d0407baSopenharmony_ci        PRINT_ERR("%s: groupNum is null!", __func__);
1923d0407baSopenharmony_ci        return HDF_FAILURE;
1933d0407baSopenharmony_ci    }
1943d0407baSopenharmony_ci    if (bitNum == NULL) {
1953d0407baSopenharmony_ci        PRINT_ERR("%s: bitNum is null!", __func__);
1963d0407baSopenharmony_ci        return HDF_FAILURE;
1973d0407baSopenharmony_ci    }
1983d0407baSopenharmony_ci
1993d0407baSopenharmony_ci    ret = drsOps->GetUint32(node, "groupNum", groupNum, 0);
2003d0407baSopenharmony_ci    if (ret != HDF_SUCCESS) {
2013d0407baSopenharmony_ci        PRINT_ERR("%s: read groupNum failed!", __func__);
2023d0407baSopenharmony_ci    }
2033d0407baSopenharmony_ci
2043d0407baSopenharmony_ci    ret = drsOps->GetUint32(node, "bitNum", bitNum, 0);
2053d0407baSopenharmony_ci    if (ret != HDF_SUCCESS) {
2063d0407baSopenharmony_ci        PRINT_ERR("%s: read bitNum failed!", __func__);
2073d0407baSopenharmony_ci    }
2083d0407baSopenharmony_ci
2093d0407baSopenharmony_ci    return HDF_SUCCESS;
2103d0407baSopenharmony_ci}
2113d0407baSopenharmony_ci
2123d0407baSopenharmony_cistatic struct GpioMethod m_gpio_method = {
2133d0407baSopenharmony_ci    .request = NULL,
2143d0407baSopenharmony_ci    .release = NULL,
2153d0407baSopenharmony_ci    .write = iodrv_write,
2163d0407baSopenharmony_ci    .read = iodrv_read,
2173d0407baSopenharmony_ci    .setDir = iodrv_setdir,
2183d0407baSopenharmony_ci    .getDir = iodrv_getdir,
2193d0407baSopenharmony_ci    .toIrq = NULL,
2203d0407baSopenharmony_ci    .setIrq = NULL,
2213d0407baSopenharmony_ci    .unsetIrq = NULL,
2223d0407baSopenharmony_ci    .enableIrq = NULL,
2233d0407baSopenharmony_ci    .disableIrq = NULL,
2243d0407baSopenharmony_ci};
2253d0407baSopenharmony_ci
2263d0407baSopenharmony_cistatic int32_t iodrv_init(struct HdfDeviceObject *device)
2273d0407baSopenharmony_ci{
2283d0407baSopenharmony_ci    int32_t ret;
2293d0407baSopenharmony_ci    struct GpioCntlr *cntlr = &m_gpioCntlr;
2303d0407baSopenharmony_ci    uint32_t i;
2313d0407baSopenharmony_ci
2323d0407baSopenharmony_ci    PRINT_LOG("%s: Enter\n", __func__);
2333d0407baSopenharmony_ci    if ((device == NULL) || (device->property == NULL)) {
2343d0407baSopenharmony_ci        PRINT_ERR("%s: device or property is null!", __func__);
2353d0407baSopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
2363d0407baSopenharmony_ci    }
2373d0407baSopenharmony_ci
2383d0407baSopenharmony_ci    ret = iodrv_readdrs(device->property, &m_groupNum, &m_bitNum);
2393d0407baSopenharmony_ci    if (ret != HDF_SUCCESS) {
2403d0407baSopenharmony_ci        PRINT_ERR("%s: read drs failed(%d)", __func__, ret);
2413d0407baSopenharmony_ci        return ret;
2423d0407baSopenharmony_ci    }
2433d0407baSopenharmony_ci
2443d0407baSopenharmony_ci    for (i = 0; i < GPIO_MAXSIZE; i++) {
2453d0407baSopenharmony_ci        m_gpio_init_flag[i] = 0;
2463d0407baSopenharmony_ci    }
2473d0407baSopenharmony_ci
2483d0407baSopenharmony_ci    m_gpioInfo = (struct GpioInfo *)OsalMemAlloc(sizeof(struct GpioInfo));
2493d0407baSopenharmony_ci    if (m_gpioInfo == NULL) {
2503d0407baSopenharmony_ci        PRINT_ERR("m_gpioInfo OsalMemAlloc failed!\n");
2513d0407baSopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
2523d0407baSopenharmony_ci    }
2533d0407baSopenharmony_ci
2543d0407baSopenharmony_ci    memset_s(m_gpioInfo->name, GPIO_NAME_LEN, 0, GPIO_NAME_LEN - 1);
2553d0407baSopenharmony_ci    memcpy_s(m_gpioInfo->name, GPIO_NAME_LEN, RK2206_GPIO_NAME, strlen(RK2206_GPIO_NAME));
2563d0407baSopenharmony_ci
2573d0407baSopenharmony_ci    cntlr->start = 0;
2583d0407baSopenharmony_ci    cntlr->count = m_groupNum * m_bitNum;
2593d0407baSopenharmony_ci    cntlr->ops = &m_gpio_method;
2603d0407baSopenharmony_ci    cntlr->ginfos = &m_gpioInfo;
2613d0407baSopenharmony_ci    cntlr->priv = (void *)device->property;
2623d0407baSopenharmony_ci
2633d0407baSopenharmony_ci    ret = GpioCntlrAdd(cntlr);
2643d0407baSopenharmony_ci    if (ret != HDF_SUCCESS) {
2653d0407baSopenharmony_ci        PRINT_ERR("GpioCntlrAdd failed(%d)\n", ret);
2663d0407baSopenharmony_ci        return ret;
2673d0407baSopenharmony_ci    }
2683d0407baSopenharmony_ci
2693d0407baSopenharmony_ci    PRINT_LOG("gpio service: %s init success!\n", HdfDeviceGetServiceName(device));
2703d0407baSopenharmony_ci    return HDF_SUCCESS;
2713d0407baSopenharmony_ci}
2723d0407baSopenharmony_ci
2733d0407baSopenharmony_cistatic void iodrv_release(struct HdfDeviceObject *device)
2743d0407baSopenharmony_ci{
2753d0407baSopenharmony_ci    struct Gpiocntlr *cntlr;
2763d0407baSopenharmony_ci
2773d0407baSopenharmony_ci    if (device == NULL) {
2783d0407baSopenharmony_ci        PRINT_ERR("%s: device is null", __func__);
2793d0407baSopenharmony_ci        return;
2803d0407baSopenharmony_ci    }
2813d0407baSopenharmony_ci
2823d0407baSopenharmony_ci    cntlr = GpioCntlrFromHdfDev(device);
2833d0407baSopenharmony_ci    if (cntlr == NULL) {
2843d0407baSopenharmony_ci        PRINT_ERR("%s: no service binded!\n", __func__);
2853d0407baSopenharmony_ci        return;
2863d0407baSopenharmony_ci    }
2873d0407baSopenharmony_ci
2883d0407baSopenharmony_ci    GpioCntlrRemove(cntlr);
2893d0407baSopenharmony_ci    PRINT_LOG("gpio service: %s release!\n", HdfDeviceGetServiceName(device));
2903d0407baSopenharmony_ci}
2913d0407baSopenharmony_ci
2923d0407baSopenharmony_cistatic int32_t iodrv_bind(struct HdfDeviceObject *device)
2933d0407baSopenharmony_ci{
2943d0407baSopenharmony_ci    (void)device;
2953d0407baSopenharmony_ci    return HDF_SUCCESS;
2963d0407baSopenharmony_ci}
2973d0407baSopenharmony_ci
2983d0407baSopenharmony_cistruct HdfDriverEntry g_gpioDriverEntry = {
2993d0407baSopenharmony_ci    .moduleVersion = 1,
3003d0407baSopenharmony_ci    .moduleName = "HDF_PLATFORM_GPIO",
3013d0407baSopenharmony_ci    .Bind = iodrv_bind,
3023d0407baSopenharmony_ci    .Init = iodrv_init,
3033d0407baSopenharmony_ci    .Release = iodrv_release,
3043d0407baSopenharmony_ci};
3053d0407baSopenharmony_ci
3063d0407baSopenharmony_ciHDF_INIT(g_gpioDriverEntry);
307