source: branches/contrib/debian/package-build/linux-patch-bcm47xx/patches-3.16/159-cpu_fixes.patch @ 671

Last change on this file since 671 was 671, checked in by ehem, 5 years ago

Initial experimental set of patches against Debian's 3.16 kernel for
Broadcom 47xx devices. These are mostly untested and are likely to fail
spectacularly. Progress appears to be being made towards building a
kernel that may work on actual hardware.

File size: 13.8 KB
  • arch/mips/include/asm/r4kcache.h

    a b  
    2222extern void (*r4k_blast_dcache)(void);
    2323extern void (*r4k_blast_icache)(void);
    2424
     25#ifdef CONFIG_BCM47XX
     26#include <asm/paccess.h>
     27#include <linux/ssb/ssb.h>
     28#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE)))
     29
     30#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
     31#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
     32#else
     33#define BCM4710_DUMMY_RREG()
     34
     35#define BCM4710_FILL_TLB(addr)
     36#define BCM4710_PROTECTED_FILL_TLB(addr)
     37#endif
     38
    2539/*
    2640 * This macro return a properly sign-extended address suitable as base address
    2741 * for indexed cache operations.  Two issues here:
    static inline void flush_icache_line_ind 
    154168static inline void flush_dcache_line_indexed(unsigned long addr)
    155169{
    156170        __dflush_prologue
     171        BCM4710_DUMMY_RREG();
    157172        cache_op(Index_Writeback_Inv_D, addr);
    158173        __dflush_epilogue
    159174}
    static inline void flush_icache_line(uns 
    181196static inline void flush_dcache_line(unsigned long addr)
    182197{
    183198        __dflush_prologue
     199        BCM4710_DUMMY_RREG();
    184200        cache_op(Hit_Writeback_Inv_D, addr);
    185201        __dflush_epilogue
    186202}
    static inline void flush_dcache_line(uns 
    188204static inline void invalidate_dcache_line(unsigned long addr)
    189205{
    190206        __dflush_prologue
     207        BCM4710_DUMMY_RREG();
    191208        cache_op(Hit_Invalidate_D, addr);
    192209        __dflush_epilogue
    193210}
    static inline void protected_flush_icach 
    243260#ifdef CONFIG_EVA
    244261                protected_cachee_op(Hit_Invalidate_I, addr);
    245262#else
     263                BCM4710_DUMMY_RREG();
    246264                protected_cache_op(Hit_Invalidate_I, addr);
    247265#endif
    248266                break;
    static inline void protected_flush_icach 
    257275 */
    258276static inline void protected_writeback_dcache_line(unsigned long addr)
    259277{
     278        BCM4710_DUMMY_RREG();
    260279#ifdef CONFIG_EVA
    261280        protected_cachee_op(Hit_Writeback_Inv_D, addr);
    262281#else
    static inline void invalidate_tcache_pag 
    466485                : "r" (base),                                           \
    467486                  "i" (op));
    468487
     488static inline void blast_dcache(void)
     489{
     490        unsigned long start = KSEG0;
     491        unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
     492        unsigned long end = (start + dcache_size);
     493
     494        do {
     495                BCM4710_DUMMY_RREG();
     496                cache_op(Index_Writeback_Inv_D, start);
     497                start += current_cpu_data.dcache.linesz;
     498        } while(start < end);
     499}
     500
     501static inline void blast_dcache_page(unsigned long page)
     502{
     503        unsigned long start = page;
     504        unsigned long end = start + PAGE_SIZE;
     505
     506        BCM4710_FILL_TLB(start);
     507        do {
     508                BCM4710_DUMMY_RREG();
     509                cache_op(Hit_Writeback_Inv_D, start);
     510                start += current_cpu_data.dcache.linesz;
     511        } while(start < end);
     512}
     513
     514static inline void blast_dcache_page_indexed(unsigned long page)
     515{
     516        unsigned long start = page;
     517        unsigned long end = start + PAGE_SIZE;
     518        unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
     519        unsigned long ws_end = current_cpu_data.dcache.ways <<
     520                               current_cpu_data.dcache.waybit;
     521        unsigned long ws, addr;
     522        for (ws = 0; ws < ws_end; ws += ws_inc) {
     523                start = page + ws;
     524                for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
     525                        BCM4710_DUMMY_RREG();
     526                        cache_op(Index_Writeback_Inv_D, addr);
     527                }
     528        }
     529}
     530
    469531/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
    470 #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra)    \
     532#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \
    471533static inline void extra##blast_##pfx##cache##lsize(void)               \
    472534{                                                                       \
    473535        unsigned long start = INDEX_BASE;                               \
    static inline void extra##blast_##pfx##c 
    479541                                                                        \
    480542        __##pfx##flush_prologue                                         \
    481543                                                                        \
     544        war                                                             \
    482545        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
    483546                for (addr = start; addr < end; addr += lsize * 32)      \
    484547                        cache##lsize##_unroll32(addr|ws, indexop);      \
    static inline void extra##blast_##pfx##c 
    493556                                                                        \
    494557        __##pfx##flush_prologue                                         \
    495558                                                                        \
     559        war                                                             \
    496560        do {                                                            \
    497561                cache##lsize##_unroll32(start, hitop);                  \
    498562                start += lsize * 32;                                    \
    static inline void extra##blast_##pfx##c 
    511575                               current_cpu_data.desc.waybit;            \
    512576        unsigned long ws, addr;                                         \
    513577                                                                        \
     578        war                                                             \
     579                                                                        \
    514580        __##pfx##flush_prologue                                         \
    515581                                                                        \
    516582        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
    static inline void extra##blast_##pfx##c 
    520586        __##pfx##flush_epilogue                                         \
    521587}
    522588
    523 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
    524 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
    525 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
    526 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
    527 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
    528 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
    529 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
    530 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
    531 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
    532 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
    533 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, )
    534 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, )
    535 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
    536 
    537 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
    538 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
    539 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
    540 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
    541 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
    542 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
     589__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , )
     590__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);)
     591__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , )
     592__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , )
     593__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);)
     594__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);)
     595__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , )
     596__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , )
     597__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);)
     598__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , )
     599__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, , )
     600__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, , )
     601__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , )
     602
     603__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , )
     604__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , )
     605__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , )
     606__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , )
     607__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , )
     608__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , )
    543609
    544610#define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \
    545611static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \
    __BUILD_BLAST_USER_CACHE(d, dcache, Inde 
    568634__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
    569635
    570636/* build blast_xxx_range, protected_blast_xxx_range */
    571 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)        \
     637#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2)     \
    572638static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
    573639                                                    unsigned long end)  \
    574640{                                                                       \
    575641        unsigned long lsize = cpu_##desc##_line_size();                 \
    576642        unsigned long addr = start & ~(lsize - 1);                      \
    577643        unsigned long aend = (end - 1) & ~(lsize - 1);                  \
     644        war                                                             \
    578645                                                                        \
    579646        __##pfx##flush_prologue                                         \
    580647                                                                        \
    581648        while (1) {                                                     \
     649                war2                                                    \
    582650                prot##cache_op(hitop, addr);                            \
    583651                if (addr == aend)                                       \
    584652                        break;                                          \
    static inline void prot##extra##blast_## 
    590658
    591659#ifndef CONFIG_EVA
    592660
    593 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
    594 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
     661__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
     662__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , )
    595663
    596664#else
    597665
    __BUILD_PROT_BLAST_CACHE_RANGE(d, dcache 
    628696__BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I)
    629697
    630698#endif
    631 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
     699__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , )
    632700__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
    633         protected_, loongson2_)
    634 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
    635 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , )
    636 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
     701        protected_, loongson2_, , )
     702__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
     703__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , , , )
     704__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , )
    637705/* blast_inv_dcache_range */
    638 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
    639 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
     706__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();)
     707__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , )
    640708
    641709#endif /* _ASM_R4KCACHE_H */
  • arch/mips/include/asm/stackframe.h

    a b  
    333333                .macro  RESTORE_SP_AND_RET
    334334                LONG_L  sp, PT_R29(sp)
    335335                .set    arch=r4000
     336#ifdef CONFIG_BCM47XX
     337                nop
     338                nop
     339#endif
    336340                eret
    337341                .set    mips0
    338342                .endm
  • arch/mips/kernel/genex.S

    a b  
    3232NESTED(except_vec3_generic, 0, sp)
    3333        .set    push
    3434        .set    noat
     35#ifdef CONFIG_BCM47XX
     36        nop
     37        nop
     38#endif
    3539#if R5432_CP0_INTERRUPT_WAR
    3640        mfc0    k0, CP0_INDEX
    3741#endif
  • arch/mips/mm/c-r4k.c

    a b  
    3838#include <asm/traps.h>
    3939#include <asm/dma-coherence.h>
    4040
     41/* For enabling BCM4710 cache workarounds */
     42int bcm4710 = 0;
     43
    4144/*
    4245 * Special Variant of smp_call_function for use by cache functions:
    4346 *
    static void r4k_blast_dcache_user_page_s 
    149152{
    150153        unsigned long  dc_lsize = cpu_dcache_line_size();
    151154
     155        if (bcm4710)
     156                r4k_blast_dcache_page = blast_dcache_page;
     157        else
    152158        if (dc_lsize == 0)
    153159                r4k_blast_dcache_user_page = (void *)cache_noop;
    154160        else if (dc_lsize == 16)
    static void r4k_blast_dcache_page_indexe 
    167173{
    168174        unsigned long dc_lsize = cpu_dcache_line_size();
    169175
     176        if (bcm4710)
     177                r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
     178        else
    170179        if (dc_lsize == 0)
    171180                r4k_blast_dcache_page_indexed = (void *)cache_noop;
    172181        else if (dc_lsize == 16)
    static void r4k_blast_dcache_setup(void) 
    186195{
    187196        unsigned long dc_lsize = cpu_dcache_line_size();
    188197
     198        if (bcm4710)
     199                r4k_blast_dcache = blast_dcache;
     200        else
    189201        if (dc_lsize == 0)
    190202                r4k_blast_dcache = (void *)cache_noop;
    191203        else if (dc_lsize == 16)
    static void local_r4k_flush_cache_sigtra 
    784796        unsigned long addr = (unsigned long) arg;
    785797
    786798        R4600_HIT_CACHEOP_WAR_IMPL;
     799        BCM4710_PROTECTED_FILL_TLB(addr);
     800        BCM4710_PROTECTED_FILL_TLB(addr + 4);
    787801        if (dc_lsize)
    788802                protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
    789803        if (!cpu_icache_snoops_remote_store && scache_size)
    static void coherency_setup(void) 
    15661580         * silly idea of putting something else there ...
    15671581         */
    15681582        switch (current_cpu_type()) {
     1583        case CPU_BMIPS3300:
     1584                {
     1585                        u32 cm;
     1586                        cm = read_c0_diag();
     1587                        /* Enable icache */
     1588                        cm |= (1 << 31);
     1589                        /* Enable dcache */
     1590                        cm |= (1 << 30);
     1591                        write_c0_diag(cm);
     1592                }
     1593                break;
    15691594        case CPU_R4000PC:
    15701595        case CPU_R4000SC:
    15711596        case CPU_R4000MC:
    void r4k_cache_init(void) 
    16121637        extern void build_copy_page(void);
    16131638        struct cpuinfo_mips *c = &current_cpu_data;
    16141639
     1640        /* Check if special workarounds are required */
     1641#ifdef CONFIG_BCM47XX
     1642        if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) {
     1643                printk("Enabling BCM4710A0 cache workarounds.\n");
     1644                bcm4710 = 1;
     1645        } else
     1646#endif
     1647                bcm4710 = 0;
     1648
    16151649        probe_pcache();
    16161650        setup_scache();
    16171651
    void r4k_cache_init(void) 
    16811715         */
    16821716        local_r4k___flush_cache_all(NULL);
    16831717
     1718#ifdef CONFIG_BCM47XX
     1719        {
     1720                static void (*_coherency_setup)(void);
     1721                _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
     1722                _coherency_setup();
     1723        }
     1724#else
    16841725        coherency_setup();
     1726#endif
    16851727        board_cache_error_setup = r4k_cache_error_setup;
    16861728}
    16871729
  • arch/mips/mm/tlbex.c

    a b static void build_r4000_tlb_refill_handl 
    12851285                        /* No need for uasm_i_nop */
    12861286                }
    12871287
     1288#ifdef CONFIG_BCM47XX
     1289                uasm_i_nop(&p);
     1290#endif
    12881291#ifdef CONFIG_64BIT
    12891292                build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
    12901293#else
    build_r4000_tlbchange_handler_head(u32 * 
    18471850{
    18481851        struct work_registers wr = build_get_work_registers(p);
    18491852
     1853#ifdef CONFIG_BCM47XX
     1854        uasm_i_nop(p);
     1855#endif
    18501856#ifdef CONFIG_64BIT
    18511857        build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
    18521858#else
Note: See TracBrowser for help on using the repository browser.