/* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Copyright (c) 2008 Microsoft. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Reset entry must be restored for reboot
*/
restore_locore();
/* Tell the power manager to halt? */
for (;howto & RB_HALT;) {
epmc_halt();
/* We should not be here!! */
ps |= EMIPS_SR_RP | EMIPS_SR_INT; /* but not current */
SetPsr(ps);
}
/* For a reboot, all we can really do is a reset actually */
for (;;) {
ps |= EMIPS_SR_RST;
SetPsr(ps);
}
}
static void
halt(int *unused, int howto)
{
/* We must switch to a safe stack! TLB will go down
*/
switch_stack_and_call((void *)howto,real_halt);
/* no return, stack lost */
}
/* Need to scan the PMT for all memory controllers
* Actually.. just enough to make the kernel fit but we dont know how big it is
*/
/* Common format for SRAM, DDRAM, and FLASH controllers.
* Use SRAM decl. and careful about DDRAM that is twice as big.
*/
typedef struct _Sram *ram_controller_t;
# define RAMBT_TAG SRAMBT_TAG
# define RAMBT_BASE SRAMBT_BASE
# define RAMST_SIZE SRAMST_SIZE
int init_memory(void)
{
struct _Pmt *Pmt;
ram_controller_t Ram, Ours, First;
uint32_t base, addr, moi = (uint32_t)(&init_memory) & 0x3ffff000;
size_t size;
uint16_t tag;
int nsr, ndr, nfl;
/* Make three passes.
* First find which controller we are running under, cuz we cant touch it.
* Then remap every RAM segment around it.
* Then make sure FLASH segments do not overlap RAM.
*/
nsr = ndr = nfl = 0;
First = Ours = NULL;
base = ~0;
for (Pmt = ThePmt;;Pmt--) {
tag = Pmt->Tag;
//printf("PMT @%x tag=%x\n",Pmt,tag);
switch (tag) {
case PMTTAG_END_OF_TABLE:
goto DoneFirst;
case PMTTAG_SRAM:
case PMTTAG_DDRAM:
case PMTTAG_FLASH:
Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
/* Scan the whole segment */
for (;;) {
//printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
break;
addr = Ram->BaseAddressAndTag & RAMBT_BASE;
if ((tag != PMTTAG_FLASH) && (addr < base)) {
base = addr;
First = Ram;
}
size = Ram->Control & RAMST_SIZE;
if ((moi >= addr) && (moi < (addr + size))) {
Ours = Ram;
}
/* Next one.. and count them */
Ram++;
switch (tag) {
case PMTTAG_SRAM:
nsr++;
break;
case PMTTAG_FLASH:
nfl++;
break;
case PMTTAG_DDRAM:
Ram++; /* yeach */
ndr++;
break;
}
}
break;
default:
break;
}
}
/* Make sure we know */
DoneFirst:
if ((First == NULL) || (Ours == NULL)) {
printf("Bad memory layout (%p, %p), wont work.\n", First, Ours);
return 0;
}
/* Second pass now */
base += First->BaseAddressAndTag & RAMBT_BASE;
for (Pmt = ThePmt;;Pmt--) {
tag = Pmt->Tag;
//printf("PMT @%x tag=%x\n",Pmt,tag);
switch (tag) {
case PMTTAG_END_OF_TABLE:
goto DoneSecond;
case PMTTAG_SRAM:
case PMTTAG_DDRAM:
case PMTTAG_FLASH:
Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
/* Scan the whole segment */
for (;;) {
//printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
break;
/* Leave us alone */
if (Ram == Ours)
goto Next;
/* Leave the first alone too */
if (Ram == First)
goto Next;
/* We do FLASH next round */
if (tag == PMTTAG_FLASH)
goto Next;