]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/commitdiff
remoteproc/pru: Introduce new vendor interrupt resource for K3 AM65x SoCs
authorSuman Anna <s-anna@ti.com>
Sat, 28 Apr 2018 19:37:33 +0000 (14:37 -0500)
committerSuman Anna <s-anna@ti.com>
Mon, 25 Feb 2019 19:31:39 +0000 (13:31 -0600)
The PRU-ICSS IP present within K3 AM65x SoCs, commonly called ICSSG, has
an INTC that supports more System Events (160 vs 64), more Interrupt
Channels and Host Interrupts (20 vs 10) compared to the current generation
PRUSS INTC instances. The current custom vendor interrupt resource
configuration used by the pru_rproc driver is not adequate to support
this ICSSG INTC.

Add a new version of the custom vendor interrupt resource named
fw_rsc_custom_intrmap_k3 and enhance the pru_handle_vendor_intrmap()
function to add support for configuring this newer INTC sub-module.
This new resource structure is a revised version of the existing
fw_rsc_custom_intrmap resource, with additional fields for the
increased number of channels. Support for both resource types is
provided through the PRUSS_RSC_INTRS vendor resource type and
distinguished using a version field in the sub_type.

Signed-off-by: Suman Anna <s-anna@ti.com>
drivers/remoteproc/pru_rproc.c
drivers/remoteproc/pru_rproc.h

index 0d5dfda6c8dd0fa6d9b9cd065b00ad21b2ba5c2d..9857715faaba3dad466759d27c1a110ddb0b01a2 100644 (file)
@@ -739,22 +739,47 @@ static int pru_handle_vendor_intrmap(struct rproc *rproc,
        struct pru_rproc *pru = rproc->priv;
        struct pruss *pruss = pru->pruss;
        struct pruss_event_chnl *event_chnl_map;
-       struct fw_rsc_pruss_intrmap *intr_rsc =
-               (struct fw_rsc_pruss_intrmap *)rsc->data;
+       struct fw_rsc_pruss_intrmap *intr_rsc0;
+       struct fw_rsc_pruss_intrmap_k3 *intr_rsc1;
        int i, ret;
+       u32 event_chnl_map_da, event_chnl_map_size;
        s8 sys_evt, chnl, intr_no;
+       s8 *chnl_host_intr_map;
+       u8 max_system_events, max_pru_channels, max_pru_host_ints;
 
-       dev_dbg(dev, "version %d event_chnl_map_size %d event_chnl_map_addr 0x%x\n",
-               rsc->u.st.st_ver, intr_rsc->event_chnl_map_size,
-               intr_rsc->event_chnl_map_addr);
-
-       if (rsc->u.st.st_ver != 0) {
-               dev_err(dev, "only PRU interrupt resource version 0 supported\n");
+       if (rsc->u.st.st_ver != 0 && rsc->u.st.st_ver != 1) {
+               dev_err(dev, "only PRU interrupt resource versions 0 and 1 are supported\n");
                return -EINVAL;
        }
 
-       if (intr_rsc->event_chnl_map_size < 0 ||
-           intr_rsc->event_chnl_map_size >= MAX_PRU_SYS_EVENTS) {
+       if (!rsc->u.st.st_ver) {
+               intr_rsc0 = (struct fw_rsc_pruss_intrmap *)rsc->data;
+               event_chnl_map_da = intr_rsc0->event_chnl_map_addr;
+               event_chnl_map_size = intr_rsc0->event_chnl_map_size;
+               chnl_host_intr_map = intr_rsc0->chnl_host_intr_map;
+               max_system_events = MAX_PRU_SYS_EVENTS;
+               max_pru_channels = MAX_PRU_CHANNELS;
+               max_pru_host_ints = MAX_PRU_HOST_INT;
+
+               dev_dbg(dev, "version %d event_chnl_map_size %d event_chnl_map_da 0x%x\n",
+                       rsc->u.st.st_ver, intr_rsc0->event_chnl_map_size,
+                       event_chnl_map_da);
+       } else {
+               intr_rsc1 = (struct fw_rsc_pruss_intrmap_k3 *)rsc->data;
+               event_chnl_map_da = intr_rsc1->event_chnl_map_addr;
+               event_chnl_map_size = intr_rsc1->event_chnl_map_size;
+               chnl_host_intr_map = intr_rsc1->chnl_host_intr_map;
+               max_system_events = MAX_PRU_SYS_EVENTS_K3;
+               max_pru_channels = MAX_PRU_CHANNELS_K3;
+               max_pru_host_ints = MAX_PRU_HOST_INT_K3;
+
+               dev_dbg(dev, "version %d event_chnl_map_size %d event_chnl_map_da 0x%x\n",
+                       rsc->u.st.st_ver, intr_rsc1->event_chnl_map_size,
+                       event_chnl_map_da);
+       }
+
+       if (event_chnl_map_size < 0 ||
+           event_chnl_map_size >= max_system_events) {
                dev_err(dev, "PRU interrupt resource has more events than present on hardware\n");
                return -EINVAL;
        }
@@ -763,8 +788,8 @@ static int pru_handle_vendor_intrmap(struct rproc *rproc,
         * XXX: The event_chnl_map_addr mapping is currently a pointer in device
         * memory, evaluate if this needs to be directly in firmware file.
         */
-       event_chnl_map = pru_d_da_to_va(pru, intr_rsc->event_chnl_map_addr,
-                                       intr_rsc->event_chnl_map_size *
+       event_chnl_map = pru_d_da_to_va(pru, event_chnl_map_da,
+                                       event_chnl_map_size *
                                        sizeof(*event_chnl_map));
        if (!event_chnl_map) {
                dev_err(dev, "PRU interrupt resource has inadequate event_chnl_map configuration\n");
@@ -779,15 +804,15 @@ static int pru_handle_vendor_intrmap(struct rproc *rproc,
                pru->intc_config.ch_to_host[i] = -1;
 
        /* parse and fill in system event to interrupt channel mapping */
-       for (i = 0; i < intr_rsc->event_chnl_map_size; i++) {
+       for (i = 0; i < event_chnl_map_size; i++) {
                sys_evt = event_chnl_map[i].event;
                chnl = event_chnl_map[i].chnl;
 
-               if (sys_evt < 0 || sys_evt >= MAX_PRU_SYS_EVENTS) {
+               if (sys_evt < 0 || sys_evt >= max_system_events) {
                        dev_err(dev, "[%d] bad sys event %d\n", i, sys_evt);
                        return -EINVAL;
                }
-               if (chnl < 0 || chnl >= MAX_PRU_CHANNELS) {
+               if (chnl < 0 || chnl >= max_pru_channels) {
                        dev_err(dev, "[%d] bad channel value %d\n", i, chnl);
                        return -EINVAL;
                }
@@ -797,14 +822,14 @@ static int pru_handle_vendor_intrmap(struct rproc *rproc,
        }
 
        /* parse and handle interrupt channel-to-host interrupt mapping */
-       for (i = 0; i < MAX_PRU_CHANNELS; i++) {
-               intr_no = intr_rsc->chnl_host_intr_map[i];
+       for (i = 0; i < max_pru_channels; i++) {
+               intr_no = chnl_host_intr_map[i];
                if (intr_no < 0) {
                        dev_dbg(dev, "skip intr mapping for chnl %d\n", i);
                        continue;
                }
 
-               if (intr_no >= MAX_PRU_HOST_INT) {
+               if (intr_no >= max_pru_host_ints) {
                        dev_err(dev, "bad intr mapping for chnl %d, intr_no %d\n",
                                i, intr_no);
                        return -EINVAL;
index 9cfe399b702a6e6da3d59feca58347ac8316489f..41d48cd1f60d8e84d529a4f235ae8d267fc22817 100644 (file)
@@ -62,4 +62,31 @@ struct fw_rsc_pruss_intrmap {
        u32 event_chnl_map_addr;
 };
 
+/**
+ * struct fw_rsc_pruss_intrmap_k3 - K3 custom resource to define PRU interrupts
+ * @chnl_host_intr_map: array of PRU channels to host interrupt mappings
+ * @event_chnl_map_size: number of event_channel mappings defined in
+ *                      @event_chnl_map_addr
+ * @event_chnl_map_addr: PRU device address of pointer to array of events to
+ *                      channel mappings (struct pruss_event_chnl elements)
+ *
+ * PRU system events are mapped to channels, and these channels are mapped
+ * to host interrupts. Events can be mapped to channels in a one-to-one or
+ * many-to-one ratio (multiple events per channel), and channels can be
+ * mapped to host interrupts in a one-to-one or many-to-one ratio (multiple
+ * channels per interrupt).
+ *
+ * This structure needs to be used using PRU vendor interrupt resource version
+ * number 1. This structure is to be used with firmwares dealing with the
+ * additional host interrupts on ICSSG IP instances. The firmwares for PRU
+ * cores on ICSSG can get away with the standard version (if not dealing with
+ * Task Manager), but the firmwares for RTU cores would definitely need this
+ * for mapping to the corresponding higher host interrupts.
+ */
+struct fw_rsc_pruss_intrmap_k3 {
+       s8 chnl_host_intr_map[20];
+       u32 event_chnl_map_size;
+       u32 event_chnl_map_addr;
+};
+
 #endif /* _PRU_RPROC_H_ */