Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'rproc-v4.14' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:
"This adds and improves remoteproc support for TI DA8xx/OMAP-L13x DSP,
TI Keystone 66AK2G DSP and iMX6SX/7D Cortex M4 coprocessors. It
introduces the Qualcomm restart notifier and a few fixes"

* tag 'rproc-v4.14' of git://github.com/andersson/remoteproc:
remoteproc: Introduce rproc handle accessor for children
remoteproc: qcom: Make ssr_notifiers local
remoteproc: Stop subdevices in reverse order
remoteproc: imx_rproc: add a NXP/Freescale imx_rproc driver
remoteproc: dt: Provide bindings for iMX6SX/7D Remote Processor Controller driver
remoteproc: qcom: Use PTR_ERR_OR_ZERO
remoteproc: st: explicitly request exclusive reset control
remoteproc: qcom: explicitly request exclusive reset control
remoteproc/keystone: explicitly request exclusive reset control
remoteproc/keystone: Add support for Keystone 66AK2G SOCs
remoteproc/davinci: Add device tree support for OMAP-L138 DSP
dt-bindings: remoteproc: Add bindings for Davinci DSP processors
remoteproc/davinci: Add support to parse internal memories
remoteproc/davinci: Switch to platform_get_resource_byname()
remoteproc: make device_type const
soc: qcom: GLINK SSR notifier
remoteproc: qcom: Add support for SSR notifications
remoteproc: Merge __rproc_boot() with rproc_boot()

+1032 -37
+33
Documentation/devicetree/bindings/remoteproc/imx-rproc.txt
··· 1 + NXP iMX6SX/iMX7D Co-Processor Bindings 2 + ---------------------------------------- 3 + 4 + This binding provides support for ARM Cortex M4 Co-processor found on some 5 + NXP iMX SoCs. 6 + 7 + Required properties: 8 + - compatible Should be one of: 9 + "fsl,imx7d-cm4" 10 + "fsl,imx6sx-cm4" 11 + - clocks Clock for co-processor (See: ../clock/clock-bindings.txt) 12 + - syscon Phandle to syscon block which provide access to 13 + System Reset Controller 14 + 15 + Optional properties: 16 + - memory-region list of phandels to the reserved memory regions. 17 + (See: ../reserved-memory/reserved-memory.txt) 18 + 19 + Example: 20 + m4_reserved_sysmem1: cm4@80000000 { 21 + reg = <0x80000000 0x80000>; 22 + }; 23 + 24 + m4_reserved_sysmem2: cm4@81000000 { 25 + reg = <0x81000000 0x80000>; 26 + }; 27 + 28 + imx7d-cm4 { 29 + compatible = "fsl,imx7d-cm4"; 30 + memory-region = <&m4_reserved_sysmem1>, <&m4_reserved_sysmem2>; 31 + syscon = <&src>; 32 + clocks = <&clks IMX7D_ARM_M4_ROOT_CLK>; 33 + };
+86
Documentation/devicetree/bindings/remoteproc/ti,davinci-rproc.txt
··· 1 + TI Davinci DSP devices 2 + ======================= 3 + 4 + Binding status: Unstable - Subject to changes for DT representation of clocks 5 + and resets 6 + 7 + The TI Davinci family of SoCs usually contains a TI DSP Core sub-system that 8 + is used to offload some of the processor-intensive tasks or algorithms, for 9 + achieving various system level goals. 10 + 11 + The processor cores in the sub-system usually contain additional sub-modules 12 + like L1 and/or L2 caches/SRAMs, an Interrupt Controller, an external memory 13 + controller, a dedicated local power/sleep controller etc. The DSP processor 14 + core used in Davinci SoCs is usually a C674x DSP CPU. 15 + 16 + DSP Device Node: 17 + ================ 18 + Each DSP Core sub-system is represented as a single DT node. 19 + 20 + Required properties: 21 + -------------------- 22 + The following are the mandatory properties: 23 + 24 + - compatible: Should be one of the following, 25 + "ti,da850-dsp" for DSPs on OMAP-L138 SoCs 26 + 27 + - reg: Should contain an entry for each value in 'reg-names'. 28 + Each entry should have the memory region's start address 29 + and the size of the region, the representation matching 30 + the parent node's '#address-cells' and '#size-cells' values. 31 + 32 + - reg-names: Should contain strings with the following names, each 33 + representing a specific internal memory region or a 34 + specific register space, 35 + "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig_base" 36 + 37 + - interrupts: Should contain the interrupt number used to receive the 38 + interrupts from the DSP. The value should follow the 39 + interrupt-specifier format as dictated by the 40 + 'interrupt-parent' node. 41 + 42 + - memory-region: phandle to the reserved memory node to be associated 43 + with the remoteproc device. The reserved memory node 44 + can be a CMA memory node, and should be defined as 45 + per the bindings in 46 + Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt 47 + 48 + Optional properties: 49 + -------------------- 50 + - interrupt-parent: phandle to the interrupt controller node. This property 51 + is needed if the device node hierarchy doesn't have an 52 + interrupt controller. 53 + 54 + 55 + Example: 56 + -------- 57 + 58 + /* DSP Reserved Memory node */ 59 + reserved-memory { 60 + #address-cells = <1>; 61 + #size-cells = <1>; 62 + ranges; 63 + 64 + dsp_memory_region: dsp-memory@c3000000 { 65 + compatible = "shared-dma-pool"; 66 + reg = <0xc3000000 0x1000000>; 67 + reusable; 68 + }; 69 + }; 70 + 71 + /* DSP node */ 72 + { 73 + dsp: dsp@11800000 { 74 + compatible = "ti,da850-dsp"; 75 + reg = <0x11800000 0x40000>, 76 + <0x11e00000 0x8000>, 77 + <0x11f00000 0x8000>, 78 + <0x01c14044 0x4>, 79 + <0x01c14174 0x8>; 80 + reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", 81 + "chipsig"; 82 + interrupt-parent = <&intc>; 83 + interrupts = <28>; 84 + memory-region = <&dsp_memory_region>; 85 + }; 86 + };
+64 -9
Documentation/devicetree/bindings/remoteproc/ti,keystone-rproc.txt
··· 26 26 "ti,k2hk-dsp" for DSPs on Keystone 2 66AK2H/K SoCs 27 27 "ti,k2l-dsp" for DSPs on Keystone 2 66AK2L SoCs 28 28 "ti,k2e-dsp" for DSPs on Keystone 2 66AK2E SoCs 29 + "ti,k2g-dsp" for DSPs on Keystone 2 66AK2G SoCs 29 30 30 31 - reg: Should contain an entry for each value in 'reg-names'. 31 32 Each entry should have the memory region's start address ··· 38 37 should be defined in this order, 39 38 "l2sram", "l1pram", "l1dram" 40 39 41 - - clocks: Should contain the device's input clock, and should be 42 - defined as per the bindings in, 43 - Documentation/devicetree/bindings/clock/keystone-gate.txt 44 - 45 40 - ti,syscon-dev: Should be a pair of the phandle to the Keystone Device 46 41 State Control node, and the register offset of the DSP 47 42 boot address register within that node's address space. 48 43 49 44 - resets: Should contain the phandle to the reset controller node 50 45 managing the resets for this device, and a reset 51 - specifier. Please refer to the following reset bindings 52 - for the reset argument specifier as per SoC, 46 + specifier. Please refer to either of the following reset 47 + bindings for the reset argument specifier as per SoC, 53 48 Documentation/devicetree/bindings/reset/ti-syscon-reset.txt 54 - for 66AK2HK/66AK2L/66AK2E SoCs 49 + for 66AK2HK/66AK2L/66AK2E SoCs or, 50 + Documentation/devicetree/bindings/reset/ti,sci-reset.txt 51 + for 66AK2G SoCs 55 52 56 53 - interrupt-parent: Should contain a phandle to the Keystone 2 IRQ controller 57 54 IP node that is used by the ARM CorePac processor to ··· 74 75 The gpio device to be used is as per the bindings in, 75 76 Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt 76 77 78 + SoC-specific Required properties: 79 + --------------------------------- 80 + The following are mandatory properties for Keystone 2 66AK2HK, 66AK2L and 66AK2E 81 + SoCs only: 82 + 83 + - clocks: Should contain the device's input clock, and should be 84 + defined as per the bindings in, 85 + Documentation/devicetree/bindings/clock/keystone-gate.txt 86 + 87 + The following are mandatory properties for Keystone 2 66AK2G SoCs only: 88 + 89 + - power-domains: Should contain a phandle to a PM domain provider node 90 + and an args specifier containing the DSP device id 91 + value. This property is as per the binding, 92 + Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt 93 + 77 94 Optional properties: 78 95 -------------------- 79 96 ··· 100 85 Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt 101 86 102 87 103 - Example: 104 - -------- 88 + Examples: 89 + --------- 90 + 91 + 1. 105 92 /* 66AK2H/K DSP aliases */ 106 93 aliases { 107 94 rproc0 = &dsp0; ··· 147 130 memory-region = <&dsp_common_memory>; 148 131 }; 149 132 133 + }; 134 + 135 + 2. 136 + /* 66AK2G DSP alias */ 137 + aliases { 138 + rproc0 = &dsp0; 139 + }; 140 + 141 + /* 66AK2G DSP memory node */ 142 + reserved-memory { 143 + #address-cells = <2>; 144 + #size-cells = <2>; 145 + ranges; 146 + 147 + dsp_common_memory: dsp-common-memory@81f800000 { 148 + compatible = "shared-dma-pool"; 149 + reg = <0x00000008 0x1f800000 0x00000000 0x800000>; 150 + reusable; 151 + }; 152 + }; 153 + 154 + /* 66AK2G DSP node */ 155 + soc { 156 + dsp0: dsp@10800000 { 157 + compatible = "ti,k2g-dsp"; 158 + reg = <0x10800000 0x00100000>, 159 + <0x10e00000 0x00008000>, 160 + <0x10f00000 0x00008000>; 161 + reg-names = "l2sram", "l1pram", "l1dram"; 162 + power-domains = <&k2g_pds 0x0046>; 163 + ti,syscon-dev = <&devctrl 0x40>; 164 + resets = <&k2g_reset 0x0046 0x1>; 165 + interrupt-parent = <&kirq0>; 166 + interrupts = <0 8>; 167 + interrupt-names = "vring", "exception"; 168 + kick-gpios = <&dspgpio0 27 0>; 169 + memory-region = <&dsp_common_memory>; 170 + }; 150 171 };
+9
drivers/remoteproc/Kconfig
··· 12 12 13 13 if REMOTEPROC 14 14 15 + config IMX_REMOTEPROC 16 + tristate "IMX6/7 remoteproc support" 17 + depends on SOC_IMX6SX || SOC_IMX7D 18 + help 19 + Say y here to support iMX's remote processors (Cortex M4 20 + on iMX7D) via the remote processor framework. 21 + 22 + It's safe to say N here. 23 + 15 24 config OMAP_REMOTEPROC 16 25 tristate "OMAP remoteproc support" 17 26 depends on HAS_DMA
+1
drivers/remoteproc/Makefile
··· 8 8 remoteproc-y += remoteproc_sysfs.o 9 9 remoteproc-y += remoteproc_virtio.o 10 10 remoteproc-y += remoteproc_elf_loader.o 11 + obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o 11 12 obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o 12 13 obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o 13 14 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
+93 -5
drivers/remoteproc/da8xx_remoteproc.c
··· 16 16 #include <linux/irq.h> 17 17 #include <linux/kernel.h> 18 18 #include <linux/module.h> 19 + #include <linux/of_reserved_mem.h> 19 20 #include <linux/platform_device.h> 20 21 #include <linux/remoteproc.h> 21 22 ··· 39 38 #define SYSCFG_CHIPSIG3 BIT(3) 40 39 #define SYSCFG_CHIPSIG4 BIT(4) 41 40 41 + #define DA8XX_RPROC_LOCAL_ADDRESS_MASK (SZ_16M - 1) 42 + 43 + /** 44 + * struct da8xx_rproc_mem - internal memory structure 45 + * @cpu_addr: MPU virtual address of the memory region 46 + * @bus_addr: Bus address used to access the memory region 47 + * @dev_addr: Device address of the memory region from DSP view 48 + * @size: Size of the memory region 49 + */ 50 + struct da8xx_rproc_mem { 51 + void __iomem *cpu_addr; 52 + phys_addr_t bus_addr; 53 + u32 dev_addr; 54 + size_t size; 55 + }; 56 + 42 57 /** 43 58 * struct da8xx_rproc - da8xx remote processor instance state 44 59 * @rproc: rproc handle 60 + * @mem: internal memory regions data 61 + * @num_mems: number of internal memory regions 45 62 * @dsp_clk: placeholder for platform's DSP clk 46 63 * @ack_fxn: chip-specific ack function for ack'ing irq 47 64 * @irq_data: ack_fxn function parameter ··· 69 50 */ 70 51 struct da8xx_rproc { 71 52 struct rproc *rproc; 53 + struct da8xx_rproc_mem *mem; 54 + int num_mems; 72 55 struct clk *dsp_clk; 73 56 void (*ack_fxn)(struct irq_data *data); 74 57 struct irq_data *irq_data; ··· 179 158 .kick = da8xx_rproc_kick, 180 159 }; 181 160 161 + static int da8xx_rproc_get_internal_memories(struct platform_device *pdev, 162 + struct da8xx_rproc *drproc) 163 + { 164 + static const char * const mem_names[] = {"l2sram", "l1pram", "l1dram"}; 165 + int num_mems = ARRAY_SIZE(mem_names); 166 + struct device *dev = &pdev->dev; 167 + struct resource *res; 168 + int i; 169 + 170 + drproc->mem = devm_kcalloc(dev, num_mems, sizeof(*drproc->mem), 171 + GFP_KERNEL); 172 + if (!drproc->mem) 173 + return -ENOMEM; 174 + 175 + for (i = 0; i < num_mems; i++) { 176 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 177 + mem_names[i]); 178 + drproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res); 179 + if (IS_ERR(drproc->mem[i].cpu_addr)) { 180 + dev_err(dev, "failed to parse and map %s memory\n", 181 + mem_names[i]); 182 + return PTR_ERR(drproc->mem[i].cpu_addr); 183 + } 184 + drproc->mem[i].bus_addr = res->start; 185 + drproc->mem[i].dev_addr = 186 + res->start & DA8XX_RPROC_LOCAL_ADDRESS_MASK; 187 + drproc->mem[i].size = resource_size(res); 188 + 189 + dev_dbg(dev, "memory %8s: bus addr %pa size 0x%x va %p da 0x%x\n", 190 + mem_names[i], &drproc->mem[i].bus_addr, 191 + drproc->mem[i].size, drproc->mem[i].cpu_addr, 192 + drproc->mem[i].dev_addr); 193 + } 194 + drproc->num_mems = num_mems; 195 + 196 + return 0; 197 + } 198 + 182 199 static int da8xx_rproc_probe(struct platform_device *pdev) 183 200 { 184 201 struct device *dev = &pdev->dev; ··· 243 184 return -EINVAL; 244 185 } 245 186 246 - bootreg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 187 + bootreg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 188 + "host1cfg"); 247 189 bootreg = devm_ioremap_resource(dev, bootreg_res); 248 190 if (IS_ERR(bootreg)) 249 191 return PTR_ERR(bootreg); 250 192 251 - chipsig_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 193 + chipsig_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 194 + "chipsig"); 252 195 chipsig = devm_ioremap_resource(dev, chipsig_res); 253 196 if (IS_ERR(chipsig)) 254 197 return PTR_ERR(chipsig); ··· 262 201 return PTR_ERR(dsp_clk); 263 202 } 264 203 204 + if (dev->of_node) { 205 + ret = of_reserved_mem_device_init(dev); 206 + if (ret) { 207 + dev_err(dev, "device does not have specific CMA pool: %d\n", 208 + ret); 209 + return ret; 210 + } 211 + } 212 + 265 213 rproc = rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name, 266 214 sizeof(*drproc)); 267 - if (!rproc) 268 - return -ENOMEM; 215 + if (!rproc) { 216 + ret = -ENOMEM; 217 + goto free_mem; 218 + } 269 219 270 220 drproc = rproc->priv; 271 221 drproc->rproc = rproc; 272 222 drproc->dsp_clk = dsp_clk; 273 223 rproc->has_iommu = false; 224 + 225 + ret = da8xx_rproc_get_internal_memories(pdev, drproc); 226 + if (ret) 227 + goto free_rproc; 274 228 275 229 platform_set_drvdata(pdev, rproc); 276 230 ··· 323 247 324 248 free_rproc: 325 249 rproc_free(rproc); 326 - 250 + free_mem: 251 + if (dev->of_node) 252 + of_reserved_mem_device_release(dev); 327 253 return ret; 328 254 } 329 255 ··· 333 255 { 334 256 struct rproc *rproc = platform_get_drvdata(pdev); 335 257 struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv; 258 + struct device *dev = &pdev->dev; 336 259 337 260 /* 338 261 * The devm subsystem might end up releasing things before ··· 344 265 345 266 rproc_del(rproc); 346 267 rproc_free(rproc); 268 + if (dev->of_node) 269 + of_reserved_mem_device_release(dev); 347 270 348 271 return 0; 349 272 } 273 + 274 + static const struct of_device_id davinci_rproc_of_match[] __maybe_unused = { 275 + { .compatible = "ti,da850-dsp", }, 276 + { /* sentinel */ }, 277 + }; 278 + MODULE_DEVICE_TABLE(of, davinci_rproc_of_match); 350 279 351 280 static struct platform_driver da8xx_rproc_driver = { 352 281 .probe = da8xx_rproc_probe, 353 282 .remove = da8xx_rproc_remove, 354 283 .driver = { 355 284 .name = "davinci-rproc", 285 + .of_match_table = of_match_ptr(davinci_rproc_of_match), 356 286 }, 357 287 }; 358 288
+426
drivers/remoteproc/imx_rproc.c
··· 1 + /* 2 + * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/err.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/kernel.h> 13 + #include <linux/mfd/syscon.h> 14 + #include <linux/module.h> 15 + #include <linux/of_address.h> 16 + #include <linux/of_device.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/regmap.h> 19 + #include <linux/remoteproc.h> 20 + 21 + #define IMX7D_SRC_SCR 0x0C 22 + #define IMX7D_ENABLE_M4 BIT(3) 23 + #define IMX7D_SW_M4P_RST BIT(2) 24 + #define IMX7D_SW_M4C_RST BIT(1) 25 + #define IMX7D_SW_M4C_NON_SCLR_RST BIT(0) 26 + 27 + #define IMX7D_M4_RST_MASK (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \ 28 + | IMX7D_SW_M4C_RST \ 29 + | IMX7D_SW_M4C_NON_SCLR_RST) 30 + 31 + #define IMX7D_M4_START (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \ 32 + | IMX7D_SW_M4C_RST) 33 + #define IMX7D_M4_STOP IMX7D_SW_M4C_NON_SCLR_RST 34 + 35 + /* Address: 0x020D8000 */ 36 + #define IMX6SX_SRC_SCR 0x00 37 + #define IMX6SX_ENABLE_M4 BIT(22) 38 + #define IMX6SX_SW_M4P_RST BIT(12) 39 + #define IMX6SX_SW_M4C_NON_SCLR_RST BIT(4) 40 + #define IMX6SX_SW_M4C_RST BIT(3) 41 + 42 + #define IMX6SX_M4_START (IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \ 43 + | IMX6SX_SW_M4C_RST) 44 + #define IMX6SX_M4_STOP IMX6SX_SW_M4C_NON_SCLR_RST 45 + #define IMX6SX_M4_RST_MASK (IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \ 46 + | IMX6SX_SW_M4C_NON_SCLR_RST \ 47 + | IMX6SX_SW_M4C_RST) 48 + 49 + #define IMX7D_RPROC_MEM_MAX 8 50 + 51 + /** 52 + * struct imx_rproc_mem - slim internal memory structure 53 + * @cpu_addr: MPU virtual address of the memory region 54 + * @sys_addr: Bus address used to access the memory region 55 + * @size: Size of the memory region 56 + */ 57 + struct imx_rproc_mem { 58 + void __iomem *cpu_addr; 59 + phys_addr_t sys_addr; 60 + size_t size; 61 + }; 62 + 63 + /* att flags */ 64 + /* M4 own area. Can be mapped at probe */ 65 + #define ATT_OWN BIT(1) 66 + 67 + /* address translation table */ 68 + struct imx_rproc_att { 69 + u32 da; /* device address (From Cortex M4 view)*/ 70 + u32 sa; /* system bus address */ 71 + u32 size; /* size of reg range */ 72 + int flags; 73 + }; 74 + 75 + struct imx_rproc_dcfg { 76 + u32 src_reg; 77 + u32 src_mask; 78 + u32 src_start; 79 + u32 src_stop; 80 + const struct imx_rproc_att *att; 81 + size_t att_size; 82 + }; 83 + 84 + struct imx_rproc { 85 + struct device *dev; 86 + struct regmap *regmap; 87 + struct rproc *rproc; 88 + const struct imx_rproc_dcfg *dcfg; 89 + struct imx_rproc_mem mem[IMX7D_RPROC_MEM_MAX]; 90 + struct clk *clk; 91 + }; 92 + 93 + static const struct imx_rproc_att imx_rproc_att_imx7d[] = { 94 + /* dev addr , sys addr , size , flags */ 95 + /* OCRAM_S (M4 Boot code) - alias */ 96 + { 0x00000000, 0x00180000, 0x00008000, 0 }, 97 + /* OCRAM_S (Code) */ 98 + { 0x00180000, 0x00180000, 0x00008000, ATT_OWN }, 99 + /* OCRAM (Code) - alias */ 100 + { 0x00900000, 0x00900000, 0x00020000, 0 }, 101 + /* OCRAM_EPDC (Code) - alias */ 102 + { 0x00920000, 0x00920000, 0x00020000, 0 }, 103 + /* OCRAM_PXP (Code) - alias */ 104 + { 0x00940000, 0x00940000, 0x00008000, 0 }, 105 + /* TCML (Code) */ 106 + { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, 107 + /* DDR (Code) - alias, first part of DDR (Data) */ 108 + { 0x10000000, 0x80000000, 0x0FFF0000, 0 }, 109 + 110 + /* TCMU (Data) */ 111 + { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, 112 + /* OCRAM (Data) */ 113 + { 0x20200000, 0x00900000, 0x00020000, 0 }, 114 + /* OCRAM_EPDC (Data) */ 115 + { 0x20220000, 0x00920000, 0x00020000, 0 }, 116 + /* OCRAM_PXP (Data) */ 117 + { 0x20240000, 0x00940000, 0x00008000, 0 }, 118 + /* DDR (Data) */ 119 + { 0x80000000, 0x80000000, 0x60000000, 0 }, 120 + }; 121 + 122 + static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { 123 + /* dev addr , sys addr , size , flags */ 124 + /* TCML (M4 Boot Code) - alias */ 125 + { 0x00000000, 0x007F8000, 0x00008000, 0 }, 126 + /* OCRAM_S (Code) */ 127 + { 0x00180000, 0x008F8000, 0x00004000, 0 }, 128 + /* OCRAM_S (Code) - alias */ 129 + { 0x00180000, 0x008FC000, 0x00004000, 0 }, 130 + /* TCML (Code) */ 131 + { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, 132 + /* DDR (Code) - alias, first part of DDR (Data) */ 133 + { 0x10000000, 0x80000000, 0x0FFF8000, 0 }, 134 + 135 + /* TCMU (Data) */ 136 + { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, 137 + /* OCRAM_S (Data) - alias? */ 138 + { 0x208F8000, 0x008F8000, 0x00004000, 0 }, 139 + /* DDR (Data) */ 140 + { 0x80000000, 0x80000000, 0x60000000, 0 }, 141 + }; 142 + 143 + static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { 144 + .src_reg = IMX7D_SRC_SCR, 145 + .src_mask = IMX7D_M4_RST_MASK, 146 + .src_start = IMX7D_M4_START, 147 + .src_stop = IMX7D_M4_STOP, 148 + .att = imx_rproc_att_imx7d, 149 + .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), 150 + }; 151 + 152 + static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { 153 + .src_reg = IMX6SX_SRC_SCR, 154 + .src_mask = IMX6SX_M4_RST_MASK, 155 + .src_start = IMX6SX_M4_START, 156 + .src_stop = IMX6SX_M4_STOP, 157 + .att = imx_rproc_att_imx6sx, 158 + .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), 159 + }; 160 + 161 + static int imx_rproc_start(struct rproc *rproc) 162 + { 163 + struct imx_rproc *priv = rproc->priv; 164 + const struct imx_rproc_dcfg *dcfg = priv->dcfg; 165 + struct device *dev = priv->dev; 166 + int ret; 167 + 168 + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, 169 + dcfg->src_mask, dcfg->src_start); 170 + if (ret) 171 + dev_err(dev, "Filed to enable M4!\n"); 172 + 173 + return ret; 174 + } 175 + 176 + static int imx_rproc_stop(struct rproc *rproc) 177 + { 178 + struct imx_rproc *priv = rproc->priv; 179 + const struct imx_rproc_dcfg *dcfg = priv->dcfg; 180 + struct device *dev = priv->dev; 181 + int ret; 182 + 183 + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, 184 + dcfg->src_mask, dcfg->src_stop); 185 + if (ret) 186 + dev_err(dev, "Filed to stop M4!\n"); 187 + 188 + return ret; 189 + } 190 + 191 + static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, 192 + int len, u64 *sys) 193 + { 194 + const struct imx_rproc_dcfg *dcfg = priv->dcfg; 195 + int i; 196 + 197 + /* parse address translation table */ 198 + for (i = 0; i < dcfg->att_size; i++) { 199 + const struct imx_rproc_att *att = &dcfg->att[i]; 200 + 201 + if (da >= att->da && da + len < att->da + att->size) { 202 + unsigned int offset = da - att->da; 203 + 204 + *sys = att->sa + offset; 205 + return 0; 206 + } 207 + } 208 + 209 + dev_warn(priv->dev, "Translation filed: da = 0x%llx len = 0x%x\n", 210 + da, len); 211 + return -ENOENT; 212 + } 213 + 214 + static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len) 215 + { 216 + struct imx_rproc *priv = rproc->priv; 217 + void *va = NULL; 218 + u64 sys; 219 + int i; 220 + 221 + if (len <= 0) 222 + return NULL; 223 + 224 + /* 225 + * On device side we have many aliases, so we need to convert device 226 + * address (M4) to system bus address first. 227 + */ 228 + if (imx_rproc_da_to_sys(priv, da, len, &sys)) 229 + return NULL; 230 + 231 + for (i = 0; i < IMX7D_RPROC_MEM_MAX; i++) { 232 + if (sys >= priv->mem[i].sys_addr && sys + len < 233 + priv->mem[i].sys_addr + priv->mem[i].size) { 234 + unsigned int offset = sys - priv->mem[i].sys_addr; 235 + /* __force to make sparse happy with type conversion */ 236 + va = (__force void *)(priv->mem[i].cpu_addr + offset); 237 + break; 238 + } 239 + } 240 + 241 + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va); 242 + 243 + return va; 244 + } 245 + 246 + static const struct rproc_ops imx_rproc_ops = { 247 + .start = imx_rproc_start, 248 + .stop = imx_rproc_stop, 249 + .da_to_va = imx_rproc_da_to_va, 250 + }; 251 + 252 + static int imx_rproc_addr_init(struct imx_rproc *priv, 253 + struct platform_device *pdev) 254 + { 255 + const struct imx_rproc_dcfg *dcfg = priv->dcfg; 256 + struct device *dev = &pdev->dev; 257 + struct device_node *np = dev->of_node; 258 + int a, b = 0, err, nph; 259 + 260 + /* remap required addresses */ 261 + for (a = 0; a < dcfg->att_size; a++) { 262 + const struct imx_rproc_att *att = &dcfg->att[a]; 263 + 264 + if (!(att->flags & ATT_OWN)) 265 + continue; 266 + 267 + if (b > IMX7D_RPROC_MEM_MAX) 268 + break; 269 + 270 + priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, 271 + att->sa, att->size); 272 + if (IS_ERR(priv->mem[b].cpu_addr)) { 273 + dev_err(dev, "devm_ioremap_resource failed\n"); 274 + err = PTR_ERR(priv->mem[b].cpu_addr); 275 + return err; 276 + } 277 + priv->mem[b].sys_addr = att->sa; 278 + priv->mem[b].size = att->size; 279 + b++; 280 + } 281 + 282 + /* memory-region is optional property */ 283 + nph = of_count_phandle_with_args(np, "memory-region", NULL); 284 + if (nph <= 0) 285 + return 0; 286 + 287 + /* remap optional addresses */ 288 + for (a = 0; a < nph; a++) { 289 + struct device_node *node; 290 + struct resource res; 291 + 292 + node = of_parse_phandle(np, "memory-region", a); 293 + err = of_address_to_resource(node, 0, &res); 294 + if (err) { 295 + dev_err(dev, "unable to resolve memory region\n"); 296 + return err; 297 + } 298 + 299 + if (b > IMX7D_RPROC_MEM_MAX) 300 + break; 301 + 302 + priv->mem[b].cpu_addr = devm_ioremap_resource(&pdev->dev, &res); 303 + if (IS_ERR(priv->mem[b].cpu_addr)) { 304 + dev_err(dev, "devm_ioremap_resource failed\n"); 305 + err = PTR_ERR(priv->mem[b].cpu_addr); 306 + return err; 307 + } 308 + priv->mem[b].sys_addr = res.start; 309 + priv->mem[b].size = resource_size(&res); 310 + b++; 311 + } 312 + 313 + return 0; 314 + } 315 + 316 + static int imx_rproc_probe(struct platform_device *pdev) 317 + { 318 + struct device *dev = &pdev->dev; 319 + struct device_node *np = dev->of_node; 320 + struct imx_rproc *priv; 321 + struct rproc *rproc; 322 + struct regmap_config config = { .name = "imx-rproc" }; 323 + const struct imx_rproc_dcfg *dcfg; 324 + struct regmap *regmap; 325 + int ret; 326 + 327 + regmap = syscon_regmap_lookup_by_phandle(np, "syscon"); 328 + if (IS_ERR(regmap)) { 329 + dev_err(dev, "failed to find syscon\n"); 330 + return PTR_ERR(regmap); 331 + } 332 + regmap_attach_dev(dev, regmap, &config); 333 + 334 + /* set some other name then imx */ 335 + rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops, 336 + NULL, sizeof(*priv)); 337 + if (!rproc) { 338 + ret = -ENOMEM; 339 + goto err; 340 + } 341 + 342 + dcfg = of_device_get_match_data(dev); 343 + if (!dcfg) 344 + return -EINVAL; 345 + 346 + priv = rproc->priv; 347 + priv->rproc = rproc; 348 + priv->regmap = regmap; 349 + priv->dcfg = dcfg; 350 + priv->dev = dev; 351 + 352 + dev_set_drvdata(dev, rproc); 353 + 354 + ret = imx_rproc_addr_init(priv, pdev); 355 + if (ret) { 356 + dev_err(dev, "filed on imx_rproc_addr_init\n"); 357 + goto err_put_rproc; 358 + } 359 + 360 + priv->clk = devm_clk_get(dev, NULL); 361 + if (IS_ERR(priv->clk)) { 362 + dev_err(dev, "Failed to get clock\n"); 363 + rproc_free(rproc); 364 + return PTR_ERR(priv->clk); 365 + } 366 + 367 + /* 368 + * clk for M4 block including memory. Should be 369 + * enabled before .start for FW transfer. 370 + */ 371 + ret = clk_prepare_enable(priv->clk); 372 + if (ret) { 373 + dev_err(&rproc->dev, "Failed to enable clock\n"); 374 + rproc_free(rproc); 375 + return ret; 376 + } 377 + 378 + ret = rproc_add(rproc); 379 + if (ret) { 380 + dev_err(dev, "rproc_add failed\n"); 381 + goto err_put_clk; 382 + } 383 + 384 + return ret; 385 + 386 + err_put_clk: 387 + clk_disable_unprepare(priv->clk); 388 + err_put_rproc: 389 + rproc_free(rproc); 390 + err: 391 + return ret; 392 + } 393 + 394 + static int imx_rproc_remove(struct platform_device *pdev) 395 + { 396 + struct rproc *rproc = platform_get_drvdata(pdev); 397 + struct imx_rproc *priv = rproc->priv; 398 + 399 + clk_disable_unprepare(priv->clk); 400 + rproc_del(rproc); 401 + rproc_free(rproc); 402 + 403 + return 0; 404 + } 405 + 406 + static const struct of_device_id imx_rproc_of_match[] = { 407 + { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d }, 408 + { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, 409 + {}, 410 + }; 411 + MODULE_DEVICE_TABLE(of, imx_rproc_of_match); 412 + 413 + static struct platform_driver imx_rproc_driver = { 414 + .probe = imx_rproc_probe, 415 + .remove = imx_rproc_remove, 416 + .driver = { 417 + .name = "imx-rproc", 418 + .of_match_table = imx_rproc_of_match, 419 + }, 420 + }; 421 + 422 + module_platform_driver(imx_rproc_driver); 423 + 424 + MODULE_LICENSE("GPL v2"); 425 + MODULE_DESCRIPTION("IMX6SX/7D remote processor control driver"); 426 + MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+2 -1
drivers/remoteproc/keystone_remoteproc.c
··· 410 410 if (ret) 411 411 goto free_rproc; 412 412 413 - ksproc->reset = devm_reset_control_get(dev, NULL); 413 + ksproc->reset = devm_reset_control_get_exclusive(dev, NULL); 414 414 if (IS_ERR(ksproc->reset)) { 415 415 ret = PTR_ERR(ksproc->reset); 416 416 goto free_rproc; ··· 505 505 { .compatible = "ti,k2hk-dsp", }, 506 506 { .compatible = "ti,k2l-dsp", }, 507 507 { .compatible = "ti,k2e-dsp", }, 508 + { .compatible = "ti,k2g-dsp", }, 508 509 { /* sentinel */ }, 509 510 }; 510 511 MODULE_DEVICE_TABLE(of, keystone_rproc_of_match);
+7 -4
drivers/remoteproc/qcom_adsp_pil.c
··· 38 38 const char *firmware_name; 39 39 int pas_id; 40 40 bool has_aggre2_clk; 41 + const char *ssr_name; 41 42 }; 42 43 43 44 struct qcom_adsp { ··· 73 72 size_t mem_size; 74 73 75 74 struct qcom_rproc_subdev smd_subdev; 75 + struct qcom_rproc_ssr ssr_subdev; 76 76 }; 77 77 78 78 static int adsp_load(struct rproc *rproc, const struct firmware *fw) ··· 268 266 regulator_set_load(adsp->cx_supply, 100000); 269 267 270 268 adsp->px_supply = devm_regulator_get(adsp->dev, "px"); 271 - if (IS_ERR(adsp->px_supply)) 272 - return PTR_ERR(adsp->px_supply); 273 - 274 - return 0; 269 + return PTR_ERR_OR_ZERO(adsp->px_supply); 275 270 } 276 271 277 272 static int adsp_request_irq(struct qcom_adsp *adsp, ··· 401 402 } 402 403 403 404 qcom_add_smd_subdev(rproc, &adsp->smd_subdev); 405 + qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); 404 406 405 407 ret = rproc_add(rproc); 406 408 if (ret) ··· 423 423 rproc_del(adsp->rproc); 424 424 425 425 qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); 426 + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 426 427 rproc_free(adsp->rproc); 427 428 428 429 return 0; ··· 434 433 .firmware_name = "adsp.mdt", 435 434 .pas_id = 1, 436 435 .has_aggre2_clk = false, 436 + .ssr_name = "lpass", 437 437 }; 438 438 439 439 static const struct adsp_data slpi_resource_init = { ··· 442 440 .firmware_name = "slpi.mdt", 443 441 .pas_id = 12, 444 442 .has_aggre2_clk = true, 443 + .ssr_name = "dsps", 445 444 }; 446 445 447 446 static const struct of_device_id adsp_of_match[] = {
+72 -1
drivers/remoteproc/qcom_common.c
··· 18 18 #include <linux/firmware.h> 19 19 #include <linux/kernel.h> 20 20 #include <linux/module.h> 21 + #include <linux/notifier.h> 21 22 #include <linux/remoteproc.h> 22 23 #include <linux/rpmsg/qcom_smd.h> 23 24 ··· 26 25 #include "qcom_common.h" 27 26 28 27 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev) 28 + #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev) 29 + 30 + static BLOCKING_NOTIFIER_HEAD(ssr_notifiers); 29 31 30 32 /** 31 33 * qcom_mdt_find_rsc_table() - provide dummy resource table for remoteproc ··· 55 51 56 52 smd->edge = qcom_smd_register_edge(smd->dev, smd->node); 57 53 58 - return IS_ERR(smd->edge) ? PTR_ERR(smd->edge) : 0; 54 + return PTR_ERR_OR_ZERO(smd->edge); 59 55 } 60 56 61 57 static void smd_subdev_remove(struct rproc_subdev *subdev) ··· 95 91 of_node_put(smd->node); 96 92 } 97 93 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev); 94 + 95 + /** 96 + * qcom_register_ssr_notifier() - register SSR notification handler 97 + * @nb: notifier_block to notify for restart notifications 98 + * 99 + * Returns 0 on success, negative errno on failure. 100 + * 101 + * This register the @notify function as handler for restart notifications. As 102 + * remote processors are stopped this function will be called, with the SSR 103 + * name passed as a parameter. 104 + */ 105 + int qcom_register_ssr_notifier(struct notifier_block *nb) 106 + { 107 + return blocking_notifier_chain_register(&ssr_notifiers, nb); 108 + } 109 + EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier); 110 + 111 + /** 112 + * qcom_unregister_ssr_notifier() - unregister SSR notification handler 113 + * @nb: notifier_block to unregister 114 + */ 115 + void qcom_unregister_ssr_notifier(struct notifier_block *nb) 116 + { 117 + blocking_notifier_chain_unregister(&ssr_notifiers, nb); 118 + } 119 + EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier); 120 + 121 + static int ssr_notify_start(struct rproc_subdev *subdev) 122 + { 123 + return 0; 124 + } 125 + 126 + static void ssr_notify_stop(struct rproc_subdev *subdev) 127 + { 128 + struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev); 129 + 130 + blocking_notifier_call_chain(&ssr_notifiers, 0, (void *)ssr->name); 131 + } 132 + 133 + /** 134 + * qcom_add_ssr_subdev() - register subdevice as restart notification source 135 + * @rproc: rproc handle 136 + * @ssr: SSR subdevice handle 137 + * @ssr_name: identifier to use for notifications originating from @rproc 138 + * 139 + * As the @ssr is registered with the @rproc SSR events will be sent to all 140 + * registered listeners in the system as the remoteproc is shut down. 141 + */ 142 + void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, 143 + const char *ssr_name) 144 + { 145 + ssr->name = ssr_name; 146 + 147 + rproc_add_subdev(rproc, &ssr->subdev, ssr_notify_start, ssr_notify_stop); 148 + } 149 + EXPORT_SYMBOL_GPL(qcom_add_ssr_subdev); 150 + 151 + /** 152 + * qcom_remove_ssr_subdev() - remove subdevice as restart notification source 153 + * @rproc: rproc handle 154 + * @ssr: SSR subdevice handle 155 + */ 156 + void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr) 157 + { 158 + rproc_remove_subdev(rproc, &ssr->subdev); 159 + } 160 + EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev); 98 161 99 162 MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver"); 100 163 MODULE_LICENSE("GPL v2");
+10
drivers/remoteproc/qcom_common.h
··· 12 12 struct qcom_smd_edge *edge; 13 13 }; 14 14 15 + struct qcom_rproc_ssr { 16 + struct rproc_subdev subdev; 17 + 18 + const char *name; 19 + }; 20 + 15 21 struct resource_table *qcom_mdt_find_rsc_table(struct rproc *rproc, 16 22 const struct firmware *fw, 17 23 int *tablesz); 18 24 19 25 void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd); 20 26 void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd); 27 + 28 + void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, 29 + const char *ssr_name); 30 + void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr); 21 31 22 32 #endif
+5 -1
drivers/remoteproc/qcom_q6v5_pil.c
··· 153 153 size_t mpss_size; 154 154 155 155 struct qcom_rproc_subdev smd_subdev; 156 + struct qcom_rproc_ssr ssr_subdev; 156 157 }; 157 158 158 159 static int q6v5_regulator_init(struct device *dev, struct reg_info *regs, ··· 868 867 869 868 static int q6v5_init_reset(struct q6v5 *qproc) 870 869 { 871 - qproc->mss_restart = devm_reset_control_get(qproc->dev, NULL); 870 + qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev, 871 + NULL); 872 872 if (IS_ERR(qproc->mss_restart)) { 873 873 dev_err(qproc->dev, "failed to acquire mss restart\n"); 874 874 return PTR_ERR(qproc->mss_restart); ··· 1040 1038 } 1041 1039 1042 1040 qcom_add_smd_subdev(rproc, &qproc->smd_subdev); 1041 + qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); 1043 1042 1044 1043 ret = rproc_add(rproc); 1045 1044 if (ret) ··· 1061 1058 rproc_del(qproc->rproc); 1062 1059 1063 1060 qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev); 1061 + qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev); 1064 1062 rproc_free(qproc->rproc); 1065 1063 1066 1064 return 0;
+22 -13
drivers/remoteproc/remoteproc_core.c
··· 794 794 { 795 795 struct rproc_subdev *subdev; 796 796 797 - list_for_each_entry(subdev, &rproc->subdevs, node) 797 + list_for_each_entry_reverse(subdev, &rproc->subdevs, node) 798 798 subdev->remove(subdev); 799 799 } 800 800 ··· 1119 1119 } 1120 1120 1121 1121 /** 1122 - * __rproc_boot() - boot a remote processor 1122 + * rproc_boot() - boot a remote processor 1123 1123 * @rproc: handle of a remote processor 1124 1124 * 1125 1125 * Boot a remote processor (i.e. load its firmware, power it on, ...). ··· 1129 1129 * 1130 1130 * Returns 0 on success, and an appropriate error value otherwise. 1131 1131 */ 1132 - static int __rproc_boot(struct rproc *rproc) 1132 + int rproc_boot(struct rproc *rproc) 1133 1133 { 1134 1134 const struct firmware *firmware_p; 1135 1135 struct device *dev; ··· 1179 1179 unlock_mutex: 1180 1180 mutex_unlock(&rproc->lock); 1181 1181 return ret; 1182 - } 1183 - 1184 - /** 1185 - * rproc_boot() - boot a remote processor 1186 - * @rproc: handle of a remote processor 1187 - */ 1188 - int rproc_boot(struct rproc *rproc) 1189 - { 1190 - return __rproc_boot(rproc); 1191 1182 } 1192 1183 EXPORT_SYMBOL(rproc_boot); 1193 1184 ··· 1360 1369 kfree(rproc); 1361 1370 } 1362 1371 1363 - static struct device_type rproc_type = { 1372 + static const struct device_type rproc_type = { 1364 1373 .name = "remoteproc", 1365 1374 .release = rproc_type_release, 1366 1375 }; ··· 1431 1440 rproc->dev.parent = dev; 1432 1441 rproc->dev.type = &rproc_type; 1433 1442 rproc->dev.class = &rproc_class; 1443 + rproc->dev.driver_data = rproc; 1434 1444 1435 1445 /* Assign a unique device index and name */ 1436 1446 rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL); ··· 1569 1577 list_del(&subdev->node); 1570 1578 } 1571 1579 EXPORT_SYMBOL(rproc_remove_subdev); 1580 + 1581 + /** 1582 + * rproc_get_by_child() - acquire rproc handle of @dev's ancestor 1583 + * @dev: child device to find ancestor of 1584 + * 1585 + * Returns the ancestor rproc instance, or NULL if not found. 1586 + */ 1587 + struct rproc *rproc_get_by_child(struct device *dev) 1588 + { 1589 + for (dev = dev->parent; dev; dev = dev->parent) { 1590 + if (dev->type == &rproc_type) 1591 + return dev->driver_data; 1592 + } 1593 + 1594 + return NULL; 1595 + } 1596 + EXPORT_SYMBOL(rproc_get_by_child); 1572 1597 1573 1598 /** 1574 1599 * rproc_report_crash() - rproc crash reporter function
-1
drivers/remoteproc/remoteproc_internal.h
··· 48 48 /* from remoteproc_core.c */ 49 49 void rproc_release(struct kref *kref); 50 50 irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 51 - int rproc_boot_nowait(struct rproc *rproc); 52 51 void rproc_vdev_release(struct kref *ref); 53 52 54 53 /* from remoteproc_virtio.c */
+4 -2
drivers/remoteproc/st_remoteproc.c
··· 212 212 int err; 213 213 214 214 if (ddata->config->sw_reset) { 215 - ddata->sw_reset = devm_reset_control_get(dev, "sw_reset"); 215 + ddata->sw_reset = devm_reset_control_get_exclusive(dev, 216 + "sw_reset"); 216 217 if (IS_ERR(ddata->sw_reset)) { 217 218 dev_err(dev, "Failed to get S/W Reset\n"); 218 219 return PTR_ERR(ddata->sw_reset); ··· 221 220 } 222 221 223 222 if (ddata->config->pwr_reset) { 224 - ddata->pwr_reset = devm_reset_control_get(dev, "pwr_reset"); 223 + ddata->pwr_reset = devm_reset_control_get_exclusive(dev, 224 + "pwr_reset"); 225 225 if (IS_ERR(ddata->pwr_reset)) { 226 226 dev_err(dev, "Failed to get Power Reset\n"); 227 227 return PTR_ERR(ddata->pwr_reset);
+9
drivers/soc/qcom/Kconfig
··· 1 1 # 2 2 # QCOM Soc drivers 3 3 # 4 + config QCOM_GLINK_SSR 5 + tristate "Qualcomm Glink SSR driver" 6 + depends on RPMSG 7 + depends on QCOM_RPROC_COMMON 8 + help 9 + Say y here to enable GLINK SSR support. The GLINK SSR driver 10 + implements the SSR protocol for notifying the remote processor about 11 + neighboring subsystems going up or down. 12 + 4 13 config QCOM_GSBI 5 14 tristate "QCOM General Serial Bus Interface" 6 15 depends on ARCH_QCOM
+1
drivers/soc/qcom/Makefile
··· 1 + obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o 1 2 obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o 2 3 obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o 3 4 obj-$(CONFIG_QCOM_PM) += spm.o
+2
include/linux/remoteproc.h
··· 510 510 }; 511 511 512 512 struct rproc *rproc_get_by_phandle(phandle phandle); 513 + struct rproc *rproc_get_by_child(struct device *dev); 514 + 513 515 struct rproc *rproc_alloc(struct device *dev, const char *name, 514 516 const struct rproc_ops *ops, 515 517 const char *firmware, int len);
+22
include/linux/remoteproc/qcom_rproc.h
··· 1 + #ifndef __QCOM_RPROC_H__ 2 + #define __QCOM_RPROC_H__ 3 + 4 + struct notifier_block; 5 + 6 + #if IS_ENABLED(CONFIG_QCOM_RPROC_COMMON) 7 + 8 + int qcom_register_ssr_notifier(struct notifier_block *nb); 9 + void qcom_unregister_ssr_notifier(struct notifier_block *nb); 10 + 11 + #else 12 + 13 + static inline int qcom_register_ssr_notifier(struct notifier_block *nb) 14 + { 15 + return 0; 16 + } 17 + 18 + static inline void qcom_unregister_ssr_notifier(struct notifier_block *nb) {} 19 + 20 + #endif 21 + 22 + #endif