]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
zynqmp: pm: Add SiP call to obtain PM callback data
authorSoren Brinkmann <soren.brinkmann@xilinx.com>
Fri, 30 Sep 2016 21:24:25 +0000 (14:24 -0700)
committerSoren Brinkmann <soren.brinkmann@xilinx.com>
Wed, 16 Nov 2016 23:55:58 +0000 (15:55 -0800)
The callback IRQ is delivered to the NS OS. Provide an interface to
allow the NS OS to obtain the callback data from the secure HW.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
plat/xilinx/zynqmp/pm_service/pm_api_sys.c
plat/xilinx/zynqmp/pm_service/pm_api_sys.h
plat/xilinx/zynqmp/pm_service/pm_ipi.c
plat/xilinx/zynqmp/pm_service/pm_ipi.h
plat/xilinx/zynqmp/pm_service/pm_svc_main.c

index c7b8b9a7de07cf998490a5c24a4a4c39f18eb62a..15e12fa8e7a10466b136b637047af7581ccf34eb 100644 (file)
@@ -557,3 +557,16 @@ enum pm_ret_status pm_get_chipid(uint32_t *value)
        PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
        return pm_ipi_send_sync(primary_proc, payload, value, 2);
 }
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ *
+ * Read value from ipi buffer response buffer.
+ */
+void pm_get_callbackdata(uint32_t *data, size_t count)
+{
+
+       pm_ipi_buff_read_callb(data, count);
+       pm_ipi_irq_clear();
+}
index 8cbd13b2f54b99f5cbe3c5c0a27817d443934998..7e229488fd3b3439870c4392ec3e6b1e6db39155 100644 (file)
@@ -116,5 +116,6 @@ enum pm_ret_status pm_fpga_load(uint32_t address_high,
 enum pm_ret_status pm_fpga_get_status(unsigned int *value);
 
 enum pm_ret_status pm_get_chipid(uint32_t *value);
+void pm_get_callbackdata(uint32_t *data, size_t count);
 
 #endif /* _PM_API_SYS_H_ */
index df3b854d83ef2a1b6a06ae7a19c6f65cee36f590..9148f90942dfc20ef4878f4ecb20f8e9cb837437 100644 (file)
@@ -56,6 +56,8 @@
 #define IPI_BUFFER_TARGET_PL_3_OFFSET  0x180U
 #define IPI_BUFFER_TARGET_PMU_OFFSET   0x1C0U
 
+#define IPI_BUFFER_MAX_WORDS   8
+
 #define IPI_BUFFER_REQ_OFFSET  0x0U
 #define IPI_BUFFER_RESP_OFFSET 0x20U
 
@@ -217,6 +219,29 @@ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
        return mmio_read_32(buffer_base);
 }
 
+/**
+ * pm_ipi_buff_read_callb() - Reads IPI response after PMU has handled interrupt
+ * @value      Used to return value from IPI buffer element (optional)
+ * @count      Number of values to return in @value
+ *
+ * @return     Returns status, either success or error+reason
+ */
+void pm_ipi_buff_read_callb(unsigned int *value, size_t count)
+{
+       size_t i;
+       uintptr_t buffer_base = IPI_BUFFER_PMU_BASE +
+                               IPI_BUFFER_TARGET_APU_OFFSET +
+                               IPI_BUFFER_REQ_OFFSET;
+
+       if (count > IPI_BUFFER_MAX_WORDS)
+               count = IPI_BUFFER_MAX_WORDS;
+
+       for (i = 0; i <= count; i++) {
+               *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
+               value++;
+       }
+}
+
 /**
  * pm_ipi_send_sync() - Sends IPI request to the PMU
  * @proc       Pointer to the processor who is initiating request
@@ -258,3 +283,8 @@ void pm_ipi_irq_disable(void)
 {
        mmio_write_32(IPI_APU_IDR, IPI_APU_IXR_PMU_0_MASK);
 }
+
+void pm_ipi_irq_clear(void)
+{
+       mmio_write_32(IPI_APU_ISR, IPI_APU_IXR_PMU_0_MASK);
+}
index fefe89ab7c943e90d6f07451241266d82b78a6a6..b314b80aeef7b8d7d50b73fbf117f23aaf7443f3 100644 (file)
@@ -40,7 +40,9 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
 enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
                                    uint32_t payload[PAYLOAD_ARG_CNT],
                                    unsigned int *value, size_t count);
+void pm_ipi_buff_read_callb(unsigned int *value, size_t count);
 void pm_ipi_irq_enable(void);
 void pm_ipi_irq_disable(void);
+void pm_ipi_irq_clear(void);
 
 #endif /* _PM_IPI_H_ */
index 8a4bba617beb5c0b8c1c5932514448d6168074ba..036ed8a20299608a88a85db2e8d0e67f4f5d6a7a 100644 (file)
@@ -42,6 +42,8 @@
 #include "pm_ipi.h"
 #include "../zynqmp_private.h"
 
+#define PM_GET_CALLBACK_DATA   0xa01
+
 /* 0 - UP, !0 - DOWN */
 static int32_t pm_down = !0;
 
@@ -257,6 +259,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
                         result[1]);
        }
 
+       case PM_GET_CALLBACK_DATA:
+       {
+               uint32_t result[4];
+
+               pm_get_callbackdata(result, sizeof(result));
+               SMC_RET2(handle,
+                        (uint64_t)result[0] | ((uint64_t)result[1] << 32),
+                        (uint64_t)result[2] | ((uint64_t)result[3] << 32));
+       }
+
        default:
                WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
                SMC_RET1(handle, SMC_UNK);