blob: ff88da2965d9302d3912f2f857af18363c3cd67d [file] [log] [blame]
/*
* (C) Copyright IBM Corp. 2007, 2010
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses>.
*
* Author: Chris Ward <tjcw@uk.ibm.com>
*
* Based on earlier code:
* Copyright (C) Paul Mackerras 1997.
*
* Matt Porter <mporter@kernel.crashing.org>
* Copyright 2002-2005 MontaVista Software Inc.
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
* Copyright (c) 2003, 2004 Zultys Technologies
*
* David Gibson, IBM Corporation, 2007
*
*/
#include "types.h"
#include "ops.h"
#include "stdio.h"
#include "4xx.h"
#include "44x.h"
#include "bgcns.h"
/* Types needed for the personality */
typedef u8 uint8_t;
typedef u16 uint16_t;
typedef u32 uint32_t;
#include "bgp_personality.h"
/* Blue Gene firmware jumps to 0x10.
* Simply branch to _zimage_start which is typically 0x800000.
* Must also link with --section-start bgstart=0
*/
asm (
" .section bgstart, \"ax\"; "
" .=0x10; "
" lis %r9, _zimage_start@h; "
" ori %r9, %r9, _zimage_start@l; "
" mtlr %r9; "
" blr; "
" .previous "
);
/* This will point directly to CNS which remains mapped on entry. */
BGCNS_Descriptor* cns;
//static void bgp_console_write(const char *msg, int len) __attribute__((unused)) ;
static void bgp_console_write(const char *msg, int len)
{
if (cns)
cns->services->writeToMailboxConsole((char *)msg, len);
}
static void bgp_fixup_bluegene_cns(BGCNS_Descriptor *cns)
{
void *node = finddevice("/ibm,bluegene/cns");
if (node) {
setprop_val(node, "base-va", cns->baseVirtualAddress);
setprop_val(node, "base-pa", cns->basePhysicalAddress);
setprop_val(node, "size", cns->size);
setprop_val(node, "services", cns->services);
setprop_val(node, "version", cns->version);
} else {
fatal("could not find /ibm,bluegene/cns node in device tree");
}
}
static void bgp_fixup_bluegene_personality(BGP_Personality_t *bgpers)
{
void *node = finddevice("/ibm,bluegene/personality");
if (node) {
/* We could include individual fields of the personality as needed
* so that Linux doesn't need to decode the struct directly. We
* provide raw-data for external tools and daemons.
* This can replace /proc/personality
*/
unsigned frequency = bgpers->Kernel_Config.FreqMHz * 1000000;
setprop(node, "raw-data", bgpers, sizeof(*bgpers));
setprop_val(node, "frequency", frequency);
} else {
fatal("could not find /ibm,bluegene/personality node in device tree");
}
}
static void bgp_fixup_bluegene_initrd(void)
{
void *node = finddevice("/chosen");
if (node) {
/* On Blue Gene we may have a gzipped ramdisk loaded at a fixed
* address (0x1000000). It is preceeded by a 4-byte magic value and a
* 4-byte big endian length.
*/
unsigned *rd = (unsigned *)0x1000000; /* 16M */
if (rd[0] == 0xf0e1d2c3 && rd[1] != 0) {
unsigned initrd_start = (unsigned)(rd+2);
unsigned initrd_len = rd[1];
unsigned initrd_end = initrd_start + initrd_len;
setprop_val(node, "linux,initrd-start", initrd_start);
setprop_val(node, "linux,initrd-end", initrd_end);
}
} else {
fatal("could not find chosen node in device tree");
}
}
static void bgp_fixups(void)
{
BGP_Personality_t *bgpers = cns->services->getPersonalityData();
unsigned int DDRSize = (bgpers->DDR_Config.DDRSizeMB << 20) - cns->size;
unsigned int freq = bgpers->Kernel_Config.FreqMHz * 1000000;
/* For vRNIC configurations, turn down the memory that Linux thinks is on the node so the vRNIC can map it all */
if ( (DDRSize & 0xf0000000 ) == 0xd0000000 ) DDRSize = 0xb0000000 ;
dt_fixup_memory(0, DDRSize);
dt_fixup_cpu_clocks(freq, freq, freq);
bgp_fixup_bluegene_cns(cns);
bgp_fixup_bluegene_personality(bgpers);
bgp_fixup_bluegene_initrd();
#if 0
/* FIXME: sysclk should be derived by reading the FPGA registers */
unsigned long sysclk = 33000000;
ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
ibm4xx_sdram_fixup_memsize();
dt_fixup_mac_address_by_alias("ethernet0", ebony_mac0);
dt_fixup_mac_address_by_alias("ethernet1", ebony_mac1);
ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
ebony_flashsel_fixup();
#endif
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
cns = (BGCNS_Descriptor*) r3;
#if defined(CONFIG_PPC_EARLY_DEBUG_BGP)
{
BGP_Personality_t bgpers;
/* ZXXX: only rank0 prints msg */
if( cns ) {
memcpy(&bgpers, cns->services->getPersonalityData(), sizeof(bgpers) );
if( bgpers.Network_Config.Rank == 0 ) {
console_ops.write = bgp_console_write;
} else {
console_ops.write = 0;
}
}
}
#endif
simple_alloc_init(_end, 256 << 20, 32, 64);
platform_ops.fixups = bgp_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
fdt_init(_dtb_start);
/* serial_console_init(); */
}