Merge tag 'rproc-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 May 2021 18:13:33 +0000 (11:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 May 2021 18:13:33 +0000 (11:13 -0700)
Pull remoteproc updates from Bjorn Andersson:
 "This adds support to the remoteproc core for detaching Linux from a
  running remoteproc, e.g. to reboot Linux while leaving the remoteproc
  running, and it enable this support in the stm32 remoteproc driver.

  It also introduces a property for memory carveouts to track if they
  are iomem or system ram, to enable proper handling of the differences.

  The imx_rproc received a number of fixes and improvements, in
  particular support for attaching to already running remote processors
  and i.MX8MQ and i.MX8MM support.

  The Qualcomm wcss driver gained support for starting and stopping the
  wireless subsystem on QCS404, when not using the TrustZone-based
  validator/loader.

  Finally it brings a few fixes to the TI PRU and to the firmware loader
  for the Qualcomm modem subsystem drivers"

* tag 'rproc-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc: (53 commits)
  remoteproc: stm32: add capability to detach
  dt-bindings: remoteproc: stm32-rproc: add new mailbox channel for detach
  remoteproc: imx_rproc: support remote cores booted before Linux Kernel
  remoteproc: imx_rproc: move memory parsing to rproc_ops
  remoteproc: imx_rproc: enlarge IMX7D_RPROC_MEM_MAX
  remoteproc: imx_rproc: add missing of_node_put
  remoteproc: imx_rproc: fix build error without CONFIG_MAILBOX
  remoteproc: qcom: wcss: Remove unnecessary PTR_ERR()
  remoteproc: qcom: wcss: Fix wrong pointer passed to PTR_ERR()
  remoteproc: qcom: pas: Add modem support for SDX55
  dt-bindings: remoteproc: qcom: pas: Add binding for SDX55
  remoteproc: qcom: wcss: Fix return value check in q6v5_wcss_init_mmio()
  remoteproc: pru: Fix and cleanup firmware interrupt mapping logic
  remoteproc: pru: Fix wrong success return value for fw events
  remoteproc: pru: Fixup interrupt-parent logic for fw events
  remoteproc: qcom: wcnss: Allow specifying firmware-name
  remoteproc: qcom: wcss: explicitly request exclusive reset control
  remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404
  dt-bindings: remoteproc: qcom: Add Q6V5 Modem PIL binding for QCS404
  remoteproc: qcom: wcss: populate hardcoded param using driver data
  ...

1  2 
drivers/remoteproc/pru_rproc.c

@@@ -244,8 -244,8 +244,8 @@@ static int pru_rproc_debug_ss_get(void 
  
        return 0;
  }
- DEFINE_SIMPLE_ATTRIBUTE(pru_rproc_debug_ss_fops, pru_rproc_debug_ss_get,
-                       pru_rproc_debug_ss_set, "%llu\n");
+ DEFINE_DEBUGFS_ATTRIBUTE(pru_rproc_debug_ss_fops, pru_rproc_debug_ss_get,
+                        pru_rproc_debug_ss_set, "%llu\n");
  
  /*
   * Create PRU-specific debugfs entries
@@@ -266,12 -266,17 +266,17 @@@ static void pru_rproc_create_debug_entr
  
  static void pru_dispose_irq_mapping(struct pru_rproc *pru)
  {
-       while (pru->evt_count--) {
+       if (!pru->mapped_irq)
+               return;
+       while (pru->evt_count) {
+               pru->evt_count--;
                if (pru->mapped_irq[pru->evt_count] > 0)
                        irq_dispose_mapping(pru->mapped_irq[pru->evt_count]);
        }
  
        kfree(pru->mapped_irq);
+       pru->mapped_irq = NULL;
  }
  
  /*
@@@ -284,7 -289,7 +289,7 @@@ static int pru_handle_intrmap(struct rp
        struct pru_rproc *pru = rproc->priv;
        struct pru_irq_rsc *rsc = pru->pru_interrupt_map;
        struct irq_fwspec fwspec;
-       struct device_node *irq_parent;
+       struct device_node *parent, *irq_parent;
        int i, ret = 0;
  
        /* not having pru_interrupt_map is not an error */
        pru->evt_count = rsc->num_evts;
        pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int),
                                  GFP_KERNEL);
-       if (!pru->mapped_irq)
+       if (!pru->mapped_irq) {
+               pru->evt_count = 0;
                return -ENOMEM;
+       }
  
        /*
         * parse and fill in system event to interrupt channel and
-        * channel-to-host mapping
+        * channel-to-host mapping. The interrupt controller to be used
+        * for these mappings for a given PRU remoteproc is always its
+        * corresponding sibling PRUSS INTC node.
         */
-       irq_parent = of_irq_find_parent(pru->dev->of_node);
+       parent = of_get_parent(dev_of_node(pru->dev));
+       if (!parent) {
+               kfree(pru->mapped_irq);
+               pru->mapped_irq = NULL;
+               pru->evt_count = 0;
+               return -ENODEV;
+       }
+       irq_parent = of_get_child_by_name(parent, "interrupt-controller");
+       of_node_put(parent);
        if (!irq_parent) {
                kfree(pru->mapped_irq);
+               pru->mapped_irq = NULL;
+               pru->evt_count = 0;
                return -ENODEV;
        }
  
  
                pru->mapped_irq[i] = irq_create_fwspec_mapping(&fwspec);
                if (!pru->mapped_irq[i]) {
-                       dev_err(dev, "failed to get virq\n");
-                       ret = pru->mapped_irq[i];
+                       dev_err(dev, "failed to get virq for fw mapping %d: event %d chnl %d host %d\n",
+                               i, fwspec.param[0], fwspec.param[1],
+                               fwspec.param[2]);
+                       ret = -EINVAL;
                        goto map_fail;
                }
        }
+       of_node_put(irq_parent);
  
        return ret;
  
  map_fail:
        pru_dispose_irq_mapping(pru);
+       of_node_put(irq_parent);
  
        return ret;
  }
@@@ -387,8 -411,7 +411,7 @@@ static int pru_rproc_stop(struct rproc 
        pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
  
        /* dispose irq mapping - new firmware can provide new mapping */
-       if (pru->mapped_irq)
-               pru_dispose_irq_mapping(pru);
+       pru_dispose_irq_mapping(pru);
  
        return 0;
  }
@@@ -450,24 -473,6 +473,24 @@@ static void *pru_i_da_to_va(struct pru_
        if (len == 0)
                return NULL;
  
 +      /*
 +       * GNU binutils do not support multiple address spaces. The GNU
 +       * linker's default linker script places IRAM at an arbitrary high
 +       * offset, in order to differentiate it from DRAM. Hence we need to
 +       * strip the artificial offset in the IRAM addresses coming from the
 +       * ELF file.
 +       *
 +       * The TI proprietary linker would never set those higher IRAM address
 +       * bits anyway. PRU architecture limits the program counter to 16-bit
 +       * word-address range. This in turn corresponds to 18-bit IRAM
 +       * byte-address range for ELF.
 +       *
 +       * Two more bits are added just in case to make the final 20-bit mask.
 +       * Idea is to have a safeguard in case TI decides to add banking
 +       * in future SoCs.
 +       */
 +      da &= 0xfffff;
 +
        if (da >= PRU_IRAM_DA &&
            da + len <= PRU_IRAM_DA + pru->mem_regions[PRU_IOMEM_IRAM].size) {
                offset = da - PRU_IRAM_DA;
   * core for any PRU client drivers. The PRU Instruction RAM access is restricted
   * only to the PRU loader code.
   */
- static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+ static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
  {
        struct pru_rproc *pru = rproc->priv;
  
@@@ -603,7 -608,7 +626,7 @@@ pru_rproc_load_elf_segments(struct rpro
                        break;
                }
  
 -              if (pru->data->is_k3 && is_iram) {
 +              if (pru->data->is_k3) {
                        ret = pru_rproc_memcpy(ptr, elf_data + phdr->p_offset,
                                               filesz);
                        if (ret) {