[U-Boot] [PATCH 01/17] SPARC: added unaligned definitions, patch supplied by Magnus Sjalander.

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 */

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(®s->mdio) & GRETH_MII_BUSY) { }
- GRETH_REGSAVE(®s->mdio, (0 << 11) | ((addr & 0x1F) << 6) | 2); + GRETH_REGSAVE(®s->mdio, ((phyaddr & 0x1F) << 11) | ((regaddr & 0x1F) << 6) | 2);
while (GRETH_REGLOAD(®s->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(®s->mdio) & GRETH_MII_BUSY) { }
GRETH_REGSAVE(®s->mdio, - ((data & 0xFFFF) << 16) | (0 << 11) | ((addr & 0x1F) << 6) - | 1); + ((data & 0xFFFF) << 16) | ((phyaddr & 0x1F) << 11) | + ((regaddr & 0x1F) << 6) | 1);
while (GRETH_REGLOAD(®s->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(®s->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(®s->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; }

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(®s->control, (GRETH_RESET | (greth->gb << 8) | + (greth->sp << 7) | (greth->fd << 4))); + + /* Wait for Reset to complete */ + while ( GRETH_REGLOAD(®s->control) & GRETH_RESET) ; + + GRETH_REGSAVE(®s->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;

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@gaisler.com + * (C) Copyright 2010 + * Daniel Hellstrom, Aeroflex Gaisler, daniel@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@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@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@gaisler.com. + * (C) Copyright 2009 + * Daniel Hellstrom, Aeroflex Gaisler, daniel@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

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@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@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@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)

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@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@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@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

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;

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;

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

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

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. */

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

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@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

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@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: ");

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 *)

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;

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@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@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@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

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

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

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

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

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

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
participants (3)
-
Daniel Hellstrom
-
Mike Frysinger
-
Wolfgang Denk