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