* [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
@ 2006-05-18 0:21 Mark A. Greer
2006-05-18 5:32 ` Benjamin Herrenschmidt
2006-05-18 13:47 ` Matthew McClintock
0 siblings, 2 replies; 17+ messages in thread
From: Mark A. Greer @ 2006-05-18 0:21 UTC (permalink / raw)
To: linuxppc-dev
Hi,
This is a patch with some very rough code that adds support for the
sandpoint to arch/powerpc. I'm posting it now in the hope that it
will spark a deeper discussion on exactly how we're going to support
flattened device tree code in the bootwrapper for non-OF platforms.
I'm also hoping that it will help others that are working on the same
sort of thing so we can help each other.
Again, the code is rough with lots of hacks but it boots and is
something we can point to during this discussion.
So...I am on the right path?
Mark
---
Kconfig | 10
boot/Makefile | 8
boot/dt_utils.c | 95 +++
boot/dts/sandpoint.dts | 204 +++++++
boot/io.h | 160 +++++
boot/main.c | 42 +
boot/mpc10x.c | 88 +++
boot/ns16550.c | 118 ++++
boot/prom.h | 52 +
boot/prom_embedded.c | 112 ++++
boot/sandpoint.c | 110 ++++
boot/types.h | 28 +
configs/sandpoint_defconfig | 1017 ++++++++++++++++++++++++++++++++++++++
kernel/legacy_serial.c | 2
platforms/Makefile | 1
platforms/embedded6xx/Makefile | 4
platforms/embedded6xx/sandpoint.c | 629 +++++++++++++++++++++++
sysdev/mpic.c | 7
18 files changed, 2676 insertions(+), 11 deletions(-)
---
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6729c98..de09eac 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -323,7 +323,10 @@ config PPC_ISERIES
config EMBEDDED6xx
bool "Embedded 6xx/7xx/7xxx-based board"
- depends on PPC32 && BROKEN
+ depends on PPC32
+ select PPC_UDBG_16550
+ select MPIC
+ select MPIC_SERIAL
config APUS
bool "Amiga-APUS"
@@ -411,6 +414,11 @@ config MPIC
depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP
bool
default y
+
+config MPIC_SERIAL
+ depends on EMBEDDED6xx
+ bool
+ default n
config PPC_RTAS
bool
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 840ae59..1995544 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,8 +36,14 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
-src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
+src-boot := crt0.S string.S stdio.c main.c div64.S
src-boot += $(zlib)
+ifeq ($(CONFIG_EMBEDDED6xx),y)
+src-boot += prom_embedded.c ns16550.c dts/sandpoint.S \
+ dt_utils.c sandpoint.c mpc10x.c
+else
+src-boot += prom.c
+endif
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
diff --git a/arch/powerpc/boot/dt_utils.c b/arch/powerpc/boot/dt_utils.c
new file mode 100644
index 0000000..c991598
--- /dev/null
+++ b/arch/powerpc/boot/dt_utils.c
@@ -0,0 +1,95 @@
+/*
+ * Simple dtb (binary flattened device tree) search/manipulation routines.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ * - The code for strrchr() was copied from lib/string.c and is
+ * copyrighted by Linus Torvalds.
+ * - The smarts for dt_find_prop_by_name() were copied with the author's
+ * permission from u-boot:common/ft_build.c which was written by
+ * Pantelis Antoniou <pantelis@embeddedalley.com>.
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/* Supports dtb version 0x10 only */
+
+#include <stdarg.h>
+#include "page.h"
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
+
+struct boot_param_header *
+dt_get_bph(void *dt_blob)
+{
+ return (struct boot_param_header *)dt_blob;
+}
+
+char *
+strrchr(const char *s, int c)
+{
+ const char *p = s + strlen(s);
+
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+
+
+void *
+dt_find_prop_by_name(void *dt_blob, char *full_name, u32 *val_sizep)
+{
+ struct boot_param_header *bph = dt_get_bph(dt_blob);
+ u32 *dp, tag, size;
+ char *s, *str_region;
+ static char path[256], prop[256];
+
+ path[0] = '\0';
+
+ if (bph->magic != OF_DT_HEADER) {
+ printf("dt_find_prop_by_name: bogus magic value: 0x%x\n",
+ bph->magic);
+ return NULL;
+ }
+
+ dp = (u32 *)((u32)dt_blob + bph->off_dt_struct);
+ str_region = (char *)((u32)dt_blob + bph->off_dt_strings);
+
+ while ((tag = *dp++) != OF_DT_END) {
+ switch (tag) {
+ case OF_DT_PROP:
+ size = *dp++;
+ s = str_region + *dp++;
+
+ strcpy(prop, path);
+ strcat(prop, s);
+ if (!strcmp(prop, full_name)) {
+ *val_sizep = size;
+ return dp; /* ptr to prop value */
+ }
+
+ dp = (u32 *)_ALIGN_UP((unsigned long)dp + size, 4);
+ break;
+ case OF_DT_BEGIN_NODE:
+ s = (char *)dp;
+ strcat(path, s);
+ strcat(path, "/");
+ dp = (u32 *)_ALIGN_UP((u32)dp + strlen(s) + 1, 4);
+ break;
+ case OF_DT_END_NODE:
+ path[strlen(path) - 1] = '\0';
+ s = strrchr(path, '/');
+ if (s != NULL)
+ s[1] = '\0';
+ break;
+ default:
+ printf("dt_find_prop_by_name: bugus tag: 0x%x\n", tag);
+ }
+ }
+ return NULL;
+}
diff --git a/arch/powerpc/boot/dts/sandpoint.dts b/arch/powerpc/boot/dts/sandpoint.dts
new file mode 100644
index 0000000..93ecf37
--- /dev/null
+++ b/arch/powerpc/boot/dts/sandpoint.dts
@@ -0,0 +1,204 @@
+/*
+ * Device Tree Souce for Freescale Sandpoint
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+
+XXXX add flash parts, rtc, ??
+
+build with: "dtc -I dts -O asm -o sandpoint.S -V 16 sandpoint.dts"
+
+
+ */
+
+/ {
+ linux,phandle = <1000>;
+ model = "Sandpoint";
+ compatible = "classic+mpc10x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ linux,phandle = <2000>;
+ #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,603e { /* Really 75x, 74xx, 824x */
+ linux,phandle = <2100>;
+ linux,boot-cpu;
+ device_type = "cpu";
+ reg = <0>;
+ clock-frequency = <0>; /* Fixed by bootwrapper */
+ timebase-frequency = <0>; /* Fixed by bootwrapper */
+ /* Following required by dtc but not used */
+ i-cache-line-size = <0>;
+ d-cache-line-size = <0>;
+ i-cache-size = <0>;
+ d-cache-size = <0>;
+ };
+ };
+
+ memory {
+ linux,phandle = <3000>;
+ device_type = "memory";
+ reg = <00000000 00000000>; /* Fixed by bootwrapper */
+ };
+
+ mpc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+ linux,phandle = <4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "mpc10x-bridge";
+ compatible = "mpc10x-bridge";
+ store-gathering = <0>; /* 0 == off, !0 == on */
+ reg = <fc000000 00100000>;
+ ranges = <80000000 80000000 70000000 /* pci mem space */
+ fe000000 fe000000 00c00000 /* pci i/o space */
+ fec00000 fec00000 00300000 /* pci cfg regs */
+ fef00000 fec00000 00100000>; /* pci iack */
+
+ dma@1100 {
+ linux,phandle = <4100>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "dma";
+ compatible = "fsl-dma";
+ clock-frequency = <0>;
+ reg = <fc001100 00000024>;
+ interrupts = <33 0>;
+ interrupt-parent = <4400>;
+ };
+
+ dma@1200 {
+ linux,phandle = <4200>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "dma";
+ compatible = "fsl-dma";
+ clock-frequency = <0>;
+ reg = <fc001200 00000024>;
+ interrupts = <34 0>;
+ interrupt-parent = <4400>;
+ };
+
+ i2c {
+ linux,phandle = <4300>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "i2c";
+ compatible = "fsl-i2c";
+ clock-frequency = <0>;
+ reg = <fc003000 00001000>;
+ interrupts = <32 0>;
+ interrupt-parent = <4400>;
+ };
+
+ pic {
+ linux,phandle = <4400>;
+ clock-frequency = <0>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ device_type = "open-pic";
+ compatible = "chrp,open-pic";
+ reg = <fc040000 00040000>;
+ };
+
+ pci {
+ linux,phandle = <4500>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+ reg = <fec00000 00400000>;
+ ranges = <01000000 0 0 fe000000 0 00c00000
+ 02000000 0 80000000 80000000 0 70000000>;
+ bus-range = <0 ff>;
+ clock-frequency = <7f28155>;
+ interrupt-parent = <4400>;
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x11 */
+ 8800 0 0 1 4100 18 0
+ 8800 0 0 2 4100 18 0
+ 8800 0 0 3 4100 18 0
+ 8800 0 0 4 4100 18 0
+ /* IDSEL 0x12 */
+ 9000 0 0 1 4100 19 0
+ 9000 0 0 2 4100 19 0
+ 9000 0 0 3 4100 19 0
+ 9000 0 0 4 4100 19 0
+ /* IDSEL 0x13 */
+ 9800 0 0 1 4100 20 0
+ 9800 0 0 2 4100 20 0
+ 9800 0 0 3 4100 20 0
+ 9800 0 0 4 4100 20 0
+ /* IDSEL 0x14 */
+ a000 0 0 1 4100 21 0
+ a000 0 0 2 4100 21 0
+ a000 0 0 3 4100 21 0
+ a000 0 0 4 4100 21 0
+ /* IDSEL 0x15 */
+ a800 0 0 1 4100 22 0
+ a800 0 0 2 4100 22 0
+ a800 0 0 3 4100 22 0
+ a800 0 0 4 4100 22 0
+ /* IDSEL 0x16 */
+ b000 0 0 1 4100 23 0
+ b000 0 0 2 4100 23 0
+ b000 0 0 3 4100 23 0
+ b000 0 0 4 4100 23 0
+ >;
+
+ isa {
+ linux,phandle = <4510>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "isa";
+ compatible = "isa";
+ ranges = <0 0 01000000 0 0 00800000>;
+
+ serial@3f8 {
+ linux,phandle = <4511>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0 3f8 8>;
+ clock-frequency = <1c2000>;
+ current-speed = <2580>;
+ interrupts = <4 0>;
+ interrupt-parent = <4400>;
+ };
+
+ serial@2f8 {
+ linux,phandle = <4512>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0 2f8 8>;
+ clock-frequency = <1c2000>;
+ current-speed = <2580>;
+ interrupts = <3 0>;
+ interrupt-parent = <4400>;
+ };
+ };
+ };
+ };
+
+ chosen {
+ linux,phandle = <5000>;
+ linux,platform = <1>;
+ bootargs = "ip=on";
+ linux,stdout-path = "/mpc8245/pci/isa/serial@3f8";
+ interrupt-controller = <4100>;
+ };
+};
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 0000000..65c1864
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,160 @@
+#ifndef _IO_H
+#define __IO_H
+
+#include "types.h"
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ * These routines do not perform EEH-related I/O address translation,
+ * and should not be used directly by device drivers. Use inb/readb
+ * instead.
+ */
+static inline int in_8(const volatile unsigned char *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+ __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline int in_le16(const volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline int in_be16(const volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("sthbrx %1,0,%2; sync"
+ : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void out_be16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("sth%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned in_le32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline unsigned in_be32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+ : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned long in_le64(const volatile unsigned long *addr)
+{
+ unsigned long tmp, ret;
+
+ __asm__ __volatile__(
+ "ld %1,0(%2)\n"
+ "twi 0,%1,0\n"
+ "isync\n"
+ "rldimi %0,%1,5*8,1*8\n"
+ "rldimi %0,%1,3*8,2*8\n"
+ "rldimi %0,%1,1*8,3*8\n"
+ "rldimi %0,%1,7*8,4*8\n"
+ "rldicl %1,%1,32,0\n"
+ "rlwimi %0,%1,8,8,31\n"
+ "rlwimi %0,%1,24,16,23\n"
+ : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr));
+ return ret;
+}
+
+static inline unsigned long in_be64(const volatile unsigned long *addr)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ld%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le64(volatile unsigned long *addr, unsigned long val)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__(
+ "rldimi %0,%1,5*8,1*8\n"
+ "rldimi %0,%1,3*8,2*8\n"
+ "rldimi %0,%1,1*8,3*8\n"
+ "rldimi %0,%1,7*8,4*8\n"
+ "rldicl %1,%1,32,0\n"
+ "rlwimi %0,%1,8,8,31\n"
+ "rlwimi %0,%1,24,16,23\n"
+ "std %0,0(%3)\n"
+ "sync"
+ : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr));
+}
+
+static inline void out_be64(volatile unsigned long *addr, unsigned long val)
+{
+ __asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
+}
+
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+
+/* Indirect PCI config space access routines */
+static inline void
+pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
+ int offset, u8 *val)
+{
+ out_be32(cfg_addr,
+ ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
+ *val = in_8((u8 *)(cfg_data + (offset & 3)));
+ return;
+}
+
+static inline void
+pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
+ int offset, u32 *val)
+{
+ out_be32(cfg_addr,
+ ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
+ *val = in_le32(cfg_data + (offset & 3));
+ return;
+}
+
+#endif /* _IO_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 816446f..6acdf66 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -48,10 +48,19 @@ static char scratch[46912]; /* scratch s
static char elfheader[256];
+#ifdef CONFIG_PPC_OF
typedef void (*kernel_entry_t)( unsigned long,
unsigned long,
void *,
void *);
+#else
+void platform_fixups(void *dt_blob);
+extern void *dt_blob_start;
+extern void *dt_blob_end;
+void edit_cmdline(void *dt_blob_start);
+typedef void (*kernel_entry_t)(void *dtb_addr, void *kernel_entry_paddr,
+ void *must_be_null);
+#endif
#undef DEBUG
@@ -218,7 +227,7 @@ void start(unsigned long a1, unsigned lo
if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
exit();
- printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
+ printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
/*
* The first available claim_base must be above the end of the
@@ -238,7 +247,7 @@ void start(unsigned long a1, unsigned lo
gunzip(elfheader, sizeof(elfheader),
(unsigned char *)vmlinuz.addr, &len);
} else
- memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+ memcpy(elfheader, (const void *)vmlinuz.addr,sizeof(elfheader));
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
@@ -263,18 +272,21 @@ void start(unsigned long a1, unsigned lo
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
- printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
+ printf("Allocating 0x%lx bytes for initrd ...\n\r",initrd.size);
initrd.addr = try_claim(initrd.size);
if (initrd.addr == 0) {
- printf("Can't allocate memory for initial ramdisk !\n\r");
+ printf("Can't allocate memory for initial "
+ "ramdisk !\n\r");
exit();
}
a1 = initrd.addr;
a2 = initrd.size;
- printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
- initrd.addr, (unsigned long)_initrd_start, initrd.size);
- memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
- printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
+ printf("initial ramdisk moving 0x%lx <- 0x%lx "
+ "(0x%lx bytes)\n\r", initrd.addr,
+ (unsigned long)_initrd_start, initrd.size);
+ memmove((void *)initrd.addr, (void *)_initrd_start,initrd.size);
+ printf("initrd head: 0x%lx\n\r",
+ *((unsigned long *)initrd.addr));
}
/* Eventually gunzip the kernel */
@@ -299,6 +311,7 @@ #endif
flush_cache((void *)vmlinux.addr, vmlinux.size);
kernel_entry = (kernel_entry_t)vmlinux.addr;
+#ifdef CONFIG_PPC_OF
#ifdef DEBUG
printf( "kernel:\n\r"
" entry addr = 0x%lx\n\r"
@@ -311,9 +324,20 @@ #ifdef DEBUG
#endif
kernel_entry(a1, a2, prom, NULL);
+#else /* !CONFIG_PPC_OF ==> flattened device tree */
+#ifdef DEBUG
+ printf("kernel:\n\r"
+ " entry addr = 0x%lx\n\r"
+ " flattened dt = 0x%lx\n\r",
+ (unsigned long)kernel_entry, &dt_blob_start);
+#endif
+ edit_cmdline(&dt_blob_start);
+ platform_fixups(&dt_blob_start);
+ kernel_entry(&dt_blob_start, (void *)vmlinux.addr, NULL);
+#endif
+
printf("Error: Linux kernel returned to zImage bootloader!\n\r");
exit();
}
-
diff --git a/arch/powerpc/boot/mpc10x.c b/arch/powerpc/boot/mpc10x.c
new file mode 100644
index 0000000..d9c0e0b
--- /dev/null
+++ b/arch/powerpc/boot/mpc10x.c
@@ -0,0 +1,88 @@
+/*
+ * Freescale mpc10[67] & mpc824[015] specific code.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "prom.h"
+
+/* Map B (CHRP Map) Defines */
+#define MPC10X_MAPB_CNFG_ADDR 0xfec00000
+#define MPC10X_MAPB_CNFG_DATA 0xfee00000
+
+/* Define offsets for the memory controller registers in the config space */
+#define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_START_2 0x84 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_START_1 0x88 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_BANK_ENABLES 0xa0
+
+
+/*
+ * Read the memory controller registers to determine the amount of memory in
+ * the system. This assumes that the firmware has correctly set up the memory
+ * controller registers.
+ * Assume memory map B (CHRP).
+ */
+u32
+mpc10x_get_mem_size(void)
+{
+ u32 *config_addr, *config_data, val;
+ u32 start, end, total, offset, i;
+ u8 bank_enables;
+
+ config_addr = (u32 *)MPC10X_MAPB_CNFG_ADDR;
+ config_data = (u32 *)MPC10X_MAPB_CNFG_DATA;
+
+ pci_indirect_read_config_byte(config_addr, config_data, PCI_DEVFN(0,0),
+ MPC10X_MCTLR_MEM_BANK_ENABLES, &bank_enables);
+
+ total = 0;
+
+ for (i=0; i<8; i++) {
+ if (bank_enables & (1 << i)) {
+ offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ start = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ start = (val << 28) | (start << 20);
+
+ offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ end = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ end = (val << 28) | (end << 20) | 0xfffff;
+
+ total += (end - start + 1);
+ }
+ }
+
+ return total;
+}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 0000000..f92073a
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,118 @@
+/*
+ * COM1 NS16550 support
+ */
+
+#include "io.h"
+#include "prom.h"
+
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+
+unsigned long com_port;
+
+/*
+ * Serial defines.
+ */
+#define SERIAL_BAUD 9600
+
+#define SANDPOINT_SERIAL_0 0xfe0003f8
+#define SANDPOINT_SERIAL_1 0xfe0002f8
+
+#define RS_TABLE_SIZE 2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+#define UART_CLK 1843200
+
+/* XXXX Get info from dt instead */
+static struct {
+ int baud_base;
+ unsigned long com_port;
+ u16 iomem_reg_shift;
+} rs_table[RS_TABLE_SIZE] = {
+ { BASE_BAUD, SANDPOINT_SERIAL_0, 0 },
+ { BASE_BAUD, SANDPOINT_SERIAL_1, 0 },
+};
+
+static int shift;
+
+unsigned long
+serial_init(int chan, void *ignored)
+{
+ unsigned long base_baud;
+ unsigned char lcr, dlm;
+
+ com_port = rs_table[chan].com_port;
+
+ /* How far apart the registers are. */
+ shift = rs_table[chan].iomem_reg_shift;
+ /* Base baud.. */
+ base_baud = rs_table[chan].baud_base;
+
+ /* save the LCR */
+ lcr = in_8((const volatile unsigned char *)com_port
+ + (UART_LCR << shift));
+ /* Access baud rate */
+ out_8((volatile unsigned char *)com_port + (UART_LCR << shift), 0x80);
+ dlm = in_8((const volatile unsigned char *)com_port
+ + (UART_DLM << shift));
+ /*
+ * Test if serial port is unconfigured.
+ * We assume that no-one uses less than 110 baud or
+ * less than 7 bits per character these days.
+ * -- paulus.
+ */
+
+ if ((dlm <= 4) && (lcr & 2))
+ /* port is configured, put the old LCR back */
+ out_8((volatile unsigned char *)com_port
+ + (UART_LCR << shift), lcr);
+ else {
+ /* Input clock. */
+ out_8((volatile unsigned char *)com_port + (UART_DLL << shift),
+ (base_baud / SERIAL_BAUD) & 0xFF);
+ out_8((volatile unsigned char *)com_port + (UART_DLM << shift),
+ (base_baud / SERIAL_BAUD) >> 8);
+ /* 8 data, 1 stop, no parity */
+ out_8((volatile unsigned char *)com_port + (UART_LCR << shift),
+ 0x03);
+ /* RTS/DTR */
+ out_8((volatile unsigned char *)com_port + (UART_MCR << shift),
+ 0x03);
+ }
+ /* Clear & enable FIFOs */
+ out_8((volatile unsigned char *)com_port + (UART_FCR << shift), 0x07);
+
+ return (com_port);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+ while ((in_8((const volatile unsigned char *)com_port
+ + (UART_LSR << shift)) & UART_LSR_THRE) == 0);
+ out_8((volatile unsigned char *)com_port, c);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+ while ((in_8((const volatile unsigned char *)com_port
+ + (UART_LSR << shift)) & UART_LSR_DR) == 0);
+ return in_8((const volatile unsigned char *)com_port);
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+ return ((in_8((const volatile unsigned char *)com_port
+ + (UART_LSR << shift)) & UART_LSR_DR) != 0);
+}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 3e2ddd4..28394f7 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -1,6 +1,58 @@
#ifndef _PPC_BOOT_PROM_H_
#define _PPC_BOOT_PROM_H_
+#include "types.h"
+
+/* #ifndef CONFIG_PPC_OF XXXX */
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER 0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
+#define OF_DT_END_NODE 0x2 /* End node */
+#define OF_DT_PROP 0x3 /* Property: name off, size,
+ * content */
+#define OF_DT_NOP 0x4 /* nop */
+#define OF_DT_END 0x9
+
+#define OF_DT_VERSION 0x10
+
+/*
+ * This is what gets passed to the kernel by prom_init or kexec
+ *
+ * The dt struct contains the device tree structure, full pathes and
+ * property contents. The dt strings contain a separate block with just
+ * the strings for the property names, and is fully page aligned and
+ * self contained in a page, so that it can be kept around by the kernel,
+ * each property name appears only once in this page (cheap compression)
+ *
+ * the mem_rsvmap contains a map of reserved ranges of physical memory,
+ * passing it here instead of in the device-tree itself greatly simplifies
+ * the job of everybody. It's just a list of u64 pairs (base/size) that
+ * ends when size is 0
+ */
+
+struct boot_param_header
+{
+ u32 magic; /* magic word OF_DT_HEADER */
+ u32 totalsize; /* total size of DT block */
+ u32 off_dt_struct; /* offset to structure */
+ u32 off_dt_strings; /* offset to strings */
+ u32 off_mem_rsvmap; /* offset to memory reserve map */
+ u32 version; /* format version */
+ u32 last_comp_version; /* last compatible version */
+ /* version 2 fields below */
+ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
+ /* version 3 fields below */
+ u32 dt_strings_size; /* size of the DT strings block */
+};
+
+unsigned long serial_init(int chan, void *ignored);
+void serial_putc(unsigned long com_port, unsigned char c);
+unsigned char serial_getc(unsigned long com_port);
+int serial_tstc(unsigned long com_port);
+
+/* #endif XXXX */
+
typedef void *phandle;
typedef void *ihandle;
diff --git a/arch/powerpc/boot/prom_embedded.c b/arch/powerpc/boot/prom_embedded.c
new file mode 100644
index 0000000..96971df
--- /dev/null
+++ b/arch/powerpc/boot/prom_embedded.c
@@ -0,0 +1,112 @@
+/*
+ * prom.c routines for non-OF/embedded platforms.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
+
+int (*prom)(void *);
+phandle chosen_handle;
+ihandle stdout;
+
+int
+service_exit(int nargs, int nret, va_list args)
+{
+ printf("EXIT\n");
+ while (1);
+ /* NOTREACHED */
+}
+
+int
+service_finddevice(int nargs, int nret, va_list args)
+{
+ return 0; /* XXXX */
+}
+
+int
+service_getprop(int nargs, int nret, va_list args)
+{
+ return 4; /* XXXX */
+}
+
+int
+call_prom(const char *service, int nargs, int nret, ...)
+{
+
+ static struct {
+ char *service;
+ int ((*rtn)(int nargs, int nret, va_list args));
+ } services[] = {
+ { "exit", service_exit },
+ { "finddevice", service_finddevice },
+ { "getprop", service_getprop },
+ /* { "write", service_write }, */
+ };
+ va_list args;
+ int i, rc = 0;
+
+ for (i=0; i<ARRAY_SIZE(services); i++)
+ if (!strcmp(service, services[i].service)) {
+ va_start(args, nret);
+ rc = services[i].rtn(nargs, nret, args);
+ va_end(args);
+ }
+
+ return (nret > 0)? rc : 0;
+}
+
+void
+*claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ return (void *)virt;
+}
+
+int
+write(void *handle, void *ptr, int nb)
+{
+ char c, *s = (char *)ptr;
+ static char first_time = 1;
+ extern unsigned long com_port;
+
+ if (first_time) {
+ serial_init(0, NULL);
+ first_time = 0;
+ }
+
+ while ((c = *s++) != '\0') {
+ serial_putc(com_port, c);
+ if (c == '\n')
+ serial_putc(com_port, '\r');
+ }
+
+ return nb;
+}
+
+void
+edit_cmdline(void *dt_blob)
+{
+ u32 i, *v;
+ extern void *dt_find_prop_by_name(void *dt_blob, char *full_name,
+ u32 *val_sizep);
+
+ if ((v = (u32 *)dt_find_prop_by_name(dt_blob,
+ "/chosen/bootargs", &i)) != NULL) {
+ printf("\nLinux/PPC load: %s", (char *)v);
+ /* edit cmdline & put back into dt (realloc may be necessary) */
+ }
+ printf("\n");
+}
+
+void __attribute__ ((weak))
+platform_fixups(void *dt_blob)
+{
+}
diff --git a/arch/powerpc/boot/sandpoint.c b/arch/powerpc/boot/sandpoint.c
new file mode 100644
index 0000000..283bb66
--- /dev/null
+++ b/arch/powerpc/boot/sandpoint.c
@@ -0,0 +1,110 @@
+/*
+ * Sandpoint specific fixups.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "prom.h"
+
+static u32 cpu_824x[32] = {
+ 5, 6, 9, 4, 4, 5, 2, 6, 6, 4, 9, 6, 5, 7, 6, 7,
+ 4, 5, 4, 6, 7, 8, 8, 4, 6, 5, 8, 6, 6, 5, 7, 0
+};
+static u32 cpu_7xx[16] = { /* 750/755 */
+ 0, 15, 14, 2, 4, 13, 20, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static u32 cpu_7457[32] = {
+ 23, 34, 15, 30, 14, 36, 2, 40, 4, 42, 13, 26, 17, 48, 19, 18,
+ 6, 21, 11, 22, 8, 20, 10, 24, 16, 28, 12, 32, 27, 56, 0, 25
+};
+
+static struct processor_info {
+ u32 pvr;
+ u32 mask;
+ u32 bus_freq;
+ u32 hid1_shift;
+ u32 hid1_mask;
+ u32 *pll_tbl;
+ u32 max_mem; /* 7457 flaky with > 64MB of mem */
+} processor_info_tbl[] = { /* From cputable -- MHz are only guesses */
+ /* 824x */
+ { 0x00810000, 0x7fff0000, 100000000, 27, 0x1f, cpu_824x, 0x80000000 },
+ /* 750 */
+ { 0x00084202, 0xffffffff, 100000000, 28, 0xf, cpu_7xx, 0x80000000 },
+ /* 745/755 */
+ { 0x00083000, 0xfffff000, 100000000, 28, 0xf, cpu_7xx, 0x80000000 },
+ /* 7447/7457 Rev 1.0 */
+ { 0x80020100, 0xffffffff, 100000000, 12, 0x1f, cpu_7457, 0x04000000 },
+ /* 7447/7457 Rev 1.1 */
+ { 0x80020101, 0xffffffff, 100000000, 12, 0x1f, cpu_7457, 0x04000000 },
+ /* 7447/7457 Rev 1.2 & up*/
+ { 0x80020000, 0xffff0000, 100000000, 12, 0x1f, cpu_7457, 0x04000000 },
+ /* 7447A */
+ { 0x80030000, 0xffff0000, 100000000, 12, 0x1f, cpu_7457, 0x80000000 },
+};
+
+struct processor_info *
+get_processor_info(u32 pvr)
+{
+ struct processor_info *pit = processor_info_tbl;
+ u32 i;
+
+ for (i=0; i<ARRAY_SIZE(processor_info_tbl); i++, pit++)
+ if (pit->pvr == (pvr & pit->mask))
+ return pit;
+ return NULL;
+}
+
+#define __stringify_1(x) #x
+#define __stringify(x) __stringify_1(x)
+
+
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define mfspr(rn) ({unsigned long rval; \
+ asm volatile("mfspr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+
+void
+platform_fixups(void *dt_blob)
+{
+ u32 i, *v, hid1, max_mem = 0xffffffff;
+ struct processor_info *pit;
+ extern void *dt_find_prop_by_name(void *dt_blob, char *full_name,
+ u32 *val_sizep);
+ extern u32 mpc10x_get_mem_size(void);
+
+ if ((pit = get_processor_info(mfspr(SPRN_PVR))) != NULL) {
+ if ((v = (u32 *)dt_find_prop_by_name(dt_blob,
+ "/cpus/PowerPC,603e/clock-frequency", &i)) != NULL) {
+
+ hid1 = (mfspr(SPRN_HID1) >> pit->hid1_shift)
+ & pit->hid1_mask;
+ v[0] = pit->bus_freq * pit->pll_tbl[hid1]/2;
+ }
+
+ if ((v = (u32 *)dt_find_prop_by_name(dt_blob,
+ "/cpus/PowerPC,603e/timebase-frequency", &i)) != NULL)
+ v[0] = pit->bus_freq / 4;
+
+ max_mem = pit->max_mem;
+ }
+
+ /* Get the RAM size from the memory controller */
+ if ((v = (u32 *)dt_find_prop_by_name(dt_blob, "/memory/reg", &i))
+ != NULL) {
+ i = mpc10x_get_mem_size();
+ v[1] = min(i, max_mem);
+ }
+}
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
new file mode 100644
index 0000000..7095b54
--- /dev/null
+++ b/arch/powerpc/boot/types.h
@@ -0,0 +1,28 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* XXXX
+#ifdef CONFIG_PPC32
+*/
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+/*
+#endif
+*/
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
+#endif /* _TYPES_H_ */
diff --git a/arch/powerpc/configs/sandpoint_defconfig b/arch/powerpc/configs/sandpoint_defconfig
new file mode 100644
index 0000000..3345c8e
--- /dev/null
+++ b/arch/powerpc/configs/sandpoint_defconfig
@@ -0,0 +1,1017 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Wed May 17 16:48:20 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_ISERIES is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_APUS is not set
+CONFIG_MPIC=y
+CONFIG_MPIC_SERIAL=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_HDPU is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+CONFIG_SANDPOINT=y
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_EV64360 is not set
+CONFIG_PPC_GEN550=y
+CONFIG_EPIC_SERIAL_MODE=y
+CONFIG_MPC10X_BRIDGE=y
+CONFIG_MPC10X_OPENPIC=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+# CONFIG_SANDPOINT_ENABLE_UART1 is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_PCMCIA_XIRCOM is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 6e67b5b..2feca55 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -147,9 +147,11 @@ static int __init add_legacy_isa_port(st
if (reg == NULL)
return -1;
+#if 0 /* XXXX */
/* Verify it's an IO port, we don't support anything else */
if (!(reg[0] & 0x00000001))
return -1;
+#endif
/* Now look for an "ibm,aix-loc" property that gives us ordering
* if any...
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index c4f6b0d..308fead 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PPC_PSERIES) += pseries/
obj-$(CONFIG_PPC_ISERIES) += iseries/
obj-$(CONFIG_PPC_MAPLE) += maple/
obj-$(CONFIG_PPC_CELL) += cell/
+obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
new file mode 100644
index 0000000..3324426
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC Embedded Platforms
+#
+obj-$(CONFIG_SANDPOINT) += sandpoint.o
diff --git a/arch/powerpc/platforms/embedded6xx/sandpoint.c b/arch/powerpc/platforms/embedded6xx/sandpoint.c
new file mode 100644
index 0000000..9567de8
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/sandpoint.c
@@ -0,0 +1,629 @@
+/*
+ * Board setup routines for the Freescale Sandpoint Test Platform.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file adds support for the Freescale Sandpoint Test Platform.
+ * These boards have a PPMC slot for the processor so any combination
+ * of cpu and host bridge can be attached. This port is for an 8240 PPMC
+ * module from Freescale and other closely related cpu/host bridge
+ * combinations (e.g., 750/755/7400 with MPC107 host bridge).
+ * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
+ * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
+ * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
+ * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
+ * but are really 5V).
+ *
+ * The firmware on the sandpoint is called DINK (not my acronym :). This port
+ * depends on DINK to do some basic initialization (e.g., initialize the memory
+ * ctlr) and to ensure that the processor is using MAP B (CHRP map).
+ *
+ * The switch settings for the Sandpoint board MUST be as follows:
+ * S3: down
+ * S4: up
+ * S5: up
+ * S6: down
+ *
+ * 'down' is in the direction from the PCI slots towards the PPMC slot;
+ * 'up' is in the direction from the PPMC slot towards the PCI slots.
+ * Be careful, the way the sandpoint board is installed in XT chasses will
+ * make the directions reversed.
+ *
+ * Since Freescale listened to our suggestions for improvement, we now have
+ * the Sandpoint X3 board. All of the PCI slots are available, it uses
+ * the serial interrupt interface (just a hardware thing we need to
+ * configure properly).
+ *
+ * Use the default X3 switch settings. The interrupts are then:
+ * EPIC Source
+ * 0 SIOINT (8259, active low)
+ * 1 PCI #1
+ * 2 PCI #2
+ * 3 PCI #3
+ * 4 PCI #4
+ * 7 Winbond INTC (IDE interrupt)
+ * 8 Winbond INTD (IDE interrupt)
+ *
+ *
+ * Freescale has finally released a version of DINK32 that correctly
+ * (seemingly) initalizes the memory controller correctly, regardless
+ * of the amount of memory in the system. Once a method of determining
+ * what version of DINK initializes the system for us, if applicable, is
+ * found, we can hopefully stop hardcoding 32MB of RAM.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+/*
+#include <asm/kgdb.h>
+*/
+#include <asm/ppc_sys.h>
+#include <asm/mpic.h>
+
+static void sandpoint_halt(void);
+
+/*
+ * Define all of the IRQ senses and polarities. Taken from the
+ * Sandpoint X3 User's manual.
+ */
+static u_char sandpoint_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 1: XXXX FILL?? */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 6: XXXX FILL?? */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 7: XXXX FILL?? */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 9: IDE (INT D) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 10: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 11: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 12: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 13: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 14: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 15: */
+};
+
+/*
+ * Interrupt setup and service. Interrrupts on the Sandpoint come
+ * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
+ * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
+ * IDE is on EPIC 7 and 8.
+ */
+static void __init
+sandpoint_init_IRQ(void)
+{
+ struct mpic *mpic;
+ phys_addr_t openpic_paddr = 0xfc000000 + /* XXXX */
+ MPC10X_EUMB_EPIC_OFFSET;
+
+ /* This doesn't handle i2c, dma, i2o, or timer intrs right now XXXX */
+ mpic = mpic_alloc(openpic_paddr, MPIC_PRIMARY,
+ 16 /* XXXX otherwise num_sources used */ ,
+ NUM_8259_INTERRUPTS,
+ 0, /* was 16 */
+ NR_IRQS - 4 /* XXXX */,
+ sandpoint_openpic_initsenses,
+ sizeof(sandpoint_openpic_initsenses), " EPIC ");
+
+ BUG_ON(mpic == NULL); /* XXXX */
+ mpic_assign_isu(mpic, 0, openpic_paddr + 0x10200);
+ mpic_init(mpic);
+ mpic_setup_cascade(NUM_8259_INTERRUPTS, i8259_irq_cascade, NULL);
+ i8259_init(0xfef00000, 0); /* pci iack addr */
+}
+
+/*
+ * Freescale Sandpoint interrupt routing.
+ */
+static inline int
+x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
+ { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
+ { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
+ { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
+ };
+
+ const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+sandpoint_setup_winbond_83553(struct pci_controller *hose)
+{
+ int devfn;
+
+ /*
+ * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
+ * We can't route the IDE interrupt to PCI INTC# or INTD# because those
+ * woule interfere with the PMC's INTC# and INTD# lines.
+ */
+ /*
+ * Winbond Fcn 0
+ */
+ devfn = PCI_DEVFN(11,0);
+
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x43, /* IDE Interrupt Routing Control */
+ 0xef);
+ early_write_config_word(hose,
+ 0,
+ devfn,
+ 0x44, /* PCI Interrupt Routing Control */
+ 0x0000);
+
+ /* Want ISA memory cycles to be forwarded to PCI bus */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x48, /* ISA-to-PCI Addr Decoder Control */
+ 0xf0);
+
+ /* Enable Port 92. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x4e, /* AT System Control Register */
+ 0x06);
+ /*
+ * Winbond Fcn 1
+ */
+ devfn = PCI_DEVFN(11,1);
+
+ /* Put IDE controller into native mode. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x09, /* Programming interface Register */
+ 0x8f);
+
+ /* Init IRQ routing, enable both ports, disable fast 16 */
+ early_write_config_dword(hose,
+ 0,
+ devfn,
+ 0x40, /* IDE Control/Status Register */
+ 0x00ff0011);
+ return;
+}
+
+static int
+x3_exclude_device(u_char bus, u_char devfn)
+{
+ if ((bus == 0) && (PCI_SLOT(devfn) == 0))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __init
+add_bridge(struct device_node *dev)
+{
+ int len;
+ struct pci_controller *hose;
+ int *bus_range;
+
+ printk("Adding PCI host bridge %s\n", dev->full_name);
+
+ bus_range = (int *) get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int))
+ printk(KERN_WARNING "Can't get bus-range for %s, assume"
+ " bus 0\n", dev->full_name);
+
+ hose = pcibios_alloc_controller();
+ if (hose == NULL)
+ return -ENOMEM;
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pci_process_bridge_OF_ranges(hose, dev, 1);
+
+ return 0;
+}
+
+u32 mag_dbg = 0;
+
+static void __init
+sandpoint_setup_arch(void)
+{
+ loops_per_jiffy = 100000000 / HZ;
+ isa_io_base = 0xfe000000;
+ isa_mem_base = 0x80000000;
+ pci_dram_offset = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+
+#if 1 /* XXXX NEW */
+ {
+ struct device_node *np;
+
+ mag_dbg = 1;
+ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+ add_bridge(np);
+ mag_dbg = 0;
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = x3_map_irq;
+ ppc_md.pci_exclude_device = x3_exclude_device; /* XXXX */
+ }
+#endif
+
+#if 0 /* XXXX */
+ if (strncmp (cur_ppc_sys_spec->ppc_sys_name, "8245", 4) == 0)
+ {
+ bd_t *bp = (bd_t *)__res;
+ struct plat_serial8250_port *pdata;
+
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC10X_UART0);
+ if (pdata)
+ {
+ pdata[0].uartclk = bp->bi_busfreq;
+ }
+
+#ifdef CONFIG_SANDPOINT_ENABLE_UART1
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC10X_UART1);
+ if (pdata)
+ {
+ pdata[0].uartclk = bp->bi_busfreq;
+ }
+#else
+ ppc_sys_device_remove(MPC10X_UART1);
+#endif
+ }
+#endif
+
+ printk(KERN_INFO "Freescale Sandpoint Test Platform\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+ /* DINK32 12.3 and below do not correctly enable any caches.
+ * We will do this now with good known values. Future versions
+ * of DINK32 are supposed to get this correct.
+ */
+ if (cpu_has_feature(CPU_FTR_SPEC7450))
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+ else if (cpu_has_feature(CPU_FTR_L2CR))
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+#if 0
+ /* Untested right now. */
+ if (cpu_has_feature(CPU_FTR_L3CR)) {
+ /* Magic value. */
+ _set_L3CR(0x8f032000);
+ }
+#endif
+}
+
+#if 1 /* XXXX */
+#define SANDPOINT_87308_CFG_ADDR 0x15c
+#define SANDPOINT_87308_CFG_DATA 0x15d
+
+#define SANDPOINT_87308_CFG_INB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ (byte) = inb(SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_CFG_OUTB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ outb((byte), SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_SELECT_DEV(dev_num) { \
+ SANDPOINT_87308_CFG_OUTB(0x07, (dev_num)); \
+}
+
+#define SANDPOINT_87308_DEV_ENABLE(dev_num) { \
+ SANDPOINT_87308_SELECT_DEV(dev_num); \
+ SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
+}
+
+/*
+ * Fix IDE interrupts.
+ */
+static int __init
+sandpoint_fix_winbond_83553(void)
+{
+ /* Make some 8259 interrupt level sensitive */
+ outb(0xe0, 0x4d0);
+ outb(0xde, 0x4d1);
+
+ return 0;
+}
+
+arch_initcall(sandpoint_fix_winbond_83553);
+
+/*
+ * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
+ */
+static int __init
+sandpoint_setup_natl_87308(void)
+{
+ u_char reg;
+
+ /*
+ * Enable all the devices on the Super I/O chip.
+ */
+ SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
+ SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
+ SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
+ SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
+ SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
+ SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
+ SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+ SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+
+ /* Set up floppy in PS/2 mode */
+ outb(0x09, SIO_CONFIG_RA);
+ reg = inb(SIO_CONFIG_RD);
+ reg = (reg & 0x3F) | 0x40;
+ outb(reg, SIO_CONFIG_RD);
+ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+
+ return 0;
+}
+
+arch_initcall(sandpoint_setup_natl_87308);
+
+static int __init
+sandpoint_request_io(void)
+{
+ request_region(0x00,0x20,"dma1");
+ request_region(0x20,0x20,"pic1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0xc0,0x20,"dma2");
+
+ return 0;
+}
+
+arch_initcall(sandpoint_request_io);
+#endif
+
+static void __init
+sandpoint_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void
+sandpoint_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* Set exception prefix high - to the firmware */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* Reset system via Port 92 */
+ outb(0x00, 0x92);
+ outb(0x01, 0x92);
+
+ for(;;); /* Spin until reset happens */
+}
+
+static void
+sandpoint_power_off(void)
+{
+ local_irq_disable();
+ for(;;); /* No way to shut power off with software */
+ /* NOTREACHED */
+}
+
+static void
+sandpoint_halt(void)
+{
+ sandpoint_power_off();
+ /* NOTREACHED */
+}
+
+static void
+sandpoint_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Freescale\n");
+ seq_printf(m, "machine\t\t: Sandpoint\n");
+}
+
+#if 0 /* XXXX */
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE support.
+ */
+static int sandpoint_ide_ports_known = 0;
+static unsigned long sandpoint_ide_regbase[MAX_HWIFS];
+static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long sandpoint_idedma_regbase;
+
+static void
+sandpoint_ide_probe(void)
+{
+ struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+ if (pdev) {
+ sandpoint_ide_regbase[0]=pdev->resource[0].start;
+ sandpoint_ide_regbase[1]=pdev->resource[2].start;
+ sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+ sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+ sandpoint_idedma_regbase=pdev->resource[4].start;
+ pci_dev_put(pdev);
+ }
+
+ sandpoint_ide_ports_known = 1;
+}
+
+static int
+sandpoint_ide_default_irq(unsigned long base)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ if (base == sandpoint_ide_regbase[0])
+ return SANDPOINT_IDE_INT0;
+ else if (base == sandpoint_ide_regbase[1])
+ return SANDPOINT_IDE_INT1;
+ else
+ return 0;
+}
+
+static unsigned long
+sandpoint_ide_default_io_base(int index)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ return sandpoint_ide_regbase[index];
+}
+
+static void __init
+sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ unsigned long ctrl_port, int *irq)
+{
+ unsigned long reg = data_port;
+ uint alt_status_base;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg++;
+ }
+
+ if (data_port == sandpoint_ide_regbase[0]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+ hw->irq = 14;
+ }
+ else if (data_port == sandpoint_ide_regbase[1]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+ hw->irq = 15;
+ }
+ else {
+ alt_status_base = 0;
+ hw->irq = 0;
+ }
+
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+ }
+
+ if (irq != NULL) {
+ *irq = hw->irq;
+ }
+}
+#endif
+#endif
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+sandpoint_set_bat(void)
+{
+ unsigned long bat3u, bat3l;
+
+ __asm__ __volatile__(
+ " lis %0,0xf800\n \
+ ori %1,%0,0x002a\n \
+ ori %0,%0,0x0ffe\n \
+ mtspr 0x21e,%0\n \
+ mtspr 0x21f,%1\n \
+ isync\n \
+ sync "
+ : "=r" (bat3u), "=r" (bat3l));
+}
+
+TODC_ALLOC();
+
+static int __init
+sandpoint_probe(void)
+{
+ return 1;
+}
+
+define_machine(sandpoint) {
+ .name = "Sandpoint",
+ .probe = sandpoint_probe,
+ .setup_arch = sandpoint_setup_arch,
+ .setup_io_mappings = sandpoint_map_io,
+ .init_IRQ = sandpoint_init_IRQ,
+ .show_cpuinfo = sandpoint_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = sandpoint_restart,
+ .power_off = sandpoint_power_off,
+ .halt = sandpoint_halt,
+ .calibrate_decr = generic_calibrate_decr,
+ /*
+ .progress = udbg_progress,
+ */
+};
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7dcdfcb..1badbec 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -629,6 +629,13 @@ #endif /* CONFIG_SMP */
mb();
}
+#ifdef CONFIG_MPIC_SERIAL
+ /* For serial interrupts & set clock ratio */
+ mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1,
+ mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1)
+ | (1<<27) | (0x7<<28));
+#endif
+
/* Read feature register, calculate num CPUs and, for non-ISU
* MPICs, num sources as well. On ISU MPICs, sources are counted
* as ISUs are added
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 0:21 [HACK] add sandpoint + flattened dt support to arch/powerpc/boot Mark A. Greer
@ 2006-05-18 5:32 ` Benjamin Herrenschmidt
2006-05-18 13:52 ` Matthew McClintock
` (2 more replies)
2006-05-18 13:47 ` Matthew McClintock
1 sibling, 3 replies; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-05-18 5:32 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> Hi,
>
> This is a patch with some very rough code that adds support for the
> sandpoint to arch/powerpc. I'm posting it now in the hope that it
> will spark a deeper discussion on exactly how we're going to support
> flattened device tree code in the bootwrapper for non-OF platforms.
> I'm also hoping that it will help others that are working on the same
> sort of thing so we can help each other.
>
> Again, the code is rough with lots of hacks but it boots and is
> something we can point to during this discussion.
>
> So...I am on the right path?
Well, we'll see, let's have a look :)
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 6729c98..de09eac 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -323,7 +323,10 @@ config PPC_ISERIES
>
> config EMBEDDED6xx
> bool "Embedded 6xx/7xx/7xxx-based board"
> - depends on PPC32 && BROKEN
> + depends on PPC32
> + select PPC_UDBG_16550
> + select MPIC
> + select MPIC_SERIAL
Not totally related to your patch but I'm tempted to turn that into a
"Generic 6xx/7xx/7xxx" rather than "embedded" if we manage to always
avoid board specific code most of the time, but instead add necessary
bits in the device-tree. We still need a per-board Kconfig option I
think that will just select the necessary bits and pieces (and more than
one can be selected at one time). Also, I think right now, the embedded
stuff is +/- exclusive from the MULTIPLATFORM stuff, that must be fixed
asap. We are all living in the same kernel now :)
> +
> +config MPIC_SERIAL
> + depends on EMBEDDED6xx
> + bool
> + default n
Not sure what the above is, I'll have a look further in the patch but I
can already tell you that it should be your per-board
CONFIG_PPC_SANDPOINT for example that "selects" the various bits you
need, and thus the above should depend on it, not EMBEDDED6xx... In fact
I'm wondering wether we should kill EMBEDDED6xx :) Unless it's purely a
reference to arch/powerpc/platforms/embedded6xx/ as a storage place for
board setup_xxx.c files which is useful for platforms that really don't
need more than one or 2 files in there.
> +ifeq ($(CONFIG_EMBEDDED6xx),y)
> +src-boot += prom_embedded.c ns16550.c dts/sandpoint.S \
> + dt_utils.c sandpoint.c mpc10x.c
> +else
> +src-boot += prom.c
> +endif
Again, I think CONFIG_EMBEDDED6xx is the wrong approach. I'd like to
avoid the word "embedded" altogether anyway :) Thing is, it would be
good if ultimately, embedded boards firmware was capable of passing a
device-tree. Thus, embedded a device-tree in the zImage wrapper is more
like a "fallback" solution which has the side effect of creating machine
specific zImage's.
That is why, I think, what we should do is have rules for building
separate zImage wrappers. The basic OF one (which exists in both real
and virtual mode versions and that I'd like to make capable of also
working if a flat device-tree is passed in), the zImage.sandpoint, the
zImage.prep, and whatever...
Thus enabling CONFIG_PPC_MYBOARD should trigger the build of the
board-flavored version of the wrapper in addition to all the other ones
for the other boards built as part of a given config.
I know it's a bit difficult because the current boot Kbuild rules aren't
really design for multiple targets but I think that's the way to go.
.../...
About the .dts file, we should look into "shipping" a pre-built one so
that dtc is not required for building a kernel. I think we already have
a mecanism for providing "shipped" versions of files and having the
option of rebuilding them from source (though I don't have the details
in mind at the moment)
> diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
.../.. io stuffs ...
Well... io accessors in here can't harm, the question is more how they
are used ;)
> +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
> +
> +/* Indirect PCI config space access routines */
> +static inline void
> +pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
> + int offset, u8 *val)
> +{
> + out_be32(cfg_addr,
> + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> + *val = in_8((u8 *)(cfg_data + (offset & 3)));
> + return;
> +}
> +
> +static inline void
> +pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
> + int offset, u32 *val)
> +{
> + out_be32(cfg_addr,
> + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> + *val = in_le32(cfg_data + (offset & 3));
> + return;
> +}
That's more annoying... if we start having PCI config space access in
the boot wrapper how far will it stop ? I'd rather keep that sort of
stuff local to myboard.c file unless it's really worth sharing... Unless
we end up with really common need for them in which case those should be
in separate files, possibly in a separate dir (thinking about it, prep
will probably need that too)
The main problem is how do we do printf kind of things from such a
bootloader. That needs IO, thus uart drivers etc... possibly parsing
from the device-tree etc... I'm tempted to just have a global
"boot_puts" function pointer set by the board and/or OF code to use
through the bootloader, maybe a shared uart.c file with various uart
bits and keep the gory implementation details of mapping the uart and
using those uart bits in the myboard.c file...
> +#ifdef CONFIG_PPC_OF
> typedef void (*kernel_entry_t)( unsigned long,
> unsigned long,
> void *,
> void *);
> +#else
> +void platform_fixups(void *dt_blob);
> +extern void *dt_blob_start;
> +extern void *dt_blob_end;
> +void edit_cmdline(void *dt_blob_start);
> +typedef void (*kernel_entry_t)(void *dtb_addr, void *kernel_entry_paddr,
> + void *must_be_null);
> +#endif
Why 2 different prototypes for kernel_entry ?
I think we need something like CONFIG_PPC_BOOT_HAS_BUILTIN_DT that
enables various DT related stuff in a clean way and have a builtin_dt.h
file with related prototypes & definitions.
> #undef DEBUG
> @@ -218,7 +227,7 @@ void start(unsigned long a1, unsigned lo
> if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
> exit();
>
> - printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
> + printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
Gratuituous uglyfication :)
> /*
> * The first available claim_base must be above the end of the
> @@ -238,7 +247,7 @@ void start(unsigned long a1, unsigned lo
> gunzip(elfheader, sizeof(elfheader),
> (unsigned char *)vmlinuz.addr, &len);
> } else
> - memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
> + memcpy(elfheader, (const void *)vmlinuz.addr,sizeof(elfheader));
Gratuituous uglyfication (bis) :)
> if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
> printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
> @@ -263,18 +272,21 @@ void start(unsigned long a1, unsigned lo
> initrd.size = (unsigned long)(_initrd_end - _initrd_start);
> initrd.memsize = initrd.size;
> if ( initrd.size > 0 ) {
> - printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
> + printf("Allocating 0x%lx bytes for initrd ...\n\r",initrd.size);
Gratuituous uglyfication (ter) :)
> initrd.addr = try_claim(initrd.size);
> if (initrd.addr == 0) {
> - printf("Can't allocate memory for initial ramdisk !\n\r");
> + printf("Can't allocate memory for initial "
> + "ramdisk !\n\r");
> exit();
> }
> a1 = initrd.addr;
> a2 = initrd.size;
> - printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
> - initrd.addr, (unsigned long)_initrd_start, initrd.size);
> - memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
> - printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
> + printf("initial ramdisk moving 0x%lx <- 0x%lx "
> + "(0x%lx bytes)\n\r", initrd.addr,
> + (unsigned long)_initrd_start, initrd.size);
> + memmove((void *)initrd.addr, (void *)_initrd_start,initrd.size);
> + printf("initrd head: 0x%lx\n\r",
> + *((unsigned long *)initrd.addr));
> }
>
> /* Eventually gunzip the kernel */
> @@ -299,6 +311,7 @@ #endif
> flush_cache((void *)vmlinux.addr, vmlinux.size);
>
> kernel_entry = (kernel_entry_t)vmlinux.addr;
> +#ifdef CONFIG_PPC_OF
> #ifdef DEBUG
> printf( "kernel:\n\r"
> " entry addr = 0x%lx\n\r"
> @@ -311,9 +324,20 @@ #ifdef DEBUG
> #endif
> kernel_entry(a1, a2, prom, NULL);
> +#else /* !CONFIG_PPC_OF ==> flattened device tree */
> +#ifdef DEBUG
> + printf("kernel:\n\r"
> + " entry addr = 0x%lx\n\r"
> + " flattened dt = 0x%lx\n\r",
> + (unsigned long)kernel_entry, &dt_blob_start);
> +#endif
> + edit_cmdline(&dt_blob_start);
> + platform_fixups(&dt_blob_start);
>
> + kernel_entry(&dt_blob_start, (void *)vmlinux.addr, NULL);
> +#endif
Let's avoid #ifdef's if we can... provide function pointers where it
matter setup by the board/OF init code maybe but not ifdef's. Afaik,
only WD actually _likes_ ifdef's :)
> +++ b/arch/powerpc/boot/mpc10x.c
We'll need some subdirs here or it will get messy quick...
> diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
Same comment as above
> +/* XXXX Get info from dt instead */
> +static struct {
> + int baud_base;
> + unsigned long com_port;
> + u16 iomem_reg_shift;
> +} rs_table[RS_TABLE_SIZE] = {
> + { BASE_BAUD, SANDPOINT_SERIAL_0, 0 },
> + { BASE_BAUD, SANDPOINT_SERIAL_1, 0 },
> +};
Well, your own comment says it all :) I think we might need an
equivalent of prom_parse.c in the bootloader
+
> +/* #ifndef CONFIG_PPC_OF XXXX */
> +
> +/* Definitions used by the flattened device tree */
> +#define OF_DT_HEADER 0xd00dfeed /* marker */
> +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
> +#define OF_DT_END_NODE 0x2 /* End node */
> +#define OF_DT_PROP 0x3 /* Property: name off, size,
> + * content */
> +#define OF_DT_NOP 0x4 /* nop */
> +#define OF_DT_END 0x9
> +
> +#define OF_DT_VERSION 0x10
.../... (flat DT definitions)
Can't we share the kernel definition here ? Maybe split the kenrel one
in two if necessary ? I don't like that sort of duplication...
> +unsigned long serial_init(int chan, void *ignored);
> +void serial_putc(unsigned long com_port, unsigned char c);
> +unsigned char serial_getc(unsigned long com_port);
> +int serial_tstc(unsigned long com_port);
Forgot to mention that earlier, but those should be uart_* imho (or even
16550_*) since we'll surely have different species of serial ports to
deal with and I don't like name mixup. Unless we consider that only ever
one of those serial files get built in a given zImage wrapper in which
case it makes some sense...
> +call_prom(const char *service, int nargs, int nret, ...)
> +{
> +
> + static struct {
> + char *service;
> + int ((*rtn)(int nargs, int nret, va_list args));
> + } services[] = {
> + { "exit", service_exit },
> + { "finddevice", service_finddevice },
> + { "getprop", service_getprop },
> + /* { "write", service_write }, */
> + };
> + va_list args;
> + int i, rc = 0;
> +
> + for (i=0; i<ARRAY_SIZE(services); i++)
> + if (!strcmp(service, services[i].service)) {
> + va_start(args, nret);
> + rc = services[i].rtn(nargs, nret, args);
> + va_end(args);
> + }
> +
> + return (nret > 0)? rc : 0;
> +}
I don't think call_prom is the right abstraction :) We have to decide
here, we have two choices:
- Either a given zImage wrapper can be booted from both a real OF and
have an embedded flat DT, in which case we need function pointers and I
think the right abstraction is for individual prom functions to have
their function pointer rathaer than "multiplex" through call_prom
- Or a given zImage wrapper is a single board thingy. That is it is
either the OF wrapper _or_ it can contain an embedded DT. Probably
easier that way and no need for funciton pointers nor mux at all... I
tend to think that might be the right way to go at this point...
Especially since as I wrote before, I'm tempted to think we should just
in that case build multiple zImage wrappers. The only thing there is
that if we go that route, I'd like the "OF" one to also be able to boot
with a flat DT passed on entry to it so it will be useable as a generic
zImage for firmwares that have a flat DT to pass to the kernel. The only
"issue" with that is it might be difficult to have console output unless
we do the putc function pointer thing I described earlier and have
several "uart" impleentations with differnet names and enough
device-tree parsing to be able to instanciate them (almost a copy of
kernel's legacy serial stuff). Another option if we want console output
is to add something to the DT header specifically for use by such early
boot code that specifies a function that can be called back for
displaying thing as long as a given memory range isn't overriden (the FW
itself)
Comments are welcome here, this is I think the most tricky point and
where we need to make a decision...
> diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
> index 6e67b5b..2feca55 100644
> --- a/arch/powerpc/kernel/legacy_serial.c
> +++ b/arch/powerpc/kernel/legacy_serial.c
> @@ -147,9 +147,11 @@ static int __init add_legacy_isa_port(st
> if (reg == NULL)
> return -1;
>
> +#if 0 /* XXXX */
> /* Verify it's an IO port, we don't support anything else */
> if (!(reg[0] & 0x00000001))
> return -1;
> +#endif
Gack ? Care to explain ?
> +obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
Hrmph.... (random noises)
> +/*
> + * Define all of the IRQ senses and polarities. Taken from the
> + * Sandpoint X3 User's manual.
> + */
> +static u_char sandpoint_openpic_initsenses[] __initdata = {
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 1: XXXX FILL?? */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 6: XXXX FILL?? */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 7: XXXX FILL?? */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 9: IDE (INT D) */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 10: */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 11: */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 12: */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 13: */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 14: */
> + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 15: */
> +};
Of course you already know that this has to go into the device-tree :)
> +/*
> + * Interrupt setup and service. Interrrupts on the Sandpoint come
> + * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
> + * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
> + * IDE is on EPIC 7 and 8.
> + */
> +static void __init
> +sandpoint_init_IRQ(void)
> +{
> + struct mpic *mpic;
> + phys_addr_t openpic_paddr = 0xfc000000 + /* XXXX */
> + MPC10X_EUMB_EPIC_OFFSET;
> +
> + /* This doesn't handle i2c, dma, i2o, or timer intrs right now XXXX */
> + mpic = mpic_alloc(openpic_paddr, MPIC_PRIMARY,
> + 16 /* XXXX otherwise num_sources used */ ,
> + NUM_8259_INTERRUPTS,
> + 0, /* was 16 */
> + NR_IRQS - 4 /* XXXX */,
> + sandpoint_openpic_initsenses,
> + sizeof(sandpoint_openpic_initsenses), " EPIC ");
> +
> + BUG_ON(mpic == NULL); /* XXXX */
> + mpic_assign_isu(mpic, 0, openpic_paddr + 0x10200);
> + mpic_init(mpic);
> + mpic_setup_cascade(NUM_8259_INTERRUPTS, i8259_irq_cascade, NULL);
> + i8259_init(0xfef00000, 0); /* pci iack addr */
> +}
It would be really nice if we could define properties to put in the
"mpic" node that defines the various attributes to pass to it and that
sort of thing so that we can have a generic "mpic_init_IRQ" that walks
all MPICs and instanciate & link them in cascade when necessary... Oh
well, food for thought, no high priority there.
> +/*
> + * Freescale Sandpoint interrupt routing.
> + */
> +static inline int
> +x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
> +{
> + static char pci_irq_table[][4] =
> + /*
> + * PCI IDSEL/INTPIN->INTLINE
> + * A B C D
> + */
> + {
> + { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
> + { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
> + { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
> + { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
> + { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
> + { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
> + };
> +
> + const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
> + return PCI_IRQ_TABLE_LOOKUP;
> +}
Of course you also know that the above has to go into the device-tree as
well :)
> +static void __init
> +sandpoint_setup_winbond_83553(struct pci_controller *hose)
> +{
> + int devfn;
> +
> + /*
> + * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
> + * We can't route the IDE interrupt to PCI INTC# or INTD# because those
> + * woule interfere with the PMC's INTC# and INTD# lines.
> + */
> + /*
> + * Winbond Fcn 0
> + */
> + devfn = PCI_DEVFN(11,0);
> +
> + early_write_config_byte(hose,
> + 0,
> + devfn,
> + 0x43, /* IDE Interrupt Routing Control */
> + 0xef);
> + early_write_config_word(hose,
> + 0,
> + devfn,
> + 0x44, /* PCI Interrupt Routing Control */
> + 0x0000);
> +
> + /* Want ISA memory cycles to be forwarded to PCI bus */
> + early_write_config_byte(hose,
> + 0,
> + devfn,
> + 0x48, /* ISA-to-PCI Addr Decoder Control */
> + 0xf0);
> +
> + /* Enable Port 92. */
> + early_write_config_byte(hose,
> + 0,
> + devfn,
> + 0x4e, /* AT System Control Register */
> + 0x06);
> + /*
> + * Winbond Fcn 1
> + */
> + devfn = PCI_DEVFN(11,1);
> +
> + /* Put IDE controller into native mode. */
> + early_write_config_byte(hose,
> + 0,
> + devfn,
> + 0x09, /* Programming interface Register */
> + 0x8f);
> +
> + /* Init IRQ routing, enable both ports, disable fast 16 */
> + early_write_config_dword(hose,
> + 0,
> + devfn,
> + 0x40, /* IDE Control/Status Register */
> + 0x00ff0011);
> + return;
> +}
How much of the above could/should be done by the wrapper since it does
config space access hacks ? My idea is that we might be able to remove
pretty much _everything_ from this sandpoint.c file ... My dream would
be to have a generic board support that matches a list of known boards
for which no special code is needed, only the device-tree (and possibly
the zImage wrapper).
The main things preventing us from doing that at the moment is that we
need to define enough standard nodes/properties to have the ability to
the setup interrupt controller tree entirely from it, and the PCI host
bridges as well. For the later, that means encoding enough of the bridge
type and config access method to allow having a generic device-tree
based piece of code that does what add_bridges() does in a generic way.
> +static int
> +x3_exclude_device(u_char bus, u_char devfn)
> +{
> + if ((bus == 0) && (PCI_SLOT(devfn) == 0))
> + return PCIBIOS_DEVICE_NOT_FOUND;
> + else
> + return PCIBIOS_SUCCESSFUL;
> +}
If we need to exclude devices in a generic way, we could define a
specific exclude list property... or use what I think has already been
defined by OF for indicating which slots should be probed :)
> +static int __init
> +add_bridge(struct device_node *dev)
> +{
> + int len;
> + struct pci_controller *hose;
> + int *bus_range;
> +
> + printk("Adding PCI host bridge %s\n", dev->full_name);
> +
> + bus_range = (int *) get_property(dev, "bus-range", &len);
> + if (bus_range == NULL || len < 2 * sizeof(int))
> + printk(KERN_WARNING "Can't get bus-range for %s, assume"
> + " bus 0\n", dev->full_name);
> +
> + hose = pcibios_alloc_controller();
> + if (hose == NULL)
> + return -ENOMEM;
> + hose->first_busno = bus_range ? bus_range[0] : 0;
> + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> + setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
> +
> + /* Interpret the "ranges" property */
> + /* This also maps the I/O region and sets isa_io/mem_base */
> + pci_process_bridge_OF_ranges(hose, dev, 1);
> +
> + return 0;
> +}
See above comments.... Looks ok but how many boards will end up having
very small variations of that same code and thus can we find a way to
make that totally generic...
> +u32 mag_dbg = 0;
> +
> +static void __init
> +sandpoint_setup_arch(void)
> +{
> + loops_per_jiffy = 100000000 / HZ;
> + isa_io_base = 0xfe000000;
> + isa_mem_base = 0x80000000;
> + pci_dram_offset = 0;
The isa stuff should probably be deduced from the device-tree, the
default LPJ too, probably not even useful anymore since we are using the
timebase nowadays.
> +#ifdef CONFIG_BLK_DEV_INITRD
> + if (initrd_start)
> + ROOT_DEV = Root_RAM0;
> + else
> +#endif
> +#ifdef CONFIG_ROOT_NFS
> + ROOT_DEV = Root_NFS;
> +#else
> + ROOT_DEV = Root_HDA1;
> +#endif
Same comment as above, this is fairly generic and we could even imagine
something like a linux,default-boot-device thing in the DT...
> +#if 1 /* XXXX NEW */
> + {
> + struct device_node *np;
> +
> + mag_dbg = 1;
> + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> + add_bridge(np);
> + mag_dbg = 0;
> +
> + ppc_md.pci_swizzle = common_swizzle;
> + ppc_md.pci_map_irq = x3_map_irq;
> + ppc_md.pci_exclude_device = x3_exclude_device; /* XXXX */
> + }
> +#endif
The problem of IRQ mapping & swizzling will be solved real soon
(hopefully early 2.6.18) so that we can completely rely on the
device-tree without needing device_node's for every PCI device. Only P2P
bridges that don't do standard swizzling (typically bridges soldered on
the motherboard) will require device nodes. I'm working on it :)
The idea is that the host bridge will need the standard interrupt-map &
interrupt-map-mask which will indicate the interrupt mapping for every
line of every slot/device in the standard way handled by OF (that
already works). And I'll add code that will be able to handle PCI
devices without a node by artificially building their "interrupts"
property based on the interrupt pin config space entry and walking up
the PCI tree, doing standard swizzling when encountering a P2P bridge
until we hit something with a device-node in which case we hook our
result to the interrupt-map of that device-node.
> + if (cpu_has_feature(CPU_FTR_SPEC7450))
> + /* 745x is different. We only want to pass along enable. */
> + _set_L2CR(L2CR_L2E);
> + else if (cpu_has_feature(CPU_FTR_L2CR))
> + /* All modules have 1MB of L2. We also assume that an
> + * L2 divisor of 3 will work.
> + */
> + _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
> + | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
Keeping in mind my idea of having as much generic code as possible,
whould we do the above in the boot wrapper or if not, should we provide
some DT entries indicating that L2CR should be reset and to which
values ?
> +#if 0
> + /* Untested right now. */
> + if (cpu_has_feature(CPU_FTR_L3CR)) {
> + /* Magic value. */
> + _set_L3CR(0x8f032000);
> + }
> +#endif
> +}
Same comment as above but for L3CR
.../...
> +/*
> + * Fix IDE interrupts.
> + */
> +static int __init
> +sandpoint_fix_winbond_83553(void)
> +{
> + /* Make some 8259 interrupt level sensitive */
> + outb(0xe0, 0x4d0);
> + outb(0xde, 0x4d1);
> +
> + return 0;
> +}
> +
> +arch_initcall(sandpoint_fix_winbond_83553);
> +
> +/*
> + * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
> + */
> +static int __init
> +sandpoint_setup_natl_87308(void)
> +{
> + u_char reg;
> +
> + /*
> + * Enable all the devices on the Super I/O chip.
> + */
> + SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
> + SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
> + SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
> + SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
> + SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
> + SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
> + SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
> + SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
> + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> + SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
> + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> +
> + /* Set up floppy in PS/2 mode */
> + outb(0x09, SIO_CONFIG_RA);
> + reg = inb(SIO_CONFIG_RD);
> + reg = (reg & 0x3F) | 0x40;
> + outb(reg, SIO_CONFIG_RD);
> + outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
> +
> + return 0;
> +}
Looks like zImage wrapper work to me... Unless we ever get booted by a
firmware that both provides a flat DT and doesn't do the above....
Ok, I'm not _ABSOLUTELY_ trying to remove the need for a myboar.c file
here ... but it might be worth doing something generic enough so that
it's either reduced to the strict minimum in many cases _or_ made
completely unnecessary if we can...
> +arch_initcall(sandpoint_setup_natl_87308);
> +
> +static int __init
> +sandpoint_request_io(void)
> +{
> + request_region(0x00,0x20,"dma1");
> + request_region(0x20,0x20,"pic1");
> + request_region(0x40,0x20,"timer");
> + request_region(0x80,0x10,"dma page reg");
> + request_region(0xa0,0x20,"pic2");
> + request_region(0xc0,0x20,"dma2");
> +
> + return 0;
> +}
The above has to go... not sure yet what is the best way but it's just a
pain... Could be made dependent on the OFDT too
> +arch_initcall(sandpoint_request_io);
> +#endif
> +
> +static void __init
> +sandpoint_map_io(void)
> +{
> + io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
> +}
To kill absolutely. What is it there for ? At the very least, make
io_block_mapping allocate virtual space as discussed earlier. I'd like
to keep BATs for RAM anyway
> +static void
> +sandpoint_restart(char *cmd)
> +{
> + local_irq_disable();
> +
> + /* Set exception prefix high - to the firmware */
> + _nmask_and_or_msr(0, MSR_IP);
> +
> + /* Reset system via Port 92 */
> + outb(0x00, 0x92);
> + outb(0x01, 0x92);
> +
> + for(;;); /* Spin until reset happens */
> +}
The above is fairly common. (Or variations of it). In the context of a
"generic" board, we could imagine having a list of known "reboot
methods" and have a DT node indicating which one to use...
> +static void
> +sandpoint_power_off(void)
> +{
> + local_irq_disable();
> + for(;;); /* No way to shut power off with software */
> + /* NOTREACHED */
> +}
The above is _VERY_ commmon :) probably worth just not having a callback
in ppc_md. at all...
> +static void
> +sandpoint_halt(void)
> +{
> + sandpoint_power_off();
> + /* NOTREACHED */
> +}
Same comment as before.
> +static void
> +sandpoint_show_cpuinfo(struct seq_file *m)
> +{
> + seq_printf(m, "vendor\t\t: Freescale\n");
> + seq_printf(m, "machine\t\t: Sandpoint\n");
> +}
Do we need that ? We could define standard DT properties that get
printed in cpuinfo and have that in setup-common.c ...
.../... (commented out IDE code)
This is a windbond ? Can't it just be probed/detected using normal PCI
probing ?
> +
> +/*
> + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
> + */
> +static __inline__ void
> +sandpoint_set_bat(void)
> +{
> + unsigned long bat3u, bat3l;
> +
> + __asm__ __volatile__(
> + " lis %0,0xf800\n \
> + ori %1,%0,0x002a\n \
> + ori %0,%0,0x0ffe\n \
> + mtspr 0x21e,%0\n \
> + mtspr 0x21f,%1\n \
> + isync\n \
> + sync "
> + : "=r" (bat3u), "=r" (bat3l));
> +}
WTF ?
> +TODC_ALLOC();
> +
> +static int __init
> +sandpoint_probe(void)
> +{
> + return 1;
> +}
WTF (bis) ? :)
> +define_machine(sandpoint) {
> + .name = "Sandpoint",
> + .probe = sandpoint_probe,
> + .setup_arch = sandpoint_setup_arch,
> + .setup_io_mappings = sandpoint_map_io,
> + .init_IRQ = sandpoint_init_IRQ,
> + .show_cpuinfo = sandpoint_show_cpuinfo,
> + .get_irq = mpic_get_irq,
> + .restart = sandpoint_restart,
> + .power_off = sandpoint_power_off,
> + .halt = sandpoint_halt,
> + .calibrate_decr = generic_calibrate_decr,
> + /*
> + .progress = udbg_progress,
> + */
> +};
So on the TODO list, replace as much as we can of the above with
generic_* equivalents until nothing remains :)
> diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> index 7dcdfcb..1badbec 100644
> --- a/arch/powerpc/sysdev/mpic.c
> +++ b/arch/powerpc/sysdev/mpic.c
> @@ -629,6 +629,13 @@ #endif /* CONFIG_SMP */
> mb();
> }
>
> +#ifdef CONFIG_MPIC_SERIAL
> + /* For serial interrupts & set clock ratio */
> + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1,
> + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1)
> + | (1<<27) | (0x7<<28));
> +#endif
This should not be an #ifdef.... this should be an MPIC init flag passed
when initializing it. (and if we do generic device-tree instanciation of
PIC's, we could define standard properties to put in the MPIC node to
enable those flags).
Keep up the good work ! :)
Cheers,
Ben.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 0:21 [HACK] add sandpoint + flattened dt support to arch/powerpc/boot Mark A. Greer
2006-05-18 5:32 ` Benjamin Herrenschmidt
@ 2006-05-18 13:47 ` Matthew McClintock
2006-05-19 0:37 ` Mark A. Greer
1 sibling, 1 reply; 17+ messages in thread
From: Matthew McClintock @ 2006-05-18 13:47 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> +void *
> +dt_find_prop_by_name(void *dt_blob, char *full_name, u32 *val_sizep)
Is there a reason you are not using of_get_flat_dt_prop() instead of
implementing your own version?
-Matthew
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 5:32 ` Benjamin Herrenschmidt
@ 2006-05-18 13:52 ` Matthew McClintock
2006-05-26 6:03 ` Benjamin Herrenschmidt
2006-05-23 0:58 ` Mark A. Greer
2006-06-14 3:37 ` Mark A. Greer
2 siblings, 1 reply; 17+ messages in thread
From: Matthew McClintock @ 2006-05-18 13:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
Do you have any comments about how you envision updating the "virtual"
mode image with information passed from the boot loader? I am asking
this from the standpoint of updating the "virtual" flat tree with
correct values, in order to boot from older firmware.
-Matthew
On Thu, 2006-05-18 at 15:32 +1000, Benjamin Herrenschmidt wrote:
> That is why, I think, what we should do is have rules for building
> separate zImage wrappers. The basic OF one (which exists in both real
> and virtual mode versions and that I'd like to make capable of also
> working if a flat device-tree is passed in), the zImage.sandpoint, the
> zImage.prep, and whatever...
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 13:47 ` Matthew McClintock
@ 2006-05-19 0:37 ` Mark A. Greer
2006-05-19 0:49 ` Michael Ellerman
0 siblings, 1 reply; 17+ messages in thread
From: Mark A. Greer @ 2006-05-19 0:37 UTC (permalink / raw)
To: Matthew McClintock; +Cc: linuxppc-dev
On Thu, May 18, 2006 at 08:47:01AM -0500, Matthew McClintock wrote:
> On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> > +void *
> > +dt_find_prop_by_name(void *dt_blob, char *full_name, u32 *val_sizep)
>
> Is there a reason you are not using of_get_flat_dt_prop() instead of
> implementing your own version?
Yes. One is in the kernel, one isn't. Or, are you asking why I didn't
just copy the kernel code? If so, I probably should have.
Hrm, we almost need a library of code shared between the kernel &
the bootwrapper. Sort of illegal but it would save duplicating code
like the flat dt code.
Comments?
Mark
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-19 0:37 ` Mark A. Greer
@ 2006-05-19 0:49 ` Michael Ellerman
2006-05-22 22:22 ` Tom Rini
0 siblings, 1 reply; 17+ messages in thread
From: Michael Ellerman @ 2006-05-19 0:49 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1132 bytes --]
On Thu, 2006-05-18 at 17:37 -0700, Mark A. Greer wrote:
> On Thu, May 18, 2006 at 08:47:01AM -0500, Matthew McClintock wrote:
> > On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> > > +void *
> > > +dt_find_prop_by_name(void *dt_blob, char *full_name, u32 *val_sizep)
> >
> > Is there a reason you are not using of_get_flat_dt_prop() instead of
> > implementing your own version?
>
> Yes. One is in the kernel, one isn't. Or, are you asking why I didn't
> just copy the kernel code? If so, I probably should have.
>
> Hrm, we almost need a library of code shared between the kernel &
> the bootwrapper. Sort of illegal but it would save duplicating code
> like the flat dt code.
>
> Comments?
Yeah we do. And it's not illegal IMHO as two of our boot wrappers
(prom_init and the iSeries one) are linked with the kernel anyway.
I think you should write it ;)
cheers
--
Michael Ellerman
IBM OzLabs
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-19 0:49 ` Michael Ellerman
@ 2006-05-22 22:22 ` Tom Rini
2006-06-05 20:41 ` Matthew McClintock
0 siblings, 1 reply; 17+ messages in thread
From: Tom Rini @ 2006-05-22 22:22 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
On Fri, May 19, 2006 at 10:49:25AM +1000, Michael Ellerman wrote:
> On Thu, 2006-05-18 at 17:37 -0700, Mark A. Greer wrote:
> > On Thu, May 18, 2006 at 08:47:01AM -0500, Matthew McClintock wrote:
> > > On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
> > > > +void *
> > > > +dt_find_prop_by_name(void *dt_blob, char *full_name, u32 *val_sizep)
> > >
> > > Is there a reason you are not using of_get_flat_dt_prop() instead of
> > > implementing your own version?
> >
> > Yes. One is in the kernel, one isn't. Or, are you asking why I didn't
> > just copy the kernel code? If so, I probably should have.
> >
> > Hrm, we almost need a library of code shared between the kernel &
> > the bootwrapper. Sort of illegal but it would save duplicating code
> > like the flat dt code.
> >
> > Comments?
>
> Yeah we do. And it's not illegal IMHO as two of our boot wrappers
> (prom_init and the iSeries one) are linked with the kernel anyway.
And on all architectures (practically) the zlib inflate code is shared
between kernel and bootstuff. So it's not unprecidented to do the ugly
define abstractions to let you easily share code as needed.
--
Tom Rini
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 5:32 ` Benjamin Herrenschmidt
2006-05-18 13:52 ` Matthew McClintock
@ 2006-05-23 0:58 ` Mark A. Greer
2006-05-23 1:13 ` Tom Rini
2006-07-19 20:02 ` Guennadi Liakhovetski
2006-06-14 3:37 ` Mark A. Greer
2 siblings, 2 replies; 17+ messages in thread
From: Mark A. Greer @ 2006-05-23 0:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
Thanks for your time, Ben. Sorry for taking so long to get back to you.
For the record, this patch was only a hack that I've done to get a sandpoint
up ASAP. I should have made it clear to not take Kconfig, etc. stuffs very
seriously. I was more worried about how we should fit flattened dt into the
bootwrapper.
I'm glad you did look at it so closely though and bring up a lot of good
questions. I'm not familiar with 64-bit platforms so all of my babbling
below is based on my 32-bit platform knowledge.
Mark
---
On Thu, May 18, 2006 at 03:32:55PM +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
<snip>
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 6729c98..de09eac 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -323,7 +323,10 @@ config PPC_ISERIES
> >
> > config EMBEDDED6xx
> > bool "Embedded 6xx/7xx/7xxx-based board"
> > - depends on PPC32 && BROKEN
> > + depends on PPC32
> > + select PPC_UDBG_16550
> > + select MPIC
> > + select MPIC_SERIAL
>
> Not totally related to your patch but I'm tempted to turn that into a
> "Generic 6xx/7xx/7xxx" rather than "embedded" if we manage to always
> avoid board specific code most of the time, but instead add necessary
> bits in the device-tree. We still need a per-board Kconfig option I
> think that will just select the necessary bits and pieces (and more than
> one can be selected at one time). Also, I think right now, the embedded
> stuff is +/- exclusive from the MULTIPLATFORM stuff, that must be fixed
> asap. We are all living in the same kernel now :)
OK.
> > +
> > +config MPIC_SERIAL
> > + depends on EMBEDDED6xx
> > + bool
> > + default n
>
> Not sure what the above is, I'll have a look further in the patch but I
> can already tell you that it should be your per-board
> CONFIG_PPC_SANDPOINT for example that "selects" the various bits you
> need, and thus the above should depend on it, not EMBEDDED6xx... In fact
> I'm wondering wether we should kill EMBEDDED6xx :) Unless it's purely a
> reference to arch/powerpc/platforms/embedded6xx/ as a storage place for
> board setup_xxx.c files which is useful for platforms that really don't
> need more than one or 2 files in there.
I have no attachment to "embedded" so I'm happy to see it
go...especially if I correctly understand what you're saying below.
> > +ifeq ($(CONFIG_EMBEDDED6xx),y)
> > +src-boot += prom_embedded.c ns16550.c dts/sandpoint.S \
> > + dt_utils.c sandpoint.c mpc10x.c
> > +else
> > +src-boot += prom.c
> > +endif
>
> Again, I think CONFIG_EMBEDDED6xx is the wrong approach. I'd like to
> avoid the word "embedded" altogether anyway :) Thing is, it would be
> good if ultimately, embedded boards firmware was capable of passing a
> device-tree. Thus, embedded a device-tree in the zImage wrapper is more
> like a "fallback" solution which has the side effect of creating machine
> specific zImage's.
>
> That is why, I think, what we should do is have rules for building
> separate zImage wrappers. The basic OF one (which exists in both real
> and virtual mode versions and that I'd like to make capable of also
> working if a flat device-tree is passed in), the zImage.sandpoint, the
> zImage.prep, and whatever...
>
> Thus enabling CONFIG_PPC_MYBOARD should trigger the build of the
> board-flavored version of the wrapper in addition to all the other ones
> for the other boards built as part of a given config.
>
> I know it's a bit difficult because the current boot Kbuild rules aren't
> really design for multiple targets but I think that's the way to go.
Okay, to make sure I understand, you're saying that you want to support a
.config file having several CONFIG_PPC_BOARD1, CONFIG_PPC_BOARD2,
CONFIG_PPC_BOARD3 defined at the same time. The resulting zImage would
run on all 3 boards, right?
I'd be happy with that. It should meet the requirements of both
the multiplatform and embedded folks. You could combine that with the
tool paulus talked about a couple weeks ago which would tack the
appropriate flattened device tree (fdt) onto the zImage after the fact.
http://ozlabs.org/pipermail/linuxppc-dev/2006-April/022435.html
We just need to come up with the tool and make the bootwrapper code
smart enough to know what dt to use (an OF dt, an fdt from a firmware, a
fdt tacked on by the tool (along with code to take bd stuff & put it
into the fdt?)).
All of the boards would likely have to be of the same "class".
Where "class" would be:
1) OF system
2) e300 core + PQIIPro (e.g., 83xx)
3) e500 core + PQIII (e.g., 85xx)
4) 6xx/7xx/74xx + mpc10x (e.g., sandpoint)
etc. Something like that, anyway--maybe there are only "OF" and
"non-OF'?
Basically, if its not OF, then its classified by its core + bridge.
So, first thing the zImage does is look for an attached ftb (attached by
paulus' tool). If its there, use it. If its not there, use either the
OFDT (for OF class) or expect a dt to be passed in from the firmware (for
all the other classes). That way you can easily override the dt in the field.
> .../...
>
> About the .dts file, we should look into "shipping" a pre-built one so
> that dtc is not required for building a kernel.
Okay, paulus' tool would allow that. We should also make it smart
enough to replace an attached dts (really dtb--'b' for 'binary') with
a new one.
> I think we already have
> a mecanism for providing "shipped" versions of files and having the
> option of rebuilding them from source (though I don't have the details
> in mind at the moment)
I don't know what you're referring to here.
> > diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
>
> .../.. io stuffs ...
>
> Well... io accessors in here can't harm, the question is more how they
> are used ;)
>
> > +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
> > +
> > +/* Indirect PCI config space access routines */
> > +static inline void
> > +pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > + int offset, u8 *val)
> > +{
> > + out_be32(cfg_addr,
> > + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > + *val = in_8((u8 *)(cfg_data + (offset & 3)));
> > + return;
> > +}
> > +
> > +static inline void
> > +pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > + int offset, u32 *val)
> > +{
> > + out_be32(cfg_addr,
> > + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > + *val = in_le32(cfg_data + (offset & 3));
> > + return;
> > +}
>
> That's more annoying... if we start having PCI config space access in
> the boot wrapper how far will it stop ? I'd rather keep that sort of
> stuff local to myboard.c file unless it's really worth sharing... Unless
> we end up with really common need for them in which case those should be
> in separate files, possibly in a separate dir (thinking about it, prep
> will probably need that too)
Sure. I was just grabbing code I needed and sticking it whereever to
get things to work. If mpc10x.c is the only one that uses those routines
then they should be in that file only.
> The main problem is how do we do printf kind of things from such a
> bootloader. That needs IO, thus uart drivers etc... possibly parsing
> from the device-tree etc... I'm tempted to just have a global
> "boot_puts" function pointer set by the board and/or OF code to use
> through the bootloader, maybe a shared uart.c file with various uart
> bits and keep the gory implementation details of mapping the uart and
> using those uart bits in the myboard.c file...
Okay.
Question: are we still going to allow cmdline editing in the
bootwrapper? If so, we also need to get uart input and munge the dtb
to put the new args back into the /chosen/bootargs field.
> > +#ifdef CONFIG_PPC_OF
> > typedef void (*kernel_entry_t)( unsigned long,
> > unsigned long,
> > void *,
> > void *);
> > +#else
> > +void platform_fixups(void *dt_blob);
> > +extern void *dt_blob_start;
> > +extern void *dt_blob_end;
> > +void edit_cmdline(void *dt_blob_start);
> > +typedef void (*kernel_entry_t)(void *dtb_addr, void *kernel_entry_paddr,
> > + void *must_be_null);
> > +#endif
>
> Why 2 different prototypes for kernel_entry ?
One for "OF", one for "non-OF" but I'll change it to
"typedef void (*kernel_entry_t)(void *addr, ...);"
to support both. Hrm, I may have another idea... Anyway, I'll do
something about the #ifdef.
> I think we need something like CONFIG_PPC_BOOT_HAS_BUILTIN_DT that
> enables various DT related stuff in a clean way and have a builtin_dt.h
> file with related prototypes & definitions.
If we have the tool mentioned above, we shouldn't need a CONFIG option.
Just check for a NULL ptr or something like that which indicates there's
no dtb attached.
> > #undef DEBUG
> > @@ -218,7 +227,7 @@ void start(unsigned long a1, unsigned lo
> > if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
> > exit();
> >
> > - printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
> > + printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
>
> Gratuituous uglyfication :)
Again, I was just hacking stuff...
<snip>
> >
> > /* Eventually gunzip the kernel */
> > @@ -299,6 +311,7 @@ #endif
> > flush_cache((void *)vmlinux.addr, vmlinux.size);
> >
> > kernel_entry = (kernel_entry_t)vmlinux.addr;
> > +#ifdef CONFIG_PPC_OF
> > #ifdef DEBUG
> > printf( "kernel:\n\r"
> > " entry addr = 0x%lx\n\r"
> > @@ -311,9 +324,20 @@ #ifdef DEBUG
> > #endif
>
> > kernel_entry(a1, a2, prom, NULL);
> > +#else /* !CONFIG_PPC_OF ==> flattened device tree */
> > +#ifdef DEBUG
> > + printf("kernel:\n\r"
> > + " entry addr = 0x%lx\n\r"
> > + " flattened dt = 0x%lx\n\r",
> > + (unsigned long)kernel_entry, &dt_blob_start);
> > +#endif
> > + edit_cmdline(&dt_blob_start);
> > + platform_fixups(&dt_blob_start);
> >
> > + kernel_entry(&dt_blob_start, (void *)vmlinux.addr, NULL);
> > +#endif
>
> Let's avoid #ifdef's if we can... provide function pointers where it
> matter setup by the board/OF init code maybe but not ifdef's. Afaik,
> only WD actually _likes_ ifdef's :)
I'll fix it up.
> > +++ b/arch/powerpc/boot/mpc10x.c
>
> We'll need some subdirs here or it will get messy quick...
Yep.
> > diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
>
> Same comment as above
>
> > +/* XXXX Get info from dt instead */
> > +static struct {
> > + int baud_base;
> > + unsigned long com_port;
> > + u16 iomem_reg_shift;
> > +} rs_table[RS_TABLE_SIZE] = {
> > + { BASE_BAUD, SANDPOINT_SERIAL_0, 0 },
> > + { BASE_BAUD, SANDPOINT_SERIAL_1, 0 },
> > +};
>
> Well, your own comment says it all :) I think we might need an
> equivalent of prom_parse.c in the bootloader
Yes, this was just a hack to get the sandpoint going.
> +
> > +/* #ifndef CONFIG_PPC_OF XXXX */
> > +
> > +/* Definitions used by the flattened device tree */
> > +#define OF_DT_HEADER 0xd00dfeed /* marker */
> > +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
> > +#define OF_DT_END_NODE 0x2 /* End node */
> > +#define OF_DT_PROP 0x3 /* Property: name off, size,
> > + * content */
> > +#define OF_DT_NOP 0x4 /* nop */
> > +#define OF_DT_END 0x9
> > +
> > +#define OF_DT_VERSION 0x10
>
> .../... (flat DT definitions)
>
> Can't we share the kernel definition here ? Maybe split the kenrel one
> in two if necessary ? I don't like that sort of duplication...
I hope so. I'm hoping we can make a special dir somewhere that has the
definitions of stuff shared between the bootwrapper & the kernel.
How about arch/powerpc/shared? I dunno, something sensible.
> > +unsigned long serial_init(int chan, void *ignored);
> > +void serial_putc(unsigned long com_port, unsigned char c);
> > +unsigned char serial_getc(unsigned long com_port);
> > +int serial_tstc(unsigned long com_port);
>
> Forgot to mention that earlier, but those should be uart_* imho (or even
> 16550_*) since we'll surely have different species of serial ports to
> deal with and I don't like name mixup. Unless we consider that only ever
> one of those serial files get built in a given zImage wrapper in which
> case it makes some sense...
Okay.
> > +call_prom(const char *service, int nargs, int nret, ...)
> > +{
> > +
> > + static struct {
> > + char *service;
> > + int ((*rtn)(int nargs, int nret, va_list args));
> > + } services[] = {
> > + { "exit", service_exit },
> > + { "finddevice", service_finddevice },
> > + { "getprop", service_getprop },
> > + /* { "write", service_write }, */
> > + };
> > + va_list args;
> > + int i, rc = 0;
> > +
> > + for (i=0; i<ARRAY_SIZE(services); i++)
> > + if (!strcmp(service, services[i].service)) {
> > + va_start(args, nret);
> > + rc = services[i].rtn(nargs, nret, args);
> > + va_end(args);
> > + }
> > +
> > + return (nret > 0)? rc : 0;
> > +}
>
> I don't think call_prom is the right abstraction :) We have to decide
> here, we have two choices:
>
> - Either a given zImage wrapper can be booted from both a real OF and
> have an embedded flat DT, in which case we need function pointers and I
> think the right abstraction is for individual prom functions to have
> their function pointer rathaer than "multiplex" through call_prom
>
> - Or a given zImage wrapper is a single board thingy. That is it is
> either the OF wrapper _or_ it can contain an embedded DT. Probably
> easier that way and no need for funciton pointers nor mux at all... I
> tend to think that might be the right way to go at this point...
> Especially since as I wrote before, I'm tempted to think we should just
> in that case build multiple zImage wrappers. The only thing there is
> that if we go that route, I'd like the "OF" one to also be able to boot
> with a flat DT passed on entry to it so it will be useable as a generic
> zImage for firmwares that have a flat DT to pass to the kernel. The only
> "issue" with that is it might be difficult to have console output unless
> we do the putc function pointer thing I described earlier and have
> several "uart" impleentations with differnet names and enough
> device-tree parsing to be able to instanciate them (almost a copy of
> kernel's legacy serial stuff). Another option if we want console output
> is to add something to the DT header specifically for use by such early
> boot code that specifies a function that can be called back for
> displaying thing as long as a given memory range isn't overriden (the FW
> itself)
>
> Comments are welcome here, this is I think the most tricky point and
> where we need to make a decision...
I'm very happy to not use the 'call_prom' abstraction. :)
I guess I have the first one in mind. You have a zImage that runs on
1 to n different platforms. The zImage has to determine which DT to use
(OF DT, fdt from firmware, fdt attached by tool) and pick it apart to
find the I/O resources and serial driver to use. The CONFIG_<BOARD>'s
that are defined would determine the drivers that get built in to the zImage.
> > diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
> > index 6e67b5b..2feca55 100644
> > --- a/arch/powerpc/kernel/legacy_serial.c
> > +++ b/arch/powerpc/kernel/legacy_serial.c
> > @@ -147,9 +147,11 @@ static int __init add_legacy_isa_port(st
> > if (reg == NULL)
> > return -1;
> >
> > +#if 0 /* XXXX */
> > /* Verify it's an IO port, we don't support anything else */
> > if (!(reg[0] & 0x00000001))
> > return -1;
> > +#endif
>
> Gack ? Care to explain ?
This 'if' always executed and threw me into the weeds. I didn't get
back to really figuring it out. This was a hack to get going.
> > +obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
>
> Hrmph.... (random noises)
? No, I needed that to get the build to go into platforms/embedded6xx.
Since platforms/embedded6xx was already there, I assumed that was where
I was to put things like the sandpoint. If/when we get rid of
"embedded", I'll move it to whereever it should go then.
> > +/*
> > + * Define all of the IRQ senses and polarities. Taken from the
> > + * Sandpoint X3 User's manual.
> > + */
> > +static u_char sandpoint_openpic_initsenses[] __initdata = {
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 1: XXXX FILL?? */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 6: XXXX FILL?? */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 7: XXXX FILL?? */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 9: IDE (INT D) */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 10: */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 11: */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 12: */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 13: */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 14: */
> > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 15: */
> > +};
>
> Of course you already know that this has to go into the device-tree :)
Yeah, I guess it should. I'll have to figure out how to do that.
> > +/*
> > + * Interrupt setup and service. Interrrupts on the Sandpoint come
> > + * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
> > + * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
> > + * IDE is on EPIC 7 and 8.
> > + */
> > +static void __init
> > +sandpoint_init_IRQ(void)
> > +{
> > + struct mpic *mpic;
> > + phys_addr_t openpic_paddr = 0xfc000000 + /* XXXX */
> > + MPC10X_EUMB_EPIC_OFFSET;
> > +
> > + /* This doesn't handle i2c, dma, i2o, or timer intrs right now XXXX */
> > + mpic = mpic_alloc(openpic_paddr, MPIC_PRIMARY,
> > + 16 /* XXXX otherwise num_sources used */ ,
> > + NUM_8259_INTERRUPTS,
> > + 0, /* was 16 */
> > + NR_IRQS - 4 /* XXXX */,
> > + sandpoint_openpic_initsenses,
> > + sizeof(sandpoint_openpic_initsenses), " EPIC ");
> > +
> > + BUG_ON(mpic == NULL); /* XXXX */
> > + mpic_assign_isu(mpic, 0, openpic_paddr + 0x10200);
> > + mpic_init(mpic);
> > + mpic_setup_cascade(NUM_8259_INTERRUPTS, i8259_irq_cascade, NULL);
> > + i8259_init(0xfef00000, 0); /* pci iack addr */
> > +}
>
> It would be really nice if we could define properties to put in the
> "mpic" node that defines the various attributes to pass to it and that
> sort of thing so that we can have a generic "mpic_init_IRQ" that walks
> all MPICs and instanciate & link them in cascade when necessary... Oh
> well, food for thought, no high priority there.
That would be great to have!
> > +/*
> > + * Freescale Sandpoint interrupt routing.
> > + */
> > +static inline int
> > +x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
> > +{
> > + static char pci_irq_table[][4] =
> > + /*
> > + * PCI IDSEL/INTPIN->INTLINE
> > + * A B C D
> > + */
> > + {
> > + { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
> > + { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
> > + { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
> > + { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
> > + { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
> > + { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
> > + };
> > +
> > + const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
> > + return PCI_IRQ_TABLE_LOOKUP;
> > +}
>
> Of course you also know that the above has to go into the device-tree as
> well :)
Okay... :)
> > +static void __init
> > +sandpoint_setup_winbond_83553(struct pci_controller *hose)
> > +{
> > + int devfn;
> > +
> > + /*
> > + * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
> > + * We can't route the IDE interrupt to PCI INTC# or INTD# because those
> > + * woule interfere with the PMC's INTC# and INTD# lines.
> > + */
> > + /*
> > + * Winbond Fcn 0
> > + */
> > + devfn = PCI_DEVFN(11,0);
> > +
> > + early_write_config_byte(hose,
> > + 0,
> > + devfn,
> > + 0x43, /* IDE Interrupt Routing Control */
> > + 0xef);
> > + early_write_config_word(hose,
> > + 0,
> > + devfn,
> > + 0x44, /* PCI Interrupt Routing Control */
> > + 0x0000);
> > +
> > + /* Want ISA memory cycles to be forwarded to PCI bus */
> > + early_write_config_byte(hose,
> > + 0,
> > + devfn,
> > + 0x48, /* ISA-to-PCI Addr Decoder Control */
> > + 0xf0);
> > +
> > + /* Enable Port 92. */
> > + early_write_config_byte(hose,
> > + 0,
> > + devfn,
> > + 0x4e, /* AT System Control Register */
> > + 0x06);
> > + /*
> > + * Winbond Fcn 1
> > + */
> > + devfn = PCI_DEVFN(11,1);
> > +
> > + /* Put IDE controller into native mode. */
> > + early_write_config_byte(hose,
> > + 0,
> > + devfn,
> > + 0x09, /* Programming interface Register */
> > + 0x8f);
> > +
> > + /* Init IRQ routing, enable both ports, disable fast 16 */
> > + early_write_config_dword(hose,
> > + 0,
> > + devfn,
> > + 0x40, /* IDE Control/Status Register */
> > + 0x00ff0011);
> > + return;
> > +}
>
> How much of the above could/should be done by the wrapper since it does
> config space access hacks ? My idea is that we might be able to remove
> pretty much _everything_ from this sandpoint.c file ... My dream would
> be to have a generic board support that matches a list of known boards
> for which no special code is needed, only the device-tree (and possibly
> the zImage wrapper).
That's a good dream. :)
> The main things preventing us from doing that at the moment is that we
> need to define enough standard nodes/properties to have the ability to
> the setup interrupt controller tree entirely from it, and the PCI host
> bridges as well. For the later, that means encoding enough of the bridge
> type and config access method to allow having a generic device-tree
> based piece of code that does what add_bridges() does in a generic way.
Yep.
> > +static int
> > +x3_exclude_device(u_char bus, u_char devfn)
> > +{
> > + if ((bus == 0) && (PCI_SLOT(devfn) == 0))
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + else
> > + return PCIBIOS_SUCCESSFUL;
> > +}
>
> If we need to exclude devices in a generic way, we could define a
> specific exclude list property... or use what I think has already been
> defined by OF for indicating which slots should be probed :)
I'll try to do it through pci quirks, if I can. If not, then I agree.
> > +static int __init
> > +add_bridge(struct device_node *dev)
> > +{
> > + int len;
> > + struct pci_controller *hose;
> > + int *bus_range;
> > +
> > + printk("Adding PCI host bridge %s\n", dev->full_name);
> > +
> > + bus_range = (int *) get_property(dev, "bus-range", &len);
> > + if (bus_range == NULL || len < 2 * sizeof(int))
> > + printk(KERN_WARNING "Can't get bus-range for %s, assume"
> > + " bus 0\n", dev->full_name);
> > +
> > + hose = pcibios_alloc_controller();
> > + if (hose == NULL)
> > + return -ENOMEM;
> > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > + setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
> > +
> > + /* Interpret the "ranges" property */
> > + /* This also maps the I/O region and sets isa_io/mem_base */
> > + pci_process_bridge_OF_ranges(hose, dev, 1);
> > +
> > + return 0;
> > +}
>
> See above comments.... Looks ok but how many boards will end up having
> very small variations of that same code and thus can we find a way to
> make that totally generic...
Many...
> > +u32 mag_dbg = 0;
> > +
> > +static void __init
> > +sandpoint_setup_arch(void)
> > +{
> > + loops_per_jiffy = 100000000 / HZ;
> > + isa_io_base = 0xfe000000;
> > + isa_mem_base = 0x80000000;
> > + pci_dram_offset = 0;
>
> The isa stuff should probably be deduced from the device-tree, the
> default LPJ too, probably not even useful anymore since we are using the
> timebase nowadays.
Okay.
> > +#ifdef CONFIG_BLK_DEV_INITRD
> > + if (initrd_start)
> > + ROOT_DEV = Root_RAM0;
> > + else
> > +#endif
> > +#ifdef CONFIG_ROOT_NFS
> > + ROOT_DEV = Root_NFS;
> > +#else
> > + ROOT_DEV = Root_HDA1;
> > +#endif
>
> Same comment as above, this is fairly generic and we could even imagine
> something like a linux,default-boot-device thing in the DT...
OK.
> > +#if 1 /* XXXX NEW */
> > + {
> > + struct device_node *np;
> > +
> > + mag_dbg = 1;
> > + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> > + add_bridge(np);
> > + mag_dbg = 0;
> > +
> > + ppc_md.pci_swizzle = common_swizzle;
> > + ppc_md.pci_map_irq = x3_map_irq;
> > + ppc_md.pci_exclude_device = x3_exclude_device; /* XXXX */
> > + }
> > +#endif
>
> The problem of IRQ mapping & swizzling will be solved real soon
> (hopefully early 2.6.18) so that we can completely rely on the
> device-tree without needing device_node's for every PCI device. Only P2P
> bridges that don't do standard swizzling (typically bridges soldered on
> the motherboard) will require device nodes. I'm working on it :)
>
> The idea is that the host bridge will need the standard interrupt-map &
> interrupt-map-mask which will indicate the interrupt mapping for every
> line of every slot/device in the standard way handled by OF (that
> already works). And I'll add code that will be able to handle PCI
> devices without a node by artificially building their "interrupts"
> property based on the interrupt pin config space entry and walking up
> the PCI tree, doing standard swizzling when encountering a P2P bridge
> until we hit something with a device-node in which case we hook our
> result to the interrupt-map of that device-node.
Cool. I'll keep an eye out for that.
> > + if (cpu_has_feature(CPU_FTR_SPEC7450))
> > + /* 745x is different. We only want to pass along enable. */
> > + _set_L2CR(L2CR_L2E);
> > + else if (cpu_has_feature(CPU_FTR_L2CR))
> > + /* All modules have 1MB of L2. We also assume that an
> > + * L2 divisor of 3 will work.
> > + */
> > + _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
> > + | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
>
> Keeping in mind my idea of having as much generic code as possible,
> whould we do the above in the boot wrapper or if not, should we provide
> some DT entries indicating that L2CR should be reset and to which
> values ?
I vote for a DT entry.
> > +#if 0
> > + /* Untested right now. */
> > + if (cpu_has_feature(CPU_FTR_L3CR)) {
> > + /* Magic value. */
> > + _set_L3CR(0x8f032000);
> > + }
> > +#endif
> > +}
>
> Same comment as above but for L3CR
DT entry. :)
> .../...
>
> > +/*
> > + * Fix IDE interrupts.
> > + */
> > +static int __init
> > +sandpoint_fix_winbond_83553(void)
> > +{
> > + /* Make some 8259 interrupt level sensitive */
> > + outb(0xe0, 0x4d0);
> > + outb(0xde, 0x4d1);
> > +
> > + return 0;
> > +}
> > +
> > +arch_initcall(sandpoint_fix_winbond_83553);
> > +
> > +/*
> > + * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
> > + */
> > +static int __init
> > +sandpoint_setup_natl_87308(void)
> > +{
> > + u_char reg;
> > +
> > + /*
> > + * Enable all the devices on the Super I/O chip.
> > + */
> > + SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
> > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
> > + SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
> > + SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
> > + SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
> > + SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
> > + SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
> > + SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
> > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > + SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
> > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > +
> > + /* Set up floppy in PS/2 mode */
> > + outb(0x09, SIO_CONFIG_RA);
> > + reg = inb(SIO_CONFIG_RD);
> > + reg = (reg & 0x3F) | 0x40;
> > + outb(reg, SIO_CONFIG_RD);
> > + outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
> > +
> > + return 0;
> > +}
>
> Looks like zImage wrapper work to me... Unless we ever get booted by a
> firmware that both provides a flat DT and doesn't do the above....
>
> Ok, I'm not _ABSOLUTELY_ trying to remove the need for a myboar.c file
> here ... but it might be worth doing something generic enough so that
> it's either reduced to the strict minimum in many cases _or_ made
> completely unnecessary if we can...
OK
> > +arch_initcall(sandpoint_setup_natl_87308);
> > +
> > +static int __init
> > +sandpoint_request_io(void)
> > +{
> > + request_region(0x00,0x20,"dma1");
> > + request_region(0x20,0x20,"pic1");
> > + request_region(0x40,0x20,"timer");
> > + request_region(0x80,0x10,"dma page reg");
> > + request_region(0xa0,0x20,"pic2");
> > + request_region(0xc0,0x20,"dma2");
> > +
> > + return 0;
> > +}
>
> The above has to go... not sure yet what is the best way but it's just a
> pain... Could be made dependent on the OFDT too
OK
> > +arch_initcall(sandpoint_request_io);
> > +#endif
> > +
> > +static void __init
> > +sandpoint_map_io(void)
> > +{
> > + io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
> > +}
>
> To kill absolutely. What is it there for ? At the very least, make
> io_block_mapping allocate virtual space as discussed earlier. I'd like
> to keep BATs for RAM anyway
It'll go away eventually.
> > +static void
> > +sandpoint_restart(char *cmd)
> > +{
> > + local_irq_disable();
> > +
> > + /* Set exception prefix high - to the firmware */
> > + _nmask_and_or_msr(0, MSR_IP);
> > +
> > + /* Reset system via Port 92 */
> > + outb(0x00, 0x92);
> > + outb(0x01, 0x92);
> > +
> > + for(;;); /* Spin until reset happens */
> > +}
>
> The above is fairly common. (Or variations of it). In the context of a
> "generic" board, we could imagine having a list of known "reboot
> methods" and have a DT node indicating which one to use...
Yep.
> > +static void
> > +sandpoint_power_off(void)
> > +{
> > + local_irq_disable();
> > + for(;;); /* No way to shut power off with software */
> > + /* NOTREACHED */
> > +}
>
> The above is _VERY_ commmon :) probably worth just not having a callback
> in ppc_md. at all...
>
> > +static void
> > +sandpoint_halt(void)
> > +{
> > + sandpoint_power_off();
> > + /* NOTREACHED */
> > +}
>
> Same comment as before.
I do see a couple in arch/ppc/platforms that do something different so
how about keeping ppc_md.power_off/_halt but making the above the default
(with only 1 implementation) which can be changed by board code?
> > +static void
> > +sandpoint_show_cpuinfo(struct seq_file *m)
> > +{
> > + seq_printf(m, "vendor\t\t: Freescale\n");
> > + seq_printf(m, "machine\t\t: Sandpoint\n");
> > +}
>
> Do we need that ? We could define standard DT properties that get
> printed in cpuinfo and have that in setup-common.c ...
That would be better.
> .../... (commented out IDE code)
>
> This is a windbond ? Can't it just be probed/detected using normal PCI
> probing ?
I have to revisit all of the IDE stuff in that file and figure out
what's really needed (if any). That's why I have it all '#if 0' right
now. I will get to it eventually.
> > +
> > +/*
> > + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
> > + */
> > +static __inline__ void
> > +sandpoint_set_bat(void)
> > +{
> > + unsigned long bat3u, bat3l;
> > +
> > + __asm__ __volatile__(
> > + " lis %0,0xf800\n \
> > + ori %1,%0,0x002a\n \
> > + ori %0,%0,0x0ffe\n \
> > + mtspr 0x21e,%0\n \
> > + mtspr 0x21f,%1\n \
> > + isync\n \
> > + sync "
> > + : "=r" (bat3u), "=r" (bat3l));
> > +}
>
> WTF ?
It'll disappear. The sandpoint.c is copied from arch/ppc and hacked.
Its pretty old so there's lots of code that can probably be weeded out.
> > +TODC_ALLOC();
> > +
> > +static int __init
> > +sandpoint_probe(void)
> > +{
> > + return 1;
> > +}
>
> WTF (bis) ? :)
bis?
Its just a hack to get it going.
> > +define_machine(sandpoint) {
> > + .name = "Sandpoint",
> > + .probe = sandpoint_probe,
> > + .setup_arch = sandpoint_setup_arch,
> > + .setup_io_mappings = sandpoint_map_io,
> > + .init_IRQ = sandpoint_init_IRQ,
> > + .show_cpuinfo = sandpoint_show_cpuinfo,
> > + .get_irq = mpic_get_irq,
> > + .restart = sandpoint_restart,
> > + .power_off = sandpoint_power_off,
> > + .halt = sandpoint_halt,
> > + .calibrate_decr = generic_calibrate_decr,
> > + /*
> > + .progress = udbg_progress,
> > + */
> > +};
>
> So on the TODO list, replace as much as we can of the above with
> generic_* equivalents until nothing remains :)
Yep, that's the goal.
> > diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> > index 7dcdfcb..1badbec 100644
> > --- a/arch/powerpc/sysdev/mpic.c
> > +++ b/arch/powerpc/sysdev/mpic.c
> > @@ -629,6 +629,13 @@ #endif /* CONFIG_SMP */
> > mb();
> > }
> >
> > +#ifdef CONFIG_MPIC_SERIAL
> > + /* For serial interrupts & set clock ratio */
> > + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1,
> > + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1)
> > + | (1<<27) | (0x7<<28));
> > +#endif
>
> This should not be an #ifdef.... this should be an MPIC init flag passed
> when initializing it. (and if we do generic device-tree instanciation of
> PIC's, we could define standard properties to put in the MPIC node to
> enable those flags).
Okay, I'll move it into the dt.
> Keep up the good work ! :)
Heh.
> Cheers,
> Ben.
Thanks for the comments.
Mark
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-23 0:58 ` Mark A. Greer
@ 2006-05-23 1:13 ` Tom Rini
2006-07-19 20:02 ` Guennadi Liakhovetski
1 sibling, 0 replies; 17+ messages in thread
From: Tom Rini @ 2006-05-23 1:13 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
On Mon, May 22, 2006 at 05:58:46PM -0700, Mark A. Greer wrote:
[snip]
> All of the boards would likely have to be of the same "class".
> Where "class" would be:
> 1) OF system
> 2) e300 core + PQIIPro (e.g., 83xx)
> 3) e500 core + PQIII (e.g., 85xx)
> 4) 6xx/7xx/74xx + mpc10x (e.g., sandpoint)
> etc. Something like that, anyway--maybe there are only "OF" and
> "non-OF'?
That's more limiting than we strictly need, I think. So long as we keep
the instructions that can't/aren't run-time nop'd over, or already done
in a way they don't run on the wrong core (ie ARCH=ppc and sandpoint
running fine on both 745x and 750), it should be (guessing a bit on the
64bit cpus):
1) 6xx/7xx/74xx/8xxx
2) 4xx
3) 8xx
4) 970
5) cell
6) etc
Or so. IOW, so long as we can either nop out, or possibly better yet,
have the compiler get things right (use Makefile/Kconfig magic to get
the LCD -mcpu=/-mtune= option so we run right). Things like PPC_BOARD1
and PPC_BOARD2 would then select PQIII core stuff, MPC10X core stuff,
TSI108 core stuff, GT64x60 core stuff, and so on. And maybe 8xxx has to
be split into BookE/non-BookE, at least to start with, for head*.S
reasons.
As a reminder to all, this also lets us say that if we just pick
PPC_8548CDS then only the stuff required for the 8548CDS would be
compiled into the kernel.
--
Tom Rini
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 13:52 ` Matthew McClintock
@ 2006-05-26 6:03 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-05-26 6:03 UTC (permalink / raw)
To: Matthew McClintock; +Cc: linuxppc-dev
On Thu, 2006-05-18 at 08:52 -0500, Matthew McClintock wrote:
> Do you have any comments about how you envision updating the "virtual"
> mode image with information passed from the boot loader? I am asking
> this from the standpoint of updating the "virtual" flat tree with
> correct values, in order to boot from older firmware.
Well, that's what need to be discussed... I'll read Mark replies and
others and will try to come up with my own comments/suggestions asap.
I'm a bit overflowed with stuff at the moment though.
Ben.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-22 22:22 ` Tom Rini
@ 2006-06-05 20:41 ` Matthew McClintock
2006-06-05 21:04 ` Tom Rini
0 siblings, 1 reply; 17+ messages in thread
From: Matthew McClintock @ 2006-06-05 20:41 UTC (permalink / raw)
To: Tom Rini; +Cc: linuxppc-dev
On Mon, 2006-05-22 at 15:22 -0700, Tom Rini wrote:
> And on all architectures (practically) the zlib inflate code is shared
> between kernel and bootstuff. So it's not unprecidented to do the
> ugly
> define abstractions to let you easily share code as needed.
Could you point me at the code you are referring too?
Thanks,
Matthew
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-06-05 20:41 ` Matthew McClintock
@ 2006-06-05 21:04 ` Tom Rini
0 siblings, 0 replies; 17+ messages in thread
From: Tom Rini @ 2006-06-05 21:04 UTC (permalink / raw)
To: Matthew McClintock; +Cc: linuxppc-dev
On Mon, Jun 05, 2006 at 03:41:53PM -0500, Matthew McClintock wrote:
> On Mon, 2006-05-22 at 15:22 -0700, Tom Rini wrote:
> > And on all architectures (practically) the zlib inflate code is shared
> > between kernel and bootstuff. So it's not unprecidented to do the
> > ugly
> > define abstractions to let you easily share code as needed.
>
> Could you point me at the code you are referring too?
arch/powerpc/boot/Makefile
arch/ppc/boot/lib/Makefile
arch/xtensa/boot/lib/Makefile
And I could have sworn there were other arches (maybe in patches in
-mm?) that switched from lib/inflate.c to lib/zlib_inflate/
--
Tom Rini
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-18 5:32 ` Benjamin Herrenschmidt
2006-05-18 13:52 ` Matthew McClintock
2006-05-23 0:58 ` Mark A. Greer
@ 2006-06-14 3:37 ` Mark A. Greer
2 siblings, 0 replies; 17+ messages in thread
From: Mark A. Greer @ 2006-06-14 3:37 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
Ben,
[The patch below is not a patch submission, its just for comment.]
I reorged the boot stuff a bit to try to make it easier for all the different
worlds to live together. Basically, there are 4 types of operations,
platform (platform_ops), firmware (fw_ops), device tree (dt_ops), and
console (console_ops). ops.h defines them all.
I'm sure some ops may need to move and some may need to be added as more
platforms are added into boot dir but its a start. I also incorporated
Michal Ostrowski's patch that puts the zImage cmdline in a separate section
(although I changed the name to zimage_cmdline to make it clear where
the cmdline came from). I also changed 'prom.c' to 'of.c' because it
seemed more accurate.
For the sandpoint, I used sandpoint_platform_ops, dink_fw_ops,
fdt_dt_ops (flat dev tree), and ns16550_console_ops (which uses some
more generic serial ops). The maple only uses the various of_*_ops
which are all in of.c.
Some of the fdt.c code can probably be merged with code that's in
kernel/prom.c or prom_parse.c but I'm not going to worry about that
for now.
The latest powerpc.git tree doesn't seem to build for me (32 bit) so
I haven't tested in that tree but in an older tree, I can build & boot
sandpoint and maple zImages.
I know there was a whole lot more I wanted to say but I'm tired and I
can't think right now.
Anyway, I would appreciate it you and others who care would take a
look and comment. I would like to get the sandpoint into the powerpc
tree sometime soon so I hope its not too far off.
Thanks,
Mark
--
arch/powerpc/boot/prom.c | 165 ----------
arch/powerpc/boot/prom.h | 34 --
b/arch/powerpc/boot/Makefile | 9
b/arch/powerpc/boot/dink.c | 57 +++
b/arch/powerpc/boot/dts/sandpoint.dts | 206 +++++++++++++
b/arch/powerpc/boot/fdt.c | 525 ++++++++++++++++++++++++++++++++++
b/arch/powerpc/boot/io.h | 160 ++++++++++
b/arch/powerpc/boot/main.c | 177 +++++------
b/arch/powerpc/boot/mpc10x.c | 87 +++++
b/arch/powerpc/boot/ns16550.c | 125 ++++++++
b/arch/powerpc/boot/of.c | 301 +++++++++++++++++++
b/arch/powerpc/boot/ops.h | 117 +++++++
b/arch/powerpc/boot/sandpoint.c | 148 +++++++++
b/arch/powerpc/boot/serial.c | 90 +++++
b/arch/powerpc/boot/stdio.c | 4
b/arch/powerpc/boot/types.h | 29 +
b/arch/powerpc/boot/util.S | 101 ++++++
17 files changed, 2041 insertions(+), 294 deletions(-)
--
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 840ae59..1e67d96 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,8 +36,15 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
-src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
+src-boot := crt0.S string.S stdio.c main.c div64.S
src-boot += $(zlib)
+ifneq ($(CONFIG_EMBEDDED6xx),y)
+src-boot += of.c
+endif
+ifeq ($(CONFIG_SANDPOINT),y)
+src-boot += sandpoint.c mpc10x.c dink.c fdt.c serial.c ns16550.c \
+ util.S dts/sandpoint.S
+endif
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
diff --git a/arch/powerpc/boot/dink.c b/arch/powerpc/boot/dink.c
new file mode 100644
index 0000000..b01efbc
--- /dev/null
+++ b/arch/powerpc/boot/dink.c
@@ -0,0 +1,57 @@
+/*
+ * Sandpoint specific fixups.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "io.h"
+#include "ops.h"
+
+#define MB (1024*1024)
+
+extern char _end[];
+
+static u32 cur_base;
+static u32 end_of_ram = 32 * MB; /* XXXX get from /memory */
+
+static void *
+dink_malloc(u32 size)
+{
+ void *area = NULL;
+ static u8 first_time = 1;
+
+ if (first_time) {
+ cur_base = _ALIGN_UP((unsigned long)_end, MB);
+ first_time = 0;
+ }
+
+ if ((cur_base + size) < end_of_ram) {
+ area = (void *)cur_base;
+ cur_base += _ALIGN_UP(size, MB);
+ }
+
+ return area;
+}
+
+static struct fw_ops dink_fw_ops;
+
+struct fw_ops *
+dink_init(void)
+{
+ dink_fw_ops.malloc = dink_malloc;
+ dink_fw_ops.free = NULL;
+ dink_fw_ops.exit = NULL;
+
+ return &dink_fw_ops;
+}
diff --git a/arch/powerpc/boot/dts/sandpoint.dts b/arch/powerpc/boot/dts/sandpoint.dts
new file mode 100644
index 0000000..dfd3f7d
--- /dev/null
+++ b/arch/powerpc/boot/dts/sandpoint.dts
@@ -0,0 +1,206 @@
+/*
+ * Device Tree Souce for Freescale Sandpoint
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+
+XXXX add flash parts, rtc, ??
+
+build with: "dtc -I dts -O asm -o sandpoint.S -V 16 sandpoint.dts"
+
+
+ */
+
+/ {
+ linux,phandle = <1000>;
+ model = "Sandpoint";
+ compatible = "classic+mpc10x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ linux,phandle = <2000>;
+ #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,603e { /* Really 75x, 74xx, 824x */
+ linux,phandle = <2100>;
+ linux,boot-cpu;
+ device_type = "cpu";
+ reg = <0>;
+ clock-frequency = <0>; /* Fixed by bootwrapper */
+ timebase-frequency = <0>; /* Fixed by bootwrapper */
+ /* Following required by dtc but not used */
+ i-cache-line-size = <0>;
+ d-cache-line-size = <0>;
+ i-cache-size = <0>;
+ d-cache-size = <0>;
+ };
+ };
+
+ memory {
+ linux,phandle = <3000>;
+ device_type = "memory";
+ reg = <00000000 00000000>; /* Fixed by bootwrapper */
+ };
+
+ mpc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+ linux,phandle = <4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "mpc10x-bridge";
+ compatible = "mpc10x-bridge";
+ store-gathering = <0>; /* 0 == off, !0 == on */
+ reg = <fc000000 00100000>;
+ ranges = <80000000 80000000 70000000 /* pci mem space */
+ fc000000 fc000000 00100000 /* EUMB */
+ fe000000 fe000000 00c00000 /* pci i/o space */
+ fec00000 fec00000 00300000 /* pci cfg regs */
+ fef00000 fef00000 00100000>; /* pci iack */
+
+ dma@1100 {
+ linux,phandle = <4100>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "dma";
+ compatible = "fsl-dma";
+ clock-frequency = <0>;
+ reg = <fc001100 00000024>;
+ interrupts = <33 0>;
+ interrupt-parent = <4400>;
+ };
+
+ dma@1200 {
+ linux,phandle = <4200>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "dma";
+ compatible = "fsl-dma";
+ clock-frequency = <0>;
+ reg = <fc001200 00000024>;
+ interrupts = <34 0>;
+ interrupt-parent = <4400>;
+ };
+
+ i2c {
+ linux,phandle = <4300>;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "i2c";
+ compatible = "fsl-i2c";
+ clock-frequency = <0>;
+ reg = <fc003000 00001000>;
+ interrupts = <32 0>;
+ interrupt-parent = <4400>;
+ };
+
+ pic {
+ linux,phandle = <4400>;
+ clock-frequency = <0>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ device_type = "open-pic";
+ compatible = "chrp,open-pic";
+ reg = <fc040000 00040000>;
+ };
+
+ pci {
+ linux,phandle = <4500>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+ reg = <fec00000 00400000>;
+ ranges = <01000000 0 0 fe000000 0 00c00000
+ 02000000 0 80000000 80000000 0 70000000>;
+ bus-range = <0 ff>;
+ clock-frequency = <7f28155>;
+ interrupt-pci-iack = <fef00000>; /* New - PCI IACK */
+ interrupt-parent = <4400>;
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x11 */
+ 8800 0 0 1 4400 16 0
+ 8800 0 0 2 4400 0 0
+ 8800 0 0 3 4400 0 0
+ 8800 0 0 4 4400 0 0
+ /* IDSEL 0x12 */
+ 9000 0 0 1 4400 0 0
+ 9000 0 0 2 4400 0 0
+ 9000 0 0 3 4400 0 0
+ 9000 0 0 4 4400 0 0
+ /* IDSEL 0x13 */
+ 9800 0 0 1 4400 18 0
+ 9800 0 0 2 4400 19 0
+ 9800 0 0 3 4400 20 0
+ 9800 0 0 4 4400 21 0
+ /* IDSEL 0x14 */
+ a000 0 0 1 4400 19 0
+ a000 0 0 2 4400 18 0
+ a000 0 0 3 4400 21 0
+ a000 0 0 4 4400 20 0
+ /* IDSEL 0x15 */
+ a800 0 0 1 4400 20 0
+ a800 0 0 2 4400 19 0
+ a800 0 0 3 4400 18 0
+ a800 0 0 4 4400 21 0
+ /* IDSEL 0x16 */
+ b000 0 0 1 4400 21 0
+ b000 0 0 2 4400 20 0
+ b000 0 0 3 4400 19 0
+ b000 0 0 4 4400 18 0
+ >;
+
+ isa {
+ linux,phandle = <4510>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ device_type = "isa";
+ compatible = "isa";
+ ranges = <1 0 01000000 0 0 00800000>;
+
+ serial@3f8 {
+ linux,phandle = <4511>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <1 3f8 8>;
+ clock-frequency = <1c2000>;
+ current-speed = <2580>;
+ interrupts = <4 0>;
+ interrupt-parent = <4400>;
+ };
+
+ serial@2f8 {
+ linux,phandle = <4512>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <1 2f8 8>;
+ clock-frequency = <1c2000>;
+ current-speed = <2580>;
+ interrupts = <3 0>;
+ interrupt-parent = <4400>;
+ };
+ };
+ };
+ };
+
+ chosen {
+ linux,phandle = <5000>;
+ linux,platform = <1>;
+ bootargs = "ip=on";
+ linux,stdout-path = "/mpc10x/pci/isa/serial@3f8";
+ interrupt-controller = <4400>;
+ };
+};
diff --git a/arch/powerpc/boot/fdt.c b/arch/powerpc/boot/fdt.c
new file mode 100644
index 0000000..f8ad8e6
--- /dev/null
+++ b/arch/powerpc/boot/fdt.c
@@ -0,0 +1,525 @@
+/*
+ * Simple dtb (binary flattened device tree) search/manipulation routines.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ * - The code for strrchr() was copied from lib/string.c and is
+ * copyrighted by Linus Torvalds.
+ * - The smarts for fdt_finddevice() were copied with the author's
+ * permission from u-boot:common/ft_build.c which was written by
+ * Pantelis Antoniou <pantelis@embeddedalley.com>.
+ * - Many of the routines related to fdt_translate_addr() came
+ * from arch/powerpc/kernel/prom_parse.c which has no author or
+ * copyright notice.
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/* Supports dtb version 0x10 only */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "page.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER 0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
+#define OF_DT_END_NODE 0x2 /* End node */
+#define OF_DT_PROP 0x3 /* Property: name off, size,
+ * content */
+#define OF_DT_NOP 0x4 /* nop */
+#define OF_DT_END 0x9
+
+#define OF_DT_VERSION 0x10
+
+struct boot_param_header
+{
+ u32 magic; /* magic word OF_DT_HEADER */
+ u32 totalsize; /* total size of DT block */
+ u32 off_dt_struct; /* offset to structure */
+ u32 off_dt_strings; /* offset to strings */
+ u32 off_mem_rsvmap; /* offset to memory reserve map */
+ u32 version; /* format version */
+ u32 last_comp_version; /* last compatible version */
+ /* version 2 fields below */
+ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
+ /* version 3 fields below */
+ u32 dt_strings_size; /* size of the DT strings block */
+};
+
+extern void *dt_blob_start;
+extern void *dt_blob_end;
+
+static void *dtb_start;
+static void *dtb_end;
+
+#define MAX_ADDR_CELLS 4
+#define BAD_ADDR ((u64)-1)
+
+struct fdt_bus {
+ u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna);
+ int (*translate)(u32 *addr, u64 offset, int na);
+};
+
+static inline struct boot_param_header *
+fdt_get_bph(void *dt_blob)
+{
+ return (struct boot_param_header *)dt_blob;
+}
+
+static char *
+fdt_strrchr(const char *s, int c)
+{
+ const char *p = s + strlen(s);
+
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+
+/* 'path' is modified */
+static void
+fdt_parentize(char *path, u8 leave_slash)
+{
+ char *s = &path[strlen(path) - 1];
+
+ if (*s == '/')
+ *s = '\0';
+ s = fdt_strrchr(path, '/');
+ if (s != NULL) {
+ if (leave_slash)
+ s[1] = '\0';
+ else if (s[0] == '/')
+ s[0] = '\0';
+ }
+}
+
+static inline u32 *
+fdt_next(u32 *dp, u32 **tagpp, char **namepp, char **datapp, u32 **sizepp)
+{
+ static char *str_region;
+
+ *namepp = NULL;
+ *datapp = NULL;
+ *sizepp = NULL;
+
+ if (dp == NULL) { /* first time */
+ struct boot_param_header *bph = fdt_get_bph(dtb_start);
+
+ if (bph->magic != OF_DT_HEADER) {
+ *tagpp = NULL;
+ return NULL;
+ }
+ dp = (u32 *)((u32)dtb_start + bph->off_dt_struct);
+ str_region = (char *)((u32)dtb_start + bph->off_dt_strings);
+ }
+
+ *tagpp = dp;
+
+ switch (*dp++) { /* Tag */
+ case OF_DT_PROP:
+ *sizepp = dp++;
+ *namepp = str_region + *dp++;
+ *datapp = (char *)dp;
+ dp = (u32 *)_ALIGN_UP((unsigned long)dp + **sizepp, 4);
+ break;
+ case OF_DT_BEGIN_NODE:
+ *namepp = (char *)dp;
+ dp = (u32 *)_ALIGN_UP((u32)dp + strlen((char *)dp) + 1, 4);
+ break;
+ case OF_DT_END_NODE:
+ case OF_DT_NOP:
+ break;
+ case OF_DT_END:
+ default:
+ dp = NULL;
+ break;
+ }
+
+ return dp;
+}
+
+static void *
+fdt_finddevice(const char *name)
+{
+ u32 *dp, *tagp, *sizep;
+ char *namep, *datap;
+ static char path[MAX_PATH_LEN];
+
+ path[0] = '\0';
+ dp = NULL;
+
+ while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+ switch (*tagp) {
+ case OF_DT_BEGIN_NODE:
+ strcat(path, namep);
+ if (!strcmp(path, name))
+ return tagp;
+ strcat(path, "/");
+ break;
+ case OF_DT_END_NODE:
+ fdt_parentize(path, 1);
+ break;
+ }
+ return NULL;
+}
+
+static int
+fdt_getprop(void *node, const char *name, void *buf, int buflen)
+{
+ u32 *dp, *tagp, *sizep, size;
+ char *namep, *datap;
+ int level;
+
+ level = 0;
+ dp = node;
+
+ while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+ switch (*tagp) {
+ case OF_DT_PROP:
+ if ((level == 1) && !strcmp(namep, name)) {
+ size = min(*sizep, (u32)buflen);
+ memcpy(buf, datap, size);
+ return size;
+ }
+ break;
+ case OF_DT_BEGIN_NODE:
+ level++;
+ break;
+ case OF_DT_END_NODE:
+ if (--level <= 0)
+ return -1;
+ break;
+ }
+ return -1;
+}
+
+static void
+fdt_modify_prop(u32 *dp, char *datap, u32 *old_prop_sizep, char *buf,
+ int buflen)
+{
+ u32 old_prop_data_len, new_prop_data_len;
+
+ old_prop_data_len = _ALIGN_UP(*old_prop_sizep, 4);
+ new_prop_data_len = _ALIGN_UP(buflen, 4);
+
+ /* Check if new prop data fits in old prop data area */
+ if (new_prop_data_len == old_prop_data_len) {
+ memcpy(datap, buf, buflen);
+ *old_prop_sizep = buflen;
+ }
+ else { /* Need to alloc new area to put larger or smaller fdt */
+ struct boot_param_header *old_bph, *new_bph;
+ u32 *old_tailp, *new_tailp, *new_datap;
+ u32 old_total_size, new_total_size, head_len, tail_len, diff;
+ void *new_dtb_start, *new_dtb_end;
+
+ old_bph = fdt_get_bph(dtb_start),
+ old_total_size = old_bph->totalsize;
+ head_len = (u32)datap - (u32)dtb_start;
+ tail_len = old_total_size - (head_len + old_prop_data_len);
+ old_tailp = (u32 *)((u32)dtb_end - tail_len);
+ new_total_size = head_len + new_prop_data_len + tail_len;
+
+ if (!(new_dtb_start = malloc(new_total_size))) {
+ printf("Can't alloc space for new fdt\n\r");
+ exit();
+ }
+
+ new_dtb_end = (void *)((u32)new_dtb_start + new_total_size);
+ new_datap = (u32 *)((u32)new_dtb_start + head_len);
+ new_tailp = (u32 *)((u32)new_dtb_end - tail_len);
+
+ memcpy(new_dtb_start, dtb_start, head_len);
+ memcpy(new_datap, buf, buflen);
+ memcpy(new_tailp, old_tailp, tail_len);
+ *(new_datap - 2) = buflen;
+
+ new_bph = fdt_get_bph(new_dtb_start),
+ new_bph->totalsize = new_total_size;
+
+ diff = new_prop_data_len - old_prop_data_len;
+
+ /* Adjust offsets of other sections, if necessary */
+ if (new_bph->off_dt_strings > new_bph->off_dt_struct)
+ new_bph->off_dt_strings += diff;
+
+ if (new_bph->off_mem_rsvmap > new_bph->off_dt_struct)
+ new_bph->off_mem_rsvmap += diff;
+
+ free(dtb_start, old_total_size);
+
+ dtb_start = new_dtb_start;
+ dtb_end = new_dtb_end;
+ }
+}
+
+/* Only modifies existing properties */
+static int
+fdt_setprop(void *node, const char *name, void *buf, int buflen)
+{
+ u32 *dp, *tagp, *sizep;
+ char *namep, *datap;
+ int level;
+
+ level = 0;
+ dp = node;
+
+ while ((dp = fdt_next(dp, &tagp, &namep, &datap, &sizep)) != NULL)
+ switch (*tagp) {
+ case OF_DT_PROP:
+ if ((level == 1) && !strcmp(namep, name)) {
+ fdt_modify_prop(tagp, datap, sizep, buf,buflen);
+ return *sizep;
+ }
+ break;
+ case OF_DT_BEGIN_NODE:
+ level++;
+ break;
+ case OF_DT_END_NODE:
+ if (--level <= 0)
+ return -1;
+ break;
+ }
+ return -1;
+}
+
+static u32
+fdt_find_cells(char *path, char *prop)
+{
+ void *devp;
+ u32 num;
+ char p[MAX_PATH_LEN];
+
+ strcpy(p, path);
+ do {
+ if ((devp = finddevice(p))
+ && (getprop(devp, prop, &num, sizeof(num)) > 0))
+ return num;
+ fdt_parentize(p, 0);
+ } while (strlen(p) > 0);
+ return 1; /* default of 1 */
+}
+
+static u64
+fdt_read_addr(u32 *cell, int size)
+{
+ u64 r = 0;
+ while (size--)
+ r = (r << 32) | *(cell++);
+ return r;
+}
+
+static u64
+fdt_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ cp = fdt_read_addr(range, na);
+ s = fdt_read_addr(range + na + pna, ns);
+ da = fdt_read_addr(addr, na);
+
+ if (da < cp || da >= (cp + s))
+ return BAD_ADDR;
+ return da - cp;
+}
+
+static int
+fdt_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+ u64 a = fdt_read_addr(addr, na);
+ memset(addr, 0, na * 4);
+ a += offset;
+ if (na > 1)
+ addr[na - 2] = a >> 32;
+ addr[na - 1] = a & 0xffffffffu;
+
+ return 0;
+}
+
+static u64
+fdt_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x03000000)
+ return BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = fdt_read_addr(range + 1, na - 1);
+ s = fdt_read_addr(range + na + pna, ns);
+ da = fdt_read_addr(addr + 1, na - 1);
+
+ if (da < cp || da >= (cp + s))
+ return BAD_ADDR;
+ return da - cp;
+}
+
+static int
+fdt_bus_pci_translate(u32 *addr, u64 offset, int na)
+{
+ return fdt_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static u64
+fdt_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x00000001)
+ return BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = fdt_read_addr(range + 1, na - 1);
+ s = fdt_read_addr(range + na + pna, ns);
+ da = fdt_read_addr(addr + 1, na - 1);
+
+ if (da < cp || da >= (cp + s))
+ return BAD_ADDR;
+ return da - cp;
+}
+
+static int
+fdt_bus_isa_translate(u32 *addr, u64 offset, int na)
+{
+ return fdt_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static void
+fdt_match_bus(char *path, struct fdt_bus *bus)
+{
+ void *devp;
+ char dtype[128]; /* XXXX */
+
+ if ((devp = finddevice(path)) && (getprop(devp, "device_type", dtype,
+ sizeof(dtype)) > 0)) {
+ if (!strcmp(dtype, "isa")) {
+ bus->map = fdt_bus_isa_map;
+ bus->translate = fdt_bus_isa_translate;
+ } else if (!strcmp(dtype, "pci")) {
+ bus->map = fdt_bus_pci_map;
+ bus->translate = fdt_bus_pci_translate;
+ } else {
+ bus->map = fdt_bus_default_map;
+ bus->translate = fdt_bus_default_translate;
+ }
+ }
+}
+
+static int
+fdt_translate_one(char *path, struct fdt_bus *bus, struct fdt_bus *pbus,
+ u32 *addr, u32 na, u32 ns, u32 pna)
+{
+ void *devp;
+ u32 ranges[10 * (na + pna + ns)]; /* XXXX */
+ u32 *rp;
+ unsigned int rlen;
+ int rone;
+ u64 offset = BAD_ADDR;
+
+ if (!(devp = finddevice(path))
+ || ((rlen = getprop(devp, "ranges", ranges,
+ sizeof(ranges))) < 0)
+ || (rlen == 0)) {
+ offset = fdt_read_addr(addr, na);
+ memset(addr, 0, pna * 4);
+ goto finish;
+ }
+
+ rlen /= 4;
+ rone = na + pna + ns;
+ rp = ranges;
+ for (; rlen >= rone; rlen -= rone, rp += rone) {
+ offset = bus->map(addr, rp, na, ns, pna);
+ if (offset != BAD_ADDR)
+ break;
+ }
+ if (offset == BAD_ADDR)
+ return 1;
+ memcpy(addr, rp + na, 4 * pna);
+
+finish:
+ /* Translate it into parent bus space */
+ return pbus->translate(addr, offset, pna);
+}
+
+/* 'addr' is modified */
+static u64
+fdt_translate_addr(char *p, u32 *in_addr, u32 addr_len)
+{
+ struct fdt_bus bus, pbus;
+ int na, ns, pna, pns;
+ u32 addr[MAX_ADDR_CELLS];
+ char path[MAX_PATH_LEN], ppath[MAX_PATH_LEN];
+
+ strcpy(ppath, p);
+ fdt_parentize(ppath, 0);
+ fdt_match_bus(ppath, &bus);
+ na = fdt_find_cells(ppath, "#address-cells");
+ ns = fdt_find_cells(ppath, "#size-cells");
+ memcpy(addr, in_addr, na * 4);
+
+ for (;;) {
+ strcpy(path, ppath);
+ fdt_parentize(ppath, 0);
+
+ if (strlen(ppath) == 0)
+ return fdt_read_addr(addr, na);
+
+ fdt_match_bus(ppath, &pbus);
+ pna = fdt_find_cells(ppath, "#address-cells");
+ pns = fdt_find_cells(ppath, "#size-cells");
+
+ if (fdt_translate_one(path, &bus, &pbus, addr, na, ns, pna))
+ exit();
+
+ na = pna;
+ ns = pns;
+ memcpy(&bus, &pbus, sizeof(struct fdt_bus));
+ }
+}
+
+static void
+fdt_call_kernel(void *entry_addr, unsigned long a1, unsigned long a2,
+ void *promptr, void *sp)
+{
+ void (*kernel_entry)(void *dt_blob, void *start_addr,
+ void *must_be_null);
+
+#ifdef DEBUG
+ printf("kernel:\n\r"
+ " entry addr = 0x%lx\n\r"
+ " flattened dt = 0x%lx\n\r",
+ (unsigned long)entry_addr, dtb_start);
+#endif
+
+ kernel_entry = entry_addr;
+ kernel_entry(dtb_start, entry_addr, NULL);
+}
+
+static struct dt_ops fdt_dt_ops;
+
+struct dt_ops *
+fdt_init(void)
+{
+ fdt_dt_ops.finddevice = fdt_finddevice;
+ fdt_dt_ops.getprop = fdt_getprop;
+ fdt_dt_ops.setprop = fdt_setprop;
+ fdt_dt_ops.translate_addr = fdt_translate_addr;
+ fdt_dt_ops.call_kernel = fdt_call_kernel;
+
+ dtb_start = &dt_blob_start;
+ dtb_end = &dt_blob_end;
+
+ return &fdt_dt_ops;
+}
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 0000000..65c1864
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,160 @@
+#ifndef _IO_H
+#define __IO_H
+
+#include "types.h"
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ * These routines do not perform EEH-related I/O address translation,
+ * and should not be used directly by device drivers. Use inb/readb
+ * instead.
+ */
+static inline int in_8(const volatile unsigned char *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+ __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline int in_le16(const volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline int in_be16(const volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("sthbrx %1,0,%2; sync"
+ : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void out_be16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("sth%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned in_le32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline unsigned in_be32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+ : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned long in_le64(const volatile unsigned long *addr)
+{
+ unsigned long tmp, ret;
+
+ __asm__ __volatile__(
+ "ld %1,0(%2)\n"
+ "twi 0,%1,0\n"
+ "isync\n"
+ "rldimi %0,%1,5*8,1*8\n"
+ "rldimi %0,%1,3*8,2*8\n"
+ "rldimi %0,%1,1*8,3*8\n"
+ "rldimi %0,%1,7*8,4*8\n"
+ "rldicl %1,%1,32,0\n"
+ "rlwimi %0,%1,8,8,31\n"
+ "rlwimi %0,%1,24,16,23\n"
+ : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr));
+ return ret;
+}
+
+static inline unsigned long in_be64(const volatile unsigned long *addr)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ld%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le64(volatile unsigned long *addr, unsigned long val)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__(
+ "rldimi %0,%1,5*8,1*8\n"
+ "rldimi %0,%1,3*8,2*8\n"
+ "rldimi %0,%1,1*8,3*8\n"
+ "rldimi %0,%1,7*8,4*8\n"
+ "rldicl %1,%1,32,0\n"
+ "rlwimi %0,%1,8,8,31\n"
+ "rlwimi %0,%1,24,16,23\n"
+ "std %0,0(%3)\n"
+ "sync"
+ : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr));
+}
+
+static inline void out_be64(volatile unsigned long *addr, unsigned long val)
+{
+ __asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
+}
+
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+
+/* Indirect PCI config space access routines */
+static inline void
+pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
+ int offset, u8 *val)
+{
+ out_be32(cfg_addr,
+ ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
+ *val = in_8((u8 *)(cfg_data + (offset & 3)));
+ return;
+}
+
+static inline void
+pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
+ int offset, u32 *val)
+{
+ out_be32(cfg_addr,
+ ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
+ *val = in_le32(cfg_data + (offset & 3));
+ return;
+}
+
+#endif /* _IO_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 816446f..03e305b 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,17 +14,11 @@ #include "elf.h"
#include "page.h"
#include "string.h"
#include "stdio.h"
-#include "prom.h"
#include "zlib.h"
+#include "ops.h"
extern void flush_cache(void *, unsigned long);
-
-/* Value picked to match that used by yaboot */
-#define PROG_START 0x01400000 /* only used on 64-bit systems */
-#define RAM_END (512<<20) /* Fixme: use OF */
-#define ONE_MB 0x100000
-
extern char _start[];
extern char __bss_start[];
extern char _end[];
@@ -46,17 +40,8 @@ static unsigned long elfoffset;
static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
static char elfheader[256];
-
-
-typedef void (*kernel_entry_t)( unsigned long,
- unsigned long,
- void *,
- void *);
-
#undef DEBUG
-
-static unsigned long claim_base;
#define HEAD_CRC 2
#define EXTRA_FIELD 4
@@ -113,24 +98,6 @@ static void gunzip(void *dst, int dstlen
}
*lenp = s.next_out - (unsigned char *) dst;
zlib_inflateEnd(&s);
-}
-
-static unsigned long try_claim(unsigned long size)
-{
- unsigned long addr = 0;
-
- for(; claim_base < RAM_END; claim_base += ONE_MB) {
-#ifdef DEBUG
- printf(" trying: 0x%08lx\n\r", claim_base);
-#endif
- addr = (unsigned long)claim(claim_base, size, 0);
- if ((void *)addr != (void *)-1)
- break;
- }
- if (addr == 0)
- return 0;
- claim_base = PAGE_ALIGN(claim_base + size);
- return addr;
}
static int is_elf64(void *hdr)
@@ -161,16 +128,6 @@ static int is_elf64(void *hdr)
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
-#if defined(PROG_START)
- /*
- * Maintain a "magic" minimum address. This keeps some older
- * firmware platforms running.
- */
-
- if (claim_base < PROG_START)
- claim_base = PROG_START;
-#endif
-
return 1;
}
@@ -204,31 +161,12 @@ static int is_elf32(void *hdr)
return 1;
}
-void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+static void prep_kernel(unsigned long *a1, unsigned long *a2, void *sp)
{
int len;
- kernel_entry_t kernel_entry;
- memset(__bss_start, 0, _end - __bss_start);
+ printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
- prom = (int (*)(void *)) promptr;
- chosen_handle = finddevice("/chosen");
- if (chosen_handle == (void *) -1)
- exit();
- if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
- exit();
-
- printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
-
- /*
- * The first available claim_base must be above the end of the
- * the loaded kernel wrapper file (_start to _end includes the
- * initrd image if it is present) and rounded up to a nice
- * 1 MB boundary for good measure.
- */
-
- claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
-
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -238,43 +176,46 @@ void start(unsigned long a1, unsigned lo
gunzip(elfheader, sizeof(elfheader),
(unsigned char *)vmlinuz.addr, &len);
} else
- memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+ memcpy(elfheader, (const void *)vmlinuz.addr,sizeof(elfheader));
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
exit();
}
- /* We need to claim the memsize plus the file offset since gzip
+ /* We need to alloc the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
* be claimed (it will be zero'd by the kernel itself)
*/
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
- vmlinux.addr = try_claim(vmlinux.memsize);
+ vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r");
exit();
}
/*
- * Now we try to claim memory for the initrd (and copy it there)
+ * Now we try to alloc memory for the initrd (and copy it there)
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
- printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
- initrd.addr = try_claim(initrd.size);
+ printf("Allocating 0x%lx bytes for initrd ...\n\r",initrd.size);
+ initrd.addr = (unsigned long)malloc((u32)initrd.size);
if (initrd.addr == 0) {
- printf("Can't allocate memory for initial ramdisk !\n\r");
+ printf("Can't allocate memory for initial "
+ "ramdisk !\n\r");
exit();
}
- a1 = initrd.addr;
- a2 = initrd.size;
- printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
- initrd.addr, (unsigned long)_initrd_start, initrd.size);
- memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
- printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
+ *a1 = initrd.addr;
+ *a2 = initrd.size;
+ printf("initial ramdisk moving 0x%lx <- 0x%lx "
+ "(0x%lx bytes)\n\r", initrd.addr,
+ (unsigned long)_initrd_start, initrd.size);
+ memmove((void *)initrd.addr, (void *)_initrd_start,initrd.size);
+ printf("initrd head: 0x%lx\n\r",
+ *((unsigned long *)initrd.addr));
}
/* Eventually gunzip the kernel */
@@ -297,23 +238,75 @@ #endif
vmlinux.addr += elfoffset;
flush_cache((void *)vmlinux.addr, vmlinux.size);
+}
- kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
- printf( "kernel:\n\r"
- " entry addr = 0x%lx\n\r"
- " a1 = 0x%lx,\n\r"
- " a2 = 0x%lx,\n\r"
- " prom = 0x%lx,\n\r"
- " bi_recs = 0x%lx,\n\r",
- (unsigned long)kernel_entry, a1, a2,
- (unsigned long)prom, NULL);
-#endif
+static char zimage_cmdline[COMMAND_LINE_SIZE]
+ __attribute__((section("__zimage_cmdline")));
- kernel_entry(a1, a2, prom, NULL);
+static void get_cmdline(char *buf, int size)
+{
+ void *devp;
+ int len = strlen(zimage_cmdline);
- printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+ buf[0] = '\0';
- exit();
+ if (len > 0) { /* zimage_cmdline overrides dt's /chosen/bootargs */
+ len = min(len, size-1);
+ strncpy(buf, zimage_cmdline, len);
+ buf[len] = '\0';
+ }
+ else if ((devp = finddevice("/chosen")))
+ getprop(devp, "bootargs", buf, size);
}
+
+static void set_cmdline(char *buf)
+{
+ void *devp;
+
+ if ((devp = finddevice("/chosen")))
+ setprop(devp, "bootargs", buf, strlen(buf) + 1);
+}
+
+struct ops *ops;
+
+void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+{
+ char cmdline[COMMAND_LINE_SIZE];
+
+ memset(__bss_start, 0, _end - __bss_start);
+
+ ops = platform_init(promptr);
+
+ if (!ops || !ops->platform_ops || !ops->fw_ops || !ops->dt_ops
+ || !ops->console_ops)
+ exit();
+ if (ops->console_ops->open && (ops->console_ops->open() < 0))
+ exit();
+ if (ops->platform_ops->fixups)
+ ops->platform_ops->fixups();
+
+ prep_kernel(&a1, &a2, sp);
+
+ /* If cmdline came from zimage wrapper or if we can edit the one
+ * in the dt, print it out and edit it, if possible.
+ */
+ if ((strlen(zimage_cmdline) > 0) || ops->console_ops->edit_cmdline) {
+ get_cmdline(cmdline, COMMAND_LINE_SIZE);
+ printf("\n\rLinux/PowerPC load: %s", cmdline);
+ if (ops->console_ops->edit_cmdline)
+ ops->console_ops->edit_cmdline(cmdline,
+ COMMAND_LINE_SIZE);
+ printf("\n\r");
+ set_cmdline(cmdline);
+ }
+
+ if (ops->console_ops->close)
+ ops->console_ops->close();
+
+ ops->dt_ops->call_kernel((void *)vmlinux.addr, a1, a2, promptr, sp);
+
+ /* console closed so printf below may not work */
+ printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+ exit();
+}
diff --git a/arch/powerpc/boot/mpc10x.c b/arch/powerpc/boot/mpc10x.c
new file mode 100644
index 0000000..2916fdc
--- /dev/null
+++ b/arch/powerpc/boot/mpc10x.c
@@ -0,0 +1,87 @@
+/*
+ * Freescale mpc10[67] & mpc824[015] specific code.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+
+/* Map B (CHRP Map) Defines */
+#define MPC10X_MAPB_CNFG_ADDR 0xfec00000
+#define MPC10X_MAPB_CNFG_DATA 0xfee00000
+
+/* Define offsets for the memory controller registers in the config space */
+#define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_START_2 0x84 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_START_1 0x88 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_BANK_ENABLES 0xa0
+
+
+/*
+ * Read the memory controller registers to determine the amount of memory in
+ * the system. This assumes that the firmware has correctly set up the memory
+ * controller registers.
+ * Assume memory map B (CHRP).
+ */
+u32
+mpc10x_get_mem_size(void)
+{
+ u32 *config_addr, *config_data, val;
+ u32 start, end, total, offset, i;
+ u8 bank_enables;
+
+ config_addr = (u32 *)MPC10X_MAPB_CNFG_ADDR;
+ config_data = (u32 *)MPC10X_MAPB_CNFG_DATA;
+
+ pci_indirect_read_config_byte(config_addr, config_data, PCI_DEVFN(0,0),
+ MPC10X_MCTLR_MEM_BANK_ENABLES, &bank_enables);
+
+ total = 0;
+
+ for (i=0; i<8; i++) {
+ if (bank_enables & (1 << i)) {
+ offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ start = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ start = (val << 28) | (start << 20);
+
+ offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ end = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
+ pci_indirect_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ end = (val << 28) | (end << 20) | 0xfffff;
+
+ total += (end - start + 1);
+ }
+ }
+
+ return total;
+}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 0000000..5a6d91f
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,125 @@
+/*
+ * 16550 serial console support
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Much of the code is copied from arch/ppc/boot/common/ns16550.c
+ * which has no Author or Copyright text.
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+int
+ns16550_get_dt_info(struct serial_console_data *scdp)
+{
+ u64 addr;
+ u32 reg[2], reg_shift;
+ void *devp;
+ char path[MAX_PATH_LEN+1], compat[MAX_PATH_LEN+1];
+
+ scdp->base = NULL;
+ scdp->reg_shift = 0;
+
+ if ((devp = finddevice("/chosen"))
+ && (getprop(devp, "linux,stdout-path", path,
+ sizeof(path)) > 0)
+ && (devp = finddevice(path))
+ && (getprop(devp, "compatible", compat, sizeof(compat))
+ > 0)
+ && !strcmp(compat, "ns16550")
+ && (getprop(devp, "reg", reg, sizeof(reg))
+ == sizeof(reg))) {
+
+ addr = ops->dt_ops->translate_addr(path, reg, sizeof(reg));
+ scdp->base = (unsigned char *)((u32)addr & 0xffffffffu);
+
+ if (getprop(devp, "reg_shift", ®_shift, sizeof(reg_shift))
+ == sizeof(reg_shift))
+ scdp->reg_shift = reg_shift;
+ return 0;
+ }
+ return -1;
+}
+
+static int
+ns16550_open(void)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+
+ if (ns16550_get_dt_info(scdp) < 0)
+ return -1;
+
+ out_8(scdp->base + (UART_FCR << scdp->reg_shift), 0x06);
+ return 0;
+}
+
+static void
+ns16550_putc(unsigned char c)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+ while ((in_8(scdp->base + (UART_LSR << scdp->reg_shift))
+ & UART_LSR_THRE) == 0);
+ out_8(scdp->base, c);
+}
+
+static unsigned char
+ns16550_getc(void)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+ while ((in_8(scdp->base + (UART_LSR << scdp->reg_shift))
+ & UART_LSR_DR) == 0);
+ return in_8(scdp->base);
+}
+
+static u8
+ns16550_tstc(void)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+ return ((in_8(scdp->base + (UART_LSR << scdp->reg_shift)) & UART_LSR_DR)
+ != 0);
+}
+
+static struct serial_console_data ns16550_scd;
+static struct console_ops ns16550_console_ops;
+
+struct console_ops *
+ns16550_init(void)
+{
+ ns16550_scd.open = ns16550_open;
+ ns16550_scd.putc = ns16550_putc;
+ ns16550_scd.getc = ns16550_getc;
+ ns16550_scd.tstc = ns16550_tstc;
+ ns16550_scd.close = NULL;
+ ns16550_scd.base = NULL;
+ ns16550_scd.reg_shift = 0;
+
+ ns16550_console_ops.open = serial_open;
+ ns16550_console_ops.write = serial_write;
+ ns16550_console_ops.edit_cmdline = serial_edit_cmdline;
+ ns16550_console_ops.close = serial_close;
+ ns16550_console_ops.data = &ns16550_scd;
+
+ return &ns16550_console_ops;
+}
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
new file mode 100644
index 0000000..313f125
--- /dev/null
+++ b/arch/powerpc/boot/of.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+typedef void *ihandle;
+typedef void *phandle;
+
+extern char _end[];
+
+/* Value picked to match that used by yaboot */
+#define PROG_START 0x01400000 /* only used on 64-bit systems */
+#define RAM_END (512<<20) /* Fixme: use OF */
+#define ONE_MB 0x100000
+
+int (*prom) (void *);
+
+
+static unsigned long claim_base;
+
+static int call_prom(const char *service, int nargs, int nret, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, nret);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, rets);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ if (rets != (void *) 0)
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = args.args[nargs+i];
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+ for (; *s2; ++s2)
+ if (*s1++ != *s2)
+ return 0;
+ return 1;
+}
+
+static int check_of_version(void)
+{
+ phandle oprom, chosen;
+ char version[64];
+
+ oprom = finddevice("/openprom");
+ if (oprom == (phandle) -1)
+ return 0;
+ if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return 0;
+ version[sizeof(version)-1] = 0;
+ printf("OF version = '%s'\r\n", version);
+ if (!string_match(version, "Open Firmware, 1.")
+ && !string_match(version, "FirmWorks,3."))
+ return 0;
+ chosen = finddevice("/chosen");
+ if (chosen == (phandle) -1) {
+ chosen = finddevice("/chosen@0");
+ if (chosen == (phandle) -1) {
+ printf("no chosen\n");
+ return 0;
+ }
+ }
+ if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+ printf("no mmu\n");
+ return 0;
+ }
+ memory = (ihandle) call_prom("open", 1, 1, "/memory");
+ if (memory == (ihandle) -1) {
+ memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+ if (memory == (ihandle) -1) {
+ printf("no memory node\n");
+ return 0;
+ }
+ }
+ printf("old OF detected\r\n");
+ return 1;
+}
+
+static void *claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ int ret;
+ unsigned int result;
+
+ if (need_map < 0)
+ need_map = check_of_version();
+ if (align || !need_map)
+ return (void *) call_prom("claim", 3, 1, virt, size, align);
+
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+ align, size, virt);
+ if (ret != 0 || result == -1)
+ return (void *) -1;
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+ align, size, virt);
+ /* 0x12 == coherent + read/write */
+ ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+ 0x12, size, virt, virt);
+ return (void *) virt;
+}
+
+static void *of_try_claim(u32 size)
+{
+ unsigned long addr = 0;
+ static u8 first_time = 1;
+
+ if (first_time) {
+#if defined(PROG_START)
+ /*
+ * Maintain a "magic" minimum address. This keeps some older
+ * firmware platforms running.
+ */
+
+ if (claim_base < PROG_START)
+ claim_base = PROG_START;
+#endif
+ claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+ first_time = 0;
+ }
+
+ for(; claim_base < RAM_END; claim_base += ONE_MB) {
+#ifdef DEBUG
+ printf(" trying: 0x%08lx\n\r", claim_base);
+#endif
+ addr = (unsigned long)claim(claim_base, size, 0);
+ if ((void *)addr != (void *)-1)
+ break;
+ }
+ if (addr == 0)
+ return NULL;
+ claim_base = PAGE_ALIGN(claim_base + size);
+ return (void *)addr;
+}
+
+static void of_fw_exit(void)
+{
+ call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+static void *of_finddevice(const char *name)
+{
+ return (phandle) call_prom("finddevice", 1, 1, name);
+}
+
+static int of_getprop(void *phandle, const char *name,
+ void *buf, int buflen)
+{
+ return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+static int of_setprop(void *phandle, const char *name,
+ void *buf, int buflen)
+{
+ return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
+
+static void of_call_kernel(void *entry_addr, unsigned long a1,
+ unsigned long a2, void *promptr, void *sp)
+{
+ void (*kernel_entry)(unsigned long a1, unsigned long a2, void *promptr,
+ void *sp);
+
+ kernel_entry = entry_addr;
+ kernel_entry(a1, a2, promptr, sp);
+}
+
+/*
+ * OF console routines
+ */
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+ void *devp;
+
+ if (((devp = finddevice("/chosen")) != NULL)
+ && (getprop(devp, "stdout", &of_stdout_handle,
+ sizeof(of_stdout_handle))
+ == sizeof(of_stdout_handle)))
+ return 0;
+
+ return -1;
+}
+
+static void of_console_write(char *buf, int len)
+{
+ call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+/* Init code that hooks up all of the routines */
+static struct platform_ops of_platform_ops;
+static struct fw_ops of_fw_ops;
+static struct dt_ops of_dt_ops;
+static struct console_ops of_console_ops;
+static struct ops of_ops;
+
+struct ops *platform_init(void *promptr)
+{
+ of_platform_ops.fixups = NULL;
+ of_platform_ops.exit = NULL;
+
+ of_fw_ops.malloc = of_try_claim;
+ of_fw_ops.free = NULL;
+ of_fw_ops.exit = of_fw_exit;
+
+ of_dt_ops.finddevice = of_finddevice;
+ of_dt_ops.getprop = of_getprop;
+ of_dt_ops.setprop = of_setprop;
+ of_dt_ops.call_kernel = of_call_kernel;
+
+ of_console_ops.open = of_console_open;
+ of_console_ops.write = of_console_write;
+ of_console_ops.edit_cmdline = NULL;
+ of_console_ops.close = NULL;
+ of_console_ops.data = NULL;
+
+ of_ops.platform_ops = &of_platform_ops;
+ of_ops.fw_ops = &of_fw_ops;
+ of_ops.dt_ops = &of_dt_ops;
+ of_ops.console_ops = &of_console_ops;
+
+ prom = (int (*)(void *))promptr;
+
+ return &of_ops;
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
new file mode 100644
index 0000000..c214f2b
--- /dev/null
+++ b/arch/powerpc/boot/ops.h
@@ -0,0 +1,117 @@
+/*
+ * Global definition of all the bootwrapper operations.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef _PPC_BOOT_OPS_H_
+#define _PPC_BOOT_OPS_H_
+
+#include "types.h"
+
+/* Platform specific operations */
+struct platform_ops {
+ void (*fixups)(void);
+ void (*exit)(void);
+};
+
+/* Firmware specific operations */
+struct fw_ops {
+ void * (*malloc)(u32 size);
+ void (*free)(void *ptr, u32 size);
+ void (*exit)(void);
+};
+
+/* Device Tree operations */
+struct dt_ops {
+ void * (*finddevice)(const char *name);
+ int (*getprop)(void *node, const char *name, void *buf, int buflen);
+ int (*setprop)(void *node, const char *name, void *buf, int buflen);
+ u64 (*translate_addr)(char *path, u32 *in_addr, u32 addr_len);
+ void (*call_kernel)(void *entry_addr, unsigned long a1,
+ unsigned long a2, void *promptr, void *sp);
+};
+
+/* Serial console operations */
+struct serial_console_data {
+ int (*open)(void);
+ void (*putc)(unsigned char c);
+ unsigned char (*getc)(void);
+ u8 (*tstc)(void);
+ void (*close)(void);
+ unsigned char *base;
+ u8 reg_shift;
+};
+
+/* Console operations */
+struct console_ops {
+ int (*open)(void);
+ void (*write)(char *buf, int len);
+ void (*edit_cmdline)(char *buf, int len);
+ void (*close)(void);
+ void *data;
+};
+
+struct ops {
+ struct platform_ops *platform_ops;
+ struct fw_ops *fw_ops;
+ struct dt_ops *dt_ops;
+ struct console_ops *console_ops;
+};
+
+extern struct ops *ops;
+
+extern struct ops *platform_init(void *promptr);
+extern struct fw_ops *dink_init(void);
+extern struct dt_ops *fdt_init(void);
+extern struct console_ops *ns16550_init(void);
+
+extern int serial_open(void);
+extern void serial_write(char *buf, int len);
+extern void serial_edit_cmdline(char *buf, int len);
+extern void serial_close(void);
+
+static inline void *finddevice(const char *name)
+{
+ return (ops->dt_ops->finddevice) ? ops->dt_ops->finddevice(name) : NULL;
+}
+
+static inline int getprop(void *devp, const char *name, void *buf, int buflen)
+{
+ return (ops->dt_ops->getprop) ?
+ ops->dt_ops->getprop(devp, name, buf, buflen) : -1;
+}
+
+static inline int setprop(void *devp, const char *name, void *buf, int buflen)
+{
+ return (ops->dt_ops->setprop) ?
+ ops->dt_ops->setprop(devp, name, buf, buflen) : -1;
+}
+
+static inline void *malloc(u32 size)
+{
+ return (ops->fw_ops->malloc) ? ops->fw_ops->malloc(size) : NULL;
+}
+
+static inline void free(void *ptr, u32 size)
+{
+ if (ops->fw_ops->free)
+ ops->fw_ops->free(ptr, size);
+}
+
+static inline void exit(void)
+{
+ if (ops) {
+ if (ops->platform_ops && ops->platform_ops->exit)
+ ops->platform_ops->exit();
+ if (ops->fw_ops && ops->fw_ops->exit)
+ ops->fw_ops->exit();
+ }
+ for(;;);
+}
+
+#endif /* _PPC_BOOT_OPS_H_ */
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
deleted file mode 100644
index fa00577..0000000
--- a/arch/powerpc/boot/prom.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdarg.h>
-#include <stddef.h>
-#include "string.h"
-#include "stdio.h"
-#include "prom.h"
-
-int (*prom)(void *);
-phandle chosen_handle;
-ihandle stdout;
-
-int call_prom(const char *service, int nargs, int nret, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, nret);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-int call_prom_ret(const char *service, int nargs, int nret,
- unsigned int *rets, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, rets);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- if (rets != (void *) 0)
- for (i = 1; i < nret; ++i)
- rets[i-1] = args.args[nargs+i];
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-int write(void *handle, void *ptr, int nb)
-{
- return call_prom("write", 3, 1, handle, ptr, nb);
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
- for (; *s2; ++s2)
- if (*s1++ != *s2)
- return 0;
- return 1;
-}
-
-static int check_of_version(void)
-{
- phandle oprom, chosen;
- char version[64];
-
- oprom = finddevice("/openprom");
- if (oprom == (phandle) -1)
- return 0;
- if (getprop(oprom, "model", version, sizeof(version)) <= 0)
- return 0;
- version[sizeof(version)-1] = 0;
- printf("OF version = '%s'\r\n", version);
- if (!string_match(version, "Open Firmware, 1.")
- && !string_match(version, "FirmWorks,3."))
- return 0;
- chosen = finddevice("/chosen");
- if (chosen == (phandle) -1) {
- chosen = finddevice("/chosen@0");
- if (chosen == (phandle) -1) {
- printf("no chosen\n");
- return 0;
- }
- }
- if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
- printf("no mmu\n");
- return 0;
- }
- memory = (ihandle) call_prom("open", 1, 1, "/memory");
- if (memory == (ihandle) -1) {
- memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
- if (memory == (ihandle) -1) {
- printf("no memory node\n");
- return 0;
- }
- }
- printf("old OF detected\r\n");
- return 1;
-}
-
-void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
- int ret;
- unsigned int result;
-
- if (need_map < 0)
- need_map = check_of_version();
- if (align || !need_map)
- return (void *) call_prom("claim", 3, 1, virt, size, align);
-
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
- align, size, virt);
- if (ret != 0 || result == -1)
- return (void *) -1;
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
- align, size, virt);
- /* 0x12 == coherent + read/write */
- ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
- 0x12, size, virt, virt);
- return (void *) virt;
-}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
deleted file mode 100644
index 3e2ddd4..0000000
--- a/arch/powerpc/boot/prom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _PPC_BOOT_PROM_H_
-#define _PPC_BOOT_PROM_H_
-
-typedef void *phandle;
-typedef void *ihandle;
-
-extern int (*prom) (void *);
-extern phandle chosen_handle;
-extern ihandle stdout;
-
-int call_prom(const char *service, int nargs, int nret, ...);
-int call_prom_ret(const char *service, int nargs, int nret,
- unsigned int *rets, ...);
-
-extern int write(void *handle, void *ptr, int nb);
-extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
-
-static inline void exit(void)
-{
- call_prom("exit", 0, 0);
-}
-
-static inline phandle finddevice(const char *name)
-{
- return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static inline int getprop(void *phandle, const char *name,
- void *buf, int buflen)
-{
- return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/boot/sandpoint.c b/arch/powerpc/boot/sandpoint.c
new file mode 100644
index 0000000..dc10e51
--- /dev/null
+++ b/arch/powerpc/boot/sandpoint.c
@@ -0,0 +1,148 @@
+/*
+ * Sandpoint specific fixups.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+#define CPU_824X 0
+#define CPU_7XX 1
+#define CPU_7457 2
+#define CPU_NUM 3
+
+static u32 cpu_pll[CPU_NUM][32] = {
+ [CPU_824X] = { /* 824x */
+ 5, 6, 9, 4, 4, 5, 2, 6, 6, 4, 9, 6, 5, 7, 6, 7,
+ 4, 5, 4, 6, 7, 8, 8, 4, 6, 5, 8, 6, 6, 5, 7, 0
+ },
+ [CPU_7XX] = { /* 750/755 */
+ 0, 15, 14, 2, 4, 13, 20, 9, 6, 11, 8, 10, 16, 12, 7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+ },
+ [CPU_7457] = { /* 7457 */
+ 23, 34, 15, 30, 14, 36, 2, 40, 4, 42, 13, 26, 17, 48, 19, 18,
+ 6, 21, 11, 22, 8, 20, 10, 24, 16, 28, 12, 32, 27, 56, 0, 25
+ }
+};
+
+static struct processor_info {
+ u32 pvr;
+ u32 mask;
+ u32 bus_freq;
+ u32 hid1_shift;
+ u32 hid1_mask;
+ u32 pll_tbl_idx;
+ u32 max_mem; /* 7457 flaky with > 64MB of mem */
+} processor_info_tbl[] = { /* From cputable -- MHz are only guesses */
+ /* 824x */
+ { 0x00810000, 0x7fff0000, 100000000, 27, 0x1f, CPU_824X, 0x80000000 },
+ /* 750 */
+ { 0x00084202, 0xffffffff, 100000000, 28, 0xf, CPU_7XX, 0x80000000 },
+ /* 745/755 */
+ { 0x00083000, 0xfffff000, 100000000, 28, 0xf, CPU_7XX, 0x80000000 },
+ /* 7447/7457 Rev 1.0 */
+ { 0x80020100, 0xffffffff, 100000000, 12, 0x1f, CPU_7457, 0x04000000 },
+ /* 7447/7457 Rev 1.1 */
+ { 0x80020101, 0xffffffff, 100000000, 12, 0x1f, CPU_7457, 0x04000000 },
+ /* 7447/7457 Rev 1.2 & up*/
+ { 0x80020000, 0xffff0000, 100000000, 12, 0x1f, CPU_7457, 0x04000000 },
+ /* 7447A */
+ { 0x80030000, 0xffff0000, 100000000, 12, 0x1f, CPU_7457, 0x80000000 },
+};
+
+static struct processor_info *
+get_processor_info(u32 pvr)
+{
+ struct processor_info *pit = processor_info_tbl;
+ u32 i;
+
+ for (i=0; i<ARRAY_SIZE(processor_info_tbl); i++, pit++)
+ if (pit->pvr == (pvr & pit->mask))
+ return pit;
+ return NULL;
+}
+
+#define __stringify_1(x) #x
+#define __stringify(x) __stringify_1(x)
+
+
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define mfspr(rn) ({unsigned long rval; \
+ asm volatile("mfspr %0," __stringify(rn) \
+ : "=r" (rval)); rval;})
+
+static void
+sandpoint_fixups(void)
+{
+ u32 i, v[2], hid1, max_mem = 0xffffffff;
+ void *devp;
+ struct processor_info *pit;
+ extern u32 mpc10x_get_mem_size(void);
+
+ if ((pit = get_processor_info(mfspr(SPRN_PVR)))
+ && (devp = finddevice("/cpus/PowerPC,603e"))) {
+
+ max_mem = pit->max_mem;
+
+ hid1 = (mfspr(SPRN_HID1) >> pit->hid1_shift) & pit->hid1_mask;
+ v[0] = pit->bus_freq * cpu_pll[pit->pll_tbl_idx][hid1]/2;
+ setprop(devp, "clock-frequency", v, sizeof(v[0]));
+
+ v[0] = pit->bus_freq / 4;
+ setprop(devp, "timebase-frequency", v, sizeof(v[0]));
+ }
+
+ /* Get the RAM size from the memory controller */
+ if ((devp = finddevice("/memory"))) {
+ i = mpc10x_get_mem_size();
+ v[0] = 0;
+ v[1] = min(i, max_mem);
+ setprop(devp, "reg", v, sizeof(v));
+ }
+
+ /* XXXX stuff from platforms/.../sandpoint.c should be here */
+}
+
+static void
+sandpoint_reset(void)
+{
+ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+ _nmask_and_or_msr(0, (1<<6)); /* Set exception prefix high - firmware */
+
+ /* Reset system via Port 92 */
+ out_8((volatile unsigned char *)0xfe000092, 0x00);
+ out_8((volatile unsigned char *)0xfe000092, 0x01);
+
+ for(;;); /* Spin until reset happens */
+}
+
+static struct ops sandpoint_ops;
+static struct platform_ops sandpoint_platform_ops;
+
+struct ops *
+platform_init(void *promptr)
+{
+ sandpoint_platform_ops.fixups = sandpoint_fixups;
+ sandpoint_platform_ops.exit = sandpoint_reset;
+
+ sandpoint_ops.platform_ops = &sandpoint_platform_ops;
+ sandpoint_ops.fw_ops = dink_init();
+ sandpoint_ops.dt_ops = fdt_init();
+ sandpoint_ops.console_ops = ns16550_init();
+
+ return &sandpoint_ops;
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 0000000..91d6e91
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,90 @@
+/*
+ * Generic serial console support
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Code in serial_edit_cmdline() copied from arch/ppc/boot/simple/misc.c
+ * and was written by Matt Porter <mporter@kernel.crashing.org>.
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+extern void udelay(long delay);
+
+int
+serial_open(void)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+ return scdp->open();
+}
+
+void
+serial_write(char *buf, int len)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+
+ while (*buf != '\0')
+ scdp->putc(*buf++);
+}
+
+void
+serial_edit_cmdline(char *buf, int len)
+{
+ int timer = 0, count;
+ char ch, *cp;
+ struct serial_console_data *scdp = ops->console_ops->data;
+
+ cp = buf;
+ count = strlen(buf);
+ cp = &buf[count];
+ count++;
+
+ while (timer++ < 5*1000) {
+ if (scdp->tstc()) {
+ while ((ch = scdp->getc()) != '\n' && ch != '\r') {
+ /* Test for backspace/delete */
+ if (ch == '\b' || ch == '\177') {
+ if (cp != buf) {
+ cp--;
+ count--;
+ printf("\b \b");
+ }
+ /* Test for ^x/^u (and wipe the line) */
+ } else if (ch == '\030' || ch == '\025') {
+ while (cp != buf) {
+ cp--;
+ count--;
+ printf("\b \b");
+ }
+ } else if (count < len) {
+ *cp++ = ch;
+ count++;
+ scdp->putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+}
+
+void
+serial_close(void)
+{
+ struct serial_console_data *scdp = ops->console_ops->data;
+
+ if (scdp->close)
+ scdp->close();
+}
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index b5aa522..7ccc504 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -10,7 +10,7 @@ #include <stdarg.h>
#include <stddef.h>
#include "string.h"
#include "stdio.h"
-#include "prom.h"
+#include "ops.h"
size_t strnlen(const char * s, size_t count)
{
@@ -320,6 +320,6 @@ printf(const char *fmt, ...)
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
- write(stdout, sprint_buf, n);
+ ops->console_ops->write(sprint_buf, n);
return n;
}
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
new file mode 100644
index 0000000..2a2fa2b
--- /dev/null
+++ b/arch/powerpc/boot/types.h
@@ -0,0 +1,29 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#define COMMAND_LINE_SIZE 512
+#define MAX_PATH_LEN 256
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+#ifdef __powerpc64__
+typedef unsigned long u64;
+#else
+typedef unsigned long long u64;
+#endif
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
+#endif /* _TYPES_H_ */
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644
index 0000000..c86d3ba
--- /dev/null
+++ b/arch/powerpc/boot/util.S
@@ -0,0 +1,101 @@
+/*
+ * Copied from arch/powerpc/kernel/misc_32.S
+ *
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * 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 "ppc_asm.h"
+
+#define SPRN_PVR 0x11F /* Processor Version Register */
+
+ .text
+/*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+ */
+ .globl _nmask_and_or_msr
+_nmask_and_or_msr:
+ mfmsr r0 /* Get current msr */
+ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
+ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
+ SYNC /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ isync
+ blr /* Done */
+
+/* udelay (on non-601 processors) needs to know the period of the
+ * timebase in nanoseconds. This used to be hardcoded to be 60ns
+ * (period of 66MHz/4). Now a variable is used that is initialized to
+ * 60 for backward compatibility, but it can be overridden as necessary
+ * with code something like this:
+ * extern unsigned long timebase_period_ns;
+ * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ */
+ .data
+ .globl timebase_period_ns
+timebase_period_ns:
+ .long 60
+
+ .text
+/*
+ * Delay for a number of microseconds
+ */
+ .globl udelay
+udelay:
+ mfspr r4,SPRN_PVR
+ srwi r4,r4,16
+ cmpwi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ /* Change r4 to be the number of ticks using:
+ * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
+ * timebase_period_ns defaults to 60 (16.6MHz) */
+ mflr r5
+ bl 0f
+0: mflr r6
+ mtlr r5
+ lis r5,0b@ha
+ addi r5,r5,0b@l
+ subf r5,r5,r6 /* In case we're relocated */
+ addis r5,r5,timebase_period_ns@ha
+ lwz r5,timebase_period_ns@l(r5)
+ add r4,r4,r5
+ addi r4,r4,-1
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmpw 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmpw 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmpw 0,r6,r9
+ blt 2b
+3: blr
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-05-23 0:58 ` Mark A. Greer
2006-05-23 1:13 ` Tom Rini
@ 2006-07-19 20:02 ` Guennadi Liakhovetski
2006-07-19 22:10 ` Mark A. Greer
1 sibling, 1 reply; 17+ messages in thread
From: Guennadi Liakhovetski @ 2006-07-19 20:02 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
Mark, Ben,
On Mon, 22 May 2006, Mark A. Greer wrote:
> Thanks for your time, Ben. Sorry for taking so long to get back to you.
don't have much to comment to specific points, but quoting the entire
discussion below in case you'll want to further add to it.
What's the status of this work? Mark, have you been further working on
your port? I'd like to integrate kurobox/linkstation support with
sandpoint (also 8241). I think, it would be very interesting as it would
allow us to develop / test the "universal" kernel idea, and at the same
time explore the limits of board-specific support. Kurobox have a couple
of very nice "specialities", like a serially attached AVR acting as a
power-manager, thus requiring __special__ halt and reboot callbacks (so,
please, Ben, don't remove them).
Any progress with fdt-parsing library for the wrapper / kernel and with
replacing hard-coded constants and tables with dt-entries?
I'd love to discuss the stuff and come to an acceptable design / APIs.
Thanks
Guennadi
> For the record, this patch was only a hack that I've done to get a sandpoint
> up ASAP. I should have made it clear to not take Kconfig, etc. stuffs very
> seriously. I was more worried about how we should fit flattened dt into the
> bootwrapper.
>
> I'm glad you did look at it so closely though and bring up a lot of good
> questions. I'm not familiar with 64-bit platforms so all of my babbling
> below is based on my 32-bit platform knowledge.
>
> Mark
> ---
>
> On Thu, May 18, 2006 at 03:32:55PM +1000, Benjamin Herrenschmidt wrote:
> > On Wed, 2006-05-17 at 17:21 -0700, Mark A. Greer wrote:
>
> <snip>
>
> > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > > index 6729c98..de09eac 100644
> > > --- a/arch/powerpc/Kconfig
> > > +++ b/arch/powerpc/Kconfig
> > > @@ -323,7 +323,10 @@ config PPC_ISERIES
> > >
> > > config EMBEDDED6xx
> > > bool "Embedded 6xx/7xx/7xxx-based board"
> > > - depends on PPC32 && BROKEN
> > > + depends on PPC32
> > > + select PPC_UDBG_16550
> > > + select MPIC
> > > + select MPIC_SERIAL
> >
> > Not totally related to your patch but I'm tempted to turn that into a
> > "Generic 6xx/7xx/7xxx" rather than "embedded" if we manage to always
> > avoid board specific code most of the time, but instead add necessary
> > bits in the device-tree. We still need a per-board Kconfig option I
> > think that will just select the necessary bits and pieces (and more than
> > one can be selected at one time). Also, I think right now, the embedded
> > stuff is +/- exclusive from the MULTIPLATFORM stuff, that must be fixed
> > asap. We are all living in the same kernel now :)
>
> OK.
>
> > > +
> > > +config MPIC_SERIAL
> > > + depends on EMBEDDED6xx
> > > + bool
> > > + default n
> >
> > Not sure what the above is, I'll have a look further in the patch but I
> > can already tell you that it should be your per-board
> > CONFIG_PPC_SANDPOINT for example that "selects" the various bits you
> > need, and thus the above should depend on it, not EMBEDDED6xx... In fact
> > I'm wondering wether we should kill EMBEDDED6xx :) Unless it's purely a
> > reference to arch/powerpc/platforms/embedded6xx/ as a storage place for
> > board setup_xxx.c files which is useful for platforms that really don't
> > need more than one or 2 files in there.
>
> I have no attachment to "embedded" so I'm happy to see it
> go...especially if I correctly understand what you're saying below.
>
> > > +ifeq ($(CONFIG_EMBEDDED6xx),y)
> > > +src-boot += prom_embedded.c ns16550.c dts/sandpoint.S \
> > > + dt_utils.c sandpoint.c mpc10x.c
> > > +else
> > > +src-boot += prom.c
> > > +endif
> >
> > Again, I think CONFIG_EMBEDDED6xx is the wrong approach. I'd like to
> > avoid the word "embedded" altogether anyway :) Thing is, it would be
> > good if ultimately, embedded boards firmware was capable of passing a
> > device-tree. Thus, embedded a device-tree in the zImage wrapper is more
> > like a "fallback" solution which has the side effect of creating machine
> > specific zImage's.
> >
> > That is why, I think, what we should do is have rules for building
> > separate zImage wrappers. The basic OF one (which exists in both real
> > and virtual mode versions and that I'd like to make capable of also
> > working if a flat device-tree is passed in), the zImage.sandpoint, the
> > zImage.prep, and whatever...
> >
> > Thus enabling CONFIG_PPC_MYBOARD should trigger the build of the
> > board-flavored version of the wrapper in addition to all the other ones
> > for the other boards built as part of a given config.
> >
> > I know it's a bit difficult because the current boot Kbuild rules aren't
> > really design for multiple targets but I think that's the way to go.
>
> Okay, to make sure I understand, you're saying that you want to support a
> .config file having several CONFIG_PPC_BOARD1, CONFIG_PPC_BOARD2,
> CONFIG_PPC_BOARD3 defined at the same time. The resulting zImage would
> run on all 3 boards, right?
>
> I'd be happy with that. It should meet the requirements of both
> the multiplatform and embedded folks. You could combine that with the
> tool paulus talked about a couple weeks ago which would tack the
> appropriate flattened device tree (fdt) onto the zImage after the fact.
>
> http://ozlabs.org/pipermail/linuxppc-dev/2006-April/022435.html
>
> We just need to come up with the tool and make the bootwrapper code
> smart enough to know what dt to use (an OF dt, an fdt from a firmware, a
> fdt tacked on by the tool (along with code to take bd stuff & put it
> into the fdt?)).
>
> All of the boards would likely have to be of the same "class".
> Where "class" would be:
> 1) OF system
> 2) e300 core + PQIIPro (e.g., 83xx)
> 3) e500 core + PQIII (e.g., 85xx)
> 4) 6xx/7xx/74xx + mpc10x (e.g., sandpoint)
> etc. Something like that, anyway--maybe there are only "OF" and
> "non-OF'?
>
> Basically, if its not OF, then its classified by its core + bridge.
>
> So, first thing the zImage does is look for an attached ftb (attached by
> paulus' tool). If its there, use it. If its not there, use either the
> OFDT (for OF class) or expect a dt to be passed in from the firmware (for
> all the other classes). That way you can easily override the dt in the field.
>
> > .../...
> >
> > About the .dts file, we should look into "shipping" a pre-built one so
> > that dtc is not required for building a kernel.
>
> Okay, paulus' tool would allow that. We should also make it smart
> enough to replace an attached dts (really dtb--'b' for 'binary') with
> a new one.
>
> > I think we already have
> > a mecanism for providing "shipped" versions of files and having the
> > option of rebuilding them from source (though I don't have the details
> > in mind at the moment)
>
> I don't know what you're referring to here.
>
> > > diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
> >
> > .../.. io stuffs ...
> >
> > Well... io accessors in here can't harm, the question is more how they
> > are used ;)
> >
> > > +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
> > > +
> > > +/* Indirect PCI config space access routines */
> > > +static inline void
> > > +pci_indirect_read_config_byte(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > > + int offset, u8 *val)
> > > +{
> > > + out_be32(cfg_addr,
> > > + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > > + *val = in_8((u8 *)(cfg_data + (offset & 3)));
> > > + return;
> > > +}
> > > +
> > > +static inline void
> > > +pci_indirect_read_config_dword(u32 *cfg_addr, u32 *cfg_data, int devfn,
> > > + int offset, u32 *val)
> > > +{
> > > + out_be32(cfg_addr,
> > > + ((offset & 0xfc) << 24) | (devfn << 16) | (0 << 8) | 0x80);
> > > + *val = in_le32(cfg_data + (offset & 3));
> > > + return;
> > > +}
> >
> > That's more annoying... if we start having PCI config space access in
> > the boot wrapper how far will it stop ? I'd rather keep that sort of
> > stuff local to myboard.c file unless it's really worth sharing... Unless
> > we end up with really common need for them in which case those should be
> > in separate files, possibly in a separate dir (thinking about it, prep
> > will probably need that too)
>
> Sure. I was just grabbing code I needed and sticking it whereever to
> get things to work. If mpc10x.c is the only one that uses those routines
> then they should be in that file only.
>
> > The main problem is how do we do printf kind of things from such a
> > bootloader. That needs IO, thus uart drivers etc... possibly parsing
> > from the device-tree etc... I'm tempted to just have a global
> > "boot_puts" function pointer set by the board and/or OF code to use
> > through the bootloader, maybe a shared uart.c file with various uart
> > bits and keep the gory implementation details of mapping the uart and
> > using those uart bits in the myboard.c file...
>
> Okay.
>
> Question: are we still going to allow cmdline editing in the
> bootwrapper? If so, we also need to get uart input and munge the dtb
> to put the new args back into the /chosen/bootargs field.
>
> > > +#ifdef CONFIG_PPC_OF
> > > typedef void (*kernel_entry_t)( unsigned long,
> > > unsigned long,
> > > void *,
> > > void *);
> > > +#else
> > > +void platform_fixups(void *dt_blob);
> > > +extern void *dt_blob_start;
> > > +extern void *dt_blob_end;
> > > +void edit_cmdline(void *dt_blob_start);
> > > +typedef void (*kernel_entry_t)(void *dtb_addr, void *kernel_entry_paddr,
> > > + void *must_be_null);
> > > +#endif
> >
> > Why 2 different prototypes for kernel_entry ?
>
> One for "OF", one for "non-OF" but I'll change it to
> "typedef void (*kernel_entry_t)(void *addr, ...);"
> to support both. Hrm, I may have another idea... Anyway, I'll do
> something about the #ifdef.
>
> > I think we need something like CONFIG_PPC_BOOT_HAS_BUILTIN_DT that
> > enables various DT related stuff in a clean way and have a builtin_dt.h
> > file with related prototypes & definitions.
>
> If we have the tool mentioned above, we shouldn't need a CONFIG option.
> Just check for a NULL ptr or something like that which indicates there's
> no dtb attached.
>
> > > #undef DEBUG
> > > @@ -218,7 +227,7 @@ void start(unsigned long a1, unsigned lo
> > > if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
> > > exit();
> > >
> > > - printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
> > > + printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start,sp);
> >
> > Gratuituous uglyfication :)
>
> Again, I was just hacking stuff...
>
> <snip>
>
> > >
> > > /* Eventually gunzip the kernel */
> > > @@ -299,6 +311,7 @@ #endif
> > > flush_cache((void *)vmlinux.addr, vmlinux.size);
> > >
> > > kernel_entry = (kernel_entry_t)vmlinux.addr;
> > > +#ifdef CONFIG_PPC_OF
> > > #ifdef DEBUG
> > > printf( "kernel:\n\r"
> > > " entry addr = 0x%lx\n\r"
> > > @@ -311,9 +324,20 @@ #ifdef DEBUG
> > > #endif
> >
> > > kernel_entry(a1, a2, prom, NULL);
> > > +#else /* !CONFIG_PPC_OF ==> flattened device tree */
> > > +#ifdef DEBUG
> > > + printf("kernel:\n\r"
> > > + " entry addr = 0x%lx\n\r"
> > > + " flattened dt = 0x%lx\n\r",
> > > + (unsigned long)kernel_entry, &dt_blob_start);
> > > +#endif
> > > + edit_cmdline(&dt_blob_start);
> > > + platform_fixups(&dt_blob_start);
> > >
> > > + kernel_entry(&dt_blob_start, (void *)vmlinux.addr, NULL);
> > > +#endif
> >
> > Let's avoid #ifdef's if we can... provide function pointers where it
> > matter setup by the board/OF init code maybe but not ifdef's. Afaik,
> > only WD actually _likes_ ifdef's :)
>
> I'll fix it up.
>
> > > +++ b/arch/powerpc/boot/mpc10x.c
> >
> > We'll need some subdirs here or it will get messy quick...
>
> Yep.
>
> > > diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
> >
> > Same comment as above
> >
> > > +/* XXXX Get info from dt instead */
> > > +static struct {
> > > + int baud_base;
> > > + unsigned long com_port;
> > > + u16 iomem_reg_shift;
> > > +} rs_table[RS_TABLE_SIZE] = {
> > > + { BASE_BAUD, SANDPOINT_SERIAL_0, 0 },
> > > + { BASE_BAUD, SANDPOINT_SERIAL_1, 0 },
> > > +};
> >
> > Well, your own comment says it all :) I think we might need an
> > equivalent of prom_parse.c in the bootloader
>
> Yes, this was just a hack to get the sandpoint going.
>
> > +
> > > +/* #ifndef CONFIG_PPC_OF XXXX */
> > > +
> > > +/* Definitions used by the flattened device tree */
> > > +#define OF_DT_HEADER 0xd00dfeed /* marker */
> > > +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
> > > +#define OF_DT_END_NODE 0x2 /* End node */
> > > +#define OF_DT_PROP 0x3 /* Property: name off, size,
> > > + * content */
> > > +#define OF_DT_NOP 0x4 /* nop */
> > > +#define OF_DT_END 0x9
> > > +
> > > +#define OF_DT_VERSION 0x10
> >
> > .../... (flat DT definitions)
> >
> > Can't we share the kernel definition here ? Maybe split the kenrel one
> > in two if necessary ? I don't like that sort of duplication...
>
> I hope so. I'm hoping we can make a special dir somewhere that has the
> definitions of stuff shared between the bootwrapper & the kernel.
>
> How about arch/powerpc/shared? I dunno, something sensible.
>
> > > +unsigned long serial_init(int chan, void *ignored);
> > > +void serial_putc(unsigned long com_port, unsigned char c);
> > > +unsigned char serial_getc(unsigned long com_port);
> > > +int serial_tstc(unsigned long com_port);
> >
> > Forgot to mention that earlier, but those should be uart_* imho (or even
> > 16550_*) since we'll surely have different species of serial ports to
> > deal with and I don't like name mixup. Unless we consider that only ever
> > one of those serial files get built in a given zImage wrapper in which
> > case it makes some sense...
>
> Okay.
>
> > > +call_prom(const char *service, int nargs, int nret, ...)
> > > +{
> > > +
> > > + static struct {
> > > + char *service;
> > > + int ((*rtn)(int nargs, int nret, va_list args));
> > > + } services[] = {
> > > + { "exit", service_exit },
> > > + { "finddevice", service_finddevice },
> > > + { "getprop", service_getprop },
> > > + /* { "write", service_write }, */
> > > + };
> > > + va_list args;
> > > + int i, rc = 0;
> > > +
> > > + for (i=0; i<ARRAY_SIZE(services); i++)
> > > + if (!strcmp(service, services[i].service)) {
> > > + va_start(args, nret);
> > > + rc = services[i].rtn(nargs, nret, args);
> > > + va_end(args);
> > > + }
> > > +
> > > + return (nret > 0)? rc : 0;
> > > +}
> >
> > I don't think call_prom is the right abstraction :) We have to decide
> > here, we have two choices:
> >
> > - Either a given zImage wrapper can be booted from both a real OF and
> > have an embedded flat DT, in which case we need function pointers and I
> > think the right abstraction is for individual prom functions to have
> > their function pointer rathaer than "multiplex" through call_prom
> >
> > - Or a given zImage wrapper is a single board thingy. That is it is
> > either the OF wrapper _or_ it can contain an embedded DT. Probably
> > easier that way and no need for funciton pointers nor mux at all... I
> > tend to think that might be the right way to go at this point...
> > Especially since as I wrote before, I'm tempted to think we should just
> > in that case build multiple zImage wrappers. The only thing there is
> > that if we go that route, I'd like the "OF" one to also be able to boot
> > with a flat DT passed on entry to it so it will be useable as a generic
> > zImage for firmwares that have a flat DT to pass to the kernel. The only
> > "issue" with that is it might be difficult to have console output unless
> > we do the putc function pointer thing I described earlier and have
> > several "uart" impleentations with differnet names and enough
> > device-tree parsing to be able to instanciate them (almost a copy of
> > kernel's legacy serial stuff). Another option if we want console output
> > is to add something to the DT header specifically for use by such early
> > boot code that specifies a function that can be called back for
> > displaying thing as long as a given memory range isn't overriden (the FW
> > itself)
> >
> > Comments are welcome here, this is I think the most tricky point and
> > where we need to make a decision...
>
> I'm very happy to not use the 'call_prom' abstraction. :)
>
> I guess I have the first one in mind. You have a zImage that runs on
> 1 to n different platforms. The zImage has to determine which DT to use
> (OF DT, fdt from firmware, fdt attached by tool) and pick it apart to
> find the I/O resources and serial driver to use. The CONFIG_<BOARD>'s
> that are defined would determine the drivers that get built in to the zImage.
>
> > > diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
> > > index 6e67b5b..2feca55 100644
> > > --- a/arch/powerpc/kernel/legacy_serial.c
> > > +++ b/arch/powerpc/kernel/legacy_serial.c
> > > @@ -147,9 +147,11 @@ static int __init add_legacy_isa_port(st
> > > if (reg == NULL)
> > > return -1;
> > >
> > > +#if 0 /* XXXX */
> > > /* Verify it's an IO port, we don't support anything else */
> > > if (!(reg[0] & 0x00000001))
> > > return -1;
> > > +#endif
> >
> > Gack ? Care to explain ?
>
> This 'if' always executed and threw me into the weeds. I didn't get
> back to really figuring it out. This was a hack to get going.
>
> > > +obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
> >
> > Hrmph.... (random noises)
>
> ? No, I needed that to get the build to go into platforms/embedded6xx.
> Since platforms/embedded6xx was already there, I assumed that was where
> I was to put things like the sandpoint. If/when we get rid of
> "embedded", I'll move it to whereever it should go then.
>
> > > +/*
> > > + * Define all of the IRQ senses and polarities. Taken from the
> > > + * Sandpoint X3 User's manual.
> > > + */
> > > +static u_char sandpoint_openpic_initsenses[] __initdata = {
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 1: XXXX FILL?? */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 6: XXXX FILL?? */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 7: XXXX FILL?? */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 9: IDE (INT D) */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 10: */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 11: */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 12: */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 13: */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 14: */
> > > + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 15: */
> > > +};
> >
> > Of course you already know that this has to go into the device-tree :)
>
> Yeah, I guess it should. I'll have to figure out how to do that.
>
> > > +/*
> > > + * Interrupt setup and service. Interrrupts on the Sandpoint come
> > > + * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
> > > + * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
> > > + * IDE is on EPIC 7 and 8.
> > > + */
> > > +static void __init
> > > +sandpoint_init_IRQ(void)
> > > +{
> > > + struct mpic *mpic;
> > > + phys_addr_t openpic_paddr = 0xfc000000 + /* XXXX */
> > > + MPC10X_EUMB_EPIC_OFFSET;
> > > +
> > > + /* This doesn't handle i2c, dma, i2o, or timer intrs right now XXXX */
> > > + mpic = mpic_alloc(openpic_paddr, MPIC_PRIMARY,
> > > + 16 /* XXXX otherwise num_sources used */ ,
> > > + NUM_8259_INTERRUPTS,
> > > + 0, /* was 16 */
> > > + NR_IRQS - 4 /* XXXX */,
> > > + sandpoint_openpic_initsenses,
> > > + sizeof(sandpoint_openpic_initsenses), " EPIC ");
> > > +
> > > + BUG_ON(mpic == NULL); /* XXXX */
> > > + mpic_assign_isu(mpic, 0, openpic_paddr + 0x10200);
> > > + mpic_init(mpic);
> > > + mpic_setup_cascade(NUM_8259_INTERRUPTS, i8259_irq_cascade, NULL);
> > > + i8259_init(0xfef00000, 0); /* pci iack addr */
> > > +}
> >
> > It would be really nice if we could define properties to put in the
> > "mpic" node that defines the various attributes to pass to it and that
> > sort of thing so that we can have a generic "mpic_init_IRQ" that walks
> > all MPICs and instanciate & link them in cascade when necessary... Oh
> > well, food for thought, no high priority there.
>
> That would be great to have!
>
> > > +/*
> > > + * Freescale Sandpoint interrupt routing.
> > > + */
> > > +static inline int
> > > +x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
> > > +{
> > > + static char pci_irq_table[][4] =
> > > + /*
> > > + * PCI IDSEL/INTPIN->INTLINE
> > > + * A B C D
> > > + */
> > > + {
> > > + { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
> > > + { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
> > > + { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
> > > + { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
> > > + { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
> > > + { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
> > > + };
> > > +
> > > + const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
> > > + return PCI_IRQ_TABLE_LOOKUP;
> > > +}
> >
> > Of course you also know that the above has to go into the device-tree as
> > well :)
>
> Okay... :)
>
> > > +static void __init
> > > +sandpoint_setup_winbond_83553(struct pci_controller *hose)
> > > +{
> > > + int devfn;
> > > +
> > > + /*
> > > + * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
> > > + * We can't route the IDE interrupt to PCI INTC# or INTD# because those
> > > + * woule interfere with the PMC's INTC# and INTD# lines.
> > > + */
> > > + /*
> > > + * Winbond Fcn 0
> > > + */
> > > + devfn = PCI_DEVFN(11,0);
> > > +
> > > + early_write_config_byte(hose,
> > > + 0,
> > > + devfn,
> > > + 0x43, /* IDE Interrupt Routing Control */
> > > + 0xef);
> > > + early_write_config_word(hose,
> > > + 0,
> > > + devfn,
> > > + 0x44, /* PCI Interrupt Routing Control */
> > > + 0x0000);
> > > +
> > > + /* Want ISA memory cycles to be forwarded to PCI bus */
> > > + early_write_config_byte(hose,
> > > + 0,
> > > + devfn,
> > > + 0x48, /* ISA-to-PCI Addr Decoder Control */
> > > + 0xf0);
> > > +
> > > + /* Enable Port 92. */
> > > + early_write_config_byte(hose,
> > > + 0,
> > > + devfn,
> > > + 0x4e, /* AT System Control Register */
> > > + 0x06);
> > > + /*
> > > + * Winbond Fcn 1
> > > + */
> > > + devfn = PCI_DEVFN(11,1);
> > > +
> > > + /* Put IDE controller into native mode. */
> > > + early_write_config_byte(hose,
> > > + 0,
> > > + devfn,
> > > + 0x09, /* Programming interface Register */
> > > + 0x8f);
> > > +
> > > + /* Init IRQ routing, enable both ports, disable fast 16 */
> > > + early_write_config_dword(hose,
> > > + 0,
> > > + devfn,
> > > + 0x40, /* IDE Control/Status Register */
> > > + 0x00ff0011);
> > > + return;
> > > +}
> >
> > How much of the above could/should be done by the wrapper since it does
> > config space access hacks ? My idea is that we might be able to remove
> > pretty much _everything_ from this sandpoint.c file ... My dream would
> > be to have a generic board support that matches a list of known boards
> > for which no special code is needed, only the device-tree (and possibly
> > the zImage wrapper).
>
> That's a good dream. :)
>
> > The main things preventing us from doing that at the moment is that we
> > need to define enough standard nodes/properties to have the ability to
> > the setup interrupt controller tree entirely from it, and the PCI host
> > bridges as well. For the later, that means encoding enough of the bridge
> > type and config access method to allow having a generic device-tree
> > based piece of code that does what add_bridges() does in a generic way.
>
> Yep.
>
> > > +static int
> > > +x3_exclude_device(u_char bus, u_char devfn)
> > > +{
> > > + if ((bus == 0) && (PCI_SLOT(devfn) == 0))
> > > + return PCIBIOS_DEVICE_NOT_FOUND;
> > > + else
> > > + return PCIBIOS_SUCCESSFUL;
> > > +}
> >
> > If we need to exclude devices in a generic way, we could define a
> > specific exclude list property... or use what I think has already been
> > defined by OF for indicating which slots should be probed :)
>
> I'll try to do it through pci quirks, if I can. If not, then I agree.
>
> > > +static int __init
> > > +add_bridge(struct device_node *dev)
> > > +{
> > > + int len;
> > > + struct pci_controller *hose;
> > > + int *bus_range;
> > > +
> > > + printk("Adding PCI host bridge %s\n", dev->full_name);
> > > +
> > > + bus_range = (int *) get_property(dev, "bus-range", &len);
> > > + if (bus_range == NULL || len < 2 * sizeof(int))
> > > + printk(KERN_WARNING "Can't get bus-range for %s, assume"
> > > + " bus 0\n", dev->full_name);
> > > +
> > > + hose = pcibios_alloc_controller();
> > > + if (hose == NULL)
> > > + return -ENOMEM;
> > > + hose->first_busno = bus_range ? bus_range[0] : 0;
> > > + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> > > + setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
> > > +
> > > + /* Interpret the "ranges" property */
> > > + /* This also maps the I/O region and sets isa_io/mem_base */
> > > + pci_process_bridge_OF_ranges(hose, dev, 1);
> > > +
> > > + return 0;
> > > +}
> >
> > See above comments.... Looks ok but how many boards will end up having
> > very small variations of that same code and thus can we find a way to
> > make that totally generic...
>
> Many...
>
> > > +u32 mag_dbg = 0;
> > > +
> > > +static void __init
> > > +sandpoint_setup_arch(void)
> > > +{
> > > + loops_per_jiffy = 100000000 / HZ;
> > > + isa_io_base = 0xfe000000;
> > > + isa_mem_base = 0x80000000;
> > > + pci_dram_offset = 0;
> >
> > The isa stuff should probably be deduced from the device-tree, the
> > default LPJ too, probably not even useful anymore since we are using the
> > timebase nowadays.
>
> Okay.
>
> > > +#ifdef CONFIG_BLK_DEV_INITRD
> > > + if (initrd_start)
> > > + ROOT_DEV = Root_RAM0;
> > > + else
> > > +#endif
> > > +#ifdef CONFIG_ROOT_NFS
> > > + ROOT_DEV = Root_NFS;
> > > +#else
> > > + ROOT_DEV = Root_HDA1;
> > > +#endif
> >
> > Same comment as above, this is fairly generic and we could even imagine
> > something like a linux,default-boot-device thing in the DT...
>
> OK.
>
> > > +#if 1 /* XXXX NEW */
> > > + {
> > > + struct device_node *np;
> > > +
> > > + mag_dbg = 1;
> > > + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> > > + add_bridge(np);
> > > + mag_dbg = 0;
> > > +
> > > + ppc_md.pci_swizzle = common_swizzle;
> > > + ppc_md.pci_map_irq = x3_map_irq;
> > > + ppc_md.pci_exclude_device = x3_exclude_device; /* XXXX */
> > > + }
> > > +#endif
> >
> > The problem of IRQ mapping & swizzling will be solved real soon
> > (hopefully early 2.6.18) so that we can completely rely on the
> > device-tree without needing device_node's for every PCI device. Only P2P
> > bridges that don't do standard swizzling (typically bridges soldered on
> > the motherboard) will require device nodes. I'm working on it :)
> >
> > The idea is that the host bridge will need the standard interrupt-map &
> > interrupt-map-mask which will indicate the interrupt mapping for every
> > line of every slot/device in the standard way handled by OF (that
> > already works). And I'll add code that will be able to handle PCI
> > devices without a node by artificially building their "interrupts"
> > property based on the interrupt pin config space entry and walking up
> > the PCI tree, doing standard swizzling when encountering a P2P bridge
> > until we hit something with a device-node in which case we hook our
> > result to the interrupt-map of that device-node.
>
> Cool. I'll keep an eye out for that.
>
> > > + if (cpu_has_feature(CPU_FTR_SPEC7450))
> > > + /* 745x is different. We only want to pass along enable. */
> > > + _set_L2CR(L2CR_L2E);
> > > + else if (cpu_has_feature(CPU_FTR_L2CR))
> > > + /* All modules have 1MB of L2. We also assume that an
> > > + * L2 divisor of 3 will work.
> > > + */
> > > + _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
> > > + | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
> >
> > Keeping in mind my idea of having as much generic code as possible,
> > whould we do the above in the boot wrapper or if not, should we provide
> > some DT entries indicating that L2CR should be reset and to which
> > values ?
>
> I vote for a DT entry.
>
> > > +#if 0
> > > + /* Untested right now. */
> > > + if (cpu_has_feature(CPU_FTR_L3CR)) {
> > > + /* Magic value. */
> > > + _set_L3CR(0x8f032000);
> > > + }
> > > +#endif
> > > +}
> >
> > Same comment as above but for L3CR
>
> DT entry. :)
>
> > .../...
> >
> > > +/*
> > > + * Fix IDE interrupts.
> > > + */
> > > +static int __init
> > > +sandpoint_fix_winbond_83553(void)
> > > +{
> > > + /* Make some 8259 interrupt level sensitive */
> > > + outb(0xe0, 0x4d0);
> > > + outb(0xde, 0x4d1);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +arch_initcall(sandpoint_fix_winbond_83553);
> > > +
> > > +/*
> > > + * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
> > > + */
> > > +static int __init
> > > +sandpoint_setup_natl_87308(void)
> > > +{
> > > + u_char reg;
> > > +
> > > + /*
> > > + * Enable all the devices on the Super I/O chip.
> > > + */
> > > + SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
> > > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
> > > + SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
> > > + SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
> > > + SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
> > > + SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
> > > + SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
> > > + SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
> > > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > > + SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
> > > + SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
> > > +
> > > + /* Set up floppy in PS/2 mode */
> > > + outb(0x09, SIO_CONFIG_RA);
> > > + reg = inb(SIO_CONFIG_RD);
> > > + reg = (reg & 0x3F) | 0x40;
> > > + outb(reg, SIO_CONFIG_RD);
> > > + outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
> > > +
> > > + return 0;
> > > +}
> >
> > Looks like zImage wrapper work to me... Unless we ever get booted by a
> > firmware that both provides a flat DT and doesn't do the above....
> >
> > Ok, I'm not _ABSOLUTELY_ trying to remove the need for a myboar.c file
> > here ... but it might be worth doing something generic enough so that
> > it's either reduced to the strict minimum in many cases _or_ made
> > completely unnecessary if we can...
>
> OK
>
> > > +arch_initcall(sandpoint_setup_natl_87308);
> > > +
> > > +static int __init
> > > +sandpoint_request_io(void)
> > > +{
> > > + request_region(0x00,0x20,"dma1");
> > > + request_region(0x20,0x20,"pic1");
> > > + request_region(0x40,0x20,"timer");
> > > + request_region(0x80,0x10,"dma page reg");
> > > + request_region(0xa0,0x20,"pic2");
> > > + request_region(0xc0,0x20,"dma2");
> > > +
> > > + return 0;
> > > +}
> >
> > The above has to go... not sure yet what is the best way but it's just a
> > pain... Could be made dependent on the OFDT too
>
> OK
>
> > > +arch_initcall(sandpoint_request_io);
> > > +#endif
> > > +
> > > +static void __init
> > > +sandpoint_map_io(void)
> > > +{
> > > + io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
> > > +}
> >
> > To kill absolutely. What is it there for ? At the very least, make
> > io_block_mapping allocate virtual space as discussed earlier. I'd like
> > to keep BATs for RAM anyway
>
> It'll go away eventually.
>
> > > +static void
> > > +sandpoint_restart(char *cmd)
> > > +{
> > > + local_irq_disable();
> > > +
> > > + /* Set exception prefix high - to the firmware */
> > > + _nmask_and_or_msr(0, MSR_IP);
> > > +
> > > + /* Reset system via Port 92 */
> > > + outb(0x00, 0x92);
> > > + outb(0x01, 0x92);
> > > +
> > > + for(;;); /* Spin until reset happens */
> > > +}
> >
> > The above is fairly common. (Or variations of it). In the context of a
> > "generic" board, we could imagine having a list of known "reboot
> > methods" and have a DT node indicating which one to use...
>
> Yep.
>
> > > +static void
> > > +sandpoint_power_off(void)
> > > +{
> > > + local_irq_disable();
> > > + for(;;); /* No way to shut power off with software */
> > > + /* NOTREACHED */
> > > +}
> >
> > The above is _VERY_ commmon :) probably worth just not having a callback
> > in ppc_md. at all...
> >
> > > +static void
> > > +sandpoint_halt(void)
> > > +{
> > > + sandpoint_power_off();
> > > + /* NOTREACHED */
> > > +}
> >
> > Same comment as before.
>
> I do see a couple in arch/ppc/platforms that do something different so
> how about keeping ppc_md.power_off/_halt but making the above the default
> (with only 1 implementation) which can be changed by board code?
>
> > > +static void
> > > +sandpoint_show_cpuinfo(struct seq_file *m)
> > > +{
> > > + seq_printf(m, "vendor\t\t: Freescale\n");
> > > + seq_printf(m, "machine\t\t: Sandpoint\n");
> > > +}
> >
> > Do we need that ? We could define standard DT properties that get
> > printed in cpuinfo and have that in setup-common.c ...
>
> That would be better.
>
> > .../... (commented out IDE code)
> >
> > This is a windbond ? Can't it just be probed/detected using normal PCI
> > probing ?
>
> I have to revisit all of the IDE stuff in that file and figure out
> what's really needed (if any). That's why I have it all '#if 0' right
> now. I will get to it eventually.
>
> > > +
> > > +/*
> > > + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
> > > + */
> > > +static __inline__ void
> > > +sandpoint_set_bat(void)
> > > +{
> > > + unsigned long bat3u, bat3l;
> > > +
> > > + __asm__ __volatile__(
> > > + " lis %0,0xf800\n \
> > > + ori %1,%0,0x002a\n \
> > > + ori %0,%0,0x0ffe\n \
> > > + mtspr 0x21e,%0\n \
> > > + mtspr 0x21f,%1\n \
> > > + isync\n \
> > > + sync "
> > > + : "=r" (bat3u), "=r" (bat3l));
> > > +}
> >
> > WTF ?
>
> It'll disappear. The sandpoint.c is copied from arch/ppc and hacked.
> Its pretty old so there's lots of code that can probably be weeded out.
>
> > > +TODC_ALLOC();
> > > +
> > > +static int __init
> > > +sandpoint_probe(void)
> > > +{
> > > + return 1;
> > > +}
> >
> > WTF (bis) ? :)
>
> bis?
>
> Its just a hack to get it going.
>
> > > +define_machine(sandpoint) {
> > > + .name = "Sandpoint",
> > > + .probe = sandpoint_probe,
> > > + .setup_arch = sandpoint_setup_arch,
> > > + .setup_io_mappings = sandpoint_map_io,
> > > + .init_IRQ = sandpoint_init_IRQ,
> > > + .show_cpuinfo = sandpoint_show_cpuinfo,
> > > + .get_irq = mpic_get_irq,
> > > + .restart = sandpoint_restart,
> > > + .power_off = sandpoint_power_off,
> > > + .halt = sandpoint_halt,
> > > + .calibrate_decr = generic_calibrate_decr,
> > > + /*
> > > + .progress = udbg_progress,
> > > + */
> > > +};
> >
> > So on the TODO list, replace as much as we can of the above with
> > generic_* equivalents until nothing remains :)
>
> Yep, that's the goal.
>
> > > diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> > > index 7dcdfcb..1badbec 100644
> > > --- a/arch/powerpc/sysdev/mpic.c
> > > +++ b/arch/powerpc/sysdev/mpic.c
> > > @@ -629,6 +629,13 @@ #endif /* CONFIG_SMP */
> > > mb();
> > > }
> > >
> > > +#ifdef CONFIG_MPIC_SERIAL
> > > + /* For serial interrupts & set clock ratio */
> > > + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1,
> > > + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1)
> > > + | (1<<27) | (0x7<<28));
> > > +#endif
> >
> > This should not be an #ifdef.... this should be an MPIC init flag passed
> > when initializing it. (and if we do generic device-tree instanciation of
> > PIC's, we could define standard properties to put in the MPIC node to
> > enable those flags).
>
> Okay, I'll move it into the dt.
>
> > Keep up the good work ! :)
>
> Heh.
>
> > Cheers,
> > Ben.
>
> Thanks for the comments.
>
> Mark
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
---
Guennadi Liakhovetski
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-07-19 20:02 ` Guennadi Liakhovetski
@ 2006-07-19 22:10 ` Mark A. Greer
2006-07-19 22:29 ` Guennadi Liakhovetski
0 siblings, 1 reply; 17+ messages in thread
From: Mark A. Greer @ 2006-07-19 22:10 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: linuxppc-dev
Hi Guennadi,
On Wed, Jul 19, 2006 at 10:02:01PM +0200, Guennadi Liakhovetski wrote:
> Mark, Ben,
>
> On Mon, 22 May 2006, Mark A. Greer wrote:
>
> > Thanks for your time, Ben. Sorry for taking so long to get back to you.
>
> don't have much to comment to specific points, but quoting the entire
> discussion below in case you'll want to further add to it.
Ben and I have talked a little bit privately and the ball is in my court
to produce a set of patches. To that end, I have them ready so expect to
see them shortly.
> What's the status of this work? Mark, have you been further working on
> your port?
Patches to come...
> I'd like to integrate kurobox/linkstation support with
> sandpoint (also 8241). I think, it would be very interesting as it would
> allow us to develop / test the "universal" kernel idea, and at the same
> time explore the limits of board-specific support. Kurobox have a couple
> of very nice "specialities", like a serially attached AVR acting as a
> power-manager, thus requiring __special__ halt and reboot callbacks (so,
> please, Ben, don't remove them).
>
> Any progress with fdt-parsing library for the wrapper / kernel and with
> replacing hard-coded constants and tables with dt-entries?
No real progress with making a library because even though a lot of
functionality is duplicated, most of the kernel code does it on an
internal representation of the fdt and not on the actual fdt. The
bootwrapper code needs to work directly on the fdt so I didn't bother
library-izing it. Once the dust settles, we can library-ize the duplicate
code but for now, its all in arch/powerpc/boot/fdt.c (in my upcoming patches).
> I'd love to discuss the stuff and come to an acceptable design / APIs.
Me too. :)
Mark
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-07-19 22:10 ` Mark A. Greer
@ 2006-07-19 22:29 ` Guennadi Liakhovetski
2006-07-20 0:39 ` Mark A. Greer
0 siblings, 1 reply; 17+ messages in thread
From: Guennadi Liakhovetski @ 2006-07-19 22:29 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
On Wed, 19 Jul 2006, Mark A. Greer wrote:
>
> Ben and I have talked a little bit privately and the ball is in my court
> to produce a set of patches. To that end, I have them ready so expect to
> see them shortly.
Great! So, I can really relax and enjoy my holiday next week in beautiful
Eifel:-) And as your patches arrive we'll see how best to integrate
kurobox with them.
One question so far. Looking at your sandpoint.dts pci map:
ranges = <80000000 80000000 70000000 /* pci mem space */
fc000000 fc000000 00100000 /* EUMB */
fe000000 fe000000 00c00000 /* pci i/o space */
fec00000 fec00000 00300000 /* pci cfg regs */
fef00000 fef00000 00100000>; /* pci iack */
I can match hardware addresses against defines in
include/asm-ppc/mpc10x.h, but virtual one - is the map above just an
example and anyway-not-used, or is it a new mapping, or am I missing
something and it has always been like that (1-to-1)? At least this comment
* MAP B (CHRP Map)
* Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
* Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
* PCI MEM: 0x00000000 -> Processor System Memory: 0x00000000
* EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
seems to contradict with the above map in pci io area, as well as this
one:
* Want processor accesses of 0xFDxxxxxx to be mapped
* to PCI memory space at 0x00000000. Do not want
Actually, I cannot even match these 2 together?
Thanks
Guennadi
---
Guennadi Liakhovetski
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [HACK] add sandpoint + flattened dt support to arch/powerpc/boot
2006-07-19 22:29 ` Guennadi Liakhovetski
@ 2006-07-20 0:39 ` Mark A. Greer
0 siblings, 0 replies; 17+ messages in thread
From: Mark A. Greer @ 2006-07-20 0:39 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: linuxppc-dev
On Thu, Jul 20, 2006 at 12:29:04AM +0200, Guennadi Liakhovetski wrote:
> On Wed, 19 Jul 2006, Mark A. Greer wrote:
> >
> > Ben and I have talked a little bit privately and the ball is in my court
> > to produce a set of patches. To that end, I have them ready so expect to
> > see them shortly.
>
> Great! So, I can really relax and enjoy my holiday next week in beautiful
> Eifel:-) And as your patches arrive we'll see how best to integrate
> kurobox with them.
Okay, but don't be in too much of a rush. I'm sure there will be
comments that will induce changes to those patches.
> One question so far. Looking at your sandpoint.dts pci map:
>
> ranges = <80000000 80000000 70000000 /* pci mem space */
> fc000000 fc000000 00100000 /* EUMB */
> fe000000 fe000000 00c00000 /* pci i/o space */
> fec00000 fec00000 00300000 /* pci cfg regs */
> fef00000 fef00000 00100000>; /* pci iack */
>
> I can match hardware addresses against defines in
> include/asm-ppc/mpc10x.h,
Don't spend a lot of time in ppc, powerpc is where you need to live now.
> but virtual one - is the map above just an
> example and anyway-not-used, or is it a new mapping, or am I missing
> something and it has always been like that (1-to-1)? At least this comment
The above mapping are physical addresses and are a part of the hardware
description passed into the kernel (i.e., the fdt). It knows nothing
about virtual addresses.
> * MAP B (CHRP Map)
> * Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
> * Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
> * PCI MEM: 0x00000000 -> Processor System Memory: 0x00000000
This table is telling you how the hardware maps processor physical
memory space to/from PCI I/O and MEM space. For example, if the
processor reads physical location 0xfe000000 that will go across the
hostbridge and read PCI I/O location/register 0 (assuming there is a
PCI device set to respond to that PCI I/O address). If a PCI device
reads PCI MEM address 0 it will go across the hostbridge and read
address 0 of the processor's physical address space (i.e., system
memory address 0).
> * EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
>
> seems to contradict with the above map in pci io area, as well as this
> one:
>
> * Want processor accesses of 0xFDxxxxxx to be mapped
> * to PCI memory space at 0x00000000. Do not want
>
> Actually, I cannot even match these 2 together?
You need to read the "Address Map B Options Register" section of the
824x or 10x manuals. This is talking about an alias capability of the
hardware that I enabled...but as I think about it, I probably shouldn't
have. 8-P Anyway, if you get confused by a comment, read the code--code
doesn't lie...it may be wrong, but it doesn't lie. ;)
Mark
--
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2006-07-20 0:39 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-18 0:21 [HACK] add sandpoint + flattened dt support to arch/powerpc/boot Mark A. Greer
2006-05-18 5:32 ` Benjamin Herrenschmidt
2006-05-18 13:52 ` Matthew McClintock
2006-05-26 6:03 ` Benjamin Herrenschmidt
2006-05-23 0:58 ` Mark A. Greer
2006-05-23 1:13 ` Tom Rini
2006-07-19 20:02 ` Guennadi Liakhovetski
2006-07-19 22:10 ` Mark A. Greer
2006-07-19 22:29 ` Guennadi Liakhovetski
2006-07-20 0:39 ` Mark A. Greer
2006-06-14 3:37 ` Mark A. Greer
2006-05-18 13:47 ` Matthew McClintock
2006-05-19 0:37 ` Mark A. Greer
2006-05-19 0:49 ` Michael Ellerman
2006-05-22 22:22 ` Tom Rini
2006-06-05 20:41 ` Matthew McClintock
2006-06-05 21:04 ` Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).