X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fmisc%2Ffsl_law.c;h=287e5559005172fd4cd4dbfedf11c1d4d63dcff0;hb=c55096c084308c08bf8891c190f90bdc3a232394;hp=58340c16bd7259c0074e3d0fbc0609c59563166f;hpb=9eb468da3fd8753de55ab271d6ff5ed7f36d7ea2;p=oweals%2Fu-boot.git diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c index 58340c16bd..287e555900 100644 --- a/drivers/misc/fsl_law.c +++ b/drivers/misc/fsl_law.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2008-2009 Freescale Semiconductor, Inc. * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -29,22 +29,76 @@ 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) #define FSL_HW_NUM_LAWS 8 #elif defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \ - defined(CONFIG_MPC8568) || \ + 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_P2020) + defined(CONFIG_P1011) || defined(CONFIG_P1020) || \ + defined(CONFIG_P2010) || defined(CONFIG_P2020) #define FSL_HW_NUM_LAWS 12 +#elif defined(CONFIG_PPC_P4080) +#define FSL_HW_NUM_LAWS 32 #else #error FSL_HW_NUM_LAWS not defined for this platform #endif +#ifdef CONFIG_FSL_CORENET +void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR); + + gd->used_laws |= (1 << idx); + + out_be32(&ccm->law[idx].lawar, 0); + out_be32(&ccm->law[idx].lawbarh, ((u64)addr >> 32)); + out_be32(&ccm->law[idx].lawbarl, addr & 0xffffffff); + out_be32(&ccm->law[idx].lawar, LAW_EN | ((u32)id << 20) | (u32)sz); + + /* Read back so that we sync the writes */ + in_be32(&ccm->law[idx].lawar); +} + +void disable_law(u8 idx) +{ + volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR); + + gd->used_laws &= ~(1 << idx); + + out_be32(&ccm->law[idx].lawar, 0); + out_be32(&ccm->law[idx].lawbarh, 0); + out_be32(&ccm->law[idx].lawbarl, 0); + + /* Read back so that we sync the writes */ + in_be32(&ccm->law[idx].lawar); + + return; +} + +#ifndef CONFIG_NAND_SPL +static int get_law_entry(u8 i, struct law_entry *e) +{ + volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR); + u32 lawar; + + lawar = in_be32(&ccm->law[i].lawar); + + if (!(lawar & LAW_EN)) + return 0; + + e->addr = ((u64)in_be32(&ccm->law[i].lawbarh) << 32) | + in_be32(&ccm->law[i].lawbarl); + e->size = lawar & 0x3f; + e->trgt_id = (lawar >> 20) & 0xff; + + return 1; +} +#endif +#else void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) { volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08); @@ -55,11 +109,51 @@ void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) out_be32(lawar, 0); out_be32(lawbar, addr >> 12); - out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz); + out_be32(lawar, LAW_EN | ((u32)id << 20) | (u32)sz); - return ; + /* Read back so that we sync the writes */ + in_be32(lawar); +} + +void disable_law(u8 idx) +{ + 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); + + /* Read back so that we sync the writes */ + in_be32(lawar); + + return; } +#ifndef CONFIG_NAND_SPL +static int get_law_entry(u8 i, struct law_entry *e) +{ + volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08); + volatile u32 *lawbar = base + 8 * i; + volatile u32 *lawar = base + 8 * i + 2; + u32 temp; + + temp = in_be32(lawar); + + if (!(temp & LAW_EN)) + return 0; + + e->addr = (u64)in_be32(lawbar) << 12; + e->size = temp & 0x3f; + e->trgt_id = (temp >> 20) & 0xff; + + return 1; +} +#endif +#endif + int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) { u32 idx = ffz(gd->used_laws); @@ -72,6 +166,7 @@ int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) 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; @@ -91,18 +186,30 @@ int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) 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) @@ -139,6 +246,9 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) 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) { @@ -161,12 +271,19 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) 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)