ppc4xx: Big lwmon5 board support rework/update
This patch brings the lwmon5 board support up-to-date. Here a
summary of the changes:
lwmon5 board port related:
- GPIO's changed to control the LSB transmitter
- Reset USB PHY's upon power-up
- Enable CAN upon power-up
- USB init error workaround (errata CHIP_6)
- EBC: Enable burstmode and modify the timings for the GDC memory
- EBC: Speed up NOR flash timings
lwmon5 board POST related:
- Add FPGA memory test
- Add GDC memory test
- DSP POST reworked
- SYSMON POST: Fix handling of negative temperatures
- Add output for sysmon1 POST
- HW-watchdog min. time test reworked
Additionally some coding-style changes were done.
Signed-off-by: Sascha Laue <sascha.laue@liebherr.com>
Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/board/lwmon5/kbd.c b/board/lwmon5/kbd.c
index 0e26b89..5231c7a 100644
--- a/board/lwmon5/kbd.c
+++ b/board/lwmon5/kbd.c
@@ -45,6 +45,10 @@
/*--------------------- Local macros and constants --------------------*/
#define _NOT_USED_ 0xFFFFFFFF
+/*------------------------- dspic io expander -----------------------*/
+#define DSPIC_PON_STATUS_REG 0x80A
+#define DSPIC_PON_INV_STATUS_REG 0x80C
+#define DSPIC_PON_KEY_REG 0x810
/*------------------------- Keyboard controller -----------------------*/
/* command codes */
#define KEYBD_CMD_READ_KEYS 0x01
@@ -75,6 +79,7 @@
/* maximum number of "magic" key codes that can be assigned */
static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR;
+static uchar dspic_addr = CONFIG_SYS_I2C_DSPIC_IO_ADDR;
static uchar *key_match (uchar *);
@@ -167,6 +172,23 @@
}
}
+
+/* Read a register from the dsPIC. */
+int _dspic_read(ushort reg, ushort *data)
+{
+ uchar buf[sizeof(*data)];
+ int rval;
+
+ if (i2c_read(dspic_addr, reg, 2, buf, 2))
+ return -1;
+
+ rval = i2c_read(dspic_addr, reg, sizeof(reg), buf, sizeof(*data));
+ *data = (buf[0] << 8) | buf[1];
+
+ return rval;
+}
+
+
/***********************************************************************
F* Function: int misc_init_r (void) P*A*Z*
*
@@ -197,6 +219,7 @@
uchar kbd_init_status = gd->kbd_status >> 8;
uchar kbd_status = gd->kbd_status;
uchar val;
+ ushort data, inv_data;
char *str;
int i;
@@ -231,9 +254,31 @@
i2c_write (kbd_addr, 0, 0, &val, 1);
i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
+ /* read out start key from bse01 received via can */
+ _dspic_read(DSPIC_PON_STATUS_REG, &data);
+ /* check highbyte from status register */
+ if (data > 0xFF) {
+ _dspic_read(DSPIC_PON_INV_STATUS_REG, &inv_data);
+
+ /* check inverse data */
+ if ((data+inv_data) == 0xFFFF) {
+ /* don't overwrite local key */
+ if (kbd_data[1] == 0) {
+ /* read key value */
+ _dspic_read(DSPIC_PON_KEY_REG, &data);
+ str = (char *)&data;
+ /* swap bytes */
+ kbd_data[1] = str[1];
+ kbd_data[2] = str[0];
+ printf("CAN received startkey: 0x%X\n", data);
+ }
+ }
+ }
+
for (i = 0; i < KEYBD_DATALEN; ++i) {
sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
}
+
setenv ("keybd", keybd_env);
str = strdup ((char *)key_match (kbd_data)); /* decode keys */
diff --git a/board/lwmon5/lwmon5.c b/board/lwmon5/lwmon5.c
index 9622b70..dd275bf 100644
--- a/board/lwmon5/lwmon5.c
+++ b/board/lwmon5/lwmon5.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2007
+ * (C) Copyright 2007-2010
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* This program is free software; you can redistribute it and/or
@@ -24,10 +24,13 @@
#include <asm/processor.h>
#include <asm/ppc4xx-gpio.h>
#include <asm/io.h>
+#include <post.h>
+#include <flash.h>
+#include <mtd/cfi_flash.h>
DECLARE_GLOBAL_DATA_PTR;
-extern flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+static phys_addr_t lwmon5_cfi_flash_bank_addr[2] = CONFIG_SYS_FLASH_BANKS_LIST;
ulong flash_get_size(ulong base, int banknum);
int misc_init_r_kbd(void);
@@ -97,16 +100,18 @@
gpio_write_bit(CONFIG_SYS_GPIO_FLASH_WP, 1);
#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1
- gpio_write_bit(CONFIG_SYS_GPIO_HIGHSIDE, 1);
+ /* enable the LSB transmitter */
+ gpio_write_bit(CONFIG_SYS_GPIO_LSB_ENABLE, 1);
+ /* enable the CAN transmitter */
+ gpio_write_bit(CONFIG_SYS_GPIO_CAN_ENABLE, 1);
reg = 0; /* reuse as counter */
out_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR,
in_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR)
& ~CONFIG_SYS_DSPIC_TEST_MASK);
- while (!gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY) && reg++ < 1000) {
+ while (gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY) && reg++ < 1000) {
udelay(1000);
}
- gpio_write_bit(CONFIG_SYS_GPIO_HIGHSIDE, 0);
if (gpio_read_in_bit(CONFIG_SYS_GPIO_DSPIC_READY)) {
/* set "boot error" flag */
out_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR,
@@ -135,9 +140,61 @@
return 0;
}
-/*---------------------------------------------------------------------------+
- | misc_init_r.
- +---------------------------------------------------------------------------*/
+/*
+ * Override weak default with board specific version
+ */
+phys_addr_t cfi_flash_bank_addr(int bank)
+{
+ return lwmon5_cfi_flash_bank_addr[bank];
+}
+
+/*
+ * Override the weak default mapping function with a board specific one
+ */
+u32 flash_get_bank_size(int cs, int idx)
+{
+ return flash_info[idx].size;
+}
+
+int board_early_init_r(void)
+{
+ u32 val0, val1;
+
+ /*
+ * lwmon5 is manufactured in 2 different board versions:
+ * The lwmon5a board has 64MiB NOR flash instead of the
+ * 128MiB of the original lwmon5. Unfortunately the CFI driver
+ * will report 2 banks of 64MiB even for the smaller flash
+ * chip, since the bank is mirrored. To fix this, we bring
+ * one bank into CFI query mode and read its response. This
+ * enables us to detect the real number of flash devices/
+ * banks which will be used later on by the common CFI driver.
+ */
+
+ /* Put bank 0 into CFI command mode and read */
+ out_be32((void *)CONFIG_SYS_FLASH0, 0x00980098);
+ val0 = in_be32((void *)CONFIG_SYS_FLASH0 + FLASH_OFFSET_CFI_RESP);
+ val1 = in_be32((void *)CONFIG_SYS_FLASH1 + FLASH_OFFSET_CFI_RESP);
+
+ /* Reset flash again out of query mode */
+ out_be32((void *)CONFIG_SYS_FLASH0, 0x00f000f0);
+
+ /* When not identical, we have 2 different flash devices/banks */
+ if (val0 != val1)
+ return 0;
+
+ /*
+ * Now we're sure that we're running on a LWMON5a board with
+ * only 64MiB NOR flash in one bank:
+ *
+ * Set flash base address and bank count for CFI driver probing.
+ */
+ cfi_flash_num_flash_banks = 1;
+ lwmon5_cfi_flash_bank_addr[0] = CONFIG_SYS_FLASH0;
+
+ return 0;
+}
+
int misc_init_r(void)
{
u32 pbcr;
@@ -145,7 +202,7 @@
u32 reg;
unsigned long usb2d0cr = 0;
unsigned long usb2phy0cr, usb2h0cr = 0;
- unsigned long sdr0_pfc1;
+ unsigned long sdr0_pfc1, sdr0_srst;
/*
* FLASH stuff...
@@ -158,32 +215,7 @@
gd->bd->bi_flashoffset = 0;
mfebc(PB0CR, pbcr);
- switch (gd->bd->bi_flashsize) {
- case 1 << 20:
- size_val = 0;
- break;
- case 2 << 20:
- size_val = 1;
- break;
- case 4 << 20:
- size_val = 2;
- break;
- case 8 << 20:
- size_val = 3;
- break;
- case 16 << 20:
- size_val = 4;
- break;
- case 32 << 20:
- size_val = 5;
- break;
- case 64 << 20:
- size_val = 6;
- break;
- case 128 << 20:
- size_val = 7;
- break;
- }
+ size_val = ffs(gd->bd->bi_flashsize) - 21;
pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17);
mtebc(PB0CR, pbcr);
@@ -193,53 +225,92 @@
flash_get_size(gd->bd->bi_flashstart, 0);
/* Monitor protection ON by default */
- (void)flash_protect(FLAG_PROTECT_SET,
- -CONFIG_SYS_MONITOR_LEN,
- 0xffffffff,
- &flash_info[1]);
+ flash_protect(FLAG_PROTECT_SET, -CONFIG_SYS_MONITOR_LEN, 0xffffffff,
+ &flash_info[cfi_flash_num_flash_banks - 1]);
/* Env protection ON by default */
- (void)flash_protect(FLAG_PROTECT_SET,
- CONFIG_ENV_ADDR_REDUND,
- CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1,
- &flash_info[1]);
+ flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
+ CONFIG_ENV_ADDR_REDUND + 2 * CONFIG_ENV_SECT_SIZE - 1,
+ &flash_info[cfi_flash_num_flash_banks - 1]);
/*
* USB suff...
*/
+
+ /* Reset USB */
+ /* Reset of USB2PHY0 must be active at least 10 us */
+ mtsdr(SDR0_SRST0, SDR0_SRST0_USB2H | SDR0_SRST0_USB2D);
+ udelay(2000);
+
+ mtsdr(SDR0_SRST1, SDR0_SRST1_USB20PHY | SDR0_SRST1_USB2HUTMI |
+ SDR0_SRST1_USB2HPHY | SDR0_SRST1_OPBA2 |
+ SDR0_SRST1_PLB42OPB1 | SDR0_SRST1_OPB2PLB40);
+ udelay(2000);
+
+ /* Errata CHIP_6 */
+
+ /* 1. Set internal PHY configuration */
/* SDR Setting */
mfsdr(SDR0_PFC1, sdr0_pfc1);
mfsdr(SDR0_USB0, usb2d0cr);
mfsdr(SDR0_USB2PHY0CR, usb2phy0cr);
mfsdr(SDR0_USB2H0CR, usb2h0cr);
- usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_XOCLK_MASK;
- usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_XOCLK_EXTERNAL; /*0*/
- usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_WDINT_MASK;
- usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_WDINT_16BIT_30MHZ; /*1*/
- usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_DVBUS_MASK;
- usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DVBUS_PURDIS; /*0*/
- usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_DWNSTR_MASK;
- usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DWNSTR_HOST; /*1*/
- usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_UTMICN_MASK;
- usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_UTMICN_HOST; /*1*/
+ usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_XOCLK_MASK;
+ usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_XOCLK_EXTERNAL; /*0*/
+ usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_WDINT_MASK;
+ usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_WDINT_16BIT_30MHZ; /*1*/
+ usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_DVBUS_MASK;
+ usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DVBUS_PUREN; /*1*/
+ usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_DWNSTR_MASK;
+ usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_DWNSTR_HOST; /*1*/
+ usb2phy0cr = usb2phy0cr & ~SDR0_USB2PHY0CR_UTMICN_MASK;
+ usb2phy0cr = usb2phy0cr | SDR0_USB2PHY0CR_UTMICN_HOST; /*1*/
- /* An 8-bit/60MHz interface is the only possible alternative
- when connecting the Device to the PHY */
- usb2h0cr = usb2h0cr &~SDR0_USB2H0CR_WDINT_MASK;
- usb2h0cr = usb2h0cr | SDR0_USB2H0CR_WDINT_16BIT_30MHZ; /*1*/
+ /*
+ * An 8-bit/60MHz interface is the only possible alternative
+ * when connecting the Device to the PHY
+ */
+ usb2h0cr = usb2h0cr & ~SDR0_USB2H0CR_WDINT_MASK;
+ usb2h0cr = usb2h0cr | SDR0_USB2H0CR_WDINT_16BIT_30MHZ; /*1*/
mtsdr(SDR0_PFC1, sdr0_pfc1);
mtsdr(SDR0_USB0, usb2d0cr);
mtsdr(SDR0_USB2PHY0CR, usb2phy0cr);
mtsdr(SDR0_USB2H0CR, usb2h0cr);
+ /* 2. De-assert internal PHY reset */
+ mfsdr(SDR0_SRST1, sdr0_srst);
+ sdr0_srst = sdr0_srst & ~SDR0_SRST1_USB20PHY;
+ mtsdr(SDR0_SRST1, sdr0_srst);
+
+ /* 3. Wait for more than 1 ms */
+ udelay(2000);
+
+ /* 4. De-assert USB 2.0 Host main reset */
+ mfsdr(SDR0_SRST0, sdr0_srst);
+ sdr0_srst = sdr0_srst &~ SDR0_SRST0_USB2H;
+ mtsdr(SDR0_SRST0, sdr0_srst);
+ udelay(1000);
+
+ /* 5. De-assert reset of OPB2 cores */
+ mfsdr(SDR0_SRST1, sdr0_srst);
+ sdr0_srst = sdr0_srst &~ SDR0_SRST1_PLB42OPB1;
+ sdr0_srst = sdr0_srst &~ SDR0_SRST1_OPB2PLB40;
+ sdr0_srst = sdr0_srst &~ SDR0_SRST1_OPBA2;
+ mtsdr(SDR0_SRST1, sdr0_srst);
+ udelay(1000);
+
+ /* 6. Set EHCI Configure FLAG */
+
+ /* 7. Reassert internal PHY reset: */
+ mtsdr(SDR0_SRST1, SDR0_SRST1_USB20PHY);
+ udelay(1000);
+
/*
* Clear resets
*/
- udelay (1000);
mtsdr(SDR0_SRST1, 0x00000000);
- udelay (1000);
mtsdr(SDR0_SRST0, 0x00000000);
printf("USB: Host(int phy) Device(ext phy)\n");
@@ -264,7 +335,7 @@
{
char *s = getenv("serial#");
- printf("Board: lwmon5");
+ puts("Board: lwmon5");
if (s != NULL) {
puts(", serial# ");
@@ -331,34 +402,33 @@
extern GraphicDevice mb862xx;
-static const gdc_regs init_regs [] =
-{
- {0x0100, 0x00000f00},
- {0x0020, 0x801401df},
- {0x0024, 0x00000000},
- {0x0028, 0x00000000},
- {0x002c, 0x00000000},
- {0x0110, 0x00000000},
- {0x0114, 0x00000000},
- {0x0118, 0x01df0280},
- {0x0004, 0x031f0000},
- {0x0008, 0x027f027f},
- {0x000c, 0x015f028f},
- {0x0010, 0x020c0000},
- {0x0014, 0x01df01ea},
- {0x0018, 0x00000000},
- {0x001c, 0x01e00280},
- {0x0100, 0x80010f00},
- {0x0, 0x0}
+static const gdc_regs init_regs [] = {
+ { 0x0100, 0x00000f00 },
+ { 0x0020, 0x801401df },
+ { 0x0024, 0x00000000 },
+ { 0x0028, 0x00000000 },
+ { 0x002c, 0x00000000 },
+ { 0x0110, 0x00000000 },
+ { 0x0114, 0x00000000 },
+ { 0x0118, 0x01df0280 },
+ { 0x0004, 0x031f0000 },
+ { 0x0008, 0x027f027f },
+ { 0x000c, 0x015f028f },
+ { 0x0010, 0x020c0000 },
+ { 0x0014, 0x01df01ea },
+ { 0x0018, 0x00000000 },
+ { 0x001c, 0x01e00280 },
+ { 0x0100, 0x80010f00 },
+ { 0x0, 0x0 }
};
-const gdc_regs *board_get_regs (void)
+const gdc_regs *board_get_regs(void)
{
return init_regs;
}
/* Returns Lime base address */
-unsigned int board_video_init (void)
+unsigned int board_video_init(void)
{
/*
* Reset Lime controller
@@ -375,7 +445,7 @@
return CONFIG_SYS_LIME_BASE_0;
}
-#define DEFAULT_BRIGHTNESS 0x64
+#define DEFAULT_BRIGHTNESS 0x64
static void board_backlight_brightness(int brightness)
{
@@ -390,7 +460,7 @@
}
}
-void board_backlight_switch (int flag)
+void board_backlight_switch(int flag)
{
char * param;
int rc;
@@ -410,15 +480,14 @@
/*
* Return text to be printed besides the logo.
*/
-void video_get_info_str (int line_number, char *info)
+void video_get_info_str(int line_number, char *info)
{
- if (line_number == 1) {
- strcpy (info, " Board: Lwmon5 (Liebherr Elektronik GmbH)");
- } else {
+ if (line_number == 1)
+ strcpy(info, " Board: Lwmon5 (Liebherr Elektronik GmbH)");
+ else
info [0] = '\0';
- }
}
-#endif
+#endif /* CONFIG_CONSOLE_EXTRA_INFO */
#endif /* CONFIG_VIDEO */
void board_reset(void)