]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blobdiff - lib/remoteproc/drivers/zynqmp_remoteproc_a53.c
Remove remoteproc_plat from ZynqMP R5 rproc driver
[processor-sdk/open-amp.git] / lib / remoteproc / drivers / zynqmp_remoteproc_a53.c
index 83a9c7e4062dc00d77838a1b1d0ae2dbdbac7a90..92a7fa1b7bebb7fc6069767eb8ff06c10ab74c64 100644 (file)
  *
  **************************************************************************/
 
+#include <errno.h>
+#include <string.h>
+#include "metal/io.h"
+#include "metal/device.h"
+#include "metal/utilities.h"
+#include "metal/atomic.h"
+#include "metal/irq.h"
+#include "metal/alloc.h"
 #include "openamp/hil.h"
-#include "machine.h"
+#include "openamp/virtqueue.h"
+
+/* IPI REGs OFFSET */
+#define IPI_TRIG_OFFSET          0x00000000    /* IPI trigger register offset */
+#define IPI_OBS_OFFSET           0x00000004    /* IPI observation register offset */
+#define IPI_ISR_OFFSET           0x00000010    /* IPI interrupt status register offset */
+#define IPI_IMR_OFFSET           0x00000014    /* IPI interrupt mask register offset */
+#define IPI_IER_OFFSET           0x00000018    /* IPI interrupt enable register offset */
+#define IPI_IDR_OFFSET           0x0000001C    /* IPI interrupt disable register offset */
+
+#define _rproc_wait() asm volatile("wfi")
 
 /* -- FIX ME: ipi info is to be defined -- */
 struct ipi_info {
-       uint32_t ipi_base_addr;
+       const char *name;
+       const char *bus_name;
+       struct metal_device *dev;
+       struct metal_io_region *io;
+       metal_phys_addr_t paddr;
        uint32_t ipi_chn_mask;
+       int need_reg;
+       atomic_int sync;
 };
 
 /*--------------------------- Declare Functions ------------------------ */
 static int _enable_interrupt(struct proc_vring *vring_hw);
-static void _notify(int cpu_id, struct proc_intr *intr_info);
-static int _boot_cpu(int cpu_id, unsigned int load_addr);
-static void _shutdown_cpu(int cpu_id);
-static void _ipi_handler(int vect_id, void *data);
-static void _ipi_handler_deinit(int vect_id, void *data);
-static void _reg_ipi_after_deinit(struct proc_vring *vring_hw);
+static void _notify(struct hil_proc *proc, struct proc_intr *intr_info);
+static int _boot_cpu(struct hil_proc *proc, unsigned int load_addr);
+static void _shutdown_cpu(struct hil_proc *proc);
+static int _poll(struct hil_proc *proc, int nonblock);
+static int _initialize(struct hil_proc *proc);
+static void _release(struct hil_proc *proc);
+
+static int _ipi_handler(int vect_id, void *data);
 
 /*--------------------------- Globals ---------------------------------- */
-struct hil_platform_ops proc_ops = {
-       .enable_interrupt = _enable_interrupt,
-       .reg_ipi_after_deinit = _reg_ipi_after_deinit,
-       .notify = _notify,
-       .boot_cpu = _boot_cpu,
-       .shutdown_cpu = _shutdown_cpu,
+struct hil_platform_ops zynqmp_r5_a53_proc_ops = {
+       .enable_interrupt     = _enable_interrupt,
+       .notify               = _notify,
+       .boot_cpu             = _boot_cpu,
+       .shutdown_cpu         = _shutdown_cpu,
+       .poll                 = _poll,
+       .initialize    = _initialize,
+       .release    = _release,
 };
 
-/* Extern functions defined out from OpenAMP lib */
-extern void ipi_enable_interrupt(unsigned int vector);
-extern void ipi_isr(int vect_id, void *data);
-
-/* static variables */
-static struct ipi_info saved_ipi_info;
-
-/*------------------- Extern variable -----------------------------------*/
-extern struct hil_proc proc_table[];
-extern const int proc_table_size;
-
-void _ipi_handler(int vect_id, void *data)
+int _ipi_handler(int vect_id, void *data)
 {
        (void) vect_id;
        struct proc_vring *vring_hw = (struct proc_vring *)(data);
-       struct ipi_info *chn_ipi_info =
+       struct ipi_info *ipi =
                (struct ipi_info *)(vring_hw->intr_info.data);
-       unsigned int ipi_base_addr = chn_ipi_info->ipi_base_addr;
-       unsigned int ipi_intr_status =
-           (unsigned int)HIL_MEM_READ32(ipi_base_addr + IPI_ISR_OFFSET);
-       if (ipi_intr_status & chn_ipi_info->ipi_chn_mask) {
-               platform_dcache_all_flush();
-               platform_isr(vect_id, data);
-               HIL_MEM_WRITE32((ipi_base_addr + IPI_ISR_OFFSET),
-                               chn_ipi_info->ipi_chn_mask);
-       }
-}
-
-void _ipi_handler_deinit(int vect_id, void *data)
-{
-       (void) vect_id;
-       struct ipi_info *chn_ipi_info =
-               (struct ipi_info *)(data);
-       unsigned int ipi_base_addr = chn_ipi_info->ipi_base_addr;
+       struct metal_io_region *io = ipi->io;
        unsigned int ipi_intr_status =
-           (unsigned int)HIL_MEM_READ32(ipi_base_addr + IPI_ISR_OFFSET);
-       if (ipi_intr_status & chn_ipi_info->ipi_chn_mask) {
-               HIL_MEM_WRITE32((ipi_base_addr + IPI_ISR_OFFSET),
-                               chn_ipi_info->ipi_chn_mask);
+           (unsigned int)metal_io_read32(io, IPI_ISR_OFFSET);
+       if (ipi_intr_status & ipi->ipi_chn_mask) {
+               atomic_flag_clear(&ipi->sync);
+               metal_io_write32(io, IPI_ISR_OFFSET,
+                               ipi->ipi_chn_mask);
+               return 0;
        }
-       return;
+       return -1;
 }
 
 static int _enable_interrupt(struct proc_vring *vring_hw)
 {
-       struct ipi_info *chn_ipi_info =
+       struct ipi_info *ipi =
            (struct ipi_info *)(vring_hw->intr_info.data);
-       unsigned int ipi_base_addr = chn_ipi_info->ipi_base_addr;
+       struct metal_io_region *io = ipi->io;
 
-       if (vring_hw->intr_info.vect_id == 0xFFFFFFFF) {
+       if (!ipi->need_reg) {
                return 0;
        }
 
        /* Register ISR */
-       env_register_isr_shared(vring_hw->intr_info.vect_id,
-                        vring_hw, _ipi_handler, "remoteproc_a53", 1);
+       metal_irq_register(vring_hw->intr_info.vect_id, _ipi_handler,
+                               vring_hw->intr_info.dev, vring_hw);
        /* Enable IPI interrupt */
-       env_enable_interrupt(vring_hw->intr_info.vect_id,
-                            vring_hw->intr_info.priority,
-                            vring_hw->intr_info.trigger_type);
-       HIL_MEM_WRITE32((ipi_base_addr + IPI_IER_OFFSET),
-               chn_ipi_info->ipi_chn_mask);
+       metal_irq_enable(vring_hw->intr_info.vect_id);
+       metal_io_write32(io, IPI_IER_OFFSET, ipi->ipi_chn_mask);
        return 0;
 }
 
-/* In case there is an interrupt received after deinit. */
-void _reg_ipi_after_deinit(struct proc_vring *vring_hw)
+static void _notify(struct hil_proc *proc, struct proc_intr *intr_info)
 {
-       struct ipi_info *chn_ipi_info =
-           (struct ipi_info *)(vring_hw->intr_info.data);
 
-       if (vring_hw->intr_info.vect_id == 0xFFFFFFFF)
+       (void)proc;
+       struct ipi_info *ipi = (struct ipi_info *)(intr_info->data);
+       if (ipi == NULL)
                return;
-       saved_ipi_info.ipi_base_addr = chn_ipi_info->ipi_base_addr;
-       saved_ipi_info.ipi_chn_mask = chn_ipi_info->ipi_chn_mask;
-
-       env_update_isr(vring_hw->intr_info.vect_id, &saved_ipi_info,
-                    _ipi_handler_deinit,
-                    "remoteproc_a53", 1);
-}
 
-void _notify(int cpu_id, struct proc_intr *intr_info)
-{
-
-       (void)cpu_id;
-       struct ipi_info *chn_ipi_info = (struct ipi_info *)(intr_info->data);
-       if (chn_ipi_info == NULL)
-               return;
-       platform_dcache_all_flush();
-       env_wmb();
        /* Trigger IPI */
-       HIL_MEM_WRITE32((chn_ipi_info->ipi_base_addr + IPI_TRIG_OFFSET),
-                       chn_ipi_info->ipi_chn_mask);
+       metal_io_write32(ipi->io, IPI_TRIG_OFFSET, ipi->ipi_chn_mask);
 }
 
-int _boot_cpu(int cpu_id, unsigned int load_addr)
+static int _boot_cpu(struct hil_proc *proc, unsigned int load_addr)
 {
-       (void)cpu_id;
+       (void)proc;
        (void)load_addr;
        return -1;
 }
 
-void _shutdown_cpu(int cpu_id)
+static void _shutdown_cpu(struct hil_proc *proc)
 {
-       (void)cpu_id;
+       (void)proc;
        return;
 }
 
-/**
- * platform_get_processor_info
- *
- * Copies the target info from the user defined data structures to
- * HIL proc  data structure.In case of remote contexts this function
- * is called with the reserved CPU ID HIL_RSVD_CPU_ID, because for
- * remotes there is only one master.
- *
- * @param proc   - HIL proc to populate
- * @param cpu_id - CPU ID
- *
- * return  - status of execution
- */
-int platform_get_processor_info(struct hil_proc *proc , int cpu_id)
+static int _poll(struct hil_proc *proc, int nonblock)
 {
-       int idx;
-       for(idx = 0; idx < proc_table_size; idx++) {
-               if((cpu_id == HIL_RSVD_CPU_ID) || (proc_table[idx].cpu_id == cpu_id) ) {
-                       env_memcpy(proc,&proc_table[idx], sizeof(struct hil_proc));
+       struct proc_vring *vring;
+       struct ipi_info *ipi;
+       unsigned int flags;
+
+       vring = &proc->vdev.vring_info[1];
+       ipi = (struct ipi_info *)(vring->intr_info.data);
+       while(1) {
+               flags = metal_irq_save_disable();
+               if (!(atomic_flag_test_and_set(&ipi->sync))) {
+                       metal_irq_restore_enable(flags);
+                       virtqueue_notification(vring->vq);
                        return 0;
                }
+               if (nonblock) {
+                       metal_irq_restore_enable(flags);
+                       return -EAGAIN;
+               }
+               _rproc_wait();
+               metal_irq_restore_enable(flags);
+       }
+}
+
+static int _initialize(struct hil_proc *proc)
+{
+       int ret;
+       struct proc_intr *intr_info;
+       struct ipi_info *ipi;
+       unsigned int ipi_intr_status;
+       int i;
+
+       if (!proc)
+               return -1;
+
+       for (i = 0; i < HIL_MAX_NUM_VRINGS; i++) {
+               intr_info = &(proc->vdev.vring_info[i].intr_info);
+               ipi = intr_info->data;
+
+               if (ipi && ipi->name && ipi->bus_name) {
+                       ret = metal_device_open(ipi->bus_name, ipi->name,
+                                                    &ipi->dev);
+                       if (ret)
+                               return -ENODEV;
+                       ipi->io = metal_device_io_region(ipi->dev, 0);
+               } else if (ipi->paddr) {
+                       ipi->io = metal_allocate_memory(
+                               sizeof(struct metal_io_region));
+                       if (!ipi->io)
+                               goto error;
+                       metal_io_init(ipi->io, (void *)ipi->paddr,
+                               &ipi->paddr, 0x1000,
+                               (unsigned)(-1),
+                               METAL_UNCACHED | METAL_IO_MAPPED,
+                               NULL);
+               }
+
+               if (ipi->io) {
+                       ipi_intr_status = (unsigned int)metal_io_read32(
+                               ipi->io, IPI_ISR_OFFSET);
+                       if (ipi_intr_status & ipi->ipi_chn_mask)
+                               metal_io_write32(ipi->io, IPI_ISR_OFFSET,
+                                       ipi->ipi_chn_mask);
+                       metal_io_write32(ipi->io, IPI_IDR_OFFSET,
+                               ipi->ipi_chn_mask);
+                       atomic_store(&ipi->sync, 1);
+               }
        }
+       return 0;
+
+error:
+       _release(proc);
        return -1;
 }
 
-int platform_get_processor_for_fw(char *fw_name)
+static void _release(struct hil_proc *proc)
 {
-       (void)fw_name;
-       return 1;
+       int i;
+       struct proc_intr *intr_info;
+       struct ipi_info *ipi;
+
+       if (!proc)
+               return;
+       for (i = 0; i < HIL_MAX_NUM_VRINGS; i++) {
+               intr_info = &(proc->vdev.vring_info[1].intr_info);
+               ipi = (struct ipi_info *)(intr_info->data);
+               if (ipi) {
+                       if (ipi->io) {
+                               metal_io_write32(ipi->io, IPI_IDR_OFFSET,
+                                       ipi->ipi_chn_mask);
+                               if (ipi->dev) {
+                                       metal_device_close(ipi->dev);
+                                       ipi->dev = NULL;
+                               } else {
+                                       metal_free_memory(ipi->io);
+                               }
+                               ipi->io = NULL;
+                       }
+               }
+
+       }
 }
+