diff --git a/bsp/README.md b/bsp/README.md index d78584f143d..77e1e93eb0a 100644 --- a/bsp/README.md +++ b/bsp/README.md @@ -760,9 +760,9 @@ This document is based on the RT-Thread mainline repository and categorizes the #### 🟢 K230 (RT-Smart) -| BSP Name | GPIO | UART | I2C | RTC | ADC | PWM | SDIO | HWTimer | WDT | SPI | -|----------|------|------|-----|-----|-----|-----|------|---------|-----|-----| -| [k230](k230) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| BSP Name | GPIO | UART | I2C | RTC | ADC | PWM | SDIO | HWTimer | WDT | SPI | GNNE | +|----------|------|------|-----|-----|-----|-----|------|---------|-----|-----|------| +| [k230](k230) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | #### 🟢 Xuantie (RT-Smart) diff --git a/bsp/k230/.ci/attachconfig/ci.attachconfig.yml b/bsp/k230/.ci/attachconfig/ci.attachconfig.yml index e579d18af98..1903f7d7762 100644 --- a/bsp/k230/.ci/attachconfig/ci.attachconfig.yml +++ b/bsp/k230/.ci/attachconfig/ci.attachconfig.yml @@ -1,6 +1,10 @@ scons.args: &scons scons_arg: - '--strict' +devices.gnee: + <<: *scons + kconfig: + - CONFIG_BSP_USING_GNNE=y devices.spi: <<: *scons kconfig: diff --git a/bsp/k230/.config b/bsp/k230/.config index e4c479c1e6a..63a6f5c1d3b 100644 --- a/bsp/k230/.config +++ b/bsp/k230/.config @@ -1624,6 +1624,7 @@ CONFIG_PKG_ZLIB_VER="latest" # # Drivers Configuration # +# CONFIG_BSP_USING_GNNE is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_RTC is not set diff --git a/bsp/k230/board/Kconfig b/bsp/k230/board/Kconfig index bae60bb9902..6a479ef8846 100644 --- a/bsp/k230/board/Kconfig +++ b/bsp/k230/board/Kconfig @@ -1,4 +1,8 @@ menu "Drivers Configuration" + + config BSP_USING_GNNE + bool "Enable KPU and AI2D" + default n menuconfig BSP_USING_SPI bool "Enable SPI" diff --git a/bsp/k230/drivers/interdrv/gnne/SConscript b/bsp/k230/drivers/interdrv/gnne/SConscript new file mode 100644 index 00000000000..4cca7123719 --- /dev/null +++ b/bsp/k230/drivers/interdrv/gnne/SConscript @@ -0,0 +1,19 @@ +# RT-Thread building script for gnne component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Gnne', src, depend = ['BSP_USING_GNNE'], CPPPATH = CPPPATH) + +objs = [group] + +list = os.listdir(cwd) + +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + objs = objs + SConscript(os.path.join(item, 'SConscript')) + +Return('objs') diff --git a/bsp/k230/drivers/interdrv/gnne/ai2d_dev.c b/bsp/k230/drivers/interdrv/gnne/ai2d_dev.c new file mode 100644 index 00000000000..fbf922c7d6b --- /dev/null +++ b/bsp/k230/drivers/interdrv/gnne/ai2d_dev.c @@ -0,0 +1,227 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "drv_hardlock.h" +#include "board.h" + +#if defined(RT_USING_POSIX_DEVIO) + #include + #include + #include +#endif + +#define AI2D_CMD_LOCK 0 +#define AI2D_CMD_TRYLOCK 1 +#define AI2D_CMD_UNLOCK 2 +static hardlock_type g_ai2d_lock = HARDLOCK_MAX; + +struct ai_2d_dev_handle +{ + rt_wqueue_t *wait; + rt_bool_t is_lock; +}; + + +#define ai_2d_log(s...) rt_kprintf(s) + +#define ai_2d_err(s...) do { \ + ai_2d_log("[%s:%d] ", __func__, __LINE__); \ + ai_2d_log(s); \ + ai_2d_log("\r\n"); \ +} while (0) + +static struct rt_device g_ai_2d_device = {0}; +static struct rt_event g_ai_2d_event = {0}; +extern void *gnne_base_addr; + +static int ai_2d_device_open(struct dfs_file *file) +{ + struct ai_2d_dev_handle *handle; + rt_device_t device; + + handle = rt_malloc(sizeof(struct ai_2d_dev_handle)); + if (handle == RT_NULL) + { + ai_2d_err("malloc failed\n"); + return -1; + } + device = (rt_device_t)file->vnode->data; + handle->wait = &device->wait_queue; + handle->is_lock = RT_FALSE; + file->data = (void *)handle; + return RT_EOK; +} + +static int ai_2d_device_close(struct dfs_file *file) +{ + struct ai_2d_dev_handle *handle; + + handle = (struct ai_2d_dev_handle *)file->data; + if (handle == RT_NULL) + { + ai_2d_err("try to close a invalid handle"); + return -RT_EINVAL; + } + if (handle->is_lock) + { + kd_hardlock_unlock(g_ai2d_lock); + } + rt_free(handle); + file->data = RT_NULL; + return RT_EOK; +} + +static int ai_2d_device_ioctl(struct dfs_file *file, int cmd, void *args) +{ + struct ai_2d_dev_handle *handle; + int ret = -1; + + handle = (struct ai_2d_dev_handle *)file->data; + if (g_ai2d_lock == HARDLOCK_MAX) + return ret; + + if (cmd == AI2D_CMD_LOCK) + { + if (handle->is_lock == RT_TRUE) + { + return 0; + } + while (kd_hardlock_lock(g_ai2d_lock)); + handle->is_lock = RT_TRUE; + ret = 0; + } + else if (cmd == AI2D_CMD_UNLOCK) + { + if (handle->is_lock == RT_FALSE) + { + return 0; + } + kd_hardlock_unlock(g_ai2d_lock); + handle->is_lock = RT_FALSE; + ret = 0; + } + else if (cmd == AI2D_CMD_TRYLOCK) + { + if (handle->is_lock == RT_TRUE) + { + return 0; + } + if (!kd_hardlock_lock(g_ai2d_lock)) + { + handle->is_lock = RT_TRUE; + ret = 0; + } + } + return ret; +} + +int ai_2d_device_poll(struct dfs_file *file, struct rt_pollreq *req) +{ + struct ai_2d_dev_handle *handle; + unsigned int flags; + handle = (struct ai_2d_dev_handle *)file->data; + if (!handle) + { + ai_2d_err("ai_2d_dev_handle NULL!"); + return -EINVAL; + } + rt_event_recv(&g_ai_2d_event, 0x01, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, NULL); + rt_poll_add(handle->wait, req); + return POLLIN; +} + +static const struct dfs_file_ops ai_2d_input_fops = +{ + .open = ai_2d_device_open, + .close = ai_2d_device_close, + .ioctl = ai_2d_device_ioctl, + .poll = ai_2d_device_poll, +}; + +static void irq_callback(int irq, void *data) +{ + rt_wqueue_t *wait = (rt_wqueue_t *)data; + volatile rt_uint32_t *write_addr = (rt_uint32_t *)((char *)gnne_base_addr + 0xca0); + if (gnne_base_addr == RT_NULL) + { + ai_2d_err("ai2d interrupts while the hardware is not yet initialized\n"); + } + write_addr[0] = 1; + write_addr[1] = 0; + write_addr[2] = 0; + write_addr[3] = 0; + rt_wqueue_wakeup(wait, (void *)POLLIN); + rt_event_send(&g_ai_2d_event, 0x1); +} + +int ai_2d_device_init(void) +{ + int ret = 0; + rt_isr_handler_t old_handler; + rt_device_t ai_2d_device = &g_ai_2d_device; + + ret = rt_event_init(&g_ai_2d_event, "ai_2d_event", RT_IPC_FLAG_PRIO); + if (ret) + { + ai_2d_err("event init failed\n"); + return -ENOMEM; + } + + ret = rt_device_register(ai_2d_device, "ai_2d_device", RT_DEVICE_FLAG_RDWR); + if (ret) + { + ai_2d_err("ai_2d_device register fail\n"); + return ret; + } + + rt_wqueue_init(&ai_2d_device->wait_queue); + old_handler = rt_hw_interrupt_install(K230_IRQ_AI_2D, irq_callback, &ai_2d_device->wait_queue, "ai_2d_irq"); + if (old_handler == RT_NULL) + { + ai_2d_err("ai_2d_device interrupt install fail\n"); + return -RT_ERROR; + } + rt_hw_interrupt_umask(K230_IRQ_AI_2D); + + ai_2d_device->fops = &ai_2d_input_fops; + + if (kd_request_lock(HARDLOCK_AI2D)) + { + ai_2d_err("fail to request hardlock-%d\n", HARDLOCK_AI2D); + } + else + { + g_ai2d_lock = HARDLOCK_AI2D; + } + return RT_EOK; +} diff --git a/bsp/k230/drivers/interdrv/gnne/ai_module.c b/bsp/k230/drivers/interdrv/gnne/ai_module.c new file mode 100644 index 00000000000..b9d5592aabc --- /dev/null +++ b/bsp/k230/drivers/interdrv/gnne/ai_module.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NOTE: Currently untested - nncase cannot run due to missing mmz library. + * The mmz library depends on MPP driver, which relies on deprecated RT-Thread + * kernel APIs (rt_proc_entry_create, rt_dma_chan_request, etc.) that are no + * longer available in the mainline kernel. Awaiting resolution. + */ + +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +extern int gnne_device_init(void); +extern int ai_2d_device_init(void); + +int ai_module_init(void) +{ + gnne_device_init(); + ai_2d_device_init(); +} +INIT_COMPONENT_EXPORT(ai_module_init); diff --git a/bsp/k230/drivers/interdrv/gnne/gnne_dev.c b/bsp/k230/drivers/interdrv/gnne/gnne_dev.c new file mode 100644 index 00000000000..df1934dbc09 --- /dev/null +++ b/bsp/k230/drivers/interdrv/gnne/gnne_dev.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "io.h" +#include +#include "board.h" +#include "drv_hardlock.h" + +#if defined(RT_USING_POSIX_DEVIO) + #include + #include + #include +#endif + +struct gnne_dev_handle +{ + rt_wqueue_t *wait; + rt_bool_t is_lock; +}; + +#define gnne_log(s...) rt_kprintf(s) + +#define gnne_err(s...) do { \ + gnne_log("[%s:%d] ", __func__, __LINE__); \ + gnne_log(s); \ + gnne_log("\r\n"); \ +} while (0) + +#define GNNE_CMD_LOCK 0 +#define GNNE_CMD_TRYLOCK 1 +#define GNNE_CMD_UNLOCK 2 + +static struct rt_device g_gnne_device = {0}; +static struct rt_event g_gnne_event = {0}; +void *gnne_base_addr = RT_NULL; +static hardlock_type g_kpu_lock = HARDLOCK_MAX; + +static int gnne_device_open(struct dfs_file *file) +{ + struct gnne_dev_handle *handle; + rt_device_t device; + + handle = rt_malloc(sizeof(struct gnne_dev_handle)); + if (handle == RT_NULL) + { + gnne_err("malloc failed\n"); + return -1; + } + device = (rt_device_t)file->vnode->data; + handle->wait = &device->wait_queue; + handle->is_lock = RT_FALSE; + file->data = (void *)handle; + return RT_EOK; +} + +static int gnne_device_close(struct dfs_file *file) +{ + struct gnne_dev_handle *handle; + + handle = (struct gnne_dev_handle *)file->data; + if (handle == RT_NULL) + { + gnne_err("try to close a invalid handle"); + return -RT_EINVAL; + } + if (handle->is_lock) + { + kd_hardlock_unlock(g_kpu_lock); + } + rt_free(handle); + file->data = RT_NULL; + return RT_EOK; +} + +static int gnne_device_ioctl(struct dfs_file *file, int cmd, void *args) +{ + struct gnne_dev_handle *handle; + int ret = -1; + handle = (struct gnne_dev_handle *)file->data; + if ((g_kpu_lock == HARDLOCK_MAX)) + { + return ret; + } + if (cmd == GNNE_CMD_LOCK) + { + if (handle->is_lock == RT_TRUE) + { + return 0; + } + while (kd_hardlock_lock(g_kpu_lock)); + handle->is_lock = RT_TRUE; + ret = 0; + } + else if (cmd == GNNE_CMD_UNLOCK) + { + if (handle->is_lock == RT_FALSE) + { + return 0; + } + kd_hardlock_unlock(g_kpu_lock); + handle->is_lock = RT_FALSE; + ret = 0; + } + else if (cmd == GNNE_CMD_TRYLOCK) + { + if (handle->is_lock == RT_TRUE) + { + return 0; + } + if (!kd_hardlock_lock(g_kpu_lock)) + { + handle->is_lock = RT_TRUE; + ret = 0; + } + } + return ret; +} + +int gnne_device_poll(struct dfs_file *file, struct rt_pollreq *req) +{ + struct gnne_dev_handle *handle; + unsigned int flags; + handle = (struct gnne_dev_handle *)file->data; + if (!handle) + { + gnne_err("gnne_dev_handle NULL!"); + return -EINVAL; + } + rt_event_recv(&g_gnne_event, 0x01, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, NULL); + rt_poll_add(handle->wait, req); + return POLLIN; +} + +static const struct dfs_file_ops gnne_input_fops = +{ + .open = gnne_device_open, + .close = gnne_device_close, + .ioctl = gnne_device_ioctl, + .poll = gnne_device_poll, +}; + +static void irq_callback(int irq, void *data) +{ + rt_wqueue_t *wait = (rt_wqueue_t *)data; + volatile void *write_addr = (void *)((char *)gnne_base_addr + 0x128); + if (gnne_base_addr == RT_NULL) + { + gnne_err("gnne interrupts while the hardware is not yet initialized\n"); + } + /*clear kpu intr*/ + __iowmb(); + *(rt_uint64_t *)write_addr = 0x400000004; + rt_wqueue_wakeup(wait, (void *)POLLIN); + rt_event_send(&g_gnne_event, 0x1); +} + +int gnne_device_init(void) +{ + int ret = 0; + rt_isr_handler_t old_handler; + rt_device_t gnne_device = &g_gnne_device; + + ret = rt_event_init(&g_gnne_event, "gnne_event", RT_IPC_FLAG_PRIO); + if (ret) + { + gnne_err("event init failed\n"); + return -ENOMEM; + } + + ret = rt_device_register(gnne_device, "gnne_device", RT_DEVICE_FLAG_RDWR); + if (ret) + { + gnne_err("gnne_device register fail\n"); + return ret; + } + + + /*rt_ioremap maps the size of at least one page*/ + gnne_base_addr = rt_ioremap((void *)KPU_BASE_ADDR, (KPU_IO_SIZE + FFT_IO_SIZE + AI2D_IO_SIZE)); + if (gnne_base_addr == RT_NULL) + { + gnne_err("gnne ioremap error\n"); + return -1; + } + + rt_wqueue_init(&gnne_device->wait_queue); + old_handler = rt_hw_interrupt_install(K230_IRQ_GNNE, irq_callback, &gnne_device->wait_queue, "gnne_irq"); + if (old_handler == RT_NULL) + { + gnne_err("gnne_device interrupt install fail\n"); + return -RT_ERROR; + } + rt_hw_interrupt_umask(K230_IRQ_GNNE); + + gnne_device->fops = &gnne_input_fops; + + if (kd_request_lock(HARDLOCK_KPU)) + { + gnne_err("fail to request hardlock-%d\n", HARDLOCK_KPU); + } + else + { + g_kpu_lock = HARDLOCK_KPU; + } + + return RT_EOK; +} diff --git a/bsp/k230/drivers/interdrv/hardlock/drv_hardlock.h b/bsp/k230/drivers/interdrv/hardlock/drv_hardlock.h index d62f6d8f798..74fd0c5e5ea 100644 --- a/bsp/k230/drivers/interdrv/hardlock/drv_hardlock.h +++ b/bsp/k230/drivers/interdrv/hardlock/drv_hardlock.h @@ -39,6 +39,7 @@ typedef enum k230_hardlock_type HARDLOCK_AES = 7, HARDLOCK_SM4 = 8, HARDLOCK_PDMA = 9, + HARDLOCK_AI2D = 10, HARDLOCK_MAX = 128 } hardlock_type;