/*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
DECLARE_GLOBAL_DATA_PTR;
-#define LAWAR_EN 0x80000000
/* number of LAWs in the hw implementation */
#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610)
#define FSL_HW_NUM_LAWS 10
#elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \
- defined(CONFIG_P2020)
+ defined(CONFIG_P1011) || defined(CONFIG_P1020) || \
+ defined(CONFIG_P1012) || defined(CONFIG_P1021) || \
+ defined(CONFIG_P1013) || defined(CONFIG_P1022) || \
+ defined(CONFIG_P2010) || defined(CONFIG_P2020)
#define FSL_HW_NUM_LAWS 12
+#elif defined(CONFIG_PPC_P3041) || defined(CONFIG_PPC_P4080) || \
+ defined(CONFIG_PPC_P5020)
+#define FSL_HW_NUM_LAWS 32
#else
#error FSL_HW_NUM_LAWS not defined for this platform
#endif
-void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+#ifdef CONFIG_FSL_CORENET
+#define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR)
+#define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
+#define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
+#define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
+#define LAWBAR_SHIFT 0
+#else
+#define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
+#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
+#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
+#define LAWBAR_SHIFT 12
+#endif
+
+
+static inline phys_addr_t get_law_base_addr(int idx)
+{
+#ifdef CONFIG_FSL_CORENET
+ return (phys_addr_t)
+ ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) |
+ in_be32(LAWBARL_ADDR(idx));
+#else
+ return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
+#endif
+}
+
+static inline void set_law_base_addr(int idx, phys_addr_t addr)
{
- volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
- volatile u32 *lawbar = base + 8 * idx;
- volatile u32 *lawar = base + 8 * idx + 2;
+#ifdef CONFIG_FSL_CORENET
+ out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff);
+ out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32);
+#else
+ out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
+#endif
+}
+void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+{
gd->used_laws |= (1 << idx);
- out_be32(lawar, 0);
- out_be32(lawbar, addr >> 12);
- out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz);
+ out_be32(LAWAR_ADDR(idx), 0);
+ set_law_base_addr(idx, addr);
+ out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
- return ;
+ /* Read back so that we sync the writes */
+ in_be32(LAWAR_ADDR(idx));
}
+void disable_law(u8 idx)
+{
+ gd->used_laws &= ~(1 << idx);
+
+ out_be32(LAWAR_ADDR(idx), 0);
+ set_law_base_addr(idx, 0);
+
+ /* Read back so that we sync the writes */
+ in_be32(LAWAR_ADDR(idx));
+
+ return;
+}
+
+#ifndef CONFIG_NAND_SPL
+static int get_law_entry(u8 i, struct law_entry *e)
+{
+ u32 lawar;
+
+ lawar = in_be32(LAWAR_ADDR(i));
+
+ if (!(lawar & LAW_EN))
+ return 0;
+
+ e->addr = get_law_base_addr(i);
+ e->size = lawar & 0x3f;
+ e->trgt_id = (lawar >> 20) & 0xff;
+
+ return 1;
+}
+#endif
+
int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
{
u32 idx = ffz(gd->used_laws);
return idx;
}
+#ifndef CONFIG_NAND_SPL
int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
{
u32 idx;
return idx;
}
-void disable_law(u8 idx)
+struct law_entry find_law(phys_addr_t addr)
{
- volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
- volatile u32 *lawbar = base + 8 * idx;
- volatile u32 *lawar = base + 8 * idx + 2;
+ struct law_entry entry;
+ int i;
- gd->used_laws &= ~(1 << idx);
+ entry.index = -1;
+ entry.addr = 0;
+ entry.size = 0;
+ entry.trgt_id = 0;
- out_be32(lawar, 0);
- out_be32(lawbar, 0);
+ for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+ u64 upper;
- return;
+ if (!get_law_entry(i, &entry))
+ continue;
+
+ upper = entry.addr + (2ull << entry.size);
+ if ((addr >= entry.addr) && (addr < upper)) {
+ entry.index = i;
+ break;
+ }
+ }
+
+ return entry;
}
void print_laws(void)
{
- volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
- volatile u32 *lawbar = base;
- volatile u32 *lawar = base + 2;
int i;
+ u32 lawar;
printf("\nLocal Access Window Configuration\n");
- for(i = 0; i < FSL_HW_NUM_LAWS; i++) {
- printf("\tLAWBAR%d : 0x%08x, LAWAR%d : 0x%08x\n",
- i, in_be32(lawbar), i, in_be32(lawar));
- lawbar += 8;
- lawar += 8;
+ for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+ lawar = in_be32(LAWAR_ADDR(i));
+#ifdef CONFIG_FSL_CORENET
+ printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
+ i, in_be32(LAWBARH_ADDR(i)),
+ i, in_be32(LAWBARL_ADDR(i)));
+#else
+ printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i)));
+#endif
+ printf(" LAWAR0x%02d: 0x%08x\n", i, lawar);
+ printf("\t(EN: %d TGT: 0x%02x SIZE: ",
+ (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff);
+ print_size(lawar_size(lawar), ")\n");
}
return;
if (set_last_law(start, law_sz_enc, id) < 0)
return -1;
+ /* recalculate size based on what was actually covered by the law */
+ law_sz = 1ull << __ilog2_u64(law_sz);
+
/* do we still have anything to map */
sz = sz - law_sz;
if (sz) {
return 0;
}
+#endif
void init_laws(void)
{
int i;
+#if FSL_HW_NUM_LAWS < 32
gd->used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
+#elif FSL_HW_NUM_LAWS == 32
+ gd->used_laws = 0;
+#else
+#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
+#endif
for (i = 0; i < num_law_entries; i++) {
if (law_table[i].index == -1)