X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmisc%2Ffsl_law.c;h=7bdd355c745fa985e5efb0c797688135dfa79ea5;hb=74c5dfd81f94a2a1f0d6990d17c491d718e8b9ea;hp=dca6a4da4a0ab83a2487b8c36e328876a1b2b1bb;hpb=5561857aae9a5921772b18b571708956788148d8;p=u-boot diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c index dca6a4da4a..7bdd355c74 100644 --- a/drivers/misc/fsl_law.c +++ b/drivers/misc/fsl_law.c @@ -27,27 +27,80 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + #define LAWAR_EN 0x80000000 -#define FSL_HW_NUM_LAWS 10 /* number of LAWs in the hw implementation */ +/* number of LAWs in the hw implementation */ +#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555) +#define FSL_HW_NUM_LAWS 8 +#elif defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \ + defined(CONFIG_MPC8568) || defined(CONFIG_MPC8569) || \ + defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610) +#define FSL_HW_NUM_LAWS 10 +#elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \ + defined(CONFIG_P1011) || defined(CONFIG_P1020) || \ + defined(CONFIG_P2010) || defined(CONFIG_P2020) +#define FSL_HW_NUM_LAWS 12 +#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) { - volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); + volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08); volatile u32 *lawbar = base + 8 * idx; volatile u32 *lawar = base + 8 * idx + 2; + gd->used_laws |= (1 << idx); + + out_be32(lawar, 0); out_be32(lawbar, addr >> 12); out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz); - return ; + /* Read back so that we sync the writes */ + in_be32(lawar); +} + +int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx = ffz(gd->used_laws); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; +} + +int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx; + + /* we have no LAWs free */ + if (gd->used_laws == -1) + return -1; + + /* grab the last free law */ + idx = __ilog2(~(gd->used_laws)); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; } void disable_law(u8 idx) { - volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); + volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08); volatile u32 *lawbar = base + 8 * idx; volatile u32 *lawar = base + 8 * idx + 2; + gd->used_laws &= ~(1 << idx); + out_be32(lawar, 0); out_be32(lawbar, 0); @@ -56,7 +109,7 @@ void disable_law(u8 idx) void print_laws(void) { - volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); + volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08); volatile u32 *lawbar = base; volatile u32 *lawar = base + 2; int i; @@ -72,17 +125,61 @@ void print_laws(void) return; } +/* use up to 2 LAWs for DDR, used the last available LAWs */ +int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) +{ + u64 start_align, law_sz; + int law_sz_enc; + + if (start == 0) + start_align = 1ull << (LAW_SIZE_32G + 1); + else + start_align = 1ull << (ffs64(start) - 1); + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + 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) { + start += law_sz; + + start_align = 1ull << (ffs64(start) - 1); + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + if (set_last_law(start, law_sz_enc, id) < 0) + return -1; + } else { + return 0; + } + + /* do we still have anything to map */ + sz = sz - law_sz; + if (sz) + return 1; + + return 0; +} + void init_laws(void) { int i; - u8 law_idx = 0; - for (i = 0; i < num_law_entries; i++) { - if (law_table[i].index != -1) - law_idx = law_table[i].index; + gd->used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1); - set_law(law_idx++, law_table[i].addr, - law_table[i].size, law_table[i].trgt_id); + for (i = 0; i < num_law_entries; i++) { + if (law_table[i].index == -1) + set_next_law(law_table[i].addr, law_table[i].size, + law_table[i].trgt_id); + else + set_law(law_table[i].index, law_table[i].addr, + law_table[i].size, law_table[i].trgt_id); } return ;