2 * Copyright 2008-2011 Freescale Semiconductor, Inc.
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * SPDX-License-Identifier: GPL-2.0+
11 #include <linux/compiler.h>
12 #include <asm/fsl_law.h>
15 DECLARE_GLOBAL_DATA_PTR
;
17 #define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS
19 #ifdef CONFIG_FSL_CORENET
20 #define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR)
21 #define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
22 #define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
23 #define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
24 #define LAWBAR_SHIFT 0
26 #define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
27 #define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
28 #define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
29 #define LAWBAR_SHIFT 12
33 static inline phys_addr_t
get_law_base_addr(int idx
)
35 #ifdef CONFIG_FSL_CORENET
37 ((u64
)in_be32(LAWBARH_ADDR(idx
)) << 32) |
38 in_be32(LAWBARL_ADDR(idx
));
40 return (phys_addr_t
)in_be32(LAWBAR_ADDR(idx
)) << LAWBAR_SHIFT
;
44 static inline void set_law_base_addr(int idx
, phys_addr_t addr
)
46 #ifdef CONFIG_FSL_CORENET
47 out_be32(LAWBARL_ADDR(idx
), addr
& 0xffffffff);
48 out_be32(LAWBARH_ADDR(idx
), (u64
)addr
>> 32);
50 out_be32(LAWBAR_ADDR(idx
), addr
>> LAWBAR_SHIFT
);
54 void set_law(u8 idx
, phys_addr_t addr
, enum law_size sz
, enum law_trgt_if id
)
56 gd
->arch
.used_laws
|= (1 << idx
);
58 out_be32(LAWAR_ADDR(idx
), 0);
59 set_law_base_addr(idx
, addr
);
60 out_be32(LAWAR_ADDR(idx
), LAW_EN
| ((u32
)id
<< 20) | (u32
)sz
);
62 /* Read back so that we sync the writes */
63 in_be32(LAWAR_ADDR(idx
));
66 void disable_law(u8 idx
)
68 gd
->arch
.used_laws
&= ~(1 << idx
);
70 out_be32(LAWAR_ADDR(idx
), 0);
71 set_law_base_addr(idx
, 0);
73 /* Read back so that we sync the writes */
74 in_be32(LAWAR_ADDR(idx
));
79 #if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
80 static int get_law_entry(u8 i
, struct law_entry
*e
)
84 lawar
= in_be32(LAWAR_ADDR(i
));
86 if (!(lawar
& LAW_EN
))
89 e
->addr
= get_law_base_addr(i
);
90 e
->size
= lawar
& 0x3f;
91 e
->trgt_id
= (lawar
>> 20) & 0xff;
97 int set_next_law(phys_addr_t addr
, enum law_size sz
, enum law_trgt_if id
)
99 u32 idx
= ffz(gd
->arch
.used_laws
);
101 if (idx
>= FSL_HW_NUM_LAWS
)
104 set_law(idx
, addr
, sz
, id
);
109 #if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
110 int set_last_law(phys_addr_t addr
, enum law_size sz
, enum law_trgt_if id
)
114 /* we have no LAWs free */
115 if (gd
->arch
.used_laws
== -1)
118 /* grab the last free law */
119 idx
= __ilog2(~(gd
->arch
.used_laws
));
121 if (idx
>= FSL_HW_NUM_LAWS
)
124 set_law(idx
, addr
, sz
, id
);
129 struct law_entry
find_law(phys_addr_t addr
)
131 struct law_entry entry
;
139 for (i
= 0; i
< FSL_HW_NUM_LAWS
; i
++) {
142 if (!get_law_entry(i
, &entry
))
145 upper
= entry
.addr
+ (2ull << entry
.size
);
146 if ((addr
>= entry
.addr
) && (addr
< upper
)) {
155 void print_laws(void)
160 printf("\nLocal Access Window Configuration\n");
161 for (i
= 0; i
< FSL_HW_NUM_LAWS
; i
++) {
162 lawar
= in_be32(LAWAR_ADDR(i
));
163 #ifdef CONFIG_FSL_CORENET
164 printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
165 i
, in_be32(LAWBARH_ADDR(i
)),
166 i
, in_be32(LAWBARL_ADDR(i
)));
168 printf("LAWBAR%02d: 0x%08x", i
, in_be32(LAWBAR_ADDR(i
)));
170 printf(" LAWAR%02d: 0x%08x\n", i
, lawar
);
171 printf("\t(EN: %d TGT: 0x%02x SIZE: ",
172 (lawar
& LAW_EN
) ? 1 : 0, (lawar
>> 20) & 0xff);
173 print_size(lawar_size(lawar
), ")\n");
179 /* use up to 2 LAWs for DDR, used the last available LAWs */
180 int set_ddr_laws(u64 start
, u64 sz
, enum law_trgt_if id
)
182 u64 start_align
, law_sz
;
186 start_align
= 1ull << (LAW_SIZE_32G
+ 1);
188 start_align
= 1ull << (ffs64(start
) - 1);
189 law_sz
= min(start_align
, sz
);
190 law_sz_enc
= __ilog2_u64(law_sz
) - 1;
192 if (set_last_law(start
, law_sz_enc
, id
) < 0)
195 /* recalculate size based on what was actually covered by the law */
196 law_sz
= 1ull << __ilog2_u64(law_sz
);
198 /* do we still have anything to map */
203 start_align
= 1ull << (ffs64(start
) - 1);
204 law_sz
= min(start_align
, sz
);
205 law_sz_enc
= __ilog2_u64(law_sz
) - 1;
207 if (set_last_law(start
, law_sz_enc
, id
) < 0)
213 /* do we still have anything to map */
226 #if FSL_HW_NUM_LAWS < 32
227 gd
->arch
.used_laws
= ~((1 << FSL_HW_NUM_LAWS
) - 1);
228 #elif FSL_HW_NUM_LAWS == 32
229 gd
->arch
.used_laws
= 0;
231 #error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
235 * Any LAWs that were set up before we booted assume they are meant to
236 * be around and mark them used.
238 for (i
= 0; i
< FSL_HW_NUM_LAWS
; i
++) {
239 u32 lawar
= in_be32(LAWAR_ADDR(i
));
242 gd
->arch
.used_laws
|= (1 << i
);
245 #if (defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)) || \
246 (defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
248 * in SPL boot we've already parsed the law_table and setup those LAWs
249 * so don't do it again.
254 for (i
= 0; i
< num_law_entries
; i
++) {
255 if (law_table
[i
].index
== -1)
256 set_next_law(law_table
[i
].addr
, law_table
[i
].size
,
257 law_table
[i
].trgt_id
);
259 set_law(law_table
[i
].index
, law_table
[i
].addr
,
260 law_table
[i
].size
, law_table
[i
].trgt_id
);
263 #ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
264 /* check RCW to get which port is used for boot */
265 ccsr_gur_t
*gur
= (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR
;
266 u32 bootloc
= in_be32(&gur
->rcwsr
[6]);
268 * in SRIO or PCIE boot we need to set specail LAWs for
269 * SRIO or PCIE interfaces.
271 switch ((bootloc
& FSL_CORENET_RCWSR6_BOOT_LOC
) >> 23) {
272 case 0x0: /* boot from PCIE1 */
273 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS
,
276 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS
,
280 case 0x1: /* boot from PCIE2 */
281 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS
,
284 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS
,
288 case 0x2: /* boot from PCIE3 */
289 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS
,
292 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS
,
296 case 0x8: /* boot from SRIO1 */
297 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS
,
300 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS
,
304 case 0x9: /* boot from SRIO2 */
305 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS
,
308 set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS
,