summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/blackfin/initcode.c157
-rw-r--r--cpu/blackfin/serial.h72
-rw-r--r--cpu/mpc512x/Makefile3
-rw-r--r--cpu/mpc512x/iim.c394
-rw-r--r--cpu/ppc4xx/4xx_pci.c5
-rw-r--r--cpu/ppc4xx/4xx_pcie.c2
-rw-r--r--cpu/ppc4xx/fdt.c24
7 files changed, 531 insertions, 126 deletions
diff --git a/cpu/blackfin/initcode.c b/cpu/blackfin/initcode.c
index 6091f8c..ae0016d 100644
--- a/cpu/blackfin/initcode.c
+++ b/cpu/blackfin/initcode.c
@@ -20,7 +20,7 @@
#include "serial.h"
__attribute__((always_inline))
-static inline uint32_t serial_init(void)
+static inline void serial_init(void)
{
#ifdef __ADSPBF54x__
# ifdef BFIN_BOOT_UART_USE_RTS
@@ -61,25 +61,16 @@ static inline uint32_t serial_init(void)
}
#endif
- uint32_t old_baud;
- if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART)
- old_baud = serial_early_get_baud();
- else
- old_baud = CONFIG_BAUDRATE;
-
if (BFIN_DEBUG_EARLY_SERIAL) {
+ int ucen = *pUART_GCTL & UCEN;
serial_early_init();
/* If the UART is off, that means we need to program
* the baud rate ourselves initially.
*/
- if (!old_baud) {
- old_baud = CONFIG_BAUDRATE;
+ if (ucen != UCEN)
serial_early_set_baud(CONFIG_BAUDRATE);
- }
}
-
- return old_baud;
}
__attribute__((always_inline))
@@ -93,30 +84,6 @@ static inline void serial_deinit(void)
#endif
}
-/* We need to reset the baud rate when we have early debug turned on
- * or when we are booting over the UART.
- * XXX: we should fix this to calc the old baud and restore it rather
- * than hardcoding it via CONFIG_LDR_LOAD_BAUD ... but we have
- * to figure out how to avoid the division in the baud calc ...
- */
-__attribute__((always_inline))
-static inline void serial_reset_baud(uint32_t baud)
-{
- if (!BFIN_DEBUG_EARLY_SERIAL && CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART)
- return;
-
-#ifndef CONFIG_LDR_LOAD_BAUD
-# define CONFIG_LDR_LOAD_BAUD 115200
-#endif
-
- if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS)
- serial_early_set_baud(baud);
- else if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART)
- serial_early_set_baud(CONFIG_LDR_LOAD_BAUD);
- else
- serial_early_set_baud(CONFIG_BAUDRATE);
-}
-
__attribute__((always_inline))
static inline void serial_putc(char c)
{
@@ -133,12 +100,22 @@ static inline void serial_putc(char c)
}
-/* Max SCLK can be 133MHz ... dividing that by 4 gives
- * us a freq of 33MHz for SPI which should generally be
+/* Max SCLK can be 133MHz ... dividing that by (2*4) gives
+ * us a freq of 16MHz for SPI which should generally be
* slow enough for the slow reads the bootrom uses.
*/
+#if !defined(CONFIG_SPI_FLASH_SLOW_READ) && \
+ ((defined(__ADSPBF52x__) && __SILICON_REVISION__ >= 2) || \
+ (defined(__ADSPBF54x__) && __SILICON_REVISION__ >= 1))
+# define BOOTROM_SUPPORTS_SPI_FAST_READ 1
+#else
+# define BOOTROM_SUPPORTS_SPI_FAST_READ 0
+#endif
#ifndef CONFIG_SPI_BAUD_INITBLOCK
-# define CONFIG_SPI_BAUD_INITBLOCK 4
+# define CONFIG_SPI_BAUD_INITBLOCK (BOOTROM_SUPPORTS_SPI_FAST_READ ? 2 : 4)
+#endif
+#ifdef SPI0_BAUD
+# define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD
#endif
/* PLL_DIV defines */
@@ -168,11 +145,18 @@ static inline void serial_putc(char c)
#ifndef CONFIG_EBIU_RSTCTL_VAL
# define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */
#endif
+#if ((CONFIG_EBIU_RSTCTL_VAL & 0xFFFFFFC4) != 0)
+# error invalid EBIU_RSTCTL value: must not set reserved bits
+#endif
#ifndef CONFIG_EBIU_MBSCTL_VAL
# define CONFIG_EBIU_MBSCTL_VAL 0
#endif
+#if defined(CONFIG_EBIU_DDRQUE_VAL) && ((CONFIG_EBIU_DDRQUE_VAL & 0xFFFF8000) != 0)
+# error invalid EBIU_DDRQUE value: must not set reserved bits
+#endif
+
/* Make sure our voltage value is sane so we don't blow up! */
#ifndef CONFIG_VR_CTL_VAL
# define BFIN_CCLK ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_CCLK_DIV)
@@ -199,6 +183,9 @@ static inline void serial_putc(char c)
# elif defined(__ADSPBF54x__) /* TBD; use default */
# undef CONFIG_VR_CTL_VLEV
# define CONFIG_VR_CTL_VLEV VLEV_120
+# elif defined(__ADSPBF538__) || defined(__ADSPBF539__) /* TBD; use default */
+# undef CONFIG_VR_CTL_VLEV
+# define CONFIG_VR_CTL_VLEV VLEV_125
# endif
# ifdef CONFIG_BFIN_MAC
@@ -216,10 +203,17 @@ static inline void serial_putc(char c)
# define CONFIG_VR_CTL_VAL (CONFIG_VR_CTL_CLKBUF | CONFIG_VR_CTL_VLEV | CONFIG_VR_CTL_FREQ)
#endif
-__attribute__((saveall))
+BOOTROM_CALLED_FUNC_ATTR
void initcode(ADI_BOOT_DATA *bootstruct)
{
- uint32_t old_baud = serial_init();
+ /* Save the clock pieces that are used in baud rate calculation */
+ unsigned int sdivB, divB, vcoB;
+ serial_init();
+ if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
+ sdivB = bfin_read_PLL_DIV() & 0xf;
+ vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+ divB = serial_early_get_div();
+ }
#ifdef CONFIG_HW_WATCHDOG
# ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE
@@ -244,12 +238,11 @@ void initcode(ADI_BOOT_DATA *bootstruct)
* boot. Once we switch over to u-boot's SPI flash driver, we'll
* increase the speed appropriately.
*/
- if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER)
-#ifdef SPI0_BAUD
- bfin_write_SPI0_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
-#else
+ if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
+ if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
+ bootstruct->dFlags |= BFLAG_FASTREAD;
bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
-#endif
+ }
serial_putc('B');
@@ -267,40 +260,68 @@ void initcode(ADI_BOOT_DATA *bootstruct)
bfin_write_SIC_IWR(1);
#endif
- serial_putc('L');
+ /* With newer bootroms, we use the helper function to set up
+ * the memory controller. Older bootroms lacks such helpers
+ * so we do it ourselves.
+ */
+ if (BOOTROM_CAPS_SYSCONTROL) {
+ serial_putc('S');
+
+ ADI_SYSCTRL_VALUES memory_settings;
+ memory_settings.uwVrCtl = CONFIG_VR_CTL_VAL;
+ memory_settings.uwPllCtl = CONFIG_PLL_CTL_VAL;
+ memory_settings.uwPllDiv = CONFIG_PLL_DIV_VAL;
+ memory_settings.uwPllLockCnt = CONFIG_PLL_LOCKCNT_VAL;
+ syscontrol(SYSCTRL_WRITE | SYSCTRL_VRCTL | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT |
+ (CONFIG_VR_CTL_VAL & FREQ_MASK ? SYSCTRL_INTVOLTAGE : SYSCTRL_EXTVOLTAGE), &memory_settings, NULL);
+ } else {
+ serial_putc('L');
- bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL);
+ bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL);
- serial_putc('A');
+ serial_putc('A');
- /* Only reprogram when needed to avoid triggering unnecessary
- * PLL relock sequences.
- */
- if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) {
- serial_putc('!');
- bfin_write_VR_CTL(CONFIG_VR_CTL_VAL);
- asm("idle;");
- }
+ /* Only reprogram when needed to avoid triggering unnecessary
+ * PLL relock sequences.
+ */
+ if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) {
+ serial_putc('!');
+ bfin_write_VR_CTL(CONFIG_VR_CTL_VAL);
+ asm("idle;");
+ }
- serial_putc('C');
+ serial_putc('C');
- bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL);
+ bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL);
- serial_putc('K');
+ serial_putc('K');
- /* Only reprogram when needed to avoid triggering unnecessary
- * PLL relock sequences.
- */
- if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) {
- serial_putc('!');
- bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL);
- asm("idle;");
+ /* Only reprogram when needed to avoid triggering unnecessary
+ * PLL relock sequences.
+ */
+ if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) {
+ serial_putc('!');
+ bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL);
+ asm("idle;");
+ }
}
/* Since we've changed the SCLK above, we may need to update
* the UART divisors (UART baud rates are based on SCLK).
+ * Do the division by hand as there are no native instructions
+ * for dividing which means we'd generate a libgcc reference.
*/
- serial_reset_baud(old_baud);
+ if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
+ unsigned int sdivR, vcoR;
+ sdivR = bfin_read_PLL_DIV() & 0xf;
+ vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+ int dividend = sdivB * divB * vcoR;
+ int divisor = vcoB * sdivR;
+ unsigned int quotient;
+ for (quotient = 0; dividend > 0; ++quotient)
+ dividend -= divisor;
+ serial_early_put_div(quotient - ANOMALY_05000230);
+ }
serial_putc('F');
diff --git a/cpu/blackfin/serial.h b/cpu/blackfin/serial.h
index f671096..ce39148 100644
--- a/cpu/blackfin/serial.h
+++ b/cpu/blackfin/serial.h
@@ -156,16 +156,25 @@ static inline void serial_early_init(void)
}
__attribute__((always_inline))
-static inline uint32_t serial_early_get_baud(void)
+static inline void serial_early_put_div(uint16_t divisor)
{
- /* If the UART isnt enabled, then we are booting an LDR
- * from a non-UART source (so like flash) which means
- * the baud rate here is meaningless.
- */
- if ((*pUART_GCTL & UCEN) != UCEN)
- return 0;
+ /* Set DLAB in LCR to Access DLL and DLH */
+ ACCESS_LATCH();
+ SSYNC();
-#if (0) /* See comment for serial_reset_baud() in initcode.c */
+ /* Program the divisor to get the baud rate we want */
+ *pUART_DLL = LOB(divisor);
+ *pUART_DLH = HIB(divisor);
+ SSYNC();
+
+ /* Clear DLAB in LCR to Access THR RBR IER */
+ ACCESS_PORT_IER();
+ SSYNC();
+}
+
+__attribute__((always_inline))
+static inline uint16_t serial_early_get_div(void)
+{
/* Set DLAB in LCR to Access DLL and DLH */
ACCESS_LATCH();
SSYNC();
@@ -173,16 +182,12 @@ static inline uint32_t serial_early_get_baud(void)
uint8_t dll = *pUART_DLL;
uint8_t dlh = *pUART_DLH;
uint16_t divisor = (dlh << 8) | dll;
- uint32_t baud = get_sclk() / (divisor * 16);
/* Clear DLAB in LCR to Access THR RBR IER */
ACCESS_PORT_IER();
SSYNC();
- return baud;
-#else
- return CONFIG_BAUDRATE;
-#endif
+ return divisor;
}
__attribute__((always_inline))
@@ -192,20 +197,7 @@ static inline void serial_early_set_baud(uint32_t baud)
* weird multiplication is to make sure we over sample just
* a little rather than under sample the incoming signals.
*/
- uint16_t divisor = (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230;
-
- /* Set DLAB in LCR to Access DLL and DLH */
- ACCESS_LATCH();
- SSYNC();
-
- /* Program the divisor to get the baud rate we want */
- *pUART_DLL = LOB(divisor);
- *pUART_DLH = HIB(divisor);
- SSYNC();
-
- /* Clear DLAB in LCR to Access THR RBR IER */
- ACCESS_PORT_IER();
- SSYNC();
+ serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
}
#ifndef BFIN_IN_INITCODE
@@ -235,32 +227,6 @@ static inline void serial_early_puts(const char *s)
#endif
.endm
-/* Recursively expand calls to _serial_putc for every byte
- * passed to us. Append a newline when we're all done.
- */
-.macro _serial_early_putc byte:req morebytes:vararg
-#ifdef CONFIG_DEBUG_EARLY_SERIAL
- R0 = \byte;
- call _serial_putc;
-.ifnb \morebytes
- _serial_early_putc \morebytes
-.else
-.if (\byte != '\n')
- _serial_early_putc '\n'
-.endif
-.endif
-#endif
-.endm
-
-/* Wrapper around recurisve _serial_early_putc macro which
- * simply prepends the string "Early: "
- */
-.macro serial_early_putc byte:req morebytes:vararg
-#ifdef CONFIG_DEBUG_EARLY_SERIAL
- _serial_early_putc 'E', 'a', 'r', 'l', 'y', ':', ' ', \byte, \morebytes
-#endif
-.endm
-
/* Since we embed the string right into our .text section, we need
* to find its address. We do this by getting our PC and adding 2
* bytes (which is the length of the jump instruction). Then we
diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile
index e8f1060..297d135 100644
--- a/cpu/mpc512x/Makefile
+++ b/cpu/mpc512x/Makefile
@@ -26,6 +26,9 @@ LIB = $(obj)lib$(CPU).a
START = start.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o i2c.o iopin.o
+ifdef CONFIG_IIM
+COBJS += iim.o
+endif
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/mpc512x/iim.c b/cpu/mpc512x/iim.c
new file mode 100644
index 0000000..6cdc422
--- /dev/null
+++ b/cpu/mpc512x/iim.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2008 Silicon Turnkey Express, Inc.
+ * Martha Marx <mmarx@silicontkx.com>
+ *
+ * ADS5121 IIM (Fusebox) Interface
+ *
+ * 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 <command.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CMD_FUSE
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char cur_bank = '1';
+
+char *iim_err_msg(u32 err)
+{
+ static char *IIM_errs[] = {
+ "Parity Error in cache",
+ "Explicit Sense Cycle Error",
+ "Write to Locked Register Error",
+ "Read Protect Error",
+ "Override Protect Error",
+ "Write Protect Error"};
+
+ int i;
+
+ if (!err)
+ return "";
+ for (i = 1; i < 8; i++)
+ if (err & (1 << i))
+ printf("IIM - %s\n", IIM_errs[i-1]);
+ return "";
+}
+
+int in_range(int n, int min, int max, char *err, char *usg)
+{
+ if (n > max || n < min) {
+ printf(err);
+ printf("Usage:\n%s\n", usg);
+ return 0;
+ }
+ return 1;
+}
+
+int ads5121_fuse_read(int bank, int fstart, int num)
+{
+ iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+ u32 *iim_fb, dummy;
+ int f, ctr;
+
+ out_be32(&iim->err, in_be32(&iim->err));
+ if (bank == 0)
+ iim_fb = (u32 *)&(iim->fbac0);
+ else
+ iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+ dummy = in_be32(&iim_fb[0]);
+ if (in_be32(&iim->err) & IIM_ERR_RPE) {
+ printf("\tRead protect fuse is set\n");
+ out_be32(&iim->err, IIM_ERR_RPE);
+ return 0;
+ }
+ printf("Reading Bank %d cache\n", bank);
+ for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
+ if (ctr % 4 == 0)
+ printf("F%2d:", f);
+ printf("\t%#04x", (u8)(iim_fb[f]));
+ if (ctr % 4 == 3)
+ printf("\n");
+ }
+ if (ctr % 4 != 0)
+ printf("\n");
+}
+
+int ads5121_fuse_override(int bank, int f, u8 val)
+{
+ iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+ u32 *iim_fb;
+ u32 iim_stat;
+ int i;
+
+ out_be32(&iim->err, in_be32(&iim->err));
+ if (bank == 0)
+ iim_fb = (u32 *)&(iim->fbac0);
+ else
+ iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+ iim_stat = in_be32(&iim_fb[0]);
+ if (in_be32(&iim->err) & IIM_ERR_RPE) {
+ printf("Read protect fuse is set on bank %d;"
+ "Override protect may also be set\n", bank);
+ printf("An attempt will be made to override\n");
+ out_be32(&iim->err, IIM_ERR_RPE);
+ }
+ if (iim_stat & IIM_FBAC_FBOP) {
+ printf("Override protect fuse is set on bank %d\n", bank);
+ return 1;
+ }
+ if (f > IIM_FMAX) /* reset the entire bank */
+ for (i = 0; i < IIM_FMAX + 1; i++)
+ out_be32(&iim_fb[i], 0);
+ else
+ out_be32(&iim_fb[f], val);
+ return 0;
+}
+
+int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno)
+{
+ iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+ int f, i, bitno;
+ u32 stat, err;
+
+ f = simple_strtol(fuseno_bitno, NULL, 10);
+ if (f == 0 && fuseno_bitno[0] != '0')
+ f = -1;
+ if (!in_range(f, 0, IIM_FMAX,
+ "<frow> must be between 0-31\n\n", cmdtp->usage))
+ return 1;
+ bitno = -1;
+ for (i = 0; i < 6; i++) {
+ if (fuseno_bitno[i] == '_') {
+ bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
+ if (bitno == 0 && fuseno_bitno[i+1] != '0')
+ bitno = -1;
+ break;
+ }
+ }
+ if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
+ "Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
+ cmdtp->usage))
+ return 1;
+ out_be32(&iim->err, in_be32(&iim->err));
+ out_be32(&iim->prg_p, IIM_PRG_P_SET);
+ out_be32(&iim->ua, IIM_SET_UA(bank, f));
+ out_be32(&iim->la, IIM_SET_LA(f, bitno));
+#ifdef DEBUG
+ printf("Programming disabled with DEBUG defined \n");
+ printf(""Set up to pro
+ printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
+#else
+ out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
+ do
+ udelay(20);
+ while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+ out_be32(&iim->prg_p, 0);
+ err = in_be32(&iim->err);
+ if (stat & IIM_STAT_PRGD) {
+ if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
+ printf("Fuse is successfully set");
+ if (err)
+ printf(" - however there are other errors");
+ printf("\n");
+ }
+ iim->stat = 0;
+ }
+ if (err) {
+ iim_err_msg(err);
+ out_be32(&iim->err, in_be32(&iim->err));
+ }
+#endif
+}
+
+int ads5121_fuse_sense(int bank, int fstart, int num)
+{
+ iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+ u32 iim_fbac;
+ u32 stat, err, err_hold = 0;
+ int f, ctr;
+
+ out_be32(&iim->err, in_be32(&iim->err));
+ if (bank == 0)
+ iim_fbac = in_be32(&iim->fbac0);
+ else
+ iim_fbac = in_be32(&iim->fbac1);
+ if (iim_fbac & IIM_FBAC_FBESP) {
+ printf("\tSense Protect disallows this operation\n");
+ out_be32(&iim->err, IIM_FBAC_FBESP);
+ return 1;
+ }
+ err = in_be32(&iim->err);
+ if (err) {
+ iim_err_msg(err);
+ err_hold |= err;
+ }
+ if (err & IIM_ERR_RPE)
+ printf("\tRead protect fuse is set; "
+ "Sense Protect may be set but will be attempted\n");
+ if (err)
+ out_be32(&iim->err, err);
+ printf("Sensing fuse(s) on Bank %d\n", bank);
+ for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
+ out_be32(&iim->ua, IIM_SET_UA(bank, f));
+ out_be32(&iim->la, IIM_SET_LA(f, 0));
+ out_be32(&iim->fctl, IIM_FCTL_ESNS_N);
+ do
+ udelay(20);
+ while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+ err = in_be32(&iim->err);
+ if (err & IIM_ERR_SNSE) {
+ iim_err_msg(err);
+ out_be32(&iim->err, IIM_ERR_SNSE);
+ return 1;
+ }
+ if (stat & IIM_STAT_SNSD) {
+ out_be32(&iim->stat, 0);
+ if (ctr % 4 == 0)
+ printf("F%2d:", f);
+ printf("\t%#04x", (u8)iim->sdat);
+ if (ctr % 4 == 3)
+ printf("\n");
+ }
+ if (err) {
+ err_hold |= err;
+ out_be32(&iim->err, err);
+ }
+ }
+ if (ctr % 4 != 0)
+ printf("\n");
+ if (err_hold)
+ iim_err_msg(err_hold);
+
+ return 0;
+}
+
+int ads5121_fuse_stat(int bank)
+{
+ iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+ u32 iim_fbac;
+ u32 err;
+
+ out_be32(&iim->err, in_be32(&iim->err));
+ if (bank == 0)
+ iim_fbac = in_be32(&iim->fbac0);
+ else
+ iim_fbac = in_be32(&iim->fbac1);
+ err = in_be32(&iim->err);
+ if (err)
+ iim_err_msg(err);
+ if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
+ if (iim_fbac == 0)
+ printf("Since protection settings can't be read - "
+ "try sensing fuse row 0;\n");
+ return 0;
+ }
+ if (iim_fbac & IIM_PROTECTION)
+ printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
+ else if (!(err & IIM_ERR_RPE))
+ printf("No Protection fuses are set\n");
+ if (iim_fbac & IIM_FBAC_FBWP)
+ printf("\tWrite Protect fuse is set\n");
+ if (iim_fbac & IIM_FBAC_FBOP)
+ printf("\tOverride Protect fuse is set\n");
+ if (iim_fbac & IIM_FBAC_FBESP)
+ printf("\tSense Protect Fuse is set\n");
+ out_be32(&iim->err, in_be32(&iim->err));
+
+ return 0;
+}
+
+int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int frow, n, v, bank;
+
+ if (cur_bank == '0')
+ bank = 0;
+ else
+ bank = 1;
+
+ switch (argc) {
+ case 0:
+ case 1:
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ case 2:
+ if (strncmp(argv[1], "stat", 4) == 0)
+ return ads5121_fuse_stat(bank);
+ if (strncmp(argv[1], "read", 4) == 0)
+ return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
+ if (strncmp(argv[1], "sense", 5) == 0)
+ return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
+ if (strncmp(argv[1], "ovride", 6) == 0)
+ return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
+ if (strncmp(argv[1], "bank", 4) == 0) {
+ printf("Active Fuse Bank is %c\n", cur_bank);
+ return 0;
+ }
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ case 3:
+ if (strncmp(argv[1], "bank", 4) == 0) {
+ if (argv[2][0] == '0')
+ cur_bank = '0';
+ else if (argv[2][0] == '1')
+ cur_bank = '1';
+ else {
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ printf("Setting Active Fuse Bank to %c\n", cur_bank);
+ return 0;
+ }
+ if (strncmp(argv[1], "prog", 4) == 0)
+ return ads5121_fuse_prog(cmdtp, bank, argv[2]);
+
+ frow = (int)simple_strtol(argv[2], NULL, 10);
+ if (frow == 0 && argv[2][0] != '0')
+ frow = -1;
+ if (!in_range(frow, 0, IIM_FMAX,
+ "<frow> must be between 0-31\n\n", cmdtp->usage))
+ return 1;
+ if (strncmp(argv[1], "read", 4) == 0)
+ return ads5121_fuse_read(bank, frow, 1);
+ if (strncmp(argv[1], "ovride", 6) == 0)
+ return ads5121_fuse_override(bank, frow, 0);
+ if (strncmp(argv[1], "sense", 5) == 0)
+ return ads5121_fuse_sense(bank, frow, 1);
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ case 4:
+ frow = (int)simple_strtol(argv[2], NULL, 10);
+ if (frow == 0 && argv[2][0] != '0')
+ frow = -1;
+ if (!in_range(frow, 0, IIM_FMAX,
+ "<frow> must be between 0-31\n\n", cmdtp->usage))
+ return 1;
+ if (strncmp(argv[1], "read", 4) == 0) {
+ n = (int)simple_strtol(argv[3], NULL, 10);
+ if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+ "<frow>+<n> must be between 1-32\n\n",
+ cmdtp->usage))
+ return 1;
+ return ads5121_fuse_read(bank, frow, n);
+ }
+ if (strncmp(argv[1], "ovride", 6) == 0) {
+ v = (int)simple_strtol(argv[3], NULL, 10);
+ return ads5121_fuse_override(bank, frow, v);
+ }
+ if (strncmp(argv[1], "sense", 5) == 0) {
+ n = (int)simple_strtol(argv[3], NULL, 10);
+ if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+ "<frow>+<n> must be between 1-32\n\n",
+ cmdtp->usage))
+ return 1;
+ return ads5121_fuse_sense(bank, frow, n);
+ }
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ default: /* at least 5 args */
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+}
+
+U_BOOT_CMD(
+ fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
+ " - Read, Sense, Override or Program Fuses\n",
+ "bank <n> - sets active Fuse Bank to 0 or 1\n"
+ " no args shows current active bank\n"
+ "fuse stat - print active fuse bank's protection status\n"
+ "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
+ " no args to print entire bank's fuses\n"
+ "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
+ " no <v> defaults to 0 for the row\n"
+ " no args resets entire bank to 0\n"
+ " NOTE - settings persist until hard reset\n"
+ "fuse sense [<frow>] - senses current fuse at <frow>\n"
+ " no args for entire bank\n"
+ "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n"
+ " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
+ " WARNING - this is permanent\n"
+ );
+#endif /* CONFIG_CMD_FUSE */
diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
index e8871fc..2e75886 100644
--- a/cpu/ppc4xx/4xx_pci.c
+++ b/cpu/ppc4xx/4xx_pci.c
@@ -588,8 +588,9 @@ void pci_init_board(void)
int busno;
busno = pci_440_init (&ppc440_hose);
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if (defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+ !defined(CONFIG_PCI_DISABLE_PCIE)
pcie_setup_hoses(busno + 1);
#endif
}
diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c
index fd40d8a..58d96bb 100644
--- a/cpu/ppc4xx/4xx_pcie.c
+++ b/cpu/ppc4xx/4xx_pcie.c
@@ -33,7 +33,7 @@
#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \
defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
- defined(CONFIG_PCI)
+ defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE)
#include <asm/4xx_pcie.h>
diff --git a/cpu/ppc4xx/fdt.c b/cpu/ppc4xx/fdt.c
index c55e1cf..ba5c120 100644
--- a/cpu/ppc4xx/fdt.c
+++ b/cpu/ppc4xx/fdt.c
@@ -113,6 +113,7 @@ void fdt_pcie_setup(void *blob)
void ft_cpu_setup(void *blob, bd_t *bd)
{
sys_info_t sys_info;
+ int off, ndepth = 0;
get_sys_info(&sys_info);
@@ -133,9 +134,28 @@ void ft_cpu_setup(void *blob, bd_t *bd)
fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
/*
- * Setup all baudrates for the UARTs
+ * Fixup all UART clocks for CPU internal UARTs
+ * (only these UARTs are definitely clocked by gd->uart_clk)
+ *
+ * These UARTs are direct childs of /plb/opb. This code
+ * does not touch any UARTs that are connected to the ebc.
*/
- do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1);
+ off = fdt_path_offset(blob, "/plb/opb");
+ while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) {
+ /*
+ * process all sub nodes and stop when we are back
+ * at the starting depth
+ */
+ if (ndepth <= 0)
+ break;
+
+ /* only update direct childs */
+ if ((ndepth == 1) &&
+ (fdt_node_check_compatible(blob, off, "ns16550") == 0))
+ fdt_setprop(blob, off,
+ "clock-frequency",
+ (void*)&(gd->uart_clk), 4);
+ }
/*
* Fixup all ethernet nodes