Changeset bad1f53 in mainline


Ignore:
Timestamp:
2013-01-19T16:35:17Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
827aae5
Parents:
5fcd537
Message:

arm32: Detect caches on armv7

Location:
kernel/arch/arm32
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/include/cp15.h

    r5fcd537 rbad1f53  
    104104CONTROL_REG_GEN_READ(ID_ISAR5, c0, 0, c2, 5);
    105105
     106enum {
     107        CCSIDR_WT_FLAG = 1 << 31,
     108        CCSIDR_WB_FLAG = 1 << 30,
     109        CCSIDR_RA_FLAG = 1 << 29,
     110        CCSIDR_WA_FLAG = 1 << 28,
     111        CCSIDR_NUMSETS_MASK = 0x7fff,
     112        CCSIDR_NUMSETS_SHIFT = 13,
     113        CCSIDR_ASSOC_MASK = 0x3ff,
     114        CCSIDR_ASSOC_SHIFT = 3,
     115        CCSIDR_LINESIZE_MASK = 0x7,
     116        CCSIDR_LINESIZE_SHIFT = 0,
     117};
    106118CONTROL_REG_GEN_READ(CCSIDR, c0, 1, c0, 0);
     119
     120enum {
     121        CLIDR_LOUU_MASK = 0x7,
     122        CLIDR_LOUU_SHIFT = 27,
     123        CLIDR_LOC_MASK = 0x7,
     124        CLIDR_LOC_SHIFT = 24,
     125        CLIDR_LOUIS_MASK = 0x7,
     126        CLIDR_LOUIS_SHIFT = 21,
     127        CLIDR_NOCACHE = 0x0,
     128        CLIDR_ICACHE_ONLY = 0x1,
     129        CLIDR_DCACHE_ONLY = 0x2,
     130        CLIDR_SEP_CACHE = 0x3,
     131        CLIDR_UNI_CACHE = 0x4,
     132        CLIDR_CACHE_MASK = 0x7,
     133#define CLIDR_CACHE(level, val)   ((val >> (level - 1) * 3) & CLIDR_CACHE_MASK)
     134};
    107135CONTROL_REG_GEN_READ(CLIDR, c0, 1, c0, 1);
    108136CONTROL_REG_GEN_READ(AIDR, c0, 1, c0, 7); /* Implementation defined or MIDR */
    109137
     138enum {
     139        CCSELR_LEVEL_MASK = 0x7,
     140        CCSELR_LEVEL_SHIFT = 1,
     141        CCSELR_INSTRUCTION_FLAG = 1 << 0,
     142};
    110143CONTROL_REG_GEN_READ(CSSELR, c0, 2, c0, 0);
    111144CONTROL_REG_GEN_WRITE(CSSELR, c0, 2, c0, 0);
  • kernel/arch/arm32/include/cpu.h

    r5fcd537 rbad1f53  
    4040#include <arch/asm.h>
    4141
     42enum {
     43        ARM_MAX_CACHE_LEVELS = 7,
     44};
    4245
    4346/** Struct representing ARM CPU identification. */
     
    5760        /** Revision number. */
    5861        uint32_t rev_num;
     62
     63        struct {
     64                unsigned ways;
     65                unsigned sets;
     66                unsigned line_size;
     67                unsigned way_shift;
     68                unsigned set_shift;
     69        } dcache[ARM_MAX_CACHE_LEVELS];
     70        unsigned dcache_levels;
    5971} cpu_arch_t;
    6072
  • kernel/arch/arm32/src/cpu/cpu.c

    r5fcd537 rbad1f53  
    3434 */
    3535
     36#include <arch/cache.h>
    3637#include <arch/cpu.h>
     38#include <arch/cp15.h>
    3739#include <cpu.h>
    3840#include <arch.h>
    3941#include <print.h>
     42
     43static inline unsigned log2(unsigned val)
     44{
     45        unsigned log = 0;
     46        --val;
     47        while (val) {
     48                ++log;
     49                val >>= 1;
     50        }
     51        return log;
     52}
     53
     54static unsigned dcache_ways(unsigned level);
     55static unsigned dcache_sets(unsigned level);
     56static unsigned dcache_linesize_log(unsigned level);
     57
    4058
    4159/** Implementers (vendor) names */
     
    93111        cpu->rev_num = (ident << 28) >> 28;
    94112        // TODO CPUs with arch_num == 0xf use CPUID scheme for identification
     113        cpu->dcache_levels = dcache_levels();
     114
     115        for (unsigned i = 0; i < cpu->dcache_levels; ++i) {
     116                cpu->dcache[i].ways = dcache_ways(i);
     117                cpu->dcache[i].sets = dcache_sets(i);
     118                cpu->dcache[i].way_shift = 31 - log2(cpu->dcache[i].ways);
     119                cpu->dcache[i].set_shift = dcache_linesize_log(i);
     120                cpu->dcache[i].line_size = 1 << dcache_linesize_log(i);
     121                printf("Found DCache L%u: %u-way, %u sets, %u byte lines "
     122                    "(shifts: w%u, s%u)\n", i + 1, cpu->dcache[i].ways,
     123                    cpu->dcache[i].sets, cpu->dcache[i].line_size,
     124                    cpu->dcache[i].way_shift, cpu->dcache[i].set_shift);
     125        }
    95126}
    96127
     
    170201}
    171202
     203/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     204static unsigned dcache_linesize_log(unsigned level)
     205{
     206#ifdef PROCESSOR_ARCH_armv7_a
     207        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     208        const unsigned ls_log = 2 +
     209            ((CCSIDR_read() >> CCSIDR_LINESIZE_SHIFT) & CCSIDR_LINESIZE_MASK);
     210        return ls_log + 2; //return log2(bytes)
     211#endif
     212        return 0;
     213
     214}
     215
     216/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     217static unsigned dcache_ways(unsigned level)
     218{
     219#ifdef PROCESSOR_ARCH_armv7_a
     220        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     221        const unsigned ways = 1 +
     222            ((CCSIDR_read() >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK);
     223        return ways;
     224#endif
     225        return 0;
     226}
     227
     228/** See chapter B4.1.19 of ARM Architecture Reference Manual */
     229static unsigned dcache_sets(unsigned level)
     230{
     231#ifdef PROCESSOR_ARCH_armv7_a
     232        CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
     233        const unsigned sets = 1 +
     234            ((CCSIDR_read() >> CCSIDR_NUMSETS_SHIFT) & CCSIDR_NUMSETS_MASK);
     235        return sets;
     236#endif
     237        return 0;
     238}
     239
     240unsigned dcache_levels(void)
     241{
     242        const uint32_t val = CLIDR_read();
     243        unsigned levels = 0;
     244        for (unsigned i = 1; i <= 7; ++i) {
     245                const unsigned ctype = CLIDR_CACHE(i, val);
     246                switch (ctype) {
     247                case CLIDR_DCACHE_ONLY:
     248                case CLIDR_SEP_CACHE:
     249                case CLIDR_UNI_CACHE:
     250                        ++levels;
     251                default:
     252                        (void)0;
     253                }
     254        }
     255        return levels;
     256}
     257
     258static void dcache_clean_manual(unsigned level, bool invalidate,
     259    unsigned ways, unsigned sets, unsigned way_shift, unsigned set_shift)
     260{
     261
     262        for (unsigned i = 0; i < ways; ++i) {
     263                for (unsigned j = 0; j < sets; ++j) {
     264                        const uint32_t val =
     265                            ((level & 0x7) << 1) |
     266                            (j << set_shift) | (i << way_shift);
     267                        if (invalidate)
     268                                DCCISW_write(val);
     269                        else
     270                                DCCSW_write(val);
     271                }
     272        }
     273}
     274
     275void dcache_flush(void)
     276{
     277        /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
     278        const unsigned levels = dcache_levels();
     279        for (unsigned i = 0; i < levels; ++i) {
     280                const unsigned ways = dcache_ways(i);
     281                const unsigned sets = dcache_sets(i);
     282                const unsigned way_shift =  31 - log2(ways);
     283                const unsigned set_shift = dcache_linesize_log(i);
     284                dcache_clean_manual(i, false, ways, sets, way_shift, set_shift);
     285        }
     286}
     287
     288void dcache_flush_invalidate(void)
     289{
     290        /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
     291        const unsigned levels = dcache_levels();
     292        for (unsigned i = 0; i < levels; ++i) {
     293                const unsigned ways = dcache_ways(i);
     294                const unsigned sets = dcache_sets(i);
     295                const unsigned way_shift =  31 - log2(ways);
     296                const unsigned set_shift = dcache_linesize_log(i);
     297                dcache_clean_manual(i, true, ways, sets, way_shift, set_shift);
     298        }
     299}
     300
     301
     302void cpu_dcache_flush(void)
     303{
     304        for (unsigned i = 0; i < CPU->arch.dcache_levels; ++i)
     305                dcache_clean_manual(i, false,
     306                    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
     307                    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
     308}
     309
     310void cpu_dcache_flush_invalidate(void)
     311{
     312        const unsigned levels =  dcache_levels();
     313        for (unsigned i = 0; i < levels; ++i)
     314                dcache_clean_manual(i, true,
     315                    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
     316                    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
     317}
     318
     319void icache_invalidate(void)
     320{
     321        ICIALLU_write(0);
     322}
     323
    172324/** @}
    173325 */
Note: See TracChangeset for help on using the changeset viewer.