blob: f3a9749625c9655014ff1e4c19dfae6609619af9 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kumar Gala95fd2f62008-01-16 01:13:58 -06002/*
Poonam Aggrwal2ba3ee02011-01-13 21:39:27 +05303 * Copyright 2008-2011 Freescale Semiconductor, Inc.
Kumar Gala95fd2f62008-01-16 01:13:58 -06004 *
5 * (C) Copyright 2000
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Kumar Gala95fd2f62008-01-16 01:13:58 -06007 */
8
Simon Glass1ab16922022-07-31 12:28:48 -06009#include <display_options.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060010#include <asm/bitops.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Kumar Gala6a74ade2011-02-03 09:02:13 -060012#include <linux/compiler.h>
Kumar Gala95fd2f62008-01-16 01:13:58 -060013#include <asm/fsl_law.h>
14#include <asm/io.h>
Fabio Estevam1a03a7e2015-11-05 12:43:40 -020015#include <linux/log2.h>
Kumar Gala95fd2f62008-01-16 01:13:58 -060016
Kumar Gala75639e02008-06-11 00:44:10 -050017DECLARE_GLOBAL_DATA_PTR;
18
Kumar Galafe137112011-01-19 03:05:26 -060019#define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS
Kumar Gala95fd2f62008-01-16 01:13:58 -060020
Kumar Gala65e6c322009-03-19 02:32:23 -050021#ifdef CONFIG_FSL_CORENET
Tom Rini376b88a2022-10-28 20:27:13 -040022#define LAW_BASE (CFG_SYS_FSL_CORENET_CCM_ADDR)
Becky Bruceeb891f02010-06-17 11:37:23 -050023#define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
24#define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
25#define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
26#define LAWBAR_SHIFT 0
27#else
28#define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
29#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
30#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
31#define LAWBAR_SHIFT 12
32#endif
Kumar Gala65e6c322009-03-19 02:32:23 -050033
Kumar Gala65e6c322009-03-19 02:32:23 -050034
Becky Bruceeb891f02010-06-17 11:37:23 -050035static inline phys_addr_t get_law_base_addr(int idx)
Kumar Gala65e6c322009-03-19 02:32:23 -050036{
Becky Bruceeb891f02010-06-17 11:37:23 -050037#ifdef CONFIG_FSL_CORENET
38 return (phys_addr_t)
39 ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) |
40 in_be32(LAWBARL_ADDR(idx));
41#else
42 return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
43#endif
Kumar Gala65e6c322009-03-19 02:32:23 -050044}
45
Becky Bruceeb891f02010-06-17 11:37:23 -050046static inline void set_law_base_addr(int idx, phys_addr_t addr)
Kumar Gala65e6c322009-03-19 02:32:23 -050047{
Becky Bruceeb891f02010-06-17 11:37:23 -050048#ifdef CONFIG_FSL_CORENET
49 out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff);
50 out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32);
Kumar Gala65e6c322009-03-19 02:32:23 -050051#else
Becky Bruceeb891f02010-06-17 11:37:23 -050052 out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
53#endif
54}
55
Kumar Gala65e6c322009-03-19 02:32:23 -050056void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
57{
Simon Glassc6622d62012-12-13 20:48:51 +000058 gd->arch.used_laws |= (1 << idx);
Kumar Gala75639e02008-06-11 00:44:10 -050059
Becky Bruceeb891f02010-06-17 11:37:23 -050060 out_be32(LAWAR_ADDR(idx), 0);
61 set_law_base_addr(idx, addr);
62 out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
Kumar Gala95fd2f62008-01-16 01:13:58 -060063
Timur Tabi52fa71f2009-09-04 17:05:24 -050064 /* Read back so that we sync the writes */
Becky Bruceeb891f02010-06-17 11:37:23 -050065 in_be32(LAWAR_ADDR(idx));
Kumar Gala95fd2f62008-01-16 01:13:58 -060066}
67
Kumar Gala65e6c322009-03-19 02:32:23 -050068void disable_law(u8 idx)
69{
Simon Glassc6622d62012-12-13 20:48:51 +000070 gd->arch.used_laws &= ~(1 << idx);
Kumar Gala65e6c322009-03-19 02:32:23 -050071
Becky Bruceeb891f02010-06-17 11:37:23 -050072 out_be32(LAWAR_ADDR(idx), 0);
73 set_law_base_addr(idx, 0);
Kumar Gala65e6c322009-03-19 02:32:23 -050074
75 /* Read back so that we sync the writes */
Becky Bruceeb891f02010-06-17 11:37:23 -050076 in_be32(LAWAR_ADDR(idx));
Kumar Gala65e6c322009-03-19 02:32:23 -050077
78 return;
79}
80
Ying Zhangffc86e22013-08-16 15:16:10 +080081#if !defined(CONFIG_NAND_SPL) && \
Tom Rini6b15c162022-05-13 12:26:35 -040082 (!defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(INIT_MINIMAL))
Kumar Gala65e6c322009-03-19 02:32:23 -050083static int get_law_entry(u8 i, struct law_entry *e)
84{
Becky Bruceeb891f02010-06-17 11:37:23 -050085 u32 lawar;
Kumar Gala65e6c322009-03-19 02:32:23 -050086
Becky Bruceeb891f02010-06-17 11:37:23 -050087 lawar = in_be32(LAWAR_ADDR(i));
Kumar Gala65e6c322009-03-19 02:32:23 -050088
Becky Bruceeb891f02010-06-17 11:37:23 -050089 if (!(lawar & LAW_EN))
Kumar Gala65e6c322009-03-19 02:32:23 -050090 return 0;
91
Becky Bruceeb891f02010-06-17 11:37:23 -050092 e->addr = get_law_base_addr(i);
93 e->size = lawar & 0x3f;
94 e->trgt_id = (lawar >> 20) & 0xff;
Kumar Gala65e6c322009-03-19 02:32:23 -050095
96 return 1;
97}
98#endif
99
Kumar Gala75639e02008-06-11 00:44:10 -0500100int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
101{
Simon Glassc6622d62012-12-13 20:48:51 +0000102 u32 idx = ffz(gd->arch.used_laws);
Kumar Gala75639e02008-06-11 00:44:10 -0500103
104 if (idx >= FSL_HW_NUM_LAWS)
105 return -1;
106
107 set_law(idx, addr, sz, id);
108
109 return idx;
110}
111
Ying Zhangffc86e22013-08-16 15:16:10 +0800112#if !defined(CONFIG_NAND_SPL) && \
Tom Rini6b15c162022-05-13 12:26:35 -0400113 (!defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(INIT_MINIMAL))
Kumar Galaa9abb002008-06-10 16:16:02 -0500114int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
115{
116 u32 idx;
117
118 /* we have no LAWs free */
Simon Glassc6622d62012-12-13 20:48:51 +0000119 if (gd->arch.used_laws == -1)
Kumar Galaa9abb002008-06-10 16:16:02 -0500120 return -1;
121
122 /* grab the last free law */
Simon Glassc6622d62012-12-13 20:48:51 +0000123 idx = __ilog2(~(gd->arch.used_laws));
Kumar Galaa9abb002008-06-10 16:16:02 -0500124
125 if (idx >= FSL_HW_NUM_LAWS)
126 return -1;
127
128 set_law(idx, addr, sz, id);
129
130 return idx;
131}
132
Pali Rohárf40662d2024-06-06 18:33:23 +0200133struct law_entry find_law_by_addr_id(phys_addr_t addr, enum law_trgt_if id)
Kumar Gala95fd2f62008-01-16 01:13:58 -0600134{
Kumar Gala65e6c322009-03-19 02:32:23 -0500135 struct law_entry entry;
136 int i;
Kumar Gala95fd2f62008-01-16 01:13:58 -0600137
Kumar Gala65e6c322009-03-19 02:32:23 -0500138 entry.index = -1;
139 entry.addr = 0;
140 entry.size = 0;
141 entry.trgt_id = 0;
Kumar Gala75639e02008-06-11 00:44:10 -0500142
Kumar Gala65e6c322009-03-19 02:32:23 -0500143 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
144 u64 upper;
Kumar Gala95fd2f62008-01-16 01:13:58 -0600145
Kumar Gala65e6c322009-03-19 02:32:23 -0500146 if (!get_law_entry(i, &entry))
147 continue;
148
Pali Rohárf40662d2024-06-06 18:33:23 +0200149 if (id != -1 && id != entry.trgt_id)
150 continue;
151
Kumar Gala65e6c322009-03-19 02:32:23 -0500152 upper = entry.addr + (2ull << entry.size);
153 if ((addr >= entry.addr) && (addr < upper)) {
154 entry.index = i;
155 break;
156 }
157 }
158
159 return entry;
Kumar Gala95fd2f62008-01-16 01:13:58 -0600160}
161
Becky Bruce2a15f752008-01-23 16:31:05 -0600162void print_laws(void)
163{
Becky Bruce2a15f752008-01-23 16:31:05 -0600164 int i;
Becky Bruceeb891f02010-06-17 11:37:23 -0500165 u32 lawar;
Becky Bruce2a15f752008-01-23 16:31:05 -0600166
167 printf("\nLocal Access Window Configuration\n");
Becky Bruceeb891f02010-06-17 11:37:23 -0500168 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
169 lawar = in_be32(LAWAR_ADDR(i));
Becky Bruced58f8d52010-06-17 11:37:24 -0500170#ifdef CONFIG_FSL_CORENET
171 printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
172 i, in_be32(LAWBARH_ADDR(i)),
173 i, in_be32(LAWBARL_ADDR(i)));
174#else
Becky Bruceeb891f02010-06-17 11:37:23 -0500175 printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i)));
Becky Bruced58f8d52010-06-17 11:37:24 -0500176#endif
Kumar Gala978bb792011-02-12 15:34:08 -0600177 printf(" LAWAR%02d: 0x%08x\n", i, lawar);
Becky Bruceeb891f02010-06-17 11:37:23 -0500178 printf("\t(EN: %d TGT: 0x%02x SIZE: ",
179 (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff);
180 print_size(lawar_size(lawar), ")\n");
Becky Bruce2a15f752008-01-23 16:31:05 -0600181 }
182
183 return;
184}
185
Kumar Gala61ed0532008-08-26 15:01:28 -0500186/* use up to 2 LAWs for DDR, used the last available LAWs */
187int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
188{
189 u64 start_align, law_sz;
190 int law_sz_enc;
191
192 if (start == 0)
193 start_align = 1ull << (LAW_SIZE_32G + 1);
194 else
Ashish kumare7d15f62016-01-22 15:50:10 +0530195 start_align = 1ull << (__ffs64(start));
Kumar Gala61ed0532008-08-26 15:01:28 -0500196 law_sz = min(start_align, sz);
197 law_sz_enc = __ilog2_u64(law_sz) - 1;
198
199 if (set_last_law(start, law_sz_enc, id) < 0)
200 return -1;
201
Kumar Gala894cc882009-04-04 10:21:02 -0500202 /* recalculate size based on what was actually covered by the law */
203 law_sz = 1ull << __ilog2_u64(law_sz);
204
Kumar Gala61ed0532008-08-26 15:01:28 -0500205 /* do we still have anything to map */
206 sz = sz - law_sz;
207 if (sz) {
208 start += law_sz;
209
Ashish kumare7d15f62016-01-22 15:50:10 +0530210 start_align = 1ull << (__ffs64(start));
Kumar Gala61ed0532008-08-26 15:01:28 -0500211 law_sz = min(start_align, sz);
212 law_sz_enc = __ilog2_u64(law_sz) - 1;
213
214 if (set_last_law(start, law_sz_enc, id) < 0)
215 return -1;
216 } else {
217 return 0;
218 }
219
220 /* do we still have anything to map */
221 sz = sz - law_sz;
222 if (sz)
223 return 1;
224
225 return 0;
226}
Scott Wood095b7122012-09-20 19:02:18 -0500227#endif /* not SPL */
Kumar Gala61ed0532008-08-26 15:01:28 -0500228
Prabhakar Kushwaha21a25902014-04-08 19:12:46 +0530229void disable_non_ddr_laws(void)
230{
231 int i;
232 int id;
233 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
234 u32 lawar = in_be32(LAWAR_ADDR(i));
235
236 if (lawar & LAW_EN) {
237 id = (lawar & ~LAW_EN) >> 20;
238 switch (id) {
239 case LAW_TRGT_IF_DDR_1:
240 case LAW_TRGT_IF_DDR_2:
241 case LAW_TRGT_IF_DDR_3:
242 case LAW_TRGT_IF_DDR_4:
243 case LAW_TRGT_IF_DDR_INTRLV:
244 case LAW_TRGT_IF_DDR_INTLV_34:
245 case LAW_TRGT_IF_DDR_INTLV_123:
246 case LAW_TRGT_IF_DDR_INTLV_1234:
247 continue;
248 default:
249 disable_law(i);
250 }
251 }
252 }
253}
254
Kumar Gala95fd2f62008-01-16 01:13:58 -0600255void init_laws(void)
256{
257 int i;
Kumar Gala95fd2f62008-01-16 01:13:58 -0600258
Kumar Gala65e6c322009-03-19 02:32:23 -0500259#if FSL_HW_NUM_LAWS < 32
Simon Glassc6622d62012-12-13 20:48:51 +0000260 gd->arch.used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
Kumar Gala65e6c322009-03-19 02:32:23 -0500261#elif FSL_HW_NUM_LAWS == 32
Simon Glassc6622d62012-12-13 20:48:51 +0000262 gd->arch.used_laws = 0;
Kumar Gala65e6c322009-03-19 02:32:23 -0500263#else
264#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
265#endif
Kumar Gala95fd2f62008-01-16 01:13:58 -0600266
Udit Agarwald2dd2f72019-11-07 16:11:39 +0000267#if defined(CONFIG_NXP_ESBC) && defined(CONFIG_E500) && \
Aneesh Bansal060384a2014-03-11 23:21:45 +0530268 !defined(CONFIG_E500MC)
269 /* ISBC (Boot ROM) creates a LAW 0 entry for non PBL platforms,
270 * which is not disabled before transferring the control to uboot.
271 * Disable the LAW 0 entry here.
272 */
273 disable_law(0);
274#endif
275
Udit Agarwald2dd2f72019-11-07 16:11:39 +0000276#if !defined(CONFIG_NXP_ESBC)
Prabhakar Kushwaha21a25902014-04-08 19:12:46 +0530277 /*
278 * if any non DDR LAWs has been created earlier, remove them before
279 * LAW table is parsed.
280 */
281 disable_non_ddr_laws();
282#endif
Aneesh Bansal060384a2014-03-11 23:21:45 +0530283
Wolfgang Denk80f70212011-05-19 22:21:41 +0200284 /*
Kumar Gala6a74ade2011-02-03 09:02:13 -0600285 * Any LAWs that were set up before we booted assume they are meant to
286 * be around and mark them used.
287 */
288 for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
289 u32 lawar = in_be32(LAWAR_ADDR(i));
Wolfgang Denk80f70212011-05-19 22:21:41 +0200290
Kumar Gala6a74ade2011-02-03 09:02:13 -0600291 if (lawar & LAW_EN)
Simon Glassc6622d62012-12-13 20:48:51 +0000292 gd->arch.used_laws |= (1 << i);
Kumar Gala6a74ade2011-02-03 09:02:13 -0600293 }
294
Kumar Gala75639e02008-06-11 00:44:10 -0500295 for (i = 0; i < num_law_entries; i++) {
296 if (law_table[i].index == -1)
297 set_next_law(law_table[i].addr, law_table[i].size,
298 law_table[i].trgt_id);
299 else
300 set_law(law_table[i].index, law_table[i].addr,
301 law_table[i].size, law_table[i].trgt_id);
Kumar Gala95fd2f62008-01-16 01:13:58 -0600302 }
303
Liu Gangb4611ee2012-08-09 05:10:03 +0000304#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
Liu Gange86e1a32012-08-09 05:10:00 +0000305 /* check RCW to get which port is used for boot */
Tom Rinid5c3bf22022-10-28 20:27:12 -0400306 ccsr_gur_t *gur = (void *)CFG_SYS_MPC85xx_GUTS_ADDR;
Liu Gange86e1a32012-08-09 05:10:00 +0000307 u32 bootloc = in_be32(&gur->rcwsr[6]);
Liu Gangb4611ee2012-08-09 05:10:03 +0000308 /*
309 * in SRIO or PCIE boot we need to set specail LAWs for
310 * SRIO or PCIE interfaces.
311 */
Liu Gange86e1a32012-08-09 05:10:00 +0000312 switch ((bootloc & FSL_CORENET_RCWSR6_BOOT_LOC) >> 23) {
Liu Gangb4611ee2012-08-09 05:10:03 +0000313 case 0x0: /* boot from PCIE1 */
Tom Rini40eb5562022-11-16 13:10:40 -0500314 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000315 LAW_SIZE_1M,
316 LAW_TRGT_IF_PCIE_1);
Tom Rini40eb5562022-11-16 13:10:40 -0500317 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000318 LAW_SIZE_1M,
319 LAW_TRGT_IF_PCIE_1);
320 break;
321 case 0x1: /* boot from PCIE2 */
Tom Rini40eb5562022-11-16 13:10:40 -0500322 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000323 LAW_SIZE_1M,
324 LAW_TRGT_IF_PCIE_2);
Tom Rini40eb5562022-11-16 13:10:40 -0500325 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000326 LAW_SIZE_1M,
327 LAW_TRGT_IF_PCIE_2);
328 break;
329 case 0x2: /* boot from PCIE3 */
Tom Rini40eb5562022-11-16 13:10:40 -0500330 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000331 LAW_SIZE_1M,
332 LAW_TRGT_IF_PCIE_3);
Tom Rini40eb5562022-11-16 13:10:40 -0500333 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
Liu Gangb4611ee2012-08-09 05:10:03 +0000334 LAW_SIZE_1M,
335 LAW_TRGT_IF_PCIE_3);
336 break;
Liu Gange86e1a32012-08-09 05:10:00 +0000337 case 0x8: /* boot from SRIO1 */
Tom Rini40eb5562022-11-16 13:10:40 -0500338 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
Liu Gange86e1a32012-08-09 05:10:00 +0000339 LAW_SIZE_1M,
340 LAW_TRGT_IF_RIO_1);
Tom Rini40eb5562022-11-16 13:10:40 -0500341 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
Liu Gange86e1a32012-08-09 05:10:00 +0000342 LAW_SIZE_1M,
343 LAW_TRGT_IF_RIO_1);
344 break;
345 case 0x9: /* boot from SRIO2 */
Tom Rini40eb5562022-11-16 13:10:40 -0500346 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
Liu Gange86e1a32012-08-09 05:10:00 +0000347 LAW_SIZE_1M,
348 LAW_TRGT_IF_RIO_2);
Tom Rini40eb5562022-11-16 13:10:40 -0500349 set_next_law(CFG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
Liu Gange86e1a32012-08-09 05:10:00 +0000350 LAW_SIZE_1M,
351 LAW_TRGT_IF_RIO_2);
352 break;
353 default:
354 break;
355 }
356#endif
357
Bin Meng75a6a372022-10-26 12:40:07 +0800358 return;
Kumar Gala95fd2f62008-01-16 01:13:58 -0600359}