linux-gbmc: aspeed-g7: edaf: device driver for moving data Add a device driver to move the blob to the given reserved memory. Tested: ```` // device nodes for dual nodes created successfully. :~# ls -la /dev/edaf-map* crw------- 1 root root 248, 0 Jul 10 23:14 /dev/edaf-map0 crw------- 1 root root 247, 0 Jul 10 23:14 /dev/edaf-map1 ``` Google-Bug-Id: 401416725 Change-Id: I8fd15c3c027dee540049855e6907a9cd734a80a6 Signed-off-by: wukaihua <eason.kh.wu@fii-na.corp-partner.google.com>
diff --git a/recipes-kernel/linux/files/0030-data-transfer-to-reserved-memory-for-edaf.patch b/recipes-kernel/linux/files/0030-data-transfer-to-reserved-memory-for-edaf.patch new file mode 100644 index 0000000..2ccbfe8 --- /dev/null +++ b/recipes-kernel/linux/files/0030-data-transfer-to-reserved-memory-for-edaf.patch
@@ -0,0 +1,324 @@ +From 1182b60689cd5034c9ee3fd150e968bd36f4972c Mon Sep 17 00:00:00 2001 +From: wukaihua <eason.kh.wu@fii-na.corp-partner.google.com> +Date: Fri, 11 Jul 2025 12:45:14 +0800 +Subject: [PATCH] data transfer to reserved memory for edaf + +Signed-off-by: wukaihua <eason.kh.wu@fii-na.corp-partner.google.com> +--- + drivers/misc/Kconfig | 8 + + drivers/misc/Makefile | 1 + + drivers/misc/ast2700-fii-edaf-map.c | 274 ++++++++++++++++++++++++++++ + 3 files changed, 283 insertions(+) + create mode 100644 drivers/misc/ast2700-fii-edaf-map.c + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 36ddfdbb5..c68d205b7 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -562,6 +562,14 @@ config TPS6594_PFSM + This driver can also be built as a module. If so, the module + will be called tps6594-pfsm. + ++config AST2700_FII_EDAF_MAP ++ tristate "FXN EDAF MAP on AST2700" ++ select REGMAP ++ select MFD_SYSCON ++ default ARCH_ASPEED ++ help ++ Transfer data from/to reserved memory ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/gbmc/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index c817fa6a9..c10994a67 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -68,3 +68,4 @@ obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o + obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o + obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o + obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o ++obj-$(CONFIG_AST2700_FII_EDAF_MAP) += ast2700-fii-edaf-map.o +diff --git a/drivers/misc/ast2700-fii-edaf-map.c b/drivers/misc/ast2700-fii-edaf-map.c +new file mode 100644 +index 000000000..f8c131f28 +--- /dev/null ++++ b/drivers/misc/ast2700-fii-edaf-map.c +@@ -0,0 +1,274 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/regmap.h> ++#include <linux/sizes.h> ++#include <linux/module.h> ++#include <linux/io.h> ++#include <linux/cdev.h> ++#include <linux/string.h> ++#include <linux/fs.h> ++#include <linux/err.h> ++#include <linux/types.h> ++#include <linux/semaphore.h> ++ ++#define DEVICE_NAME "edaf-map" ++#define READ_SIZE 4096 ++ ++static DEFINE_IDA(fii_edaf_mapping_ida); ++static struct semaphore sem; ++ ++struct edaf_blob_ioctl { ++ u64 offset; ++ u64 trans_bytes; ++ u8 buf[READ_SIZE]; ++}; ++ ++#define MAP_TO_MEM _IOW(0xb2, 0, struct edaf_blob_ioctl) ++#define MAP_TO_DEV _IOR(0xb2, 1, struct edaf_blob_ioctl) ++ ++static dev_t edaf_devno; ++static struct class *edaf_class; ++struct edaf_chardev { ++ struct device parent_dev; ++ struct device *chdev; ++ int (*cntlwrfn)(struct edaf_blob_ioctl *blob_ioctl, struct device *dev); ++ int (*cntlrdfn)(struct edaf_blob_ioctl *blob_ioctl, struct device *dev); ++ struct cdev edafcdev; ++}; ++ ++struct edaf_map { ++ u8 node; ++ char *devname; ++ volatile void *mem_addr; ++ struct resource res; ++}; ++ ++static int edaf_chdev_open(struct inode *inode, struct file *filp) { ++ struct edaf_chardev *edaf_cdev; ++ ++ edaf_cdev = container_of(inode->i_cdev, struct edaf_chardev, edafcdev); ++ filp->private_data = edaf_cdev; ++ return 0; ++} ++ ++static int edaf_chdev_close(struct inode *inode, struct file *filp) { ++ filp->private_data = NULL; ++ return 0; ++} ++ ++int wrfn(struct edaf_blob_ioctl *blob_ioctl, struct device *dev) { ++ struct platform_device *pdev; ++ struct edaf_map *edaf; ++ ++ pdev = container_of(dev, struct platform_device, dev); ++ edaf = (struct edaf_map *) platform_get_drvdata(pdev); ++ ++ edaf->mem_addr = memremap(edaf->res.start, ++ edaf->res.end - edaf->res.start + 1, MEMREMAP_WT); ++ if (!edaf->mem_addr) { ++ dev_err(dev, "Error returned from memremap()\n"); ++ return -ENOMEM; ++ } ++ memcpy(edaf->mem_addr + blob_ioctl->offset, blob_ioctl->buf, blob_ioctl->trans_bytes); ++ wmb(); ++ memunmap(edaf->mem_addr); ++ return 0; ++} ++ ++int rdfn(struct edaf_blob_ioctl *blob_ioctl, struct device *dev) { ++ struct platform_device *pdev; ++ struct edaf_map *edaf; ++ ++ pdev = container_of(dev, struct platform_device, dev); ++ edaf = (struct edaf_map *) platform_get_drvdata(pdev); ++ ++ edaf->mem_addr = memremap(edaf->res.start, ++ edaf->res.end - edaf->res.start + 1, MEMREMAP_WT); ++ if (!edaf->mem_addr) { ++ dev_err(dev, "Error returned from memremap()\n"); ++ return -ENOMEM; ++ } ++ ++ rmb(); ++ memcpy(blob_ioctl->buf, edaf->mem_addr + blob_ioctl->offset, READ_SIZE); ++ memunmap(edaf->mem_addr); ++ blob_ioctl->offset += READ_SIZE; ++ blob_ioctl->trans_bytes = READ_SIZE; ++ return 0; ++} ++ ++static long mem_mapping_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { ++ struct edaf_blob_ioctl blob_ioctl; ++ struct edaf_chardev *edaf_cdev; ++ long rc = 0; ++ ++ down(&sem); ++ edaf_cdev = filp->private_data; ++ switch (cmd) { ++ case MAP_TO_MEM: ++ if (copy_from_user(&blob_ioctl, (struct edaf_blob_ioctl *) arg, ++ sizeof(struct edaf_blob_ioctl)) != 0) { ++ pr_err("edaf %s(): error occurs when receiving info\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ edaf_cdev->cntlwrfn(&blob_ioctl, &edaf_cdev->parent_dev); ++ break; ++ case MAP_TO_DEV: ++ if (copy_from_user(&blob_ioctl, (struct edaf_blob_ioctl *) arg, ++ sizeof(struct edaf_blob_ioctl)) != 0) { ++ pr_err("edaf %s(): error occurs when receiving info\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ edaf_cdev->cntlrdfn(&blob_ioctl, &edaf_cdev->parent_dev); ++ if (copy_to_user((struct edaf_blob_ioctl *) arg, &blob_ioctl, ++ sizeof(struct edaf_blob_ioctl)) != 0) { ++ pr_err("edaf %s(): error occurs when data returns\n", __func__); ++ rc = -EFAULT; ++ } ++ break; ++ default: ++ pr_err("edaf %s(): unsupport command\n", __func__); ++ rc = -EINVAL; ++ break; ++ } ++ ++ up(&sem); ++ return rc; ++} ++ ++static const struct file_operations edaf_map_fops = { ++ .owner = THIS_MODULE, ++ .open = edaf_chdev_open, ++ .release = edaf_chdev_close, ++ .unlocked_ioctl = mem_mapping_ioctl, ++}; ++ ++static int init_dev_node(char *devname) { ++ int rc = 0; ++ ++ rc = alloc_chrdev_region(&edaf_devno, 0, 1, devname); ++ if (rc < 0) { ++ pr_err("%s(): err %d when alloc chrdev region\n", __func__, rc); ++ return rc; ++ } ++ edaf_class = class_create(devname); ++ if (edaf_class == NULL) { ++ pr_err("%s(): err when creating chrdev device\n", __func__); ++ goto unreg_chrdev; ++ } ++ return rc; ++ ++unreg_chrdev: ++ unregister_chrdev_region(edaf_devno, 1); ++ return rc; ++} ++ ++int setup_edaf_chardev(struct edaf_chardev *edaf_cdev, char *devname) { ++ struct device *chdev; ++ int rc; ++ ++ chdev = device_create(edaf_class, &edaf_cdev->parent_dev, ++ edaf_devno, NULL, devname); ++ if (chdev == NULL) { ++ pr_err("Error when creating a char device and registers it with sysfs\n"); ++ return -EIO; ++ } ++ edaf_cdev->chdev = chdev; ++ edaf_cdev->cntlwrfn = wrfn; ++ edaf_cdev->cntlrdfn = rdfn; ++ ++ cdev_init(&edaf_cdev->edafcdev, &edaf_map_fops); ++ rc = cdev_add(&edaf_cdev->edafcdev, edaf_devno, 1); ++ if (rc) { ++ pr_err("Error when adding char device: %d\n", rc); ++ device_destroy(edaf_class, edaf_devno); ++ } ++ ++ return rc; ++} ++ ++static int fii_edaf_map_probe(struct platform_device *pdev) { ++ int rc = 0; ++ struct device *dev; ++ struct device_node *np; ++ struct edaf_chardev *edaf_cdev; ++ struct edaf_map *edaf; ++ ++ dev = &pdev->dev; ++ edaf = devm_kzalloc(dev, sizeof(struct edaf_map), GFP_KERNEL); ++ if (!edaf) { ++ dev_err(dev, "No memory address assgined\n"); ++ return -ENOMEM; ++ } ++ ++ np = of_parse_phandle(dev->of_node, "memory-region", 0); ++ if (!np) { ++ dev_err(dev, "No %s specified\n", "memory-region"); ++ return -ENODEV; ++ } ++ rc = of_address_to_resource(np, 0, &edaf->res); ++ if (rc) { ++ dev_err(dev, "No memory address assigned to the region\n"); ++ return -EINVAL; ++ } ++ ++ edaf->node = ida_alloc(&fii_edaf_mapping_ida, GFP_KERNEL); ++ edaf->devname = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, edaf->node); ++ dev_info(dev, "devname: %s\n", edaf->devname); ++ platform_set_drvdata(pdev, edaf); ++ ++ sema_init(&sem, 1); ++ ++ rc = init_dev_node(edaf->devname); ++ if (rc) { ++ return rc; ++ } ++ ++ edaf_cdev = devm_kzalloc(dev, sizeof(struct edaf_chardev), GFP_KERNEL); ++ if (edaf_cdev == NULL) { ++ dev_err(dev, "%s(): No space for allocating the structure\n", __func__); ++ return -ENOMEM; ++ } ++ edaf_cdev->parent_dev = *dev; ++ rc = setup_edaf_chardev(edaf_cdev, edaf->devname); ++ return rc; ++} ++ ++static int fii_edaf_map_remove(struct platform_device *pdev) { ++ int rc = 0; ++ struct edaf_map *edaf; ++ struct edaf_chardev *edaf_cdev; ++ ++ edaf_cdev = container_of(&pdev->dev, struct edaf_chardev, parent_dev); ++ cdev_del(&edaf_cdev->edafcdev); ++ device_destroy(edaf_class, edaf_devno); ++ class_destroy(edaf_class); ++ unregister_chrdev_region(edaf_devno, 1); ++ ++ edaf = platform_get_drvdata(pdev); ++ platform_set_drvdata(pdev, NULL); ++ ++ return rc; ++} ++ ++static const struct of_device_id fii_edaf_map_of_matches[] = { ++ { .compatible = "edaf-map" }, ++}; ++MODULE_DEVICE_TABLE(of, fii_edaf_map_of_matches); ++ ++static struct platform_driver fii_edaf_map_driver = { ++ .driver = { ++ .name = "fii-edaf-map", ++ .of_match_table = fii_edaf_map_of_matches, ++ }, ++ .probe = fii_edaf_map_probe, ++ .remove = fii_edaf_map_remove, ++}; ++module_platform_driver(fii_edaf_map_driver); ++ ++MODULE_AUTHOR("Wu, Kai-Hua <eason.kh.wu@fii-foxconn.com>"); ++MODULE_DESCRIPTION("AST2700 FII ESPI EDAF MAPPING"); ++MODULE_LICENSE("GPL"); +-- +2.34.1 +
diff --git a/recipes-kernel/linux/files/aspeed-g7-gbmc.cfg b/recipes-kernel/linux/files/aspeed-g7-gbmc.cfg index c34791c..fab63bd 100644 --- a/recipes-kernel/linux/files/aspeed-g7-gbmc.cfg +++ b/recipes-kernel/linux/files/aspeed-g7-gbmc.cfg
@@ -330,5 +330,6 @@ # CONFIG_SCHED_DEBUG is not set CONFIG_DEBUG_LIST=y CONFIG_FUNCTION_TRACER=y +CONFIG_AST2700_FII_EDAF_MAP=y # CONFIG_STRICT_DEVMEM is not set # CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/recipes-kernel/linux/linux-gbmc_aspeedg7.bb b/recipes-kernel/linux/linux-gbmc_aspeedg7.bb index 6b1f827..97b5039 100644 --- a/recipes-kernel/linux/linux-gbmc_aspeedg7.bb +++ b/recipes-kernel/linux/linux-gbmc_aspeedg7.bb
@@ -77,6 +77,7 @@ # Server3.0 ast2750 customized patches SRC_URI:append:aspeed-g7 = " \ file://0027-Add-setting-SGPIO-default-value.patch \ + file://0030-data-transfer-to-reserved-memory-for-edaf.patch \ " KCONFIG_MODE="--allnoconfig"