blob: d8324064349c490edcf52adf387abff0e333fa33 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek84c72042015-01-15 10:01:51 +01002/*
3 * (C) Copyright 2014 - 2015 Xilinx, Inc.
4 * Michal Simek <michal.simek@xilinx.com>
Michal Simek84c72042015-01-15 10:01:51 +01005 */
6
7#include <common.h>
Simon Glass049f8d62019-12-28 10:44:59 -07008#include <time.h>
Michal Simek84c72042015-01-15 10:01:51 +01009#include <asm/arch/hardware.h>
10#include <asm/arch/sys_proto.h>
Alexander Graf96519f32016-03-04 01:09:49 +010011#include <asm/armv8/mmu.h>
Simon Glass90526e92020-05-10 11:39:56 -060012#include <asm/cache.h>
Michal Simek84c72042015-01-15 10:01:51 +010013#include <asm/io.h>
Ibai Erkiaga009ab7b2019-09-27 11:37:01 +010014#include <zynqmp_firmware.h>
Ovidiu Panait61848582020-03-29 20:57:40 +030015#include <asm/cache.h>
Michal Simek84c72042015-01-15 10:01:51 +010016
17#define ZYNQ_SILICON_VER_MASK 0xF000
18#define ZYNQ_SILICON_VER_SHIFT 12
19
20DECLARE_GLOBAL_DATA_PTR;
21
Nitin Jain06789412018-04-20 12:30:40 +053022/*
23 * Number of filled static entries and also the first empty
24 * slot in zynqmp_mem_map.
25 */
26#define ZYNQMP_MEM_MAP_USED 4
27
Siva Durga Prasad Paladugu3b644a32018-01-12 15:35:46 +053028#if !defined(CONFIG_ZYNQMP_NO_DDR)
Nitin Jain06789412018-04-20 12:30:40 +053029#define DRAM_BANKS CONFIG_NR_DRAM_BANKS
30#else
31#define DRAM_BANKS 0
Siva Durga Prasad Paladugu3b644a32018-01-12 15:35:46 +053032#endif
Nitin Jain06789412018-04-20 12:30:40 +053033
34#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
35#define TCM_MAP 1
36#else
37#define TCM_MAP 0
38#endif
39
40/* +1 is end of list which needs to be empty */
41#define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1)
42
43static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = {
Siva Durga Prasad Paladugu3b644a32018-01-12 15:35:46 +053044 {
York Suncd4b0c52016-06-24 16:46:22 -070045 .virt = 0x80000000UL,
46 .phys = 0x80000000UL,
Alexander Graf96519f32016-03-04 01:09:49 +010047 .size = 0x70000000UL,
48 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
49 PTE_BLOCK_NON_SHARE |
50 PTE_BLOCK_PXN | PTE_BLOCK_UXN
Nitin Jain06789412018-04-20 12:30:40 +053051 }, {
York Suncd4b0c52016-06-24 16:46:22 -070052 .virt = 0xf8000000UL,
53 .phys = 0xf8000000UL,
Alexander Graf96519f32016-03-04 01:09:49 +010054 .size = 0x07e00000UL,
55 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
56 PTE_BLOCK_NON_SHARE |
57 PTE_BLOCK_PXN | PTE_BLOCK_UXN
58 }, {
York Suncd4b0c52016-06-24 16:46:22 -070059 .virt = 0x400000000UL,
60 .phys = 0x400000000UL,
Anders Hedlund501fbc62017-12-19 17:24:41 +010061 .size = 0x400000000UL,
Alexander Graf96519f32016-03-04 01:09:49 +010062 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
63 PTE_BLOCK_NON_SHARE |
64 PTE_BLOCK_PXN | PTE_BLOCK_UXN
Nitin Jain06789412018-04-20 12:30:40 +053065 }, {
Anders Hedlund501fbc62017-12-19 17:24:41 +010066 .virt = 0x1000000000UL,
67 .phys = 0x1000000000UL,
68 .size = 0xf000000000UL,
Alexander Graf96519f32016-03-04 01:09:49 +010069 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
70 PTE_BLOCK_NON_SHARE |
71 PTE_BLOCK_PXN | PTE_BLOCK_UXN
Alexander Graf96519f32016-03-04 01:09:49 +010072 }
73};
Nitin Jain06789412018-04-20 12:30:40 +053074
75void mem_map_fill(void)
76{
77 int banks = ZYNQMP_MEM_MAP_USED;
78
79#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
80 zynqmp_mem_map[banks].virt = 0xffe00000UL;
81 zynqmp_mem_map[banks].phys = 0xffe00000UL;
82 zynqmp_mem_map[banks].size = 0x00200000UL;
83 zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
84 PTE_BLOCK_INNER_SHARE;
85 banks = banks + 1;
86#endif
87
88#if !defined(CONFIG_ZYNQMP_NO_DDR)
89 for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
90 /* Zero size means no more DDR that's this is end */
91 if (!gd->bd->bi_dram[i].size)
92 break;
93
94 zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start;
95 zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start;
96 zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size;
97 zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
98 PTE_BLOCK_INNER_SHARE;
99 banks = banks + 1;
100 }
101#endif
102}
103
Alexander Graf96519f32016-03-04 01:09:49 +0100104struct mm_region *mem_map = zynqmp_mem_map;
105
Michal Simek9c152ed2016-05-30 10:41:26 +0200106u64 get_page_table_size(void)
107{
108 return 0x14000;
109}
110
Siva Durga Prasad Paladugu5860bc12018-10-05 15:09:05 +0530111#if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP)
112void tcm_init(u8 mode)
Siva Durga Prasad Paladugu12ad2992018-10-05 15:09:04 +0530113{
114 puts("WARNING: Initializing TCM overwrites TCM content\n");
115 initialize_tcm(mode);
116 memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE);
117}
Siva Durga Prasad Paladugu5860bc12018-10-05 15:09:05 +0530118#endif
Siva Durga Prasad Paladugu12ad2992018-10-05 15:09:04 +0530119
Siva Durga Prasad Paladugu5860bc12018-10-05 15:09:05 +0530120#ifdef CONFIG_SYS_MEM_RSVD_FOR_MMU
Ovidiu Panait61848582020-03-29 20:57:40 +0300121int arm_reserve_mmu(void)
Siva Durga Prasad Paladugue042d362017-07-13 19:01:11 +0530122{
Siva Durga Prasad Paladugu12ad2992018-10-05 15:09:04 +0530123 tcm_init(TCM_LOCK);
Siva Durga Prasad Paladugue042d362017-07-13 19:01:11 +0530124 gd->arch.tlb_size = PGTABLE_SIZE;
125 gd->arch.tlb_addr = ZYNQMP_TCM_BASE_ADDR;
126
127 return 0;
128}
129#endif
130
Michal Simek0785dfd2015-11-05 08:34:35 +0100131static unsigned int zynqmp_get_silicon_version_secure(void)
132{
133 u32 ver;
134
135 ver = readl(&csu_base->version);
136 ver &= ZYNQMP_SILICON_VER_MASK;
137 ver >>= ZYNQMP_SILICON_VER_SHIFT;
138
139 return ver;
140}
141
Michal Simek84c72042015-01-15 10:01:51 +0100142unsigned int zynqmp_get_silicon_version(void)
143{
Michal Simek0785dfd2015-11-05 08:34:35 +0100144 if (current_el() == 3)
145 return zynqmp_get_silicon_version_secure();
146
Michal Simek84c72042015-01-15 10:01:51 +0100147 gd->cpu_clk = get_tbclk();
148
149 switch (gd->cpu_clk) {
150 case 50000000:
151 return ZYNQMP_CSU_VERSION_QEMU;
152 }
153
Michal Simekbe6f6af2015-08-20 14:01:39 +0200154 return ZYNQMP_CSU_VERSION_SILICON;
Michal Simek84c72042015-01-15 10:01:51 +0100155}
Siva Durga Prasad Paladugue0752bc2017-02-02 01:10:46 +0530156
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530157static int zynqmp_mmio_rawwrite(const u32 address,
Siva Durga Prasad Paladugue0752bc2017-02-02 01:10:46 +0530158 const u32 mask,
159 const u32 value)
160{
161 u32 data;
162 u32 value_local = value;
Michal Simeke3c26b82018-06-13 10:38:33 +0200163 int ret;
Siva Durga Prasad Paladugue0752bc2017-02-02 01:10:46 +0530164
Michal Simeke3c26b82018-06-13 10:38:33 +0200165 ret = zynqmp_mmio_read(address, &data);
166 if (ret)
167 return ret;
168
Siva Durga Prasad Paladugue0752bc2017-02-02 01:10:46 +0530169 data &= ~mask;
170 value_local &= mask;
171 value_local |= data;
172 writel(value_local, (ulong)address);
173 return 0;
174}
175
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530176static int zynqmp_mmio_rawread(const u32 address, u32 *value)
Siva Durga Prasad Paladugue0752bc2017-02-02 01:10:46 +0530177{
178 *value = readl((ulong)address);
179 return 0;
180}
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530181
182int zynqmp_mmio_write(const u32 address,
183 const u32 mask,
184 const u32 value)
185{
186 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3)
187 return zynqmp_mmio_rawwrite(address, mask, value);
Michal Simek866225f2019-10-04 15:45:29 +0200188#if defined(CONFIG_ZYNQMP_FIRMWARE)
Heinrich Schuchardt549d6842017-10-13 01:14:27 +0200189 else
Michal Simek40361952019-10-04 15:35:45 +0200190 return xilinx_pm_request(PM_MMIO_WRITE, address, mask,
191 value, 0, NULL);
Michal Simek866225f2019-10-04 15:45:29 +0200192#endif
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530193
194 return -EINVAL;
195}
196
197int zynqmp_mmio_read(const u32 address, u32 *value)
198{
Michal Simek866225f2019-10-04 15:45:29 +0200199 u32 ret = -EINVAL;
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530200
201 if (!value)
Michal Simek866225f2019-10-04 15:45:29 +0200202 return ret;
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530203
204 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
205 ret = zynqmp_mmio_rawread(address, value);
Michal Simek866225f2019-10-04 15:45:29 +0200206 }
207#if defined(CONFIG_ZYNQMP_FIRMWARE)
208 else {
209 u32 ret_payload[PAYLOAD_ARG_CNT];
210
Michal Simek40361952019-10-04 15:35:45 +0200211 ret = xilinx_pm_request(PM_MMIO_READ, address, 0, 0,
212 0, ret_payload);
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530213 *value = ret_payload[1];
214 }
Michal Simek866225f2019-10-04 15:45:29 +0200215#endif
Siva Durga Prasad Paladugucb186e72017-07-13 19:01:12 +0530216
217 return ret;
218}