diff --git a/drivers/Kconfig b/drivers/Kconfig index 0ecc5f535e..7f4cdacba3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -65,3 +65,4 @@ source "drivers/devicetree/Kconfig" source "drivers/reset/Kconfig" source "drivers/pci/Kconfig" source "drivers/coresight/Kconfig" +source "drivers/aie/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 42d632a42a..e7c19669ab 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -83,6 +83,7 @@ include usrsock/Make.defs include reset/Make.defs include pci/Make.defs include coresight/Make.defs +include aie/Make.defs ifeq ($(CONFIG_SPECIFIC_DRIVERS),y) -include platform/Make.defs diff --git a/drivers/aie/Kconfig b/drivers/aie/Kconfig new file mode 100644 index 0000000000..57a708b03d --- /dev/null +++ b/drivers/aie/Kconfig @@ -0,0 +1,10 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config AI_ENGINE + bool "AI Engine Acceleration Support" + default n + ---help--- + Drivers for various AI engine devices. diff --git a/drivers/aie/Make.defs b/drivers/aie/Make.defs new file mode 100644 index 0000000000..1e849b0de4 --- /dev/null +++ b/drivers/aie/Make.defs @@ -0,0 +1,31 @@ +############################################################################ +# drivers/aie/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you 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. +# +############################################################################ + +ifeq ($(CONFIG_AI_ENGINE),y) + +CSRCS += ai_engine.c + +# Include AI engine device driver build support + +DEPPATH += --dep-path aie +VPATH += :aie +CFLAGS += -I$(TOPDIR)$(DELIM)drivers$(DELIM)aie + +endif # CONFIG_AI_ENGINE diff --git a/drivers/aie/ai_engine.c b/drivers/aie/ai_engine.c new file mode 100644 index 0000000000..b098694165 --- /dev/null +++ b/drivers/aie/ai_engine.c @@ -0,0 +1,320 @@ +/**************************************************************************** + * drivers/aie/ai_engine.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +enum aie_state_e +{ + AIE_STATE_NOP = 0, + AIE_STATE_INITED, + AIE_STATE_FEEDED, + AIE_STATE_INFERENCED, +}; + +/* This structure describes the state of the upper half driver */ + +struct aie_upperhalf_s +{ + FAR struct aie_lowerhalf_s *lower; /* The handle of lower half driver */ + volatile enum aie_state_e state; /* The device state */ + mutex_t lock; /* Mutual exclusion */ + uint8_t crefs; /* The number of times the engine + * has been opend. */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int aie_open(FAR struct file *filep); + +static int aie_close(FAR struct file *filep); + +static int aie_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_aie_ops = +{ + aie_open, /* open */ + aie_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + aie_ioctl, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: aie_open + * + * Description: + * A open method to increase the crefs. + * + ****************************************************************************/ + +static int aie_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct aie_upperhalf_s *upper = inode->i_private; + int ret; + + DEBUGASSERT(upper != NULL); + ret = nxmutex_lock(&upper->lock); + if (ret < 0) + { + return ret; + } + + if (upper->crefs == 0) + { + upper->crefs++; + ret = OK; + } + else + { + ret = -EBUSY; + } + + nxmutex_unlock(&upper->lock); + + return ret; +} + +/**************************************************************************** + * Name: aie_close + * + * Description: + * A close method to decrease the crefs. + * + ****************************************************************************/ + +static int aie_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct aie_upperhalf_s *upper = inode->i_private; + FAR struct aie_lowerhalf_s *lower = NULL; + int ret; + + DEBUGASSERT(upper != NULL); + lower = upper->lower; + DEBUGASSERT(lower != NULL); + + ret = nxmutex_lock(&upper->lock); + if (ret < 0) + { + return ret; + } + + if (upper->crefs == 1) + { + ret = lower->ops->deinit(lower, filep); + if (ret == OK) + { + upper->state = AIE_STATE_NOP; + upper->crefs--; + } + } + else + { + ret = OK; + } + + nxmutex_unlock(&upper->lock); + + return ret; +} + +/**************************************************************************** + * Name: aie_ioctl + * + * Description: + * The standard ioctl method. + * This is where ALL of the aie work is done. + * + ****************************************************************************/ + +static int aie_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct aie_upperhalf_s *upper = inode->i_private; + FAR struct aie_lowerhalf_s *lower = NULL; + int ret; + + DEBUGASSERT(upper != NULL); + lower = upper->lower; + DEBUGASSERT(lower != NULL); + + _info("cmd: %d arg: %lu\n", cmd, arg); + + ret = nxmutex_lock(&upper->lock); + if (ret < 0) + { + return ret; + } + + switch (cmd) + { + case AIE_CMD_INIT: + ret = lower->ops->init(lower, filep, arg); + if (ret != OK) + { + break; + } + + if (lower->workspace_len) + { + lower->workspace = kmm_malloc(lower->workspace_len); + if (!lower->workspace) + { + ret = -ENOMEM; + break; + } + } + + upper->state = AIE_STATE_INITED; + break; + + case AIE_CMD_FEED_INPUT: + if (upper->state == AIE_STATE_INITED || + upper->state == AIE_STATE_INFERENCED) + { + lower->input = (uintptr_t)arg; + ret = lower->ops->feed_input(lower, filep); + if (ret == OK) + { + upper->state = AIE_STATE_FEEDED; + } + } + else + { + ret = -EPERM; + } + break; + + case AIE_CMD_GET_OUTPUT: + if (upper->state == AIE_STATE_FEEDED) + { + lower->output = (uintptr_t)arg; + ret = lower->ops->get_output(lower, filep); + if (ret == OK) + { + upper->state = AIE_STATE_INFERENCED; + } + } + else + { + ret = -EPERM; + } + break; + + default: + + /* Lowerhalf driver process other cmd. */ + + if (lower->ops->control) + { + ret = lower->ops->control(lower, filep, cmd, arg); + } + else + { + ret = -ENOSYS; + } + break; + } + + nxmutex_unlock(&upper->lock); + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: aie_register + * + * Description: + * Register a aie driver. + * + ****************************************************************************/ + +int aie_register(FAR const char *path, + FAR struct aie_lowerhalf_s *lower) +{ + FAR struct aie_upperhalf_s *upper = NULL; + int ret = -ENOMEM; + + DEBUGASSERT(path); + + /* Allocate the upper-half data structure */ + + upper = (FAR struct aie_upperhalf_s *) + kmm_malloc(sizeof(struct aie_upperhalf_s)); + if (!upper) + { + _err("Upper half allocation failed\n"); + goto errout; + } + + /* Initialize the aie device structure */ + + upper->lower = lower; + upper->state = AIE_STATE_NOP; + upper->crefs = 0; + lower->priv = upper; + + nxmutex_init(&upper->lock); + + /* Register the aie device */ + + ret = register_driver(path, &g_aie_ops, 0666, upper); + if (ret < 0) + { + _err("register aie driver failed: %d\n", ret); + nxmutex_destroy(&upper->lock); + kmm_free(upper); + } + +errout: + return ret; +} diff --git a/include/nuttx/aie/ai_engine.h b/include/nuttx/aie/ai_engine.h new file mode 100644 index 0000000000..1dfd40577a --- /dev/null +++ b/include/nuttx/aie/ai_engine.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * include/nuttx/aie/ai_engine.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __INCLUDE_NUTTX_AIE_AI_ENGINE_H +#define __INCLUDE_NUTTX_AIE_AI_ENGINE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This enumeration type indicates work of aie_ioctl. */ + +enum aie_cmd_e +{ + AIE_CMD_INIT = 0, + AIE_CMD_FEED_INPUT, + AIE_CMD_GET_OUTPUT +}; + +/* This structure provides the "lower-half" driver operations available to + * the "upper-half" driver. + */ + +struct aie_lowerhalf_s; +struct aie_ops_s +{ + /* Common routes */ + + CODE int (*init)(FAR struct aie_lowerhalf_s *lower, + FAR struct file *filep, + uintptr_t bin_model); + + CODE int (*feed_input)(FAR struct aie_lowerhalf_s *lower, + FAR struct file *filep); + + CODE int (*get_output)(FAR struct aie_lowerhalf_s *lower, + FAR struct file *filep); + + CODE int (*deinit)(FAR struct aie_lowerhalf_s *lower, + FAR struct file *filep); + + /* Custom route */ + + CODE int (*control)(FAR struct aie_lowerhalf_s *lower, + FAR struct file *filep, + int cmd, unsigned long arg); +}; + +/* This structure provides the publicly visible representation of the + * "lower-half" driver state structure. "lower half" drivers will have an + * internal structure definition that will be cast-compatible with this + * structure definitions. + */ + +struct aie_lowerhalf_s +{ + /* The private opaque pointer to be passed to upper-layer */ + + FAR void *priv; + FAR const struct aie_ops_s *ops; /* Lower half operations */ + const void *bin_model; /* The model address */ + const void *input; /* The input buffer */ + void *output; /* The output buffer */ + void *workspace; /* Workspace free to use */ + size_t workspace_len; /* Length of workspace. + * >0: need the workspace + * 0: no need */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ai_engine_register + * + * Description: + * Register all ai engine related drivers. + * + ****************************************************************************/ + +int aie_register(FAR const char *path, + FAR struct aie_lowerhalf_s *lower); + +#endif /* __INCLUDE_NUTTX_AIE_AI_ENGINE_H */