// // $Id: kahlua.s,v 1.17 2000/05/24 18:46:07 garym Exp $ // // Copyright Motorola, Inc. 1993, 1994 // ALL RIGHTS RESERVED // // You are hereby granted a copyright license to use, modify, and // distribute the SOFTWARE so long as this entire notice is retained // without alteration in any modified and/or redistributed versions, // and that such modified versions are clearly identified as such. // No licenses are granted by implication, estoppel or otherwise under // any patents or trademarks of Motorola, Inc. // // The SOFTWARE is provided on an "AS IS" basis and without warranty. // To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS // ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH // REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS // THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. // // To the maximum extent permitted by applicable law, IN NO EVENT SHALL // MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER // (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF // BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS // INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR // INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility // for the maintenance and support of the SOFTWARE. // file: kahlua.s // // 10/08/98 -- created -- GM & My // .file "kahlua.s" /* Includes */ #include "yellowknife.h" #include "dink_asm.h" .extern config_addr .extern config_data .equ EUMBBAR_HI, 0x8000 .equ EUMBBAR_LO, 0x0078 /* Globals */ .text .align 2 .global KahluaInit /* entry: r3 contains Kahlua Vendor ID */ KahluaInit: // save Kahlua Vendor ID or r11, r3, r3 // If the MPC8240 is detected, it must be running on a // Sandpoint with the Unity (PPMC8240) board (or possibly // a Yellowknife X4 with an adapter card). // The board_type of Sandpoint+PMC8240 X4 is 4. This code // stores the value 4 to sprg0, which will be stored to the // board_type variable after DINK is copied form ROM to RAM. addi r3, r0, 0x4 mtspr sprg0, r3 // Errata to address latency timer RP 7/20/99 addis r3,r0,BMC_BASE // Select LATENCY_TIMER ori r3,r3,0x000d li r4, 0x20 // Set to 0x20 stwbrx r3,0,r5 sync stb r4, 1(r6) sync addis r3,r0,BMC_BASE // Select CACHE_LINE_SIZE ori r3,r3,0x000c li r4, 0x08 // Set to 0x08 stwbrx r3,0,r5 sync stb r4, 0(r6) sync addis r3,r0,BMC_BASE // Select PCI_CMD ori r3,r3,0x0004 li r4, 0x0006 // Set to 06 (Memory Space) stwbrx r3,0,r5 sync sthbrx r4, 0, r6 sync addis r3,r0,BMC_BASE // Select PCI_STAT ori r3,r3,0x0006 stwbrx r3,0,r5 sync li r3, 0x0002 lhbrx r4, r3, r6 // Get old PCI_STAT sync ori r4, r4, 0xffff // Writing all ones will clear all bits in sthbrx r4, r3, r6 // write the modified data to CONFIG_DATA // ===PICR1=== PROCESSOR INTERFACE CONFIGURATION // // PICR1/2 are much simpler than a MPC106 equivalent, mostly due to // the elimination of the L3 interface. // Note: you cannot just set the LE(little-endian bit); there's a // special sequence involved -- contact RISC Applications for details. addis r3,r0,BMC_BASE // Select PICR1 (A8) ori r3,r3,PROCINTCONF1 stwbrx r3,0,r5 sync lwbrx r4,0,r6 // Get PICR1 bits lis r0,0xFF11 ori r0,r0,0x0010 // preserve RCS0/AddrMap/Bit4 bits. and r4,r4,r0 lis r0, 0x0004 // processor type = 603/750 ori r0, r0, 0x1000 // enable Flash write ori r0, r0, 0x0800 // enable MCP* assertion ori r0, r0, 0x0200 // enable data bus parking ori r0, r0, 0x0040 // enable PCI store gathering ori r0, r0, 0x0010 // RESERVED -- Set ori r0, r0, 0x0008 // enable address bus parking // ori r0, r0, 0x0004 // enable speculative PCI reads or r4, r4, r0 // sets the desired bits stwbrx r4,0,r6 sync // ===PICR2=== PROCESSOR INTERFACE CONFIGURATION // addis r3, r0, BMC_BASE // Select PICR2 (AC) ori r3, r3, PROCINTCONF2 stwbrx r3, 0, r5 sync // Nothing preserved. lis r0, 0x0000 // oris r0, r0, 0x2000 // Disable Serialize Config cycles // oris r0, r0, 0x0800 // Disable PCI Snoop cycles oris r0, r0, 0x0400 // FF0 is Local ROM // oris r0, r0, 0x0200 // Flash write lockout oris r0, r0, 0x0000 // snoop wt states = 0 // oris r0, r0, 0x0004 // snoop wt states = 1 // oris r0, r0, 0x0008 // snoop wt states = 2 // oris r0, r0, 0x000c // snoop wt states = 3 ori r0, r0, 0x0000 // addr. phase wt states = 0 // ori r0, r0, 0x0004 // addr. phase wt states = 1 // ori r0, r0, 0x0008 // addr. phase wt states = 2 // ori r0, r0, 0x000c // addr. phase wt states = 3 stwbrx r0,0,r6 // ===EUMBBAR=== Embedded Utility Memory Block Base Address Register // addis r3,r0,BMC_BASE // Select EUMBBAR (78) ori r3,r3,0x0078 stwbrx r3,0,r5 sync lis r4,0xfc00 // EUMBBAR = 0xFC00_0000 stwbrx r4,0,r6 // Don't forget to map this area sync // into the BATs // ===AMBOR=== Address Map B Options Register // // Even if Address Map B is not being used (though it should), the // memory DLL needs to be cleared/set/cleared before using memory. // addis r3,r0,BMC_BASE // Select AMBOR (E0) ori r3,r3,0x00E0 stwbrx r3,0,r5 sync lwbrx r4,0,r6 // Get current bits andi. r4,r4,0xFFDF stwbrx r4,0,r6 // Clear DLL_RESET sync ori r3,r3,0x0020 stwbrx r4,0,r6 // Set DLL_RESET sync andi. r4,r4,0xFFDF stwbrx r4,0,r6 // Clear DLL_RESET sync // ===MCCR1=== MEMORY CONTROL CONFIGURATION // addis r3,r0,BMC_BASE // Select MCCR1 (F0) ori r3,r3,0x00F0 stwbrx r3,0,r5 sync lwbrx r7,0,r6 // Get MCCR1 bits; used w/MCCR4 lis r0,0x0040 and r7,r7,r0 // R7: =0 if 32 bits, /= 0 if 64. lis r4, 0x7580 // Safe Local ROM = 11+3 clocks // lis r4, 0x7380 // Fast Local ROM = 7+3 clocks // oris r4, r4, 0x0010 // Burst ROM/Flash enable // oris r4, r4, 0x0004 // Self-refresh enable // oris r4, r4, 0x0002 // EDO/FP enable (else SDRAM) // oris r4, r4, 0x0001 // Parity check // Set all banks to same type (they don't have to be) // ori r4, r4, 0xFFFF // 16Mbit/2bank SDRAM // ori r4, r4, 0x5555 // 64Mbit/2bank SDRAM ori r4, r4, 0x0000 // 64Mbit/4bank SDRAM stwbrx r4,0,r6 sync // ===MCCR2=== MEMORY CONTROL CONFIGURATION // addis r3,r0,BMC_BASE // Select MCCR2 (F4) ori r3,r3,0x00F4 stwbrx r3,0,r5 sync lis r4, 0x0000 // oris r4, r4, 0x4000 // TS_WAIT_TIMER = 3 clocks oris r4, r4, 0x0400 // ASRISE = 2 clocks oris r4, r4, 0x0040 // ASFALL = 2 clocks // oris r4, r4, 0x0010 // SDRAM Parity (else ECC) // oris r4, r4, 0x0008 // Write parity check // oris r4, r4, 0x0004 // SDRAM inline reads // oris r4, r4, 0x0002 // ECC enable // oris r4, r4, 0x0001 // EDO (else FP) // Select a refresh rate; it needs to match the bus speed; if too // slow, data may be lost; if too fast, performance is lost. We // use the fastest value so we run at all speeds. // Refresh = (15600ns/busclk) - (213 (see UM)). // ori r4, r4, 0x1d2c // 133 MHz mem bus = 1867 // ori r4, r4, 0x150c // 100 MHz mem bus = 1347 // ori r4, r4, 0x10fc // 83 MHz mem bus = 1087 // ori r4, r4, 0x0cc4 // 66 MHz mem bus = 817 ori r4, r4, 0x04cc // 33 MHz mem bus (SAFE) = 307 // ori r4, r4, 0x0002 // Reserve a page // ori r4, r4, 0x0001 // RWM parity stwbrx r4,0,r6 sync // ===MCCR3=== MEMORY CONTROL CONFIGURATION // addis r3,r0,BMC_BASE // Select MCCR3 (F8) ori r3,r3,0x00F8 stwbrx r3,0,r5 sync lis r4, 0x7000 // BSTOPRE_M = 7 (see A/N) oris r4, r4, 0x0800 // REFREC = 8 clocks oris r4, r4, 0x0040 // RDLAT = 4 clocks (CL+1) SAFE // oris r4, r4, 0x0030 // RDLAT = 3 clocks (CL+1) FAST // The rest of the bits are EDO only; the PrPMC8240 does not support // EDO. stwbrx r4,0,r6 sync // ===MCCR4=== MEMORY CONTROL CONFIGURATION // addis r3,r0,BMC_BASE // Select MCCR4 (FC) ori r3,r3,0x00Fc stwbrx r3,0,r5 sync lis r4, 0x3000 // PRETOACT = 3 clocks oris r4, r4, 0x0500 // ACTOPRE = 5 clocks // oris r4, r4, 0x0080 // Enable 8-beat burst (32-bit bus) // oris r4, r4, 0x0040 // Enable Inline ECC/Parity oris r4, r4, 0x0010 // Registered buffers // oris r4, r4, 0x0000 // BSTOPRE_U = 0 (see A/N) // ori r4, r4, 0x8000 // Registered DIMMs ori r4, r4, 0x3000 // CAS Latency (CL=3) (see RDLAT) // ori r4, r4, 0x2000 // CAS Latency (CL=2) (see RDLAT) ori r4, r4, 0x0030 // ACTORW = 3 clocks ori r4, r4, 0x0009 // BSTOPRE_L = 9 (see A/N) // Set the SDRAM size to 4- or 8-beat bursts for 64- or 32-bit bus mode, // respectively. cmpi 0,0,r7,0x0 // test 32/64 bit mode beq k_is32bits ori r4, r4, 0x0200 // Sequential wrap/4-beat burst b mccr4set k_is32bits: ori r4, r4, 0x0300 // Sequential wrap/8-beat burst mccr4set: stwbrx r4,0,r6 sync // ===MSAR=== MEMORY START ADDRESS REGISTER // // MSAR1 / MSAR2 / MESAR1 / MESAR2 // // All eight registers are programmed to non-overlapping values. // Assuming each bank controls 32Mb, the maximum address per bank // is 0x1FFFFFF; we set each bank to start at 0x0000000, 0x2000000, etc. // Since the lower "00000" are implied, we see the pattern 0x00, 0x20, in // the start registers (with the extended addresses all 0s). addis r3,r0,BMC_BASE // Select MSAR1 (80) ori r3,r3,MEMSTARTADDR1 stwbrx r3,0,r5 addis r4,r0,0x6040 ori r4,r4,0x2000 stwbrx r4,0,r6 addis r3,r0,BMC_BASE // Select MSAR2 (84) ori r3,r3,MEMSTARTADDR2 stwbrx r3,0,r5 addis r4,r0,0xe0c0 ori r4,r4,0xa080 stwbrx r4,0,r6 addis r3,r0,BMC_BASE // Select MESAR1 (88) ori r3,r3,XMEMSTARTADDR1 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0000 stwbrx r4,0,r6 addis r3,r0,BMC_BASE // Select MESAR2 (8c) ori r3,r3,XMEMSTARTADDR2 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0000 stwbrx r4,0,r6 // ===MEAR=== MEMORY END ADDRESS REGISTER // // MEAR1 / MEAR2 / MEEAR1 / MEEAR2 // Similar to the previous values, less one from the next bank. // Therefore, 0x1F, 0x3F, etc. addis r3,r0,BMC_BASE // Select MEAR1 (90) ori r3,r3,MEMENDADDR1 stwbrx r3,0,r5 addis r4,r0,0x7f5f ori r4,r4,0x3f1f stwbrx r4,0,r6 addis r3,r0,BMC_BASE // Select MEAR2 (94) ori r3,r3,MEMENDADDR2 stwbrx r3,0,r5 addis r4,r0,0xffdf ori r4,r4,0xbf9f stwbrx r4,0,r6 addis r3,r0,BMC_BASE // MEEAR1 (98) ori r3,r3,XMEMENDADDR1 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0000 stwbrx r4,0,r6 addis r3,r0,BMC_BASE // MEEAR2 (9c) ori r3,r3,XMEMENDADDR2 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0000 stwbrx r4,0,r6 // ===ODCR=== OUTPUT DRIVER CONTROL CONFIGURATION // // NOTE: this is different than the MPC106 and MPC107! addis r3,r0,BMC_BASE // Select ODCR ori r3,r3,0x73 stwbrx r3,0,r5 sync lbz r4, 3(r6) // read current register state // li r4, 0x00cd // 20 ohm memory bus // li r4, 0x00dc // 13 ohm memory bus // li r4, 0x00dd // 8 ohm memory bus li r4, 0x00ff // -default settings- stb r4, 3(r6) // New settings. // ===MBEN=== MEMORY BANK ENABLE // // Set a bit in MBEN for each enabled bank. We can have two on the // SODIMM. Each bank corresponds to a RAS/CS pin. addis r3,r0,BMC_BASE // Select MBEN (a0) ori r3,r3,0xa0 stwbrx r3,0,r5 li r4, 0x03 // Enable bank 0 and 1 (for dual- stb r4, 0(r6) // bank SODIMMs. // ===PGMAX=== Page Max // // Refer to the MPC106 SDRAM programming A/N for details (applies to // MPC8240 also). addis r3,r0,BMC_BASE ori r3,r3,0xa3 stwbrx r3,0,r5 // li r4, 0x0000 // Page Mode Off li r4, 0x0032 // 33 MHz - w/ROMFAL=8 // li r4, 0x0064 // 66 MHz - w/ROMFAL=8 // li r4, 0x0096 // 100 MHz - w/ROMFAL=8 stb r4, 3(r6) // Write PGMAX (note offset) //--------------------------------------------------------------------------- // Initialization is done, now wait a bit before enabling the memory // controller. lis r4,0x0003 mtctr r4 KMClp1: bdnz KMClp1 // Set MEMGO bit addis r3,r0,BMC_BASE // MCCR1 (F0) |= PGMAX ori r3,r3,0x00F0 stwbrx r3,0,r5 sync lwbrx r4,0,r6 // old MCCR1 oris r4,r4,0x0008 // MEMGO <= 1 // lis r0, 0x0008 // MEMGO=1 // or r4, r4, r0 // set the MEMGO bit stwbrx r4, 0, r6 // Wait again lis r4,0x0003 mtctr r4 KMClp2: bdnz KMClp2 //------ WP1_CNTL_TRIG addis r3,r0,BMC_BASE_HIGH // WP1_CNTL_TRIG (0xFF018) = ori r3,r3,0xF018 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0180 stwbrx r4,0,r6 //------ WP1_ADDR_TRIG addis r3,r0,BMC_BASE_HIGH // WP1_ADDR_TRIG (0xFF01C) = ori r3,r3,0xF01C stwbrx r3,0,r5 addis r4,r0,0x0006 // Set to 0x60000 ori r4,r4,0x0000 stwbrx r4,0,r6 //------ WP1_CNTL_MASK addis r3,r0,BMC_BASE_HIGH // WP1_CNTL_MASK (0xFF020) = ori r3,r3,0xF020 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x0180 stwbrx r4,0,r6 //------ WP1_ADDR_MASK addis r3,r0,BMC_BASE_HIGH // WP1_ADDR_MASK (0xFF024) = ori r3,r3,0xF024 stwbrx r3,0,r5 addis r4,r0,0xFFFF ori r4,r4,0xFFFF stwbrx r4,0,r6 //------ WP_CONTROL addis r3,r0,BMC_BASE_HIGH // WP_CONTROL (0xFF048) = ori r3,r3,0xF048 stwbrx r3,0,r5 addis r4,r0,0x0000 ori r4,r4,0x01C6 stwbrx r4,0,r6 addis r4,r0,0x0100 // Enable Watchpoint on seperate write ori r4,r4,0x01C6 stwbrx r4,0,r6 sync eieio lis r3, 0x0 or r3, r3, r11 // restore Kahlua Vendor ID blr /********************************************************** * function: get_eumbbar * * output: r3 - content of eumbbar **********************************************************/ .text .align 2 .global get_eumbbar get_eumbbar: lis r4,config_addr@h ori r4,r4,config_addr@l lwz r4,0(r4) lis r3,EUMBBAR_HI ori r3,r3,EUMBBAR_LO stwbrx r3,0,r4 lis r4,config_data@h ori r4,r4,config_data@l lwz r4,0(r4) lwbrx r3,0,r4 blr