From 95347e734846ac3276f5e1b338c79aec9d9809dd Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 19 May 2021 13:03:03 -0500 Subject: remoteproc: Add kernel-doc comment for is_iomem Add a kernel-doc comment for the is_iomem function argument in rproc_da_to_va(). This fixes a warning generated when building the remoteproc_core with W=1, warning: Function parameter or member 'is_iomem' not described in 'rproc_da_to_va' Reviewed-by: Mathieu Poirier Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210519180304.23563-2-s-anna@ti.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 626a6b90fba2..8c279039b6a3 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -165,6 +165,7 @@ EXPORT_SYMBOL(rproc_va_to_pa); * @rproc: handle of a remote processor * @da: remoteproc device address to translate * @len: length of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * * Some remote processors will ask us to allocate them physically contiguous * memory regions (which we call "carveouts"), and map them to specific -- cgit v1.2.3 From f2867434002387c9739494041ac81c17a3808150 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 19 May 2021 13:03:04 -0500 Subject: remoteproc: Fix various kernel-doc warnings Fix all the kernel-doc warnings in various remoteproc core files. Some of them just needed a formatting cleanup change, while others needed the Return statement to be added, or documenting the missed structure elements. Reviewed-by: Mathieu Poirier Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210519180304.23563-3-s-anna@ti.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 44 +++++++++++++++++--------- drivers/remoteproc/remoteproc_elf_loader.c | 12 ++++--- drivers/remoteproc/remoteproc_virtio.c | 6 ++-- include/linux/remoteproc.h | 50 ++++++++++++++++-------------- 4 files changed, 69 insertions(+), 43 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 8c279039b6a3..6348aaa42bbb 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -183,12 +183,12 @@ EXPORT_SYMBOL(rproc_va_to_pa); * translations on the internal remoteproc memory regions through a platform * implementation specific da_to_va ops, if present. * - * The function returns a valid kernel address on success or NULL on failure. - * * Note: phys_to_virt(iommu_iova_to_phys(rproc->domain, da)) will work too, * but only on kernel direct mapped RAM memory. Instead, we're just using * here the output of the DMA API for the carveouts, which should be more * correct. + * + * Return: a valid kernel address on success or NULL on failure */ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) { @@ -509,7 +509,7 @@ static int copy_dma_range_map(struct device *to, struct device *from) * use RSC_DEVMEM resource entries to map their required @da to the physical * address of their base CMA region (ouch, hacky!). * - * Returns 0 on success, or an appropriate error code otherwise + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, int offset, int avail) @@ -644,7 +644,7 @@ void rproc_vdev_release(struct kref *ref) * support dynamically allocating this address using the generic * DMA API (but currently there isn't a use case for that). * - * Returns 0 on success, or an appropriate error code otherwise + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_trace(struct rproc *rproc, void *ptr, int offset, int avail) @@ -721,6 +721,8 @@ static int rproc_handle_trace(struct rproc *rproc, void *ptr, * tell us ranges of physical addresses the firmware is allowed to request, * and not allow firmwares to request access to physical addresses that * are outside those ranges. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_devmem(struct rproc *rproc, void *ptr, int offset, int avail) @@ -783,6 +785,8 @@ out: * * This function allocate specified memory entry @mem using * dma_alloc_coherent() as default allocator + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_alloc_carveout(struct rproc *rproc, struct rproc_mem_entry *mem) @@ -889,6 +893,8 @@ dma_free: * * This function releases specified memory entry @mem allocated via * rproc_alloc_carveout() function by @rproc. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_release_carveout(struct rproc *rproc, struct rproc_mem_entry *mem) @@ -918,6 +924,8 @@ static int rproc_release_carveout(struct rproc *rproc, * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB * pressure is important; it may have a substantial impact on performance. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_carveout(struct rproc *rproc, void *ptr, int offset, int avail) @@ -1006,6 +1014,8 @@ EXPORT_SYMBOL(rproc_add_carveout); * * This function allocates a rproc_mem_entry struct and fill it with parameters * provided by client. + * + * Return: a valid pointer on success, or NULL on failure */ __printf(8, 9) struct rproc_mem_entry * @@ -1050,6 +1060,8 @@ EXPORT_SYMBOL(rproc_mem_entry_init); * * This function allocates a rproc_mem_entry struct and fill it with parameters * provided by client. + * + * Return: a valid pointer on success, or NULL on failure */ __printf(5, 6) struct rproc_mem_entry * @@ -1881,6 +1893,8 @@ static int __rproc_detach(struct rproc *rproc) * remoteproc functional again. * * This function can sleep, so it cannot be called from atomic context. + * + * Return: 0 on success or a negative value upon failure */ int rproc_trigger_recovery(struct rproc *rproc) { @@ -1965,7 +1979,7 @@ static void rproc_crash_handler_work(struct work_struct *work) * If the remote processor is already powered on, this function immediately * returns (successfully). * - * Returns 0 on success, and an appropriate error value otherwise. + * Return: 0 on success, and an appropriate error value otherwise */ int rproc_boot(struct rproc *rproc) { @@ -2100,6 +2114,8 @@ EXPORT_SYMBOL(rproc_shutdown); * no longer available. From there it should be possible to remove the * platform driver and even power cycle the application processor (if the HW * supports it) without needing to switch off the remote processor. + * + * Return: 0 on success, and an appropriate error value otherwise */ int rproc_detach(struct rproc *rproc) { @@ -2152,7 +2168,7 @@ EXPORT_SYMBOL(rproc_detach); * This function increments the remote processor's refcount, so always * use rproc_put() to decrement it back once rproc isn't needed anymore. * - * Returns the rproc handle on success, and NULL on failure. + * Return: rproc handle on success, and NULL on failure */ #ifdef CONFIG_OF struct rproc *rproc_get_by_phandle(phandle phandle) @@ -2302,8 +2318,6 @@ static int rproc_validate(struct rproc *rproc) * This is called by the platform-specific rproc implementation, whenever * a new remote processor device is probed. * - * Returns 0 on success and an appropriate error code otherwise. - * * Note: this function initiates an asynchronous firmware loading * context, which will look for virtio devices supported by the rproc's * firmware. @@ -2311,6 +2325,8 @@ static int rproc_validate(struct rproc *rproc) * If found, those virtio devices will be created and added, so as a result * of registering this remote processor, additional virtio drivers might be * probed. + * + * Return: 0 on success and an appropriate error code otherwise */ int rproc_add(struct rproc *rproc) { @@ -2364,7 +2380,7 @@ static void devm_rproc_remove(void *rproc) * This function performs like rproc_add() but the registered rproc device will * automatically be removed on driver detach. * - * Returns: 0 on success, negative errno on failure + * Return: 0 on success, negative errno on failure */ int devm_rproc_add(struct device *dev, struct rproc *rproc) { @@ -2472,10 +2488,10 @@ static int rproc_alloc_ops(struct rproc *rproc, const struct rproc_ops *ops) * implementations should then call rproc_add() to complete * the registration of the remote processor. * - * On success the new rproc is returned, and on failure, NULL. - * * Note: _never_ directly deallocate @rproc, even if it was not registered * yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). + * + * Return: new rproc pointer on success, and NULL on failure */ struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -2588,7 +2604,7 @@ EXPORT_SYMBOL(rproc_put); * of the outstanding reference created by rproc_alloc. To decrement that * one last refcount, one still needs to call rproc_free(). * - * Returns 0 on success and -EINVAL if @rproc isn't valid. + * Return: 0 on success and -EINVAL if @rproc isn't valid */ int rproc_del(struct rproc *rproc) { @@ -2635,7 +2651,7 @@ static void devm_rproc_free(struct device *dev, void *res) * This function performs like rproc_alloc() but the acquired rproc device will * automatically be released on driver detach. * - * Returns: new rproc instance, or NULL on failure + * Return: new rproc instance, or NULL on failure */ struct rproc *devm_rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -2687,7 +2703,7 @@ EXPORT_SYMBOL(rproc_remove_subdev); * rproc_get_by_child() - acquire rproc handle of @dev's ancestor * @dev: child device to find ancestor of * - * Returns the ancestor rproc instance, or NULL if not found. + * Return: the ancestor rproc instance, or NULL if not found */ struct rproc *rproc_get_by_child(struct device *dev) { diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 11423588965a..469c52e62faf 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -31,6 +31,8 @@ * @fw: the ELF firmware image * * Make sure this fw image is sane (ie a correct ELF32/ELF64 file). + * + * Return: 0 on success and -EINVAL upon any failure */ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) { @@ -117,11 +119,11 @@ EXPORT_SYMBOL(rproc_elf_sanity_check); * @rproc: the remote processor handle * @fw: the ELF firmware image * - * This function returns the entry point address of the ELF - * image. - * * Note that the boot address is not a configurable property of all remote * processors. Some will always boot at a specific hard-coded address. + * + * Return: entry point address of the ELF image + * */ u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw) { @@ -152,6 +154,8 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr); * might be different: they might not have iommus, and would prefer to * directly allocate memory for every segment/resource. This is not yet * supported, though. + * + * Return: 0 on success and an appropriate error code otherwise */ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) { @@ -362,7 +366,7 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table); * This function finds the location of the loaded resource table. Don't * call this function if the table wasn't loaded yet - it's a bug if you do. * - * Returns the pointer to the resource table if it is found or NULL otherwise. + * Return: pointer to the resource table if it is found or NULL otherwise. * If the table wasn't loaded yet the result is unspecified. */ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 0cc617f76068..cf4d54e98e6a 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -45,7 +45,7 @@ static bool rproc_virtio_notify(struct virtqueue *vq) * when the remote processor signals that a specific virtqueue has pending * messages available. * - * Returns IRQ_NONE if no message was found in the @notifyid virtqueue, + * Return: IRQ_NONE if no message was found in the @notifyid virtqueue, * and otherwise returns IRQ_HANDLED. */ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) @@ -325,7 +325,7 @@ static void rproc_virtio_dev_release(struct device *dev) * This function registers a virtio device. This vdev's partent is * the rproc device. * - * Returns 0 on success or an appropriate error value otherwise. + * Return: 0 on success or an appropriate error value otherwise */ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) { @@ -432,6 +432,8 @@ out: * @data: must be null * * This function unregisters an existing virtio device. + * + * Return: 0 */ int rproc_remove_virtio_dev(struct device *dev, void *data) { diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 8b795b544f75..a5b37bc10865 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -243,7 +243,7 @@ struct fw_rsc_trace { * @da: device address * @align: the alignment between the consumer and producer parts of the vring * @num: num of buffers supported by this vring (must be power of two) - * @notifyid is a unique rproc-wide notify index for this vring. This notify + * @notifyid: a unique rproc-wide notify index for this vring. This notify * index is used when kicking a remote processor, to let it know that this * vring is triggered. * @pa: physical address @@ -266,18 +266,18 @@ struct fw_rsc_vdev_vring { /** * struct fw_rsc_vdev - virtio device header * @id: virtio device id (as in virtio_ids.h) - * @notifyid is a unique rproc-wide notify index for this vdev. This notify + * @notifyid: a unique rproc-wide notify index for this vdev. This notify * index is used when kicking a remote processor, to let it know that the * status/features of this vdev have changes. - * @dfeatures specifies the virtio device features supported by the firmware - * @gfeatures is a place holder used by the host to write back the + * @dfeatures: specifies the virtio device features supported by the firmware + * @gfeatures: a place holder used by the host to write back the * negotiated features that are supported by both sides. - * @config_len is the size of the virtio config space of this vdev. The config + * @config_len: the size of the virtio config space of this vdev. The config * space lies in the resource table immediate after this vdev header. - * @status is a place holder where the host will indicate its virtio progress. - * @num_of_vrings indicates how many vrings are described in this vdev header + * @status: a place holder where the host will indicate its virtio progress. + * @num_of_vrings: indicates how many vrings are described in this vdev header * @reserved: reserved (must be zero) - * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. + * @vring: an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. * * This resource is a virtio device header: it provides information about * the vdev, and is then used by the host and its peer remote processors @@ -287,16 +287,17 @@ struct fw_rsc_vdev_vring { * to statically allocate a vdev upon registration of the rproc (dynamic vdev * allocation is not yet supported). * - * Note: unlike virtualization systems, the term 'host' here means - * the Linux side which is running remoteproc to control the remote - * processors. We use the name 'gfeatures' to comply with virtio's terms, - * though there isn't really any virtualized guest OS here: it's the host - * which is responsible for negotiating the final features. - * Yeah, it's a bit confusing. - * - * Note: immediately following this structure is the virtio config space for - * this vdev (which is specific to the vdev; for more info, read the virtio - * spec). the size of the config space is specified by @config_len. + * Note: + * 1. unlike virtualization systems, the term 'host' here means + * the Linux side which is running remoteproc to control the remote + * processors. We use the name 'gfeatures' to comply with virtio's terms, + * though there isn't really any virtualized guest OS here: it's the host + * which is responsible for negotiating the final features. + * Yeah, it's a bit confusing. + * + * 2. immediately following this structure is the virtio config space for + * this vdev (which is specific to the vdev; for more info, read the virtio + * spec). The size of the config space is specified by @config_len. */ struct fw_rsc_vdev { u32 id; @@ -440,7 +441,7 @@ enum rproc_state { * enum rproc_crash_type - remote processor crash types * @RPROC_MMUFAULT: iommu fault * @RPROC_WATCHDOG: watchdog bite - * @RPROC_FATAL_ERROR fatal error + * @RPROC_FATAL_ERROR: fatal error * * Each element of the enum is used as an array index. So that, the value of * the elements should be always something sane. @@ -457,9 +458,9 @@ enum rproc_crash_type { * enum rproc_dump_mechanism - Coredump options for core * @RPROC_COREDUMP_DISABLED: Don't perform any dump * @RPROC_COREDUMP_ENABLED: Copy dump to separate buffer and carry on with - recovery + * recovery * @RPROC_COREDUMP_INLINE: Read segments directly from device memory. Stall - recovery until all segments are read + * recovery until all segments are read */ enum rproc_dump_mechanism { RPROC_COREDUMP_DISABLED, @@ -475,6 +476,7 @@ enum rproc_dump_mechanism { * @priv: private data associated with the dump_segment * @dump: custom dump function to fill device memory segment associated * with coredump + * @offset: offset of the segment */ struct rproc_dump_segment { struct list_head node; @@ -524,7 +526,9 @@ struct rproc_dump_segment { * @auto_boot: flag to indicate if remote processor should be auto-started * @dump_segments: list of segments in the firmware * @nb_vdev: number of vdev currently handled by rproc - * @char_dev: character device of the rproc + * @elf_class: firmware ELF class + * @elf_machine: firmware ELF machine + * @cdev: character device of the rproc * @cdev_put_on_release: flag to indicate if remoteproc should be shutdown on @char_dev release */ struct rproc { @@ -613,10 +617,10 @@ struct rproc_vring { * struct rproc_vdev - remoteproc state for a supported virtio device * @refcount: reference counter for the vdev and vring allocations * @subdev: handle for registering the vdev as a rproc subdevice + * @dev: device struct used for reference count semantics * @id: virtio device id (as in virtio_ids.h) * @node: list node * @rproc: the rproc handle - * @vdev: the virio device * @vring: the vrings for this vdev * @rsc_offset: offset of the vdev's resource entry * @index: vdev position versus other vdev declared in resource table -- cgit v1.2.3 From ee99ee7c929c3e7484b663c4b7da91ab1f050d5b Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sat, 27 Mar 2021 09:31:17 -0500 Subject: remoteproc: k3-r5: Extend support to R5F clusters on AM64x SoCs The K3 AM64x SoC family has a revised R5F sub-system and contains a subset of the R5F clusters present on J721E SoCs. The K3 AM64x SoCs only have two dual-core Arm R5F clusters/subsystems with 2 R5F cores each present within the MAIN voltage domain (MAIN_R5FSS0 & MAIN_R5FSS1). The revised IP has the following distinct features: 1. The R5FSS IP supports a new "Single-CPU" mode instead of the LockStep mode on existing SoCs (AM65x, J721E or J7200). This mode is similar to LockStep-mode on J7200 SoCs in terms of TCM usage without the fault-tolerant safety feature provided by the LockStep mode. The Core1 TCMs are combined with the Core0 TCMs effectively doubling the amount of TCMs available in Single-CPU mode. The LockStep-mode on previous AM65x and J721E SoCs could only use the Core0 TCMs. These combined TCMs appear contiguous at the respective Core0 TCM addresses. The code though is executed only on a single CPU (on Core0), and as such, requires the halt signal to be programmed only for Core0, while the resets need to be managed for both the cores. 2. TCMs are auto-initialized during module power-up, and the behavior is programmable through a MMR bit. This feature is the same as on the recent J7200 SoCs. Extend the support to these clusters in the K3 R5F remoteproc driver using AM64x specific compatibles. New TI-SCI flags and a unique cluster mode are also needed for the cluster mode detection on these SoCs. The reset assert and deassert sequence of both the cores in Single-CPU mode is agnostic of the order, so the same LockStep reset and release sequences are re-used. The integration of these clusters is very much similar to existing SoCs otherwise. Reviewed-by: Mathieu Poirier Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210327143117.1840-3-s-anna@ti.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/ti_k3_r5_remoteproc.c | 149 +++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 29 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index 5cf8d030a1f0..2975393ebacd 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -40,6 +40,8 @@ #define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 /* Available from J7200 SoCs onwards */ #define PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS 0x00004000 +/* Applicable to only AM64x SoCs */ +#define PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE 0x00008000 /* R5 TI-SCI Processor Control Flags */ #define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 @@ -49,6 +51,8 @@ #define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 #define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 #define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 +/* Applicable to only AM64x SoCs */ +#define PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY 0x00000200 /** * struct k3_r5_mem - internal memory structure @@ -64,19 +68,29 @@ struct k3_r5_mem { size_t size; }; +/* + * All cluster mode values are not applicable on all SoCs. The following + * are the modes supported on various SoCs: + * Split mode : AM65x, J721E, J7200 and AM64x SoCs + * LockStep mode : AM65x, J721E and J7200 SoCs + * Single-CPU mode : AM64x SoCs only + */ enum cluster_mode { CLUSTER_MODE_SPLIT = 0, CLUSTER_MODE_LOCKSTEP, + CLUSTER_MODE_SINGLECPU, }; /** * struct k3_r5_soc_data - match data to handle SoC variations * @tcm_is_double: flag to denote the larger unified TCMs in certain modes * @tcm_ecc_autoinit: flag to denote the auto-initialization of TCMs for ECC + * @single_cpu_mode: flag to denote if SoC/IP supports Single-CPU mode */ struct k3_r5_soc_data { bool tcm_is_double; bool tcm_ecc_autoinit; + bool single_cpu_mode; }; /** @@ -369,6 +383,13 @@ static inline int k3_r5_core_run(struct k3_r5_core *core) * applicable cores to allow loading into the TCMs. The .prepare() ops is * invoked by remoteproc core before any firmware loading, and is followed * by the .start() ops after loading to actually let the R5 cores run. + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to + * execute code, but combines the TCMs from both cores. The resets for both + * cores need to be released to make this possible, as the TCMs are in general + * private to each core. Only Core0 needs to be unhalted for running the + * cluster in this mode. The function uses the same reset logic as LockStep + * mode for this (though the behavior is agnostic of the reset release order). */ static int k3_r5_rproc_prepare(struct rproc *rproc) { @@ -386,7 +407,9 @@ static int k3_r5_rproc_prepare(struct rproc *rproc) return ret; mem_init_dis = !!(cfg & PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS); - ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + /* Re-use LockStep-mode reset logic for Single-CPU mode */ + ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? k3_r5_lockstep_release(cluster) : k3_r5_split_release(core); if (ret) { dev_err(dev, "unable to enable cores for TCM loading, ret = %d\n", @@ -427,6 +450,12 @@ static int k3_r5_rproc_prepare(struct rproc *rproc) * cores. The cores themselves are only halted in the .stop() ops, and the * .unprepare() ops is invoked by the remoteproc core after the remoteproc is * stopped. + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) combines the TCMs from + * both cores. The access is made possible only with releasing the resets for + * both cores, but with only Core0 unhalted. This function re-uses the same + * reset assert logic as LockStep mode for this mode (though the behavior is + * agnostic of the reset assert order). */ static int k3_r5_rproc_unprepare(struct rproc *rproc) { @@ -436,7 +465,9 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc) struct device *dev = kproc->dev; int ret; - ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + /* Re-use LockStep-mode reset logic for Single-CPU mode */ + ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? k3_r5_lockstep_reset(cluster) : k3_r5_split_reset(core); if (ret) dev_err(dev, "unable to disable cores, ret = %d\n", ret); @@ -455,6 +486,10 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc) * first followed by Core0. The Split-mode requires that Core0 to be maintained * always in a higher power state that Core1 (implying Core1 needs to be started * always only after Core0 is started). + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute + * code, so only Core0 needs to be unhalted. The function uses the same logic + * flow as Split-mode for this. */ static int k3_r5_rproc_start(struct rproc *rproc) { @@ -539,6 +574,10 @@ put_mbox: * Core0 to be maintained always in a higher power state that Core1 (implying * Core1 needs to be stopped first before Core0). * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute + * code, so only Core0 needs to be halted. The function uses the same logic + * flow as Split-mode for this. + * * Note that the R5F halt operation in general is not effective when the R5F * core is running, but is needed to make sure the core won't run after * deasserting the reset the subsequent time. The asserting of reset can @@ -665,7 +704,9 @@ static const struct rproc_ops k3_r5_rproc_ops = { * * Each R5FSS has a cluster-level setting for configuring the processor * subsystem either in a safety/fault-tolerant LockStep mode or a performance - * oriented Split mode. Each R5F core has a number of settings to either + * oriented Split mode on most SoCs. A fewer SoCs support a non-safety mode + * as an alternate for LockStep mode that exercises only a single R5F core + * called Single-CPU mode. Each R5F core has a number of settings to either * enable/disable each of the TCMs, control which TCM appears at the R5F core's * address 0x0. These settings need to be configured before the resets for the * corresponding core are released. These settings are all protected and managed @@ -677,11 +718,13 @@ static const struct rproc_ops k3_r5_rproc_ops = { * the cores are halted before the .prepare() step. * * The function is called from k3_r5_cluster_rproc_init() and is invoked either - * once (in LockStep mode) or twice (in Split mode). Support for LockStep-mode - * is dictated by an eFUSE register bit, and the config settings retrieved from - * DT are adjusted accordingly as per the permitted cluster mode. All cluster - * level settings like Cluster mode and TEINIT (exception handling state - * dictating ARM or Thumb mode) can only be set and retrieved using Core0. + * once (in LockStep mode or Single-CPU modes) or twice (in Split mode). Support + * for LockStep-mode is dictated by an eFUSE register bit, and the config + * settings retrieved from DT are adjusted accordingly as per the permitted + * cluster mode. Another eFUSE register bit dictates if the R5F cluster only + * supports a Single-CPU mode. All cluster level settings like Cluster mode and + * TEINIT (exception handling state dictating ARM or Thumb mode) can only be set + * and retrieved using Core0. * * The function behavior is different based on the cluster mode. The R5F cores * are configured independently as per their individual settings in Split mode. @@ -700,10 +743,16 @@ static int k3_r5_rproc_configure(struct k3_r5_rproc *kproc) u32 set_cfg = 0, clr_cfg = 0; u64 boot_vec = 0; bool lockstep_en; + bool single_cpu; int ret; core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem); - core = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? core0 : kproc->core; + if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) { + core = core0; + } else { + core = kproc->core; + } ret = ti_sci_proc_get_status(core->tsp, &boot_vec, &cfg, &ctrl, &stat); @@ -713,23 +762,48 @@ static int k3_r5_rproc_configure(struct k3_r5_rproc *kproc) dev_dbg(dev, "boot_vector = 0x%llx, cfg = 0x%x ctrl = 0x%x stat = 0x%x\n", boot_vec, cfg, ctrl, stat); + /* check if only Single-CPU mode is supported on applicable SoCs */ + if (cluster->soc_data->single_cpu_mode) { + single_cpu = + !!(stat & PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY); + if (single_cpu && cluster->mode == CLUSTER_MODE_SPLIT) { + dev_err(cluster->dev, "split-mode not permitted, force configuring for single-cpu mode\n"); + cluster->mode = CLUSTER_MODE_SINGLECPU; + } + goto config; + } + + /* check conventional LockStep vs Split mode configuration */ lockstep_en = !!(stat & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED); if (!lockstep_en && cluster->mode == CLUSTER_MODE_LOCKSTEP) { dev_err(cluster->dev, "lockstep mode not permitted, force configuring for split-mode\n"); cluster->mode = CLUSTER_MODE_SPLIT; } +config: /* always enable ARM mode and set boot vector to 0 */ boot_vec = 0x0; if (core == core0) { clr_cfg = PROC_BOOT_CFG_FLAG_R5_TEINIT; - /* - * LockStep configuration bit is Read-only on Split-mode _only_ - * devices and system firmware will NACK any requests with the - * bit configured, so program it only on permitted devices - */ - if (lockstep_en) - clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + if (cluster->soc_data->single_cpu_mode) { + /* + * Single-CPU configuration bit can only be configured + * on Core0 and system firmware will NACK any requests + * with the bit configured, so program it only on + * permitted cores + */ + if (cluster->mode == CLUSTER_MODE_SINGLECPU) + set_cfg = PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE; + } else { + /* + * LockStep configuration bit is Read-only on Split-mode + * _only_ devices and system firmware will NACK any + * requests with the bit configured, so program it only + * on permitted devices + */ + if (lockstep_en) + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + } } if (core->atcm_enable) @@ -894,12 +968,12 @@ static void k3_r5_reserved_mem_exit(struct k3_r5_rproc *kproc) * cores are usable in Split-mode, but only the Core0 TCMs can be used in * LockStep-mode. The newer revisions of the R5FSS IP maximizes these TCMs by * leveraging the Core1 TCMs as well in certain modes where they would have - * otherwise been unusable (Eg: LockStep-mode on J7200 SoCs). This is done by - * making a Core1 TCM visible immediately after the corresponding Core0 TCM. - * The SoC memory map uses the larger 64 KB sizes for the Core0 TCMs, and the - * dts representation reflects this increased size on supported SoCs. The Core0 - * TCM sizes therefore have to be adjusted to only half the original size in - * Split mode. + * otherwise been unusable (Eg: LockStep-mode on J7200 SoCs, Single-CPU mode on + * AM64x SoCs). This is done by making a Core1 TCM visible immediately after the + * corresponding Core0 TCM. The SoC memory map uses the larger 64 KB sizes for + * the Core0 TCMs, and the dts representation reflects this increased size on + * supported SoCs. The Core0 TCM sizes therefore have to be adjusted to only + * half the original size in Split mode. */ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc) { @@ -909,6 +983,7 @@ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc) struct k3_r5_core *core0; if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU || !cluster->soc_data->tcm_is_double) return; @@ -987,8 +1062,9 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev) goto err_add; } - /* create only one rproc in lockstep mode */ - if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + /* create only one rproc in lockstep mode or single-cpu mode */ + if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) break; } @@ -1020,11 +1096,12 @@ static void k3_r5_cluster_rproc_exit(void *data) struct rproc *rproc; /* - * lockstep mode has only one rproc associated with first core, whereas - * split-mode has two rprocs associated with each core, and requires - * that core1 be powered down first + * lockstep mode and single-cpu modes have only one rproc associated + * with first core, whereas split-mode has two rprocs associated with + * each core, and requires that core1 be powered down first */ - core = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + core = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? list_first_entry(&cluster->cores, struct k3_r5_core, elem) : list_last_entry(&cluster->cores, struct k3_r5_core, elem); @@ -1396,7 +1473,12 @@ static int k3_r5_probe(struct platform_device *pdev) return -ENOMEM; cluster->dev = dev; - cluster->mode = CLUSTER_MODE_LOCKSTEP; + /* + * default to most common efuse configurations - Split-mode on AM64x + * and LockStep-mode on all others + */ + cluster->mode = data->single_cpu_mode ? + CLUSTER_MODE_SPLIT : CLUSTER_MODE_LOCKSTEP; cluster->soc_data = data; INIT_LIST_HEAD(&cluster->cores); @@ -1450,17 +1532,26 @@ static int k3_r5_probe(struct platform_device *pdev) static const struct k3_r5_soc_data am65_j721e_soc_data = { .tcm_is_double = false, .tcm_ecc_autoinit = false, + .single_cpu_mode = false, }; static const struct k3_r5_soc_data j7200_soc_data = { .tcm_is_double = true, .tcm_ecc_autoinit = true, + .single_cpu_mode = false, +}; + +static const struct k3_r5_soc_data am64_soc_data = { + .tcm_is_double = true, + .tcm_ecc_autoinit = true, + .single_cpu_mode = true, }; static const struct of_device_id k3_r5_of_match[] = { { .compatible = "ti,am654-r5fss", .data = &am65_j721e_soc_data, }, { .compatible = "ti,j721e-r5fss", .data = &am65_j721e_soc_data, }, { .compatible = "ti,j7200-r5fss", .data = &j7200_soc_data, }, + { .compatible = "ti,am64-r5fss", .data = &am64_soc_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, k3_r5_of_match); -- cgit v1.2.3 From 3e25e407a1c93b53a87a7743ea0cd4703d3985b7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 21 Apr 2021 16:00:40 +0200 Subject: remoteproc: stm32: fix phys_addr_t format string A phys_addr_t may be wider than an int or pointer: drivers/remoteproc/stm32_rproc.c: In function 'stm32_rproc_da_to_pa': drivers/remoteproc/stm32_rproc.c:583:30: error: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'phys_addr_t' {aka 'long long unsigned int'} [-Werror=format=] 583 | dev_dbg(dev, "da %llx to pa %#x\n", da, *pa); Print it by reference using the special %pap format string. Reviewed-by: Arnaud Pouliquen Fixes: 8a471396d21c ("remoteproc: stm32: Move resource table setup to rproc_ops") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210421140053.3727528-1-arnd@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/stm32_rproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 7353f9e7e7af..32595c950569 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -580,7 +580,7 @@ static int stm32_rproc_da_to_pa(struct rproc *rproc, continue; *pa = da - p_mem->dev_addr + p_mem->bus_addr; - dev_dbg(dev, "da %llx to pa %#x\n", da, *pa); + dev_dbg(dev, "da %llx to pa %pap\n", da, pa); return 0; } -- cgit v1.2.3 From 34c4da6d5dfba48f49f891ebd75bb55999f0c538 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 6 May 2021 22:46:01 +0200 Subject: remoteproc: k3-r5: Fix an error message 'ret' is known to be 0 here. Reorder the code so that the expected error code is printed. Acked-by: Suman Anna Fixes: 6dedbd1d5443 ("remoteproc: k3-r5: Add a remoteproc driver for R5F subsystem") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/d6e29d903b48957bf59c67229d54b0fc215e31ae.1620333870.git.christophe.jaillet@wanadoo.fr Signed-off-by: Bjorn Andersson --- drivers/remoteproc/ti_k3_r5_remoteproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index 2975393ebacd..71615210df3e 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -1349,9 +1349,9 @@ static int k3_r5_core_of_init(struct platform_device *pdev) core->tsp = k3_r5_core_of_get_tsp(dev, core->ti_sci); if (IS_ERR(core->tsp)) { + ret = PTR_ERR(core->tsp); dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n", ret); - ret = PTR_ERR(core->tsp); goto err; } -- cgit v1.2.3 From e13d1a43aa0f6ef509c9dfda6489fe80b7315620 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 6 May 2021 12:08:39 +0800 Subject: remoteproc: imx_rproc: parse fsl,auto-boot Parse fsl,auto-boot to indicate whether need remoteproc framework auto boot or not. When remote processor is booted before Linux Kernel up, do not parse fsl,auto-boot, so only need to parse the property when rproc state is RPROC_DETACHED. Signed-off-by: Peng Fan Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/1620274123-1461-5-git-send-email-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index d6338872c6db..06dac92e98e6 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -654,6 +654,9 @@ static int imx_rproc_probe(struct platform_device *pdev) INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); + if (rproc->state != RPROC_DETACHED) + rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); + ret = rproc_add(rproc); if (ret) { dev_err(dev, "rproc_add failed\n"); -- cgit v1.2.3 From 52bda8d375143585c366a7d4e5b5e680cf14100b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 6 May 2021 12:08:40 +0800 Subject: remoteproc: imx_rproc: initial support for mutilple start/stop method Add three methods IMX_RPROC_NONE(no need start/stop), IMX_RPROC_MMIO (start/stop through mmio) and IMX_RPROC_SMC(start/stop through ARM SMCCC). The current SoCs supported are all using IMX_RPROC_MMIO. Signed-off-by: Peng Fan Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/1620274123-1461-6-git-send-email-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 06dac92e98e6..6289aeae95b6 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -74,6 +74,15 @@ struct imx_rproc_att { int flags; }; +/* Remote core start/stop method */ +enum imx_rproc_method { + IMX_RPROC_NONE, + /* Through syscon regmap */ + IMX_RPROC_MMIO, + /* Through ARM SMCCC */ + IMX_RPROC_SMC, +}; + struct imx_rproc_dcfg { u32 src_reg; u32 src_mask; @@ -81,6 +90,7 @@ struct imx_rproc_dcfg { u32 src_stop; const struct imx_rproc_att *att; size_t att_size; + enum imx_rproc_method method; }; struct imx_rproc { @@ -183,6 +193,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx8mq, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), + .method = IMX_RPROC_MMIO, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { @@ -192,6 +203,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx7d, .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), + .method = IMX_RPROC_MMIO, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { @@ -201,6 +213,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { .src_stop = IMX6SX_M4_STOP, .att = imx_rproc_att_imx6sx, .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), + .method = IMX_RPROC_MMIO, }; static int imx_rproc_start(struct rproc *rproc) -- cgit v1.2.3 From cc0316c10fb7063022f604fdaee129109723d1ea Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 6 May 2021 12:08:41 +0800 Subject: remoteproc: imx_rproc: make clk optional To i.MX7ULP, M4 is the master to control everything, no need to provide clk from Linux side. So make clk optional when method is IMX_RPROC_NONE. Signed-off-by: Peng Fan Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/1620274123-1461-7-git-send-email-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 46 ++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 6289aeae95b6..e9d9860e4fce 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -590,6 +590,35 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) return 0; } +static int imx_rproc_clk_enable(struct imx_rproc *priv) +{ + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + int ret; + + /* Remote core is not under control of Linux */ + if (dcfg->method == IMX_RPROC_NONE) + return 0; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "Failed to get clock\n"); + return PTR_ERR(priv->clk); + } + + /* + * clk for M4 block including memory. Should be + * enabled before .start for FW transfer. + */ + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); + return ret; + } + + return 0; +} + static int imx_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -648,22 +677,9 @@ static int imx_rproc_probe(struct platform_device *pdev) if (ret) goto err_put_mbox; - priv->clk = devm_clk_get(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "Failed to get clock\n"); - ret = PTR_ERR(priv->clk); - goto err_put_mbox; - } - - /* - * clk for M4 block including memory. Should be - * enabled before .start for FW transfer. - */ - ret = clk_prepare_enable(priv->clk); - if (ret) { - dev_err(&rproc->dev, "Failed to enable clock\n"); + ret = imx_rproc_clk_enable(priv); + if (ret) goto err_put_mbox; - } INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); -- cgit v1.2.3 From c8a1a56d8729bdad179e6d4c35830ba3b8dfa20e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 6 May 2021 12:08:42 +0800 Subject: remoteproc: imx_rproc: support i.MX7ULP i.MX7ULP A7 core runs under control of M4 core, M4 core starts by ROM and powers most services used by A7 core, so A7 core has no power to start and stop M4 core. And the M4 core's state is default RPROC_DETACHED and remoteproc framework not able to stop the M4 core. Reviewed-by: Mathieu Poirier Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/1620274123-1461-8-git-send-email-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 49 ++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index e9d9860e4fce..d26254609a52 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -136,6 +136,14 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { { 0x40000000, 0x40000000, 0x80000000, 0 }, }; +static const struct imx_rproc_att imx_rproc_att_imx7ulp[] = { + {0x1FFD0000, 0x1FFD0000, 0x30000, ATT_OWN}, + {0x20000000, 0x20000000, 0x10000, ATT_OWN}, + {0x2F000000, 0x2F000000, 0x20000, ATT_OWN}, + {0x2F020000, 0x2F020000, 0x20000, ATT_OWN}, + {0x60000000, 0x60000000, 0x40000000, 0} +}; + static const struct imx_rproc_att imx_rproc_att_imx7d[] = { /* dev addr , sys addr , size , flags */ /* OCRAM_S (M4 Boot code) - alias */ @@ -196,6 +204,12 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .method = IMX_RPROC_MMIO, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { + .att = imx_rproc_att_imx7ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), + .method = IMX_RPROC_NONE, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { .src_reg = IMX7D_SRC_SCR, .src_mask = IMX7D_M4_RST_MASK, @@ -238,6 +252,9 @@ static int imx_rproc_stop(struct rproc *rproc) struct device *dev = priv->dev; int ret; + if (dcfg->method == IMX_RPROC_NONE) + return -EOPNOTSUPP; + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); if (ret) @@ -573,12 +590,31 @@ static void imx_rproc_free_mbox(struct rproc *rproc) static int imx_rproc_detect_mode(struct imx_rproc *priv) { + struct regmap_config config = { .name = "imx-rproc" }; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct regmap *regmap; int ret; u32 val; - ret = regmap_read(priv->regmap, dcfg->src_reg, &val); + switch (dcfg->method) { + case IMX_RPROC_NONE: + priv->rproc->state = RPROC_DETACHED; + return 0; + default: + break; + } + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to find syscon\n"); + return PTR_ERR(regmap); + } + + priv->regmap = regmap; + regmap_attach_dev(dev, regmap, &config); + + ret = regmap_read(regmap, dcfg->src_reg, &val); if (ret) { dev_err(dev, "Failed to read src\n"); return ret; @@ -625,18 +661,9 @@ static int imx_rproc_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct imx_rproc *priv; struct rproc *rproc; - struct regmap_config config = { .name = "imx-rproc" }; const struct imx_rproc_dcfg *dcfg; - struct regmap *regmap; int ret; - regmap = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(regmap)) { - dev_err(dev, "failed to find syscon\n"); - return PTR_ERR(regmap); - } - regmap_attach_dev(dev, regmap, &config); - /* set some other name then imx */ rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops, NULL, sizeof(*priv)); @@ -651,7 +678,6 @@ static int imx_rproc_probe(struct platform_device *pdev) priv = rproc->priv; priv->rproc = rproc; - priv->regmap = regmap; priv->dcfg = dcfg; priv->dev = dev; @@ -720,6 +746,7 @@ static int imx_rproc_remove(struct platform_device *pdev) } static const struct of_device_id imx_rproc_of_match[] = { + { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp }, { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d }, { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq }, -- cgit v1.2.3 From 79806d32d5aaafbf170e9b0c03b15d1be77f4c64 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 6 May 2021 12:08:43 +0800 Subject: remoteproc: imx_rproc: support i.MX8MN/P Add i.MX8MN/P remote processor(Cortex-M7) support, we are using ARM SMCCC to start/stop M core, not using regmap interface. Reviewed-by: Mathieu Poirier Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/1620274123-1461-9-git-send-email-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 87 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 7 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index d26254609a52..7cc0cadea1cc 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -3,6 +3,7 @@ * Copyright (c) 2017 Pengutronix, Oleksij Rempel */ +#include #include #include #include @@ -50,6 +51,11 @@ #define IMX_RPROC_MEM_MAX 32 +#define IMX_SIP_RPROC 0xC2000005 +#define IMX_SIP_RPROC_START 0x00 +#define IMX_SIP_RPROC_STARTED 0x01 +#define IMX_SIP_RPROC_STOP 0x02 + /** * struct imx_rproc_mem - slim internal memory structure * @cpu_addr: MPU virtual address of the memory region @@ -108,6 +114,36 @@ struct imx_rproc { void __iomem *rsc_table; }; +static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + /* dev addr , sys addr , size , flags */ + /* ITCM */ + { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00009000, 0 }, + /* OCRAM */ + { 0x00900000, 0x00900000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00920000, 0x00920000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00940000, 0x00940000, 0x00050000, 0 }, + /* QSPI Code - alias */ + { 0x08000000, 0x08000000, 0x08000000, 0 }, + /* DDR (Code) - alias */ + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* DTCM */ + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, + /* OCRAM_S - alias */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ + { 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20240000, 0x00940000, 0x00040000, ATT_OWN }, + /* DDR (Data) */ + { 0x40000000, 0x40000000, 0x80000000, 0 }, +}; + static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { /* dev addr , sys addr , size , flags */ /* TCML - alias */ @@ -194,6 +230,12 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { { 0x80000000, 0x80000000, 0x60000000, 0 }, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_SMC, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .src_reg = IMX7D_SRC_SCR, .src_mask = IMX7D_M4_RST_MASK, @@ -235,12 +277,24 @@ static int imx_rproc_start(struct rproc *rproc) struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct arm_smccc_res res; int ret; - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, - dcfg->src_mask, dcfg->src_start); + switch (dcfg->method) { + case IMX_RPROC_MMIO: + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, + dcfg->src_start); + break; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + break; + default: + return -EOPNOTSUPP; + } + if (ret) - dev_err(dev, "Failed to enable M4!\n"); + dev_err(dev, "Failed to enable remote core!\n"); return ret; } @@ -250,15 +304,26 @@ static int imx_rproc_stop(struct rproc *rproc) struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct arm_smccc_res res; int ret; - if (dcfg->method == IMX_RPROC_NONE) + switch (dcfg->method) { + case IMX_RPROC_MMIO: + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, + dcfg->src_stop); + break; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (res.a1) + dev_info(dev, "Not in wfi, force stopped\n"); + break; + default: return -EOPNOTSUPP; + } - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, - dcfg->src_mask, dcfg->src_stop); if (ret) - dev_err(dev, "Failed to stop M4!\n"); + dev_err(dev, "Failed to stop remote core\n"); return ret; } @@ -594,6 +659,7 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; struct regmap *regmap; + struct arm_smccc_res res; int ret; u32 val; @@ -601,6 +667,11 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) case IMX_RPROC_NONE: priv->rproc->state = RPROC_DETACHED; return 0; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) + priv->rproc->state = RPROC_DETACHED; + return 0; default: break; } @@ -751,6 +822,8 @@ static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq }, + { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn }, + { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn }, {}, }; MODULE_DEVICE_TABLE(of, imx_rproc_of_match); -- cgit v1.2.3 From 1cd6239426a47efb8eab6cdcb1e45ffd5601b12e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 10 Jun 2021 11:15:30 +0800 Subject: remoteproc: imx-rproc: Fix IMX_REMOTEPROC configuration When CONFIG_IMX_REMOTEPROC is y and CONFIG_HAVE_ARM_SMCCC is not set, compiling errors are encountered as follows: drivers/remoteproc/imx_rproc.o: in function `imx_rproc_stop': imx_rproc.c:(.text+0x140): undefined reference to `__arm_smccc_smc' drivers/remoteproc/imx_rproc.o: in function `imx_rproc_detect_mode': imx_rproc.c:(.text+0x272): undefined reference to `__arm_smccc_smc' drivers/remoteproc/imx_rproc.o: in function `imx_rproc_start': imx_rproc.c:(.text+0x5e0): undefined reference to `__arm_smccc_smc' __arm_smccc_smc is defined when HAVE_ARM_SMCCC is y, so add dependency on HAVE_ARM_SMCCC in IMX_REMOTEPROC configuration. Fixes: 79806d32d5aa ("remoteproc: imx_rproc: support i.MX8MN/P") Reviewed-by: Mathieu Poirier Reported-by: kernel test robot Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20210610031530.26326-1-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index e68fcedc999c..9a6eedc3994a 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -26,6 +26,7 @@ config REMOTEPROC_CDEV config IMX_REMOTEPROC tristate "i.MX remoteproc support" depends on ARCH_MXC + depends on HAVE_ARM_SMCCC select MAILBOX help Say y here to support iMX's remote processors via the remote -- cgit v1.2.3 From 632f1ca39698a278aba3ac3ef299bf623d760bb9 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Fri, 18 Jun 2021 13:15:55 +0200 Subject: remoteproc: qcom_q6v5: Use devm_qcom_smem_state_get() to fix missing put() qcom_q6v5 is requesting a smem state with qcom_smem_state_get() but qcom_smem_state_put() is not called anywhere. Use the new devm_() variant to fix this without making the code more complicated. Fixes: 051fb70fd4ea ("remoteproc: qcom: Driver for the self-authenticating Hexagon v5") Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210618111556.53416-2-stephan@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 9627a950928e..7e9244c748da 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -280,7 +280,7 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, return ret; } - q6v5->state = qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); + q6v5->state = devm_qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); if (IS_ERR(q6v5->state)) { dev_err(&pdev->dev, "failed to acquire stop state\n"); return PTR_ERR(q6v5->state); -- cgit v1.2.3 From 8131156974cb1a698ff568314434aa0519e2a2a0 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Fri, 18 Jun 2021 13:15:56 +0200 Subject: remoteproc: qcom_wcnss: Use devm_qcom_smem_state_get() Use the new managed devm_qcom_smem_state_get() variant instead of calling qcom_smem_state_put() explicitly in remove() to simplify the code a bit. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210618111556.53416-3-stephan@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 5f3455aa7e0e..f1cbc6b2edbb 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -624,8 +624,8 @@ static int wcnss_probe(struct platform_device *pdev) wcnss->stop_ack_irq = ret; if (wcnss->stop_ack_irq) { - wcnss->state = qcom_smem_state_get(&pdev->dev, "stop", - &wcnss->stop_bit); + wcnss->state = devm_qcom_smem_state_get(&pdev->dev, "stop", + &wcnss->stop_bit); if (IS_ERR(wcnss->state)) { ret = PTR_ERR(wcnss->state); goto detach_pds; @@ -659,7 +659,6 @@ static int wcnss_remove(struct platform_device *pdev) of_platform_depopulate(&pdev->dev); - qcom_smem_state_put(wcnss->state); rproc_del(wcnss->rproc); qcom_remove_sysmon_subdev(wcnss->sysmon); -- cgit v1.2.3 From 0740ec0893ea1d74a217000d684e79b6e648bb9d Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 23 Jun 2021 12:32:42 -0500 Subject: remoteproc: pru: Add support for various PRU cores on K3 AM64x SoCs The K3 AM64x family of SoCs have a ICSSG IP that is similar to the version on AM65x SR2.0 SoCs with some minor differences. The AM64x SoCs contain two instances of this newer ICSSG IP. Each ICSSG processor subsystem contains 2 primary PRU cores, 2 auxiliary PRU cores called RTUs, and 2 new auxiliary cores called Transmit PRUs (Tx_PRUs). Enhance the existing PRU remoteproc driver to support all these PRU, RTU and Tx_PRU cores by using specific compatibles. The cores have the same memory copying limitations as on AM65x, so reuses the custom memcpy function within the driver's ELF loader implementation. The initial names for the firmware images for each PRU core are retrieved from DT nodes, and can be adjusted through sysfs if required. Reviewed-by: Grygorii Strashko Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210623173243.7862-3-s-anna@ti.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/pru_rproc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index e5778e476245..1777a01fa84e 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -887,6 +887,9 @@ static const struct of_device_id pru_rproc_match[] = { { .compatible = "ti,am3356-pru", .data = &pru_data }, { .compatible = "ti,am4376-pru", .data = &pru_data }, { .compatible = "ti,am5728-pru", .data = &pru_data }, + { .compatible = "ti,am642-pru", .data = &k3_pru_data }, + { .compatible = "ti,am642-rtu", .data = &k3_rtu_data }, + { .compatible = "ti,am642-tx-pru", .data = &k3_tx_pru_data }, { .compatible = "ti,k2g-pru", .data = &pru_data }, { .compatible = "ti,am654-pru", .data = &k3_pru_data }, { .compatible = "ti,am654-rtu", .data = &k3_rtu_data }, -- cgit v1.2.3 From c6659ee893e29912dd47f4d1d2db810fadf4d8fd Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 14 Jun 2021 19:21:08 -0700 Subject: remoteproc: core: Move cdev add before device add When cdev_add is called after device_add has been called there is no way for the userspace to know about the addition of a cdev as cdev_add itself doesn't trigger a uevent notification, or for the kernel to know about the change to devt. This results in two problems: - mknod is never called for the cdev and hence no cdev appears on devtmpfs. - sysfs links to the new cdev are not established. The cdev needs to be added and devt assigned before device_add() is called in order for the relevant sysfs and devtmpfs entries to be created and the uevent to be properly populated. Signed-off-by: Siddharth Gupta Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/1623723671-5517-2-git-send-email-sidgup@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 6348aaa42bbb..9ad8c5f96500 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2333,6 +2333,11 @@ int rproc_add(struct rproc *rproc) struct device *dev = &rproc->dev; int ret; + /* add char device for this remoteproc */ + ret = rproc_char_device_add(rproc); + if (ret < 0) + return ret; + ret = device_add(dev); if (ret < 0) return ret; @@ -2346,11 +2351,6 @@ int rproc_add(struct rproc *rproc) /* create debugfs entries */ rproc_create_debug_dir(rproc); - /* add char device for this remoteproc */ - ret = rproc_char_device_add(rproc); - if (ret < 0) - return ret; - /* if rproc is marked always-on, request it to boot */ if (rproc->auto_boot) { ret = rproc_trigger_auto_boot(rproc); -- cgit v1.2.3 From 519346ecabd3c1d5821f076b5df1695ecfabe2f6 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 14 Jun 2021 19:21:09 -0700 Subject: remoteproc: core: Move validate before device add We can validate whether the remoteproc is correctly setup before making the cdev_add and device_add calls. This saves us the trouble of cleaning up later on. Signed-off-by: Siddharth Gupta Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/1623723671-5517-3-git-send-email-sidgup@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9ad8c5f96500..b65fce32e88c 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2333,16 +2333,16 @@ int rproc_add(struct rproc *rproc) struct device *dev = &rproc->dev; int ret; - /* add char device for this remoteproc */ - ret = rproc_char_device_add(rproc); + ret = rproc_validate(rproc); if (ret < 0) return ret; - ret = device_add(dev); + /* add char device for this remoteproc */ + ret = rproc_char_device_add(rproc); if (ret < 0) return ret; - ret = rproc_validate(rproc); + ret = device_add(dev); if (ret < 0) return ret; -- cgit v1.2.3 From 930eec0be20c93a53160c74005a1485a230e6911 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 14 Jun 2021 19:21:10 -0700 Subject: remoteproc: core: Fix cdev remove and rproc del The rproc_char_device_remove() call currently unmaps the cdev region instead of simply deleting the cdev that was added as a part of the rproc_char_device_add() call. This change fixes that behaviour, and also fixes the order in which device_del() and cdev_del() need to be called. Signed-off-by: Siddharth Gupta Link: https://lore.kernel.org/r/1623723671-5517-4-git-send-email-sidgup@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_cdev.c | 2 +- drivers/remoteproc/remoteproc_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_cdev.c b/drivers/remoteproc/remoteproc_cdev.c index 0b8a84c04f76..4ad98b0b8caa 100644 --- a/drivers/remoteproc/remoteproc_cdev.c +++ b/drivers/remoteproc/remoteproc_cdev.c @@ -124,7 +124,7 @@ int rproc_char_device_add(struct rproc *rproc) void rproc_char_device_remove(struct rproc *rproc) { - __unregister_chrdev(MAJOR(rproc->dev.devt), rproc->index, 1, "remoteproc"); + cdev_del(&rproc->cdev); } void __init rproc_init_cdev(void) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index b65fce32e88c..b8742807ca1c 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2619,7 +2619,6 @@ int rproc_del(struct rproc *rproc) mutex_unlock(&rproc->lock); rproc_delete_debug_dir(rproc); - rproc_char_device_remove(rproc); /* the rproc is downref'ed as soon as it's removed from the klist */ mutex_lock(&rproc_list_mutex); @@ -2630,6 +2629,7 @@ int rproc_del(struct rproc *rproc) synchronize_rcu(); device_del(&rproc->dev); + rproc_char_device_remove(rproc); return 0; } -- cgit v1.2.3 From 7dbdb8bd7c028c83ac75e5c97536559a7274c797 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 14 Jun 2021 19:21:11 -0700 Subject: remoteproc: core: Cleanup device in case of failure When a failure occurs in rproc_add() it returns an error, but does not cleanup after itself. This change adds the failure path in such cases. Signed-off-by: Siddharth Gupta Link: https://lore.kernel.org/r/1623723671-5517-5-git-send-email-sidgup@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index b8742807ca1c..d823f707267f 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2343,8 +2343,10 @@ int rproc_add(struct rproc *rproc) return ret; ret = device_add(dev); - if (ret < 0) - return ret; + if (ret < 0) { + put_device(dev); + goto rproc_remove_cdev; + } dev_info(dev, "%s is available\n", rproc->name); @@ -2355,7 +2357,7 @@ int rproc_add(struct rproc *rproc) if (rproc->auto_boot) { ret = rproc_trigger_auto_boot(rproc); if (ret < 0) - return ret; + goto rproc_remove_dev; } /* expose to rproc_get_by_phandle users */ @@ -2364,6 +2366,13 @@ int rproc_add(struct rproc *rproc) mutex_unlock(&rproc_list_mutex); return 0; + +rproc_remove_dev: + rproc_delete_debug_dir(rproc); + device_del(dev); +rproc_remove_cdev: + rproc_char_device_remove(rproc); + return ret; } EXPORT_SYMBOL(rproc_add); -- cgit v1.2.3 From 51c4b4e212269a8634dee2000182cfca7f11575b Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Tue, 20 Apr 2021 11:19:22 +0200 Subject: remoteproc: stm32: fix mbox_send_message call mbox_send_message is called by passing a local dummy message or a function parameter. As the message is queued, it is dereferenced. This works because the message field is not used by the stm32 ipcc driver, but it is not clean. Fix by passing a constant string in all cases. The associated comments are removed because rproc should not have to deal with the behavior of the mailbox frame. Reported-by: Bjorn Andersson Signed-off-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210420091922.29429-1-arnaud.pouliquen@foss.st.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/stm32_rproc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 32595c950569..b643efcf995a 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -474,14 +474,12 @@ static int stm32_rproc_attach(struct rproc *rproc) static int stm32_rproc_detach(struct rproc *rproc) { struct stm32_rproc *ddata = rproc->priv; - int err, dummy_data, idx; + int err, idx; /* Inform the remote processor of the detach */ idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_DETACH); if (idx >= 0 && ddata->mb[idx].chan) { - /* A dummy data is sent to allow to block on transmit */ - err = mbox_send_message(ddata->mb[idx].chan, - &dummy_data); + err = mbox_send_message(ddata->mb[idx].chan, "stop"); if (err < 0) dev_warn(&rproc->dev, "warning: remote FW detach without ack\n"); } @@ -493,15 +491,13 @@ static int stm32_rproc_detach(struct rproc *rproc) static int stm32_rproc_stop(struct rproc *rproc) { struct stm32_rproc *ddata = rproc->priv; - int err, dummy_data, idx; + int err, idx; /* request shutdown of the remote processor */ if (rproc->state != RPROC_OFFLINE) { idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); if (idx >= 0 && ddata->mb[idx].chan) { - /* a dummy data is sent to allow to block on transmit */ - err = mbox_send_message(ddata->mb[idx].chan, - &dummy_data); + err = mbox_send_message(ddata->mb[idx].chan, "detach"); if (err < 0) dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); } @@ -556,7 +552,7 @@ static void stm32_rproc_kick(struct rproc *rproc, int vqid) continue; if (!ddata->mb[i].chan) return; - err = mbox_send_message(ddata->mb[i].chan, (void *)(long)vqid); + err = mbox_send_message(ddata->mb[i].chan, "kick"); if (err < 0) dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n", __func__, ddata->mb[i].name, err); -- cgit v1.2.3 From d59eedc0e408565cb65eab46040bb1a07eaec315 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 22 Jun 2021 14:01:48 +0800 Subject: remoteproc: imx_rproc: support i.MX8ULP i.MX8ULP is a new SoC with Ultra low power support, it has a Cortex-M33 core and two Cortex-A35 cores. We need to add new configuration because it could not reuse the previous i.MX7/8 configuration. i.MX8ULP M33 core is kicked by ROM, it is not under control of A35 core. So need to mark the method is IMX_RPROC_NONE. Signed-off-by: Peng Fan Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/20210622060148.18411-3-peng.fan@oss.nxp.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/imx_rproc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 7cc0cadea1cc..d88f76f5305e 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -172,6 +172,12 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { { 0x40000000, 0x40000000, 0x80000000, 0 }, }; +static const struct imx_rproc_att imx_rproc_att_imx8ulp[] = { + {0x1FFC0000, 0x1FFC0000, 0xC0000, ATT_OWN}, + {0x21000000, 0x21000000, 0x10000, ATT_OWN}, + {0x80000000, 0x80000000, 0x60000000, 0} +}; + static const struct imx_rproc_att imx_rproc_att_imx7ulp[] = { {0x1FFD0000, 0x1FFD0000, 0x30000, ATT_OWN}, {0x20000000, 0x20000000, 0x10000, ATT_OWN}, @@ -246,6 +252,12 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .method = IMX_RPROC_MMIO, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = { + .att = imx_rproc_att_imx8ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp), + .method = IMX_RPROC_NONE, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { .att = imx_rproc_att_imx7ulp, .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), @@ -824,6 +836,7 @@ static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn }, { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn }, + { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp }, {}, }; MODULE_DEVICE_TABLE(of, imx_rproc_of_match); -- cgit v1.2.3 From aef6a521e5bf61b3be4567f6c88776956a6d8b32 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 8 Jun 2021 10:49:44 -0700 Subject: remoteproc: qcom: pas: Add SC8180X adsp, cdsp and mpss The Qualcomm SC8180X has the typical ADSP, CDSP and MPSS remote processors operated using the PAS interface, add support for these. Attempts to configuring mss.lvl is failing, so a new adsp_data is provided that skips this resource, for now. Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20210608174944.2045215-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/remoteproc') diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index b921fc26cd04..a79bee901e9b 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -689,6 +689,25 @@ static const struct adsp_data mpss_resource_init = { .ssctl_id = 0x12, }; +static const struct adsp_data sc8180x_mpss_resource = { + .crash_reason_smem = 421, + .firmware_name = "modem.mdt", + .pas_id = 4, + .has_aggre2_clk = false, + .auto_boot = false, + .active_pd_names = (char*[]){ + "load_state", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + NULL + }, + .ssr_name = "mpss", + .sysmon_name = "modem", + .ssctl_id = 0x12, +}; + static const struct adsp_data slpi_resource_init = { .crash_reason_smem = 424, .firmware_name = "slpi.mdt", @@ -811,6 +830,9 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init}, + { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource}, + { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource}, + { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource}, { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init}, { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init}, { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource}, -- cgit v1.2.3