[BACK]Return to cache_sh4.c CVS log [TXT][DIR] Up to [local] / sys / arch / sh / sh

Annotation of sys/arch/sh/sh/cache_sh4.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cache_sh4.c,v 1.3 2007/03/19 20:12:43 miod Exp $      */
        !             2: /*     $NetBSD: cache_sh4.c,v 1.15 2005/12/24 23:24:02 perry Exp $     */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2002 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by UCHIYAMA Yasushi.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42:
        !            43: #include <sh/cache.h>
        !            44: #include <sh/cache_sh4.h>
        !            45:
        !            46: #define        round_line(x)           (((x) + 31) & ~31)
        !            47: #define        trunc_line(x)           ((x) & ~31)
        !            48:
        !            49: void sh4_icache_sync_all(void);
        !            50: void sh4_icache_sync_range(vaddr_t, vsize_t);
        !            51: void sh4_icache_sync_range_index(vaddr_t, vsize_t);
        !            52: void sh4_dcache_wbinv_all(void);
        !            53: void sh4_dcache_wbinv_range(vaddr_t, vsize_t);
        !            54: void sh4_dcache_wbinv_range_index(vaddr_t, vsize_t);
        !            55: void sh4_dcache_inv_range(vaddr_t, vsize_t);
        !            56: void sh4_dcache_wb_range(vaddr_t, vsize_t);
        !            57:
        !            58: /* EMODE */
        !            59: void sh4_emode_icache_sync_all(void);
        !            60: void sh4_emode_icache_sync_range_index(vaddr_t, vsize_t);
        !            61: void sh4_emode_dcache_wbinv_all(void);
        !            62: void sh4_emode_dcache_wbinv_range_index(vaddr_t, vsize_t);
        !            63:
        !            64: /* must be inlined. */
        !            65: static inline void cache_sh4_op_line_32(vaddr_t, vaddr_t, uint32_t,
        !            66:     uint32_t);
        !            67: static inline void cache_sh4_op_8lines_32(vaddr_t, vaddr_t, uint32_t,
        !            68:     uint32_t);
        !            69: static inline void cache_sh4_emode_op_line_32(vaddr_t, vaddr_t,
        !            70:     uint32_t, uint32_t, uint32_t);
        !            71: static inline void cache_sh4_emode_op_8lines_32(vaddr_t, vaddr_t,
        !            72:     uint32_t, uint32_t, uint32_t);
        !            73:
        !            74: void
        !            75: sh4_cache_config(void)
        !            76: {
        !            77:        int icache_size;
        !            78:        int dcache_size;
        !            79:        int ways;
        !            80:        uint32_t r;
        !            81:
        !            82:         /* Determine cache size */
        !            83:        switch (cpu_product) {
        !            84:        default:
        !            85:                /* FALLTHROUGH */
        !            86:        case CPU_PRODUCT_7750:
        !            87:        case CPU_PRODUCT_7750S:
        !            88:        case CPU_PRODUCT_7751:
        !            89: #if defined(SH4_CACHE_DISABLE_EMODE)
        !            90:        case CPU_PRODUCT_7750R:
        !            91:        case CPU_PRODUCT_7751R:
        !            92: #endif
        !            93:                icache_size = SH4_ICACHE_SIZE;
        !            94:                dcache_size = SH4_DCACHE_SIZE;
        !            95:                ways = 1;
        !            96:                r = SH4_CCR_ICE|SH4_CCR_OCE|SH4_CCR_WT;
        !            97:                break;
        !            98:
        !            99: #if !defined(SH4_CACHE_DISABLE_EMODE)
        !           100:        case CPU_PRODUCT_7750R:
        !           101:        case CPU_PRODUCT_7751R:
        !           102:                icache_size = SH4_EMODE_ICACHE_SIZE;
        !           103:                dcache_size = SH4_EMODE_DCACHE_SIZE;
        !           104:                ways = 2;
        !           105:                r = SH4_CCR_EMODE|SH4_CCR_ICE|SH4_CCR_OCE|SH4_CCR_WT;
        !           106:                break;
        !           107: #endif
        !           108:        }
        !           109: #if defined(SH4_CACHE_DISABLE_ICACHE)
        !           110:        r &= ~SH4_CCR_ICE;
        !           111: #endif
        !           112: #if defined(SH4_CACHE_DISABLE_DCACHE)
        !           113:        r &= ~SH4_CCR_OCE;
        !           114: #endif
        !           115: #if !defined (SH4_CACHE_WT)
        !           116: #define        SH4_CACHE_WB_U0_P0_P3
        !           117: #define        SH4_CACHE_WB_P1
        !           118: #endif
        !           119: #if defined(SH4_CACHE_WB_U0_P0_P3)
        !           120:        r &= ~SH4_CCR_WT;
        !           121: #endif
        !           122: #if defined(SH4_CACHE_WB_P1)
        !           123:        r |= SH4_CCR_CB;
        !           124: #endif
        !           125:
        !           126:        sh4_icache_sync_all();
        !           127:        RUN_P2;
        !           128:        _reg_write_4(SH4_CCR, SH4_CCR_ICI|SH4_CCR_OCI);
        !           129:        _reg_write_4(SH4_CCR, r);
        !           130:        RUN_P1;
        !           131:
        !           132:        r = _reg_read_4(SH4_CCR);
        !           133:
        !           134:        sh_cache_unified = 0;
        !           135:        sh_cache_enable_icache = (r & SH4_CCR_ICE);
        !           136:        sh_cache_enable_dcache = (r & SH4_CCR_OCE);
        !           137:        sh_cache_ways = ways;
        !           138:        sh_cache_line_size = SH4_CACHE_LINESZ;
        !           139:        sh_cache_prefer_mask = (dcache_size / ways - 1);
        !           140:        sh_cache_write_through_p0_u0_p3 = (r & SH4_CCR_WT);
        !           141:        sh_cache_write_through_p1 = !(r & SH4_CCR_CB);
        !           142:        sh_cache_write_through = sh_cache_write_through_p0_u0_p3 &&
        !           143:            sh_cache_write_through_p1;
        !           144:        sh_cache_ram_mode = (r & SH4_CCR_ORA);
        !           145:        sh_cache_index_mode_icache = (r & SH4_CCR_IIX);
        !           146:        sh_cache_index_mode_dcache = (r & SH4_CCR_OIX);
        !           147:
        !           148:        sh_cache_size_dcache = dcache_size;
        !           149:        if (sh_cache_ram_mode)
        !           150:                sh_cache_size_dcache /= 2;
        !           151:        sh_cache_size_icache = icache_size;
        !           152:
        !           153:        sh_cache_ops._icache_sync_all           = sh4_icache_sync_all;
        !           154:        sh_cache_ops._icache_sync_range         = sh4_icache_sync_range;
        !           155:        sh_cache_ops._icache_sync_range_index   = sh4_icache_sync_range_index;
        !           156:
        !           157:        sh_cache_ops._dcache_wbinv_all          = sh4_dcache_wbinv_all;
        !           158:        sh_cache_ops._dcache_wbinv_range        = sh4_dcache_wbinv_range;
        !           159:        sh_cache_ops._dcache_wbinv_range_index  = sh4_dcache_wbinv_range_index;
        !           160:        sh_cache_ops._dcache_inv_range          = sh4_dcache_inv_range;
        !           161:        sh_cache_ops._dcache_wb_range           = sh4_dcache_wb_range;
        !           162:
        !           163:        switch (cpu_product) {
        !           164:        case CPU_PRODUCT_7750R:
        !           165:        case CPU_PRODUCT_7751R:
        !           166:                if (!(r & SH4_CCR_EMODE)) {
        !           167:                        break;
        !           168:                }
        !           169:                sh_cache_ops._icache_sync_all = sh4_emode_icache_sync_all;
        !           170:                sh_cache_ops._icache_sync_range_index = sh4_emode_icache_sync_range_index;
        !           171:                sh_cache_ops._dcache_wbinv_all = sh4_emode_dcache_wbinv_all;
        !           172:                sh_cache_ops._dcache_wbinv_range_index = sh4_emode_dcache_wbinv_range_index;
        !           173:                break;
        !           174:        }
        !           175: }
        !           176:
        !           177: /*
        !           178:  * cache_sh4_op_line_32: (index-operation)
        !           179:  *
        !           180:  *     Clear the specified bits on single 32-byte cache line.
        !           181:  */
        !           182: static inline void
        !           183: cache_sh4_op_line_32(vaddr_t va, vaddr_t base, uint32_t mask, uint32_t bits)
        !           184: {
        !           185:        vaddr_t cca;
        !           186:
        !           187:        cca = base | (va & mask);
        !           188:        _reg_bclr_4(cca, bits);
        !           189: }
        !           190:
        !           191: /*
        !           192:  * cache_sh4_op_8lines_32: (index-operation)
        !           193:  *
        !           194:  *     Clear the specified bits on 8 32-byte cache lines.
        !           195:  */
        !           196: static inline void
        !           197: cache_sh4_op_8lines_32(vaddr_t va, vaddr_t base, uint32_t mask, uint32_t bits)
        !           198: {
        !           199:        volatile uint32_t *cca = (volatile uint32_t *)
        !           200:            (base | (va & mask));
        !           201:
        !           202:        cca[ 0] &= ~bits;
        !           203:        cca[ 8] &= ~bits;
        !           204:        cca[16] &= ~bits;
        !           205:        cca[24] &= ~bits;
        !           206:        cca[32] &= ~bits;
        !           207:        cca[40] &= ~bits;
        !           208:        cca[48] &= ~bits;
        !           209:        cca[56] &= ~bits;
        !           210: }
        !           211:
        !           212: void
        !           213: sh4_icache_sync_all(void)
        !           214: {
        !           215:        vaddr_t va = 0;
        !           216:        vaddr_t eva = SH4_ICACHE_SIZE;
        !           217:
        !           218:        sh4_dcache_wbinv_all();
        !           219:
        !           220:        RUN_P2;
        !           221:        while (va < eva) {
        !           222:                cache_sh4_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V);
        !           223:                va += 32 * 8;
        !           224:        }
        !           225:        RUN_P1;
        !           226: }
        !           227:
        !           228: void
        !           229: sh4_icache_sync_range(vaddr_t va, vsize_t sz)
        !           230: {
        !           231:        vaddr_t ccia;
        !           232:        vaddr_t eva = round_line(va + sz);
        !           233:        va = trunc_line(va);
        !           234:
        !           235:        sh4_dcache_wbinv_range(va, (eva - va));
        !           236:
        !           237:        RUN_P2;
        !           238:        while (va < eva) {
        !           239:                /* CCR.IIX has no effect on this entry specification */
        !           240:                ccia = SH4_CCIA | CCIA_A | (va & CCIA_ENTRY_MASK);
        !           241:                _reg_write_4(ccia, va & CCIA_TAGADDR_MASK); /* V = 0 */
        !           242:                va += 32;
        !           243:        }
        !           244:        RUN_P1;
        !           245: }
        !           246:
        !           247: void
        !           248: sh4_icache_sync_range_index(vaddr_t va, vsize_t sz)
        !           249: {
        !           250:        vaddr_t eva = round_line(va + sz);
        !           251:        va = trunc_line(va);
        !           252:
        !           253:        sh4_dcache_wbinv_range_index(va, eva - va);
        !           254:
        !           255:        RUN_P2;
        !           256:        while ((eva - va) >= (8 * 32)) {
        !           257:                cache_sh4_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V);
        !           258:                va += 32 * 8;
        !           259:        }
        !           260:
        !           261:        while (va < eva) {
        !           262:                cache_sh4_op_line_32(va, SH4_CCIA, CCIA_ENTRY_MASK, CCIA_V);
        !           263:                va += 32;
        !           264:        }
        !           265:        RUN_P1;
        !           266: }
        !           267:
        !           268: void
        !           269: sh4_dcache_wbinv_all(void)
        !           270: {
        !           271:        vaddr_t va = 0;
        !           272:        vaddr_t eva = SH4_DCACHE_SIZE;
        !           273:
        !           274:        RUN_P2;
        !           275:        while (va < eva) {
        !           276:                cache_sh4_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           277:                    (CCDA_U | CCDA_V));
        !           278:                va += 32 * 8;
        !           279:        }
        !           280:        RUN_P1;
        !           281: }
        !           282:
        !           283: void
        !           284: sh4_dcache_wbinv_range(vaddr_t va, vsize_t sz)
        !           285: {
        !           286:        vaddr_t eva = round_line(va + sz);
        !           287:        va = trunc_line(va);
        !           288:
        !           289:        while (va < eva) {
        !           290:                __asm volatile("ocbp @%0" : : "r"(va));
        !           291:                va += 32;
        !           292:        }
        !           293: }
        !           294:
        !           295: void
        !           296: sh4_dcache_wbinv_range_index(vaddr_t va, vsize_t sz)
        !           297: {
        !           298:        vaddr_t eva = round_line(va + sz);
        !           299:        va = trunc_line(va);
        !           300:
        !           301:        RUN_P2;
        !           302:        while ((eva - va) >= (8 * 32)) {
        !           303:                cache_sh4_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           304:                    (CCDA_U | CCDA_V));
        !           305:                va += 32 * 8;
        !           306:        }
        !           307:
        !           308:        while (va < eva) {
        !           309:                cache_sh4_op_line_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           310:                    (CCDA_U | CCDA_V));
        !           311:                va += 32;
        !           312:        }
        !           313:        RUN_P1;
        !           314: }
        !           315:
        !           316: void
        !           317: sh4_dcache_inv_range(vaddr_t va, vsize_t sz)
        !           318: {
        !           319:        vaddr_t eva = round_line(va + sz);
        !           320:        va = trunc_line(va);
        !           321:
        !           322:        while (va < eva) {
        !           323:                __asm volatile("ocbi @%0" : : "r"(va));
        !           324:                va += 32;
        !           325:        }
        !           326: }
        !           327:
        !           328: void
        !           329: sh4_dcache_wb_range(vaddr_t va, vsize_t sz)
        !           330: {
        !           331:        vaddr_t eva = round_line(va + sz);
        !           332:        va = trunc_line(va);
        !           333:
        !           334:        while (va < eva) {
        !           335:                __asm volatile("ocbwb @%0" : : "r"(va));
        !           336:                va += 32;
        !           337:        }
        !           338: }
        !           339:
        !           340: /*
        !           341:  * EMODE operation
        !           342:  */
        !           343: /*
        !           344:  * cache_sh4_emode_op_line_32: (index-operation)
        !           345:  *
        !           346:  *     Clear the specified bits on single 32-byte cache line. 2-ways.
        !           347:  */
        !           348: static inline void
        !           349: cache_sh4_emode_op_line_32(vaddr_t va, vaddr_t base, uint32_t mask,
        !           350:     uint32_t bits, uint32_t way_shift)
        !           351: {
        !           352:        vaddr_t cca;
        !           353:
        !           354:        /* extract entry # */
        !           355:        va &= mask;
        !           356:
        !           357:        /* operate for each way */
        !           358:        cca = base | (0 << way_shift) | va;
        !           359:        _reg_bclr_4(cca, bits);
        !           360:
        !           361:        cca = base | (1 << way_shift) | va;
        !           362:        _reg_bclr_4(cca, bits);
        !           363: }
        !           364:
        !           365: /*
        !           366:  * cache_sh4_emode_op_8lines_32: (index-operation)
        !           367:  *
        !           368:  *     Clear the specified bits on 8 32-byte cache lines. 2-ways.
        !           369:  */
        !           370: static inline void
        !           371: cache_sh4_emode_op_8lines_32(vaddr_t va, vaddr_t base, uint32_t mask,
        !           372:     uint32_t bits, uint32_t way_shift)
        !           373: {
        !           374:        volatile uint32_t *cca;
        !           375:
        !           376:        /* extract entry # */
        !           377:        va &= mask;
        !           378:
        !           379:        /* operate for each way */
        !           380:        cca = (volatile uint32_t *)(base | (0 << way_shift) | va);
        !           381:        cca[ 0] &= ~bits;
        !           382:        cca[ 8] &= ~bits;
        !           383:        cca[16] &= ~bits;
        !           384:        cca[24] &= ~bits;
        !           385:        cca[32] &= ~bits;
        !           386:        cca[40] &= ~bits;
        !           387:        cca[48] &= ~bits;
        !           388:        cca[56] &= ~bits;
        !           389:
        !           390:        cca = (volatile uint32_t *)(base | (1 << way_shift) | va);
        !           391:        cca[ 0] &= ~bits;
        !           392:        cca[ 8] &= ~bits;
        !           393:        cca[16] &= ~bits;
        !           394:        cca[24] &= ~bits;
        !           395:        cca[32] &= ~bits;
        !           396:        cca[40] &= ~bits;
        !           397:        cca[48] &= ~bits;
        !           398:        cca[56] &= ~bits;
        !           399: }
        !           400:
        !           401: void
        !           402: sh4_emode_icache_sync_all(void)
        !           403: {
        !           404:        vaddr_t va = 0;
        !           405:        vaddr_t eva = SH4_EMODE_ICACHE_SIZE;
        !           406:
        !           407:        sh4_emode_dcache_wbinv_all();
        !           408:
        !           409:        RUN_P2;
        !           410:        while (va < eva) {
        !           411:                cache_sh4_emode_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK,
        !           412:                    CCIA_V, 13);
        !           413:                va += 32 * 8;
        !           414:        }
        !           415:        RUN_P1;
        !           416: }
        !           417:
        !           418: void
        !           419: sh4_emode_icache_sync_range_index(vaddr_t va, vsize_t sz)
        !           420: {
        !           421:        vaddr_t eva = round_line(va + sz);
        !           422:        va = trunc_line(va);
        !           423:
        !           424:        sh4_emode_dcache_wbinv_range_index(va, eva - va);
        !           425:
        !           426:        RUN_P2;
        !           427:        while ((eva - va) >= (8 * 32)) {
        !           428:                cache_sh4_emode_op_8lines_32(va, SH4_CCIA, CCIA_ENTRY_MASK,
        !           429:                    CCIA_V, 13);
        !           430:                va += 32 * 8;
        !           431:        }
        !           432:
        !           433:        while (va < eva) {
        !           434:                cache_sh4_emode_op_line_32(va, SH4_CCIA, CCIA_ENTRY_MASK,
        !           435:                    CCIA_V, 13);
        !           436:                va += 32;
        !           437:        }
        !           438:        RUN_P1;
        !           439: }
        !           440:
        !           441: void
        !           442: sh4_emode_dcache_wbinv_all(void)
        !           443: {
        !           444:        vaddr_t va = 0;
        !           445:        vaddr_t eva = SH4_EMODE_DCACHE_SIZE;
        !           446:
        !           447:        RUN_P2;
        !           448:        while (va < eva) {
        !           449:                cache_sh4_emode_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           450:                    (CCDA_U | CCDA_V), 14);
        !           451:                va += 32 * 8;
        !           452:        }
        !           453:        RUN_P1;
        !           454: }
        !           455:
        !           456: void
        !           457: sh4_emode_dcache_wbinv_range_index(vaddr_t va, vsize_t sz)
        !           458: {
        !           459:        vaddr_t eva = round_line(va + sz);
        !           460:        va = trunc_line(va);
        !           461:
        !           462:        RUN_P2;
        !           463:        while ((eva - va) >= (8 * 32)) {
        !           464:                cache_sh4_emode_op_8lines_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           465:                    (CCDA_U | CCDA_V), 14);
        !           466:                va += 32 * 8;
        !           467:        }
        !           468:
        !           469:        while (va < eva) {
        !           470:                cache_sh4_emode_op_line_32(va, SH4_CCDA, CCDA_ENTRY_MASK,
        !           471:                    (CCDA_U | CCDA_V), 14);
        !           472:                va += 32;
        !           473:        }
        !           474:        RUN_P1;
        !           475: }

CVSweb