Path: blob/master/arch/mn10300/mm/cache-flush-by-reg.S
10817 views
/* MN10300 CPU core caching routines, using indirect regs on cache controller1*2* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public Licence7* as published by the Free Software Foundation; either version8* 2 of the Licence, or (at your option) any later version.9*/1011#include <linux/sys.h>12#include <linux/linkage.h>13#include <asm/smp.h>14#include <asm/page.h>15#include <asm/cache.h>16#include <asm/irqflags.h>1718.am33_21920#ifndef CONFIG_SMP21.globl mn10300_dcache_flush22.globl mn10300_dcache_flush_page23.globl mn10300_dcache_flush_range24.globl mn10300_dcache_flush_range225.globl mn10300_dcache_flush_inv26.globl mn10300_dcache_flush_inv_page27.globl mn10300_dcache_flush_inv_range28.globl mn10300_dcache_flush_inv_range22930mn10300_dcache_flush = mn10300_local_dcache_flush31mn10300_dcache_flush_page = mn10300_local_dcache_flush_page32mn10300_dcache_flush_range = mn10300_local_dcache_flush_range33mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range234mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv35mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page36mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range37mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range23839#endif /* !CONFIG_SMP */4041###############################################################################42#43# void mn10300_local_dcache_flush(void)44# Flush the entire data cache back to RAM45#46###############################################################################47ALIGN48.globl mn10300_local_dcache_flush49.type mn10300_local_dcache_flush,@function50mn10300_local_dcache_flush:51movhu (CHCTR),d052btst CHCTR_DCEN,d053beq mn10300_local_dcache_flush_end5455mov DCPGCR,a05657LOCAL_CLI_SAVE(d1)5859# wait for busy bit of area purge60setlb61mov (a0),d062btst DCPGCR_DCPGBSY,d063lne6465# set mask66clr d067mov d0,(DCPGMR)6869# area purge70#71# DCPGCR = DCPGCR_DCP72#73mov DCPGCR_DCP,d074mov d0,(a0)7576# wait for busy bit of area purge77setlb78mov (a0),d079btst DCPGCR_DCPGBSY,d080lne8182LOCAL_IRQ_RESTORE(d1)8384mn10300_local_dcache_flush_end:85ret [],086.size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush8788###############################################################################89#90# void mn10300_local_dcache_flush_page(unsigned long start)91# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)92# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)93# Flush a range of addresses on a page in the dcache94#95###############################################################################96ALIGN97.globl mn10300_local_dcache_flush_page98.globl mn10300_local_dcache_flush_range99.globl mn10300_local_dcache_flush_range2100.type mn10300_local_dcache_flush_page,@function101.type mn10300_local_dcache_flush_range,@function102.type mn10300_local_dcache_flush_range2,@function103mn10300_local_dcache_flush_page:104and ~(PAGE_SIZE-1),d0105mov PAGE_SIZE,d1106mn10300_local_dcache_flush_range2:107add d0,d1108mn10300_local_dcache_flush_range:109movm [d2,d3,a2],(sp)110111movhu (CHCTR),d2112btst CHCTR_DCEN,d2113beq mn10300_local_dcache_flush_range_end114115# calculate alignsize116#117# alignsize = L1_CACHE_BYTES;118# for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1)119# alignsize <<= 1;120# d2 = alignsize;121#122mov L1_CACHE_BYTES,d2123sub d0,d1,d3124add -1,d3125lsr L1_CACHE_SHIFT,d3126beq 2f1271:128add d2,d2129lsr 1,d3130bne 1b1312:132mov d1,a1 # a1 = end133134LOCAL_CLI_SAVE(d3)135mov DCPGCR,a0136137# wait for busy bit of area purge138setlb139mov (a0),d1140btst DCPGCR_DCPGBSY,d1141lne142143# determine the mask144mov d2,d1145add -1,d1146not d1 # d1 = mask = ~(alignsize-1)147mov d1,(DCPGMR)148149and d1,d0,a2 # a2 = mask & start150151dcpgloop:152# area purge153mov a2,d0154or DCPGCR_DCP,d0155mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP156157# wait for busy bit of area purge158setlb159mov (a0),d1160btst DCPGCR_DCPGBSY,d1161lne162163# check purge of end address164add d2,a2 # a2 += alignsize165cmp a1,a2 # if (a2 < end) goto dcpgloop166bns dcpgloop167168LOCAL_IRQ_RESTORE(d3)169170mn10300_local_dcache_flush_range_end:171ret [d2,d3,a2],12172173.size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page174.size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range175.size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2176177###############################################################################178#179# void mn10300_local_dcache_flush_inv(void)180# Flush the entire data cache and invalidate all entries181#182###############################################################################183ALIGN184.globl mn10300_local_dcache_flush_inv185.type mn10300_local_dcache_flush_inv,@function186mn10300_local_dcache_flush_inv:187movhu (CHCTR),d0188btst CHCTR_DCEN,d0189beq mn10300_local_dcache_flush_inv_end190191mov DCPGCR,a0192193LOCAL_CLI_SAVE(d1)194195# wait for busy bit of area purge & invalidate196setlb197mov (a0),d0198btst DCPGCR_DCPGBSY,d0199lne200201# set the mask to cover everything202clr d0203mov d0,(DCPGMR)204205# area purge & invalidate206mov DCPGCR_DCP|DCPGCR_DCI,d0207mov d0,(a0)208209# wait for busy bit of area purge & invalidate210setlb211mov (a0),d0212btst DCPGCR_DCPGBSY,d0213lne214215LOCAL_IRQ_RESTORE(d1)216217mn10300_local_dcache_flush_inv_end:218ret [],0219.size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv220221###############################################################################222#223# void mn10300_local_dcache_flush_inv_page(unsigned long start)224# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)225# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)226# Flush and invalidate a range of addresses on a page in the dcache227#228###############################################################################229ALIGN230.globl mn10300_local_dcache_flush_inv_page231.globl mn10300_local_dcache_flush_inv_range232.globl mn10300_local_dcache_flush_inv_range2233.type mn10300_local_dcache_flush_inv_page,@function234.type mn10300_local_dcache_flush_inv_range,@function235.type mn10300_local_dcache_flush_inv_range2,@function236mn10300_local_dcache_flush_inv_page:237and ~(PAGE_SIZE-1),d0238mov PAGE_SIZE,d1239mn10300_local_dcache_flush_inv_range2:240add d0,d1241mn10300_local_dcache_flush_inv_range:242movm [d2,d3,a2],(sp)243244movhu (CHCTR),d2245btst CHCTR_DCEN,d2246beq mn10300_local_dcache_flush_inv_range_end247248# calculate alignsize249#250# alignsize = L1_CACHE_BYTES;251# for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)252# alignsize <<= 1;253# d2 = alignsize254#255mov L1_CACHE_BYTES,d2256sub d0,d1,d3257add -1,d3258lsr L1_CACHE_SHIFT,d3259beq 2f2601:261add d2,d2262lsr 1,d3263bne 1b2642:265mov d1,a1 # a1 = end266267LOCAL_CLI_SAVE(d3)268mov DCPGCR,a0269270# wait for busy bit of area purge & invalidate271setlb272mov (a0),d1273btst DCPGCR_DCPGBSY,d1274lne275276# set the mask277mov d2,d1278add -1,d1279not d1 # d1 = mask = ~(alignsize-1)280mov d1,(DCPGMR)281282and d1,d0,a2 # a2 = mask & start283284dcpgivloop:285# area purge & invalidate286mov a2,d0287or DCPGCR_DCP|DCPGCR_DCI,d0288mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI289290# wait for busy bit of area purge & invalidate291setlb292mov (a0),d1293btst DCPGCR_DCPGBSY,d1294lne295296# check purge & invalidate of end address297add d2,a2 # a2 += alignsize298cmp a1,a2 # if (a2 < end) goto dcpgivloop299bns dcpgivloop300301LOCAL_IRQ_RESTORE(d3)302303mn10300_local_dcache_flush_inv_range_end:304ret [d2,d3,a2],12305.size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page306.size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range307.size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2308309310