2020-09-30 17:12:29 +02:00

552 lines
13 KiB
ArmAsm

//
//
// Copyright (c) 1993 IBM Corporation
//
// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
// contains copyrighted material. Use of this file is restricted
// by the provisions of a Motorola Software License Agreement.
//
// Module Name:
//
// PXL2.S
//
// Abstract:
//
// This module implements the routines to size & enable the L2 cache
// on an Eagle based system.
//
// Author:
//
// Steve Johns (sjohns@pets.sps.mot.com)
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
// 11-Aug-94 saj Added Eagle L2 cache support for Big Bend.
// 23-Nov-94 saj Added input parameter specifying write-back or write-thru
// 01-Dec-94 saj Removed all hardware workarounds
// Enable L2 Parity error checking (Eagle register 0xC4)
// 08-Mar-95 saj Added input parameter EagleAC
// 21-Aug-95 v-matth Steve's sizing functionality is walking on the
// page file database if we have 128Mb of RAM. I'm
// going to change it to save off main memory before
// we do our writes to main memory, then restore those
// values before we exit.
// 01-Sep-95 saj Check if L2 is already enabled. If so, just exit.
// Otherwise, size L2 and exit with L2 disabled. Don't read
// DBATs, since can't be read reliably on 603e.
//
#include "kxppc.h"
#include "halppc.h"
.extern HalpIoControlBase
.set HID0, 1008
//
// Eagle register A8 fields:
//
.set CF_WRITE_THRU, 0x0001 // Write-through
.set CF_WRITE_BACK, 0x0002 // Write-back
.set CF_L2_MP, 0x0003 // Bits 1..0 (LE bit order)
//
// Eagle register AC fields:
//
.set L2_EN, 0x40000000
.set L2_UPDATE_EN, 0x80000000
.set CF_FLUSH_L2, 0x10000000
.set CF_INV_MODE, 0x00001000
//
// L2 cache sizes:
//
.set CF_L2_SIZE, 0x0030 // Bits 5..4 (LE bit order)
.set L2_1M, 0x0020
.set L2_512K, 0x0010
.set L2_256K, 0x0000
.set L2_LINE_SIZE, 32
//
// Local parameters
//
.set CacheSize, r.3 // Return value
.set Pattern, r.3
.set Offset, r.5
.set EagleA8, r.6
.set EagleAC, r.7
.set L2off, r.8 // Eagle register A8 for L2 disabled
.set Restore, r.9
.set ISA, r.10 // Pointer to ISA I/O space
.set Virtual, r.11
.set Pattern0, 0x77777777 // Patterns for L2 cache sizing
.set Pattern1, 0x11111111
.set Pattern2, 0x22222222
.set Pattern3, 0X33333333
.set Pattern4, 0x44444444
.set VIRTUAL, 0xFFC00000 // Virtual address for L2 sizing
.set PHYSICAL, 0x00C00000 // Physical mem. used for L2 sizing
.set BAT_REG, 1 // BAT register to use for L2 sizing
//***********************************************************************
//
// Synopsis:
// ULONG HalpSizeL2(VOID)
//
// Purpose:
// Sizes and enables the Eagle L2 cache.
//
// Returns:
// Size of L2 cache or zero if not installed.
// Valid sizes are 256, 512, and 1024.
//
// Global Variables Referenced:
// HalpIoControlBase
//
// NOTE: Interrupts are assumed to be disabled upon entry.
//***********************************************************************
LEAF_ENTRY(HalpSizeL2)
//
// Lock the I-cache so instruction fetching doesn't impact the L2 cache
// while we are sizing it. With the I-cache locked, instruction fetches will
// not bursted in, so the L2 will not respond to those cycles.
//
mfspr r.0, HID0
ori r.0, r.0, 0x2000 // Lock the Icache
mtspr HID0, r.0
//
// Get ptr to Eagle I/O (ISA bus)
//
lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
lwz ISA,0(ISA)
LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
//
// Return if L2 cache is already enabled.
//
stw EagleAC, 0xCF8(ISA)
sync
lwz r.0, 0xCFC(ISA)
andis. r.4, r.0, (L2_EN >> 16) // Test L2_EN
beq Init_BAT
stw EagleA8, 0xCF8(ISA)
sync
lwz r.4, 0xCFC(ISA)
andi. r.4, r.4, CF_L2_MP // Test CF_L2_MP
beq Init_BAT
andi. r.0, r.0, CF_L2_SIZE // Isolate L2 size field
cmpi 0,0,r.0, 0x30 // Reserved ?
li CacheSize, 0
beq L2_Exit
li CacheSize, 256
cmpi 0,0,r.0, L2_256K
beq L2_Exit
li CacheSize, 512
cmpi 0,0,r.0, L2_512K
beq L2_Exit
li CacheSize, 1024
b L2_Exit
//
// Initialize a BAT register to map the memory at PHYSICAL to VIRTUAL.
// The sizing algorithm depends on the block of memory being marked WRITE-THRU.
//
Init_BAT:
LWI (Virtual, VIRTUAL)
LWI (r.0, PHYSICAL + 0x5A) // WIMG = 1011; PP = 10
mtdbatl BAT_REG, r.0
ori r.0, Virtual, 0x003F // BL = 2MB; Vs = Vp = 1
mtdbatu BAT_REG, r.0
isync
//
// Save the 4 test locations.
//
lis Offset, 4 // Offset = 256K
lwz Pattern,[toc].LRDATA(rtoc) // Pattern <- address of .LRDATA
lwz r.0, 0 (Virtual)
stw r.0, 0 (Pattern) // Save Memory[ 0K];
dcbf r.0, Virtual
lwzux r.0, Virtual, Offset
dcbf r.0, Virtual
stw r0, 4(Pattern) // Save Memory[256K];
lwzux r.0, Virtual, Offset
mr r.9, Virtual // r.9 = Virtual + 512K
dcbf r.0, Virtual
stw r0, 8(Pattern) // Save Memory[512K];
lwzux r.0, Virtual, Offset
dcbf r.0, Virtual
stw r0,12(Pattern) // Save Memory[768K];
LWI (Virtual, VIRTUAL)
//
// Set the L2 cache to Write-Through
//
stw EagleA8, 0xCF8(ISA)
sync
lwz L2off, 0xCFC(ISA)
rlwinm L2off, L2off,0,~CF_L2_MP
ori r.0, L2off, CF_WRITE_THRU
stw r.0, 0xCFC(ISA)
sync
//
// Enable the L2 cache for 1 MB
//
stw EagleAC, 0xCF8(ISA)
sync
lwz r.0, 0xCFC(ISA)
rlwinm r.0, r.0, 0, ~CF_L2_SIZE
ori r.0, r.0, L2_1M
oris r.0, r.0, ((L2_EN+L2_UPDATE_EN) >> 16)
stw r.0, 0xCFC(ISA)
sync
sync
//
// Load the 4 test locations into the L2 cache.
//
lwzx r.0, r.9, Offset // 768 KB
lwz r.0, 0(r.9) // 512 KB
lwzx r.0, Virtual, Offset // 256 KB
lwz r.0, 0 (Virtual) // 0 KB
//
// Store different patterns to the 4 test locations. This should cause
// values to be stored in the L2 cache and memory.
//
LWI (Pattern, Pattern4) // L2_Cache[768K] = Pattern4;
stwx Pattern, r.9, Offset
LWI (Pattern, Pattern3) // L2_Cache[512K] = Pattern3;
stw Pattern, 0 (r.9)
LWI (Pattern, Pattern2) // L2_Cache[256K] = Pattern2;
stwx Pattern, Virtual, Offset
LWI (Pattern, Pattern1) // L2_Cache[ 0K] = Pattern1;
stw Pattern, 0 (Virtual)
//
// Disable the L2 cache. The tags are NOT invalidated. No L2 snoop
// operations or data updates are performed.
//
stw EagleAC, 0xCF8(ISA)
sync
lwz r.0, 0xCFC(ISA)
rlwinm r.0, r.0, 0, ~(L2_EN+L2_UPDATE_EN)
stw r.0, 0xCFC(ISA)
sync
//
// Store PATTERN0 to our 4 test locations. Only L1 and main memory will be
// written since the L2 cache has been disabled. This allows us to distinguish
// patterns in the L2 from main memory.
//
LWI (Pattern, Pattern0) // L2_Cache[768K] = Pattern0;
stwx Pattern, r.9, Offset
stw Pattern, 0 (r.9) // L2_Cache[512K] = Pattern0;
stwx Pattern, Virtual,Offset // L2_Cache[256K] = Pattern0;
stw Pattern, 0 (Virtual) // L2_Cache[ 0K] = Pattern0;
//
// Load 8 locations (for an 8-way L1 cache) 4096 bytes apart in order to flush
// the test locations from the L1. We can't use DCBF since that would flush
// the L2 also.
//
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
lwzu Pattern, 4096(Virtual)
LWI (Virtual, VIRTUAL)
//
// Re-enable the L2 cache
//
stw EagleAC, 0xCF8(ISA)
sync
lwz r.0, 0xCFC(ISA)
oris r.0, r.0, ((L2_EN + L2_UPDATE_EN) >> 16)
stw r.0, 0xCFC(ISA)
sync
lwz Pattern, 0(Virtual) // Read test location @ 0 KB
lwzx r.0, Virtual, Offset // Read test location @ 256 KB
rlwimi Pattern, r.0, 0, 8, 15
lwz r.0, 0 (r.9) // Read test location @ 512 KB
rlwimi Pattern, r.0, 0, 16, 23
lwzx r.0, r.9, Offset // Read test location @ 768 KB
rlwimi Pattern, r.0, 0, 24, 31
//
// Test the pattern from L2 to determine it's size
//
LWI (r.0, 0x11777777)
cmpl 0,0, Pattern, r.0
beq Set_256K
LWI (r.0, 0x11227777)
cmpl 0,0, Pattern, r.0
beq Set_512K
LWI (r.0, 0x11223344)
cmpl 0,0, Pattern, r.0
beq Set_1M
// LWI (r.0, 0x77777777)
// cmpl 0,0, Pattern, r.0
// bne InvalidPattern
li CacheSize, 0
b DisableCache
//
// Unexpected pattern. Return it for display.
//
InvalidPattern:
// mr CacheSize, Pattern // Not needed if CacheSize == Pattern
b DisableCache
Set_256K:
li CacheSize, 256
li r.4, L2_256K
b SetCacheSize
Set_512K:
li CacheSize, 512
li r.4, L2_512K
b SetCacheSize
Set_1M:
li CacheSize, 1024
li r.4, L2_1M
//
// r.3 = cache size in KB
// r.4 = cache size field to be inserted into Eagle register AC.
//
SetCacheSize:
stw EagleAC, 0xCF8(ISA)
sync
lwz r.9, 0xCFC(ISA)
rlwimi r.9, r.4, 0, CF_L2_SIZE // Insert CF_L2_SIZE field
stw r.9, 0xCFC(ISA)
sync
//
// Eagle 2.1 BUG:
// Write-back works OK
// Write-thru walks thru addresses but does not invalidate them.
// Don't need to flush for write-thru anyway!!!!
//
// NOTE: If changing from WRITE-BACK to WRITE-THROUGH, you must flush
// beforehand because castouts are not supported in write-through.
// If the L2 has dirty data, then switching to write-through, the
// dirty data won't get flushed (cast out) to main memory.
//
rlwinm r.4, r.9, 0, 1,31 // Clear L2_UPDATE_EN (lock L2)
stw r.4, 0xCFC(ISA)
oris r.0, r.4, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
sync
stw r.0, 0xCFC(ISA)
sync
stw r.4, 0xCFC(ISA)
//
// Flush the L2 by walking through memory (2x L2 size)
//
rlwinm r.0, CacheSize, 10-5+1, 0, 31 // L2Size * (1024 / LINE_SIZE) * 2
mtctr r.0
subi r.4, Virtual, L2_LINE_SIZE
FlushLoop:
lwzu r.0, L2_LINE_SIZE (r.4)
bdnz FlushLoop
//
// Disable the L2 cache
//
DisableCache:
sync
lwz r.9, 0xCFC(ISA)
rlwinm r.9, r.9, 0, ~(L2_EN+L2_UPDATE_EN)
stw r.9, 0xCFC(ISA)
sync
stw EagleA8, 0xCF8(ISA)
sync
stw L2off, 0xCFC(ISA) // Disable the L2 cache
sync
//
// Restore the original contents of the test locations
//
lwz Restore,[toc].LRDATA(rtoc)
lwz r0, 0(Restore) // Restore test location 0
stw r0, 0(Virtual)
lwz r0, 4(Restore) // Restore test location 1
stwux r0, Virtual, Offset
lwz r0, 8(Restore) // Restore test location 2
stwux r0, Virtual, Offset
lwz r0,12(Restore) // Restore test location 3
stwx r0, Virtual, Offset
li r.0, 0 // Invalidate the BAT we used
mtdbatu BAT_REG, r.0
mtdbatl BAT_REG, r.0
L2_Exit:
mfspr r.0, HID0
rlwinm r.0, r.0, 0, ~0x2000 // Unlock the Icache
mtspr HID0, r.0
LEAF_EXIT(HalpSizeL2)
//***********************************************************************
//
// Synopsis:
// VOID HalpFlushAndDisableL2(VOID)
//
// Purpose:
// If the L2 is enabled and in WRITE-BACK mode, the L2 is flushed.
// In either mode, the L2 is invalidated, and upon exit, the L2 is
// left disabled.
//
// Returns:
// nothing
//
// Global Variables Referenced:
// HalpIoControlBase
//
// NOTE: Interrupts are assumed to be disabled upon entry.
//***********************************************************************
LEAF_ENTRY(HalpFlushAndDisableL2)
mfsprg r.12, 1 // Get PCR->SecondLevelDcacheSize
lwz r.0, PcSecondLevelDcacheSize (r.12)
srwi. r.0, r.0, 5 // # lines in L2
beqlr-
mtctr r.0
lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
lwz ISA,0(ISA)
LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
stw EagleAC, 0xCF8(ISA)
sync
lwz r.5, 0xCFC(ISA)
andis. r.0, r.5, (L2_EN >> 16) // Disable the L2 (L2_EN = 0)
beqlr
mfspr r.9, HID0 // Lock the Icache
ori r.0, r.9, 0x2000
mtspr HID0, r.0
isync
stw EagleA8, 0xCF8(ISA) // Check CF_L2_MP
sync
lwz r.4, 0xCFC(ISA)
andi. r.0, r.4, CF_L2_MP
beq FlushExit // Return if L2 is disabled
cmpwi r.0, CF_WRITE_THRU // Is L2 in write-through mode ?
beq InvalidateL2 // Yes, then flush is not necessary
//
// Flush the L2 contents to main memory
//
stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
rlwinm r.0, r.5, 0, 1,31
oris r.0, r.0, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
stw r.0, 0xCFC(ISA)
sync
stw r.5, 0xCFC(ISA)
InvalidateL2:
stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
sync
rlwinm r.5, r.5, 0, 2,0 // Clear L2_EN (disable the L2 cache)
ori r.0, r.5, CF_INV_MODE // Set L2 to invalidate mode
stw r.0, 0xCFC(ISA)
sync
//
// Invalidate the L2 by walking thru memory
//
LWI (r.12, 0x80000000-L2_LINE_SIZE)
Invalidate:
lwzu r.0, L2_LINE_SIZE (r.12)// Read from L2 cache
bdnz Invalidate
stw EagleA8, 0xCF8(ISA)
sync
rlwinm r.4, r.4, 0, ~CF_L2_MP // Clear CF_L2_MP
stw r.4, 0xCFC(ISA)
FlushExit:
stw EagleAC, 0xCF8(ISA)
sync
rlwinm r.5, r.5, 0, 2,31 // Clear L2_EN & L2_UPDATE_EN
stw r.5, 0xCFC(ISA) // Clear CF_INV_MODE
mtspr HID0, r.9 // Unlock the Icache
LEAF_EXIT(HalpFlushAndDisableL2)
.LRDATA:
// loc 0 - Holds memory at 0K
.ualong 0x0
// loc 4 - Holds memory at 256K
.ualong 0x0
// loc 8 - Holds memory at 512K
.ualong 0x0
// loc 12 - Holds memory at 1024K
.ualong 0x0