From f1dbcf3bf9868e2667f834e7491d89dd933bde5d Mon Sep 17 00:00:00 2001 From: donghuawei Date: Fri, 24 May 2024 13:59:55 +0800 Subject: [PATCH 032/222] refactor:khandle, dsp subsys drv Changelogs: adaptor khandle, dsp subsys drv for linux-6.6 --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/eswin/Kconfig | 20 ++ drivers/soc/eswin/Makefile | 4 + drivers/soc/eswin/dsp_subsys.c | 348 +++++++++++++++++++++++++++ drivers/soc/eswin/eswin-dsp-subsys.h | 44 ++++ drivers/soc/eswin/eswin-khandle.c | 242 +++++++++++++++++++ drivers/soc/eswin/eswin-khandle.h | 84 +++++++ drivers/soc/eswin/eswin_timer.h | 6 + 9 files changed, 750 insertions(+) create mode 100644 drivers/soc/eswin/Kconfig create mode 100644 drivers/soc/eswin/Makefile create mode 100644 drivers/soc/eswin/dsp_subsys.c create mode 100644 drivers/soc/eswin/eswin-dsp-subsys.h create mode 100644 drivers/soc/eswin/eswin-khandle.c create mode 100644 drivers/soc/eswin/eswin-khandle.h create mode 100644 drivers/soc/eswin/eswin_timer.h diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index d21e75d69294..bc857765a996 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig" source "drivers/soc/rockchip/Kconfig" source "drivers/soc/samsung/Kconfig" source "drivers/soc/sifive/Kconfig" +source "drivers/soc/eswin/Kconfig" source "drivers/soc/starfive/Kconfig" source "drivers/soc/sunxi/Kconfig" source "drivers/soc/tegra/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 0706a27d13be..5dbaca5b7bac 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -29,6 +29,7 @@ obj-y += renesas/ obj-y += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ obj-y += sifive/ +obj-y += eswin/ obj-y += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ diff --git a/drivers/soc/eswin/Kconfig b/drivers/soc/eswin/Kconfig new file mode 100644 index 000000000000..54179b920cc8 --- /dev/null +++ b/drivers/soc/eswin/Kconfig @@ -0,0 +1,20 @@ +if SOC_SIFIVE || SOC_STARFIVE + +config ESWIN_KHANDLE + bool "eswin kernel khandle functions" + default y + help + eswin realize this khandle, and mainly use for user process resource + mangement. + +config ESWIN_DSP_SUBSYS + tristate "Eswin dsp subsys" + default y + help + This is hardware-specific DSP subsys kernel driver for the eswin + hardware. It should be enabled to support dsp on eswin + platform. + + If unsure, say N. + +endif diff --git a/drivers/soc/eswin/Makefile b/drivers/soc/eswin/Makefile new file mode 100644 index 000000000000..290bd185817f --- /dev/null +++ b/drivers/soc/eswin/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_ESWIN_KHANDLE) += eswin-khandle.o +obj-$(CONFIG_ESWIN_DSP_SUBSYS) += dsp_subsys.o + + diff --git a/drivers/soc/eswin/dsp_subsys.c b/drivers/soc/eswin/dsp_subsys.c new file mode 100644 index 000000000000..acf33631926a --- /dev/null +++ b/drivers/soc/eswin/dsp_subsys.c @@ -0,0 +1,348 @@ +/* + * Program's name, and a brief idea of what it does(One line). + * Copyright 20XX, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved. + * SPDX-License-Identifier: GPL-2.0-only + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "eswin-dsp-subsys.h" + +#define DRIVER_NAME "eswin-dsp-subsys" + +/** + * dsp_subsys_status - query the dsp subsys transaction status + * + * @void + * + * return: module transaction status on success , 1 if idle, 0 if busy. + * negative for error + * if can't get idle status in 3 seconds, return current status. + */ +static int dsp_subsys_status(void) +{ + unsigned long deadline = jiffies + 3 * HZ; + int status = 0; + + do { + status = win2030_noc_sideband_mgr_query(SBM_DSPT_SNOC); + status |= win2030_noc_sideband_mgr_query(SBM_CNOC_DSPT); + if (0 != status) { + break; + } + schedule(); + } while (time_before(jiffies, deadline)); + + return status; +} + +static inline int dsp_subsys_clk_init(struct platform_device *pdev, + struct es_dsp_subsys *subsys) +{ + int ret; + + subsys->cfg_clk = devm_clk_get(&pdev->dev, "cfg_clk"); + if (IS_ERR(subsys->cfg_clk)) { + ret = PTR_ERR(subsys->cfg_clk); + dev_err(&pdev->dev, "failed to get cfg_clk: %d\n", ret); + return ret; + } + return 0; +} + +static int dsp_subsys_reset(struct es_dsp_subsys *subsys) +{ + int ret; + + /*reset dsp bus*/ + ret = reset_control_reset(subsys->rstc_axi); + WARN_ON(0 != ret); + + ret = reset_control_reset(subsys->rstc_div4); + WARN_ON(0 != ret); + + /*reset dsp cfg*/ + ret = reset_control_reset(subsys->rstc_cfg); + WARN_ON(0 != ret); + + /*reset dsp core clk div*/ + ret = reset_control_reset(subsys->rstc_div_0); + WARN_ON(0 != ret); + + ret = reset_control_reset(subsys->rstc_div_1); + WARN_ON(0 != ret); + + ret = reset_control_reset(subsys->rstc_div_2); + WARN_ON(0 != ret); + + ret = reset_control_reset(subsys->rstc_div_3); + WARN_ON(0 != ret); + + return 0; +} + +static int dsp_subsys_clk_enable(struct es_dsp_subsys *subsys) +{ + int ret; + + ret = clk_prepare_enable(subsys->cfg_clk); + if (ret) { + dev_err(&subsys->pdev->dev, "failed to enable cfg_clk: %d\n", ret); + return ret; + } + return 0; +} + +static int dsp_subsys_reset_init(struct platform_device *pdev, + struct es_dsp_subsys *subsys) +{ + subsys->rstc_axi = devm_reset_control_get_optional(&pdev->dev, "axi"); + if (IS_ERR_OR_NULL(subsys->rstc_axi)) { + dev_err(&subsys->pdev->dev, "Failed to get axi reset handle\n"); + return -EFAULT; + } + + subsys->rstc_div4 = devm_reset_control_get_optional(&pdev->dev, "div4"); + if (IS_ERR_OR_NULL(subsys->rstc_div4)) { + dev_err(&subsys->pdev->dev, "Failed to div4 reset handle\n"); + return -EFAULT; + } + + subsys->rstc_cfg = devm_reset_control_get_optional(&pdev->dev, "cfg"); + if (IS_ERR_OR_NULL(subsys->rstc_cfg)) { + dev_err(&subsys->pdev->dev, "Failed to get cfg reset handle\n"); + return -EFAULT; + } + + subsys->rstc_div_0 = devm_reset_control_get_optional(&pdev->dev, "div_0"); + if (IS_ERR_OR_NULL(subsys->rstc_div_0)) { + dev_err(&subsys->pdev->dev, "Failed to div_0 reset handle\n"); + return -EFAULT; + } + subsys->rstc_div_1 = devm_reset_control_get_optional(&pdev->dev, "div_1"); + if (IS_ERR_OR_NULL(subsys->rstc_div_1)) { + dev_err(&subsys->pdev->dev, "Failed to div_1 reset handle\n"); + return -EFAULT; + } + subsys->rstc_div_2 = devm_reset_control_get_optional(&pdev->dev, "div_2"); + if (IS_ERR_OR_NULL(subsys->rstc_div_2)) { + dev_err(&subsys->pdev->dev, "Failed to div_2 reset handle\n"); + return -EFAULT; + } + subsys->rstc_div_3 = devm_reset_control_get_optional(&pdev->dev, "div_3"); + if (IS_ERR_OR_NULL(subsys->rstc_div_3)) { + dev_err(&subsys->pdev->dev, "Failed to div_3 reset handle\n"); + return -EFAULT; + } + return 0; +} + +static int dsp_subsys_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct es_dsp_subsys *subsys = context; + + *val = readl_relaxed(subsys->reg_base + reg); + return 0; +} + +static int dsp_subsys_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct es_dsp_subsys *subsys = context; + + writel_relaxed(val, subsys->reg_base + reg); + return 0; +} + +static int dsp_subsys_con_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct es_dsp_subsys *subsys = context; + + *val = readl_relaxed(subsys->con_reg_base + reg); + return 0; +} + +static int dsp_subsys_con_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct es_dsp_subsys *subsys = context; + + writel_relaxed(val, subsys->con_reg_base + reg); + return 0; +} + +/** + * dsp_subsys_init_regmap() - Initialize registers map + * + * Autodetects needed register access mode and creates the regmap with + * corresponding read/write callbacks. This must be called before doing any + * other register access. + */ +static int dsp_subsys_init_regmap(struct es_dsp_subsys *subsys) +{ + struct regmap_config map_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .use_hwlock = true, + .cache_type = REGCACHE_NONE, + .can_sleep = false, + .reg_read = dsp_subsys_reg_read, + .reg_write = dsp_subsys_reg_write, + }; + struct regmap_config con_map_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .use_hwlock = true, + .cache_type = REGCACHE_NONE, + .can_sleep = false, + .reg_read = dsp_subsys_con_reg_read, + .reg_write = dsp_subsys_con_reg_write, + }; + + /* + * Note we'll check the return value of the regmap IO accessors only + * at the probe stage. The rest of the code won't do this because + * basically we have MMIO-based regmap so non of the read/write methods + * can fail. + */ + subsys->map = devm_regmap_init(&subsys->pdev->dev, NULL, subsys, &map_cfg); + if (IS_ERR(subsys->map)) { + dev_err(&subsys->pdev->dev, "Failed to init the registers map\n"); + return PTR_ERR(subsys->map); + } + + subsys->con_map = devm_regmap_init(&subsys->pdev->dev, NULL, subsys, &con_map_cfg); + if (IS_ERR(subsys->con_map)) { + dev_err(&subsys->pdev->dev, "Failed to init the con registers map\n"); + return PTR_ERR(subsys->con_map); + } + + return 0; +} + +static int es_dsp_subsys_probe(struct platform_device *pdev) +{ + struct es_dsp_subsys *subsys; + int ret; + struct resource *res; + + dev_info(&pdev->dev, "%s\n", __func__); + subsys = devm_kzalloc(&pdev->dev, sizeof(*subsys), GFP_KERNEL); + if (!subsys) { + return -ENOMEM; + } + + dev_set_drvdata(&pdev->dev, subsys); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + subsys->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR_OR_NULL(subsys->reg_base)) { + return PTR_ERR(subsys->reg_base); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) + return -ENODEV; + + subsys->con_reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR_OR_NULL(subsys->con_reg_base)) { + return PTR_ERR(subsys->con_reg_base); + } + + subsys->pdev = pdev; + + ret = dsp_subsys_init_regmap(subsys); + if (0 != ret) { + return -ENODEV; + } + + ret = dsp_subsys_reset_init(pdev, subsys); + if (0 != ret) { + return ret; + } + + ret = dsp_subsys_clk_init(pdev, subsys); + if (0 != ret) { + return ret; + } + + ret = dsp_subsys_clk_enable(subsys); + if (0 != ret) { + return ret; + } + + ret = dsp_subsys_reset(subsys); + if (0 != ret) { + return ret; + } + + subsys->dsp_subsys_status = dsp_subsys_status; + + /* enable qos */ + // win2030_noc_qos_set("DSPT"); + + return 0; +} + +static int es_dsp_subsys_remove(struct platform_device *pdev) +{ + struct es_dsp_subsys *subsys = dev_get_drvdata(&pdev->dev); + if (subsys) { + clk_disable_unprepare(subsys->cfg_clk); + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id es_dsp_subsys_match[] = { + { + .compatible = "es-dsp-subsys", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, es_dsp_subsys_match); +#endif + +static struct platform_driver es_dsp_subsys_driver = { + .probe = es_dsp_subsys_probe, + .remove = es_dsp_subsys_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = of_match_ptr(es_dsp_subsys_match), + }, +}; + +module_platform_driver(es_dsp_subsys_driver); + +MODULE_AUTHOR("Eswin"); +MODULE_DESCRIPTION("DSP: Low Level Device Driver For Eswin DSP"); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/soc/eswin/eswin-dsp-subsys.h b/drivers/soc/eswin/eswin-dsp-subsys.h new file mode 100644 index 000000000000..4933411fde94 --- /dev/null +++ b/drivers/soc/eswin/eswin-dsp-subsys.h @@ -0,0 +1,44 @@ +/* + * Program's name, and a brief idea of what it does(One line). + * Copyright 20XX, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved. + * SPDX-License-Identifier: GPL-2.0-only + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ESWIN_DSP_SUBSYS_H__ +#define __ESWIN_DSP_SUBSYS_H__ +#include +#include +#include + +typedef int (*dsp_subsys_status_pfunc)(void); + +struct es_dsp_subsys { + void __iomem *reg_base; + void __iomem *con_reg_base; + struct regmap *map; + struct regmap *con_map; + struct platform_device *pdev; + + struct reset_control *rstc_axi; + struct reset_control *rstc_cfg; + struct reset_control *rstc_div4; + struct reset_control *rstc_div_0; + struct reset_control *rstc_div_1; + struct reset_control *rstc_div_2; + struct reset_control *rstc_div_3; + struct clk *cfg_clk; + dsp_subsys_status_pfunc dsp_subsys_status; +}; +#endif \ No newline at end of file diff --git a/drivers/soc/eswin/eswin-khandle.c b/drivers/soc/eswin/eswin-khandle.c new file mode 100644 index 000000000000..055615a17b7a --- /dev/null +++ b/drivers/soc/eswin/eswin-khandle.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "eswin-khandle.h" +#include +#include +#include + +struct fd_pool_desc { + spinlock_t lock; + struct xarray fd_array; +}; + +static void init_fd_pool(void *fd_pool) +{ + struct fd_pool_desc *pool = (struct fd_pool_desc *)fd_pool; + pr_debug("%s, %d, pool=0x%px", __func__, __LINE__, pool); + xa_init_flags(&pool->fd_array, XA_FLAGS_ALLOC); + spin_lock_init(&pool->lock); +} + +static int alloc_fd(void *fd_pool, struct khandle *h) +{ + struct fd_pool_desc *pool = (struct fd_pool_desc *)fd_pool; + int ret; + u32 fd; + + pr_debug("%s, %d, pool=0x%px", __func__, __LINE__, pool); + ret = xa_alloc(&pool->fd_array, &fd, h, xa_limit_32b, GFP_ATOMIC); + if (ret < 0) { + pr_err("%s, %d, ret=%d.\n", __func__, __LINE__, ret); + return ret; + } + pr_debug("%s, %d, pool=0x%px, fd=%d.\n", __func__, __LINE__, pool, fd); + return fd; +} + +static void release_fd(void *fd_pool, int fd) +{ + unsigned long flags; + struct khandle *h; + struct fd_pool_desc *pool = (struct fd_pool_desc *)fd_pool; + + pr_debug("%s, %d, pool=0x%px, fd=%d.\n", __func__, __LINE__, pool, fd); + + spin_lock_irqsave(&pool->lock, flags); + h = xa_load(&pool->fd_array, fd); + if (!h) { + spin_unlock_irqrestore(&pool->lock, flags); + return; + } + xa_erase(&pool->fd_array, fd); + spin_unlock_irqrestore(&pool->lock, flags); +} + +static struct khandle *find_khandle_by_fd(void *fd_pool, int fd) +{ + unsigned long flags; + struct khandle *h; + struct fd_pool_desc *pool = (struct fd_pool_desc *)fd_pool; + + spin_lock_irqsave(&pool->lock, flags); + h = xa_load(&pool->fd_array, fd); + if (h == NULL) { + spin_unlock_irqrestore(&pool->lock, flags); + return NULL; + } + kref_get(&h->refcount); + spin_unlock_irqrestore(&pool->lock, flags); + return h; +} + +static void kref_khandle_fn(struct kref *kref) +{ + unsigned long flags; + struct khandle *h = container_of(kref, struct khandle, refcount); + struct khandle *parent; + struct fd_pool_desc *pool; + + pr_debug("%s, h address=0x%px.\n", __func__, h); + BUG_ON(h == NULL); + BUG_ON(h->fd != INVALID_HANDLE_VALUE); + + pr_debug("%s, k->fd=%d, refcount=%d.\n", __func__, h->fd, + kref_read(kref)); + + parent = h->parent; + + if (parent == NULL) { + pool = h->fd_pool; + xa_destroy(&pool->fd_array); + vfree(h->fd_pool); + } else { + spin_lock_irqsave(&parent->lock, flags); + list_del_init(&h->entry); + spin_unlock_irqrestore(&parent->lock, flags); + } + + if (h->fn != NULL) { + h->fn(h); + } + + if (parent != NULL) { + kref_put(&parent->refcount, kref_khandle_fn); + } +} + +void kernel_handle_addref(struct khandle *h) +{ + BUG_ON(h == NULL); + + kref_get(&h->refcount); + pr_debug("%s, h addr=0x%px, fd=%d, refcount=%d.\n", __func__, h, h->fd, + kref_read(&h->refcount)); +} +EXPORT_SYMBOL(kernel_handle_addref); + +void kernel_handle_decref(struct khandle *h) +{ + BUG_ON(h == NULL); + + kref_put(&h->refcount, kref_khandle_fn); + pr_debug("%s, done.\n", __func__); +} +EXPORT_SYMBOL(kernel_handle_decref); + +static struct list_head *capture_next_khandle_node(struct list_head *head, + struct list_head *cur) +{ + struct khandle *h; + + while (true) { + cur = cur->next; + if (cur == head) { + return cur; + } + + /* Protect child not released until return of kernel_handle_release_family. */ + h = container_of(cur, struct khandle, entry); + if (kref_get_unless_zero(&h->refcount) != 0) { + return cur; + } + } +} + +void kernel_handle_release_family(struct khandle *h) +{ + unsigned long flags; + struct list_head *child; + struct khandle *child_khandle; + + BUG_ON(h == NULL); + spin_lock_irqsave(&h->lock, flags); + if (h->fd == INVALID_HANDLE_VALUE) { + spin_unlock_irqrestore(&h->lock, flags); + return; + } + + release_fd(h->fd_pool, h->fd); + h->fd = INVALID_HANDLE_VALUE; + child = capture_next_khandle_node(&h->head, &h->head); + while (child != &h->head) { + child_khandle = container_of(child, struct khandle, entry); + child = capture_next_khandle_node(&h->head, child); + spin_unlock_irqrestore(&h->lock, flags); + kernel_handle_release_family(child_khandle); + kernel_handle_decref(child_khandle); + spin_lock_irqsave(&h->lock, flags); + } + + spin_unlock_irqrestore(&h->lock, flags); + kref_put(&h->refcount, kref_khandle_fn); + pr_debug("%s, done.\n", __func__); +} +EXPORT_SYMBOL(kernel_handle_release_family); + +int init_kernel_handle(struct khandle *h, release_khandle_fn fn, int magic, + struct khandle *parent) +{ + unsigned long flags; + void *fd_pool; + + BUG_ON(h == NULL); + kref_init(&h->refcount); + kref_get(&h->refcount); + + if ((h->parent = parent) == NULL) { + fd_pool = vmalloc(sizeof(struct fd_pool_desc)); + init_fd_pool(fd_pool); + if (fd_pool == NULL) { + return -ENOMEM; + } + } else { + fd_pool = parent->fd_pool; + } + h->fd_pool = fd_pool; + + if ((h->fd = alloc_fd(fd_pool, h)) == INVALID_HANDLE_VALUE) { + BUG_ON(parent == NULL); + return -EINVAL; + } + + pr_debug("%s, hfile addr=%u.\n", __func__, h->fd); + h->fn = fn; + h->magic = magic; + spin_lock_init(&h->lock); + + INIT_LIST_HEAD(&h->head); + INIT_LIST_HEAD(&h->entry); + + if (parent != NULL) { + spin_lock_irqsave(&parent->lock, flags); + if (parent->fd == INVALID_HANDLE_VALUE) { + spin_unlock_irqrestore(&parent->lock, flags); + release_fd(fd_pool, h->fd); + return -EINVAL; + } + + list_add_tail(&h->entry, &parent->head); + kref_get(&parent->refcount); + spin_unlock_irqrestore(&parent->lock, flags); + } + + return 0; +} +EXPORT_SYMBOL(init_kernel_handle); + +struct khandle *find_kernel_handle(struct khandle *ancestor, int fd, int magic) +{ + struct khandle *h; + + h = find_khandle_by_fd(ancestor->fd_pool, fd); + if (h == NULL) { + return NULL; + } + + if (h->magic != magic) { + kref_put(&h->refcount, kref_khandle_fn); + return NULL; + } + return h; +} +EXPORT_SYMBOL(find_kernel_handle); diff --git a/drivers/soc/eswin/eswin-khandle.h b/drivers/soc/eswin/eswin-khandle.h new file mode 100644 index 000000000000..7e086388890a --- /dev/null +++ b/drivers/soc/eswin/eswin-khandle.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ESWIN_KHANDLE_H_ +#define __ESWIN_KHANDLE_H_ + +#include +#include +#include +#include + +#define INVALID_HANDLE_VALUE (-1) + +struct khandle; +typedef void (*release_khandle_fn)(struct khandle *h); +struct khandle { + int fd; + int magic; + spinlock_t lock; + release_khandle_fn fn; + struct kref refcount; + struct list_head entry; + struct list_head head; + struct khandle *parent; + void *fd_pool; +}; + +/** + * @brief Remove the family relations hierachy. This function also actively + * free the fd of this kernel object and its descendants. + * + * @param o: This is the kernel object. + */ +void kernel_handle_release_family(struct khandle *o); + +/** + * @brief Decrease the reference of kernel object `o`. If reference reaches 0, + * the release delegation function is called. + * + * @param o: This is the kernel object. + */ +void kernel_handle_decref(struct khandle *o); + + +/** + * @brief Increase the reference of kernel object `o`. + * + * @param o: This is the kernel object. + */ +void kernel_handle_addref(struct khandle *o); + + +/** + * @brief This function intialize an kernel object in the memory specified by + * `o`. It returns zero on success or a Linux error code. Note this function + * should only be called in IOCtl context. The initial reference is set to 1. + * + * @param o: This specifies an memory for holding kernel object. + * @param fn: This points to a callback delegation function. When the + * reference of `o` reaches 0, this callback function is called. It + * is intended for releasing resources associated with this kernel + * object. + * @param magic: This is a magic number for determining the type of kernel + * object. + * @param parent: Points to the parent of this kernel object. + * @return It returns zero on success or a Linux error code. + * + * when use khandle, host structure release must use kernel_handle_decref function. + */ +int init_kernel_handle(struct khandle *o, release_khandle_fn fn, int magic, + struct khandle *parent); + + +/** + * @brief This function is used to find the kernel object associated with fd. + * Note the khandle object has one additional reference so user should dereference + * it if not needed. + * + * @param ancestor: This is one ancestor of kernel object that matches fd. + * @param fd: This is the fd associated with a specific kernel object. + * @param magic: This is the magic associated with a specific kernel object. + * @return It returns the kernel object on success or NULL if the given fd + * is invalid. + */ +struct khandle *find_kernel_handle(struct khandle *ancestor, int fd, int magic); +#endif diff --git a/drivers/soc/eswin/eswin_timer.h b/drivers/soc/eswin/eswin_timer.h new file mode 100644 index 000000000000..a7fac84ac613 --- /dev/null +++ b/drivers/soc/eswin/eswin_timer.h @@ -0,0 +1,6 @@ +#ifndef __ESWIN_TIMER_H_ +#define __ESWIN_TIMER_H_ + +extern u32 get_perf_timer_cnt(void); + +#endif -- 2.47.0