X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmisc%2Ffsl_law.c;h=8255175d2a010ac8fcd9acabb14666881d1caa25;hb=fd4e49c18901a50b1648235f26da1e8caa0f8764;hp=7bdd355c745fa985e5efb0c797688135dfa79ea5;hpb=74c5dfd81f94a2a1f0d6990d17c491d718e8b9ea;p=u-boot diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c index 7bdd355c74..8255175d2a 100644 --- a/drivers/misc/fsl_law.c +++ b/drivers/misc/fsl_law.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2008-2010 Freescale Semiconductor, Inc. * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -29,7 +29,6 @@ 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) @@ -40,12 +39,68 @@ DECLARE_GLOBAL_DATA_PTR; #define FSL_HW_NUM_LAWS 10 #elif defined(CONFIG_MPC8536) || defined(CONFIG_MPC8572) || \ 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_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); @@ -56,11 +111,50 @@ 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); + + /* 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) { @@ -74,6 +168,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; @@ -93,18 +188,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) @@ -166,12 +273,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)