All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
@ 2010-01-28 12:16 Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
                   ` (17 more replies)
  0 siblings, 18 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 include/asm-sparc/unaligned.h |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
 create mode 100644 include/asm-sparc/unaligned.h

diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
new file mode 100644
index 0000000..4e604c1
--- /dev/null
+++ b/include/asm-sparc/unaligned.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_SPARC_UNALIGNED_H
+#define _ASM_SPARC_UNALIGNED_H
+
+#ifdef __KERNEL__
+
+/*
+ * The SPARC can not do unaligned accesses, it must be split into multiple
+ * byte accesses. The SPARC is in big endian mode.
+ */
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned	__get_unaligned_be
+#define put_unaligned	__put_unaligned_be
+
+#endif	/* __KERNEL__ */
+#endif	/* _ASM_SPARC_UNALIGNED_H */
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 03/17] GRETH: Added extra RESET, this is needed if GRETH was stopped during an ethernet frame reception Daniel Hellstrom
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 drivers/net/greth.c |   69 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 79bc4d9..833915d 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -45,7 +45,7 @@
 /* ByPass Cache when reading regs */
 #define GRETH_REGLOAD(addr)		SPARC_NOCACHE_READ(addr)
 /* Write-through cache ==> no bypassing needed on writes */
-#define GRETH_REGSAVE(addr,data)	(*(unsigned int *)(addr) = (data))
+#define GRETH_REGSAVE(addr,data) (*(volatile unsigned int *)(addr) = (data))
 #define GRETH_REGORIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)|data)
 #define GRETH_REGANDIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)&data)
 
@@ -102,12 +102,12 @@ typedef struct {
 } greth_priv;
 
 /* Read MII register 'addr' from core 'regs' */
-static int read_mii(int addr, volatile greth_regs * regs)
+static int read_mii(int phyaddr, int regaddr, volatile greth_regs * regs)
 {
 	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 	}
 
-	GRETH_REGSAVE(&regs->mdio, (0 << 11) | ((addr & 0x1F) << 6) | 2);
+	GRETH_REGSAVE(&regs->mdio, ((phyaddr & 0x1F) << 11) | ((regaddr & 0x1F) << 6) | 2);
 
 	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 	}
@@ -119,14 +119,14 @@ static int read_mii(int addr, volatile greth_regs * regs)
 	}
 }
 
-static void write_mii(int addr, int data, volatile greth_regs * regs)
+static void write_mii(int phyaddr, int regaddr, int data, volatile greth_regs * regs)
 {
 	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 	}
 
 	GRETH_REGSAVE(&regs->mdio,
-		      ((data & 0xFFFF) << 16) | (0 << 11) | ((addr & 0x1F) << 6)
-		      | 1);
+		      ((data & 0xFFFF) << 16) | ((phyaddr & 0x1F) << 11) | 
+		      ((regaddr & 0x1F) << 6) | 1);
 
 	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 	}
@@ -146,8 +146,6 @@ int greth_init(struct eth_device *dev, bd_t * bis)
 	printf("greth_init\n");
 #endif
 
-	GRETH_REGSAVE(&regs->control, 0);
-
 	if (!greth->rxbd_base) {
 
 		/* allocate descriptors */
@@ -161,6 +159,7 @@ int greth_init(struct eth_device *dev, bd_t * bis)
 		    malloc(GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);
 	}
 
+	memset(greth->rxbuf_base, 0, GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);
 	/* initate rx decriptors */
 	for (i = 0; i < GRETH_RXBD_CNT; i++) {
 		greth->rxbd_base[i].addr = (unsigned int)
@@ -219,6 +218,11 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 	greth_regs *regs = dev->regs;
 	int tmp, tmp1, tmp2, i;
 	unsigned int start, timeout;
+#ifdef CONFIG_SYS_GRLIB_GRETH_PHYADDR
+	int phyaddr = CONFIG_SYS_GRLIB_GRETH_PHYADDR;
+#else
+	int phyaddr = 0;
+#endif
 
 	/* X msecs to ticks */
 	timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000);
@@ -230,17 +234,25 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 
 	/* get phy control register default values */
 
-	while ((tmp = read_mii(0, regs)) & 0x8000) {
-		if (get_timer(start) > timeout)
+	while ((tmp = read_mii(phyaddr, 0, regs)) & 0x8000) {
+		if (get_timer(start) > timeout) {
+#ifdef DEBUG
+			printf("greth_init_phy: PHY read 1 failed\n");
+#endif
 			return 1;	/* Fail */
+		}
 	}
 
 	/* reset PHY and wait for completion */
-	write_mii(0, 0x8000 | tmp, regs);
+	write_mii(phyaddr, 0, 0x8000 | tmp, regs);
 
-	while (((tmp = read_mii(0, regs))) & 0x8000) {
-		if (get_timer(start) > timeout)
+	while (((tmp = read_mii(phyaddr, 0, regs))) & 0x8000) {
+		if (get_timer(start) > timeout) {
+#ifdef DEBUG
+			printf("greth_init_phy: PHY read 2 failed\n");
+#endif
 			return 1;	/* Fail */
+		}
 	}
 
 	/* Check if PHY is autoneg capable and then determine operating
@@ -251,16 +263,16 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 	dev->sp = 0;
 	dev->auto_neg = 0;
 	if (!((tmp >> 12) & 1)) {
-		write_mii(0, 0, regs);
+		write_mii(phyaddr, 0, 0, regs);
 	} else {
 		/* wait for auto negotiation to complete and then check operating mode */
 		dev->auto_neg = 1;
 		i = 0;
-		while (!(((tmp = read_mii(1, regs)) >> 5) & 1)) {
+		while (!(((tmp = read_mii(phyaddr, 1, regs)) >> 5) & 1)) {
 			if (get_timer(start) > timeout) {
 				printf("Auto negotiation timed out. "
 				       "Selecting default config\n");
-				tmp = read_mii(0, regs);
+				tmp = read_mii(phyaddr, 0, regs);
 				dev->gb = ((tmp >> 6) & 1)
 				    && !((tmp >> 13) & 1);
 				dev->sp = !((tmp >> 6) & 1)
@@ -270,8 +282,8 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 			}
 		}
 		if ((tmp >> 8) & 1) {
-			tmp1 = read_mii(9, regs);
-			tmp2 = read_mii(10, regs);
+			tmp1 = read_mii(phyaddr, 9, regs);
+			tmp2 = read_mii(phyaddr, 10, regs);
 			if ((tmp1 & GRETH_MII_EXTADV_1000FD) &&
 			    (tmp2 & GRETH_MII_EXTPRT_1000FD)) {
 				dev->gb = 1;
@@ -284,8 +296,8 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 			}
 		}
 		if ((dev->gb == 0) || ((dev->gb == 1) && (dev->gbit_mac == 0))) {
-			tmp1 = read_mii(4, regs);
-			tmp2 = read_mii(5, regs);
+			tmp1 = read_mii(phyaddr, 4, regs);
+			tmp2 = read_mii(phyaddr, 5, regs);
 			if ((tmp1 & GRETH_MII_100TXFD) &&
 			    (tmp2 & GRETH_MII_100TXFD)) {
 				dev->sp = 1;
@@ -302,7 +314,7 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 			if ((dev->gb == 1) && (dev->gbit_mac == 0)) {
 				dev->gb = 0;
 				dev->fd = 0;
-				write_mii(0, dev->sp << 13, regs);
+				write_mii(phyaddr, 0, dev->sp << 13, regs);
 			}
 		}
 
@@ -314,8 +326,8 @@ int greth_init_phy(greth_priv * dev, bd_t * bis)
 #endif
 	/* Read out PHY info if extended registers are available */
 	if (tmp & 1) {
-		tmp1 = read_mii(2, regs);
-		tmp2 = read_mii(3, regs);
+		tmp1 = read_mii(phyaddr, 2, regs);
+		tmp2 = read_mii(phyaddr, 3, regs);
 		tmp1 = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);
 		tmp = tmp2 & 0xF;
 
@@ -542,10 +554,9 @@ int greth_recv(struct eth_device *dev)
 		/* increase index */
 		greth->rxbd_curr =
 		    ((unsigned int)greth->rxbd_curr >=
-		     (unsigned int)greth->rxbd_max) ? greth->
-		    rxbd_base : (greth->rxbd_curr + 1);
+		     (unsigned int)greth->rxbd_max) ? greth->rxbd_base : (greth->rxbd_curr + 1);
 
-	};
+	}
 
 	if (enable) {
 		GRETH_REGORIN(&regs->control, GRETH_RXEN);
@@ -630,6 +641,9 @@ int greth_initialize(bd_t * bis)
 	/* initiate PHY, select speed/duplex depending on connected PHY */
 	if (greth_init_phy(greth, bis)) {
 		/* Failed to init PHY (timedout) */
+#ifdef DEBUG
+		printf("GRETH[0x%08x]: Failed to init PHY\n", greth->regs);
+#endif
 		return -1;
 	}
 
@@ -658,5 +672,8 @@ int greth_initialize(bd_t * bis)
 	/* set and remember MAC address */
 	greth_set_hwaddr(greth, addr);
 
+#ifdef DEBUG
+	printf("GRETH[0x%08x]: Initialized successfully\n", greth->regs);
+#endif
 	return 0;
 }
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 03/17] GRETH: Added extra RESET, this is needed if GRETH was stopped during an ethernet frame reception.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 04/17] LEON3: reimplemented AMBA Plug&Play scanning routines Daniel Hellstrom
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 drivers/net/greth.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 833915d..383b25c 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -146,13 +146,23 @@ int greth_init(struct eth_device *dev, bd_t * bis)
 	printf("greth_init\n");
 #endif
 
+	/* Reset core */
+	GRETH_REGSAVE(&regs->control, (GRETH_RESET | (greth->gb << 8) |
+		(greth->sp << 7) | (greth->fd << 4)));
+
+	/* Wait for Reset to complete */
+	while ( GRETH_REGLOAD(&regs->control) & GRETH_RESET) ;
+
+	GRETH_REGSAVE(&regs->control,
+		((greth->gb << 8) | (greth->sp << 7) | (greth->fd << 4)));
+
 	if (!greth->rxbd_base) {
 
 		/* allocate descriptors */
 		greth->rxbd_base = (greth_bd *)
 		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
 		greth->txbd_base = (greth_bd *)
-		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
+		    memalign(0x1000, GRETH_TXBD_CNT * sizeof(greth_bd));
 
 		/* allocate buffers to all descriptors  */
 		greth->rxbuf_base =
@@ -185,7 +195,7 @@ int greth_init(struct eth_device *dev, bd_t * bis)
 	for (i = 0; i < GRETH_TXBD_CNT; i++) {
 		greth->txbd_base[i].addr = 0;
 		/* enable desciptor & set wrap bit if last descriptor */
-		if (i >= (GRETH_RXBD_CNT - 1)) {
+		if (i >= (GRETH_TXBD_CNT - 1)) {
 			greth->txbd_base[i].stat = GRETH_BD_WR;
 		} else {
 			greth->txbd_base[i].stat = 0;
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 04/17] LEON3: reimplemented AMBA Plug&Play scanning routines.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 03/17] GRETH: Added extra RESET, this is needed if GRETH was stopped during an ethernet frame reception Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 05/17] LEON3: added memory controller initialization using the new AMBA PnP routines Daniel Hellstrom
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 common/cmd_ambapp.c      |  566 +++++++++++++++++++++++++-------
 cpu/leon3/Makefile       |    2 +-
 cpu/leon3/ambapp.c       |  581 +++++++++++++++++-----------------
 cpu/leon3/ambapp_low.S   |  798 ++++++++++++++++++++++++++++++++++++++++++++++
 cpu/leon3/ambapp_low_c.S |  133 ++++++++
 cpu/leon3/cpu_init.c     |  182 ++++-------
 cpu/leon3/serial.c       |    8 +-
 cpu/leon3/usb_uhci.c     |    4 +-
 drivers/net/greth.c      |   15 +-
 include/ambapp.h         |  365 ++++++++++-----------
 include/ambapp_ids.h     |  256 +++++++++++++++
 11 files changed, 2180 insertions(+), 730 deletions(-)
 create mode 100644 cpu/leon3/ambapp_low.S
 create mode 100644 cpu/leon3/ambapp_low_c.S
 create mode 100644 include/ambapp_ids.h

diff --git a/common/cmd_ambapp.c b/common/cmd_ambapp.c
index bb20ab5..55b2757 100644
--- a/common/cmd_ambapp.c
+++ b/common/cmd_ambapp.c
@@ -31,92 +31,380 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* We put these variables into .data section so that they are zero
- * when entering the AMBA Plug & Play routines (in cpu/cpu/ambapp.c)
- * the first time. BSS is not garantueed to be zero since BSS
- * hasn't been cleared the first times entering the CPU AMBA functions.
- *
- * The AMBA PnP routines call these functions if ambapp_???_print is set.
- *
- */
-int ambapp_apb_print __attribute__ ((section(".data"))) = 0;
-int ambapp_ahb_print __attribute__ ((section(".data"))) = 0;
-
 typedef struct {
 	int device_id;
 	char *name;
+	char *desc;
 } ambapp_device_name;
 
-static ambapp_device_name gaisler_devices[] = {
-	{GAISLER_LEON3, "GAISLER_LEON3"},
-	{GAISLER_LEON3DSU, "GAISLER_LEON3DSU"},
-	{GAISLER_ETHAHB, "GAISLER_ETHAHB"},
-	{GAISLER_ETHMAC, "GAISLER_ETHMAC"},
-	{GAISLER_APBMST, "GAISLER_APBMST"},
-	{GAISLER_AHBUART, "GAISLER_AHBUART"},
-	{GAISLER_SRCTRL, "GAISLER_SRCTRL"},
-	{GAISLER_SDCTRL, "GAISLER_SDCTRL"},
-	{GAISLER_APBUART, "GAISLER_APBUART"},
-	{GAISLER_IRQMP, "GAISLER_IRQMP"},
-	{GAISLER_AHBRAM, "GAISLER_AHBRAM"},
-	{GAISLER_GPTIMER, "GAISLER_GPTIMER"},
-	{GAISLER_PCITRG, "GAISLER_PCITRG"},
-	{GAISLER_PCISBRG, "GAISLER_PCISBRG"},
-	{GAISLER_PCIFBRG, "GAISLER_PCIFBRG"},
-	{GAISLER_PCITRACE, "GAISLER_PCITRACE"},
-	{GAISLER_AHBTRACE, "GAISLER_AHBTRACE"},
-	{GAISLER_ETHDSU, "GAISLER_ETHDSU"},
-	{GAISLER_PIOPORT, "GAISLER_PIOPORT"},
-	{GAISLER_AHBJTAG, "GAISLER_AHBJTAG"},
-	{GAISLER_ATACTRL, "GAISLER_ATACTRL"},
-	{GAISLER_VGA, "GAISLER_VGA"},
-	{GAISLER_KBD, "GAISLER_KBD"},
-	{GAISLER_L2TIME, "GAISLER_L2TIME"},
-	{GAISLER_L2C, "GAISLER_L2C"},
-	{GAISLER_PLUGPLAY, "GAISLER_PLUGPLAY"},
-	{GAISLER_SPW, "GAISLER_SPW"},
-	{GAISLER_SPW2, "GAISLER_SPW2"},
-	{GAISLER_EHCI, "GAISLER_EHCI"},
-	{GAISLER_UHCI, "GAISLER_UHCI"},
-	{GAISLER_AHBSTAT, "GAISLER_AHBSTAT"},
-	{GAISLER_DDR2SPA, "GAISLER_DDR2SPA"},
-	{GAISLER_DDRSPA, "GAISLER_DDRSPA"},
-	{0, NULL}
+typedef struct {
+        unsigned int vendor_id;
+        char *name;
+        char *desc;
+        ambapp_device_name *devices;
+} ambapp_vendor_devnames;    
+
+/** Vendor GAISLER devices */
+static ambapp_device_name GAISLER_devices[] =
+{
+  {GAISLER_LEON2DSU, "LEON2DSU", "Leon2 Debug Support Unit"},
+  {GAISLER_LEON3, "LEON3", "Leon3 SPARC V8 Processor"},
+  {GAISLER_LEON3DSU, "LEON3DSU", "Leon3 Debug Support Unit"},
+  {GAISLER_ETHAHB, "ETHAHB", "OC ethernet AHB interface"},
+  {GAISLER_APBMST, "APBMST", "AHB/APB Bridge"},
+  {GAISLER_AHBUART, "AHBUART", "AHB Debug UART"},
+  {GAISLER_SRCTRL, "SRCTRL", "Simple SRAM Controller"},
+  {GAISLER_SDCTRL, "SDCTRL", "PC133 SDRAM Controller"},
+  {GAISLER_SSRCTRL, "SSRCTRL", "Synchronous SRAM Controller"},
+  {GAISLER_APBUART, "APBUART", "Generic UART"},
+  {GAISLER_IRQMP, "IRQMP", "Multi-processor Interrupt Ctrl."},
+  {GAISLER_AHBRAM, "AHBRAM", "Single-port AHB SRAM module"},
+  {GAISLER_AHBDPRAM, "AHBDPRAM", "Dual-port AHB SRAM module"},
+  {GAISLER_GPTIMER, "GPTIMER", "Modular Timer Unit"},
+  {GAISLER_PCITRG, "PCITRG", "Simple 32-bit PCI Target"},
+  {GAISLER_PCISBRG, "PCISBRG", "Simple 32-bit PCI Bridge"},
+  {GAISLER_PCIFBRG, "PCIFBRG", "Fast 32-bit PCI Bridge"},
+  {GAISLER_PCITRACE, "PCITRACE", "32-bit PCI Trace Buffer"},
+  {GAISLER_DMACTRL, "DMACTRL", "AMBA DMA controller"},
+  {GAISLER_AHBTRACE, "AHBTRACE", "AMBA Trace Buffer"},
+  {GAISLER_DSUCTRL, "DSUCTRL", "DSU/ETH controller"},
+  {GAISLER_CANAHB, "CANAHB", "OC CAN AHB interface"},
+  {GAISLER_GPIO, "GPIO", "General Purpose I/O port"},
+  {GAISLER_AHBROM, "AHBROM", "Generic AHB ROM"},
+  {GAISLER_AHBJTAG, "AHBJTAG", "JTAG Debug Link"},
+  {GAISLER_ETHMAC, "ETHMAC", "GR Ethernet MAC"},
+  {GAISLER_SWNODE, "SWNODE", "SpaceWire Node Interface"},
+  {GAISLER_SPW, "SPW", "SpaceWire Serial Link"},
+  {GAISLER_AHB2AHB, "AHB2AHB", "AHB-to-AHB Bridge"},
+  {GAISLER_USBDC, "USBDC", "GR USB 2.0 Device Controller"},
+  {GAISLER_USB_DCL, "USB_DCL", "USB Debug Communication Link"},
+  {GAISLER_DDRMP, "DDRMP", "Multi-port DDR controller"},
+  {GAISLER_ATACTRL, "ATACTRL", "ATA controller"},
+  {GAISLER_DDRSP, "DDRSP", "Single-port DDR266 controller"},
+  {GAISLER_EHCI, "EHCI", "USB Enhanced Host Controller"},
+  {GAISLER_UHCI, "UHCI", "USB Universal Host Controller"},
+  {GAISLER_I2CMST, "I2CMST", "AMBA Wrapper for OC I2C-master"},
+  {GAISLER_SPW2, "SPW2", "GRSPW2 SpaceWire Serial Link"},
+  {GAISLER_AHBDMA, "AHBDMA", ""},
+  {GAISLER_NUHOSP3, "NUHOSP3", "Nuhorizons Spartan3 IO I/F"},
+  {GAISLER_CLKGATE, "CLKGATE", "Clock gating unit"},
+  {GAISLER_SPICTRL, "SPICTRL", "SPI Controller"},
+  {GAISLER_DDR2SP, "DDR2SP", "Single-port DDR2 controller"},
+  {GAISLER_SLINK, "SLINK", "SLINK Master"},
+  {GAISLER_GRTM, "GRTM", "CCSDS Telemetry Encoder"},
+  {GAISLER_GRTC, "GRTC", "CCSDS Telecommand Decoder"},
+  {GAISLER_GRPW, "GRPW", "PacketWire to AMBA AHB I/F"},
+  {GAISLER_GRCTM, "GRCTM", "CCSDS Time Manager"},
+  {GAISLER_GRHCAN, "GRHCAN", "ESA HurriCANe CAN with DMA"},
+  {GAISLER_GRFIFO, "GRFIFO", "FIFO Controller"},
+  {GAISLER_GRADCDAC, "GRADCDAC", "ADC / DAC Interface"},
+  {GAISLER_GRPULSE, "GRPULSE", "General Purpose I/O with Pulses"},
+  {GAISLER_GRTIMER, "GRTIMER", "Timer Unit with Latches"},
+  {GAISLER_AHB2PP, "AHB2PP", "AMBA AHB to Packet Parallel I/F"},
+  {GAISLER_GRVERSION, "GRVERSION", "Version and Revision Register"},
+  {GAISLER_APB2PW, "APB2PW", "PacketWire Transmit Interface"},
+  {GAISLER_PW2APB, "PW2APB", "PacketWire Receive Interface"},
+  {GAISLER_GRCAN, "GRCAN", "CAN Controller with DMA"},
+  {GAISLER_I2CSLV, "I2CSLV", "I2C Slave"},
+  {GAISLER_U16550, "U16550", "Simple 16550 UART"},
+  {GAISLER_AHBMST_EM, "AHBMST_EM", "AMBA Master Emulator"},
+  {GAISLER_AHBSLV_EM, "AHBSLV_EM", "AMBA Slave Emulator"},
+  {GAISLER_GRTESTMOD, "GRTESTMOD", "Test report module"},
+  {GAISLER_ASCS, "ASCS", "ASCS Master"},
+  {GAISLER_IPMVBCTRL, "IPMVBCTRL", "IPM-bus/MVBC memory controller"},
+  {GAISLER_SPIMCTRL, "SPIMCTRL", "SPI Memory Controller"},
+  {GAISLER_LEON4, "LEON4", "Leon4 SPARC V8 Processor"},
+  {GAISLER_LEON4DSU, "LEON4DSU", "Leon4 Debug Support Unit"},
+  {GAISLER_PWM, "PWM", "PWM generator"},
+  {GAISLER_L2CACHE, "L2CACHE", "L2-Cache Controller"},
+  {GAISLER_SDCTRL64, "SDCTRL64", ""},
+  {GAISLER_FTAHBRAM, "FTAHBRAM", "Generic FT AHB SRAM module"},
+  {GAISLER_FTSRCTRL, "FTSRCTRL", "Simple FT SRAM Controller"},
+  {GAISLER_AHBSTAT, "AHBSTAT", "AHB Status Register"},
+  {GAISLER_LEON3FT, "LEON3FT", "Leon3-FT SPARC V8 Processor"},
+  {GAISLER_FTMCTRL, "FTMCTRL", "Memory controller with EDAC"},
+  {GAISLER_FTSDCTRL, "FTSDCTRL", "FT PC133 SDRAM Controller"},
+  {GAISLER_FTSRCTRL8, "FTSRCTRL8", "FT 8-bit SRAM/16-bit IO Ctrl"},
+  {GAISLER_APBPS2, "APBPS2", "PS2 interface"},
+  {GAISLER_VGACTRL, "VGACTRL", "VGA controller"},
+  {GAISLER_LOGAN, "LOGAN", "On chip Logic Analyzer"},
+  {GAISLER_SVGACTRL, "SVGACTRL", "SVGA frame buffer"},
+  {GAISLER_T1AHB, "T1AHB", "Niagara T1 PCX/AHB bridge"},
+  {GAISLER_MP7WRAP, "MP7WRAP", "CoreMP7 wrapper"},
+  {GAISLER_GRSYSMON, "GRSYSMON", "AMBA wrapper for System Monitor"},
+  {GAISLER_GRACECTRL, "GRACECTRL", "System ACE I/F Controller"},
+  {GAISLER_ATAHBSLV, "ATAHBSLV", "AMBA Test Framework AHB Slave"},
+  {GAISLER_ATAHBMST, "ATAHBMST", "AMBA Test Framework AHB Master"},
+  {GAISLER_ATAPBSLV, "ATAPBSLV", "AMBA Test Framework APB Slave"},
+  {GAISLER_B1553BC, "B1553BC", "AMBA Wrapper for Core1553BBC"},
+  {GAISLER_B1553RT, "B1553RT", "AMBA Wrapper for Core1553BRT"},
+  {GAISLER_B1553BRM, "B1553BRM", "AMBA Wrapper for Core1553BRM"},
+  {GAISLER_AES, "AES", "Advanced Encryption Standard"},
+  {GAISLER_ECC, "ECC", "Elliptic Curve Cryptography"},
+  {GAISLER_PCIF, "PCIF", "AMBA Wrapper for CorePCIF"},
+  {GAISLER_CLKMOD, "CLKMOD", "CPU Clock Switching Ctrl module"},
+  {GAISLER_HAPSTRAK, "HAPSTRAK", "HAPS HapsTrak I/O Port"},
+  {GAISLER_TEST_1X2, "TEST_1X2", "HAPS TEST_1x2 interface"},
+  {GAISLER_WILD2AHB, "WILD2AHB", "WildCard CardBus interface"},
+  {GAISLER_BIO1, "BIO1", "Basic I/O board BIO1"},
+  {GAISLER_SATCAN, "SATCAN", "SatCAN controller"},
+  {GAISLER_CANMUX, "CANMUX", "CAN Bus multiplexer"},
+  {GAISLER_GRTMRX, "GRTMRX", "CCSDS Telemetry Receiver"},
+  {GAISLER_GRTCTX, "GRTCTX", "CCSDS Telecommand Transmitter"},
+  {GAISLER_GRTMDESC, "GRTMDESC", "CCSDS Telemetry Descriptor"},
+  {GAISLER_GRTMVC, "GRTMVC", "CCSDS Telemetry VC Generator"},
+  {GAISLER_GEFFE, "GEFFE", "Geffe Generator"},
+  {GAISLER_GPREG, "GPREG", ""},
+  {GAISLER_GRTMPAHB, "GRTMPAHB", "CCSDS Telemetry VC AHB Input"},
+  {0, NULL, NULL}
 };
 
-static ambapp_device_name esa_devices[] = {
-	{ESA_LEON2, "ESA_LEON2"},
-	{ESA_MCTRL, "ESA_MCTRL"},
-	{0, NULL}
+
+/** Vendor PENDER devices */
+static ambapp_device_name PENDER_devices[] =
+{
+  {0, NULL, NULL}
 };
 
-static ambapp_device_name opencores_devices[] = {
-	{OPENCORES_PCIBR, "OPENCORES_PCIBR"},
-	{OPENCORES_ETHMAC, "OPENCORES_ETHMAC"},
+
+/** Vendor ESA devices */
+static ambapp_device_name ESA_devices[] =
+{
+  {ESA_LEON2, "LEON2", "Leon2 SPARC V8 Processor"},
+  {ESA_LEON2APB, "LEON2APB", "Leon2 Peripheral Bus"},
+  {ESA_IRQ, "IRQ", "Leon2 Interrupt Controller"},
+  {ESA_TIMER, "TIMER", "Leon2 Timer"},
+  {ESA_UART, "UART", "Leon2 UART"},
+  {ESA_CFG, "CFG", "Leon2 Configuration Register"},
+  {ESA_IO, "IO", "Leon2 Input/Output"},
+  {ESA_MCTRL, "MCTRL", "Leon2 Memory Controller"},
+  {ESA_PCIARB, "PCIARB", "PCI Arbiter"},
+  {ESA_HURRICANE, "HURRICANE", "HurriCANe/HurryAMBA CAN Ctrl"},
+  {ESA_SPW_RMAP, "SPW_RMAP", "UoD/Saab SpaceWire/RMAP link"},
+  {ESA_AHBUART, "AHBUART", "Leon2 AHB Debug UART"},
+  {ESA_SPWA, "SPWA", "ESA/ASTRIUM SpaceWire link"},
+  {ESA_BOSCHCAN, "BOSCHCAN", "SSC/BOSCH CAN Ctrl"},
+  {ESA_IRQ2, "IRQ2", "Leon2 Secondary Irq Controller"},
+  {ESA_AHBSTAT, "AHBSTAT", "Leon2 AHB Status Register"},
+  {ESA_WPROT, "WPROT", "Leon2 Write Protection"},
+  {ESA_WPROT2, "WPROT2", "Leon2 Extended Write Protection"},
+  {ESA_PDEC3AMBA, "PDEC3AMBA", "ESA CCSDS PDEC3AMBA TC Decoder"},
+  {ESA_PTME3AMBA, "PTME3AMBA", "ESA CCSDS PTME3AMBA TM Encoder"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor ASTRIUM devices */
+static ambapp_device_name ASTRIUM_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor OPENCHIP devices */
+static ambapp_device_name OPENCHIP_devices[] =
+{
+  {OPENCHIP_APBGPIO, "APBGPIO", "APB General Purpose IO"},
+  {OPENCHIP_APBI2C, "APBI2C", "APB I2C Interface"},
+  {OPENCHIP_APBSPI, "APBSPI", "APB SPI Interface"},
+  {OPENCHIP_APBCHARLCD, "APBCHARLCD", "APB Character LCD"},
+  {OPENCHIP_APBPWM, "APBPWM", "APB PWM"},
+  {OPENCHIP_APBPS2, "APBPS2", "APB PS/2 Interface"},
+  {OPENCHIP_APBMMCSD, "APBMMCSD", "APB MMC/SD Card Interface"},
+  {OPENCHIP_APBNAND, "APBNAND", "APB NAND(SmartMedia) Interface"},
+  {OPENCHIP_APBLPC, "APBLPC", "APB LPC Interface"},
+  {OPENCHIP_APBCF, "APBCF", "APB CompactFlash (IDE)"},
+  {OPENCHIP_APBSYSACE, "APBSYSACE", "APB SystemACE Interface"},
+  {OPENCHIP_APB1WIRE, "APB1WIRE", "APB 1-Wire Interface"},
+  {OPENCHIP_APBJTAG, "APBJTAG", "APB JTAG TAP Master"},
+  {OPENCHIP_APBSUI, "APBSUI", "APB Simple User Interface"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor OPENCORES devices */
+static ambapp_device_name OPENCORES_devices[] =
+{
+	{OPENCORES_PCIBR, "PCIBR", "PCI Bridge"},
+	{OPENCORES_ETHMAC, "ETHMAC", "Ethernet MAC"},
 	{0, NULL}
 };
 
-typedef struct {
-	unsigned int vendor_id;
-	char *name;
-	ambapp_device_name *devices;
-} ambapp_vendor_devnames;
-
-static ambapp_vendor_devnames vendors[] = {
-	{VENDOR_GAISLER, "VENDOR_GAISLER", gaisler_devices},
-	{VENDOR_ESA, "VENDOR_ESA", esa_devices},
-	{VENDOR_OPENCORES, "VENDOR_OPENCORES", opencores_devices},
-	{0, NULL, 0}
+
+/** Vendor CONTRIB devices */
+static ambapp_device_name CONTRIB_devices[] =
+{
+  {CONTRIB_CORE1, "CORE1", "Contributed core 1"},
+  {CONTRIB_CORE2, "CORE2", "Contributed core 2"},
+  {0, NULL, NULL}
 };
 
-static char *ambapp_get_devname(ambapp_device_name * devs, int id)
+
+/** Vendor EONIC devices */
+static ambapp_device_name EONIC_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor RADIONOR devices */
+static ambapp_device_name RADIONOR_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor GLEICHMANN devices */
+static ambapp_device_name GLEICHMANN_devices[] =
+{
+  {GLEICHMANN_CUSTOM, "CUSTOM", "Custom device"},
+  {GLEICHMANN_GEOLCD01, "GEOLCD01", "GEOLCD01 graphics system"},
+  {GLEICHMANN_DAC, "DAC", "Sigma delta DAC"},
+  {GLEICHMANN_HPI, "HPI", "AHB-to-HPI bridge"},
+  {GLEICHMANN_SPI, "SPI", "SPI master"},
+  {GLEICHMANN_HIFC, "HIFC", "Human interface controller"},
+  {GLEICHMANN_ADCDAC, "ADCDAC", "Sigma delta ADC/DAC"},
+  {GLEICHMANN_SPIOC, "SPIOC", ""},
+  {GLEICHMANN_AC97, "AC97", ""},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor MENTA devices */
+static ambapp_device_name MENTA_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor SUN devices */
+static ambapp_device_name SUN_devices[] =
+{
+  {SUN_T1, "T1", "Niagara T1 SPARC V9 Processor"},
+  {SUN_S1, "S1", "Niagara S1 SPARC V9 Processor"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor MOVIDIA devices */
+static ambapp_device_name MOVIDIA_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor ORBITA devices */
+static ambapp_device_name ORBITA_devices[] =
+{
+  {ORBITA_1553B, "1553B", "MIL-STD-1553B Controller"},
+  {ORBITA_429, "429", "429 Interface"},
+  {ORBITA_SPI, "SPI", "SPI Interface"},
+  {ORBITA_I2C, "I2C", "I2C Interface"},
+  {ORBITA_SMARTCARD, "SMARTCARD", "Smart Card Reader"},
+  {ORBITA_SDCARD, "SDCARD", "SD Card Reader"},
+  {ORBITA_UART16550, "UART16550", "16550 UART"},
+  {ORBITA_CRYPTO, "CRYPTO", "Crypto Engine"},
+  {ORBITA_SYSIF, "SYSIF", "System Interface"},
+  {ORBITA_PIO, "PIO", "Programmable IO module"},
+  {ORBITA_RTC, "RTC", "Real-Time Clock"},
+  {ORBITA_COLORLCD, "COLORLCD", "Color LCD Controller"},
+  {ORBITA_PCI, "PCI", "PCI Module"},
+  {ORBITA_DSP, "DSP", "DPS Co-Processor"},
+  {ORBITA_USBHOST, "USBHOST", "USB Host"},
+  {ORBITA_USBDEV, "USBDEV", "USB Device"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor SYNOPSYS devices */
+static ambapp_device_name SYNOPSYS_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor NASA devices */
+static ambapp_device_name NASA_devices[] =
+{
+  {NASA_EP32, "EP32", "EP32 Forth processor"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor CAL devices */
+static ambapp_device_name CAL_devices[] =
+{
+  {CAL_DDRCTRL, "DDRCTRL", ""},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor EMBEDDIT devices */
+static ambapp_device_name EMBEDDIT_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor CETON devices */
+static ambapp_device_name CETON_devices[] =
+{
+  {0, NULL, NULL}
+};
+
+
+/** Vendor ACTEL devices */
+static ambapp_device_name ACTEL_devices[] =
+{
+  {ACTEL_COREMP7, "COREMP7", "CoreMP7 Processor"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendor APPLECORE devices */
+static ambapp_device_name APPLECORE_devices[] =
+{
+  {APPLECORE_UTLEON3, "UTLEON3", "AppleCore uT-LEON3 Processor"},
+  {APPLECORE_UTLEON3DSU, "UTLEON3DSU", "AppleCore uT-LEON3 DSU"},
+  {0, NULL, NULL}
+};
+
+
+/** Vendors and their devices */
+static ambapp_vendor_devnames vendors[] = 
+{
+  {VENDOR_GAISLER, "GAISLER", "Gaisler Research", GAISLER_devices},
+  {VENDOR_PENDER, "PENDER", "", PENDER_devices},
+  {VENDOR_ESA, "ESA", "European Space Agency", ESA_devices},
+  {VENDOR_ASTRIUM, "ASTRIUM", "", ASTRIUM_devices},
+  {VENDOR_OPENCHIP, "OPENCHIP", "OpenChip", OPENCHIP_devices},
+  {VENDOR_OPENCORES, "OPENCORES", "OpenCores", OPENCORES_devices},
+  {VENDOR_CONTRIB, "CONTRIB", "Various contributions", CONTRIB_devices},
+  {VENDOR_EONIC, "EONIC", "Eonic BV", EONIC_devices},
+  {VENDOR_RADIONOR, "RADIONOR", "Radionor Communications", RADIONOR_devices},
+  {VENDOR_GLEICHMANN, "GLEICHMANN", "Gleichmann Electronics", GLEICHMANN_devices},
+  {VENDOR_MENTA, "MENTA", "Menta", MENTA_devices},
+  {VENDOR_SUN, "SUN", "Sun Microsystems", SUN_devices},
+  {VENDOR_MOVIDIA, "MOVIDIA", "", MOVIDIA_devices},
+  {VENDOR_ORBITA, "ORBITA", "Orbita", ORBITA_devices},
+  {VENDOR_SYNOPSYS, "SYNOPSYS", "Synopsys Inc.", SYNOPSYS_devices},
+  {VENDOR_NASA, "NASA", "NASA", NASA_devices},
+  {VENDOR_CAL, "CAL", "", CAL_devices},
+  {VENDOR_EMBEDDIT, "EMBEDDIT", "Embedd.it", EMBEDDIT_devices},
+  {VENDOR_CETON, "CETON", "Ceton Corporation", CETON_devices},
+  {VENDOR_ACTEL, "ACTEL", "Actel Corporation", ACTEL_devices},
+  {VENDOR_APPLECORE, "APPLECORE", "AppleCore", APPLECORE_devices},
+  {0, NULL, NULL, NULL}
+};
+
+static ambapp_device_name *ambapp_get_dev(ambapp_device_name * devs, int id)
 {
 	if (!devs)
 		return NULL;
 
 	while (devs->device_id > 0) {
 		if (devs->device_id == id)
-			return devs->name;
+			return devs;
 		devs++;
 	}
 	return NULL;
@@ -125,10 +413,31 @@ static char *ambapp_get_devname(ambapp_device_name * devs, int id)
 char *ambapp_device_id2str(int vendor, int id)
 {
 	ambapp_vendor_devnames *ven = &vendors[0];
+	ambapp_device_name *dev;
+
+	while (ven->vendor_id > 0) {
+		if (ven->vendor_id == vendor) {
+			dev = ambapp_get_dev(ven->devices, id);
+			if ( !dev )
+				return NULL;
+			return dev->name;
+		}
+		ven++;
+	}
+	return NULL;
+}
+
+char *ambapp_device_id2desc(int vendor, int id)
+{
+	ambapp_vendor_devnames *ven = &vendors[0];
+	ambapp_device_name *dev;
 
 	while (ven->vendor_id > 0) {
 		if (ven->vendor_id == vendor) {
-			return ambapp_get_devname(ven->devices, id);
+			dev = ambapp_get_dev(ven->devices, id);
+			if ( !dev )
+				return NULL;
+			return dev->desc;
 		}
 		ven++;
 	}
@@ -150,101 +459,107 @@ char *ambapp_vendor_id2str(int vendor)
 
 static char *unknown = "unknown";
 
+char *ambapp_type_names[4] =
+{
+	/* 0 */ "UNUSED",
+	/* 1 */ "apb",
+	/* 2 */ "ahbmem",
+	/* 3 */ "ahbio"
+};
+
 /* Print one APB device */
-void ambapp_print_apb(apbctrl_pp_dev * apb, ambapp_ahbdev * apbmst, int index)
+void ambapp_print_apb(ambapp_apbdev *dev, int index)
 {
 	char *dev_str, *ven_str;
-	int irq, ver, vendor, deviceid;
-	unsigned int address, apbmst_base, mask;
-
-	vendor = amba_vendor(apb->conf);
-	deviceid = amba_device(apb->conf);
-	irq = amba_irq(apb->conf);
-	ver = amba_ver(apb->conf);
-	apbmst_base = apbmst->address[0] & LEON3_IO_AREA;
-	address = (apbmst_base | (((apb->bar & 0xfff00000) >> 12))) &
-	    (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
-
-	mask = amba_membar_mask(apb->bar) << 8;
-	mask = ((~mask) & 0x000fffff) + 1;
+	unsigned int freq;
 
-	ven_str = ambapp_vendor_id2str(vendor);
+	ven_str = ambapp_vendor_id2str(dev->vendor);
 	if (!ven_str) {
 		ven_str = unknown;
 		dev_str = unknown;
 	} else {
-		dev_str = ambapp_device_id2str(vendor, deviceid);
+		dev_str = ambapp_device_id2str(dev->vendor, dev->device);
 		if (!dev_str)
 			dev_str = unknown;
 	}
+	
+	/* Get Frequency of Core */
+	freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index);
 
-	printf("0x%02x:0x%02x:0x%02x: %s  %s\n"
+	printf("0x%02x:0x%02x:0x%02x: %s  %s  (%dkHz)\n"
 	       "   apb: 0x%08x - 0x%08x\n"
 	       "   irq: %-2d (ver: %-2d)\n",
-	       index, vendor, deviceid, ven_str, dev_str, address,
-	       address + mask, irq, ver);
+	       index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000,
+	       dev->address, dev->address + (dev->mask-1),
+	       dev->irq, dev->ver);
 }
 
-void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index)
+void ambapp_print_ahb(ambapp_ahbdev *dev, int index)
 {
-	char *dev_str, *ven_str;
-	int irq, ver, vendor, deviceid;
-	unsigned int addr, mask;
-	int j;
-
-	vendor = amba_vendor(ahb->conf);
-	deviceid = amba_device(ahb->conf);
-	irq = amba_irq(ahb->conf);
-	ver = amba_ver(ahb->conf);
+	char *dev_str, *ven_str, *type_str;
+	int i;
+	unsigned int freq;
 
-	ven_str = ambapp_vendor_id2str(vendor);
+	ven_str = ambapp_vendor_id2str(dev->vendor);
 	if (!ven_str) {
 		ven_str = unknown;
 		dev_str = unknown;
 	} else {
-		dev_str = ambapp_device_id2str(vendor, deviceid);
+		dev_str = ambapp_device_id2str(dev->vendor, dev->device);
 		if (!dev_str)
 			dev_str = unknown;
 	}
 
-	printf("0x%02x:0x%02x:0x%02x: %s  %s\n",
-	       index, vendor, deviceid, ven_str, dev_str);
+	/* Get Frequency of Core */
+	freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index);
 
-	for (j = 0; j < 4; j++) {
-		addr = amba_membar_start(ahb->bars[j]);
-		if (amba_membar_type(ahb->bars[j]) == 0)
+	printf("0x%02x:0x%02x:0x%02x: %s  %s  (%dkHz)\n",
+	       index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000);
+
+	for (i = 0; i < 4; i++) {
+		if ( dev->type[i] == 0 )
 			continue;
-		if (amba_membar_type(ahb->bars[j]) == AMBA_TYPE_AHBIO)
-			addr = AMBA_TYPE_AHBIO_ADDR(addr);
-		mask = amba_membar_mask(ahb->bars[j]) << 20;
-		printf("   mem: 0x%08x - 0x%08x\n", addr, addr + ((~mask) + 1));
+		type_str = ambapp_type_names[dev->type[i]];
+		printf("   %-7s: 0x%08x - 0x%08x\n", type_str, dev->address[i], 	
+			dev->address[i] + (dev->mask[i]-1));
 	}
 
-	printf("   irq: %-2d (ver: %d)\n", irq, ver);
+	printf("   irq: %-2d (ver: %d)\n", dev->irq, dev->ver);
 }
 
 int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
+	int index;
+	ambapp_apbdev apbdev;
+	ambapp_ahbdev ahbdev;
 
 	/* Print AHB Masters */
-	puts("--------- AHB Masters ---------\n");
-	ambapp_apb_print = 0;
-	ambapp_ahb_print = 1;
-	ambapp_ahbmst_count(99, 99);	/* Get vendor&device 99 = nonexistent... */
+	puts("\n--------- AHB Masters ---------\n");
+	index = 0;
+	while ( ambapp_ahbmst_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1 ) {
+		/* Found a AHB Master Device */
+		ambapp_print_ahb(&ahbdev, index);
+		index++;
+	}
 
 	/* Print AHB Slaves */
-	puts("--------- AHB Slaves  ---------\n");
-	ambapp_ahbslv_count(99, 99);	/* Get vendor&device 99 = nonexistent... */
+	puts("\n--------- AHB Slaves  ---------\n");
+	index = 0;
+	while ( ambapp_ahbslv_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1 ) {
+		/* Found a AHB Slave Device */
+		ambapp_print_ahb(&ahbdev, index);
+		index++;
+	}
 
 	/* Print APB Slaves */
-	puts("--------- APB Slaves  ---------\n");
-	ambapp_apb_print = 1;
-	ambapp_ahb_print = 0;
-	ambapp_apb_count(99, 99);	/* Get vendor&device 99 = nonexistent... */
-
-	/* Reset, no futher printing */
-	ambapp_apb_print = 0;
-	ambapp_ahb_print = 0;
+	puts("\n--------- APB Slaves  ---------\n");
+	index = 0;
+	while ( ambapp_apb_find(&ambapp_plb, 0, 0, index, &apbdev) == 1 ) {
+		/* Found a APB Slave Device */
+		ambapp_print_apb(&apbdev, index);
+		index++;
+	}
+
 	puts("\n");
 	return 0;
 }
@@ -256,16 +571,19 @@ int ambapp_init_reloc(void)
 
 	while (vend->vendor_id && vend->name) {
 		vend->name = (char *)((unsigned int)vend->name + gd->reloc_off);
+		vend->desc = (char *)((unsigned int)vend->desc + gd->reloc_off);
 		vend->devices =
 		    (ambapp_device_name *) ((unsigned int)vend->devices +
-					    gd->reloc_off);;
+					    gd->reloc_off);
 		dev = vend->devices;
 		vend++;
 		if (!dev)
 			continue;
 		while (dev->device_id && dev->name) {
 			dev->name =
-			    (char *)((unsigned int)dev->name + gd->reloc_off);;
+			    (char *)((unsigned int)dev->name + gd->reloc_off);
+			dev->desc =
+			    (char *)((unsigned int)dev->desc + gd->reloc_off);
 			dev++;
 		}
 	}
diff --git a/cpu/leon3/Makefile b/cpu/leon3/Makefile
index 182543d..d8f89bc 100644
--- a/cpu/leon3/Makefile
+++ b/cpu/leon3/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(CPU).a
 
 START	= start.o
-SOBJS	=
+SOBJS	= ambapp_low.o ambapp_low_c.o
 COBJS	= cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/cpu/leon3/ambapp.c b/cpu/leon3/ambapp.c
index efd41ae..d332294 100644
--- a/cpu/leon3/ambapp.c
+++ b/cpu/leon3/ambapp.c
@@ -1,9 +1,8 @@
-/* Gaisler AMBA Plug&Play bus scanning. Functions
- * ending on _nomem is inteded to be used only during
- * initialization, only registers are used (no ram).
+/* GRLIB AMBA Plug&Play information scanning, relies on assembler
+ * routines.
  *
- * (C) Copyright 2007
- * Daniel Hellstrom, Gaisler Research, daniel at gaisler.com
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -22,338 +21,348 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
+ *
  */
 
+/* #define DEBUG */
+
 #include <common.h>
-#include <command.h>
 #include <ambapp.h>
+#include <config.h>
+
+/************ C INTERFACE OF ASSEMBLER SCAN ROUTINES ************/
+struct ambapp_find_apb_info {
+	/* Address of APB device Plug&Play information */
+	struct ambapp_pnp_apb	*pnp;	
+	/* AHB Bus index of where the APB-Master Bridge device was found */
+	int			ahb_bus_index;
+	int			dec_index;
+};
 
-#if defined(CONFIG_CMD_AMBAPP)
-extern void ambapp_print_apb(apbctrl_pp_dev * apb,
-			     ambapp_ahbdev * apbmst, int index);
-extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index);
-extern int ambapp_apb_print;
-extern int ambapp_ahb_print;
-#endif
+struct ambapp_find_ahb_info {
+	/* Address of AHB device Plug&Play information */
+	struct ambapp_pnp_ahb	*pnp;
+	/* AHB Bus index of where the AHB device was found */
+	int			ahb_bus_index;
+	int			dec_index;
+};
 
-static int ambapp_apb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */
-			   unsigned int driver,	/* Plug&Play Device ID */
-			   ambapp_apbdev * dev,	/* Result(s) is placed here */
-			   int index,	/* Index of device to start copying Plug&Play
-					 * info into dev
-					 */
-			   int max_cnt	/* Maximal count that dev can hold, if dev
-					 * is NULL function will stop scanning after
-					 * max_cnt devices are found.
-					 */
-    )
+extern void ambapp_find_buses(
+	unsigned int ioarea,
+	struct ambapp_bus *abus
+	);
+
+extern int ambapp_find_apb(
+	struct ambapp_bus *abus,
+	unsigned int dev_vend,
+	int index,
+	struct ambapp_find_apb_info *result
+	);
+
+extern int ambapp_find_ahb(
+	struct ambapp_bus *abus,
+	unsigned int dev_vend,
+	int index,
+	int type,
+	struct ambapp_find_ahb_info *result
+	);
+
+/************ C ROUTINES USED BY U-BOOT AMBA CORE DRIVERS ************/
+struct ambapp_bus ambapp_plb;
+
+void ambapp_bus_init(
+	unsigned int ioarea,
+	unsigned int freq,
+	struct ambapp_bus *abus)
 {
-	int i, cnt = 0;
-	unsigned int apbmst_base;
-	ambapp_ahbdev apbmst;
-	apbctrl_pp_dev *apb;
-
-	if (max_cnt == 0)
-		return 0;
-
-	/* Get AMBA APB Master */
-	if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
-		return 0;
-	}
-
-	/* Get APB CTRL Plug&Play info area */
-	apbmst_base = apbmst.address[0] & LEON3_IO_AREA;
-	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
+	int i;
+
+	ambapp_find_buses(ioarea, abus);
+	for(i=0; i<6; i++)
+		if ( abus->ioareas[i] == 0 )
+			break;
+	abus->buses = i;
+	abus->freq = freq;
+}
 
-	for (i = 0; i < LEON3_APB_SLAVES; i++) {
-#if defined(CONFIG_CMD_AMBAPP)
-		if (ambapp_apb_print && amba_vendor(apb->conf)
-		    && amba_device(apb->conf)) {
-			ambapp_print_apb(apb, &apbmst, i);
-		}
-#endif
-		if ((amba_vendor(apb->conf) == vendor) &&
-		    (amba_device(apb->conf) == driver) && ((index < 0)
-							   || (index-- == 0))) {
-			/* Convert Plug&Play info into a more readable format */
-			cnt++;
-			if (dev) {
-				dev->irq = amba_irq(apb->conf);
-				dev->ver = amba_ver(apb->conf);
-				dev->address =
-				    (apbmst_base |
-				     (((apb->
-					bar & 0xfff00000) >> 12))) & (((apb->
-									bar &
-									0x0000fff0)
-								       << 4) |
-								      0xfff00000);
-				dev++;
-			}
-			/* found max devices? */
-			if (cnt >= max_cnt)
-				return cnt;
-		}
-		/* Get next Plug&Play entry */
-		apb++;
-	}
-	return cnt;
+/* Parse APB PnP Information */
+void ambapp_apb_parse(struct ambapp_find_apb_info *info, ambapp_apbdev *dev)
+{
+	struct ambapp_pnp_apb *apb = info->pnp;
+	unsigned int apbbase = (unsigned int)apb & 0xfff00000;
+
+	dev->vendor = amba_vendor(apb->id);
+	dev->device = amba_device(apb->id);
+	dev->irq = amba_irq(apb->id);
+	dev->ver = amba_ver(apb->id);
+	dev->address = (apbbase | (((apb->iobar & 0xfff00000) >> 12))) & 
+			(((apb->iobar &	0x0000fff0) << 4) | 0xfff00000);
+	dev->mask = amba_apb_mask(apb->iobar);
+	dev->ahb_bus_index = info->ahb_bus_index - 1;
 }
 
-unsigned int ambapp_apb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				   register unsigned int driver,	/* Plug&Play Device ID */
-				   register int index)
+/* Parse AHB PnP information */
+void ambapp_ahb_parse(struct ambapp_find_ahb_info *info, ambapp_ahbdev *dev)
 {
-	register int i;
-	register ahbctrl_pp_dev *apbmst;
-	register apbctrl_pp_dev *apb;
-	register unsigned int apbmst_base;
-
-	/* APBMST is a AHB Slave */
-	apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
-	if (!apbmst)
-		return 0;
-
-	apbmst_base = amba_membar_start(apbmst->bars[0]);
-	if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO)
-		apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base);
-	apbmst_base &= LEON3_IO_AREA;
-
-	/* Find the vendor/driver device on the first APB bus */
-	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
-
-	for (i = 0; i < LEON3_APB_SLAVES; i++) {
-		if ((amba_vendor(apb->conf) == vendor) &&
-		    (amba_device(apb->conf) == driver) && ((index < 0)
-							   || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			return (apbmst_base | (((apb->bar & 0xfff00000) >> 12)))
-			    & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
+	struct ambapp_pnp_ahb *ahb = info->pnp;
+	unsigned int ahbbase = (unsigned int)ahb & 0xfff00000;
+	int i, type;
+	unsigned int addr, mask, mbar;
+
+	dev->vendor = amba_vendor(ahb->id);
+	dev->device = amba_device(ahb->id);
+	dev->irq = amba_irq(ahb->id);
+	dev->ver = amba_ver(ahb->id);
+	dev->userdef[0] = ahb->custom[0];
+	dev->userdef[1] = ahb->custom[1];
+	dev->userdef[2] = ahb->custom[2];
+	dev->ahb_bus_index = info->ahb_bus_index - 1;
+	for (i=0; i<4; i++) {
+		mbar = ahb->mbar[i];
+		addr = amba_membar_start(mbar);
+		type = amba_membar_type(mbar);
+		if ( type == AMBA_TYPE_AHBIO ) {
+			addr = amba_ahbio_adr(addr, ahbbase);
+			mask = (((unsigned int)
+				(amba_membar_mask((~mbar))<<8)|0xff))+1;
+		} else {
+			/* AHB memory area, absolute address */
+			mask = (~((unsigned int)
+				(amba_membar_mask(mbar)<<20)))+1;
 		}
-		/* Get next Plug&Play entry */
-		apb++;
+		dev->address[i] = addr;
+		dev->mask[i] = mask;
+		dev->type[i] = type;
 	}
-	return 0;
 }
 
-/****************************** APB SLAVES ******************************/
-
-int ambapp_apb_count(unsigned int vendor, unsigned int driver)
+int ambapp_apb_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_apbdev *dev)
 {
-	return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
-}
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
+	int found;
+	struct ambapp_find_apb_info apbdev;
 
-int ambapp_apb_first(unsigned int vendor,
-		     unsigned int driver, ambapp_apbdev * dev)
-{
-	return ambapp_apb_scan(vendor, driver, dev, 0, 1);
+	found = ambapp_find_apb(abus, devid, index, &apbdev);
+	if ( found == 1 ) {
+		ambapp_apb_parse(&apbdev, dev);
+	}
+	return found;
 }
 
-int ambapp_apb_next(unsigned int vendor,
-		    unsigned int driver, ambapp_apbdev * dev, int index)
+int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device)
 {
-	return ambapp_apb_scan(vendor, driver, dev, index, 1);
-}
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
+	int found;
+	struct ambapp_find_apb_info apbdev;
 
-int ambapp_apbs_first(unsigned int vendor,
-		      unsigned int driver, ambapp_apbdev * dev, int max_cnt)
-{
-	return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
+	found = ambapp_find_apb(abus, devid, 63, &apbdev);
+	if ( found == 1 ) {
+		return 64;
+	} else {
+		return 63 - apbdev.dec_index;
+	}
 }
 
-enum {
-	AHB_SCAN_MASTER = 0,
-	AHB_SCAN_SLAVE = 1
-};
-
-/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves
- * for a certain matching Vendor and Device ID.
- *
- * Return number of devices found.
- *
- * Compact edition...
- */
-static int ambapp_ahb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */
-			   unsigned int driver,	/* Plug&Play Device ID */
-			   ambapp_ahbdev * dev,	/* Result(s) is placed here */
-			   int index,	/* Index of device to start copying Plug&Play
-					 * info into dev
-					 */
-			   int max_cnt,	/* Maximal count that dev can hold, if dev
-					 * is NULL function will stop scanning after
-					 * max_cnt devices are found.
-					 */
-			   int type	/* Selectes what type of devices to scan.
-					 * 0=AHB Masters
-					 * 1=AHB Slaves
-					 */
-    )
+int ambapp_ahb_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_ahbdev *dev,
+	int type
+	)
 {
-	int i, j, cnt = 0, max_pp_devs;
-	unsigned int addr;
-	ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
-	ahbctrl_pp_dev *ahb;
-
-	if (max_cnt == 0)
-		return 0;
-
-	if (type == 0) {
-		max_pp_devs = LEON3_AHB_MASTERS;
-		ahb = info->masters;
-	} else {
-		max_pp_devs = LEON3_AHB_SLAVES;
-		ahb = info->slaves;
-	}
+	int found;
+	struct ambapp_find_ahb_info ahbdev;
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
 
-	for (i = 0; i < max_pp_devs; i++) {
-#if defined(CONFIG_CMD_AMBAPP)
-		if (ambapp_ahb_print && amba_vendor(ahb->conf) &&
-		    amba_device(ahb->conf)) {
-			ambapp_print_ahb(ahb, i);
-		}
-#endif
-		if ((amba_vendor(ahb->conf) == vendor) &&
-		    (amba_device(ahb->conf) == driver) &&
-		    ((index < 0) || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			cnt++;
-			if (dev) {
-				dev->irq = amba_irq(ahb->conf);
-				dev->ver = amba_ver(ahb->conf);
-				dev->userdef[0] = ahb->userdef[0];
-				dev->userdef[1] = ahb->userdef[1];
-				dev->userdef[2] = ahb->userdef[2];
-				for (j = 0; j < 4; j++) {
-					addr = amba_membar_start(ahb->bars[j]);
-					if (amba_membar_type(ahb->bars[j]) ==
-					    AMBA_TYPE_AHBIO)
-						addr =
-						    AMBA_TYPE_AHBIO_ADDR(addr);
-					dev->address[j] = addr;
-				}
-				dev++;
-			}
-			/* found max devices? */
-			if (cnt >= max_cnt)
-				return cnt;
-		}
-		/* Get next Plug&Play entry */
-		ahb++;
+	found = ambapp_find_ahb(abus, devid, index, type, &ahbdev);
+	if ( found == 1 ) {
+		ambapp_ahb_parse(&ahbdev, dev);
 	}
-	return cnt;
+	return found;
 }
 
-unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
+int ambapp_ahbmst_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_ahbdev *dev)
 {
-	register unsigned int ret;
-
-	if (!ahb)
-		return 0;
-
-	switch (info) {
-	default:
-		info = 0;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		/* Get Address from PnP Info */
-		ret = amba_membar_start(ahb->bars[info]);
-		if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO)
-			ret = AMBA_TYPE_AHBIO_ADDR(ret);
-		return ret;
-	}
-	return 0;
+	return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_MST);
+}
 
+int ambapp_ahbslv_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_ahbdev *dev)
+{
+	return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_SLV);
 }
 
-ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				      register unsigned int driver,	/* Plug&Play Device ID */
-				      register unsigned int opts,	/* 1=slave, 0=master */
-				      register int index)
+int ambapp_ahb_count(struct ambapp_bus *abus, int vendor, int device, int type)
 {
-	register ahbctrl_pp_dev *ahb;
-	register ahbctrl_info *info =
-	    (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
-	register int i;
-	register int max_pp_devs;
-
-	if (opts == 0) {
-		max_pp_devs = LEON3_AHB_MASTERS;
-		ahb = info->masters;
-	} else {
-		max_pp_devs = LEON3_AHB_SLAVES;
-		ahb = info->slaves;
-	}
+	int found;
+	struct ambapp_find_ahb_info ahbdev;
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
 
-	for (i = 0; i < max_pp_devs; i++) {
-		if ((amba_vendor(ahb->conf) == vendor) &&
-		    (amba_device(ahb->conf) == driver) &&
-		    ((index < 0) || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			return ahb;
-		}
-		/* Get next Plug&Play entry */
-		ahb++;
+	found = ambapp_find_ahb(abus, devid, 63, type, &ahbdev);
+	if ( found == 1 ) {
+		return 64;
+	} else {
+		return 63 - ahbdev.dec_index;
 	}
-	return 0;
 }
 
-/****************************** AHB MASTERS ******************************/
-int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver)
+int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device)
 {
-	/* Get number of devices of this vendor&device ID */
-	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,
-			       AHB_SCAN_MASTER);
+	return ambapp_ahb_count(abus, vendor, device, DEV_AHB_MST);
 }
 
-int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,
-			ambapp_ahbdev * dev)
+int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device)
 {
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);
+	return ambapp_ahb_count(abus, vendor, device, DEV_AHB_SLV);
 }
 
-int ambapp_ahbmst_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);
-}
+/* The define CONFIG_SYS_GRLIB_SINGLE_BUS may be defined on GRLIB systems
+ * where only one AHB Bus is available - no bridges are present. This option
+ * is available only to reduce the footprint.
+ *
+ * Defining this on a multi-bus GRLIB system may also work depending on the
+ * design.
+ */
 
-int ambapp_ahbmsts_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,
-			       AHB_SCAN_MASTER);
-}
+#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
 
-/****************************** AHB SLAVES ******************************/
-int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver)
-{
-	/* Get number of devices of this vendor&device ID */
-	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,
-			       AHB_SCAN_SLAVE);
-}
+/* GAISLER AHB2AHB Version 1 Bridge Definitions */
+#define AHB2AHB_V1_FLAG_FFACT     0x0f0	/* Frequency factor against top bus */
+#define AHB2AHB_V1_FLAG_FFACT_DIR 0x100	/* Factor direction, 0=down, 1=up */
+#define AHB2AHB_V1_FLAG_MBUS      0x00c	/* Master bus number mask */
+#define AHB2AHB_V1_FLAG_SBUS      0x003	/* Slave bus number mask */
 
-int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,
-			ambapp_ahbdev * dev)
+/* Get Parent bus frequency. Note that since we go from a "child" bus 
+ * to a parent bus, the frequency factor direction is inverted.
+ */
+unsigned int gaisler_ahb2ahb_v1_freq(ambapp_ahbdev *ahb, unsigned int freq)
 {
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);
+	int dir;
+	unsigned char ffact;
+
+	/* Get division/multiple factor */
+	ffact = (ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT) >> 4;
+	if ( ffact != 0 ) {
+		dir = ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT_DIR;
+
+		/* Calculate frequency by dividing or 
+		 * multiplying system frequency 
+		 */
+		if ( dir ) {
+			freq = freq * ffact;
+		} else {
+			freq = freq / ffact;
+		}
+	}
+
+	return freq;
 }
 
-int ambapp_ahbslv_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index)
+/* AHB2AHB and L2CACHE ver 2 is not supported yet. */
+unsigned int gaisler_ahb2ahb_v2_freq(ambapp_ahbdev *ahb, unsigned int freq)
 {
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);
+	printf("gaisler_ahb2ahb_v2_freq: AHB2AHB ver 2 not supported\n");
+	while(1) ;
 }
+#endif
 
-int ambapp_ahbslvs_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
+/* Return the frequency of a AHB bus identified by index found 
+ * note that this is not the AHB Bus number.
+ */
+unsigned int ambapp_bus_freq (
+	struct ambapp_bus *abus,
+	int ahb_bus_index
+	)
 {
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);
+	unsigned int freq = abus->freq;
+#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
+	unsigned int ioarea, ioarea_parent, bridge_pnp_ofs;
+	struct ambapp_find_ahb_info ahbinfo;
+	ambapp_ahbdev ahb;
+	int parent;
+
+	debug("ambapp_bus_freq: get freq on bus %d\n", ahb_bus_index);
+
+	while ( ahb_bus_index != 0) {
+
+		debug("  BUS[0]: 0x%08x\n", abus->ioareas[0]);
+		debug("  BUS[1]: 0x%08x\n", abus->ioareas[1]);
+		debug("  BUS[2]: 0x%08x\n", abus->ioareas[2]);
+		debug("  BUS[3]: 0x%08x\n", abus->ioareas[3]);
+		debug("  BUS[4]: 0x%08x\n", abus->ioareas[4]);
+		debug("  BUS[5]: 0x%08x\n", abus->ioareas[5]);
+
+		/* Get I/O area of AHB bus */
+		ioarea = abus->ioareas[ahb_bus_index];
+		
+		printf("  IOAREA: 0x%08x\n", ioarea);
+
+		/* Get parent bus */
+		parent = (ioarea & 0x7);
+		if ( parent == 0 ) {
+			printf("ambapp_bus_freq: parent=0 indicates no parent! Stopping.\n");
+			while(1) ;
+		}
+		parent = parent - 1;
+		bridge_pnp_ofs = ioarea & 0x7e0;
+
+		debug("  PARENT: %d\n", parent);
+		debug("  BRIDGE_OFS: 0x%08x\n", bridge_pnp_ofs);
+
+		/* Get AHB/AHB bridge PnP address */
+		ioarea_parent = (abus->ioareas[parent] & 0xfff00000) | 
+				AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA;
+		ahbinfo.pnp = (struct ambapp_pnp_ahb *)
+			(ioarea_parent | bridge_pnp_ofs);
+
+		debug("  IOAREA PARENT: 0x%08x\n", ioarea_parent);
+		debug("  BRIDGE PNP: 0x%08x\n", ahbinfo.pnp);
+
+		/* Parse the AHB information */
+		ahbinfo.ahb_bus_index = parent;
+		ambapp_ahb_parse(&ahbinfo, &ahb);
+
+		debug("  BRIDGE ID: VENDOR=%d(0x%x), DEVICE=%d(0x%x)\n", 
+			ahb.vendor, ahb.vendor, ahb.device, ahb.device);
+
+		/* Different bridges may convert frequency differently */
+		if ( (ahb.vendor == VENDOR_GAISLER) &&
+			((ahb.device == GAISLER_AHB2AHB) ||
+			(ahb.device == GAISLER_L2CACHE)) ) {
+			/* Get new frequency */
+			if ( ahb.ver > 1 ) {
+				freq = gaisler_ahb2ahb_v2_freq(&ahb, freq);
+			} else {
+				freq = gaisler_ahb2ahb_v1_freq(&ahb, freq);
+			}
+			debug("  NEW FREQ: %dHz\n", freq);
+		} else {
+			printf("ambapp_bus_freq: unsupported AMBA bridge\n");
+			while(1) ;
+		}
+
+		/* Step upwards towards system top bus */
+		ahb_bus_index = parent;
+	}
+#endif
+
+	debug("ambapp_bus_freq: %dHz\n", freq);
+
+	return freq;
 }
diff --git a/cpu/leon3/ambapp_low.S b/cpu/leon3/ambapp_low.S
new file mode 100644
index 0000000..bbf2d01
--- /dev/null
+++ b/cpu/leon3/ambapp_low.S
@@ -0,0 +1,798 @@
+/* GRLIB AMBA Plug&Play information scanning implemented without
+ * using memory (stack) and one register window. The code scan
+ * the PnP info and inserts the AHB bridges/buses into register
+ * i0-i5.
+ * The code support 
+ *  - up to 6 AHB buses
+ *  - multiple APB buses
+ *  - support for AHB2AHB & L2CACHE bridges
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <ambapp.h>
+
+	.seg	"text"
+	.globl	_nomem_amba_init
+	.globl	_nomem_ambapp_find_buses
+	.globl	_nomem_find_apb
+	.globl	_nomem_find_ahb
+
+/* Overview
+ * ========
+ *
+ * _nomem_amba_init         - Init AMBA bus and calls _nomem_ambapp_find_buses
+ * _nomem_ambapp_find_buses - Scan AMBA PnP info for AHB buses/bridges and 
+ *                            place them in i0-i5, see below
+ * _nomem_find_apb          - Find one APB device identified by VENDOR:DEVICE
+ *                            ID and an index.
+ * _nomem_find_ahb          - Find one AHB Master or Slave device identified 
+ *                            by VENDOR:DEVICE ID and an index.
+ * init_ahb_bridges         - Local function. Clears i0-i5
+ * insert_ahb_bridge        - Local function. Insert a new AHB bus into first
+ *                            free register in i0-i5. It also checks that the
+ *                            bus has not already been added.
+ * get_ahb_bridge           - Local function. Get AHB bus from registers, 
+ *                            return register iN, where N is defined by o0.
+ *
+ * The _nomem_find_apb and _nomem_find_ahb function requires that i0-i5
+ * are populated with the AHB buses of the system. The registers are 
+ * initialized by _nomem_ambapp_find_buses.
+ *
+ * AHB Bus result and requirements of i0-i5
+ * ========================================
+ *
+ * i0: AHB BUS0 IOAREA, no parent bus
+ * i1: AHB BUS1 IOAREA, parent bus is always i0 (AHB BUS0) and bridge address
+ * i2: AHB BUS2 IOAREA, 3-bit parent bus number and bridge address
+ * i3: AHB BUS3 IOAREA, 3-bit parent bus number and bridge address
+ * i4: AHB BUS4 IOAREA, 3-bit parent bus number and bridge address
+ * i5: AHB BUS5 IOAREA, 3-bit parent bus number and bridge address
+ *
+ * AHB BUS
+ * -------
+ * Bits 31-20 (0xfff00000) contain the found bus I/O Area (AHB PnP area).
+ *
+ * 3-bit Parent bus
+ * ----------------
+ * Bits 2-0 (0x00000007) contain parent bus number. Zero if no parent
+ * bus, 1 = parent is AHB BUS 0 (i0), 2 = parent is AHB BUS 1 (i1)..
+ * 
+ * Bridge Address
+ * --------------
+ * Bits 10-5 (0x000007e0) contain the index of the Bridge's PnP 
+ * information on the parent. Since all bridges are found in the
+ * PnP information they all have a PnP entry. Together with the
+ * parent bus number the PnP entry can be found:
+ *  PnPEntry = (BRIDGE_ADDRESS + (iN & 0xfff00000)) | 0x000ff800
+ *  where N is the parent bus minus one.
+ *
+ */
+
+/* Function initializes the AHB Bridge I/O AREA storage. (Clears i0-i5)
+ *
+ * Arguments
+ *  none
+ * 
+ * Results
+ *  none
+ *
+ * Clobbered
+ *  none
+ */
+
+init_ahb_bridges:
+	mov	%g0, %i0
+	mov	%g0, %i1
+	mov	%g0, %i2
+	mov	%g0, %i3
+	mov	%g0, %i4
+	retl
+	 mov	%g0, %i5
+
+/* Function returns AHB Bridge I/O AREA for specified bus. 
+ *
+ * Arguments
+ *  - o0 = bus number
+ * 
+ * Results
+ *  - o0 = I/O AREA
+ *
+ * Clobbered
+ *  none
+ */
+get_ahb_bridge:
+	cmp	%o0, 1
+	be,a	L1
+	 mov	%i0, %o0
+
+	cmp	%o0, 2
+	be,a	L1
+	 mov	%i1, %o0
+
+	cmp	%o0, 3
+	be,a	L1
+	 mov	%i2, %o0
+
+	cmp	%o0, 4
+	be,a	L1
+	 mov	%i3, %o0
+
+	cmp	%o0, 5
+	be,a	L1
+	 mov	%i4, %o0
+
+	cmp	%o0, 6
+	be,a	L1
+	 mov	%i5, %o0
+
+	/* o0 > 6: only 6 buses supported */
+	mov	%g0, %o0
+L1:
+	retl
+	 nop
+
+/* Function adds a AHB Bridge I/O AREA to the i0-i5 registers if
+ * not already added. It stores the bus PnP start information.
+ *
+ * Arguments
+ *  - o0 = AHB Bridge I/O area
+ * 
+ * Results
+ *  none
+ *
+ * Clobbered
+ *  o2, o3
+ */
+insert_ahb_bridge:
+	/* Check that bridge hasn't already been added */
+	andn	%o0, 0x7ff, %o2
+	andn	%i0, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+	 andn	%i1, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+	 andn	%i2, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+	 andn	%i3, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+	 andn	%i4, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+	 andn	%i5, 0x7ff, %o3
+	cmp	%o3, %o2
+	be	L2
+
+	/* Insert into first free posistion */
+	 cmp	%i0, %g0
+	be,a	L2
+	 mov	%o0, %i0
+
+	cmp	%i1, %g0
+	be,a	L2
+	 mov	%o0, %i1
+
+	cmp	%i2, %g0
+	be,a	L2
+	 mov	%o0, %i2
+
+	cmp	%i3, %g0
+	be,a	L2
+	 mov	%o0, %i3
+
+	cmp	%i4, %g0
+	be,a	L2
+	 mov	%o0, %i4
+
+	cmp	%i5, %g0
+	be,a	L2
+	 mov	%o0, %i5
+L2:
+	retl
+	 nop
+
+/* FUNCTION int _nomem_find_ahb_bus(
+ *	unsigned int bridge,
+ *	int vendor_device,
+ *	int index,
+ *	void **pconf,
+ *	int not_used,
+ *	int option
+ *	)
+ *
+ * Scans the AHB Master or Slave area for a matching VENDOR:DEVICE, the 
+ * index is decremented when a matching device is found but index is 
+ * greater than zero. When index is zero and a matching DEVICE:VENDOR
+ * is found the AHB configuration address and AHB I/O area is returned.
+ *
+ * i0-i7,l0,l1,l2,l3,l4,g2,o6 is not available for use.
+ * o1,o5 Must be left untouched
+ *
+ * Results
+ *  - o0 Number of found devices (1 or 0)
+ *  - o2 is decremented for each matching VENDOR:DEVICE found, zero if found
+ *  - o3 Address of the AHB PnP configuration entry (Only valid if o0=1)
+ *
+ * Clobbered
+ *  - o3 (Clobbered when no device was found)
+ *  - o4 (Number of Devices left to search)
+ *  - o0 (Bus ID, PnP ID, Device)
+ */
+_nomem_find_ahb_bus:
+
+	/* Get number of Slaves/Masters. Only AHB Bus 0 has 64 AHB Masters/Slaves 
+	 * the other AHB buses has 16 slaves and 16 masters.
+	 */
+	add	%g0, 16, %o4		/* Defaulting to 16 */
+	andcc	%o0, 0x7, %g0		/* 3-bit bus id */
+	be,a	.L_maxloops_detected
+	 add	%g0, 64, %o4		/* AHB Bus 0 has 64 AHB Masters and Slaves */
+.L_maxloops_detected:
+
+	/* Get start address of AHB Slave or AHB Master area depending on what
+	 * we are searching for.
+	 */
+	andn	%o0, 0x7ff, %o0		/* Remove Bus ID and 5-bit AHB/AHB Bridge PnP Address to get I/O Area */
+	set	AMBA_CONF_AREA, %o3
+	or	%o3, %o0, %o3		/* Master area address */
+
+	cmp	%o5, DEV_AHB_SLV
+	be,a	.L_conf_area_calculated
+	 or	%o3, AMBA_AHB_SLAVE_CONF_AREA, %o3	/* Add 0x800 to get to slave area */
+.L_conf_area_calculated:
+
+	/* Iterate over all AHB device and try to find matching DEVICE:VENDOR 
+	 * o1 - VENDOR|DEVICE
+	 * o2 - Index
+	 * o3 - Current AHB Device Configuration address
+	 * o5 - Type (leave untouched)
+	 * 
+	 * o4 - Number of AHB device left to process
+	 * o0 - tmp
+	 */
+.L_process_one_conf:
+	ld	[%o3], %o0
+	andn	%o0, 0xfff, %o0
+	cmp	%o0, 0			/* No device if zero */
+	beq	.L_next_conf
+	 cmp	%o1, 0 			/* If VENDOR:DEVICE==0, consider all matching */
+	beq	.L_process_ahb_dev_found
+	 cmp	%o0, %o1		/* Does VENDOR and DEVICE Match? */
+	bne	.L_next_conf
+	 nop
+.L_process_ahb_dev_found:
+	/* Found a Matching VENDOR:DEVICE, index must also match */
+	cmp	%o2, %g0
+	bne	.L_next_conf
+	 dec	%o2
+	/* Index matches also, return happy with o3 set to AHB Conf Address */
+	mov	%g0, %o2
+	retl
+	 add	%g0, 1, %o0
+
+.L_next_conf:
+	subcc	%o4, 1, %o4			/* One device has been processed, Are there more devices to process? */
+	bne	.L_process_one_conf
+	 add	%o3, AMBA_AHB_CONF_LENGH, %o3	/* Next Configuration entry */
+	/* No Matching device found */
+	retl
+	 mov	%g0, %o0
+
+/* FUNCTION int _nomem_find_ahb(
+ *      int unused,
+ *	int vendor_device,
+ *	int index,
+ *	void **pconf,
+ *	int *ahb_bus_index,
+ *	int option,
+ *	)
+ * 
+ * Find a AHB Master or AHB Slave device, it puts the address of the AHB PnP
+ * configuration in o3 (pconf), the I/O Area base address in o4 (pioarea).
+ *
+ * Calls _nomem_find_ahb_bus for every AHB bus.
+ *
+ * i0-i7, l0, l1, o6, g1, g4-g7 is not available for use.
+ *
+ * Arguments
+ *  - o0 Unused
+ *
+ * Results
+ *  - o0 Number of found devices (1 or 0)
+ *  - o2 Decremented Index (Zero if found)
+ *  - o3 Address of the AHB PnP configuration entry
+ *  - o4 AHB Bus index the device was found on (if o0=1)
+ *  - o5 Left untouched
+ *
+ * Clobbered
+ *  - o0 (AHB Bridge and used by _nomem_find_ahb_bus)
+ *  - o2 (index is decremented)
+ *  - l2 (Current AHB Bus index)
+ *  - g2 (return address)
+ */
+_nomem_find_ahb:
+	mov	%o7, %g2		/* Save return address */
+	/* Scan all AHB Buses found for the AHB Master/Slave matching VENDOR:DEVICE */
+	clr	%l2
+.L_search_next_ahb_bus:
+	add	%l2, 1, %l2
+	call	get_ahb_bridge			/* Get bus %l0 I/O Area */
+	 mov	%l2, %o0
+	cmp	%o0, %g0
+	be	.L_no_device_found		/* If no more AHB bus is left to be scanned, proceed */
+	 nop
+	call	_nomem_find_ahb_bus		/* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented  */
+	 nop
+	cmp	%o0, %g0			/* If VENDOR:DEVICE was not found scan next AHB Bus */
+	be	.L_search_next_ahb_bus		/* Do next bus is o0=0 (not found) */
+	 nop
+	/* The device was found, o0 is 1 */
+	mov	%g2, %o7		/* Restore return address */
+	retl
+	 mov	%l2, %o4		/* The AHB bus index the device was found on */
+
+	/* No device found matching */
+.L_no_device_found:
+	mov	%g2, %o7		/* Restore return address */
+	retl
+	 mov	%g0, %o0
+
+
+/* FUNCTION int _nomem_find_apb_bus(
+ *      int apbmst,
+ *	int vendor_device,
+ *	int index,
+ *	void **pconf
+ *	)
+ * 
+ * Find a APB Slave device, it puts the address of the APB PnP configuration 
+ * in o3 (pconf).
+ *
+ * Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
+ * The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
+ *
+ * Results
+ *  - o0 Number of found devices (1 or 0)
+ *  - o2 Decremented Index
+ *  - o3 Address of the found APB device PnP configuration entry
+ *
+ * Clobbered
+ *  - o5 PnP VENDOR:DEVICE ID
+ */
+
+_nomem_find_apb_bus:
+	set	AMBA_CONF_AREA, %o3
+	or	%o0, %o3, %o3		/* Calc start of APB device PnP info */
+	add	%g0, 16, %o0		/* o0, number of APB Slaves left to scan */
+.L_process_one_apb_conf:
+	ld	[%o3], %o5
+	andn	%o5, 0xfff, %o5
+	cmp	%o5, 0			/* No device if zero */
+	beq	.L_process_apb_dev_not_found
+	 cmp	%o1, 0			/* If VENDOR:DEVICE == -1, consider all matching */
+	beq	.L_process_apb_dev_found
+	 cmp	%o1, %o5		/* Found VENDOR:DEVICE */
+	bne	.L_process_apb_dev_not_found
+	 nop
+
+.L_process_apb_dev_found:
+	/* Found matching device, compare index */
+	cmp	%o2, %g0
+	bne	.L_process_apb_dev_not_found
+	 dec	%o2
+	/* Matching index and VENDOR:DEVICE */
+	retl
+	 add	%g0, 1, %o0
+
+.L_process_apb_dev_not_found:
+	subcc	%o0, 1, %o0
+	bne	.L_process_one_apb_conf
+	 add	%o3, 8, %o3
+	retl
+	 mov	%g0, %o0
+
+/* FUNCTION int _nomem_find_apb(
+ *      int unused,
+ *	int vendor_device,
+ *	int index,
+ *	void **pconf,
+ *	int *ahb_bus_index
+ *	)
+ * 
+ * Find a APB Slave device, it puts the address of the APB PnP configuration 
+ * in o3 (pconf), the APB Master I/O Area base address in o4 (papbarea).
+ *
+ * Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
+ * The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
+ *
+ * i0-i7, l0, l1, o6 is not available for use.
+ *
+ * Arguments
+ *  - o0 Unused
+ *
+ * Results
+ *  - o0 Number of found devices (1 or 0)
+ *  - o2 Decremented Index if not found
+ *  - o3 Address of the APB PnP configuration entry
+ *  - o4 AHB Bus index of APB Bridge/APB Device
+ *
+ * Clobbered
+ *  - o0 (AHB Bridge)
+ *  - o2 (index is decremented)
+ *  - l2 (APB DEV Index [7..4] : APBMST AHB Index [3..0])
+ *  - l3 (Current AHB Bus index)
+ *  - l4 (temporary storage for APB VENDOR:DEVICE)
+ *  - o5 (AHB Slave ID)
+ *  - o0 (clobbered by _nomem_find_ahb_bus)
+ *  - g2 (Return address)
+ */
+_nomem_find_apb:
+	/* Scan all AHB Buses found for AHB/APB Bridges */
+	mov	%o7, %g2		/* Save return address */
+	mov	%o1, %l4		/* Save APB VENDOR:DEVICE */
+	sll	%o2, 4, %l2		/* APB MST index = 0 */
+	add	%g0, 1, %l3		/* AHB Bus index = 0 */
+.L2_search_next_ahb_bus:
+	call	get_ahb_bridge		/* Get bus %l3 I/O Area */
+	 mov	%l3, %o0
+	cmp	%o0, %g0
+	be	.L2_no_device_found	/* If no more AHB bus is left to be scanned, proceed */
+	 add	%g0, DEV_AHB_SLV, %o5	/* Search for AHB Slave */
+	sethi	%hi(AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_APBMST)), %o1
+	call	_nomem_find_ahb_bus	/* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented  */
+	 and	%l2, 0xf, %o2		/* Set APBMST index */
+	cmp	%o0, %g0		/* If no AHB/APB Bridge was not found, scan next AHB Bus */
+	be	.L_no_apb_bridge_found	/* Do next bus */
+	 nop
+
+	/* The AHB/APB Bridge was found.
+         * Search for the requested APB Device on the APB bus using
+	 * find_apb_bus, it will decrement the index.
+         */
+	ld	[%o3 + AMBA_AHB_MBAR0_OFS], %o3
+	sll	%o3, 16, %o0
+	and	%o0, %o3, %o0		/* Address AND Address Mask */
+	sethi	%hi(0xfff00000), %o3
+	and	%o0, %o3, %o0		/* AHB/APB Bridge address */
+
+	srl	%l2, 4, %o2		/* APB DEV Index */
+	call	_nomem_find_apb_bus
+	 mov	%l4, %o1		/* APB VENDOR:DEVICE */
+	cmp	%o0, %g0
+	be	.L_apb_dev_not_found
+	 mov	%g2, %o7		/* Restore return address */
+	/* APB Device found
+	 * o0 1
+	 * o2 Index is decremented to zero
+	 * o3 APB configuration address,
+	 * o4 APB Bridge Configuration address.
+	 */
+	mov	%g0, %o2
+	retl
+	 mov	%l3, %o4
+
+.L_apb_dev_not_found:
+	/* Update APB DEV Index by saving output from find_apb_bus
+	 * (index parameter) into bits [31..4] in L2.
+	 */
+	sll	%o2, 4, %o2
+	and	%l2, 0xf, %l2
+	or	%o2, %l2, %l2
+	/* Try finding the next AHB/APB Bridge on the same AHB bus
+	 * to find more APB devices
+	 */
+	ba	.L2_search_next_ahb_bus	/* Find next AHB/APB bridge */
+	 inc	%l2
+
+.L_no_apb_bridge_found:
+	inc	%l3			/* Next AHB Bus */
+	ba	.L2_search_next_ahb_bus	/* Process next AHB bus */
+	 andn	%l2, 0xf, %l2		/* Start at APB Bridge index 0 at every AHB Bus */
+	/* No device found matching */
+.L2_no_device_found:
+	mov	%g2, %o7		/* Restore return address */
+	srl	%l2, 4, %o2		/* APB DEV Index */
+	retl
+	 mov	%g0, %o0
+
+
+
+/* FUNCTION _nomem_amba_scan_gaisler_ahb2ahb_bridge(unsigned int bridge, int bus)
+ *
+ * Constraints:
+ *   - o1 may not be used
+ *   - o0, o2, o3 may be used.
+ *
+ * Arguments
+ *  - o0 PnP Address of Bridge AHB device
+ *  - o2 PnP ID of AHB device
+ *
+ * Results
+ *  - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
+ *
+ * Clobbered
+ *   - o0, o2
+ *
+ */
+_nomem_amba_scan_gaisler_ahb2ahb_bridge:
+	andn	%o2, 0xfff, %o2
+	sethi	%hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_AHB2AHB)), %o3
+	cmp	%o2, %o3
+	beq	.L_is_ahb2ahb_bridge
+	 nop
+
+	retl
+	 add	%g0, 1, %o0
+
+.L_is_ahb2ahb_bridge:
+	/* Found a GAISLER AHB2AHB bridge */
+	retl
+	 ld	[%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
+
+
+/* FUNCTION _nomem_amba_scan_gaisler_l2cache_bridge(unsigned int bridge, int bus)
+ *
+ * Constraints:
+ *   - o1 may not be used
+ *   - o0, o2, o3 may be used.
+ *
+ * Arguments
+ *  - o0 PnP Address of Bridge AHB device
+ *  - o2 PnP ID of AHB device
+ *
+ * Results
+ *  - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
+ *
+ * Clobbered
+ *   - o0, o2
+ *
+ */
+_nomem_amba_scan_gaisler_l2cache_bridge:
+	andn	%o2, 0xfff, %o2
+	sethi	%hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_L2CACHE)), %o3
+	cmp	%o2, %o3
+	beq	.L_is_l2cache_bridge
+	 nop
+
+	retl
+	 add	%g0, 1, %o0
+
+.L_is_l2cache_bridge:
+	/* Found a GAISLER l2cache bridge */
+	retl
+	 ld	[%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
+
+
+/* FUNCTION _nomem_amba_scan(unsigned int bridge, int bus)
+ * 
+ * Constraints:
+ *  i0-i7, l0 is used by caller
+ *  o5-o7 may not be used.
+ *
+ * Arguments
+ *  - o0 Bridge Information: I/O AREA and parent bus
+ *  - o1 Bus
+ *
+ * Results
+ *  - o0 Number of AHB bridges found
+ *
+ * Clobbered
+ *  - o0 (Current AHB slave conf address)
+ *  - o2 (Used by insert_bridge)
+ *  - o3 (Used by insert_bridge)
+ *  - l1 (Number of AHB Slaves left to process)
+ *  - l2 (Current AHB slave conf address)
+ *  - g2 (Return address)
+ */
+_nomem_amba_scan:
+	mov	%o7, %g2	/* Save return address */
+	set	16, %l1	
+	cmp	%o1, 1
+	be,a	.L2_maxloops_detected
+	 add	%g0, 64, %l1
+.L2_maxloops_detected:
+
+	/* Clear 3-bit parent bus from bridge to get I/O AREA, then or
+	 * (AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA) to get first AHB slave
+	 * conf address.
+	 */
+	andn	%o0, 0x7ff, %o0
+	set	(AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA), %l2
+	or	%o0, %l2, %l2
+
+	/* Scan AHB Slave area for AHB<->AHB bridges. For each AHB device
+	 * all "bridge drivers" are called, the driver function interface:
+	 *
+	 * Input: 
+	 *   - o0 PnP Address of Bridge AHB device
+	 *   - o2 PnP ID of AHB device
+	 * Return values:
+	 *   - o0 Address of new bus PnP area, returning a 1 in o2 means not found
+	 *
+	 * Constraints:
+	 *   - o1 may not be used
+	 *   - o0, o2, o3 may be used.
+	 *
+	 */
+.L_scan_one_ahb_slave:
+	ld	[%l2], %o2
+
+	cmp	%o2, %g0
+	beq	.L_scan_next_ahb_slave
+	 nop
+
+	/* Call the GAISLER AHB2AHB bridge driver */
+	call	_nomem_amba_scan_gaisler_ahb2ahb_bridge
+	 mov	%l2, %o0
+	cmp	%o0, 1
+	bne	.L_found_bridge
+	 ld	[%l2], %o2
+
+	/* Call the GAISLER L2CACHE bridge driver */
+	call	_nomem_amba_scan_gaisler_l2cache_bridge
+	 mov	%l2, %o0
+	cmp	%o0, 1
+	bne	.L_found_bridge
+	 ld	[%l2], %o2
+
+	/* Insert next bridge "driver" function here */
+
+
+	/* The PnP ID did not match a bridge - a new bus was not found ==> 
+	 * step to next AHB device */
+	ba	.L_scan_next_ahb_slave
+	 nop
+
+	/* Add Found bus */
+.L_found_bridge:
+	and	%l2, 0x7e0, %o2
+	or	%o2, %o0, %o0		/* Add AHB/AHB Bridge PnP address */
+	call	insert_ahb_bridge	/* Insert Bridge into found buses storage */
+	 or	%o1, %o0, %o0		/* Add parent bus LSB 3-bits */
+
+.L_scan_next_ahb_slave:
+	/* More Slaves to process? */
+	subcc	%l1, 1, %l1
+	bne	.L_scan_one_ahb_slave
+	 add	%l2, AMBA_AHB_CONF_LENGH, %l2
+
+	/* No more AHB devices to process */
+	mov	%g2, %o7	/* Restore return address */
+	retl
+	 nop
+
+/* FUNCTION _nomem_ambapp_find_buses(unsigned int ioarea)
+ * 
+ * Find AMBA AHB buses.
+ *
+ * Constraints:
+ *  i6-i7, l7 is used by caller
+ *
+ * Arguments
+ *  - o0 Bridge Information: I/O AREA and parent bus
+ *
+ * Results
+ *  - o0 Number of AHB bridges found
+ *  - i0-i5 initialized
+ *
+ * Clobbered
+ *  - o0 (Current AHB slave conf address)
+ *  - o2 (Used by insert_bridge)
+ *  - o3 (Used by insert_bridge)
+ *  - l0 (Current AHB Bus)
+ *  - l1 (Used by nomem_amba_scan)
+ *  - l2 (Used by nomem_amba_scan)
+ *  - l3 (Used by nomem_amba_scan)
+ *  - l4 (Used by nomem_amba_scan)
+ *
+ *  - g1 (level 1 return address)
+ *  - g2 (Used by nomem_amba_scan)
+ */
+_nomem_ambapp_find_buses:
+	mov	%o7, %g1	/* Save return address */
+
+	/* Initialize AHB Bus storage */
+	call	init_ahb_bridges
+	 nop
+
+	/* Insert AHB Bus 0 */
+	call	insert_ahb_bridge
+	 nop			/* Argument already prepared by caller */
+
+	/* Scan AHB Bus 0 for AHB Bridges */
+	call	_nomem_amba_scan
+	 add	%g0, 1, %o1
+
+	/* Scan all AHB Buses found for more AHB Bridges */
+	add	%g0, 2, %l0
+.L100_search_next_ahb_bus:
+	call	get_ahb_bridge			/* Get bus %l0 I/O Area */
+	 mov	%l0, %o0
+	cmp	%o0, %g0
+	be	.L100_return			/* If no more AHB bus is left to be scanned, proceed */
+	 nop
+	call	_nomem_amba_scan		/* Scan bus %l0 for AHB Bridges. i0-i7,l0 is used */
+	 mov	%l0, %o1			/* I/O AREA untouched in o0 */
+	ba	.L100_search_next_ahb_bus	/* Do next bus */
+	 add	%l0, 1, %l0
+
+.L100_return:
+	mov	%g1, %o7
+	retl
+	 nop
+
+
+/* FUNCTION _nomem_amba_init(unsigned int ioarea)
+ * 
+ *  Find all AHB buses
+ *
+ * Constraints:
+ *  i6, i7, o6, o7, l7, l6, g3, g4, g5, g6, g7 is used by caller
+ *
+ * Arguments
+ *  - o0 Bridge Information: I/O AREA and parent bus
+ *
+ * Results
+ *  - o0 Number of AHB bridges found
+ *
+ * Clobbered
+ *  - l0, l1, l2, l3, l4, g1, g2 (used by _nomem_ambapp_find_buses)
+ *  - o0, o1, o2, o3 (Used as arguments)
+ *  - o5 (return address)
+ *  - g1 (level 1 return address)
+ *  - g2 (level 2 return address)
+ */
+_nomem_amba_init:
+	mov	%o7, %o5	/* Save return address, o5 not used */
+
+	/* Scan for buses, it will init i0-i5 */
+	call	_nomem_ambapp_find_buses
+	 nop
+
+	mov	%o5, %o7
+	retl
+	 nop
+
+/* Call tree and their return address register
+ *
+ *_nomem_amba_scan           (g1)
+ * -> init_ahb_bridges       (o7)
+ * -> insert_ahb_bridge      (o7)
+ * -> _nomem_amba_scan       (g2)
+ *    -> insert_ahb_bridge   (o7)
+ * -> get_ahb_bridge         (o7)
+ *
+ *
+ * -> _nomem_find_apb        (g2)
+ *    -> get_ahb_bridge      (o7)
+ *    -> _nomem_find_ahb_bus (o7)
+ *    -> _nomem_find_apb_bus (o7)
+ * -> _nomem_find_ahb        (g2)
+ *    -> get_ahb_bridge      (o7)
+ *    -> _nomem_find_ahb_bus (o7)
+ * -> mem_handler.func()     (o7)
+ * 
+ */
diff --git a/cpu/leon3/ambapp_low_c.S b/cpu/leon3/ambapp_low_c.S
new file mode 100644
index 0000000..4ca6d55
--- /dev/null
+++ b/cpu/leon3/ambapp_low_c.S
@@ -0,0 +1,133 @@
+/* C-interface for AMBA PnP scanning functions implemented in 
+ * ambapp_low.S. At the point the memory and stack can be 
+ * used.
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+
+	.seg	"text"
+	.extern	_nomem_ambapp_find_buses
+	.extern	_nomem_find_apb
+	.extern	_nomem_find_ahb
+
+	.globl	ambapp_find_buses
+	.globl	ambapp_find_apb
+	.globl	ambapp_find_ahb
+
+
+/* C-interface for _nomem_ambapp_find_buses used when memory is
+ * available.
+ */
+ambapp_find_buses:
+	save	%sp, -104, %sp
+	mov	%i1, %l7	/* Save second argument */
+	call _nomem_ambapp_find_buses
+	 mov	%i0, %o0
+
+	/* Store result */
+	st	%g0, [%l7+0x00]
+	st	%i0, [%l7+0x04]
+	st	%i1, [%l7+0x08]
+	st	%i2, [%l7+0x0c]
+	st	%i3, [%l7+0x10]
+	st	%i4, [%l7+0x14]
+	st	%i5, [%l7+0x18]
+
+	ret
+	 restore
+
+/* C-interface for _nomem_find_apb used when memory is
+ * available.
+ *
+ * void ambapp_find_apb(
+ *	struct ambapp_bus *abus,
+ *	unsigned int dev_vend,
+ *	int index,
+ *	struct ambapp_find_apb_info *result
+ *	);
+ *
+ */
+ambapp_find_apb:
+	save	%sp, -104, %sp
+
+	mov	%i3, %l7	/* Save second argument */
+	mov	%i1, %o1
+	mov	%i2, %o2
+
+	/* Initialize buses available in system */
+	ld	[%i0+0x08], %i1
+	ld	[%i0+0x0c], %i2
+	ld	[%i0+0x10], %i3
+	ld	[%i0+0x14], %i4
+	ld	[%i0+0x18], %i5
+
+	call _nomem_find_apb
+	 ld	[%i0+0x04], %i0
+
+	st	%o2, [%l7+0x08]	/* Decremented Index */
+	st	%o3, [%l7]	/* PnP configuration address of APB Device */
+	st	%o4, [%l7+0x04]	/* AHB Bus Index of AHB/APB bridge and APB Device */
+	mov	%o0, %i0
+	ret
+	 restore
+
+/* C-interface for _nomem_find_ahb used when memory is
+ * available.
+ *
+ * void ambapp_find_ahb(
+ *	struct ambapp_bus *abus,
+ *	unsigned int dev_vend,
+ *	int index,
+ *	int type,
+ *	struct ambapp_find_ahb_info *result
+ *	);
+ *
+ */
+ambapp_find_ahb:
+	save	%sp, -104, %sp
+
+	mov	%i4, %l7	/* Save second argument */
+	clr	%o0
+	mov	%i1, %o1
+	mov	%i2, %o2
+	clr	%o3
+	clr	%o4
+	mov	%i3, %o5
+
+	/* Initialize buses available in system */
+	ld	[%i0+0x08], %i1
+	ld	[%i0+0x0c], %i2
+	ld	[%i0+0x10], %i3
+	ld	[%i0+0x14], %i4
+	ld	[%i0+0x18], %i5
+
+	call _nomem_find_ahb
+	 ld	[%i0+0x04], %i0
+
+	st	%o2, [%l7+0x08]	/* Decremented Index */
+	st	%o3, [%l7]	/* PnP configuration address of AHB Device */
+	st	%o4, [%l7+0x04]	/* AHB Bus Index of AHB Device */
+	mov	%o0, %i0
+	ret
+	 restore
diff --git a/cpu/leon3/cpu_init.c b/cpu/leon3/cpu_init.c
index be22ec2..046cfb8 100644
--- a/cpu/leon3/cpu_init.c
+++ b/cpu/leon3/cpu_init.c
@@ -31,6 +31,11 @@
 
 #include <config.h>
 
+/* Default Plug&Play I/O area */
+#ifndef CONFIG_AMBAPP_IOAREA
+#define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* reset CPU (jump to 0, without reset) */
@@ -53,64 +58,29 @@ struct {
 /*
  * Breath some life into the CPU...
  *
- * Set up the memory map,
- * initialize a bunch of registers.
- *
  * Run from FLASH/PROM:
- *  - until memory controller is set up, only registers avaiable
+ *  - memory controller has already been setup up, stack can be used
  *  - no global variables available for writing
  *  - constants avaiable
  */
-
 void cpu_init_f(void)
 {
-	/* these varaiable must not be initialized */
-	ambapp_dev_irqmp *irqmp;
-	ambapp_apbdev apbdev;
-	register unsigned int apbmst;
-
-	/* find AMBA APB Master */
-	apbmst = (unsigned int)
-	    ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
-	if (!apbmst) {
-		/*
-		 * no AHB/APB bridge, something is wrong
-		 * ==> jump to start (or hang)
-		 */
-		while (1) ;
-	}
-	/* Init memory controller */
-	if (init_memory_ctrl()) {
-		while (1) ;
-	}
-
-	/****************************************************
-	 * From here we can use the main memory and the stack.
-	 */
 
-	/* Find AMBA APB IRQMP Controller */
-	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) != 1) {
-		/* no IRQ controller, something is wrong
-		 * ==> jump to start (or hang)
-		 */
-		while (1) ;
-	}
-	irqmp = (ambapp_dev_irqmp *) apbdev.address;
-
-	/* initialize the IRQMP */
-	irqmp->ilevel = 0xf;	/* all IRQ off */
-	irqmp->iforce = 0;
-	irqmp->ipend = 0;
-	irqmp->iclear = 0xfffe;	/* clear all old pending interrupts */
-	irqmp->cpu_mask[0] = 0;	/* mask all IRQs on CPU 0 */
-	irqmp->cpu_force[0] = 0;	/* no force IRQ on CPU 0 */
-
-	/* cache */
 }
 
+/* Routine called from start.S, 
+ *
+ * Run from FLASH/PROM:
+ *  - memory controller has already been setup up, stack can be used
+ *  - global variables available for read/writing
+ *  - constants avaiable
+ */
 void cpu_init_f2(void)
 {
-
+	/* Initialize the AMBA Plug & Play bus structure, the bus
+	 * structure represents the AMBA bus that the CPU is located at.
+	 */
+	ambapp_bus_init(CONFIG_AMBAPP_IOAREA, CONFIG_SYS_CLK_FREQ, &ambapp_plb);
 }
 
 /*
@@ -119,95 +89,59 @@ void cpu_init_f2(void)
 int cpu_init_r(void)
 {
 	ambapp_apbdev apbdev;
+	int index, cpu;
+	ambapp_dev_gptimer *timer = NULL;
+	unsigned int bus_freq;
 
 	/*
 	 * Find AMBA APB IRQMP Controller,
-	 * When we come so far we know there is a IRQMP available
 	 */
-	ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev);
-	irqmp = (ambapp_dev_irqmp *) apbdev.address;
-
-	/* timer */
-	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_GPTIMER, &apbdev) != 1) {
-		printf("cpu_init_r: gptimer not found!\n");
-		return 1;
-	}
-	gptimer = (ambapp_dev_gptimer *) apbdev.address;
-	gptimer_irq = apbdev.irq;
-
-	/* initialize prescaler common to all timers to 1MHz */
-	gptimer->scalar = gptimer->scalar_reload =
-	    (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1;
-
-	return (0);
-}
-
-/* find & setup memory controller */
-int init_memory_ctrl()
-{
-	register ambapp_dev_mctrl *mctrl;
-	register ambapp_dev_sdctrl *sdctrl;
-	register ambapp_dev_ddrspa *ddrspa;
-	register ambapp_dev_ddr2spa *ddr2spa;
-	register ahbctrl_pp_dev *ahb;
-	register unsigned int base;
-	register int not_found_mctrl = -1;
-
-	/* find ESA Memory controller */
-	base = ambapp_apb_next_nomem(VENDOR_ESA, ESA_MCTRL, 0);
-	if (base) {
-		mctrl = (ambapp_dev_mctrl *) base;
-
-		/* config MCTRL memory controller */
-		mctrl->mcfg1 = CONFIG_SYS_GRLIB_MEMCFG1 | (mctrl->mcfg1 & 0x300);
-		mctrl->mcfg2 = CONFIG_SYS_GRLIB_MEMCFG2;
-		mctrl->mcfg3 = CONFIG_SYS_GRLIB_MEMCFG3;
-		not_found_mctrl = 0;
+	if ( ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, 
+		GAISLER_IRQMP, 0, &apbdev) != 1 ) {
+		printf("cpu_init_r: IRQ controller not found\n");
+		while (1) ;
 	}
+	irqmp = (ambapp_dev_irqmp *) apbdev.address;
 
-	/* find Gaisler Fault Tolerant Memory controller */
-	base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_FTMCTRL, 0);
-	if (base) {
-		mctrl = (ambapp_dev_mctrl *) base;
-
-		/* config MCTRL memory controller */
-		mctrl->mcfg1 = CONFIG_SYS_GRLIB_FT_MEMCFG1 | (mctrl->mcfg1 & 0x300);
-		mctrl->mcfg2 = CONFIG_SYS_GRLIB_FT_MEMCFG2;
-		mctrl->mcfg3 = CONFIG_SYS_GRLIB_FT_MEMCFG3;
-		not_found_mctrl = 0;
+	/* initialize the IRQMP */
+	irqmp->ilevel = 0xf;	/* all IRQ off */
+	irqmp->iforce = 0;
+	irqmp->ipend = 0;
+	irqmp->iclear = 0xfffe;	/* clear all old pending interrupts */
+	for (cpu=0; cpu<16; cpu++) {
+		/* mask and clear force for all IRQs on CPU[N] */
+		irqmp->cpu_mask[cpu] = 0;	
+		irqmp->cpu_force[cpu] = 0;
 	}
 
-	/* find SDRAM controller */
-	base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_SDCTRL, 0);
-	if (base) {
-		sdctrl = (ambapp_dev_sdctrl *) base;
-
-		/* config memory controller */
-		sdctrl->sdcfg = CONFIG_SYS_GRLIB_SDRAM;
-		not_found_mctrl = 0;
-	}
+	/* timer */
+	index = 0;
+	while (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER, 
+		index, &apbdev) == 1)
+	{
+		timer = (ambapp_dev_gptimer *) apbdev.address;
+		if ( gptimer == NULL ) {
+			gptimer = timer;
+			gptimer_irq = apbdev.irq;
+		}
+
+		/* Different buses may have different frequency, the 
+		 * frequency of the bus tell in which frequency the timer
+		 * prescaler operates.
+		 */
+		bus_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
 
-	ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDR2SPA, 1, 0);
-	if (ahb) {
-		ddr2spa = (ambapp_dev_ddr2spa *) ambapp_ahb_get_info(ahb, 1);
+		/* initialize prescaler common to all timers to 1MHz */
+		timer->scalar = timer->scalar_reload =
+		    (((bus_freq / 1000) + 500) / 1000) - 1;
 
-		/* Config DDR2 memory controller */
-		ddr2spa->cfg1 = CONFIG_SYS_GRLIB_DDR2_CFG1;
-		ddr2spa->cfg3 = CONFIG_SYS_GRLIB_DDR2_CFG3;
-		not_found_mctrl = 0;
+		index++;
 	}
-
-	ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDRSPA, 1, 0);
-	if (ahb) {
-		ddrspa = (ambapp_dev_ddrspa *) ambapp_ahb_get_info(ahb, 1);
-
-		/* Config DDR memory controller */
-		ddrspa->ctrl = CONFIG_SYS_GRLIB_DDR_CFG;
-		not_found_mctrl = 0;
+	if ( !gptimer ) {
+		printf("cpu_init_r: gptimer not found!\n");
+		return 1;
 	}
-
-	/* failed to find any memory controller */
-	return not_found_mctrl;
+	return (0);
 }
 
 /* Uses Timer 0 to get accurate
diff --git a/cpu/leon3/serial.c b/cpu/leon3/serial.c
index 4b2fcb8..15c380e 100644
--- a/cpu/leon3/serial.c
+++ b/cpu/leon3/serial.c
@@ -30,6 +30,11 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Select which UART that will become u-boot console */
+#ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
+#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
+#endif
+
 /* Force cache miss each time a serial controller reg is read */
 #define CACHE_BYPASS 1
 
@@ -48,7 +53,8 @@ int serial_init(void)
 	unsigned int tmp;
 
 	/* find UART */
-	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_APBUART, &apbdev) == 1) {
+	if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
+		CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) == 1) {
 
 		leon3_apbuart = (ambapp_dev_apbuart *) apbdev.address;
 
diff --git a/cpu/leon3/usb_uhci.c b/cpu/leon3/usb_uhci.c
index 8f99e1d..01310e2 100644
--- a/cpu/leon3/usb_uhci.c
+++ b/cpu/leon3/usb_uhci.c
@@ -708,11 +708,11 @@ void handle_usb_interrupt(void)
  */
 int usb_lowlevel_init(void)
 {
-	unsigned char temp;
 	ambapp_ahbdev ahbdev;
 
 	/* Find GRUSB core using AMBA Plug&Play information */
-	if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_UHCI, &ahbdev) != 1) {
+	if (ambapp_ahbslv_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_UHCI,
+		CONFIG_SYS_GRLIB_GRUSB_INDEX, &ahbdev) != 1 ) {
 		printf("USB UHCI: Failed to find GRUSB controller\n");
 		return -1;
 	}
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 383b25c..5ac0379 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -42,6 +42,13 @@
 #define GRETH_PHY_TIMEOUT_MS 3000
 #endif
 
+/* Let board select which GRETH to use as network interface, set
+ * this to zero if only one GRETH is available.
+ */
+#ifndef CONFIG_SYS_GRLIB_GRETH_INDEX
+#define CONFIG_SYS_GRLIB_GRETH_INDEX 0
+#endif
+
 /* ByPass Cache when reading regs */
 #define GRETH_REGLOAD(addr)		SPARC_NOCACHE_READ(addr)
 /* Write-through cache ==> no bypassing needed on writes */
@@ -605,8 +612,12 @@ int greth_initialize(bd_t * bis)
 #ifdef DEBUG
 	printf("Scanning for GRETH\n");
 #endif
-	/* Find Device & IRQ via AMBA Plug&Play information */
-	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_ETHMAC, &apbdev) != 1) {
+	/* Find Device & IRQ via AMBA Plug&Play information,
+	 * CONFIG_SYS_GRLIB_GRETH_INDEX select which GRETH if multiple
+	 * GRETHs in system.
+	 */
+	if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_ETHMAC,
+			CONFIG_SYS_GRLIB_GRETH_INDEX, &apbdev) != 1) {
 		return -1;	/* GRETH not found */
 	}
 
diff --git a/include/ambapp.h b/include/ambapp.h
index 42c990c..c1c07aa 100644
--- a/include/ambapp.h
+++ b/include/ambapp.h
@@ -3,8 +3,8 @@
  * the APB bus, also freely available in GRLIB at
  * www.gaisler.com.
  *
- * (C) Copyright 2007
- * Daniel Hellstrom, Gaisler Research, daniel at gaisler.com.
+ * (C) Copyright 2009
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -29,116 +29,136 @@
 #ifndef __AMBAPP_H__
 #define __AMBAPP_H__
 
-/* Default location of Plug&Play info
- * normally 0xfffff000 for AHB masters
- * and 0xfffff800 for AHB slaves.
- * Normally no need to change this.
- */
-#define LEON3_IO_AREA 0xfff00000
-#define LEON3_CONF_AREA  0xff000
-#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11)
-
-/* Max devices this software will support */
-#define LEON3_AHB_MASTERS 16
-#define LEON3_AHB_SLAVES 16
-/*#define LEON3_APB_MASTERS 1*/ /* Number of APB buses that has Plug&Play */
-#define LEON3_APB_SLAVES 16	/* Total number of APB slaves per APB bus */
-
-/* Vendor codes */
-#define VENDOR_GAISLER       1
-#define VENDOR_PENDER        2
-#define VENDOR_ESA           4
-#define VENDOR_ASTRIUM       6
-#define VENDOR_OPENCHIP      7
-#define VENDOR_OPENCORES     8
-#define VENDOR_CONTRIB       9
-#define VENDOR_EONIC         11
-#define VENDOR_RADIONOR      15
-#define VENDOR_GLEICHMANN    16
-#define VENDOR_MENTA         17
-#define VENDOR_SUN           19
-#define VENDOR_EMBEDDIT      234
-#define VENDOR_CAL           202
-
-/* Gaisler Research device id's */
-#define GAISLER_LEON3    0x003
-#define GAISLER_LEON3DSU 0x004
-#define GAISLER_ETHAHB   0x005
-#define GAISLER_APBMST   0x006
-#define GAISLER_AHBUART  0x007
-#define GAISLER_SRCTRL   0x008
-#define GAISLER_SDCTRL   0x009
-#define GAISLER_APBUART  0x00C
-#define GAISLER_IRQMP    0x00D
-#define GAISLER_AHBRAM   0x00E
-#define GAISLER_GPTIMER  0x011
-#define GAISLER_PCITRG   0x012
-#define GAISLER_PCISBRG  0x013
-#define GAISLER_PCIFBRG  0x014
-#define GAISLER_PCITRACE 0x015
-#define GAISLER_PCIDMA   0x016
-#define GAISLER_AHBTRACE 0x017
-#define GAISLER_ETHDSU   0x018
-#define GAISLER_PIOPORT  0x01A
-#define GAISLER_AHBJTAG  0x01c
-#define GAISLER_SPW      0x01f
-#define GAISLER_ATACTRL  0x024
-#define GAISLER_VGA      0x061
-#define GAISLER_KBD      0X060
-#define GAISLER_ETHMAC   0x01D
-#define GAISLER_DDRSPA   0x025
-#define GAISLER_EHCI     0x026
-#define GAISLER_UHCI     0x027
-#define GAISLER_SPW2     0x029
-#define GAISLER_DDR2SPA  0x02E
-#define GAISLER_AHBSTAT  0x052
-#define GAISLER_FTMCTRL  0x054
-
-#define GAISLER_L2TIME   0xffd	/* internal device: leon2 timer */
-#define GAISLER_L2C      0xffe	/* internal device: leon2compat */
-#define GAISLER_PLUGPLAY 0xfff	/* internal device: plug & play configarea */
-
-/* European Space Agency device id's */
-#define ESA_LEON2        0x2
-#define ESA_MCTRL        0xF
-
-/* Opencores device id's */
-#define OPENCORES_PCIBR  0x4
-#define OPENCORES_ETHMAC 0x5
-
-/* Vendor codes */
-
-/*
- *
- * Macros for manipulating Configuration registers
- *
- */
-
-#define amba_vendor(x) (((x) >> 24) & 0xff)
-
-#define amba_device(x) (((x) >> 12) & 0xfff)
-
-#define amba_membar_start(mbar) \
- (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16))
-
-#define amba_iobar_start(base, iobar) \
- ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) )
+#include <ambapp_ids.h>
 
-#define amba_irq(conf) ((conf) & 0xf)
+#ifndef __ASSEMBLER__
+/* Structures used to access Plug&Play information directly */
+struct ambapp_pnp_ahb {
+	const unsigned int	id;		/* VENDOR, DEVICE, VER, IRQ, */
+	const unsigned int	custom[3];
+	const unsigned int	mbar[4];	/* MASK, ADDRESS, TYPE,
+						 * CACHABLE/PREFETCHABLE */
+};
+
+struct ambapp_pnp_apb {
+	const unsigned int	id;		/* VENDOR, DEVICE, VER, IRQ, */
+	const unsigned int	iobar;		/* MASK, ADDRESS, TYPE,
+						 * CACHABLE/PREFETCHABLE */
+};
 
-#define amba_ver(conf) (((conf)>>5) & 0x1f)
+/* AMBA Plug&Play AHB Masters & Slaves information locations
+ * Max devices is 64 supported by HW, however often only 16
+ * are used.
+ */
+struct ambapp_pnp_info {
+	struct ambapp_pnp_ahb	masters[64];
+	struct ambapp_pnp_ahb	slaves[63];
+	const unsigned int	unused[4];
+	const unsigned int	systemid[4];
+};
+
+/* Describes a AMBA PnP bus */
+struct ambapp_bus {
+	int		buses;		/* Number of buses */
+	unsigned int	ioareas[6];	/* PnP I/O AREAs of AHB buses */
+	unsigned int	freq;		/* Frequency of bus0 [Hz] */
+};
+
+/* Processor Local AMBA bus */
+extern struct ambapp_bus ambapp_plb;
+
+/* Get Bus frequency of a certain AMBA bus */
+extern unsigned int ambapp_bus_freq(
+	struct ambapp_bus *abus,
+	int ahb_bus_index
+	);
+
+/* AMBA PnP information of a APB Device */
+typedef struct {
+	unsigned int vendor;
+	unsigned int device;
+	unsigned char irq;
+	unsigned char ver;
+	unsigned int address;
+	unsigned int mask;
+	int ahb_bus_index;
+} ambapp_apbdev;
 
-#define amba_membar_type(mbar) ((mbar) & 0xf)
+/* AMBA PnP information of a AHB Device */
+typedef struct {
+	unsigned int vendor;
+	unsigned int device;
+	unsigned char irq;
+	unsigned char ver;
+	unsigned int userdef[3];
+	unsigned int address[4];
+	unsigned int mask[4];
+	int type[4];
+	int ahb_bus_index;
+} ambapp_ahbdev;
 
-#define amba_membar_mask(mbar) (((mbar)>>4) & 0xfff)
+/* Scan AMBA Bus for AHB Bridges */
+extern void ambapp_bus_init(
+	unsigned int ioarea,
+	unsigned int freq,
+	struct ambapp_bus *abus);
 
-#define AMBA_TYPE_APBIO 0x1
-#define AMBA_TYPE_MEM   0x2
-#define AMBA_TYPE_AHBIO 0x3
+/* Find APB Slave device by index using breath first search.
+ *
+ * When vendor and device are both set to zero, any device 
+ * with a non-zero device ID will match the search. It may be
+ * useful when processing all devices on a AMBA bus.
+ */
+extern int ambapp_apb_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_apbdev *dev
+	);
+
+/* Find AHB Master device by index using breath first search. 
+ *
+ * When vendor and device are both set to zero, any device 
+ * with a non-zero device ID will match the search. It may be
+ * useful when processing all devices on a AMBA bus.
+ */
+extern int ambapp_ahbmst_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_ahbdev *dev
+	);
+
+/* Find AHB Slave device by index using breath first search.
+ *
+ * When vendor and device are both set to zero, any device 
+ * with a non-zero device ID will match the search. It may be
+ * useful when processing all devices on a AMBA bus.
+ */
+extern int ambapp_ahbslv_find(
+	struct ambapp_bus *abus,
+	int vendor,
+	int device,
+	int index,
+	ambapp_ahbdev *dev
+	);
+
+/* Return number of APB Slave devices of a certain ID (VENDOR:DEVICE)
+ * zero is returned if no devices was found.
+ */
+extern int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device);
 
-#define AMBA_TYPE_AHBIO_ADDR(addr) (LEON3_IO_AREA | ((addr) >> 12))
+/* Return number of AHB Master devices of a certain ID (VENDOR:DEVICE)
+ * zero is returned if no devices was found.
+ */
+extern int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device);
 
-#ifndef __ASSEMBLER__
+/* Return number of AHB Slave devices of a certain ID (VENDOR:DEVICE)
+ * zero is returned if no devices was found.
+ */
+extern int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device);
 
 #ifdef CONFIG_CMD_AMBAPP
 
@@ -152,109 +172,72 @@ char *ambapp_device_id2str(int vendor, int id);
 
 /* Return name of vendor */
 char *ambapp_vendor_id2str(int vendor);
-#endif
 
-/*
- *  Types and structure used for AMBA Plug & Play bus scanning
- */
+/* Return description of a device */
+char *ambapp_device_id2desc(int vendor, int id);
 
-/* AMBA Plug&Play AHB information layout */
-typedef struct {
-	unsigned int conf;
-	unsigned int userdef[3];
-	unsigned int bars[4];
-} ahbctrl_pp_dev;
-
-/* Prototypes for scanning AMBA Plug&Play bus for AMBA
- *  i)   AHB Masters
- *  ii)  AHB Slaves
- *  iii) APB Slaves (APB MST is a AHB Slave)
- */
+#endif
 
-typedef struct {
-	unsigned char irq;
-	unsigned char ver;
-	unsigned int address;
-} ambapp_apbdev;
+#endif /* defined(__ASSEMBLER__) */
 
-typedef struct {
-	unsigned char irq;
-	unsigned char ver;
-	unsigned int userdef[3];
-	unsigned int address[4];
-} ambapp_ahbdev;
+#define AMBA_DEFAULT_IOAREA 0xfff00000
+#define AMBA_CONF_AREA 0xff000
+#define AMBA_AHB_SLAVE_CONF_AREA 0x800
 
-/* AMBA Plug&Play AHB Masters & Slaves information locations
- * Max devices is 64 supported by HW, however often only 8
- * are used.
- */
-typedef struct {
-	ahbctrl_pp_dev masters[64];
-	ahbctrl_pp_dev slaves[64];
-} ahbctrl_info;
+#define DEV_NONE	0
+#define DEV_AHB_MST	1
+#define DEV_AHB_SLV	2
+#define DEV_APB_SLV	3
 
-/* AMBA Plug&Play AHB information layout */
-typedef struct {
-	unsigned int conf;
-	unsigned int bar;
-} apbctrl_pp_dev;
+#define AMBA_TYPE_APBIO 0x1
+#define AMBA_TYPE_MEM 0x2
+#define AMBA_TYPE_AHBIO 0x3
 
-/* All functions return the number of found devices
- * 0 = no devices found
+/* ID layout for APB and AHB devices */
+#define AMBA_PNP_ID(vendor, device) ( ((vendor)<<24) | ((device)<<12) )
+
+/* APB Slave PnP layout definitions */
+#define AMBA_APB_ID_OFS		(0*4)
+#define AMBA_APB_IOBAR_OFS	(1*4)
+#define AMBA_APB_CONF_LENGH	(2*4)
+
+/* AHB Master/Slave layout PnP definitions */
+#define AMBA_AHB_ID_OFS		(0*4)
+#define AMBA_AHB_CUSTOM0_OFS	(1*4)
+#define AMBA_AHB_CUSTOM1_OFS	(2*4)
+#define AMBA_AHB_CUSTOM2_OFS	(3*4)
+#define AMBA_AHB_MBAR0_OFS	(4*4)
+#define AMBA_AHB_MBAR1_OFS	(5*4)
+#define AMBA_AHB_MBAR2_OFS	(6*4)
+#define AMBA_AHB_MBAR3_OFS	(7*4)
+#define AMBA_AHB_CONF_LENGH	(8*4)
+
+/* Macros for extracting information from AMBA PnP information
+ * registers.
  */
 
-/****************************** APB SLAVES ******************************/
-int ambapp_apb_count(unsigned int vendor, unsigned int driver);
-
-int ambapp_apb_first(unsigned int vendor,
-		     unsigned int driver, ambapp_apbdev * dev);
-
-int ambapp_apb_next(unsigned int vendor,
-		    unsigned int driver, ambapp_apbdev * dev, int index);
-
-int ambapp_apbs_first(unsigned int vendor,
-		      unsigned int driver, ambapp_apbdev * dev, int max_cnt);
-
-/****************************** AHB MASTERS ******************************/
-int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver);
-
-int ambapp_ahbmst_first(unsigned int vendor,
-			unsigned int driver, ambapp_ahbdev * dev);
+#define amba_vendor(x) (((x) >> 24) & 0xff)
 
-int ambapp_ahbmst_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index);
+#define amba_device(x) (((x) >> 12) & 0xfff)
 
-int ambapp_ahbmsts_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt);
+#define amba_irq(conf) ((conf) & 0x1f)
 
-/****************************** AHB SLAVES ******************************/
-int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver);
+#define amba_ver(conf) (((conf)>>5) & 0x1f)
 
-int ambapp_ahbslv_first(unsigned int vendor,
-			unsigned int driver, ambapp_ahbdev * dev);
+#define amba_iobar_start(base, iobar) \
+ ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) )
 
-int ambapp_ahbslv_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index);
+#define amba_membar_start(mbar) \
+ (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16))
 
-int ambapp_ahbslvs_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt);
+#define amba_membar_type(mbar) ((mbar) & 0xf)
 
-/*************************** AHB/APB only regs functions *************************
- * During start up, no memory is available we can use the simplified functions
- * to get to the memory controller.
- *
- * Functions uses no stack/memory, only registers.
- */
-unsigned int ambapp_apb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				   register unsigned int driver,	/* Plug&Play Device ID */
-				   register int index);
+#define amba_membar_mask(mbar) (((mbar) >> 4) & 0xfff)
 
-ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				      register unsigned int driver,	/* Plug&Play Device ID */
-				      register unsigned int opts,	/* scan for AHB 1=slave, 0=masters */
-				      register int index);
+#define amba_ahbio_adr(addr,base_ioarea) \
+	((unsigned int)(base_ioarea) | ((addr) >> 12))
 
-unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info);
+#define amba_apb_mask(iobar) ((~(amba_membar_mask(iobar)<<8) & 0x000fffff) + 1)
 
 /*************************** AMBA Plug&Play device register MAPS *****************/
 
@@ -308,6 +291,8 @@ unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info);
 #define LEON_REG_PS2_CTRL_RI     0x00000004	/* Keyboard receive interrupt  */
 #define LEON_REG_PS2_CTRL_TI     0x00000008	/* Keyboard transmit interrupt */
 
+#ifndef __ASSEMBLER__
+
 typedef struct {
 	volatile unsigned int ilevel;
 	volatile unsigned int ipend;
diff --git a/include/ambapp_ids.h b/include/ambapp_ids.h
new file mode 100644
index 0000000..b7eb98b
--- /dev/null
+++ b/include/ambapp_ids.h
@@ -0,0 +1,256 @@
+/* AMBA Plug & Play Bus Vendor and Device IDs.
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel@gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef __AMBAPP_IDS_H__
+#define __AMBAPP_IDS_H__
+
+/* Vendor ID defines */
+#define VENDOR_GAISLER       0x01
+#define VENDOR_PENDER        0x02
+#define VENDOR_ESA           0x04
+#define VENDOR_ASTRIUM       0x06
+#define VENDOR_OPENCHIP      0x07
+#define VENDOR_OPENCORES     0x08
+#define VENDOR_CONTRIB       0x09
+#define VENDOR_EONIC         0x0b
+#define VENDOR_RADIONOR      0x0f
+#define VENDOR_GLEICHMANN    0x10
+#define VENDOR_MENTA         0x11
+#define VENDOR_SUN           0x13
+#define VENDOR_MOVIDIA       0x14
+#define VENDOR_ORBITA        0x17
+#define VENDOR_SYNOPSYS      0x21
+#define VENDOR_NASA          0x22
+#define VENDOR_CAL           0xca
+#define VENDOR_EMBEDDIT      0xea
+#define VENDOR_CETON         0xcb
+#define VENDOR_ACTEL         0xac
+#define VENDOR_APPLECORE     0xae
+
+/* Aeroflex Gaisler device ID defines */
+#define GAISLER_LEON2DSU     0x002
+#define GAISLER_LEON3        0x003
+#define GAISLER_LEON3DSU     0x004
+#define GAISLER_ETHAHB       0x005
+#define GAISLER_APBMST       0x006
+#define GAISLER_AHBUART      0x007
+#define GAISLER_SRCTRL       0x008
+#define GAISLER_SDCTRL       0x009
+#define GAISLER_SSRCTRL      0x00a
+#define GAISLER_APBUART      0x00c
+#define GAISLER_IRQMP        0x00d
+#define GAISLER_AHBRAM       0x00e
+#define GAISLER_AHBDPRAM     0x00f
+#define GAISLER_GPTIMER      0x011
+#define GAISLER_PCITRG       0x012
+#define GAISLER_PCISBRG      0x013
+#define GAISLER_PCIFBRG      0x014
+#define GAISLER_PCITRACE     0x015
+#define GAISLER_DMACTRL      0x016
+#define GAISLER_AHBTRACE     0x017
+#define GAISLER_DSUCTRL      0x018
+#define GAISLER_CANAHB       0x019
+#define GAISLER_GPIO         0x01a
+#define GAISLER_AHBROM       0x01b
+#define GAISLER_AHBJTAG      0x01c
+#define GAISLER_ETHMAC       0x01d
+#define GAISLER_SWNODE       0x01e
+#define GAISLER_SPW          0x01f
+#define GAISLER_AHB2AHB      0x020
+#define GAISLER_USBDC        0x021
+#define GAISLER_USB_DCL      0x022
+#define GAISLER_DDRMP        0x023
+#define GAISLER_ATACTRL      0x024
+#define GAISLER_DDRSP        0x025
+#define GAISLER_EHCI         0x026
+#define GAISLER_UHCI         0x027
+#define GAISLER_I2CMST       0x028
+#define GAISLER_SPW2         0x029
+#define GAISLER_AHBDMA       0x02a
+#define GAISLER_NUHOSP3      0x02b
+#define GAISLER_CLKGATE      0x02c
+#define GAISLER_SPICTRL      0x02d
+#define GAISLER_DDR2SP       0x02e
+#define GAISLER_SLINK        0x02f
+#define GAISLER_GRTM         0x030
+#define GAISLER_GRTC         0x031
+#define GAISLER_GRPW         0x032
+#define GAISLER_GRCTM        0x033
+#define GAISLER_GRHCAN       0x034
+#define GAISLER_GRFIFO       0x035
+#define GAISLER_GRADCDAC     0x036
+#define GAISLER_GRPULSE      0x037
+#define GAISLER_GRTIMER      0x038
+#define GAISLER_AHB2PP       0x039
+#define GAISLER_GRVERSION    0x03a
+#define GAISLER_APB2PW       0x03b
+#define GAISLER_PW2APB       0x03c
+#define GAISLER_GRCAN        0x03d
+#define GAISLER_I2CSLV       0x03e
+#define GAISLER_U16550       0x03f
+#define GAISLER_AHBMST_EM    0x040
+#define GAISLER_AHBSLV_EM    0x041
+#define GAISLER_GRTESTMOD    0x042
+#define GAISLER_ASCS         0x043
+#define GAISLER_IPMVBCTRL    0x044
+#define GAISLER_SPIMCTRL     0x045
+#define GAISLER_LEON4        0x048
+#define GAISLER_LEON4DSU     0x049
+#define GAISLER_PWM          0x04a
+#define GAISLER_L2CACHE      0x04b
+#define GAISLER_SDCTRL64     0x04c
+#define GAISLER_FTAHBRAM     0x050
+#define GAISLER_FTSRCTRL     0x051
+#define GAISLER_AHBSTAT      0x052
+#define GAISLER_LEON3FT      0x053
+#define GAISLER_FTMCTRL      0x054
+#define GAISLER_FTSDCTRL     0x055
+#define GAISLER_FTSRCTRL8    0x056
+#define GAISLER_APBPS2       0x060
+#define GAISLER_VGACTRL      0x061
+#define GAISLER_LOGAN        0x062
+#define GAISLER_SVGACTRL     0x063
+#define GAISLER_T1AHB        0x064
+#define GAISLER_MP7WRAP      0x065
+#define GAISLER_GRSYSMON     0x066
+#define GAISLER_GRACECTRL    0x067
+#define GAISLER_ATAHBSLV     0x068
+#define GAISLER_ATAHBMST     0x069
+#define GAISLER_ATAPBSLV     0x06a
+#define GAISLER_B1553BC      0x070
+#define GAISLER_B1553RT      0x071
+#define GAISLER_B1553BRM     0x072
+#define GAISLER_AES          0x073
+#define GAISLER_ECC          0x074
+#define GAISLER_PCIF         0x075
+#define GAISLER_CLKMOD       0x076
+#define GAISLER_HAPSTRAK     0x077
+#define GAISLER_TEST_1X2     0x078
+#define GAISLER_WILD2AHB     0x079
+#define GAISLER_BIO1         0x07a
+#define GAISLER_SATCAN       0x080
+#define GAISLER_CANMUX       0x081
+#define GAISLER_GRTMRX       0x082
+#define GAISLER_GRTCTX       0x083
+#define GAISLER_GRTMDESC     0x084
+#define GAISLER_GRTMVC       0x085
+#define GAISLER_GEFFE        0x086
+#define GAISLER_GPREG        0x087
+#define GAISLER_GRTMPAHB     0x088
+
+/* European Space Agency device ID defines */
+#define ESA_LEON2            0x002
+#define ESA_LEON2APB         0x003
+#define ESA_IRQ              0x005
+#define ESA_TIMER            0x006
+#define ESA_UART             0x007
+#define ESA_CFG              0x008
+#define ESA_IO               0x009
+#define ESA_MCTRL            0x00f
+#define ESA_PCIARB           0x010
+#define ESA_HURRICANE        0x011
+#define ESA_SPW_RMAP         0x012
+#define ESA_AHBUART          0x013
+#define ESA_SPWA             0x014
+#define ESA_BOSCHCAN         0x015
+#define ESA_IRQ2             0x016
+#define ESA_AHBSTAT          0x017
+#define ESA_WPROT            0x018
+#define ESA_WPROT2           0x019
+#define ESA_PDEC3AMBA        0x020
+#define ESA_PTME3AMBA        0x021
+
+/* OpenChip device ID defines */
+#define OPENCHIP_APBGPIO     0x001
+#define OPENCHIP_APBI2C      0x002
+#define OPENCHIP_APBSPI      0x003
+#define OPENCHIP_APBCHARLCD  0x004
+#define OPENCHIP_APBPWM      0x005
+#define OPENCHIP_APBPS2      0x006
+#define OPENCHIP_APBMMCSD    0x007
+#define OPENCHIP_APBNAND     0x008
+#define OPENCHIP_APBLPC      0x009
+#define OPENCHIP_APBCF       0x00a
+#define OPENCHIP_APBSYSACE   0x00b
+#define OPENCHIP_APB1WIRE    0x00c
+#define OPENCHIP_APBJTAG     0x00d
+#define OPENCHIP_APBSUI      0x00e
+
+/* Various contributions device ID defines */
+#define CONTRIB_CORE1        0x001
+#define CONTRIB_CORE2        0x002
+
+/* Gleichmann Electronics device ID defines */
+#define GLEICHMANN_CUSTOM    0x001
+#define GLEICHMANN_GEOLCD01  0x002
+#define GLEICHMANN_DAC       0x003
+#define GLEICHMANN_HPI       0x004
+#define GLEICHMANN_SPI       0x005
+#define GLEICHMANN_HIFC      0x006
+#define GLEICHMANN_ADCDAC    0x007
+#define GLEICHMANN_SPIOC     0x008
+#define GLEICHMANN_AC97      0x009
+
+/* Sun Microsystems device ID defines */
+#define SUN_T1               0x001
+#define SUN_S1               0x011
+
+/* Orbita device ID defines */
+#define ORBITA_1553B         0x001
+#define ORBITA_429           0x002
+#define ORBITA_SPI           0x003
+#define ORBITA_I2C           0x004
+#define ORBITA_SMARTCARD     0x064
+#define ORBITA_SDCARD        0x065
+#define ORBITA_UART16550     0x066
+#define ORBITA_CRYPTO        0x067
+#define ORBITA_SYSIF         0x068
+#define ORBITA_PIO           0x069
+#define ORBITA_RTC           0x0c8
+#define ORBITA_COLORLCD      0x12c
+#define ORBITA_PCI           0x190
+#define ORBITA_DSP           0x1f4
+#define ORBITA_USBHOST       0x258
+#define ORBITA_USBDEV        0x2bc
+
+/* NASA device ID defines */
+#define NASA_EP32            0x001
+
+/* CAL device ID defines */
+#define CAL_DDRCTRL          0x188
+
+/* Actel Corporation device ID defines */
+#define ACTEL_COREMP7        0x001
+
+/* AppleCore device ID defines */
+#define APPLECORE_UTLEON3    0x001
+#define APPLECORE_UTLEON3DSU 0x002
+
+/* Opencores device id's */
+#define OPENCORES_PCIBR  0x4
+#define OPENCORES_ETHMAC 0x5
+
+#endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 05/17] LEON3: added memory controller initialization using the new AMBA PnP routines.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (2 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 04/17] LEON3: reimplemented AMBA Plug&Play scanning routines Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 06/17] LEON3: Moved GRLIB core header files to common include/grlib directory Daniel Hellstrom
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/Makefile               |    5 +-
 cpu/leon3/memcfg.c               |  276 ++++++++++++++++++++++++++++++++++++++
 cpu/leon3/memcfg.h               |  106 +++++++++++++++
 cpu/leon3/memcfg_low.S           |  270 +++++++++++++++++++++++++++++++++++++
 cpu/leon3/start.S                |   36 +++++
 include/configs/gr_cpci_ax2000.h |   27 ++--
 include/configs/gr_ep2s60.h      |   32 +++--
 include/configs/gr_xc3s_1500.h   |   23 ++--
 include/configs/grsim.h          |   27 +++--
 9 files changed, 754 insertions(+), 48 deletions(-)
 create mode 100644 cpu/leon3/memcfg.c
 create mode 100644 cpu/leon3/memcfg.h
 create mode 100644 cpu/leon3/memcfg_low.S

diff --git a/cpu/leon3/Makefile b/cpu/leon3/Makefile
index d8f89bc..f1bb808 100644
--- a/cpu/leon3/Makefile
+++ b/cpu/leon3/Makefile
@@ -26,8 +26,9 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(CPU).a
 
 START	= start.o
-SOBJS	= ambapp_low.o ambapp_low_c.o
-COBJS	= cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o
+SOBJS	= ambapp_low.o ambapp_low_c.o memcfg_low.o
+COBJS	= cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o \
+	memcfg.o
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/leon3/memcfg.c b/cpu/leon3/memcfg.c
new file mode 100644
index 0000000..83e55e4
--- /dev/null
+++ b/cpu/leon3/memcfg.c
@@ -0,0 +1,276 @@
+/* GRLIB Memory controller setup. The register values are used
+ * from the associated low level assembler routine implemented
+ * in memcfg_low.S.
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <ambapp.h>
+#include "memcfg.h"
+#include <config.h>
+
+#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL1
+struct mctrl_setup esa_mctrl1_cfg =
+{
+	.reg_mask = 0x7,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000300,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2,
+		},	
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3,
+		},
+	}
+};
+#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL2
+struct mctrl_setup esa_mctrl2_cfg =
+{
+	.reg_mask = 0x7,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000300,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG1,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG2,
+		},	
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG3,
+		},
+	}
+};
+#endif
+#endif
+
+#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+struct mctrl_setup gaisler_ftmctrl1_cfg =
+{
+	.reg_mask = 0x7,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000300,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2,
+		},	
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3,
+		},
+	}
+};
+#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2
+struct mctrl_setup gaisler_ftmctrl2_cfg =
+{
+	.reg_mask = 0x7,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000300,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG1,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG2,
+		},	
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG3,
+		},
+	}
+};
+#endif
+#endif
+
+#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
+struct mctrl_setup gaisler_sdctrl1_cfg =
+{
+	.reg_mask = 0x1,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_SDCTRL1_CTRL,
+		},
+	}
+};
+#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL2
+struct mctrl_setup gaisler_sdctrl2_cfg =
+{
+	.reg_mask = 0x1,
+	.regs =
+	{
+		{ 
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_SDCTRL2_CTRL,
+		},
+	}
+};
+#endif
+#endif
+
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
+struct ahbmctrl_setup gaisler_ddr2spa1_cfg =
+{
+	.ahb_mbar_no = 1,
+	.reg_mask = 0xd,
+	.regs =
+	{
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG1,
+		},
+		{ 0x00000000, 0},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG3,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG4,
+		},
+	}
+};
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2
+struct ahbmctrl_setup gaisler_ddr2spa2_cfg =
+{
+	.ahb_mbar_no = 1,
+	.reg_mask = 0xd,
+	.regs =
+	{
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG1,
+		},
+		{ 0x00000000, 0},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG3,
+		},
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG4,
+		},
+	}
+};
+#endif
+#endif
+
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
+struct ahbmctrl_setup gaisler_ddrspa1_cfg =
+{
+	.ahb_mbar_no = 1,
+	.reg_mask = 0x1,
+	.regs =
+	{
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDRSPA1_CTRL,
+		},
+	}
+};
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA2
+struct ahbmctrl_setup gaisler_ddrspa2_cfg =
+{
+	.ahb_mbar_no = 1,
+	.reg_mask = 0x1,
+	.regs =
+	{
+		{
+			.mask = 0x00000000,
+			.value = CONFIG_SYS_GRLIB_GAISLER_DDRSPA2_CTRL,
+		},
+	}
+};
+#endif
+#endif
+
+struct grlib_mctrl_handler grlib_mctrl_handlers[] = 
+{
+
+/* ESA MCTRL (PROM/FLASH/IO/SRAM/SDRAM) */
+#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL1
+	{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_ESA,ESA_MCTRL),
+	_nomem_mctrl_init, (void *)&esa_mctrl1_cfg},
+#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL2
+	{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_ESA,ESA_MCTRL),
+	_nomem_mctrl_init, (void *)&esa_mctrl2_cfg},
+#endif
+#endif
+
+/* GAISLER Fault Tolerant Memory controller (PROM/FLASH/IO/SRAM/SDRAM) */
+#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+	{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_FTMCTRL),
+	_nomem_mctrl_init, (void *)&gaisler_ftmctrl1_cfg},
+#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2
+	{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_FTMCTRL),
+	_nomem_mctrl_init, (void *)&gaisler_ftmctrl2_cfg},
+#endif
+#endif
+
+/* GAISLER SDRAM-only Memory controller (SDRAM) */
+#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
+	{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_SDCTRL),
+	_nomem_mctrl_init, (void *)&gaisler_sdctrl1_cfg},
+#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL2
+	{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_SDCTRL),
+	_nomem_mctrl_init, (void *)&gaisler_sdctrl2_cfg},
+#endif
+#endif
+
+/* GAISLER DDR Memory controller (DDR) */
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
+	{DEV_AHB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_DDRSP),
+	_nomem_ahbmctrl_init, (void *)&gaisler_ddrspa1_cfg},
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA2
+	{DEV_AHB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_DDRSP),
+	_nomem_ahbmctrl_init, (void *)&gaisler_ddrspa2_cfg},
+#endif
+#endif
+
+/* GAISLER DDR2 Memory controller (DDR2) */
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
+	{DEV_AHB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_DDR2SP),
+	_nomem_ahbmctrl_init, (void *)&gaisler_ddr2spa1_cfg},
+#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2
+	{DEV_AHB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_DDR2SP),
+	_nomem_ahbmctrl_init, (void *)&gaisler_ddr2spa2_cfg},
+#endif
+#endif
+
+	/* Mark end */
+	MH_END
+};
diff --git a/cpu/leon3/memcfg.h b/cpu/leon3/memcfg.h
new file mode 100644
index 0000000..0b4738e
--- /dev/null
+++ b/cpu/leon3/memcfg.h
@@ -0,0 +1,106 @@
+/* GRLIB Memory controller setup structures
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __MEMCFG_H__
+#define __MEMCFG_H__
+
+/*********** Low Level Memory Controller Initalization ***********/
+
+#ifndef __ASSEMBLER__
+
+typedef void (*mctrl_handler_t)(
+	struct grlib_mctrl_handler *dev,
+	void *conf,
+	unsigned int ioarea
+	);
+
+/* Memory Controller Handler Structure */
+struct grlib_mctrl_handler {
+	unsigned char	type;		/* 0x00. MASK: AHB MST&SLV, APB SLV */
+	char		index;		/* 0x01. Unit number, 0, 1, 2... */
+	char		unused[2];	/* 0x02 */
+	unsigned int	ven_dev;	/* 0x04. Device and Vendor */
+	mctrl_handler_t	func;		/* 0x08. Memory Controller Handler */
+	void		*priv;		/* 0x0c. Optional private data, ptr to
+					 * info how to set up controller */
+};
+
+extern struct grlib_mctrl_handler grlib_mctrl_handlers[];
+
+#endif
+
+#define MH_STRUCT_SIZE		(4*4)
+#define MH_TYPE			0x00
+#define MH_INDEX		0x01
+#define MH_UNUSED		0x02
+#define MH_VENDOR_DEVICE	0x04
+#define MH_FUNC			0x08
+#define MH_PRIV			0x0c
+
+#define MH_TYPE_NONE	DEV_NONE
+#define MH_TYPE_AHB_MST	DEV_AHB_MST
+#define MH_TYPE_AHB_SLV	DEV_AHB_SLV
+#define MH_TYPE_APB_SLV	DEV_APB_SLV
+
+#define MH_UNUSED	{0, 0}
+#define MH_END		{DEV_NONE, 0, MH_UNUSED, AMBA_PNP_ID(0,0), 0, 0}
+
+/*********** Low Level Memory Controller Initalization Handlers ***********/
+
+#ifndef __ASSEMBLER__
+extern void _nomem_mctrl_init(
+	struct grlib_mctrl_handler *dev,
+	void *conf,
+	unsigned int ioarea_apbmst);
+
+struct mctrl_setup {
+	unsigned int reg_mask;		/* Which registers to write */
+	struct {
+		unsigned int mask;	/* Mask used keep reg bits unchanged */
+		unsigned int value;	/* Value written to register */
+	} regs[8];
+};
+
+extern void _nomem_ahbmctrl_init(
+	struct grlib_mctrl_handler *dev,
+	void *conf,
+	unsigned int ioarea_apbmst);
+
+struct ahbmctrl_setup {
+	int ahb_mbar_no;		/* MBAR to get register address from */
+	unsigned int reg_mask;		/* Which registers to write */
+	struct {
+		unsigned int mask;	/* Mask used keep reg bits unchanged */
+		unsigned int value;	/* Value written to register */
+	} regs[8];
+};
+#endif
+
+/* mctrl_setup data structure defines */
+#define NREGS_OFS 0
+#define REGS_OFS 0x4
+#define REGS_SIZE 8
+
+#endif
diff --git a/cpu/leon3/memcfg_low.S b/cpu/leon3/memcfg_low.S
new file mode 100644
index 0000000..7ff7230
--- /dev/null
+++ b/cpu/leon3/memcfg_low.S
@@ -0,0 +1,270 @@
+/* This is the memory initialization functions, the function
+ * implemented below initializes each memory controller 
+ * found and specified by the input grlib_mctrl_handler structure.
+ *
+ * After the memory controllers have been initialized the stack
+ * can be used.
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <ambapp.h>
+#include "memcfg.h"
+#include <config.h>
+
+	.seg	"text"
+	.globl	_nomem_memory_ctrl_init
+	.globl	_nomem_mctrl_init, _nomem_ahbmctrl_init
+	.extern	_nomem_find_apb
+	.extern	_nomem_find_ahb
+
+
+/* FUNCTION
+ *   _nomem_memory_controller_init(struct grlib_mctrl_handler *mem_handlers)
+ *
+ * Initialize AMBA devices, _nomem_amba_init() has prepared i0-i5
+ * with the AHB buses on the system.
+ *
+ * For each entry in mem_handlers find the VENDOR:DEVICE and handle it
+ * by calling the handler function pointer.
+ *
+ * Constraints:
+ *  i6, i7, o6, l7, l6, g3, g4, g5, g6, g7 is used by caller
+ *  o7 is return address
+ *  l5 reserved for this function for future use.
+ *
+ * Arguments
+ *  - o0 Pointer to memory handler array
+ *
+ * Results
+ *  - o0 Number of memory controllers found
+ *
+ * Clobbered
+ *  - o0 (Current AHB slave conf address)
+ *  - l0 (mem handler entry address)
+ *  - l1 (Return value, number of memory controllers found)
+ *  - o7 (function pointer)
+ *  - l0, l1, l2, l3, l4, g1, g2 (used by _nomem_ambapp_find_buses)
+ *  - o0, o1, o2, o3, o4, o5 (Used as arguments)
+ *
+ *  - g1 ( level 1 return address)
+ *  - g2 ( level 2 return address)
+ */
+
+_nomem_memory_ctrl_init:
+	/* At this point all AHB buses has been found and the I/O Areas of 
+	 * all AHB buses is stored in the i0-i5 registers. Max 6 buses. Next,
+	 * memory controllers are found by searching all buses for matching
+	 * VENDOR:DEVICE. The VENDOR:DEVICE to search for are taken from the
+	 * mem_handlers array. For each match the function pointer stored in 
+	 * the mem_handler entry is called to handle the hardware setup.
+	 */
+	mov	%o7, %g1	/* Save return address */
+	mov	%o0, %l0
+	mov	%g0, %l1	/* The return value */
+
+.L_do_one_mem_handler:
+	ld	[%l0 + MH_FUNC], %o7
+	cmp	%o7, %g0
+	be	.L_all_mctrl_handled
+	 nop
+
+	/*** Scan for memory controller ***/
+
+	/* Set up argments, o5 not used by _nomem_find_apb */
+	ldub	[%l0 + MH_TYPE], %o5
+	clr	%o4
+	clr	%o3
+	ldub	[%l0 + MH_INDEX], %o2
+	ld	[%l0 + MH_VENDOR_DEVICE], %o1
+
+	/* An empty config? */
+	cmp	%o5, DEV_NONE
+	beq	.L_all_mctrl_next
+
+	/* Select function (APB or AHB) */
+	 cmp	%o5, DEV_APB_SLV
+	bne	.L_find_ahb_memctrl
+	 clr	%o0
+.L_find_apb_memctrl:
+	call	_nomem_find_apb			/* Scan for APB slave device */
+	 nop
+
+	/* o3 = iobar address
+	 * o4 = AHB Bus index
+	 *
+	 * REG ADR = ((iobar >> 12) & (iobar << 4) & 0xfff00) | "APB Base"
+	 */
+	ld	[%o3 + AMBA_APB_IOBAR_OFS], %o5
+	srl	%o5, 12, %o2
+	sll	%o5, 4, %o5
+	and	%o2, %o5, %o5
+	set	0xfff00, %o2
+	and	%o2, %o5, %o5
+	sethi	%hi(0xfff00000), %o2
+	and	%o3, %o2, %o2
+	or	%o5, %o2, %o5	/* Register base address */
+
+	ba	.L_call_one_mem_handler
+	 nop
+
+.L_find_ahb_memctrl:
+	call	_nomem_find_ahb		/* Scan for AHB Slave or Master.
+					 * o5 determine type. */
+	 nop
+	clr	%o5
+
+	/* Call the handler function if the hardware was found
+	 *
+	 * o0 = mem_handler
+	 * o1 = Configuration address
+	 * o2 = AHB Bus index
+	 * o3 = APB Base register (if APB Slave)
+	 *
+	 * Constraints:
+	 * i0-i7, l0, l1, l5, g1, g3-g7 may no be used.
+	 */
+.L_call_one_mem_handler:
+	cmp	%o0, %g0
+	be	.L_all_mctrl_next
+	 mov	%l0, %o0			/* Mem handler pointer */
+	mov	%o3, %o1			/* AMBA PnP Configuration address */
+	mov	%o4, %o2			/* AHB Bus index */
+	ld	[%l0 + MH_FUNC], %o7	/* Get Function pointer */
+	call	%o7
+	 mov	%o5, %o3			/* APB Register Base Address */
+
+	inc	%l1				/* Number of Memory controllers
+						 * handled. */
+
+	/* Do next entry in mem_handlers */
+.L_all_mctrl_next:
+	ba	.L_do_one_mem_handler
+	 add	%l0, MH_STRUCT_SIZE, %l0
+
+.L_all_mctrl_handled:
+	mov	%g1, %o7	/* Restore return address */
+	retl
+	 mov	%l1, %o0
+
+
+
+/* Generic Memory controller initialization routine (APB Registers)
+ *
+ * o0 = mem_handler structure pointer
+ * o1 = Configuration address
+ * o2 = AHB Bus index
+ * o3 = APB Base register
+ *
+ * Clobbered
+ *  o0-o4
+ */
+_nomem_mctrl_init:
+	ld	[%o0 + MH_PRIV], %o0	/* Get Private structure */
+	ld	[%o0], %o1		/* Get Reg Mask */
+	and	%o1, 0xff, %o1
+	add	%o0, REGS_OFS, %o0	/* Point to first reg */
+.L_do_one_reg:
+	andcc	%o1, 0x1, %g0
+	beq	.L_do_next_reg
+	 ld	[%o0], %o2
+	ld	[%o3], %o4
+	and	%o4, %o2, %o4
+	ld	[%o0 + 4], %o2
+	or	%o4, %o2, %o4
+	st	%o4, [%o3]
+
+.L_do_next_reg:
+	add	%o0, REGS_SIZE, %o0
+	add	%o3, 4, %o3
+	srl	%o1, 1, %o1
+	cmp	%o1, 0
+	bne	.L_do_one_reg
+	 nop
+
+	/* No more registers to write */
+	retl
+	 nop
+
+
+
+/* Generic Memory controller initialization routine (AHB Registers)
+ *
+ * o0 = mem_handler structure pointer
+ * o1 = Configuration address of memory controller
+ * o2 = AHB Bus index
+ *
+ * Clobbered
+ *  o0-o5
+ */
+_nomem_ahbmctrl_init:
+	ld	[%o0 + MH_PRIV], %o0		/* Get Private structure */
+
+	/* Get index of AHB MBAR to get registers from */
+	ld	[%o0], %o5			
+	add	%o0, 4, %o0
+
+	/* Get Address of MBAR in PnP info */
+	add	%o5, 4, %o5
+	sll	%o5, 2, %o5
+	add	%o5, %o1, %o5			/* Address of MBAR */
+
+	/* Get Address of registers from PnP information 
+	 * Address is in AHB I/O format, i.e. relative to bus
+	 *
+	 * ADR = (iobar & (iobar << 16) & 0xfff00000)
+	 * IOADR = (ADR >> 12) | "APB Base"
+	 */
+	ld	[%o5], %o5
+	sll	%o5, 16, %o4
+	and	%o5, %o4, %o5
+	sethi	%hi(0xfff00000), %o4
+	and	%o5, %o4, %o5			/* ADR */
+	and	%o4, %o1, %o4
+	srl	%o5, 12, %o5
+	or	%o5, %o4, %o3			/* IOADR in o3 */
+
+	ld	[%o0], %o1			/* Get Reg Mask */
+	and	%o1, 0xff, %o1
+	add	%o0, REGS_OFS, %o0		/* Point to first reg */
+.L_do_one_ahbreg:
+	andcc	%o1, 0x1, %g0
+	beq	.L_do_next_reg
+	 ld	[%o0], %o2
+	ld	[%o3], %o4
+	and	%o4, %o2, %o4
+	ld	[%o0 + 4], %o2
+	or	%o4, %o2, %o4
+	st	%o4, [%o3]
+
+.L_do_next_ahbreg:
+	add	%o0, REGS_SIZE, %o0
+	add	%o3, 4, %o3
+	srl	%o1, 1, %o1
+	cmp	%o1, 0
+	bne	.L_do_one_reg
+	 nop
+
+	/* No more registers to write */
+	retl
+	 nop
diff --git a/cpu/leon3/start.S b/cpu/leon3/start.S
index bd634bd..d9faa86 100644
--- a/cpu/leon3/start.S
+++ b/cpu/leon3/start.S
@@ -29,6 +29,12 @@
 #include <asm/leon.h>
 #include <timestamp.h>
 #include <version.h>
+#include <ambapp.h>
+
+/* Default Plug&Play I/O area */
+#ifndef CONFIG_AMBAPP_IOAREA
+#define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
+#endif
 
 /* Entry for traps which jump to a programmer-specified trap handler.  */
 #define TRAPR(H)  \
@@ -205,6 +211,7 @@ version_string:
 	.ascii CONFIG_IDENT_STRING, "\0"
 
 	.section	".text"
+	.extern	_nomem_amba_init, _nomem_memory_ctrl_init
 	.align 4
 
 _hardreset:
@@ -256,6 +263,34 @@ stackp:
 	andn	%fp, 0x0f, %fp
 	sub	%fp, 64, %sp
 
+/* Scan AMBA Bus for AMBA buses using PnP information. All found
+ * AMBA buses I/O area will be located in i0-i5 upon return.
+ * The i0-i5 registers are later used by _nomem_amba_init2
+ */
+ambainit:
+	call	_nomem_amba_init
+	 sethi	%hi(CONFIG_AMBAPP_IOAREA), %o0
+
+/* Scan AMBA Buses for memory controllers, then initialize the
+ * memory controllers. Note that before setting up the memory controller
+ * the stack can not be used.
+ */
+memory_ctrl_init:
+ 	sethi	%hi(grlib_mctrl_handlers), %o0
+	call	_nomem_memory_ctrl_init
+	 or	%o0, %lo(grlib_mctrl_handlers), %o0
+
+/* The return valu indicate how many memory controllers where found and 
+ * initialized, if no memory controller was initialized, we can not continue
+ * because from here on we expect memory to be working.
+ */
+	cmp	%o0, 0
+memory_ctrl_init_failed:
+	beq	memory_ctrl_init_failed
+	 nop
+
+/*** From now on the stack can be used. ***/
+
 cpu_init_unreloc:
 	call	cpu_init_f
 	nop
@@ -385,6 +420,7 @@ jump:
 
 	set	board_init_f,%o1
 	set	CONFIG_SYS_RELOC_MONITOR_BASE,%o2
+	set	TEXT_START, %g1
 	add	%o1,%o2,%o1
 	sub	%o1,%g1,%o1
 	call	%o1
diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h
index d188439..b9d45dd 100644
--- a/include/configs/gr_cpci_ax2000.h
+++ b/include/configs/gr_cpci_ax2000.h
@@ -340,33 +340,36 @@
 /* AMBA Plug & Play info display on startup */
 /*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/
 
-#define CONFIG_SYS_GRLIB_SDRAM    0
+/* No SDRAM Configuration */
+#undef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
 
 /* See, GRLIB Docs (grip.pdf) on how to set up
  * These the memory controller registers.
  */
-#define CONFIG_SYS_GRLIB_MEMCFG1   (0x10f800ff | (1<<11))
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1   (0x10f800ff | (1<<11))
 #if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM_NOSRAM
-#define CONFIG_SYS_GRLIB_MEMCFG2   0x82206000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2   0x82206000
 #else
-#define CONFIG_SYS_GRLIB_MEMCFG2   0x82205260
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2   0x82205260
 #endif
-#define CONFIG_SYS_GRLIB_MEMCFG3   0x0809a000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3   0x0809a000
 
-#define CONFIG_SYS_GRLIB_FT_MEMCFG1   (0x10f800ff | (1<<11))
+/* GRLIB FT-MCTRL configuration */
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1   (0x10f800ff | (1<<11))
 #if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM_NOSRAM
-#define CONFIG_SYS_GRLIB_FT_MEMCFG2   0x82206000
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2   0x82206000
 #else
-#define CONFIG_SYS_GRLIB_FT_MEMCFG2   0x82205260
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2   0x82205260
 #endif
-#define CONFIG_SYS_GRLIB_FT_MEMCFG3   0x0809a000
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3   0x0809a000
 
 /* no DDR controller */
-#define CONFIG_SYS_GRLIB_DDR_CFG   0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
 
 /* no DDR2 Controller */
-#define CONFIG_SYS_GRLIB_DDR2_CFG1 0x00000000
-#define CONFIG_SYS_GRLIB_DDR2_CFG3 0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
 
 /* Calculate scaler register value from default baudrate */
 #define CONFIG_SYS_GRLIB_APBUART_SCALER \
diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h
index 3a568ff..6edb92c 100644
--- a/include/configs/gr_ep2s60.h
+++ b/include/configs/gr_ep2s60.h
@@ -326,23 +326,29 @@
 /* AMBA Plug & Play info display on startup */
 /*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/
 
-#define CONFIG_SYS_GRLIB_SDRAM    0
+/* No SDRAM Configuration */
+#undef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
 
 /* See, GRLIB Docs (grip.pdf) on how to set up
  * These the memory controller registers.
  */
-#define CONFIG_SYS_GRLIB_MEMCFG1  (0x10f800ff | (1<<11))
-#define CONFIG_SYS_GRLIB_MEMCFG2  0x00000000
-#define CONFIG_SYS_GRLIB_MEMCFG3  0x00000000
-
-#define CONFIG_SYS_GRLIB_FT_MEMCFG1  (0x10f800ff | (1<<11))
-#define CONFIG_SYS_GRLIB_FT_MEMCFG2  0x00000000
-#define CONFIG_SYS_GRLIB_FT_MEMCFG3  0x00000000
-
-#define CONFIG_SYS_GRLIB_DDR_CFG  0xa900830a
-
-#define CONFIG_SYS_GRLIB_DDR2_CFG1 0x00000000
-#define CONFIG_SYS_GRLIB_DDR2_CFG3 0x00000000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1  (0x10f800ff | (1<<11))
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2  0x00000000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3  0x00000000
+
+/* GRLIB FT-MCTRL configuration */
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1  (0x10f800ff | (1<<11))
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2  0x00000000
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3  0x00000000
+
+/* DDR controller */
+#define CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
+#define CONFIG_SYS_GRLIB_GAISLER_DDRSPA1_CTRL  0xa900830a
+
+/* no DDR2 Controller */
+#undef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
 
 /* Calculate scaler register value from default baudrate */
 #define CONFIG_SYS_GRLIB_APBUART_SCALER \
diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h
index 4dd9a0f..1f9dd4a 100644
--- a/include/configs/gr_xc3s_1500.h
+++ b/include/configs/gr_xc3s_1500.h
@@ -288,25 +288,28 @@
 /* AMBA Plug & Play info display on startup */
 /*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/
 
-#define CONFIG_SYS_GRLIB_SDRAM    0
+/* No SDRAM Configuration */
+#undef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
 
 /* See, GRLIB Docs (grip.pdf) on how to set up
  * These the memory controller registers.
  */
-#define CONFIG_SYS_GRLIB_MEMCFG1   (0x000000ff | (1<<11))
-#define CONFIG_SYS_GRLIB_MEMCFG2   0x82206000
-#define CONFIG_SYS_GRLIB_MEMCFG3   0x00136000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1   (0x000000ff | (1<<11))
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2   0x82206000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3   0x00136000
 
-#define CONFIG_SYS_GRLIB_FT_MEMCFG1   (0x000000ff | (1<<11))
-#define CONFIG_SYS_GRLIB_FT_MEMCFG2   0x82206000
-#define CONFIG_SYS_GRLIB_FT_MEMCFG3   0x00136000
+/* GRLIB FT-MCTRL configuration */
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1   (0x000000ff | (1<<11))
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2   0x82206000
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3   0x00136000
 
 /* no DDR controller */
-#define CONFIG_SYS_GRLIB_DDR_CFG   0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
 
 /* no DDR2 Controller */
-#define CONFIG_SYS_GRLIB_DDR2_CFG1 0x00000000
-#define CONFIG_SYS_GRLIB_DDR2_CFG3 0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
 
 /* Calculate scaler register value from default baudrate */
 #define CONFIG_SYS_GRLIB_APBUART_SCALER \
diff --git a/include/configs/grsim.h b/include/configs/grsim.h
index c3f1a31..f815672 100644
--- a/include/configs/grsim.h
+++ b/include/configs/grsim.h
@@ -307,27 +307,32 @@
 /* AMBA Plug & Play info display on startup */
 /*#define CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP*/
 
-#define CONFIG_SYS_GRLIB_SDRAM     0
-#define CONFIG_SYS_GRLIB_MEMCFG1   (0x000000ff | (1<<11))
+/* No SDRAM Configuration */
+#undef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
+
+/* LEON2 MCTRL configuration */
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1   (0x000000ff | (1<<11))
 #if CONFIG_GRSIM
 /* GRSIM configuration */
-#define CONFIG_SYS_GRLIB_MEMCFG2   0x82206000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2   0x82206000
 #else
 /* TSIM configuration */
-#define CONFIG_SYS_GRLIB_MEMCFG2   0x00001820
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2   0x00001820
 #endif
-#define CONFIG_SYS_GRLIB_MEMCFG3   0x00136000
+#define CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3   0x00136000
 
-#define CONFIG_SYS_GRLIB_FT_MEMCFG1   (0x000000ff | (1<<11))
-#define CONFIG_SYS_GRLIB_FT_MEMCFG2   0x82206000
-#define CONFIG_SYS_GRLIB_FT_MEMCFG3   0x00136000
+/* GRLIB FT-MCTRL configuration */
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1   (0x000000ff | (1<<11))
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2   0x82206000
+#define CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3   0x00136000
 
 /* no DDR controller */
-#define CONFIG_SYS_GRLIB_DDR_CFG   0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
 
 /* no DDR2 Controller */
-#define CONFIG_SYS_GRLIB_DDR2_CFG1 0x00000000
-#define CONFIG_SYS_GRLIB_DDR2_CFG3 0x00000000
+#undef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
 
 #define CONFIG_SYS_GRLIB_APBUART_SCALER \
  ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10)
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 06/17] LEON3: Moved GRLIB core header files to common include/grlib directory
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (3 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 05/17] LEON3: added memory controller initialization using the new AMBA PnP routines Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 07/17] LEON3: serial baud rate register support multiple buses with different frequency Daniel Hellstrom
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/cpu_init.c    |   10 ++--
 cpu/leon3/interrupts.c  |    7 ++-
 cpu/leon3/memcfg.h      |    1 -
 cpu/leon3/prom.c        |    7 ++-
 cpu/leon3/serial.c      |   16 +++---
 drivers/net/greth.c     |    2 +-
 include/ambapp.h        |  137 -----------------------------------------------
 include/grlib/apbuart.h |   63 +++++++++++++++++++++
 include/grlib/gptimer.h |   50 +++++++++++++++++
 include/grlib/greth.h   |  103 +++++++++++++++++++++++++++++++++++
 include/grlib/irqmp.h   |   39 +++++++++++++
 11 files changed, 277 insertions(+), 158 deletions(-)
 create mode 100644 include/grlib/apbuart.h
 create mode 100644 include/grlib/gptimer.h
 create mode 100644 include/grlib/greth.h
 create mode 100644 include/grlib/irqmp.h

diff --git a/cpu/leon3/cpu_init.c b/cpu/leon3/cpu_init.c
index 046cfb8..e2e1181 100644
--- a/cpu/leon3/cpu_init.c
+++ b/cpu/leon3/cpu_init.c
@@ -28,6 +28,8 @@
 #include <asm/asi.h>
 #include <asm/leon.h>
 #include <ambapp.h>
+#include <grlib/irqmp.h>
+#include <grlib/gptimer.h>
 
 #include <config.h>
 
@@ -41,11 +43,7 @@ DECLARE_GLOBAL_DATA_PTR;
 /* reset CPU (jump to 0, without reset) */
 void start(void);
 
-/* find & initialize the memory controller */
-int init_memory_ctrl(void);
-
 ambapp_dev_irqmp *irqmp = NULL;
-ambapp_dev_mctrl memctrl;
 ambapp_dev_gptimer *gptimer = NULL;
 unsigned int gptimer_irq = 0;
 int leon3_snooping_avail = 0;
@@ -164,8 +162,8 @@ int timer_interrupt_init_cpu(void)
 	gptimer->e[0].val = 0;
 	gptimer->e[0].rld = 999;	/* (((1000000 / 100) - 1)) */
 	gptimer->e[0].ctrl =
-	    (LEON3_GPTIMER_EN |
-	     LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
+	    (GPTIMER_CTRL_EN | GPTIMER_CTRL_RS |
+	     GPTIMER_CTRL_LD | GPTIMER_CTRL_IE);
 
 	return gptimer_irq;
 }
diff --git a/cpu/leon3/interrupts.c b/cpu/leon3/interrupts.c
index ac6aca5..d927de1 100644
--- a/cpu/leon3/interrupts.c
+++ b/cpu/leon3/interrupts.c
@@ -39,6 +39,8 @@
 
 #include <asm/leon.h>
 #include <ambapp.h>
+#include <grlib/irqmp.h>
+#include <grlib/gptimer.h>
 
 /* 15 normal irqs and a non maskable interrupt */
 #define NR_IRQS 15
@@ -141,9 +143,8 @@ int interrupt_init_cpu(void)
 /* Handle Timer 0 IRQ */
 void timer_interrupt_cpu(void *arg)
 {
-	gptimer->e[0].ctrl = (LEON3_GPTIMER_EN |
-			      LEON3_GPTIMER_RL |
-			      LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
+	gptimer->e[0].ctrl = (GPTIMER_CTRL_EN | GPTIMER_CTRL_RS |
+			      GPTIMER_CTRL_LD | GPTIMER_CTRL_IE);
 	/* nothing to do here */
 	return;
 }
diff --git a/cpu/leon3/memcfg.h b/cpu/leon3/memcfg.h
index 0b4738e..02086ce 100644
--- a/cpu/leon3/memcfg.h
+++ b/cpu/leon3/memcfg.h
@@ -54,7 +54,6 @@ extern struct grlib_mctrl_handler grlib_mctrl_handlers[];
 #define MH_STRUCT_SIZE		(4*4)
 #define MH_TYPE			0x00
 #define MH_INDEX		0x01
-#define MH_UNUSED		0x02
 #define MH_VENDOR_DEVICE	0x04
 #define MH_FUNC			0x08
 #define MH_PRIV			0x0c
diff --git a/cpu/leon3/prom.c b/cpu/leon3/prom.c
index 18d2fb2..86376bb 100644
--- a/cpu/leon3/prom.c
+++ b/cpu/leon3/prom.c
@@ -32,6 +32,9 @@
 #include <asm/irq.h>
 #include <asm/leon.h>
 #include <ambapp.h>
+#include <grlib/apbuart.h>
+#include <grlib/irqmp.h>
+#include <grlib/gptimer.h>
 
 #include <config.h>
 /*
@@ -757,14 +760,14 @@ static int PROM_TEXT leon_nbputchar(int c)
 
 	/* Wait for last character to go. */
 	while (!(SPARC_BYPASS_READ(&uart->status)
-		 & LEON_REG_UART_STATUS_THE)) ;
+		 & APBUART_STATUS_THE)) ;
 
 	/* Send data */
 	SPARC_BYPASS_WRITE(&uart->data, c);
 
 	/* Wait for data to be sent */
 	while (!(SPARC_BYPASS_READ(&uart->status)
-		 & LEON_REG_UART_STATUS_TSE)) ;
+		 & APBUART_STATUS_TSE)) ;
 
 	return 0;
 }
diff --git a/cpu/leon3/serial.c b/cpu/leon3/serial.c
index 15c380e..8964310 100644
--- a/cpu/leon3/serial.c
+++ b/cpu/leon3/serial.c
@@ -27,6 +27,7 @@
 #include <asm/processor.h>
 #include <asm/leon.h>
 #include <ambapp.h>
+#include <grlib/apbuart.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -69,9 +70,9 @@ int serial_init(void)
 		/* Let bit 11 be unchanged (debug bit for GRMON) */
 		tmp = READ_WORD(leon3_apbuart->ctrl);
 
-		leon3_apbuart->ctrl = ((tmp & LEON_REG_UART_CTRL_DBG) |
-				       LEON_REG_UART_CTRL_RE |
-				       LEON_REG_UART_CTRL_TE);
+		leon3_apbuart->ctrl = ((tmp & APBUART_CTRL_DBG) |
+				       APBUART_CTRL_RE |
+				       APBUART_CTRL_TE);
 
 		return 0;
 	}
@@ -92,14 +93,14 @@ void serial_putc_raw(const char c)
 		return;
 
 	/* Wait for last character to go. */
-	while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_THE)) ;
+	while (!(READ_WORD(leon3_apbuart->status) & APBUART_STATUS_THE)) ;
 
 	/* Send data */
 	leon3_apbuart->data = c;
 
 #ifdef LEON_DEBUG
 	/* Wait for data to be sent */
-	while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_TSE)) ;
+	while (!(READ_WORD(leon3_apbuart->status) & APBUART_STATUS_TSE)) ;
 #endif
 }
 
@@ -116,7 +117,7 @@ int serial_getc(void)
 		return 0;
 
 	/* Wait for a character to arrive. */
-	while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_DR)) ;
+	while (!(READ_WORD(leon3_apbuart->status) & APBUART_STATUS_DR)) ;
 
 	/* read data */
 	return READ_WORD(leon3_apbuart->data);
@@ -125,8 +126,7 @@ int serial_getc(void)
 int serial_tstc(void)
 {
 	if (leon3_apbuart)
-		return (READ_WORD(leon3_apbuart->status) &
-			LEON_REG_UART_STATUS_DR);
+		return (READ_WORD(leon3_apbuart->status) & APBUART_STATUS_DR);
 	return 0;
 }
 
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 5ac0379..582bc81 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -35,7 +35,7 @@
 
 /* #define DEBUG */
 
-#include "greth.h"
+#include <grlib/greth.h>
 
 /* Default to 3s timeout on autonegotiation */
 #ifndef GRETH_PHY_TIMEOUT_MS
diff --git a/include/ambapp.h b/include/ambapp.h
index c1c07aa..2a4c966 100644
--- a/include/ambapp.h
+++ b/include/ambapp.h
@@ -239,141 +239,4 @@ char *ambapp_device_id2desc(int vendor, int id);
 
 #define amba_apb_mask(iobar) ((~(amba_membar_mask(iobar)<<8) & 0x000fffff) + 1)
 
-/*************************** AMBA Plug&Play device register MAPS *****************/
-
-/*
- *  The following defines the bits in the LEON UART Status Registers.
- */
-
-#define LEON_REG_UART_STATUS_DR   0x00000001	/* Data Ready */
-#define LEON_REG_UART_STATUS_TSE  0x00000002	/* TX Send Register Empty */
-#define LEON_REG_UART_STATUS_THE  0x00000004	/* TX Hold Register Empty */
-#define LEON_REG_UART_STATUS_BR   0x00000008	/* Break Error */
-#define LEON_REG_UART_STATUS_OE   0x00000010	/* RX Overrun Error */
-#define LEON_REG_UART_STATUS_PE   0x00000020	/* RX Parity Error */
-#define LEON_REG_UART_STATUS_FE   0x00000040	/* RX Framing Error */
-#define LEON_REG_UART_STATUS_ERR  0x00000078	/* Error Mask */
-
-/*
- *  The following defines the bits in the LEON UART Ctrl Registers.
- */
-
-#define LEON_REG_UART_CTRL_RE     0x00000001	/* Receiver enable */
-#define LEON_REG_UART_CTRL_TE     0x00000002	/* Transmitter enable */
-#define LEON_REG_UART_CTRL_RI     0x00000004	/* Receiver interrupt enable */
-#define LEON_REG_UART_CTRL_TI     0x00000008	/* Transmitter interrupt enable */
-#define LEON_REG_UART_CTRL_PS     0x00000010	/* Parity select */
-#define LEON_REG_UART_CTRL_PE     0x00000020	/* Parity enable */
-#define LEON_REG_UART_CTRL_FL     0x00000040	/* Flow control enable */
-#define LEON_REG_UART_CTRL_LB     0x00000080	/* Loop Back enable */
-#define LEON_REG_UART_CTRL_DBG    (1<<11)	/* Debug Bit used by GRMON */
-
-#define LEON3_GPTIMER_EN 1
-#define LEON3_GPTIMER_RL 2
-#define LEON3_GPTIMER_LD 4
-#define LEON3_GPTIMER_IRQEN 8
-
-/*
- *  The following defines the bits in the LEON PS/2 Status Registers.
- */
-
-#define LEON_REG_PS2_STATUS_DR   0x00000001	/* Data Ready */
-#define LEON_REG_PS2_STATUS_PE   0x00000002	/* Parity error */
-#define LEON_REG_PS2_STATUS_FE   0x00000004	/* Framing error */
-#define LEON_REG_PS2_STATUS_KI   0x00000008	/* Keyboard inhibit */
-
-/*
- *  The following defines the bits in the LEON PS/2 Ctrl Registers.
- */
-
-#define LEON_REG_PS2_CTRL_RE     0x00000001	/* Receiver enable */
-#define LEON_REG_PS2_CTRL_TE     0x00000002	/* Transmitter enable */
-#define LEON_REG_PS2_CTRL_RI     0x00000004	/* Keyboard receive interrupt  */
-#define LEON_REG_PS2_CTRL_TI     0x00000008	/* Keyboard transmit interrupt */
-
-#ifndef __ASSEMBLER__
-
-typedef struct {
-	volatile unsigned int ilevel;
-	volatile unsigned int ipend;
-	volatile unsigned int iforce;
-	volatile unsigned int iclear;
-	volatile unsigned int mstatus;
-	volatile unsigned int notused[11];
-	volatile unsigned int cpu_mask[16];
-	volatile unsigned int cpu_force[16];
-} ambapp_dev_irqmp;
-
-typedef struct {
-	volatile unsigned int data;
-	volatile unsigned int status;
-	volatile unsigned int ctrl;
-	volatile unsigned int scaler;
-} ambapp_dev_apbuart;
-
-typedef struct {
-	volatile unsigned int val;
-	volatile unsigned int rld;
-	volatile unsigned int ctrl;
-	volatile unsigned int unused;
-} ambapp_dev_gptimer_element;
-
-#define LEON3_GPTIMER_CTRL_EN	0x1	/* Timer enable */
-#define LEON3_GPTIMER_CTRL_RS	0x2	/* Timer reStart  */
-#define LEON3_GPTIMER_CTRL_LD	0x4	/* Timer reLoad */
-#define LEON3_GPTIMER_CTRL_IE	0x8	/* interrupt enable */
-#define LEON3_GPTIMER_CTRL_IP	0x10	/* interrupt flag/pending */
-#define LEON3_GPTIMER_CTRL_CH	0x20	/* Chain with previous timer */
-
-typedef struct {
-	volatile unsigned int scalar;
-	volatile unsigned int scalar_reload;
-	volatile unsigned int config;
-	volatile unsigned int unused;
-	volatile ambapp_dev_gptimer_element e[8];
-} ambapp_dev_gptimer;
-
-typedef struct {
-	volatile unsigned int iodata;
-	volatile unsigned int ioout;
-	volatile unsigned int iodir;
-	volatile unsigned int irqmask;
-	volatile unsigned int irqpol;
-	volatile unsigned int irqedge;
-} ambapp_dev_ioport;
-
-typedef struct {
-	volatile unsigned int write;
-	volatile unsigned int dummy;
-	volatile unsigned int txcolor;
-	volatile unsigned int bgcolor;
-} ambapp_dev_textvga;
-
-typedef struct {
-	volatile unsigned int data;
-	volatile unsigned int status;
-	volatile unsigned int ctrl;
-} ambapp_dev_apbps2;
-
-typedef struct {
-	unsigned int mcfg1, mcfg2, mcfg3;
-} ambapp_dev_mctrl;
-
-typedef struct {
-	unsigned int sdcfg;
-} ambapp_dev_sdctrl;
-
-typedef struct {
-	unsigned int cfg1;
-	unsigned int cfg2;
-	unsigned int cfg3;
-} ambapp_dev_ddr2spa;
-
-typedef struct {
-	unsigned int ctrl;
-	unsigned int cfg;
-} ambapp_dev_ddrspa;
-
-#endif
-
 #endif
diff --git a/include/grlib/apbuart.h b/include/grlib/apbuart.h
new file mode 100644
index 0000000..92bbcdf
--- /dev/null
+++ b/include/grlib/apbuart.h
@@ -0,0 +1,63 @@
+/* GRLIB APBUART definitions
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __GRLIB_APBUART_H__
+#define __GRLIB_APBUART_H__
+
+/* APBUART Register map */
+typedef struct {
+	volatile unsigned int data;
+	volatile unsigned int status;
+	volatile unsigned int ctrl;
+	volatile unsigned int scaler;
+} ambapp_dev_apbuart;
+
+/*
+ *  The following defines the bits in the LEON UART Status Registers.
+ */
+
+#define APBUART_STATUS_DR   0x00000001	/* Data Ready */
+#define APBUART_STATUS_TSE  0x00000002	/* TX Send Register Empty */
+#define APBUART_STATUS_THE  0x00000004	/* TX Hold Register Empty */
+#define APBUART_STATUS_BR   0x00000008	/* Break Error */
+#define APBUART_STATUS_OE   0x00000010	/* RX Overrun Error */
+#define APBUART_STATUS_PE   0x00000020	/* RX Parity Error */
+#define APBUART_STATUS_FE   0x00000040	/* RX Framing Error */
+#define APBUART_STATUS_ERR  0x00000078	/* Error Mask */
+
+/*
+ *  The following defines the bits in the LEON UART Ctrl Registers.
+ */
+
+#define APBUART_CTRL_RE     0x00000001	/* Receiver enable */
+#define APBUART_CTRL_TE     0x00000002	/* Transmitter enable */
+#define APBUART_CTRL_RI     0x00000004	/* Receiver interrupt enable */
+#define APBUART_CTRL_TI     0x00000008	/* Transmitter interrupt enable */
+#define APBUART_CTRL_PS     0x00000010	/* Parity select */
+#define APBUART_CTRL_PE     0x00000020	/* Parity enable */
+#define APBUART_CTRL_FL     0x00000040	/* Flow control enable */
+#define APBUART_CTRL_LB     0x00000080	/* Loop Back enable */
+#define APBUART_CTRL_DBG    (1<<11)	/* Debug Bit used by GRMON */
+
+#endif
diff --git a/include/grlib/gptimer.h b/include/grlib/gptimer.h
new file mode 100644
index 0000000..4e79874
--- /dev/null
+++ b/include/grlib/gptimer.h
@@ -0,0 +1,50 @@
+/* GRLIB GPTIMER (General Purpose Timer) definitions
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __GRLIB_GPTIMER_H__
+#define __GRLIB_GPTIMER_H__
+
+typedef struct {
+	volatile unsigned int val;
+	volatile unsigned int rld;
+	volatile unsigned int ctrl;
+	volatile unsigned int unused;
+} ambapp_dev_gptimer_element;
+
+#define GPTIMER_CTRL_EN	0x1	/* Timer enable */
+#define GPTIMER_CTRL_RS	0x2	/* Timer reStart  */
+#define GPTIMER_CTRL_LD	0x4	/* Timer reLoad */
+#define GPTIMER_CTRL_IE	0x8	/* interrupt enable */
+#define GPTIMER_CTRL_IP	0x10	/* interrupt flag/pending */
+#define GPTIMER_CTRL_CH	0x20	/* Chain with previous timer */
+
+typedef struct {
+	volatile unsigned int scalar;
+	volatile unsigned int scalar_reload;
+	volatile unsigned int config;
+	volatile unsigned int unused;
+	volatile ambapp_dev_gptimer_element e[8];
+} ambapp_dev_gptimer;
+
+#endif
diff --git a/include/grlib/greth.h b/include/grlib/greth.h
new file mode 100644
index 0000000..08cdad4
--- /dev/null
+++ b/include/grlib/greth.h
@@ -0,0 +1,103 @@
+/* Gaisler.com GRETH 10/100/1000 Ethernet MAC definitions
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __GRLIB_GRETH_H__
+#define __GRLIB_GRETH_H__
+
+#define GRETH_FD 0x10
+#define GRETH_RESET 0x40
+#define GRETH_MII_BUSY 0x8
+#define GRETH_MII_NVALID 0x10
+
+/* MII registers */
+#define GRETH_MII_EXTADV_1000FD 0x00000200
+#define GRETH_MII_EXTADV_1000HD 0x00000100
+#define GRETH_MII_EXTPRT_1000FD 0x00000800
+#define GRETH_MII_EXTPRT_1000HD 0x00000400
+
+#define GRETH_MII_100T4 0x00000200
+#define GRETH_MII_100TXFD 0x00000100
+#define GRETH_MII_100TXHD 0x00000080
+#define GRETH_MII_10FD 0x00000040
+#define GRETH_MII_10HD 0x00000020
+
+#define GRETH_BD_EN 0x800
+#define GRETH_BD_WR 0x1000
+#define GRETH_BD_IE 0x2000
+#define GRETH_BD_LEN 0x7FF
+
+#define GRETH_TXEN 0x1
+#define GRETH_INT_TX 0x8
+#define GRETH_TXI 0x4
+#define GRETH_TXBD_STATUS 0x0001C000
+#define GRETH_TXBD_MORE 0x20000
+#define GRETH_TXBD_IPCS 0x40000
+#define GRETH_TXBD_TCPCS 0x80000
+#define GRETH_TXBD_UDPCS 0x100000
+#define GRETH_TXBD_ERR_LC 0x10000
+#define GRETH_TXBD_ERR_UE 0x4000
+#define GRETH_TXBD_ERR_AL 0x8000
+#define GRETH_TXBD_NUM 128
+#define GRETH_TXBD_NUM_MASK (GRETH_TXBD_NUM-1)
+#define GRETH_TX_BUF_SIZE 2048
+
+#define GRETH_INT_RX         0x4
+#define GRETH_RXEN           0x2
+#define GRETH_RXI            0x8
+#define GRETH_RXBD_STATUS    0xFFFFC000
+#define GRETH_RXBD_ERR_AE    0x4000
+#define GRETH_RXBD_ERR_FT    0x8000
+#define GRETH_RXBD_ERR_CRC   0x10000
+#define GRETH_RXBD_ERR_OE    0x20000
+#define GRETH_RXBD_ERR_LE    0x40000
+#define GRETH_RXBD_IP_DEC    0x80000
+#define GRETH_RXBD_IP_CSERR  0x100000
+#define GRETH_RXBD_UDP_DEC   0x200000
+#define GRETH_RXBD_UDP_CSERR 0x400000
+#define GRETH_RXBD_TCP_DEC   0x800000
+#define GRETH_RXBD_TCP_CSERR 0x1000000
+
+#define GRETH_RXBD_NUM 128
+#define GRETH_RXBD_NUM_MASK (GRETH_RXBD_NUM-1)
+#define GRETH_RX_BUF_SIZE 2048
+
+/* Ethernet configuration registers */
+typedef struct _greth_regs {
+	volatile unsigned int control;
+	volatile unsigned int status;
+	volatile unsigned int esa_msb;
+	volatile unsigned int esa_lsb;
+	volatile unsigned int mdio;
+	volatile unsigned int tx_desc_p;
+	volatile unsigned int rx_desc_p;
+	volatile unsigned int edcl_ip;
+} greth_regs;
+
+/* Ethernet buffer descriptor */
+typedef struct _greth_bd {
+	volatile unsigned int stat;
+	unsigned int addr;	/* Buffer address not changed by HW */
+} greth_bd;
+
+#endif
diff --git a/include/grlib/irqmp.h b/include/grlib/irqmp.h
new file mode 100644
index 0000000..1cf45ee
--- /dev/null
+++ b/include/grlib/irqmp.h
@@ -0,0 +1,39 @@
+/* GRLIB IRQMP (IRQ Multi-processor controller) definitions
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel@gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __GRLIB_IRQMP_H__
+#define __GRLIB_IRQMP_H__
+
+typedef struct {
+	volatile unsigned int ilevel;
+	volatile unsigned int ipend;
+	volatile unsigned int iforce;
+	volatile unsigned int iclear;
+	volatile unsigned int mstatus;
+	volatile unsigned int notused[11];
+	volatile unsigned int cpu_mask[16];
+	volatile unsigned int cpu_force[16];
+} ambapp_dev_irqmp;
+
+#endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 07/17] LEON3: serial baud rate register support multiple buses with different frequency.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (4 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 06/17] LEON3: Moved GRLIB core header files to common include/grlib directory Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 08/17] SPARC: added function that checks if IRQ is on or off Daniel Hellstrom
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/serial.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/cpu/leon3/serial.c b/cpu/leon3/serial.c
index 8964310..1f17ede 100644
--- a/cpu/leon3/serial.c
+++ b/cpu/leon3/serial.c
@@ -47,11 +47,18 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif
 
 ambapp_dev_apbuart *leon3_apbuart = NULL;
+unsigned int apbuart_freq = CONFIG_SYS_CLK_FREQ;
+
+unsigned int apbuart_calc_scaler(unsigned int apbuart_freq, unsigned int baud)
+{
+	return ((((apbuart_freq*10)/(baud*8))-5)/10);
+}
 
 int serial_init(void)
 {
 	ambapp_apbdev apbdev;
 	unsigned int tmp;
+	unsigned int freq;
 
 	/* find UART */
 	if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
@@ -65,7 +72,13 @@ int serial_init(void)
 		 *
 		 * Receiver & transmitter enable
 		 */
+#ifdef CONFIG_SYS_GRLIB_APBUART_SCALER
 		leon3_apbuart->scaler = CONFIG_SYS_GRLIB_APBUART_SCALER;
+#else
+		/* APBUART Frequency is equal to bus frequency */
+		freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
+		leon3_apbuart->scaler = apbuart_calc_scaler(freq, CONFIG_BAUDRATE);
+#endif
 
 		/* Let bit 11 be unchanged (debug bit for GRMON) */
 		tmp = READ_WORD(leon3_apbuart->ctrl);
@@ -136,9 +149,7 @@ void serial_setbrg(void)
 	/* update baud rate settings, read it from gd->baudrate */
 	unsigned int scaler;
 	if (leon3_apbuart && (gd->baudrate > 0)) {
-		scaler =
-		    (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) -
-		     5) / 10;
+		scaler = apbuart_calc_scaler(apbuart_freq, gd->baudrate);
 		leon3_apbuart->scaler = scaler;
 	}
 	return;
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 08/17] SPARC: added function that checks if IRQ is on or off.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (5 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 07/17] LEON3: serial baud rate register support multiple buses with different frequency Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 09/17] LEON3: added busy wait function, made wait_ms() work when IRQ is disabled Daniel Hellstrom
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 include/asm-sparc/irq.h |    3 +++
 lib_sparc/interrupts.c  |    7 +++++++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h
index c5538c0..ce78169 100644
--- a/include/asm-sparc/irq.h
+++ b/include/asm-sparc/irq.h
@@ -46,4 +46,7 @@ extern int intLock(void);
 /* Sets the PIL to oldLevel */
 extern void intUnlock(int oldLevel);
 
+/* Return non-zero if interrupts are currently enabled */
+extern int interrupt_is_enabled(void);
+
 #endif
diff --git a/lib_sparc/interrupts.c b/lib_sparc/interrupts.c
index 4c73b82..4d53e8c 100644
--- a/lib_sparc/interrupts.c
+++ b/lib_sparc/interrupts.c
@@ -63,6 +63,13 @@ int disable_interrupts(void)
 	return intLock();
 }
 
+int interrupt_is_enabled(void)
+{
+	if ( get_pil() == 15 )
+		return 0;
+	return 1;
+}
+
 int interrupt_init(void)
 {
 	int ret;
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 09/17] LEON3: added busy wait function, made wait_ms() work when IRQ is disabled.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (6 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 08/17] SPARC: added function that checks if IRQ is on or off Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 10/17] LEON3: added CPU count and frequency detection Daniel Hellstrom
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/cpu_init.c |   30 ++++++++++++++++++++++++++++--
 1 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/cpu/leon3/cpu_init.c b/cpu/leon3/cpu_init.c
index e2e1181..d2f47e1 100644
--- a/cpu/leon3/cpu_init.c
+++ b/cpu/leon3/cpu_init.c
@@ -142,14 +142,40 @@ int cpu_init_r(void)
 	return (0);
 }
 
+/* Busy wait a number of ms */
+void cpu_wait_ms_busy(unsigned long ms)
+{
+	unsigned int ms_delay;
+	volatile unsigned int tmp;
+
+	/* ~10-20 cycles per decrement */
+	ms_delay = leon_cpu_freq / (1000 * 10);
+	do {
+		/* Wait ~1ms */
+		tmp = ms_delay;
+		while ( tmp-- > 0 )
+			;
+	} while ( --ms > 0 );
+}
+
 /* Uses Timer 0 to get accurate
  * pauses. Max 2 raised to 32 ticks
  *
  */
 void cpu_wait_ticks(unsigned long ticks)
 {
-	unsigned long start = get_timer(0);
-	while (get_timer(start) < ticks) ;
+	unsigned long start;
+
+	if ( interrupt_is_enabled() ) {
+		start = get_timer(0);
+		while (get_timer(start) < ticks) ;
+	} else {
+		/* Interrupts disabled, this means that we cannot 
+		 * use get_timer(), it relies on IRQ. Instead the
+		 * CPU frequency is used.
+		 */
+		cpu_wait_ms_busy( ticks2usec(ticks) / 1000 );
+	}
 }
 
 /* initiate and setup timer0 interrupt to 1MHz
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 10/17] LEON3: added CPU count and frequency detection.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (7 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 09/17] LEON3: added busy wait function, made wait_ms() work when IRQ is disabled Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 11/17] SPARC: removed USB stop from linux bootm, arch-independent bootm stop USB Daniel Hellstrom
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/cpu.c           |   42 +++++++++++++++++++++++++++++++++++++++++-
 include/asm-sparc/leon3.h |   13 +++++++++++++
 2 files changed, 54 insertions(+), 1 deletions(-)

diff --git a/cpu/leon3/cpu.c b/cpu/leon3/cpu.c
index 976f311..5cc9513 100644
--- a/cpu/leon3/cpu.c
+++ b/cpu/leon3/cpu.c
@@ -29,15 +29,55 @@
 
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <ambapp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 extern void _reset_reloc(void);
 
+int leon_cpu_cnt = 1;
+int leon_ver = 3;
+unsigned int leon_cpu_freq = CONFIG_SYS_CLK_FREQ;
+
+int cpu_freq(void)
+{
+	ambapp_ahbdev dev;
+
+	if ( leon_ver == 3 ) {
+		ambapp_ahbmst_find(&ambapp_plb, VENDOR_GAISLER,
+			GAISLER_LEON3, 0, &dev);
+	} else {
+		ambapp_ahbmst_find(&ambapp_plb, VENDOR_GAISLER,
+			GAISLER_LEON4, 0, &dev);
+	}
+
+	leon_cpu_freq = ambapp_bus_freq(&ambapp_plb, dev.ahb_bus_index);
+}
+
 int checkcpu(void)
 {
+	int cnt;
+	char str[4];
+
 	/* check LEON version here */
-	printf("CPU: LEON3\n");
+	cnt = ambapp_ahbmst_count(&ambapp_plb, VENDOR_GAISLER, GAISLER_LEON3);
+	if ( cnt <= 0 ) {
+		cnt = ambapp_ahbmst_count(&ambapp_plb, VENDOR_GAISLER, GAISLER_LEON4);
+		if ( cnt > 0 )
+			leon_ver = 4;
+	}
+
+	cpu_freq();
+
+	str[0] = '\0';
+	if ( cnt > 1 ) {
+		leon_cpu_cnt = cnt;
+		str[0] = '0' + cnt;
+		str[1] = 'x';
+		str[2] = '\0';
+	}
+	printf("CPU: %sLEON%d @ %dMHz\n", str, leon_ver, leon_cpu_freq / 1000000);
+
 	return 0;
 }
 
diff --git a/include/asm-sparc/leon3.h b/include/asm-sparc/leon3.h
index b90d35b..60396c4 100644
--- a/include/asm-sparc/leon3.h
+++ b/include/asm-sparc/leon3.h
@@ -33,4 +33,17 @@
  * ctrl, memory controllers etc.
  */
 
+
+#ifndef __ASSEMBLER__
+/* The frequency of the CPU */
+extern unsigned int leon_cpu_freq;
+
+/* Number of LEON processors in system */
+extern int leon_cpu_cnt;
+
+/* Ver/subversion of CPU */
+extern int leon_ver;
+
+#endif /* __ASSEMBLER__ */
+
 #endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 11/17] SPARC: removed USB stop from linux bootm, arch-independent bootm stop USB.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (8 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 10/17] LEON3: added CPU count and frequency detection Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine Daniel Hellstrom
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 lib_sparc/bootm.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c
index c62cf57..f517325 100644
--- a/lib_sparc/bootm.c
+++ b/lib_sparc/bootm.c
@@ -35,10 +35,6 @@ extern image_header_t header;
 extern void srmmu_init_cpu(unsigned int entry);
 extern void prepare_bootargs(char *bootargs);
 
-#ifdef CONFIG_USB_UHCI
-extern int usb_lowlevel_stop(void);
-#endif
-
 /* sparc kernel argument (the ROM vector) */
 struct linux_romvec *kernel_arg_promvec;
 
@@ -125,10 +121,6 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t * images)
 	       linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
 #endif
 
-#ifdef CONFIG_USB_UHCI
-	usb_lowlevel_stop();
-#endif
-
 	/* set basic boot params in kernel header now that it has been
 	 * extracted and is writeable.
 	 */
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (9 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 11/17] SPARC: removed USB stop from linux bootm, arch-independent bootm stop USB Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 13/17] LEON3: Added GRETH EDCL debug link IP address initialization Daniel Hellstrom
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 lib_sparc/board.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/lib_sparc/board.c b/lib_sparc/board.c
index 11eea60..d829af0 100644
--- a/lib_sparc/board.c
+++ b/lib_sparc/board.c
@@ -65,6 +65,7 @@ extern void timer_interrupt_init(void);
 extern void malloc_bin_reloc(void);
 extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
 extern int prom_init(void);
+extern void cpu_late_init(void);
 
 #if defined(CONFIG__CMD_DOC)
 void doc_init(void);
@@ -353,6 +354,10 @@ void board_init_f(ulong bootflag)
 	/* relocate environment function pointers etc. */
 	env_relocate();
 
+#if defined(CONFIG_CPU_LATE_INIT)
+	cpu_late_init();
+#endif
+
 #if defined(CONFIG_BOARD_LATE_INIT)
 	board_late_init();
 #endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 13/17] LEON3: Added GRETH EDCL debug link IP address initialization.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (10 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 14/17] LEON: added support for GRLIB SPI Memory controller, spi command interface Daniel Hellstrom
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/cpu_init.c |   14 +++++
 cpu/leon3/greth.c    |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 cpu/leon3/greth.c

diff --git a/cpu/leon3/cpu_init.c b/cpu/leon3/cpu_init.c
index d2f47e1..39c4bb8 100644
--- a/cpu/leon3/cpu_init.c
+++ b/cpu/leon3/cpu_init.c
@@ -43,6 +43,9 @@ DECLARE_GLOBAL_DATA_PTR;
 /* reset CPU (jump to 0, without reset) */
 void start(void);
 
+/* Initialize GRETH EDCL on startup */
+extern void greth_edcl_init(void);
+
 ambapp_dev_irqmp *irqmp = NULL;
 ambapp_dev_gptimer *gptimer = NULL;
 unsigned int gptimer_irq = 0;
@@ -142,6 +145,17 @@ int cpu_init_r(void)
 	return (0);
 }
 
+/* Late CPU initialization
+ *
+ * At this point environment variables is available.
+ */
+void cpu_late_init(void)
+{
+#ifdef CONFIG_SYS_GRETH_EDCL_IP
+	greth_edcl_init();
+#endif
+}
+
 /* Busy wait a number of ms */
 void cpu_wait_ms_busy(unsigned long ms)
 {
diff --git a/cpu/leon3/greth.c b/cpu/leon3/greth.c
new file mode 100644
index 0000000..7f341e6
--- /dev/null
+++ b/cpu/leon3/greth.c
@@ -0,0 +1,152 @@
+/* GRETH EDCL IP number initialization
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <ambapp.h>
+#include <config.h>
+#include <grlib/greth.h>
+
+#ifdef CONFIG_SYS_GRETH_EDCL_IP
+
+/* Set EDCL IP of GRETH[core_index] to IP number as indicated by ip_str
+ *
+ * This is useful for designs that have a disabled EDCL (IP=0.0.0.0) on
+ * reset, or when the default EDCL IP is no correct. Often 192.168.0.51
+ * is default, the IP must be unique which is a problem when multiple
+ * boards are used.
+ *
+ * NOTE: The EDCL IP must not be the same IP as U-BOOT is using.
+ *
+ * NOTE: This code should not be located in the GRETH driver, because
+ *       we might want to set the EDCL debug link IP but not enable
+ *       u-boot networking.
+ */
+int greth_edcl_ip_set(int core_index, char *ip_str)
+{
+	ambapp_apbdev apbdev;
+	unsigned int *greth_ip_reg;
+	unsigned int ip;
+	char *start, *end;
+	unsigned char ipbyte;
+	int i;
+
+	/* Find Device & IRQ via AMBA Plug&Play information,
+	 * CONFIG_SYS_GRLIB_GRETH_INDEX select which GRETH if multiple
+	 * GRETHs in system.
+	 */
+	if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_ETHMAC,
+				core_index, &apbdev) != 1) {
+		return -1;	/* GRETH not found */
+	}
+	greth_ip_reg = (unsigned int *)(apbdev.address + 0x1C);
+
+	/* Convert IP String into IP number */
+	ip = 0;
+	start = ip_str;
+	for (i = 0; i < 4; i++) {
+		ipbyte = simple_strtoul(start, &end, 10);
+		ip |= ipbyte << (24-i*8);
+		start = end + 1; /* Next byte in IP-string */
+	}
+
+	/* Set new IP address of EDCL */
+	*greth_ip_reg = ip;
+
+	printf("GRETH[0x%08x] EDCL IP: %s\n",
+		(unsigned int)greth_ip_reg, ip_str);
+
+	return 0;
+};
+
+char *greth_edcl_ip_table[8] =
+{
+#ifdef CONFIG_SYS_GRETH0_EDCL_IP_STR
+	CONFIG_SYS_GRETH0_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH1_EDCL_IP_STR
+	CONFIG_SYS_GRETH1_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH2_EDCL_IP_STR
+	CONFIG_SYS_GRETH2_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH3_EDCL_IP_STR
+	CONFIG_SYS_GRETH3_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH4_EDCL_IP_STR
+	CONFIG_SYS_GRETH4_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH5_EDCL_IP_STR
+	CONFIG_SYS_GRETH5_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH6_EDCL_IP_STR
+	CONFIG_SYS_GRETH6_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+#ifdef CONFIG_SYS_GRETH7_EDCL_IP_STR
+	CONFIG_SYS_GRETH7_EDCL_IP_STR,
+#else
+	NULL,
+#endif
+};
+
+void greth_edcl_init(void)
+{
+	int i;
+	char *ip_str;
+	char envname[16];
+
+	/* Set EDCL IP of the first 8 cores, if requested by user through 
+	 * Environment variable "greth_edcl_ipN" when N identifies which 
+	 * GRETH core, or through defines set in board configuration.
+	 */
+	strcpy(envname, "greth_edcl_ipX");
+	for (i=0; i<8; i++) {
+		/* Is there a config for */
+		envname[13] = '0' + i;
+		ip_str = getenv(envname);
+		if ( ip_str == NULL ) {
+			ip_str = greth_edcl_ip_table[i];
+		}
+		if ( ip_str != NULL ) {
+			if ( greth_edcl_ip_set(i, ip_str) )
+				break;
+		}
+	}
+}
+
+#endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 14/17] LEON: added support for GRLIB SPI Memory controller, spi command interface.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (11 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 13/17] LEON3: Added GRETH EDCL debug link IP address initialization Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 15/17] LEON3: fixed MMU table for systems with larger memory than 128MB Daniel Hellstrom
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 drivers/spi/Makefile       |    1 +
 drivers/spi/spimctrl_spi.c |  261 ++++++++++++++++++++++++++++++++++++++++++++
 include/grlib/spimctrl.h   |   69 ++++++++++++
 lib_sparc/board.c          |   14 +++
 4 files changed, 345 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/spimctrl_spi.c
 create mode 100644 include/grlib/spimctrl.h

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 824d8e7..a730d45 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
+COBJS-$(CONFIG_SPIMCTRL_SPI) += spimctrl_spi.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/spi/spimctrl_spi.c b/drivers/spi/spimctrl_spi.c
new file mode 100644
index 0000000..a37cfa9
--- /dev/null
+++ b/drivers/spi/spimctrl_spi.c
@@ -0,0 +1,261 @@
+/* SPI interface driver for GRLIB SPIMCTRL (SPI Memory controller)
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom <daniel@gaisler.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <ambapp.h>
+#include <grlib/spimctrl.h>
+
+struct spimctrl_priv {
+	struct spimctrl_regs *regs;
+	int irq;
+	unsigned int mode;
+	unsigned int max_hz;
+};
+
+struct spi_slave_internal {
+	struct spi_slave dev;
+	struct spimctrl_priv *priv;
+	int locked;
+};
+
+static int spimctrl_cnt = 0;
+static struct spimctrl_priv *spimctrl_devs;
+
+int spimctrl_probe(void)
+{
+	int cnt, i, found;
+	ambapp_ahbdev ahbdev;
+	struct spimctrl_priv *priv;
+
+	cnt = ambapp_ahbslv_count(&ambapp_plb,VENDOR_GAISLER,GAISLER_SPIMCTRL);
+	debug("Found %d SPIMCTRLS\n", cnt);
+	if ( cnt < 1 )
+		return 0;
+
+	spimctrl_cnt = cnt;
+	spimctrl_devs = (struct spimctrl_priv *) malloc(sizeof(*priv) * cnt);
+	memset(spimctrl_devs, 0, sizeof(struct spimctrl_priv) * cnt);
+
+	for (i=0; i<cnt; i++) {
+		found = ambapp_ahbslv_find(&ambapp_plb, VENDOR_GAISLER,
+				GAISLER_SPIMCTRL, i, &ahbdev);
+		if ( !found ) {
+			printf("spimctrl_probe: internal AMBA error\n");
+			while (1) ;
+		}
+
+		priv = &spimctrl_devs[i];
+		priv->regs = (struct spimctrl_regs *)ahbdev.address[0];
+		priv->irq = ahbdev.irq;
+
+		debug("SPIMCTRL[%d]: 0x%x irq %d\n",
+			i, (unsigned int)priv->regs, priv->irq);
+	}
+
+	return cnt;
+}
+
+void spimctrl_init(struct spimctrl_priv *priv)
+{
+	debug("SPIMCTRL_INIT\n");
+
+	/* Finish any previous ongoing user activity, this should
+	 * not normally happen, but may when debugging.
+	 */
+	if ( priv->regs->stat & SPIMCTRL_STAT_DONE )
+		priv->regs->stat = SPIMCTRL_STAT_DONE;
+
+	if ( priv->regs->ctrl & SPIMCTRL_CTRL_USRC ) {
+		/* Exit User mode */
+		priv->regs->ctrl = SPIMCTRL_CTRL_CSN;
+	}
+}
+
+void spimctrl_cs_activate(struct spimctrl_priv *priv)
+{
+	debug("CS ACT\n");
+
+	if ( priv->regs->stat & SPIMCTRL_STAT_DONE )
+		priv->regs->stat = SPIMCTRL_STAT_DONE;
+
+	/* Enter User mode */
+	priv->regs->ctrl = SPIMCTRL_CTRL_CSN | SPIMCTRL_CTRL_USRC;
+
+	/* Lower chip-select */
+	priv->regs->ctrl = SPIMCTRL_CTRL_USRC;
+}
+
+void spimctrl_cs_deactivate(struct spimctrl_priv *priv)
+{
+	debug("CS INACT\n");
+
+	/* Rise chip select */
+	priv->regs->ctrl = SPIMCTRL_CTRL_CSN | SPIMCTRL_CTRL_USRC;
+
+	/* Exit User mode */
+	priv->regs->ctrl = SPIMCTRL_CTRL_CSN;
+}
+
+void spimctrl_transfer_byte(struct spimctrl_priv *priv, char *out, char *in)
+{
+	unsigned int stat;
+	unsigned char rx;
+
+	while( (stat=priv->regs->stat) & 
+		(SPIMCTRL_STAT_BUSY|SPIMCTRL_STAT_DONE) ) {
+		debug("WAITING1: 0x%x\n", stat);
+	}
+	debug("OK STAT1: 0x%x\n", stat);
+
+	if ( out ) {
+		priv->regs->tx = out[0];	
+	} else {
+		priv->regs->tx = 0;
+	}
+
+	while ( ((stat=priv->regs->stat) & SPIMCTRL_STAT_DONE) == 0 ) {
+		debug("WAITING2: 0x%x\n", stat);
+	}
+	debug("OK STAT2: 0x%x\n", stat);
+	rx = priv->regs->rx;
+	if ( in ) {
+		in[0] = rx;
+	}
+	priv->regs->stat = SPIMCTRL_STAT_DONE;
+
+	if ( out && in ) {
+		debug("OUT 0x%02x ; IN 0x%02x\n", out[0], in[0]);
+	} else if ( out ) {
+		debug("OUT 0x%02x\n", out[0]);
+	} else if ( in ) {
+		debug("IN: 0x%02x\n", in[0]);
+	}
+}
+
+void spi_init(void)
+{
+	int i;
+
+	debug("SPI INIT\n");
+
+	/* Find SPIMCTRL cores */
+	spimctrl_probe();
+
+	/* Init SPIMCTRL Core */
+	for ( i=0; i<spimctrl_cnt; i++) {
+		spimctrl_init(&spimctrl_devs[i]);
+	}
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct spi_slave_internal *slave;
+
+	debug("spi_setup_slave(%d, %d, %d, %d)\n", bus, cs, max_hz, mode);
+
+	if ( bus >= spimctrl_cnt ) {
+		printf("spi_setup_slave: NO SUCH BUS: %d\n", bus);
+		return NULL;
+	}
+
+	slave = malloc(sizeof(struct spi_slave_internal));
+	if (!slave)
+		return NULL;
+
+	slave->dev.bus = bus;
+	slave->dev.cs = cs;
+	slave->priv = &spimctrl_devs[bus];
+	slave->priv->mode = mode;
+	slave->priv->max_hz = max_hz;
+	slave->locked = 0;
+
+	return &slave->dev;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct spi_slave_internal *slv = (void *)slave;
+
+	if ( slv->locked )
+		return -1;
+	slv->locked = 1;
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct spi_slave_internal *slv = (void *)slave;
+
+	slv->locked = 0;
+	return;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+		void *din, unsigned long flags)
+{
+	struct spi_slave_internal *slv = (void *)slave;
+	int i, cnt;
+	unsigned char *out, *in;
+
+	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+		slave->bus, slave->cs, (uint)dout, (uint)din, bitlen);
+
+	if ( (bitlen & 0x7) != 0 ) {
+		printf("spi_xfer: Bitlength of != 8 not supported\n");
+		return -1;
+	}
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* Set Chip Select */
+		spimctrl_cs_activate(slv->priv);
+	}
+
+	out = (unsigned char *)dout;
+	in = (unsigned char *)din;
+	cnt = bitlen / 8;
+	for (i=0; i<cnt; i++){
+		spimctrl_transfer_byte(slv->priv, out, in);
+
+		if ( out )
+			out++;
+		if ( in )
+			in++;
+	}
+
+	if (flags & SPI_XFER_END) {
+		/* End transfer by rising ChipSelect again */
+		spimctrl_cs_deactivate(slv->priv);
+	}
+
+	return 0;
+}
diff --git a/include/grlib/spimctrl.h b/include/grlib/spimctrl.h
new file mode 100644
index 0000000..8329745
--- /dev/null
+++ b/include/grlib/spimctrl.h
@@ -0,0 +1,69 @@
+/* GRLIB SPI Memory controller (SPIMCTRL) definitions
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __GRLIB_SPIMCTRL_H__
+#define __GRLIB_SPIMCTRL_H__
+
+/*** REGISTER LAYOUT ***/
+struct spimctrl_regs {
+	volatile unsigned int conf;		/* 0x00 */
+	volatile unsigned int ctrl;		/* 0x04 */
+	volatile unsigned int stat;		/* 0x08 */
+	volatile unsigned int rx;		/* 0x0C */
+	volatile unsigned int tx;		/* 0x10 */
+};
+
+/*** CONFIGURATION REGISTER 0x00 ***/
+#define SPIMCTRL_CONF_READCMD_BIT	0
+#define SPIMCTRL_CONF_READCMD		0xff
+
+/*** CONTROL REGISTER 0x04 ***/
+#define SPIMCTRL_CTRL_USRC_BIT	0
+#define SPIMCTRL_CTRL_IEN_BIT	1
+#define SPIMCTRL_CTRL_EAS_BIT	2
+#define SPIMCTRL_CTRL_CSN_BIT	3
+#define SPIMCTRL_CTRL_RST_BIT	4
+
+#define SPIMCTRL_CTRL_USRC	(1<<SPIMCTRL_CTRL_USRC_BIT)
+#define SPIMCTRL_CTRL_IEN	(1<<SPIMCTRL_CTRL_IEN_BIT)
+#define SPIMCTRL_CTRL_EAS	(1<<SPIMCTRL_CTRL_EAS_BIT)
+#define SPIMCTRL_CTRL_CSN	(1<<SPIMCTRL_CTRL_CSN_BIT)
+#define SPIMCTRL_CTRL_RST	(1<<SPIMCTRL_CTRL_RST_BIT)
+
+/*** STATUS REGISTER 0x08 ***/
+#define SPIMCTRL_STAT_DONE_BIT	0
+#define SPIMCTRL_STAT_BUSY_BIT	1
+#define SPIMCTRL_STAT_INT_BIT	2
+#define SPIMCTRL_STAT_ERR_BIT	3
+#define SPIMCTRL_STAT_TO_BIT	4
+#define SPIMCTRL_STAT_CD_BIT	5
+
+#define SPIMCTRL_STAT_DONE	(1<<SPIMCTRL_STAT_DONE_BIT)
+#define SPIMCTRL_STAT_BUSY	(1<<SPIMCTRL_STAT_BUSY_BIT)
+#define SPIMCTRL_STAT_INT	(1<<SPIMCTRL_STAT_INT_BIT)
+#define SPIMCTRL_STAT_ERR	(1<<SPIMCTRL_STAT_ERR_BIT)
+#define SPIMCTRL_STAT_TO	(1<<SPIMCTRL_STAT_TO_BIT)
+#define SPIMCTRL_STAT_CD	(1<<SPIMCTRL_STAT_CD_BIT)
+
+#endif
diff --git a/lib_sparc/board.c b/lib_sparc/board.c
index d829af0..3362f39 100644
--- a/lib_sparc/board.c
+++ b/lib_sparc/board.c
@@ -97,6 +97,16 @@ static int init_baudrate(void)
 	return (0);
 }
 
+#if defined(CONFIG_HARD_SPI)
+static int init_func_spi (void)
+{
+        puts ("SPI:   ");
+        spi_init ();
+        puts ("ready\n");
+        return (0);
+}
+#endif
+
 /***********************************************************************/
 
 /*
@@ -304,6 +314,10 @@ void board_init_f(ulong bootflag)
 			CONFIG_SYS_MALLOC_END - CONFIG_SYS_MALLOC_BASE);
 	malloc_bin_reloc();
 
+#if defined(CONFIG_HARD_SPI)
+	init_func_spi();
+#endif
+
 #if !defined(CONFIG_SYS_NO_FLASH)
 	puts("FLASH: ");
 
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 15/17] LEON3: fixed MMU table for systems with larger memory than 128MB.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (12 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 14/17] LEON: added support for GRLIB SPI Memory controller, spi command interface Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 16/17] bootm command: added argument to arch_preboot_os, function may depend on OS type Daniel Hellstrom
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 cpu/leon3/prom.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/cpu/leon3/prom.c b/cpu/leon3/prom.c
index 86376bb..6cd2281 100644
--- a/cpu/leon3/prom.c
+++ b/cpu/leon3/prom.c
@@ -1059,6 +1059,22 @@ void srmmu_init_cpu(unsigned int entry)
 	    ((CONFIG_SYS_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE;
 	psrmmu_tables->pgd_table[0xf7] =
 	    ((CONFIG_SYS_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xf8] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0x8000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xf9] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0x9000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xfa] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xa000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xfb] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xb000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xfc] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xc000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xfd] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xd000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xfe] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xe000000) >> 4) | ACC_SU_ALL | PTE;
+	psrmmu_tables->pgd_table[0xff] =
+	    ((CONFIG_SYS_SDRAM_BASE + 0xf000000) >> 4) | ACC_SU_ALL | PTE;	
 
 	/* convert rom vec pointer to virtual address */
 	kernel_arg_promvec = (struct linux_romvec *)
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 16/17] bootm command: added argument to arch_preboot_os, function may depend on OS type.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (13 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 15/17] LEON3: fixed MMU table for systems with larger memory than 128MB Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 12:16 ` [U-Boot] [PATCH 17/17] SPARC, LEON3: added support for multiprocessing, tested Linux 2.6.21.1 SMP and RTEMS-4.10 AMP Daniel Hellstrom
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 common/cmd_bootm.c     |    8 ++++----
 cpu/mpc85xx/cpu_init.c |    2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 94ddac3..f795857 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -170,11 +170,11 @@ void __arch_lmb_reserve(struct lmb *lmb)
 void arch_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__arch_lmb_reserve")));
 
 /* Allow for arch specific config before we boot */
-void __arch_preboot_os(void)
+void __arch_preboot_os(int os)
 {
 	/* please define platform specific arch_preboot_os() */
 }
-void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
+void arch_preboot_os(int os) __attribute__((weak, alias("__arch_preboot_os")));
 
 #if defined(__ARM__)
   #define IH_INITRD_ARCH IH_ARCH_ARM
@@ -571,7 +571,7 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 			break;
 		case BOOTM_STATE_OS_GO:
 			disable_interrupts();
-			arch_preboot_os();
+			arch_preboot_os(images.os.os);
 			boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
 			break;
 	}
@@ -704,7 +704,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		return 1;
 	}
 
-	arch_preboot_os();
+	arch_preboot_os(images.os.os);
 
 	boot_fn(0, argc, argv, &images);
 
diff --git a/cpu/mpc85xx/cpu_init.c b/cpu/mpc85xx/cpu_init.c
index 0041a60..100f8f4 100644
--- a/cpu/mpc85xx/cpu_init.c
+++ b/cpu/mpc85xx/cpu_init.c
@@ -382,7 +382,7 @@ int cpu_init_r(void)
 
 extern void setup_ivors(void);
 
-void arch_preboot_os(void)
+void arch_preboot_os(int os)
 {
 	u32 msr;
 
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 17/17] SPARC, LEON3: added support for multiprocessing, tested Linux 2.6.21.1 SMP and RTEMS-4.10 AMP.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (14 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 16/17] bootm command: added argument to arch_preboot_os, function may depend on OS type Daniel Hellstrom
@ 2010-01-28 12:16 ` Daniel Hellstrom
  2010-01-28 20:41 ` [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Mike Frysinger
  2010-05-05 21:35 ` Wolfgang Denk
  17 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-01-28 12:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 board/gaisler/gr_cpci_ax2000/u-boot.lds |    7 ++
 board/gaisler/gr_ep2s60/u-boot.lds      |    7 ++
 board/gaisler/gr_xc3s_1500/u-boot.lds   |    7 ++
 board/gaisler/grsim/u-boot.lds          |    7 ++
 cpu/leon3/Makefile                      |    2 +-
 cpu/leon3/cpu.c                         |   10 ++-
 cpu/leon3/cpu_mp.c                      |   80 ++++++++++++++
 cpu/leon3/prom.c                        |   32 +++---
 cpu/leon3/start.S                       |   70 ++++++++++++
 include/asm-sparc/boot_mp.h             |   70 ++++++++++++
 include/configs/gr_cpci_ax2000.h        |   12 ++-
 include/configs/gr_ep2s60.h             |   12 ++-
 include/configs/gr_xc3s_1500.h          |   14 ++-
 include/configs/grsim.h                 |   12 ++-
 lib_sparc/Makefile                      |    2 +-
 lib_sparc/boot_mp.c                     |  177 +++++++++++++++++++++++++++++++
 lib_sparc/bootm.c                       |   57 ++++++++--
 17 files changed, 540 insertions(+), 38 deletions(-)
 create mode 100644 cpu/leon3/cpu_mp.c
 create mode 100644 include/asm-sparc/boot_mp.h
 create mode 100644 lib_sparc/boot_mp.c

diff --git a/board/gaisler/gr_cpci_ax2000/u-boot.lds b/board/gaisler/gr_cpci_ax2000/u-boot.lds
index d5d7842..17a0fc3 100644
--- a/board/gaisler/gr_cpci_ax2000/u-boot.lds
+++ b/board/gaisler/gr_cpci_ax2000/u-boot.lds
@@ -72,6 +72,13 @@ SECTIONS
 		*(.prom.text)
 		. = ALIGN(16);
 		__prom_end = .;
+		/* Align MP section to the same as the MAX size of the MP section */
+		. = ALIGN(512);
+		__mp_start = .;
+		*(.mp.data)
+		*(.mp.text)
+		. = ALIGN(16);
+		__mp_end = .;
 		*(.text)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/board/gaisler/gr_ep2s60/u-boot.lds b/board/gaisler/gr_ep2s60/u-boot.lds
index 99aa0ad..c02a6d2 100644
--- a/board/gaisler/gr_ep2s60/u-boot.lds
+++ b/board/gaisler/gr_ep2s60/u-boot.lds
@@ -72,6 +72,13 @@ SECTIONS
 		*(.prom.text)
 		. = ALIGN(16);
 		__prom_end = .;
+		/* Align MP section to the same as the MAX size of the MP section */
+		. = ALIGN(512);
+		__mp_start = .;
+		*(.mp.data)
+		*(.mp.text)
+		. = ALIGN(16);
+		__mp_end = .;
 		*(.text)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/board/gaisler/gr_xc3s_1500/u-boot.lds b/board/gaisler/gr_xc3s_1500/u-boot.lds
index 3b13190..de7ea6b 100644
--- a/board/gaisler/gr_xc3s_1500/u-boot.lds
+++ b/board/gaisler/gr_xc3s_1500/u-boot.lds
@@ -72,6 +72,13 @@ SECTIONS
 		*(.prom.text)
 		. = ALIGN(16);
 		__prom_end = .;
+		/* Align MP section to the same as the MAX size of the MP section */
+		. = ALIGN(512);
+		__mp_start = .;
+		*(.mp.data)
+		*(.mp.text)
+		. = ALIGN(16);
+		__mp_end = .;
 		*(.text)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/board/gaisler/grsim/u-boot.lds b/board/gaisler/grsim/u-boot.lds
index 0fa6627..ac7dbec 100644
--- a/board/gaisler/grsim/u-boot.lds
+++ b/board/gaisler/grsim/u-boot.lds
@@ -71,6 +71,13 @@ SECTIONS
 		*(.prom.text)
 		. = ALIGN(16);
 		__prom_end = .;
+		/* Align MP section to the same as the MAX size of the MP section */
+		. = ALIGN(512);
+		__mp_start = .;
+		*(.mp.data)
+		*(.mp.text)
+		. = ALIGN(16);
+		__mp_end = .;
 		*(.text)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/cpu/leon3/Makefile b/cpu/leon3/Makefile
index f1bb808..4d36061 100644
--- a/cpu/leon3/Makefile
+++ b/cpu/leon3/Makefile
@@ -28,7 +28,7 @@ LIB	= $(obj)lib$(CPU).a
 START	= start.o
 SOBJS	= ambapp_low.o ambapp_low_c.o memcfg_low.o
 COBJS	= cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o \
-	memcfg.o
+	memcfg.o cpu_mp.o
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/leon3/cpu.c b/cpu/leon3/cpu.c
index 5cc9513..13d3dd7 100644
--- a/cpu/leon3/cpu.c
+++ b/cpu/leon3/cpu.c
@@ -83,8 +83,14 @@ int checkcpu(void)
 
 /* ------------------------------------------------------------------------- */
 
-void cpu_reset(void)
+int cpu_reset(int nr)
 {
+	if ( nr > 0 ) {
+		puts(" CPU[N] RESET NOT SUPPORTED BY ARCHITECTURE (N>0), "
+		     "SYSTEM RESET IS POSSIBLE.");
+		return -1;
+	}
+
 	/* Interrupts off */
 	disable_interrupts();
 
@@ -94,7 +100,7 @@ void cpu_reset(void)
 
 int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
-	cpu_reset();
+	cpu_reset(0);
 
 	return 1;
 
diff --git a/cpu/leon3/cpu_mp.c b/cpu/leon3/cpu_mp.c
new file mode 100644
index 0000000..5cd5a6a
--- /dev/null
+++ b/cpu/leon3/cpu_mp.c
@@ -0,0 +1,80 @@
+/* Interface implementation for cmd_mp.c on multi processor LEON
+ * CPUs
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Gaisler Research, daniel at gaisler.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+
+#ifdef CONFIG_MP
+
+#include <grlib/irqmp.h>
+
+extern int leon_cpu_cnt;
+extern ambapp_dev_irqmp *irqmp;
+
+int cpu_numcores(void)
+{
+	return leon_cpu_cnt;
+}
+
+int cpu_status(int nr)
+{
+	printf("LEON CPUs available: %d\n", leon_cpu_cnt);
+
+	return 0;
+}
+
+int cpu_release(int nr, int argc, char *argv[])
+{
+	unsigned int ep, stack, arg0, arg1;
+
+	/* Get entry point, stack and argument */
+	if ( argc < 2 ) {
+		printf(	" At least 5 arguments must be given.\n"
+			" Argument 4 is entry point\n"
+			" Argument 5 is stack\n"
+			" Argument 6-7 is kernel arg 0 and 1 (OPTIONAL)\n");
+		return -1;
+	}
+	ep = simple_strtoul(argv[0], NULL, 16);
+	stack = simple_strtoul(argv[1], NULL, 16);
+	arg0 = arg1 = 0;
+
+	if ( argc > 2 ) {
+		arg0 = simple_strtoul(argv[2], NULL, 16);
+	}
+	if ( argc > 3 ) {
+		arg1 = simple_strtoul(argv[3], NULL, 16);
+	}
+
+	/* Register CPU start up options into MP table */
+	boot_mp_cpu_setup(nr, ep, stack, (void *)arg0, (void *)arg1);
+
+	/* Release CPU by writing to IRQ controller MP register */
+	irqmp->mstatus = (1<<nr);
+
+	return 0;
+}
+
+#endif
diff --git a/cpu/leon3/prom.c b/cpu/leon3/prom.c
index 6cd2281..2a4fc2d 100644
--- a/cpu/leon3/prom.c
+++ b/cpu/leon3/prom.c
@@ -31,6 +31,7 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/leon.h>
+#include <asm/boot_mp.h>
 #include <ambapp.h>
 #include <grlib/apbuart.h>
 #include <grlib/irqmp.h>
@@ -931,21 +932,9 @@ void leon_prom_init(struct leon_prom_info *pspi)
 	/* Set the pointer to the Console UART in romvec */
 	pspi->reloc_funcs.leon3_apbuart = leon3_apbuart;
 
-	{
-		int j = 1;
-#ifdef CONFIG_SMP
-		ambapp_dev_irqmp *b;
-		b = (ambapp_dev_irqmp *) leon3_getapbbase(VENDOR_GAISLER,
-							  GAISLER_IRQMP);
-		if (b) {
-			j = 1 + ((LEON3_BYPASS_LOAD_PA(&(b->mpstatus))
-				  >> LEON3_IRQMPSTATUS_CPUNR) & 0xf);
-		}
-#endif
 #undef nodes
-		pspi->nodes[2 + j].level = -1;
-		pspi->nodes[2 + j].properties = __va(spi.root_properties + 3);
-	}
+	pspi->nodes[2 + leon_cpu_cnt].level = -1;
+	pspi->nodes[2 + leon_cpu_cnt].properties = __va(spi.root_properties + 3);
 
 	/* Set Ethernet MAC address from environment */
 	if ((addr_str = getenv("ethaddr")) != NULL) {
@@ -1024,7 +1013,7 @@ void prepare_bootargs(char *bootargs)
 	}
 }
 
-void srmmu_init_cpu(unsigned int entry)
+void srmmu_init(unsigned int entry)
 {
 	sparc_srmmu_setup *psrmmu_tables = (void *)
 	    ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) +
@@ -1079,6 +1068,19 @@ void srmmu_init_cpu(unsigned int entry)
 	/* convert rom vec pointer to virtual address */
 	kernel_arg_promvec = (struct linux_romvec *)
 	    (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000);
+}
+
+#ifdef CONFIG_MP
+/* This function must be located in the MP or PROM part of the application because
+ * it will be called from CPU1, CPU2 ...  after CPU0 has made it into the kernel 
+ * and started the other CPUs
+ */
+void MP_TEXT boot_mp_linux_cpu_preinit(int cpu)
+#else
+void boot_mp_linux_cpu_preinit(int cpu)
+#endif
+{
+	sparc_srmmu_setup *psrmmu_tables = (void *)CONFIG_SYS_PROM_OFFSET;
 
 	/* Set Context pointer to point to context table
 	 * 256 contexts supported.
diff --git a/cpu/leon3/start.S b/cpu/leon3/start.S
index d9faa86..1f30150 100644
--- a/cpu/leon3/start.S
+++ b/cpu/leon3/start.S
@@ -27,6 +27,7 @@
 #include <asm/psr.h>
 #include <asm/stack.h>
 #include <asm/leon.h>
+#include <asm/boot_mp.h>
 #include <timestamp.h>
 #include <version.h>
 #include <ambapp.h>
@@ -258,6 +259,20 @@ wininit:
 	set	WIM_INIT, %g3
 	mov	%g3, %wim
 
+#ifdef CONFIG_MP
+/* In a multi CPU system (and the slave CPUs have been started) the slaves
+ * have a special boot up sequence. It is expected that CPU0 has already run
+ * u-boot and it has loaded an OS which now have activated one or more slave 
+ * CPUs.
+ */
+multi_cpu_detect:
+	rd	%asr17, %g3
+	srl	%g3, 28, %g3
+	cmp	%g3, %g0
+	bne	slave_cpu_init
+	 nop
+#endif
+
 stackp:
 	set	CONFIG_SYS_INIT_SP_OFFSET, %fp
 	andn	%fp, 0x0f, %fp
@@ -386,6 +401,23 @@ prom_relocate_loop:
 	bne	prom_relocate_loop
 	inc	16,%g4
 
+#ifdef CONFIG_MP
+mp_relocate:
+	set	__mp_start, %g2
+	set	__mp_end, %g3
+	set	CONFIG_SYS_MP_OFFSET, %g4
+
+mp_relocate_loop:
+	ldd	[%g2],%l0
+	ldd	[%g2+8],%l2
+	std	%l0,[%g4]
+	std	%l2,[%g4+8]
+	inc	16,%g2
+	subcc	%g3,%g2,%g0
+	bne	mp_relocate_loop
+	inc	16,%g4
+#endif
+
 /* Trap table has been moved, lets tell CPU about
  * the new trap table address
  */
@@ -651,3 +683,41 @@ _reset_reloc:
 	set	start, %l0
 	call	%l0
 	nop
+
+#ifdef CONFIG_MP
+/* Slave CPUs reach here */
+slave_cpu_init:
+
+	/* Get Index into cpu slave struct */
+	sll	%g3, 4, %i0
+
+	set	(CONFIG_SYS_MP_OFFSET+0x4), %o1	/* cpu_table is mp_data+0x4 */
+	add	%i0, %o1, %i0
+
+	/* Setup Stack Pointer from config */
+	ld	[%i0 + BOOT_MP_CPU_STACK], %fp
+	andn	%fp, 0x0f, %fp
+	sub	%fp, 64, %sp
+
+	/* Call OS-dependent CPU init routine */
+	set	CONFIG_SYS_MP_OFFSET, %o1	/* cpu_table is mp_data+0x0 */
+	ld	[%o1], %o1
+	cmp	%o1, 0
+	beq	slave_cpu_boot_kernel
+	 nop
+	call	%o1
+	 clr	%o0
+
+	/* Call Kernel */
+slave_cpu_boot_kernel:
+	ld	[%i0 + BOOT_MP_CPU_ARG0], %o0	/* ARG0 */
+	ld	[%i0 + BOOT_MP_CPU_ARG1], %o1	/* ARG1 */
+	ld	[%i0 + BOOT_MP_CPU_EP], %o3	/* ENTRY POINT */
+	call	%o3
+	 clr	%o2
+
+dead_slave:
+	/* Kernel Failed or no support for MP */
+	ta 0x1
+	 nop
+#endif
diff --git a/include/asm-sparc/boot_mp.h b/include/asm-sparc/boot_mp.h
new file mode 100644
index 0000000..e033b9c
--- /dev/null
+++ b/include/asm-sparc/boot_mp.h
@@ -0,0 +1,70 @@
+/* Multiprocessor boot setup functions.
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Gaisler Research, daniel at gaisler.com.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_SPARC_BOOT_MP_H__
+#define __ASM_SPARC_BOOT_MP_H__
+
+#define MP_TEXT __attribute__ ((__section__ (".mp.text")))
+#define MP_DATA __attribute__ ((__section__ (".mp.data")))
+
+#define BOOT_MP_CPU_EP 0x00
+#define BOOT_MP_CPU_STACK 0x04
+#define BOOT_MP_CPU_ARG0 0x08
+#define BOOT_MP_CPU_ARG1 0x0C
+
+#ifndef __ASSEMBLER__
+
+/* Allow for arch specific CPU initialization before RTEMS boot */
+extern void boot_mp_rtems_cpu_preinit(int cpu);
+
+/* Allow for arch specific CPU initialization before VxWorks boot */
+extern void boot_mp_vxworks_cpu_preinit(int cpu);
+
+/* Allow for arch specific CPU initialization before Linux boot */
+extern void boot_mp_linux_cpu_preinit(int cpu);
+
+struct boot_mp_cpu {
+	unsigned int entry_point;
+	unsigned int stack;
+	void *arg0;
+	void *arg1;
+};
+
+/* All CPU entry points and stacks */
+extern struct boot_mp_cpu boot_mp_cpu_table[];
+
+extern void boot_mp_os_setup(int os);
+
+extern void boot_mp_cpu_setup(
+	int cpu,
+	unsigned int entry_point,
+	unsigned int stack,
+	void *arg0,
+	void *arg1
+	);
+
+/* Init a CPU before entering the kernel */
+extern void boot_mp_cpu_preinit(int cpu);
+
+#endif
+
+#endif
diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h
index b9d45dd..a6d669d 100644
--- a/include/configs/gr_cpci_ax2000.h
+++ b/include/configs/gr_cpci_ax2000.h
@@ -264,8 +264,16 @@
 #define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_GBL_DATA_SIZE)
-#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_PROM_SIZE)
+#ifdef CONFIG_MP
+#define CONFIG_SYS_MP_SIZE		512
+#define CONFIG_SYS_MP_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_MP_SIZE)
+#else
+#define CONFIG_SYS_MP_SIZE		0
+#define CONFIG_SYS_MP_OFFSET		CONFIG_SYS_GBL_DATA_OFFSET
+#endif
+
+#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_MP_SIZE-CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_MP_OFFSET-CONFIG_SYS_PROM_SIZE)
 
 #define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_PROM_OFFSET-32)
 #define CONFIG_SYS_STACK_SIZE		(0x10000-32)
diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h
index 6edb92c..10afca2 100644
--- a/include/configs/gr_ep2s60.h
+++ b/include/configs/gr_ep2s60.h
@@ -232,8 +232,16 @@
 #define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_SDRAM_END - CONFIG_SYS_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_GBL_DATA_SIZE)
-#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_PROM_SIZE)
+#ifdef CONFIG_MP
+#define CONFIG_SYS_MP_SIZE		512
+#define CONFIG_SYS_MP_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_MP_SIZE)
+#else
+#define CONFIG_SYS_MP_SIZE		0
+#define CONFIG_SYS_MP_OFFSET		CONFIG_SYS_GBL_DATA_OFFSET
+#endif
+
+#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_MP_SIZE-CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_MP_OFFSET-CONFIG_SYS_PROM_SIZE)
 
 #define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_PROM_OFFSET-32)
 #define CONFIG_SYS_STACK_SIZE		(0x10000-32)
diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h
index 1f9dd4a..b57640a 100644
--- a/include/configs/gr_xc3s_1500.h
+++ b/include/configs/gr_xc3s_1500.h
@@ -54,6 +54,8 @@
 #define CONFIG_DOS_PARTITION
 #define CONFIG_MAC_PARTITION
 #define CONFIG_ISO_PARTITION
+#define CONFIG_MP
+#define CONFIG_MP_MAX_CPUS 4
 
 /*
  * Supported commands
@@ -209,8 +211,16 @@
 #define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_GBL_DATA_SIZE)
-#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_PROM_SIZE)
+#ifdef CONFIG_MP
+#define CONFIG_SYS_MP_SIZE		512
+#define CONFIG_SYS_MP_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_MP_SIZE)
+#else
+#define CONFIG_SYS_MP_SIZE		0
+#define CONFIG_SYS_MP_OFFSET		CONFIG_SYS_GBL_DATA_OFFSET
+#endif
+
+#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_MP_SIZE-CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_MP_OFFSET-CONFIG_SYS_PROM_SIZE)
 
 #define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_PROM_OFFSET-32)
 #define CONFIG_SYS_STACK_SIZE		(0x10000-32)
diff --git a/include/configs/grsim.h b/include/configs/grsim.h
index f815672..9e177e6 100644
--- a/include/configs/grsim.h
+++ b/include/configs/grsim.h
@@ -234,8 +234,16 @@
 #define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_GBL_DATA_SIZE)
-#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_PROM_SIZE)
+#ifdef CONFIG_MP
+#define CONFIG_SYS_MP_SIZE		512
+#define CONFIG_SYS_MP_OFFSET		(CONFIG_SYS_GBL_DATA_OFFSET-CONFIG_SYS_MP_SIZE)
+#else
+#define CONFIG_SYS_MP_SIZE		0
+#define CONFIG_SYS_MP_OFFSET		CONFIG_SYS_GBL_DATA_OFFSET
+#endif
+
+#define CONFIG_SYS_PROM_SIZE		(8192-CONFIG_SYS_MP_SIZE-CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_PROM_OFFSET		(CONFIG_SYS_MP_OFFSET-CONFIG_SYS_PROM_SIZE)
 
 #define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_PROM_OFFSET-32)
 #define CONFIG_SYS_STACK_SIZE		(0x10000-32)
diff --git a/lib_sparc/Makefile b/lib_sparc/Makefile
index 040ca10..3860fdc 100644
--- a/lib_sparc/Makefile
+++ b/lib_sparc/Makefile
@@ -27,7 +27,7 @@ LIB	= $(obj)lib$(ARCH).a
 
 SOBJS	=
 
-COBJS	= board.o cache.o interrupts.o time.o bootm.o
+COBJS	= board.o cache.o interrupts.o time.o bootm.o boot_mp.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/lib_sparc/boot_mp.c b/lib_sparc/boot_mp.c
new file mode 100644
index 0000000..3154fd1
--- /dev/null
+++ b/lib_sparc/boot_mp.c
@@ -0,0 +1,177 @@
+/* SPARC Multi-Processor initialization
+ *
+ * (C) Copyright 2010
+ * Daniel Hellstrom, Aeroflex Gaisler, daniel at gaisler.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/boot_mp.h>
+#include <config.h>
+
+#ifdef CONFIG_MP
+
+#ifndef CONFIG_MP_MAX_CPUS
+ #error CONFIG_MP_MAX_CPUS must be defined
+#endif
+
+typedef int (*cpu_preinit_func) (int cpu);
+
+/* Structure of all MP DATA section */
+struct boot_mp_data {
+	/* Function called for each CPU before entering kernel */
+	cpu_preinit_func func;
+
+	/* All CPU entry points and so on */
+	struct boot_mp_cpu cpu_table[CONFIG_MP_MAX_CPUS];
+
+	/* OS to boot */
+	int os;
+};
+
+struct boot_mp_data MP_DATA mp_data;
+
+/* Allow for specific RTEMS CPU initialization before RTEMS AMP boot */
+void MP_TEXT __boot_mp_rtems_cpu_preinit(int cpu)
+{
+
+}
+void boot_mp_rtems_cpu_preinit(int cpu)
+	__attribute__((weak, alias("__boot_mp_rtems_cpu_preinit")));
+
+/* Allow for specific VxWorks CPU initialization before slave CPUs boot */
+void MP_TEXT __boot_mp_vxworks_cpu_preinit(int cpu)
+{
+
+}
+void boot_mp_vxworks_cpu_preinit(int cpu)
+	__attribute__((weak, alias("__boot_mp_vxworks_cpu_preinit")));
+
+/* Allow for specific Linux CPU initialization before slave CPUs boot */
+void MP_TEXT __boot_mp_linux_cpu_preinit(int cpu)
+{
+
+}
+void boot_mp_linux_cpu_preinit(int cpu)
+	__attribute__((weak, alias("__boot_mp_linux_cpu_preinit")));
+
+static cpu_preinit_func os_cpu_preinit[] =
+{
+	[IH_OS_LINUX] = boot_mp_linux_cpu_preinit,
+	[IH_OS_RTEMS] = boot_mp_rtems_cpu_preinit,
+	[IH_OS_VXWORKS] = boot_mp_vxworks_cpu_preinit,
+};
+
+void boot_mp_os_setup(int os)
+{
+	struct boot_mp_data *mpd = (void *)CONFIG_SYS_MP_OFFSET;
+	unsigned int func;
+
+	mpd->os = os;
+
+	func = (unsigned int)os_cpu_preinit[os];
+	if ( func == 0 ) {
+		/* We assume that the OS booting does not support MP and will 
+		 * therefore not start the other CPUs.
+		 */
+		mpd->func = 0;
+	} else {
+		mpd->func = CONFIG_SYS_MP_OFFSET + (func & (CONFIG_SYS_MP_SIZE-1));
+	}
+
+	debug("boot_mp_os_setup:  0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+		os,
+		os_cpu_preinit,
+		&os_cpu_preinit[os],
+		(unsigned int)os_cpu_preinit[os],
+		CONFIG_SYS_MP_SIZE,
+		((unsigned int)os_cpu_preinit[os] & (CONFIG_SYS_MP_SIZE-1))
+		);
+}
+
+void boot_mp_cpu_setup(
+	int cpu,
+	unsigned int entry_point,
+	unsigned int stack,
+	void *arg0,
+	void *arg1
+	)
+{
+	struct boot_mp_data *mpd = (void *)CONFIG_SYS_MP_OFFSET;
+
+	if ( cpu >= CONFIG_MP_MAX_CPUS )
+		return;
+
+	mpd->cpu_table[cpu].entry_point = entry_point;
+	mpd->cpu_table[cpu].stack = stack;
+	mpd->cpu_table[cpu].arg0 = arg0;
+	mpd->cpu_table[cpu].arg1 = arg1;
+
+	debug("boot_mp_cpu_setup(%d): ep=0x%x stack=0x%x, arg=[0x%x,0x%x]\n",
+		cpu, entry_point, stack, arg0, arg1);
+}
+
+/* In a RTEMS AMP system all CPUs have different entry points and stacks,
+ * the addresses are taken from the environment variables:
+ * cpu0_entry and cpu0_stack
+ */
+void boot_mp_rtems_setup(void)
+{
+	char *str;
+	char env_str[16];
+	int cpu;
+	unsigned int entry, stack;
+
+	for(cpu=0; cpu<CONFIG_MP_MAX_CPUS; cpu++) {
+
+		entry = 0;
+		stack = 0;
+
+		strcpy(env_str, "cpuX_entry");
+		env_str[3] = '0' + cpu;
+		if ( (str = getenv(env_str)) != NULL ) {
+			entry = simple_strtoul(str, NULL, 16);
+		}
+
+		strcpy(env_str, "cpuX_stack");
+		env_str[3] = '0' + cpu;
+		if ( (str = getenv(env_str)) != NULL ) {
+			stack = simple_strtoul(str, NULL, 16);
+		}
+
+		boot_mp_cpu_setup(
+			cpu,
+			(unsigned int)entry,
+			(unsigned int)stack,
+			NULL,
+			NULL);
+	}
+}
+
+/* Prepare boot, called from bootm */
+void arch_preboot_os(int os)
+{
+	boot_mp_os_setup(os);
+
+	if ( os == IH_OS_RTEMS )
+		boot_mp_rtems_setup();
+}
+
+#endif
diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c
index f517325..428ad97 100644
--- a/lib_sparc/bootm.c
+++ b/lib_sparc/bootm.c
@@ -28,11 +28,12 @@
 #include <asm/prom.h>
 #include <asm/cache.h>
 #include <image.h>
+#include <asm-sparc/boot_mp.h>
 
 #define PRINT_KERNEL_HEADER
 
 extern image_header_t header;
-extern void srmmu_init_cpu(unsigned int entry);
+extern void srmmu_init(unsigned int entry);
 extern void prepare_bootargs(char *bootargs);
 
 /* sparc kernel argument (the ROM vector) */
@@ -43,7 +44,8 @@ struct linux_romvec *kernel_arg_promvec;
 #define RAMDISK_IMAGE_START_MASK	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
-struct __attribute__ ((packed)) {
+/* Linux Single CPU Header */
+struct linux_up_hdr {
 	char traptable[PAGE_SIZE];
 	char swapper_pg_dir[PAGE_SIZE];
 	char pg0[PAGE_SIZE];
@@ -73,7 +75,13 @@ struct __attribute__ ((packed)) {
 			unsigned int end;
 		} ver_0203;
 	} hdr_input;
-} *linux_hdr;
+} __attribute__ ((packed)) ;
+
+/* Linux SMP Header */
+struct linux_smp_hdr {
+	char traptable[3][PAGE_SIZE];
+	struct linux_up_hdr single_hdr;
+} __attribute__ ((packed));
 
 /* temporary initrd image holder */
 image_header_t ihdr;
@@ -98,23 +106,34 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t * images)
 	void (*kernel) (struct linux_romvec *, void *);
 	struct lmb *lmb = &images->lmb;
 	int ret;
+	int i;
+	struct linux_up_hdr *linux_hdr;
+	struct linux_smp_hdr *linux_smp_hdr;
 
 	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
 		return 1;
 
-	/* Get virtual address of kernel start */
-	linux_hdr = (void *)images->os.load;
-
-	/* */
+	/* Kernel Entry Point */
 	kernel = (void (*)(struct linux_romvec *, void *))images->ep;
 
+	/* Get virtual address of kernel start */
+	linux_hdr = (struct linux_up_hdr *)images->os.load;
+
 	/* check for a SPARC kernel */
 	if ((linux_hdr->hdr[0] != 'H') ||
 	    (linux_hdr->hdr[1] != 'd') ||
 	    (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
-		puts("Error reading header of SPARC Linux kernel, aborting\n");
-		goto error;
+		/* Not a valid Linux Header, check if Linux SMP header */
+		linux_smp_hdr = (struct linux_smp_hdr *)images->os.load;
+		linux_hdr = (struct linux_up_hdr *)&linux_smp_hdr->single_hdr;
+		if ((linux_hdr->hdr[0] != 'H') ||
+		    (linux_hdr->hdr[1] != 'd') ||
+		    (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
+			puts("Error reading header of SPARC Linux kernel, aborting\n");
+			goto error;
+   		}
 	}
+
 #ifdef PRINT_KERNEL_HEADER
 	printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
 	       linux_hdr->linuxver_major,
@@ -164,8 +183,24 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t * images)
 	bootargs = getenv("bootargs");
 	prepare_bootargs(bootargs);
 
-	/* turn on mmu & setup context table & page table for process 0 (kernel) */
-	srmmu_init_cpu((unsigned int)kernel);
+	/* Init MMU table of SRMMU and more */
+	srmmu_init((unsigned int)kernel);
+
+#ifdef CONFIG_MP
+	for(i=0; i<CONFIG_MP_MAX_CPUS; i++) {
+		boot_mp_cpu_setup(
+			i,
+			(unsigned int)kernel,
+			(unsigned int)CONFIG_SYS_INIT_SP_OFFSET,
+			kernel_arg_promvec,
+			NULL);
+	}
+#endif
+
+	/* turn on mmu & setup context table & page table for process 0 (kernel).
+	 * This function is later called by each CPU in a multiprocessor system.
+	 */	
+	boot_mp_linux_cpu_preinit(0);
 
 	/* Enter SPARC Linux kernel
 	 * From now on the only code in u-boot that will be
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (15 preceding siblings ...)
  2010-01-28 12:16 ` [U-Boot] [PATCH 17/17] SPARC, LEON3: added support for multiprocessing, tested Linux 2.6.21.1 SMP and RTEMS-4.10 AMP Daniel Hellstrom
@ 2010-01-28 20:41 ` Mike Frysinger
  2010-02-01 17:08   ` Daniel Hellstrom
  2010-05-05 21:35 ` Wolfgang Denk
  17 siblings, 1 reply; 24+ messages in thread
From: Mike Frysinger @ 2010-01-28 20:41 UTC (permalink / raw)
  To: u-boot

On Thursday 28 January 2010 07:16:20 Daniel Hellstrom wrote:
> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
> ---
>  include/asm-sparc/unaligned.h |   17 +++++++++++++++++
>  1 files changed, 17 insertions(+), 0 deletions(-)
>  create mode 100644 include/asm-sparc/unaligned.h
> 
> diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
> new file mode 100644
> index 0000000..4e604c1
> --- /dev/null
> +++ b/include/asm-sparc/unaligned.h
> @@ -0,0 +1,17 @@
> +#ifndef _ASM_SPARC_UNALIGNED_H
> +#define _ASM_SPARC_UNALIGNED_H
> +
> +#ifdef __KERNEL__
> +
> +/*
> + * The SPARC can not do unaligned accesses, it must be split into multiple
> + * byte accesses. The SPARC is in big endian mode.
> + */
> +#include <linux/unaligned/be_byteshift.h>
> +#include <linux/unaligned/generic.h>
> +
> +#define get_unaligned	__get_unaligned_be
> +#define put_unaligned	__put_unaligned_be
> +
> +#endif	/* __KERNEL__ */
> +#endif	/* _ASM_SPARC_UNALIGNED_H */

there is a proposed asm-generic/unaligned.h on the mailing list which i think 
you could use.  you'd just need:
#include <asm-generic/unaligned.h>
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100128/329f0c76/attachment.pgp 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-01-28 20:41 ` [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Mike Frysinger
@ 2010-02-01 17:08   ` Daniel Hellstrom
  2010-03-16 20:44     ` Mike Frysinger
  0 siblings, 1 reply; 24+ messages in thread
From: Daniel Hellstrom @ 2010-02-01 17:08 UTC (permalink / raw)
  To: u-boot


Mike Frysinger wrote:

>On Thursday 28 January 2010 07:16:20 Daniel Hellstrom wrote:
>  
>
>>Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>>---
>> include/asm-sparc/unaligned.h |   17 +++++++++++++++++
>> 1 files changed, 17 insertions(+), 0 deletions(-)
>> create mode 100644 include/asm-sparc/unaligned.h
>>
>>diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
>>new file mode 100644
>>index 0000000..4e604c1
>>--- /dev/null
>>+++ b/include/asm-sparc/unaligned.h
>>@@ -0,0 +1,17 @@
>>+#ifndef _ASM_SPARC_UNALIGNED_H
>>+#define _ASM_SPARC_UNALIGNED_H
>>+
>>+#ifdef __KERNEL__
>>+
>>+/*
>>+ * The SPARC can not do unaligned accesses, it must be split into multiple
>>+ * byte accesses. The SPARC is in big endian mode.
>>+ */
>>+#include <linux/unaligned/be_byteshift.h>
>>+#include <linux/unaligned/generic.h>
>>+
>>+#define get_unaligned	__get_unaligned_be
>>+#define put_unaligned	__put_unaligned_be
>>+
>>+#endif	/* __KERNEL__ */
>>+#endif	/* _ASM_SPARC_UNALIGNED_H */
>>    
>>
>
>there is a proposed asm-generic/unaligned.h on the mailing list which i think 
>you could use.  you'd just need:
>#include <asm-generic/unaligned.h>
>-mike
>  
>
Thank you for your comment, I will update this patch.

Daniel

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-02-01 17:08   ` Daniel Hellstrom
@ 2010-03-16 20:44     ` Mike Frysinger
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Frysinger @ 2010-03-16 20:44 UTC (permalink / raw)
  To: u-boot

On Monday 01 February 2010 12:08:51 Daniel Hellstrom wrote:
> Mike Frysinger wrote:
> >there is a proposed asm-generic/unaligned.h on the mailing list which i
> >think you could use.  you'd just need:
> >#include <asm-generic/unaligned.h>
> 
> Thank you for your comment, I will update this patch.

the generic unaligned.h has been merged if you want to post your one-line 
patch now ...
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100316/e8073a90/attachment.pgp 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
                   ` (16 preceding siblings ...)
  2010-01-28 20:41 ` [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Mike Frysinger
@ 2010-05-05 21:35 ` Wolfgang Denk
  2010-05-06  6:37   ` Daniel Hellstrom
  17 siblings, 1 reply; 24+ messages in thread
From: Wolfgang Denk @ 2010-05-05 21:35 UTC (permalink / raw)
  To: u-boot

Dear Daniel Hellstrom,

In message <1264680996-13804-1-git-send-email-daniel@gaisler.com> you wrote:
> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
> ---
>  include/asm-sparc/unaligned.h |   17 +++++++++++++++++
>  1 files changed, 17 insertions(+), 0 deletions(-)
>  create mode 100644 include/asm-sparc/unaligned.h

This whole patch series has been out there for many months, but I'm
still waiting for a pull request from you.

Do you have any such plans?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Sorry, but my karma just ran over your dogma.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-05-05 21:35 ` Wolfgang Denk
@ 2010-05-06  6:37   ` Daniel Hellstrom
  2010-05-06 10:57     ` Wolfgang Denk
  0 siblings, 1 reply; 24+ messages in thread
From: Daniel Hellstrom @ 2010-05-06  6:37 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang,

I had some minor remarks on patch 1 and 2 as I recall, and a minor 
change on another patch I discovered myself. Unfortunately I have been 
very busy, I am really sorry for that. I will try to pull my self 
together and finish them in the weekend.

Do I have to repost the patches, now that they are so delayed?

Thank you for your interest, that really helps,
Daniel Hellstrom


Wolfgang Denk wrote:

>Dear Daniel Hellstrom,
>
>In message <1264680996-13804-1-git-send-email-daniel@gaisler.com> you wrote:
>  
>
>>Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>>---
>> include/asm-sparc/unaligned.h |   17 +++++++++++++++++
>> 1 files changed, 17 insertions(+), 0 deletions(-)
>> create mode 100644 include/asm-sparc/unaligned.h
>>    
>>
>
>This whole patch series has been out there for many months, but I'm
>still waiting for a pull request from you.
>
>Do you have any such plans?
>
>Best regards,
>
>Wolfgang Denk
>
>  
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.
  2010-05-06  6:37   ` Daniel Hellstrom
@ 2010-05-06 10:57     ` Wolfgang Denk
  0 siblings, 0 replies; 24+ messages in thread
From: Wolfgang Denk @ 2010-05-06 10:57 UTC (permalink / raw)
  To: u-boot

Dear Daniel Hellstrom,

In message <4BE263AD.7020006@gaisler.com> you wrote:
> 
> I had some minor remarks on patch 1 and 2 as I recall, and a minor 
> change on another patch I discovered myself. Unfortunately I have been 
> very busy, I am really sorry for that. I will try to pull my self 
> together and finish them in the weekend.
> 
> Do I have to repost the patches, now that they are so delayed?

You will probably have to rebase these anyway, so please also repost.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"A fractal is by definition a set for which the Hausdorff Besicovitch
dimension strictly exceeds the topological dimension."
- Mandelbrot, _The Fractal Geometry of Nature_

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine.
  2010-05-18 14:48 [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
@ 2010-05-18 14:48 ` Daniel Hellstrom
  0 siblings, 0 replies; 24+ messages in thread
From: Daniel Hellstrom @ 2010-05-18 14:48 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 arch/sparc/lib/board.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 11eea60..d829af0 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -65,6 +65,7 @@ extern void timer_interrupt_init(void);
 extern void malloc_bin_reloc(void);
 extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
 extern int prom_init(void);
+extern void cpu_late_init(void);
 
 #if defined(CONFIG__CMD_DOC)
 void doc_init(void);
@@ -353,6 +354,10 @@ void board_init_f(ulong bootflag)
 	/* relocate environment function pointers etc. */
 	env_relocate();
 
+#if defined(CONFIG_CPU_LATE_INIT)
+	cpu_late_init();
+#endif
+
 #if defined(CONFIG_BOARD_LATE_INIT)
 	board_late_init();
 #endif
-- 
1.5.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2010-05-18 14:48 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-28 12:16 [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 03/17] GRETH: Added extra RESET, this is needed if GRETH was stopped during an ethernet frame reception Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 04/17] LEON3: reimplemented AMBA Plug&Play scanning routines Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 05/17] LEON3: added memory controller initialization using the new AMBA PnP routines Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 06/17] LEON3: Moved GRLIB core header files to common include/grlib directory Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 07/17] LEON3: serial baud rate register support multiple buses with different frequency Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 08/17] SPARC: added function that checks if IRQ is on or off Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 09/17] LEON3: added busy wait function, made wait_ms() work when IRQ is disabled Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 10/17] LEON3: added CPU count and frequency detection Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 11/17] SPARC: removed USB stop from linux bootm, arch-independent bootm stop USB Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 13/17] LEON3: Added GRETH EDCL debug link IP address initialization Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 14/17] LEON: added support for GRLIB SPI Memory controller, spi command interface Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 15/17] LEON3: fixed MMU table for systems with larger memory than 128MB Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 16/17] bootm command: added argument to arch_preboot_os, function may depend on OS type Daniel Hellstrom
2010-01-28 12:16 ` [U-Boot] [PATCH 17/17] SPARC, LEON3: added support for multiprocessing, tested Linux 2.6.21.1 SMP and RTEMS-4.10 AMP Daniel Hellstrom
2010-01-28 20:41 ` [U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander Mike Frysinger
2010-02-01 17:08   ` Daniel Hellstrom
2010-03-16 20:44     ` Mike Frysinger
2010-05-05 21:35 ` Wolfgang Denk
2010-05-06  6:37   ` Daniel Hellstrom
2010-05-06 10:57     ` Wolfgang Denk
2010-05-18 14:48 [U-Boot] [PATCH 02/17] GRETH: Added support for selecting PHY address from config, PHY address was always set to zero before Daniel Hellstrom
2010-05-18 14:48 ` [U-Boot] [PATCH 12/17] SPARC: added optional cpu_late_init routine Daniel Hellstrom

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.