diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-03-26 06:18:51 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-03-26 10:40:48 +0200 |
commit | 11fe8c59c6c145bca52e977363183add0fbe1b59 (patch) | |
tree | aa9810f50d832df7cd5af8befd9acc05e430fb14 /c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c | |
parent | bsp/tqm8xx: Move libcpu content to bsps (diff) | |
download | rtems-11fe8c59c6c145bca52e977363183add0fbe1b59.tar.bz2 |
bsps/powerpc: Move MMU support to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c')
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c b/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c deleted file mode 100644 index 7a9487b9ff..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * bat.c - * - * This file contains the implementation of C function to - * Instantiate 60x/7xx ppc Block Address Translation (BAT) registers. - * More detailed information can be found on motorola - * site and more precisely in the following book : - * - * MPC750 - * Risc Microporcessor User's Manual - * Mtorola REF : MPC750UM/AD 8/97 - * - * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr) - * Canon Centre Recherche France. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ -#include <rtems.h> -#include <libcpu/bat.h> -#include <libcpu/spr.h> -#include <rtems/bspIo.h> - -#include <libcpu/cpuIdent.h> - -#define TYP_I 1 -#define TYP_D 0 - -typedef union -{ /* BAT register values to be loaded */ - BAT bat; - struct - { - unsigned int u, l; - } words; -} ubat; - -typedef struct batrange -{ /* stores address ranges mapped by BATs */ - unsigned long start; - unsigned long limit; - unsigned long phys; -} batrange; - -batrange bat_addrs[2][8] = { { {0,} } }; - -/* could encode this in bat_addrs but I don't touch that one for bwds compat. reasons */ -/* bitmask of used bats */ -static unsigned bat_in_use[2] = { 0, 0 }; - -/* define a few macros */ - -#define CLRBAT_ASM(batu,r) \ - " sync \n" \ - " isync \n" \ - " li "#r ", 0 \n" \ - " mtspr "#batu ", "#r "\n" \ - " sync \n" \ - " isync \n" - -#define SETBAT_ASM(batu, batl, u, l)\ - " mtspr "#batl ", "#l " \n" \ - " sync \n" \ - " isync \n" \ - " mtspr "#batu ", "#u " \n" \ - " sync \n" \ - " isync \n" - -#define CLRBAT(bat) \ - asm volatile( \ - CLRBAT_ASM(%0, 0) \ - : \ - :"i"(bat##U) \ - :"0") - -#define GETBAT(bat,u,l) \ - asm volatile( \ - " mfspr %0, %2 \n" \ - " mfspr %1, %3 \n" \ - :"=r"(u),"=r"(l) \ - :"i"(bat##U),"i"(bat##L) \ - ) - -#define DECL_SETBAT(lcbat,bat) \ -void \ -asm_set##lcbat(unsigned int upper, unsigned int lower) \ -{ \ -asm volatile( \ - CLRBAT_ASM(%0,0) \ - SETBAT_ASM(%0,%1,%2,%3) \ - : \ - :"i"(bat##U), \ - "i"(bat##L), \ - "r"(upper),"r"(lower) \ - :"0"); \ -} - -/* export the 'asm' versions for historic reasons */ -DECL_SETBAT (dbat0, DBAT0) -DECL_SETBAT (dbat1, DBAT1) -DECL_SETBAT (dbat2, DBAT2) -DECL_SETBAT (dbat3, DBAT3) - -static DECL_SETBAT (dbat4, DBAT4) -static DECL_SETBAT (dbat5, DBAT5) -static DECL_SETBAT (dbat6, DBAT6) -static DECL_SETBAT (dbat7, DBAT7) - -static DECL_SETBAT (ibat0, IBAT0) -static DECL_SETBAT (ibat1, IBAT1) -static DECL_SETBAT (ibat2, IBAT2) -static DECL_SETBAT (ibat3, IBAT3) -static DECL_SETBAT (ibat4, IBAT4) -static DECL_SETBAT (ibat5, IBAT5) -static DECL_SETBAT (ibat6, IBAT6) -static DECL_SETBAT (ibat7, IBAT7) - - -SPR_RO (HID0); - -static void -set_hid0_sync (unsigned long val) -{ - __asm__ volatile ( - " sync \n" - " isync \n" - " mtspr %0, %1 \n" - " sync \n" - " isync \n" - : - :"i" (HID0), "r" (val) - :"memory" /* paranoia */ - ); -} - -static void -bat_addrs_put (ubat * bat, int typ, int idx) -{ - unsigned long bl; - if (bat->bat.batu.vp || bat->bat.batu.vs) { - bat_addrs[typ][idx].start = bat->bat.batu.bepi << 17; - bat_addrs[typ][idx].phys = bat->bat.batl.brpn << 17; - - /* extended BL cannot be extracted using BAT union - * - let's just hope the upper bits read 0 on pre 745x - * CPUs. - */ - bl = (bat->words.u << 15) | ((1 << 17) - 1); - bat_addrs[typ][idx].limit = bat_addrs[typ][idx].start + bl; - - bat_in_use[typ] |= (1 << idx); - } -} - -/* We don't know how the board was initialized. Therefore, - * when 'setdbat' is first used we must initialize our - * cache. - */ -static void -bat_addrs_init (void) -{ - ubat bat; - - GETBAT (DBAT0, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 0); - GETBAT (DBAT1, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 1); - GETBAT (DBAT2, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 2); - GETBAT (DBAT3, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 3); - - GETBAT (IBAT0, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 0); - GETBAT (IBAT1, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 1); - GETBAT (IBAT2, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 2); - GETBAT (IBAT3, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 3); - - - if ( ppc_cpu_has_8_bats() && (HID0_7455_HIGH_BAT_EN & _read_HID0 ())) { - GETBAT (DBAT4, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 4); - GETBAT (DBAT5, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 5); - GETBAT (DBAT6, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 6); - GETBAT (DBAT7, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_D, 7); - GETBAT (IBAT4, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 4); - GETBAT (IBAT5, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 5); - GETBAT (IBAT6, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 6); - GETBAT (IBAT7, bat.words.u, bat.words.l); - bat_addrs_put (&bat, TYP_I, 7); - } -} - -static void -do_dssall (void) -{ - /* Before changing BATs, 'dssall' must be issued. - * We check MSR for MSR_VE and issue a 'dssall' if - * MSR_VE is set hoping that - * a) on non-altivec CPUs MSR_VE reads as zero - * b) all altivec CPUs use the same bit - * NOTE: psim doesn't implement dssall so we skip if we run on psim - */ - if ( (_read_MSR () & MSR_VE) && PPC_PSIM != get_ppc_cpu_type() ) { - /* this construct is needed because we don't know - * if this file is compiled with -maltivec. - * (I plan to add altivec support outside of - * RTEMS core and hence I'd rather not - * rely on consistent compiler flags). - */ -#define DSSALL 0x7e00066c /* dssall opcode */ - __asm__ volatile (" .long %0"::"i" (DSSALL)); -#undef DSSALL - } -} - -/* Clear I/D bats 4..7 ONLY ON 7455 etc. */ -static void -clear_hi_bats (void) -{ - do_dssall (); - CLRBAT (DBAT4); - CLRBAT (DBAT5); - CLRBAT (DBAT6); - CLRBAT (DBAT7); - CLRBAT (IBAT4); - CLRBAT (IBAT5); - CLRBAT (IBAT6); - CLRBAT (IBAT7); -} - -static int -check_bat_index (int i) -{ - unsigned long hid0; - - if (i >= 0 && i < 4) - return 0; - if (i >= 4 && i < 8) { - if ( ! ppc_cpu_has_8_bats() ) - return -1; - /* OK, we're on the right hardware; - * check if we are already enabled - */ - hid0 = _read_HID0 (); - if (HID0_7455_HIGH_BAT_EN & hid0) - return 0; - /* No; enable now */ - clear_hi_bats (); - set_hid0_sync (hid0 | HID0_7455_HIGH_BAT_EN); - return 0; - } - return -1; -} - -/* size argument check: - * - must be a power of two or zero - * - must be <= 1<<28 ( non 745x cpu ) - * - can be 1<<29..1<31 or 0xffffffff on 745x - * - size < 1<<17 means 0 - * computes and returns the block mask - * RETURNS: - * block mask on success or -1 on error - */ -static int -check_bat_size (unsigned long size) -{ - unsigned long bit; - unsigned long hid0; - - /* First of all, it must be a power of two */ - if (0 == size) - return 0; - - if (0xffffffff == size) { - bit = 32; - } else { - __asm__ volatile (" cntlzw %0, %1":"=r" (bit):"r" (size)); - bit = 31 - bit; - if (1 << bit != size) - return -1; - } - /* bit < 17 is not really legal but we aliased it to 0 in the past */ - if (bit > (11 + 17)) { - if ( ! ppc_cpu_has_8_bats() ) - return -1; - - hid0 = _read_HID0 (); - /* Let's enable the larger block size if necessary */ - if (!(HID0_7455_XBSEN & hid0)) - set_hid0_sync (hid0 | HID0_7455_XBSEN); - } - - return (1 << (bit - 17)) - 1; -} - -static int -check_overlap (int typ, unsigned long start, unsigned long size) -{ - int i; - unsigned long limit = start + size - 1; - for (i = 0; i < sizeof (bat_addrs[typ]) / sizeof (bat_addrs[typ][0]); i++) { - if (!((1 << i) & bat_in_use[typ])) - continue; /* unused bat */ - /* safe is 'limit < bat_addrs[t][i].start || start > bat_addrs[t][i].limit */ - if (limit >= bat_addrs[typ][i].start && start <= bat_addrs[typ][i].limit) - return i; - } - return -1; -} - - -/* Take no risks -- the essential parts of this routine run with - * interrupts disabled! - */ - -static int -setbat (int typ, int bat_index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) -{ - unsigned long level; - unsigned int bl; - int err; - int wimgxpp; - ubat bat; - - if (check_bat_index (bat_index)) { - printk ("Invalid BAT index %d\n", bat_index); - return -1; - } - - if ((int) (bl = check_bat_size (size)) < 0) { - printk ("Invalid BAT size %u\n", size); - return -1; - } - - if (virt & (size - 1)) { - printk ("BAT effective address 0x%08lx misaligned (size is 0x%08x)\n", - virt, size); - return -1; - } - - if (phys & (size - 1)) { - printk ("BAT physical address 0x%08lx misaligned (size is 0x%08x)\n", phys, - size); - return -1; - } - - if (virt + size - 1 < virt) { - printk ("BAT range invalid: wraps around zero 0x%08lx..0x%08lx\n", virt, - virt + size - 1); - return -1; - } - - if ( TYP_I == typ && ( ( _PAGE_GUARDED | _PAGE_WRITETHRU ) & flags ) ) { - printk("IBAT must not have 'guarded' or 'writethrough' attribute\n"); - return -1; - } - -/* must protect the bat_addrs table -- since this routine is only used for board setup - * or similar special purposes we don't bother about interrupt latency too much. - */ - rtems_interrupt_disable (level); - - { /* might have to initialize our cached data */ - static char init_done = 0; - if (!init_done) { - bat_addrs_init (); - init_done = 1; - } - } - - err = check_overlap (typ, virt, size); - if ((size >= (1 << 17)) && (err >= 0) && (err != bat_index)) { - rtems_interrupt_enable (level); - printk ("BATs must not overlap; area 0x%08lx..0x%08lx hits %cBAT %i\n", - virt, virt + size, (TYP_I == typ ? 'I' : 'D'), err); - return -1; - } - - /* 603, 604, etc. */ - wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE - | _PAGE_COHERENT | _PAGE_GUARDED); - wimgxpp |= (flags & _PAGE_RW) ? BPP_RW : BPP_RX; - bat.words.u = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ - bat.words.l = phys | wimgxpp; - if (flags & _PAGE_USER) - bat.bat.batu.vp = 1; - bat_addrs[typ][bat_index].start = virt; - bat_addrs[typ][bat_index].limit = virt + ((bl + 1) << 17) - 1; - bat_addrs[typ][bat_index].phys = phys; - bat_in_use[typ] |= 1 << bat_index; - if (size < (1 << 17)) { - /* size of 0 tells us to switch it off */ - bat.bat.batu.vp = 0; - bat.bat.batu.vs = 0; - bat_in_use[typ] &= ~(1 << bat_index); - /* mimic old behavior when bl was 0 (bs==0 is actually legal; it doesnt - * indicate a size of zero. We now accept bl==0 and look at the size. - */ - bat_addrs[typ][bat_index].limit = virt; - } - do_dssall (); - if ( TYP_I == typ ) { - switch (bat_index) { - case 0: asm_setibat0 (bat.words.u, bat.words.l); break; - case 1: asm_setibat1 (bat.words.u, bat.words.l); break; - case 2: asm_setibat2 (bat.words.u, bat.words.l); break; - case 3: asm_setibat3 (bat.words.u, bat.words.l); break; - /* cpu check already done in check_index */ - case 4: asm_setibat4 (bat.words.u, bat.words.l); break; - case 5: asm_setibat5 (bat.words.u, bat.words.l); break; - case 6: asm_setibat6 (bat.words.u, bat.words.l); break; - case 7: asm_setibat7 (bat.words.u, bat.words.l); break; - default: /* should never get here anyways */ - break; - } - } else { - switch (bat_index) { - case 0: asm_setdbat0 (bat.words.u, bat.words.l); break; - case 1: asm_setdbat1 (bat.words.u, bat.words.l); break; - case 2: asm_setdbat2 (bat.words.u, bat.words.l); break; - case 3: asm_setdbat3 (bat.words.u, bat.words.l); break; - /* cpu check already done in check_index */ - case 4: asm_setdbat4 (bat.words.u, bat.words.l); break; - case 5: asm_setdbat5 (bat.words.u, bat.words.l); break; - case 6: asm_setdbat6 (bat.words.u, bat.words.l); break; - case 7: asm_setdbat7 (bat.words.u, bat.words.l); break; - default: /* should never get here anyways */ - break; - } - } - rtems_interrupt_enable (level); - - return 0; -} - -static int -getbat (int typ, int idx, unsigned long *pu, unsigned long *pl) -{ - unsigned long u, l; - - if (check_bat_index (idx)) { - printk ("Invalid BAT #%i\n", idx); - return -1; - } - if ( TYP_I == typ ) { - switch (idx) { - case 0: GETBAT (IBAT0, u, l); break; - case 1: GETBAT (IBAT1, u, l); break; - case 2: GETBAT (IBAT2, u, l); break; - case 3: GETBAT (IBAT3, u, l); break; - /* cpu check already done in check_index */ - case 4: GETBAT (IBAT4, u, l); break; - case 5: GETBAT (IBAT5, u, l); break; - case 6: GETBAT (IBAT6, u, l); break; - case 7: GETBAT (IBAT7, u, l); break; - default: /* should never get here anyways */ - return -1; - } - } else { - switch (idx) { - case 0: GETBAT (DBAT0, u, l); break; - case 1: GETBAT (DBAT1, u, l); break; - case 2: GETBAT (DBAT2, u, l); break; - case 3: GETBAT (DBAT3, u, l); break; - /* cpu check already done in check_index */ - case 4: GETBAT (DBAT4, u, l); break; - case 5: GETBAT (DBAT5, u, l); break; - case 6: GETBAT (DBAT6, u, l); break; - case 7: GETBAT (DBAT7, u, l); break; - default: /* should never get here anyways */ - return -1; - } - } - if (pu) { - *pu = u; - } - if (pl) { - *pl = l; - } - - if (!pu && !pl) { - /* dump */ - ubat b; - b.words.u = u; - b.words.l = l; - printk ("Raw %cBAT %i contents; UPPER: (0x%08lx)", (TYP_I == typ ? 'I' : 'D'), idx, u); - printk (" BEPI: 0x%08x", b.bat.batu.bepi); - printk (" BL: 0x%08lx", (u >> 2) & ((1 << 15) - 1)); - printk (" VS: 0b%i", b.bat.batu.vs); - printk (" VP: 0b%i", b.bat.batu.vp); - printk ("\n"); - printk (" LOWER: (0x%08lx)", l); - printk (" RPN: 0x%08x", b.bat.batl.brpn); - printk (" wimg: 0b%1i%1i%1i%1i", b.bat.batl.w, b.bat.batl.i, - b.bat.batl.m, b.bat.batl.g); - printk (" PP: 0x%1x", b.bat.batl.pp); - printk ("\n"); - printk ("Covering EA Range: "); - if (bat_in_use[typ] & (1 << idx)) - printk ("0x%08lx .. 0x%08lx\n", bat_addrs[typ][idx].start, - bat_addrs[typ][idx].limit); - else - printk ("<none> (BAT off)\n"); - - } - return u; -} - -int -setdbat (int bat_index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) -{ - return setbat(TYP_D, bat_index, virt, phys, size, flags); -} - -int -setibat (int bat_index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) -{ - return setbat(TYP_I, bat_index, virt, phys, size, flags); -} - -int -getdbat (int idx, unsigned long *pu, unsigned long *pl) -{ - return getbat (TYP_D, idx, pu, pl); -} - -int -getibat (int idx, unsigned long *pu, unsigned long *pl) -{ - return getbat (TYP_I, idx, pu, pl); -} |