diff options
Diffstat (limited to 'arch/powerpc/kernel/setup_64.c')
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 183 |
1 files changed, 90 insertions, 93 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 75c9a8641ba1..b87dcb2968d9 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -78,10 +78,14 @@ int spinning_secondaries; u64 ppc64_pft_size; struct ppc64_caches ppc64_caches = { - .dblock_size = 0x40, - .log_dblock_size = 6, - .iblock_size = 0x40, - .log_iblock_size = 6 + .l1d = { + .block_size = 0x40, + .log_block_size = 6, + }, + .l1i = { + .block_size = 0x40, + .log_block_size = 6 + }, }; EXPORT_SYMBOL_GPL(ppc64_caches); @@ -397,105 +401,98 @@ void smp_release_cpus(void) * cache informations about the CPU that will be used by cache flush * routines and/or provided to userland */ + +static void init_cache_info(struct ppc_cache_info *info, u32 size, u32 lsize, + u32 bsize, u32 sets) +{ + info->size = size; + info->sets = sets; + info->line_size = lsize; + info->block_size = bsize; + info->log_block_size = __ilog2(bsize); + info->blocks_per_page = PAGE_SIZE / bsize; +} + +static bool __init parse_cache_info(struct device_node *np, + bool icache, + struct ppc_cache_info *info) +{ + static const char *ipropnames[] __initdata = { + "i-cache-size", + "i-cache-sets", + "i-cache-block-size", + "i-cache-line-size", + }; + static const char *dpropnames[] __initdata = { + "d-cache-size", + "d-cache-sets", + "d-cache-block-size", + "d-cache-line-size", + }; + const char **propnames = icache ? ipropnames : dpropnames; + const __be32 *sizep, *lsizep, *bsizep, *setsp; + u32 size, lsize, bsize, sets; + bool success = true; + + size = 0; + sets = -1u; + lsize = bsize = cur_cpu_spec->dcache_bsize; + sizep = of_get_property(np, propnames[0], NULL); + if (sizep != NULL) + size = be32_to_cpu(*sizep); + setsp = of_get_property(np, propnames[1], NULL); + if (setsp != NULL) + sets = be32_to_cpu(*setsp); + bsizep = of_get_property(np, propnames[2], NULL); + lsizep = of_get_property(np, propnames[3], NULL); + if (bsizep == NULL) + bsizep = lsizep; + if (lsizep != NULL) + lsize = be32_to_cpu(*lsizep); + if (bsizep != NULL) + bsize = be32_to_cpu(*bsizep); + if (sizep == NULL || bsizep == NULL || lsizep == NULL) + success = false; + + /* + * OF is weird .. it represents fully associative caches + * as "1 way" which doesn't make much sense and doesn't + * leave room for direct mapped. We'll assume that 0 + * in OF means direct mapped for that reason. + */ + if (sets == 1) + sets = 0; + else if (sets == 0) + sets = 1; + + init_cache_info(info, size, lsize, bsize, sets); + + return success; +} + void __init initialize_cache_info(void) { struct device_node *np; - unsigned long num_cpus = 0; DBG(" -> initialize_cache_info()\n"); - for_each_node_by_type(np, "cpu") { - num_cpus += 1; + np = of_find_node_by_type(NULL, "cpu"); - /* - * We're assuming *all* of the CPUs have the same - * d-cache and i-cache sizes... -Peter - */ - if (num_cpus == 1) { - const __be32 *sizep, *lsizep, *bsizep, *setsp; - u32 size, lsize, bsize, sets; - - size = 0; - sets = -1u; - lsize = bsize = cur_cpu_spec->dcache_bsize; - sizep = of_get_property(np, "d-cache-size", NULL); - if (sizep != NULL) - size = be32_to_cpu(*sizep); - setsp = of_get_property(np, "d-cache-sets", NULL); - if (setsp != NULL) - sets = be32_to_cpu(*setsp); - bsizep = of_get_property(np, "d-cache-block-size", - NULL); - lsizep = of_get_property(np, "d-cache-line-size", - NULL); - if (bsizep == NULL) - bsizep = lsizep; - if (lsizep != NULL) - lsize = be32_to_cpu(*lsizep); - if (bsizep != NULL) - bsize = be32_to_cpu(*bsizep); - if (sizep == NULL || bsizep == NULL || lsizep == NULL) - DBG("Argh, can't find dcache properties ! " - "sizep: %p, bsizep: %p, lsizep: %p\n", - sizep, bsizep, lsizep); - - /* - * OF is weird .. it represents fully associative caches - * as "1 way" which doesn't make much sense and doesn't - * leave room for direct mapped. We'll assume that 0 - * in OF means direct mapped for that reason. - */ - if (sets == 1) - sets = 0; - else if (sets == 0) - sets = 1; - ppc64_caches.dsize = size; - ppc64_caches.dsets = sets; - ppc64_caches.dline_size = lsize; - ppc64_caches.dblock_size = bsize; - ppc64_caches.log_dblock_size = __ilog2(bsize); - ppc64_caches.dblocks_per_page = PAGE_SIZE / bsize; - - size = 0; - sets = -1u; - lsize = bsize = cur_cpu_spec->icache_bsize; - sizep = of_get_property(np, "i-cache-size", NULL); - if (sizep != NULL) - size = be32_to_cpu(*sizep); - setsp = of_get_property(np, "i-cache-sets", NULL); - if (setsp != NULL) - sets = be32_to_cpu(*setsp); - bsizep = of_get_property(np, "i-cache-block-size", - NULL); - lsizep = of_get_property(np, "i-cache-line-size", - NULL); - if (bsizep == NULL) - bsizep = lsizep; - if (lsizep != NULL) - lsize = be32_to_cpu(*lsizep); - if (bsizep != NULL) - bsize = be32_to_cpu(*bsizep); - if (sizep == NULL || bsizep == NULL || lsizep == NULL) - DBG("Argh, can't find icache properties ! " - "sizep: %p, bsizep: %p, lsizep: %p\n", - sizep, bsizep, lsizep); - - if (sets == 1) - sets = 0; - else if (sets == 0) - sets = 1; - ppc64_caches.isize = size; - ppc64_caches.isets = sets; - ppc64_caches.iline_size = lsize; - ppc64_caches.iblock_size = bsize; - ppc64_caches.log_iblock_size = __ilog2(bsize); - ppc64_caches.iblocks_per_page = PAGE_SIZE / bsize; - } + /* + * We're assuming *all* of the CPUs have the same + * d-cache and i-cache sizes... -Peter + */ + if (np) { + if (!parse_cache_info(np, false, &ppc64_caches.l1d)) + DBG("Argh, can't find dcache properties !\n"); + + if (!parse_cache_info(np, true, &ppc64_caches.l1i)) + DBG("Argh, can't find icache properties !\n"); } /* For use by binfmt_elf */ - dcache_bsize = ppc64_caches.dblock_size; - icache_bsize = ppc64_caches.iblock_size; + dcache_bsize = ppc64_caches.l1d.block_size; + icache_bsize = ppc64_caches.l1i.block_size; DBG(" <- initialize_cache_info()\n"); } |