e7e11d74f64d66c3d243bb15d0fa769d0558618d
[processor-sdk/open-amp.git] / lib / remoteproc / drivers / zynq_remoteproc_a9.c
1 /*
2  * Copyright (c) 2014, Mentor Graphics Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. Neither the name of Mentor Graphics Corporation nor the names of its
14  *    contributors may be used to endorse or promote products derived from this
15  *    software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
30 /**************************************************************************
31  * FILE NAME
32  *
33  *       platform.c
34  *
35  * DESCRIPTION
36  *
37  *       This file is the Implementation of IPC hardware layer interface
38  *       for Xilinx Zynq ZC702EVK platform.
39  *
40  **************************************************************************/
42 #include "openamp/hil.h"
44 /* ------------------------- Macros --------------------------*/
45 #define ESAL_DP_SLCR_BASE                  0xF8000000
46 #define PERIPH_BASE                        0xF8F00000
47 #define GIC_DIST_BASE                      (PERIPH_BASE + 0x00001000)
48 #define GIC_DIST_SOFTINT                   0xF00
49 #define GIC_SFI_TRIG_CPU_MASK              0x00FF0000
50 #define GIC_SFI_TRIG_SATT_MASK             0x00008000
51 #define GIC_SFI_TRIG_INTID_MASK            0x0000000F
52 #define GIC_CPU_ID_BASE                    (1 << 4)
53 #define A9_CPU_SLCR_RESET_CTRL             0x244
54 #define A9_CPU_SLCR_CLK_STOP               (1 << 4)
55 #define A9_CPU_SLCR_RST                    (1 << 0)
57 #define unlock_slcr()                       HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + 0x08, 0xDF0DDF0D)
58 #define lock_slcr()                         HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + 0x04, 0x767B767B)
61 /* L2Cpl310 L2 cache controller base address. */
62 #define         HIL_PL130_BASE              0xF8F02000
64 /********************/
65 /* Register offsets */
66 /********************/
68 #define         HIL_PL130_INVALLINE         0x770
69 #define         HIL_PL130_CLEANINVLINE      0x7F0
72 #define         HIL_PA_SBZ_MASK             ~(HIL_CACHE_LINE_SIZE - 1UL)
73 #define         HIL_CACHE_LINE_SIZE         32
74 #define         HIL_CACHE_INV_ALL_WAYS      0xFF
75 #define         HIL_CACHE_UNLOCK_ALL_WAYS   0xFFFF0000
76 #define         HIL_CACHE_CLEAR_INT         0x1FF
78 /*--------------------------- Declare Functions ------------------------ */
79 static int _enable_interrupt(struct proc_vring *vring_hw);
80 static void _notify(int cpu_id, struct proc_intr *intr_info);
81 static int _boot_cpu(int cpu_id, unsigned int load_addr);
82 static void _shutdown_cpu(int cpu_id);
83 static void platform_isr(int vect_id, void *data);
85 /*--------------------------- Globals ---------------------------------- */
86 struct hil_platform_ops proc_ops = {
87         .enable_interrupt = _enable_interrupt,
88         .notify = _notify,
89         .boot_cpu = _boot_cpu,
90         .shutdown_cpu = _shutdown_cpu,
91 };
93 static int _enable_interrupt(struct proc_vring *vring_hw)
94 {
96         /* Register ISR */
97         env_register_isr(vring_hw->intr_info.vect_id, vring_hw, platform_isr);
99         /* Enable the interrupts */
100         env_enable_interrupt(vring_hw->intr_info.vect_id,
101                              vring_hw->intr_info.priority,
102                              vring_hw->intr_info.trigger_type);
103         return 0;
106 static void _notify(int cpu_id, struct proc_intr *intr_info)
109         unsigned long mask = 0;
111         mask = ((1 << (GIC_CPU_ID_BASE + cpu_id)) | (intr_info->vect_id))
112             & (GIC_SFI_TRIG_CPU_MASK | GIC_SFI_TRIG_INTID_MASK);
114         HIL_MEM_WRITE32((GIC_DIST_BASE + GIC_DIST_SOFTINT), mask);
117 extern char zynq_trampoline;
118 extern char zynq_trampoline_jump;
119 extern char zynq_trampoline_end;
121 static int _boot_cpu(int cpu_id, unsigned int load_addr)
123         unsigned int reg;
124         unsigned int tramp_size;
125         unsigned int tramp_addr = 0;
127         if (load_addr) {
128                 tramp_size = zynq_trampoline_end - zynq_trampoline;
129                 if ((load_addr < tramp_size) || (load_addr & 0x3)) {
130                         return -1;
131                 }
133                 tramp_size = &zynq_trampoline_jump - &zynq_trampoline;
135                 /*
136                  * Trampoline code is copied to address 0 from where remote core is expected to
137                  * fetch first instruction after reset.If master is using the address 0 then
138                  * this mem copy will screwed the system. It is user responsibility to not
139                  * copy trampoline code in such cases.
140                  *
141                  */
142                 env_memcpy((char *)tramp_addr, &zynq_trampoline, tramp_size);
143                 /* Write image address at the word reserved at the trampoline end */
144                 HIL_MEM_WRITE32((char *)(tramp_addr + tramp_size), load_addr);
145         }
147         unlock_slcr();
149         reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
150         reg &= ~(A9_CPU_SLCR_CLK_STOP << cpu_id);
151         HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
152         /* De-assert reset signal and start clock to start the core */
153         reg &= ~(A9_CPU_SLCR_RST << cpu_id);
154         HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
156         lock_slcr();
158         return 0;
161 static void _shutdown_cpu(int cpu_id)
163         unsigned int reg;
165         unlock_slcr();
167         reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
168         /* Assert reset signal and stop clock to halt the core */
169         reg |= (A9_CPU_SLCR_CLK_STOP | A9_CPU_SLCR_RST) << cpu_id;
170         HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
172         lock_slcr();
175 static void platform_isr(int vect_id, void *data)
177         hil_isr(((struct proc_vring *)data));