diff --git a/Android.mk b/Android.mk index dfddf359fd..6b9a3fe586 100644 --- a/Android.mk +++ b/Android.mk @@ -24,15 +24,15 @@ KBUILD_OPTIONS += DSP_ROOT=$(DSP_BLD_DIR) KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) include $(DLKM_DIR)/Build_external_kernelmodule.mk -#include $(CLEAR_VARS) -#$(info DLKM_DIR = $(DLKM_DIR)) -#LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*) -#LOCAL_MODULE := cdsp-loader.ko -#LOCAL_MODULE_KBUILD_NAME := cdsp-loader.ko -#LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) -#KBUILD_OPTIONS += DSP_ROOT=$(DSP_BLD_DIR) -#KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) -#include $(DLKM_DIR)/Build_external_kernelmodule.mk +include $(CLEAR_VARS) +$(info DLKM_DIR = $(DLKM_DIR)) +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*) +LOCAL_MODULE := cdsp-loader.ko +LOCAL_MODULE_KBUILD_NAME := cdsp-loader.ko +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +KBUILD_OPTIONS += DSP_ROOT=$(DSP_BLD_DIR) +KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) +include $(DLKM_DIR)/Build_external_kernelmodule.mk # print out variables $(info KBUILD_OPTIONS = $(KBUILD_OPTIONS)) diff --git a/Kbuild b/Kbuild index 868bfd5ede..62fa146890 100644 --- a/Kbuild +++ b/Kbuild @@ -30,10 +30,9 @@ frpc_trusted-adsprpc-y := dsp/adsprpc.o \ dsp/adsprpc_compat.o \ dsp/adsprpc_socket.o \ -#cdsp-loader-y := dsp/cdsp-loader.o +cdsp-loader-y := dsp/cdsp-loader.o -#obj-m := frpc-adsprpc.o cdsp-loader.o -obj-m := frpc-adsprpc.o +obj-m := frpc-adsprpc.o cdsp-loader.o BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/frpc-adsprpc.ko #BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/cdsp-loader.ko diff --git a/dsp/cdsp-loader.c b/dsp/cdsp-loader.c new file mode 100644 index 0000000000..0caad0e2b2 --- /dev/null +++ b/dsp/cdsp-loader.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2014, 2017-2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOT_CMD 1 +#define IMAGE_UNLOAD_CMD 0 + +#define CDSP_SUBSYS_DOWN 0 +#define CDSP_SUBSYS_LOADED 1 + +static ssize_t cdsp_boot_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count); + +struct cdsp_loader_private { + void *pil_h; + struct kobject *boot_cdsp_obj; + struct attribute_group *attr_group; +}; + +static struct kobj_attribute cdsp_boot_attribute = + __ATTR(boot, 0220, NULL, cdsp_boot_store); + +static struct attribute *attrs[] = { + &cdsp_boot_attribute.attr, + NULL, +}; + +static u32 cdsp_state = CDSP_SUBSYS_DOWN; +static struct platform_device *cdsp_private; +static void cdsp_loader_unload(struct platform_device *pdev); + +static int cdsp_loader_do(struct platform_device *pdev) +{ + struct cdsp_loader_private *priv = NULL; + phandle rproc_phandle; + int rc = 0, sz = 0; + const char *img_name; + + if (!pdev) { + pr_err("%s: Platform device null\n", __func__); + goto fail; + } + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, + "%s: Device tree information missing\n", __func__); + goto fail; + } + + rc = of_property_read_string(pdev->dev.of_node, + "qcom,proc-img-to-load", + &img_name); + if (rc) + goto fail; + + if (!strcmp(img_name, "cdsp")) { + /* cdsp_state always returns "0".*/ + if (cdsp_state == CDSP_SUBSYS_DOWN) { + priv = platform_get_drvdata(pdev); + if (!priv) { + dev_err(&pdev->dev, + "%s: Private data get failed\n", __func__); + goto fail; + } + + sz = of_property_read_u32(pdev->dev.of_node, "qcom,rproc-handle", + &rproc_phandle); + if (sz) { + pr_err("%s: of_property_read failed, returned value %d\n", + __func__, sz); + dev_err(&pdev->dev, "error reading rproc phandle\n"); + goto fail; + } + + priv->pil_h = rproc_get_by_phandle(rproc_phandle); + if (!priv->pil_h) { + dev_err(&pdev->dev, "rproc not found\n"); + goto fail; + } + + dev_dbg(&pdev->dev, "%s: calling rproc_boot on %s\n", + __func__, img_name); + rc = rproc_boot(priv->pil_h); + if (rc) { + dev_err(&pdev->dev, "%s: rproc_boot failed with error %d\n", + __func__, rc); + goto fail; + } + + /* Set the state of the CDSP.*/ + cdsp_state = CDSP_SUBSYS_LOADED; + } else if (cdsp_state == CDSP_SUBSYS_LOADED) { + dev_dbg(&pdev->dev, + "%s: CDSP state = 0x%x\n", __func__, cdsp_state); + } + + dev_dbg(&pdev->dev, "%s: CDSP image is loaded\n", __func__); + return rc; + } + +fail: + if (pdev) + dev_err(&pdev->dev, + "%s: CDSP image loading failed\n", __func__); + return rc; +} + + +static ssize_t cdsp_boot_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int ret = 0; + uint32_t boot = 0; + + ret = kstrtou32(buf, 0, &boot); + if (ret) { + pr_debug("%s: invalid arguments for cdsp_loader.\n", __func__); + return ret; + } + + if (boot == BOOT_CMD) { + pr_debug("%s: going to call cdsp_loader_do\n", __func__); + cdsp_loader_do(cdsp_private); + } else if (boot == IMAGE_UNLOAD_CMD) { + pr_debug("%s: going to call cdsp_unloader\n", __func__); + cdsp_loader_unload(cdsp_private); + } + return count; +} + +static void cdsp_loader_unload(struct platform_device *pdev) +{ + struct cdsp_loader_private *priv = NULL; + + priv = platform_get_drvdata(pdev); + + if (!priv) + return; + + if (priv->pil_h) { + dev_dbg(&pdev->dev, "%s: calling subsystem_put\n", __func__); + rproc_shutdown(priv->pil_h); + priv->pil_h = NULL; + } +} + +static int cdsp_loader_init_sysfs(struct platform_device *pdev) +{ + int ret = -EINVAL; + struct cdsp_loader_private *priv = NULL; + + cdsp_private = NULL; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + return ret; + } + + platform_set_drvdata(pdev, priv); + + priv->pil_h = NULL; + priv->boot_cdsp_obj = NULL; + priv->attr_group = devm_kzalloc(&pdev->dev, + sizeof(*(priv->attr_group)), + GFP_KERNEL); + if (!priv->attr_group) { + ret = -ENOMEM; + goto error_return; + } + + priv->attr_group->attrs = attrs; + + priv->boot_cdsp_obj = kobject_create_and_add("boot_cdsp", kernel_kobj); + if (!priv->boot_cdsp_obj) { + dev_err(&pdev->dev, "%s: sysfs create and add failed\n", + __func__); + ret = -ENOMEM; + goto error_return; + } + + ret = sysfs_create_group(priv->boot_cdsp_obj, priv->attr_group); + if (ret) { + dev_err(&pdev->dev, "%s: sysfs create group failed %d\n", + __func__, ret); + goto error_return; + } + + cdsp_private = pdev; + + return 0; + +error_return: + + if (priv->boot_cdsp_obj) { + kobject_del(priv->boot_cdsp_obj); + priv->boot_cdsp_obj = NULL; + } + if (ret) + dev_err(&pdev->dev, "%s failed with ret %d\n", + __func__, ret); + return ret; +} + +static int cdsp_loader_remove(struct platform_device *pdev) +{ + struct cdsp_loader_private *priv = NULL; + + priv = platform_get_drvdata(pdev); + + if (!priv) + return 0; + + if (priv->pil_h) { + rproc_shutdown(priv->pil_h); + priv->pil_h = NULL; + } + + if (priv->boot_cdsp_obj) { + sysfs_remove_group(priv->boot_cdsp_obj, priv->attr_group); + kobject_del(priv->boot_cdsp_obj); + priv->boot_cdsp_obj = NULL; + } + + return 0; +} + +static int cdsp_loader_probe(struct platform_device *pdev) +{ + phandle rproc_phandle; + struct property *prop = NULL; + int size = 0; + struct rproc *cdsp = NULL; + int ret = 0; + + prop = of_find_property(pdev->dev.of_node, "qcom,rproc-handle", &size); + if (!prop) { + dev_err(&pdev->dev, "%s: error reading rproc phandle\n", __func__); + return -ENOPARAM; + } + + rproc_phandle = be32_to_cpup(prop->value); + cdsp = rproc_get_by_phandle(rproc_phandle); + if (!cdsp) { + dev_err(&pdev->dev, "%s: rproc not found\n", __func__); + return -EPROBE_DEFER; + } + + ret = cdsp_loader_init_sysfs(pdev); + + if (ret != 0) { + dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__); + return ret; + } + + return 0; +} + +static const struct of_device_id cdsp_loader_dt_match[] = { + { .compatible = "qcom,cdsp-loader" }, + { } +}; +MODULE_DEVICE_TABLE(of, cdsp_loader_dt_match); + +static struct platform_driver cdsp_loader_driver = { + .driver = { + .name = "cdsp-loader", + .of_match_table = cdsp_loader_dt_match, + }, + .probe = cdsp_loader_probe, + .remove = cdsp_loader_remove, +}; + +static int __init cdsp_loader_init(void) +{ + return platform_driver_register(&cdsp_loader_driver); +} +module_init(cdsp_loader_init); + +static void __exit cdsp_loader_exit(void) +{ + platform_driver_unregister(&cdsp_loader_driver); +} +module_exit(cdsp_loader_exit); + +MODULE_DESCRIPTION("CDSP Loader module"); +MODULE_LICENSE("GPL v2"); diff --git a/dsp_kernel_board.mk b/dsp_kernel_board.mk index d5d3dc0d14..6c0a48bf85 100644 --- a/dsp_kernel_board.mk +++ b/dsp_kernel_board.mk @@ -1,5 +1,5 @@ ifeq ($(call is-board-platform-in-list,$(TARGET_BOARD_PLATFORM)),true) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/frpc-adsprpc.ko #BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/frpc-trusted-adsprpc.ko -#BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/cdsp-loader.ko +BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/cdsp-loader.ko endif diff --git a/dsp_kernel_product.mk b/dsp_kernel_product.mk index 0f18b541d9..b7c2644e47 100644 --- a/dsp_kernel_product.mk +++ b/dsp_kernel_product.mk @@ -1,3 +1,3 @@ PRODUCT_PACKAGES += frpc-adsprpc.ko #PRODUCT_PACKAGES += frpc_trusted-adsprpc.ko -#PRODUCT_PACKAGES += cdsp-loader.ko +PRODUCT_PACKAGES += cdsp-loader.ko