From f6dfc80554b27da11dbb36ebae166b23ec3aa9ca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 May 2007 14:10:01 +1000 Subject: [POWERPC] Support for the Ebony 440GP reference board in arch/powerpc This adds platform support code for the Ebony (440GP) evaluation board. This includes both code in arch/powerpc/platforms/44x for board initialization, and zImage wrapper code to correctly tweak the flattened device tree based on information from the firmware. The zImage supports both IBM OpenBIOS (aka "treeboot") and old versions of uboot which don't support a flattened device tree. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/boot/ebony.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 arch/powerpc/boot/ebony.c (limited to 'arch/powerpc/boot/ebony.c') diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c new file mode 100644 index 00000000000..b1251ee7a10 --- /dev/null +++ b/arch/powerpc/boot/ebony.c @@ -0,0 +1,129 @@ +/* + * Copyright 2007 David Gibson, IBM Corporation. + * + * Based on earlier code: + * Copyright (C) Paul Mackerras 1997. + * + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies + * + * 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. + */ +#include +#include +#include "types.h" +#include "elf.h" +#include "string.h" +#include "stdio.h" +#include "page.h" +#include "ops.h" +#include "reg.h" +#include "dcr.h" +#include "44x.h" + +extern char _dtb_start[]; +extern char _dtb_end[]; + +static u8 *ebony_mac0, *ebony_mac1; + +/* Calculate 440GP clocks */ +void ibm440gp_fixup_clocks(unsigned int sysclk, unsigned int ser_clk) +{ + u32 sys0 = mfdcr(DCRN_CPC0_SYS0); + u32 cr0 = mfdcr(DCRN_CPC0_CR0); + u32 cpu, plb, opb, ebc, tb, uart0, uart1, m; + u32 opdv = CPC0_SYS0_OPDV(sys0); + u32 epdv = CPC0_SYS0_EPDV(sys0); + + if (sys0 & CPC0_SYS0_BYPASS) { + /* Bypass system PLL */ + cpu = plb = sysclk; + } else { + if (sys0 & CPC0_SYS0_EXTSL) + /* PerClk */ + m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv; + else + /* CPU clock */ + m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0); + cpu = sysclk * m / CPC0_SYS0_FWDVA(sys0); + plb = sysclk * m / CPC0_SYS0_FWDVB(sys0); + } + + opb = plb / opdv; + ebc = opb / epdv; + + /* FIXME: Check if this is for all 440GP, or just Ebony */ + if ((mfpvr() & 0xf0000fff) == 0x40000440) + /* Rev. B 440GP, use external system clock */ + tb = sysclk; + else + /* Rev. C 440GP, errata force us to use internal clock */ + tb = cpu; + + if (cr0 & CPC0_CR0_U0EC) + /* External UART clock */ + uart0 = ser_clk; + else + /* Internal UART clock */ + uart0 = plb / CPC0_CR0_UDIV(cr0); + + if (cr0 & CPC0_CR0_U1EC) + /* External UART clock */ + uart1 = ser_clk; + else + /* Internal UART clock */ + uart1 = plb / CPC0_CR0_UDIV(cr0); + + printf("PPC440GP: SysClk = %dMHz (%x)\n\r", + (sysclk + 500000) / 1000000, sysclk); + + dt_fixup_cpu_clocks(cpu, tb, 0); + + dt_fixup_clock("/plb", plb); + dt_fixup_clock("/plb/opb", opb); + dt_fixup_clock("/plb/opb/ebc", ebc); + dt_fixup_clock("/plb/opb/serial@40000200", uart0); + dt_fixup_clock("/plb/opb/serial@40000300", uart1); +} + +static void ebony_fixups(void) +{ + // FIXME: sysclk should be derived by reading the FPGA registers + unsigned long sysclk = 33000000; + + ibm440gp_fixup_clocks(sysclk, 6 * 1843200); + ibm44x_fixup_memsize(); + dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); +} + +#define SPRN_DBCR0 0x134 +#define DBCR0_RST_SYSTEM 0x30000000 + +static void ebony_exit(void) +{ + unsigned long tmp; + + asm volatile ( + "mfspr %0,%1\n" + "oris %0,%0,%2@h\n" + "mtspr %1,%0" + : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) + ); + +} + +void ebony_init(void *mac0, void *mac1) +{ + platform_ops.fixups = ebony_fixups; + platform_ops.exit = ebony_exit; + ebony_mac0 = mac0; + ebony_mac1 = mac1; + ft_init(_dtb_start, _dtb_end - _dtb_start, 32); + serial_console_init(); +} -- cgit v1.2.3