diff --git a/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt b/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt index 00f4c4402ece3c26509df27870684ca6361b3c40..3b05c33c331f983facf9667f1f87b37e55fc2903 100644 --- a/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt +++ b/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt @@ -7,13 +7,15 @@ Homogeneous RemoteProc Device Node: ================================= A homo_remoteproc device node is used to represent the remote core instance within SoC. +The parent node defines up to two child nodes, each representing a remote processor. + Required properties: -------------------- - - compatible : should be "homo,rproc" + - compatible : the parent node should be "homo,rproc", and the child node can be "homo,rproc-core" - remote-processor: remote processor's linux cpu logical number - - inter-processor-interrupt: IPI/SGI interrupt number, default is 9 + - inter-processor-interrupt: IPI/SGI interrupt number - memory-region: reserved memory which will be used by remote processor - - firmware-name: the name of openamp image, default is "openamp_core0.elf" + - firmware-name: the name of openamp image Example: -------- @@ -22,18 +24,32 @@ Example: #address-cells = <0x2>; #size-cells = <0x2>; ranges; - - rproc: rproc@b0100000 { + rproc0: rproc0@b0100000 { no-map; reg = <0x0 0xb0100000 0x0 0x19900000>; }; + rproc1: rpro1c@d0100000 { + no-map; + reg = <0x0 0xd0100000 0x0 0x19900000>; + }; }; homo_rproc: homo_rproc@0 { compatible = "homo,rproc"; - remote-processor = <3>; - inter-processor-interrupt = <9>; - memory-region = <&rproc>; - firmware-name = "openamp_core0.elf"; status = "disabled"; + homo_core0: homo_core0@b0100000 { + compatible = "homo,rproc-core"; + remote-processor = <3>; + inter-processor-interrupt = <9>; + memory-region = <&rproc0>; + firmware-name = "openamp_core0.elf"; + }; + homo_core1: homo_core1@d0100000 { + compatible = "homo,rproc-core"; + remote-processor = <2>; + inter-processor-interrupt = <10>; + memory-region = <&rproc1>; + firmware-name = "openamp_core1.elf"; + }; }; + diff --git a/arch/arm64/configs/amd-dc.config b/arch/arm64/configs/amd-dc.config deleted file mode 100644 index bb4551c3f78fcc95ce96ae15d5e78fdaac1dfebc..0000000000000000000000000000000000000000 --- a/arch/arm64/configs/amd-dc.config +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_DRM_RADEON=m -CONFIG_DRM_AMDGPU=m -CONFIG_DRM_AMDGPU_SI=y -CONFIG_DRM_AMDGPU_CIK=y -CONFIG_DRM_AMDGPU_USERPTR=y -CONFIG_DRM_AMDGPU_GART_DEBUGFS=y - - diff --git a/arch/arm64/configs/cobalt.config b/arch/arm64/configs/cobalt.config index c83491c6dfa92c1cdbeff67aa4ad571b6fb36242..fcb3e88e49a62c12d0b0355cbeae51b5d4921c25 100644 --- a/arch/arm64/configs/cobalt.config +++ b/arch/arm64/configs/cobalt.config @@ -1,4 +1,4 @@ -CONFIG_LOCALVERSION="-dovetail2-phytium-embeded" +CONFIG_LOCALVERSION="-dovetail2-phytium-embeded-v3.1" CONFIG_RCU_EXPERT=y CONFIG_RCU_NOCB_CPU=y # CONFIG_CPU_IDLE is not set diff --git a/arch/arm64/configs/phytium_defconfig b/arch/arm64/configs/phytium_defconfig index 3cb88a2efebd3cb0f9acdd509031b7135b6247f5..9797228499f2b8dae92611888c23047280eebb36 100644 --- a/arch/arm64/configs/phytium_defconfig +++ b/arch/arm64/configs/phytium_defconfig @@ -1,4 +1,4 @@ -CONFIG_LOCALVERSION="-phytium-embedded-v3.0" +CONFIG_LOCALVERSION="-phytium-embedded-v3.1" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -546,6 +546,12 @@ CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_HDLCD=m CONFIG_DRM_MALI_DISPLAY=m CONFIG_DRM_KOMEDA=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_RADEON_USERPTR=y +CONFIG_DRM_AMDGPU=m +CONFIG_DRM_AMDGPU_SI=y +CONFIG_DRM_AMDGPU_CIK=y +CONFIG_HSA_AMD=y CONFIG_DRM_NOUVEAU=m CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m CONFIG_DRM_PANEL_LVDS=m diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index 2f75ee1d2aeeda89b7ec4c044547299fff9af18f..fc96b44d92cfa0d5d225db2e39f9245c4ecb0de8 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -371,10 +372,8 @@ static const struct of_device_id phytium_pcie_ep_of_match[] = { static int phytium_pcie_ep_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *match = NULL; struct phytium_pcie_ep *priv = NULL; - const struct phytium_pcie_ep_config *pcie_ep_config = - &pcie_ep_2p0_config; + const struct phytium_pcie_ep_config *pcie_ep_config = NULL; struct resource *res; struct device_node *np = dev->of_node; struct pci_epc *epc; @@ -384,10 +383,10 @@ static int phytium_pcie_ep_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - match = of_match_node(phytium_pcie_ep_of_match, pdev->dev.of_node); - if (match && match->data) { - pcie_ep_config = match->data; - } + pcie_ep_config = of_device_get_match_data(&pdev->dev); + if (!pcie_ep_config) + return -ENODEV; + priv->hpb_perf_base_limit_offs = pcie_ep_config->hpb_perf_base_limit_offs; diff --git a/drivers/remoteproc/homo_remoteproc.c b/drivers/remoteproc/homo_remoteproc.c index ea03bfae81bda8f4c3df1842c387f3ab202e7e32..24d0edb2a04f2a51d3731d5d11a6f3e82f0c6733 100644 --- a/drivers/remoteproc/homo_remoteproc.c +++ b/drivers/remoteproc/homo_remoteproc.c @@ -1,8 +1,7 @@ /* * Homogeneous Remote Processor Control Driver * - * Copyright (c) 2022-2024 Phytium Technology Co., Ltd. - * Author: Shaojun Yang + * Copyright (c) 2022-2025 Phytium Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify it under the terms * of the GNU General Public License version 2 as published by the Free Software Foundation. @@ -18,22 +17,60 @@ #include #include #include +#include +#include +#include +#include #include "remoteproc_internal.h" #define RPROC_RESOURCE_ENTRIES 8 -#define PSCI_VERSION 0x84000000 -#define CPU_SUSPEND 0xc4000001 -#define CPU_OFF 0x84000002 +/* Support up to two cores */ +#define RPROC_CORE_MAX_NUM 2 + +/* cpu0 handling interrupt */ +#define RPROC_IRQ_HANDLE_CPU 0 + +/* PSCI cpu_on code */ #define CPU_ON 0xc4000003 -#define AFFINITY_INFO 0xc4000004 -#define MIGRATE 0xc4000005 + +/* stop flag use in resource table */ +#define REMOTE_PROC_STOP 0x0001U + +/* wait for 1s */ +#define HOMO_MAX_WAIT_TIME_NS (1000 * NSEC_PER_MSEC) + +/* offset of the carveout relative to the starting address of the memory region */ +#define HOMO_IMGLOAD_OFFSET 0 +#define HOMO_VDEV_VIRING0_OFFSET 0x10200000 +#define HOMO_VDEV_VIRING1_OFFSET 0x10210000 +#define HOMO_VDEV_BUFFER_OFFSET 0x10220000 + +/* size of each carveout */ +#define HOMO_IMGLOAD_SIZE 0x10200000 +#define HOMO_VDEV_VIRING0_SIZE 0x00008000 +#define HOMO_VDEV_VIRING1_SIZE 0x00008000 +#define HOMO_VDEV_BUFFER_SIZE 0x00080000 + +#define HOMO_ADD_CARVEOUT(dev, base, size, name_fmt) \ + do { \ + struct rproc_mem_entry *mem = rproc_mem_entry_init( \ + dev, NULL, (dma_addr_t)(base), (size), (base), \ + homo_mem_alloc, homo_mem_release, \ + name_fmt); \ + if (!mem) { \ + dev_err(dev, "rproc_mem_entry_init err!\n"); \ + return -ENOMEM; \ + } \ + rproc_add_carveout(rproc, mem); \ + } while (0) /* Resource table for the homo remote processors */ struct homo_resource_table { unsigned int version; unsigned int num; + /* use bit0 of reserved[0] as stop flag */ unsigned int reserved[2]; unsigned int offset[RPROC_RESOURCE_ENTRIES]; @@ -55,14 +92,38 @@ struct homo_rproc { int irq; int cpu; + struct work_struct vq_work; + int mapped_irq; }; -static int homo_rproc_irq; -static struct homo_rproc *g_priv; -static struct work_struct workqueue; +static struct homo_rproc *g_homo_rproc[RPROC_CORE_MAX_NUM]; +static int homo_rproc_num; #define MPIDR_TO_SGI_AFFINITY(cluster_id, level) (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) +static int homo_find_rproc_offset_irq(int rproc_irq) +{ + int i; + + for (i = 0; i < homo_rproc_num; i++) { + if (g_homo_rproc[i]->mapped_irq == rproc_irq) { + return i; + } + } + + return -1; +} + +static bool homo_rproc_wait_cpuoff(struct rproc *rproc, ktime_t stop) +{ + int err = 0; + struct homo_rproc *priv = rproc->priv; + + err = psci_ops.affinity_info(cpu_logical_map(priv->cpu), 0); + + return (err == 1) || ktime_after(ktime_get(), stop); +} + void gicv3_ipi_send_single(int irq, u64 mpidr) { u16 tlist = 0; @@ -86,9 +147,23 @@ void gicv3_ipi_send_single(int irq, u64 mpidr) isb(); } -static void homo_rproc_vq_irq(struct work_struct *work) +static void homo_rproc_write_stop_flag(struct homo_resource_table *table_ptr) +{ + unsigned int *flag = table_ptr->reserved; + + *flag |= REMOTE_PROC_STOP; +} + +static void homo_rproc_clear_stop_flag(struct homo_resource_table *table_ptr) +{ + unsigned int *flag = table_ptr->reserved; + + *flag &= ~REMOTE_PROC_STOP; +} + +static void homo_rproc_vq_irq(struct work_struct *vq_work) { - struct homo_rproc *priv = g_priv; + struct homo_rproc *priv = container_of(vq_work, struct homo_rproc, vq_work); struct homo_resource_table *rsc = priv->rsc; struct rproc *rproc = priv->rproc; @@ -106,12 +181,12 @@ static int homo_rproc_start(struct rproc *rproc) if (err == 0) remove_cpu(priv->cpu); - INIT_WORK(&workqueue, homo_rproc_vq_irq); + INIT_WORK(&priv->vq_work, homo_rproc_vq_irq); priv->rsc = (struct homo_resource_table *)rproc->table_ptr; /* ARMv8 requires to clean D-cache and invalidate I-cache for memory containing new instructions. */ - flush_icache_range((unsigned long)priv->addr, (unsigned long)(priv->addr + priv->size)); + flush_icache_range((unsigned long)priv->addr, (unsigned long)(priv->addr + HOMO_IMGLOAD_SIZE)); arm_smccc_smc(CPU_ON, phys_cpuid, (unsigned long long)priv->phys_addr, 0, 0, 0, 0, 0, &smc_res); @@ -120,12 +195,30 @@ static int homo_rproc_start(struct rproc *rproc) static int homo_rproc_stop(struct rproc *rproc) { - int err; struct homo_rproc *priv = rproc->priv; + ktime_t stop; - err = psci_ops.affinity_info(cpu_logical_map(priv->cpu), 0); - if (err == 1) - add_cpu(priv->cpu); + if (!priv || !priv->rsc) { + dev_err(&rproc->dev, "cannot find resource table!\n"); + return -1; + } + + homo_rproc_write_stop_flag(priv->rsc); + + gicv3_ipi_send_single(priv->irq, cpu_logical_map(priv->cpu)); + + stop = ktime_add_ns(ktime_get(), HOMO_MAX_WAIT_TIME_NS); + + spin_until_cond(homo_rproc_wait_cpuoff(rproc, stop)); + + if (ktime_after(ktime_get(), stop)) { + dev_err(&rproc->dev, "wait remote processor stop timeout!\n"); + return -1; + } + + add_cpu(priv->cpu); + + homo_rproc_clear_stop_flag(priv->rsc); return 0; } @@ -145,16 +238,9 @@ static void homo_rproc_kick(struct rproc *rproc, int vqid) if (rproc->state == RPROC_RUNNING) gicv3_ipi_send_single(priv->irq, cpu_logical_map(priv->cpu)); - return ; + return; } -static const struct rproc_ops homo_rproc_ops = { - .start = homo_rproc_start, - .stop = homo_rproc_stop, - .kick = homo_rproc_kick, - .da_to_va = homo_rproc_da_to_va, -}; - static void __iomem *homo_ioremap_prot(phys_addr_t addr, size_t size, pgprot_t prot) { unsigned long offset, vaddr; @@ -187,34 +273,136 @@ static void __iomem *homo_ioremap_prot(phys_addr_t addr, size_t size, pgprot_t p static irqreturn_t homo_rproc_irq_handler(int irq, void *data) { - schedule_work(&workqueue); + int offset; + struct homo_rproc *priv; + int cpu = smp_processor_id(); + + /* Return immediately if not the designated CPU */ + if (cpu != RPROC_IRQ_HANDLE_CPU) { + return IRQ_HANDLED; + } + + offset = homo_find_rproc_offset_irq(irq); + priv = g_homo_rproc[offset]; + + schedule_work(&priv->vq_work); return IRQ_HANDLED; } static int homo_rproc_starting_cpu(unsigned int cpu) { - enable_percpu_irq(homo_rproc_irq, irq_get_trigger_type(homo_rproc_irq)); + int i; + int irq; + + for (i = 0; i < homo_rproc_num; i++) { + irq = g_homo_rproc[i]->mapped_irq; + enable_percpu_irq(irq, irq_get_trigger_type(irq)); + } + return 0; } static int homo_rproc_dying_cpu(unsigned int cpu) { - disable_percpu_irq(homo_rproc_irq); + int i; + int irq; + + for (i = 0; i < homo_rproc_num; i++) { + irq = g_homo_rproc[i]->mapped_irq; + disable_percpu_irq(irq); + } + return 0; } -static int homo_rproc_probe(struct platform_device *pdev) +static int homo_mem_alloc(struct rproc *rproc, struct rproc_mem_entry *mem) { - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node, *p; + struct device *dev = rproc->dev.parent; + void *va; + struct homo_rproc *priv = rproc->priv; + char load_name[32]; + + va = homo_ioremap_prot(mem->dma, mem->len, PAGE_KERNEL_EXEC); + if (!va) { + dev_err(dev, "Unable to map memory region: %pa+%zx\n", + &mem->dma, mem->len); + return -ENOMEM; + } + + snprintf(load_name, sizeof(load_name), "imgload"); + if (!strcmp(mem->name, load_name)) { + priv->addr = va; + priv->phys_addr = mem->dma; + } + + dev_dbg(dev, "name: %s, ioremap: phys_addr = %016llx, addr = %llx, size = %lx\n", + mem->name, mem->dma, (u64)va, mem->len); + + /* Update memory entry va */ + mem->va = va; + + return 0; +} + +static int homo_mem_release(struct rproc *rproc, struct rproc_mem_entry *mem) +{ + vunmap(mem->va); + + return 0; +} + +static int homo_rproc_prepare(struct rproc *rproc) +{ + struct device *dev = rproc->dev.parent; + struct device_node *np = dev->of_node; + struct device_node *np_mem; struct resource res; - struct rproc *rproc; - const char *fw_name; - struct homo_rproc *priv; int ret; + struct homo_rproc *priv = rproc->priv; + + np_mem = of_parse_phandle(np, "memory-region", 0); + ret = of_address_to_resource(np_mem, 0, &res); + if (ret) { + dev_err(dev, "can't find memory-region for Baremetal\n"); + return -ENOMEM; + } + + priv->rsc = NULL; + + priv->phys_addr = res.start; + priv->size = resource_size(&res); + + HOMO_ADD_CARVEOUT(dev, priv->phys_addr + HOMO_IMGLOAD_OFFSET, HOMO_IMGLOAD_SIZE, "imgload"); + HOMO_ADD_CARVEOUT(dev, priv->phys_addr + HOMO_VDEV_VIRING0_OFFSET, HOMO_VDEV_VIRING0_SIZE, "vdev0vring0"); + HOMO_ADD_CARVEOUT(dev, priv->phys_addr + HOMO_VDEV_VIRING1_OFFSET, HOMO_VDEV_VIRING1_SIZE, "vdev0vring1"); + HOMO_ADD_CARVEOUT(dev, priv->phys_addr + HOMO_VDEV_BUFFER_OFFSET, HOMO_VDEV_BUFFER_SIZE, "vdev0buffer"); + + return 0; +} + +static const struct rproc_ops homo_rproc_ops = { + .prepare = homo_rproc_prepare, + .start = homo_rproc_start, + .stop = homo_rproc_stop, + .kick = homo_rproc_kick, + .da_to_va = homo_rproc_da_to_va, +}; + +static int homo_core_of_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev_of_node(dev), *p; + struct homo_rproc *priv; unsigned int ipi, cpu; + int ret; struct of_phandle_args oirq; + int rproc_irq; + struct rproc *rproc; + const char *fw_name; + + if (!devres_open_group(dev, homo_core_of_init, GFP_KERNEL)) + return -ENOMEM; ret = rproc_of_parse_firmware(dev, 0, &fw_name); if (ret) { @@ -231,24 +419,29 @@ static int homo_rproc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rproc); - priv = g_priv = rproc->priv; + priv = g_homo_rproc[homo_rproc_num] = rproc->priv; priv->rproc = rproc; + priv->rsc = NULL; + priv->addr = NULL; /* The following values can be modified through devicetree 'homo_rproc' node */ if (of_property_read_u32(np, "remote-processor", &cpu)) { dev_err(dev, "not found 'remote-processor' property\n"); - return -EINVAL; + ret = -EINVAL; + goto err_free; } if (of_property_read_u32(np, "inter-processor-interrupt", &ipi)) { dev_err(dev, "not found 'inter-processor-interrupt' property\n"); - return -EINVAL; + ret = -EINVAL; + goto err_free; } /* The gic-v3 driver has registered the 0-7 range of SGI interrupt for system purpose */ if (ipi < 8) { dev_err(dev, "'inter-processor-interrupt' is %d, should be between 9~15\n", ipi); - return -EINVAL; + ret = -EINVAL; + goto err_free; } priv->cpu = cpu; @@ -256,76 +449,160 @@ static int homo_rproc_probe(struct platform_device *pdev) dev_info(dev, "remote-processor = %d, inter-processor-interrupt = %d\n", cpu, ipi); - np_mem = of_parse_phandle(np, "memory-region", 0); - ret = of_address_to_resource(np_mem, 0, &res); - if (ret) { - dev_err(dev, "can't find memory-region for Baremetal\n"); - return ret; - } - - priv->rsc = NULL; - priv->addr = NULL; - - priv->phys_addr = res.start; - priv->size = resource_size(&res); - - /* Map physical memory region reserved for homo remote processor. */ - priv->addr = homo_ioremap_prot(priv->phys_addr, priv->size, PAGE_KERNEL_EXEC); - if (!priv->addr) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } - dev_info(dev, "ioremap: phys_addr = %016llx, addr = %llx, size = %lld\n", - priv->phys_addr, (u64)(priv->addr), priv->size); - /* Look for the interrupt parent. */ p = of_irq_find_parent(np); if (p == NULL) { ret = -EINVAL; - goto err; + goto err_free; } oirq.np = p; oirq.args_count = 1; oirq.args[0] = ipi; - homo_rproc_irq = irq_create_of_mapping(&oirq); - if (homo_rproc_irq <= 0) { + rproc_irq = irq_create_of_mapping(&oirq); + if (rproc_irq <= 0) { ret = -EINVAL; - goto err; + goto err_free; } - ret = request_percpu_irq(homo_rproc_irq, homo_rproc_irq_handler, "homo-rproc-ipi", &cpu_number); - if (ret) { - dev_err(dev, "failed to request percpu irq, status = %d\n", ret); - goto err; - } + priv->mapped_irq = rproc_irq; - ret = cpuhp_setup_state(CPUHP_AP_HOMO_RPROC_STARTING, "remoteproc/homo_rproc:starting", homo_rproc_starting_cpu, homo_rproc_dying_cpu); + ret = request_percpu_irq(rproc_irq, homo_rproc_irq_handler, "homo-rproc-ipi", &cpu_number); if (ret) { - dev_err(dev, "cpuhp setup state failed, status = %d\n", ret); - goto err; + dev_err(dev, "failed to request percpu irq, status = %d\n", ret); + goto err_free; } ret = rproc_add(rproc); if (ret) { dev_err(dev, "failed to add register device with remoteproc core, status = %d\n", ret); - goto err; + goto err_free; } + devres_close_group(dev, homo_core_of_init); + return 0; -err: - vunmap((void *)((unsigned long)priv->addr & PAGE_MASK)); +err_free: + rproc_free(rproc); + + devres_release_group(dev, homo_core_of_init); return ret; } -static int homo_rproc_remove(struct platform_device *pdev) +/* + * release each remote processor + */ +static void homo_core_of_exit(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rproc *rproc = platform_get_drvdata(pdev); rproc_del(rproc); rproc_free(rproc); + platform_set_drvdata(pdev, NULL); + devres_release_group(dev, homo_core_of_init); +} + +/* + * free the resources when init fail or driver remove + */ +static void homo_cluster_of_exit(void) +{ + struct rproc *rproc; + struct platform_device *cpdev; + int i; + + for (i = 0; i < homo_rproc_num; i++) { + rproc = g_homo_rproc[i]->rproc; + cpdev = to_platform_device(rproc->dev.parent); + homo_core_of_exit(cpdev); + } + + homo_rproc_num = 0; +} + +/* + * Create remote processors by identifying the child nodes of homo_rproc in the dts + */ +static int homo_cluster_of_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev_of_node(dev); + struct platform_device *cpdev; + struct device_node *child; + int ret; + + for_each_available_child_of_node(np, child) { + const char *node_name = child->name; + cpdev = of_find_device_by_node(child); + if (!cpdev) { + ret = -ENODEV; + dev_err(dev, "could not get core platform device for node %s\n", node_name); + of_node_put(child); + goto fail; + } + + ret = homo_core_of_init(cpdev); + if (ret) { + dev_err(dev, "homo_core_of_init failed, ret = %d\n", ret); + put_device(&cpdev->dev); + of_node_put(child); + goto fail; + } + + homo_rproc_num++; + put_device(&cpdev->dev); + } + + return 0; + +fail: + homo_cluster_of_exit(); + return ret; +} + +static int homo_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + int num_cores; + + num_cores = of_get_available_child_count(np); + + if (num_cores > RPROC_CORE_MAX_NUM) { + dev_err(dev, "core number (%d) out of range\n", num_cores); + return -ENODEV; + } + + ret = devm_of_platform_populate(dev); + if (ret) { + dev_err(dev, "devm_of_platform_populate failed, ret = %d\n", + ret); + return ret; + } + + ret = homo_cluster_of_init(pdev); + if (ret) { + dev_err(dev, "homo_cluster_of_init failed, ret = %d\n", ret); + return ret; + } + + ret = cpuhp_setup_state(CPUHP_AP_HOMO_RPROC_STARTING, "remoteproc/homo_rproc:starting", homo_rproc_starting_cpu, homo_rproc_dying_cpu); + if (ret) { + dev_err(dev, "cpuhp setup state failed, status = %d\n", ret); + return ret; + } + + return 0; +} + +static int homo_rproc_remove(struct platform_device *pdev) +{ + homo_cluster_of_exit(); + return 0; } @@ -347,4 +624,5 @@ module_platform_driver(homo_rproc_driver); MODULE_DESCRIPTION("Homogeneous Remote Processor Control Driver"); MODULE_AUTHOR("Shaojun Yang "); +MODULE_AUTHOR("Yuming Hu "); MODULE_LICENSE("GPL v2");