From 6aa9195daecf18f682a825213a08d28224644b93 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 10 Sep 2010 16:29:37 +0200 Subject: [PATCH 1/3] ppc4xx: Fix CATcenter build Signed-off-by: Stefan Roese --- include/configs/CATcenter.h | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/include/configs/CATcenter.h b/include/configs/CATcenter.h index 229a5138e5..002435ec11 100644 --- a/include/configs/CATcenter.h +++ b/include/configs/CATcenter.h @@ -105,6 +105,7 @@ #define CONFIG_SYS_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ +#define CONFIG_PPC4xx_EMAC #undef CONFIG_EXT_PHY #define CONFIG_NET_MULTI 1 @@ -398,6 +399,7 @@ * I2C EEPROM (CAT24WC16) for environment */ #define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CONFIG_PPC4XX_I2C /* use PPC4xx driver */ #define CONFIG_SYS_I2C_SPEED 400000 /* I2C speed and slave address */ #define CONFIG_SYS_I2C_SLAVE 0x7F @@ -410,16 +412,6 @@ /* last 4 bits of the address */ #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ -/*----------------------------------------------------------------------- - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 /* For AMCC 405 CPUs, older 405 ppc's */ - /* have only 8kB, 16kB is save here */ -#define CONFIG_SYS_CACHELINE_SIZE 32 /* ... */ -#if defined(CONFIG_CMD_KGDB) -#define CONFIG_SYS_CACHELINE_SHIFT 5 /* log base 2 of the above value */ -#endif - /* * Init Memory Controller: * @@ -570,17 +562,6 @@ #define DIMM_READ_ADDR 0xAB #define DIMM_WRITE_ADDR 0xAA -#define CPC0_PLLMR0 (CNTRL_DCR_BASE+0x0) /* PLL mode 0 register */ -#define CPC0_BOOT (CNTRL_DCR_BASE+0x1) /* Chip Clock Status register */ -#define CPC0_CR1 (CNTRL_DCR_BASE+0x2) /* Chip Control 1 register */ -#define CPC0_EPRCSR (CNTRL_DCR_BASE+0x3) /* EMAC PHY Rcv Clk Src register */ -#define CPC0_PLLMR1 (CNTRL_DCR_BASE+0x4) /* PLL mode 1 register */ -#define CPC0_UCR (CNTRL_DCR_BASE+0x5) /* UART Control register */ -#define CPC0_SRR (CNTRL_DCR_BASE+0x6) /* Soft Reset register */ -#define CPC0_JTAGID (CNTRL_DCR_BASE+0x7) /* JTAG ID register */ -#define CPC0_SPARE (CNTRL_DCR_BASE+0x8) /* Spare DCR */ -#define CPC0_PCI (CNTRL_DCR_BASE+0x9) /* PCI Control register */ - /* Defines for CPC0_PLLMR1 Register fields */ #define PLL_ACTIVE 0x80000000 #define CPC0_PLLMR1_SSCS 0x80000000 From ab25e880ca9d508b7a807aa969105af32c3e6e51 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 14 Sep 2010 09:38:18 +0200 Subject: [PATCH 2/3] ppc4xx: POST UART: Use in/out_8() io-accessor functions This patch fixes a problem in the PPC4xx POST UART driver. This driver incorrectly used the in/out8() io-accessor functions. This could lead to problems since these functions don't guarantee execution ordering. This patch now replaces these functions with the correct ones. Additionally the driver is converted to using the NS16550 struct instead of macros for the register offsets. And some common code is factored out for better maintainability. Signed-off-by: Stefan Roese --- include/ppc4xx.h | 10 ++++ post/cpu/ppc4xx/uart.c | 105 ++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 64 deletions(-) diff --git a/include/ppc4xx.h b/include/ppc4xx.h index ee30a4ca3d..5238d04aa7 100644 --- a/include/ppc4xx.h +++ b/include/ppc4xx.h @@ -99,6 +99,16 @@ #endif /* 440EP/EPX 440GR/GRX 440SP/SPE 460EX/GT/SX 405EX*/ +/* + * Define ns16550 register offset for all PPC4xx SoC's. Some + * mostly FPGA based PPC4xx implementations use a different + * offset. So let's give them a chance to define their offset + * in the board config header. + */ +#if !defined(CONFIG_SYS_NS16550_REG_SIZE) +#define CONFIG_SYS_NS16550_REG_SIZE 1 +#endif + #if defined(CONFIG_440) #include #else diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index be217fcf8d..6b61cc191e 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -4,6 +4,8 @@ * * Author: Igor Lisitsin * + * Copyright 2010, Stefan Roese, DENX Software Engineering, sr@denx.de + * * See file CREDITS for list of people who contributed to this * project. * @@ -24,6 +26,9 @@ */ #include +#include +#include +#include /* * UART test @@ -119,33 +124,24 @@ #define UDIV_MAX 32 #endif -#define UART_RBR 0x00 -#define UART_THR 0x00 -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_LSR 0x05 -#define UART_MSR 0x06 -#define UART_SCR 0x07 -#define UART_DLL 0x00 -#define UART_DLM 0x01 - -/* - * Line Status Register. - */ -#define asyncLSRDataReady1 0x01 -#define asyncLSROverrunError1 0x02 -#define asyncLSRParityError1 0x04 -#define asyncLSRFramingError1 0x08 -#define asyncLSRBreakInterrupt1 0x10 -#define asyncLSRTxHoldEmpty1 0x20 -#define asyncLSRTxShiftEmpty1 0x40 -#define asyncLSRRxFifoError1 0x80 - DECLARE_GLOBAL_DATA_PTR; +static void uart_post_init_common(struct NS16550 *com_port, unsigned short bdiv) +{ + volatile char val; + + out_8(&com_port->lcr, 0x80); /* set DLAB bit */ + out_8(&com_port->dll, bdiv); /* set baudrate divisor */ + out_8(&com_port->dlm, bdiv >> 8); /* set baudrate divisor */ + out_8(&com_port->lcr, 0x03); /* clear DLAB; set 8 bits, no parity */ + out_8(&com_port->fcr, 0x00); /* disable FIFO */ + out_8(&com_port->mcr, 0x10); /* enable loopback mode */ + val = in_8(&com_port->lsr); /* clear line status */ + val = in_8(&com_port->rbr); /* read receive buffer */ + out_8(&com_port->scr, 0x00); /* set scratchpad */ + out_8(&com_port->ier, 0x00); /* set interrupt enable reg */ +} + #if defined(CONFIG_440) || defined(CONFIG_405EX) #if !defined(CONFIG_SYS_EXT_SERIAL_CLOCK) static void serial_divs (int baudrate, unsigned long *pudiv, @@ -190,19 +186,18 @@ static void serial_divs (int baudrate, unsigned long *pudiv, } #endif -static int uart_post_init (unsigned long dev_base) +static int uart_post_init (struct NS16550 *com_port) { unsigned long reg = 0; unsigned long udiv; unsigned short bdiv; - volatile char val; #ifdef CONFIG_SYS_EXT_SERIAL_CLOCK unsigned long tmp; #endif int i; for (i = 0; i < 3500; i++) { - if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1) + if (in_8(&com_port->lsr) & UART_LSR_THRE) break; udelay (100); } @@ -239,34 +234,24 @@ static int uart_post_init (unsigned long dev_base) MTREG(UART3_SDR, reg); #endif - out8(dev_base + UART_LCR, 0x80); /* set DLAB bit */ - out8(dev_base + UART_DLL, bdiv); /* set baudrate divisor */ - out8(dev_base + UART_DLM, bdiv >> 8); /* set baudrate divisor */ - out8(dev_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8(dev_base + UART_FCR, 0x00); /* disable FIFO */ - out8(dev_base + UART_MCR, 0x10); /* enable loopback mode */ - val = in8(dev_base + UART_LSR); /* clear line status */ - val = in8(dev_base + UART_RBR); /* read receive buffer */ - out8(dev_base + UART_SCR, 0x00); /* set scratchpad */ - out8(dev_base + UART_IER, 0x00); /* set interrupt enable reg */ + uart_post_init_common(com_port, bdiv); return 0; } #else /* CONFIG_440 */ -static int uart_post_init (unsigned long dev_base) +static int uart_post_init (struct NS16550 *com_port) { unsigned long reg; unsigned long tmp; unsigned long clk; unsigned long udiv; unsigned short bdiv; - volatile char val; int i; for (i = 0; i < 3500; i++) { - if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1) + if (in_8(&com_port->lsr) & UART_LSR_THRE) break; udelay (100); } @@ -309,59 +294,51 @@ static int uart_post_init (unsigned long dev_base) bdiv = (clk + tmp / 2) / tmp; #endif /* CONFIG_405EZ */ - out8(dev_base + UART_LCR, 0x80); /* set DLAB bit */ - out8(dev_base + UART_DLL, bdiv); /* set baudrate divisor */ - out8(dev_base + UART_DLM, bdiv >> 8); /* set baudrate divisor */ - out8(dev_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8(dev_base + UART_FCR, 0x00); /* disable FIFO */ - out8(dev_base + UART_MCR, 0x10); /* enable loopback mode */ - val = in8(dev_base + UART_LSR); /* clear line status */ - val = in8(dev_base + UART_RBR); /* read receive buffer */ - out8(dev_base + UART_SCR, 0x00); /* set scratchpad */ - out8(dev_base + UART_IER, 0x00); /* set interrupt enable reg */ + uart_post_init_common(com_port, bdiv); - return (0); + return 0; } #endif /* CONFIG_440 */ -static void uart_post_putc (unsigned long dev_base, char c) +static void uart_post_putc (struct NS16550 *com_port, char c) { int i; - out8 (dev_base + UART_THR, c); /* put character out */ + out_8(&com_port->thr, c); /* put character out */ /* Wait for transfer completion */ for (i = 0; i < 3500; i++) { - if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1) + if (in_8(&com_port->lsr) & UART_LSR_THRE) break; udelay (100); } } -static int uart_post_getc (unsigned long dev_base) +static int uart_post_getc (struct NS16550 *com_port) { int i; /* Wait for character available */ for (i = 0; i < 3500; i++) { - if (in8 (dev_base + UART_LSR) & asyncLSRDataReady1) + if (in_8(&com_port->lsr) & UART_LSR_DR) break; udelay (100); } - return 0xff & in8 (dev_base + UART_RBR); + + return 0xff & in_8(&com_port->rbr); } -static int test_ctlr (unsigned long dev_base, int index) +static int test_ctlr (struct NS16550 *com_port, int index) { int res = -1; char test_str[] = "*** UART Test String ***\r\n"; int i; - uart_post_init (dev_base); + uart_post_init (com_port); for (i = 0; i < sizeof (test_str) - 1; i++) { - uart_post_putc (dev_base, test_str[i]); - if (uart_post_getc (dev_base) != test_str[i]) + uart_post_putc (com_port, test_str[i]); + if (uart_post_getc (com_port) != test_str[i]) goto done; } res = 0; @@ -377,8 +354,8 @@ int uart_post_test (int flags) int i, res = 0; static unsigned long base[] = CONFIG_SYS_POST_UART_TABLE; - for (i = 0; i < sizeof (base) / sizeof (base[0]); i++) { - if (test_ctlr (base[i], i)) + for (i = 0; i < ARRAY_SIZE(base); i++) { + if (test_ctlr((struct NS16550 *)base[i], i)) res = -1; } serial_reinit_all (); From 8a805df13615667ebdcc9f3a3a6fbf6c7778a992 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 16 Sep 2010 14:01:53 +0200 Subject: [PATCH 3/3] ppc4xx/fdt/flash: Change fdt_fixup_nor_flash_node() to not rely on cs size This patch changes the behaviour of the fdt_fixup_nor_flash_node() function. Now it doesn't patch the size of the "reg" property with the chip-select size, but with the size returned from the new function flash_get_bank_size(). This function will return per weak default the flash size of the bank (bank = chip-select numer) detected by the flash driver. If this does not fit your needs, this function may be overridden by a board specific one. For this the parameters needed to be changed. So I intentionally squashed the PPC4xx stuff using this routine into this patch. Otherwise it would not be git-bisectable anymore. The board specific function for the AMCC/APM Ebony eval board is now included in this patch version. Signed-off-by: Stefan Roese Tested-by: Detlev Zundel Cc: Gerald Van Baren Cc: Wolfgang Denk --- arch/powerpc/cpu/ppc4xx/fdt.c | 12 ++++---- board/amcc/ebony/flash.c | 31 ++++++++++++++++++++ common/fdt_support.c | 53 +++++++++++++++++++++++++++-------- include/configs/acadia.h | 8 +++++- include/fdt_support.h | 2 +- 5 files changed, 87 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/cpu/ppc4xx/fdt.c b/arch/powerpc/cpu/ppc4xx/fdt.c index 15a184b5c6..e99b2b03dc 100644 --- a/arch/powerpc/cpu/ppc4xx/fdt.c +++ b/arch/powerpc/cpu/ppc4xx/fdt.c @@ -59,15 +59,15 @@ void __ft_board_setup(void *blob, bd_t *bd) *p++ = 0; *p++ = bxcr & EBC_BXCR_BAS_MASK; *p++ = EBC_BXCR_BANK_SIZE(bxcr); - -#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE - /* Try to update reg property in nor flash node too */ - fdt_fixup_nor_flash_size(blob, i, - EBC_BXCR_BANK_SIZE(bxcr)); -#endif } } + +#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE + /* Update reg property in all nor flash nodes too */ + fdt_fixup_nor_flash_size(blob); +#endif + /* Some 405 PPC's have EBC as direct PLB child in the dts */ if (fdt_path_offset(blob, ebc_path) < 0) strcpy(ebc_path, "/plb/ebc"); diff --git a/board/amcc/ebony/flash.c b/board/amcc/ebony/flash.c index 8fe3ba1b8f..79d2c4c307 100644 --- a/board/amcc/ebony/flash.c +++ b/board/amcc/ebony/flash.c @@ -34,6 +34,7 @@ #include #include #include +#include #undef DEBUG #ifdef DEBUG @@ -71,6 +72,36 @@ static unsigned long flash_addr_table[8][CONFIG_SYS_MAX_FLASH_BANKS] = { */ static ulong flash_get_size(vu_long * addr, flash_info_t * info); +/* + * Override the weak default mapping function with a board specific one + */ +u32 flash_get_bank_size(int cs, int idx) +{ + u8 reg = in_8((void *)CONFIG_SYS_FPGA_BASE); + + if ((reg & BOOT_SMALL_FLASH) && !(reg & FLASH_ONBD_N)) { + /* + * cs0: small flash (512KiB) + * cs2: 2 * big flash (2 * 2MiB) + */ + if (cs == 0) + return flash_info[2].size; + if (cs == 2) + return flash_info[0].size + flash_info[1].size; + } else { + /* + * cs0: 2 * big flash (2 * 2MiB) + * cs2: small flash (512KiB) + */ + if (cs == 0) + return flash_info[0].size + flash_info[1].size; + if (cs == 2) + return flash_info[2].size; + } + + return 0; +} + unsigned long flash_init(void) { unsigned long total_b = 0; diff --git a/common/fdt_support.c b/common/fdt_support.c index aef4fe23e0..6f32e3f68d 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -590,12 +590,31 @@ int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose) { #endif #ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE +/* + * Provide a weak default function to return the flash bank size. + * There might be multiple non-identical flash chips connected to one + * chip-select, so we need to pass an index as well. + */ +u32 __flash_get_bank_size(int cs, int idx) +{ + extern flash_info_t flash_info[]; + + /* + * As default, a simple 1:1 mapping is provided. Boards with + * a different mapping need to supply a board specific mapping + * routine. + */ + return flash_info[cs].size; +} +u32 flash_get_bank_size(int cs, int idx) + __attribute__((weak, alias("__flash_get_bank_size"))); + /* * This function can be used to update the size in the "reg" property - * of the NOR FLASH device nodes. This is necessary for boards with + * of all NOR FLASH device nodes. This is necessary for boards with * non-fixed NOR FLASH sizes. */ -int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size) +int fdt_fixup_nor_flash_size(void *blob) { char compat[][16] = { "cfi-flash", "jedec-flash" }; int off; @@ -607,19 +626,31 @@ int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size) for (i = 0; i < 2; i++) { off = fdt_node_offset_by_compatible(blob, -1, compat[i]); while (off != -FDT_ERR_NOTFOUND) { + int idx; + /* - * Found one compatible node, now check if this one - * has the correct CS + * Found one compatible node, so fixup the size + * int its reg properties */ prop = fdt_get_property_w(blob, off, "reg", &len); if (prop) { - reg = (u32 *)&prop->data[0]; - if (reg[0] == cs) { - reg[2] = size; - fdt_setprop(blob, off, "reg", reg, - 3 * sizeof(u32)); + int tuple_size = 3 * sizeof(reg); - return 0; + /* + * There might be multiple reg-tuples, + * so loop through them all + */ + len /= tuple_size; + reg = (u32 *)&prop->data[0]; + for (idx = 0; idx < len; idx++) { + /* + * Update size in reg property + */ + reg[2] = flash_get_bank_size(reg[0], + idx); + fdt_setprop(blob, off, "reg", reg, + tuple_size); + reg += tuple_size; } } @@ -629,7 +660,7 @@ int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size) } } - return -1; + return 0; } #endif diff --git a/include/configs/acadia.h b/include/configs/acadia.h index bd3388f626..8b01c704fd 100644 --- a/include/configs/acadia.h +++ b/include/configs/acadia.h @@ -120,7 +120,13 @@ #define CONFIG_SYS_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ #else -#define CONFIG_SYS_NO_FLASH 1 /* No NOR on Acadia when NAND-booting */ +/* + * No NOR-flash on Acadia when NAND-booting. We need to undef the + * NOR device-tree fixup code as well, since flash_info is not defined + * in this case. + */ +#define CONFIG_SYS_NO_FLASH 1 +#undef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE #endif #ifdef CONFIG_ENV_IS_IN_FLASH diff --git a/include/fdt_support.h b/include/fdt_support.h index 871ef4524b..fd94929cef 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -79,7 +79,7 @@ void ft_pci_setup(void *blob, bd_t *bd); void set_working_fdt_addr(void *addr); int fdt_resize(void *blob); -int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size); +int fdt_fixup_nor_flash_size(void *blob); void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size); void fdt_del_node_and_alias(void *blob, const char *alias);