Commit 2959f936 authored by Tom Rini's avatar Tom Rini
parents 02c2c51c e29f1db3
......@@ -214,32 +214,40 @@ static void setup_usb_phys(void)
int arch_cpu_init(void)
{
#ifndef CONFIG_SPL_BUILD
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_ARMADA_38X)
/*
* Only with disabled MMU its possible to switch the base
* register address on Armada 38x. Without this the SDRAM
* located at >= 0x4000.0000 is also not accessible, as its
* still locked to cache.
*/
mmu_disable();
#endif
/* Linux expects the internal registers to be at 0xf1000000 */
writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG);
set_cbar(SOC_REGS_PHY_BASE + 0xC000);
#if !defined(CONFIG_SPL_BUILD)
/*
* From this stage on, the SoC detection is working. As we have
* configured the internal register base to the value used
* in the macros / defines in the U-Boot header (soc.h).
*/
if (mvebu_soc_family() == MVEBU_SOC_A38X) {
struct pl310_regs *const pl310 =
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
/*
* Only with disabled MMU its possible to switch the base
* register address on Armada 38x. Without this the SDRAM
* located at >= 0x4000.0000 is also not accessible, as its
* still locked to cache.
*
* So to fully release / unlock this area from cache, we need
* to first flush all caches, then disable the MMU and
* disable the L2 cache.
* To fully release / unlock this area from cache, we need
* to flush all caches and disable the L2 cache.
*/
icache_disable();
dcache_disable();
mmu_disable();
clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
}
#endif
/* Linux expects the internal registers to be at 0xf1000000 */
writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG);
set_cbar(SOC_REGS_PHY_BASE + 0xC000);
/*
* We need to call mvebu_mbus_probe() before calling
* update_sdram_window_sizes() as it disables all previously
......
......@@ -41,7 +41,7 @@
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
static int init_done;
static int init_done __attribute__((section(".data"))) = 0;
/* Timer reload and current value registers */
struct kwtmr_val {
......
......@@ -17,89 +17,6 @@
#include <stdint.h>
#include "kwbimage.h"
#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1))
/* Structure of the main header, version 0 (Kirkwood, Dove) */
struct main_hdr_v0 {
uint8_t blockid; /*0 */
uint8_t nandeccmode; /*1 */
uint16_t nandpagesize; /*2-3 */
uint32_t blocksize; /*4-7 */
uint32_t rsvd1; /*8-11 */
uint32_t srcaddr; /*12-15 */
uint32_t destaddr; /*16-19 */
uint32_t execaddr; /*20-23 */
uint8_t satapiomode; /*24 */
uint8_t rsvd3; /*25 */
uint16_t ddrinitdelay; /*26-27 */
uint16_t rsvd2; /*28-29 */
uint8_t ext; /*30 */
uint8_t checksum; /*31 */
};
struct ext_hdr_v0_reg {
uint32_t raddr;
uint32_t rdata;
};
#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg))
struct ext_hdr_v0 {
uint32_t offset;
uint8_t reserved[0x20 - sizeof(uint32_t)];
struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT];
uint8_t reserved2[7];
uint8_t checksum;
};
/* Structure of the main header, version 1 (Armada 370, Armada XP) */
struct main_hdr_v1 {
uint8_t blockid; /* 0 */
uint8_t reserved1; /* 1 */
uint16_t reserved2; /* 2-3 */
uint32_t blocksize; /* 4-7 */
uint8_t version; /* 8 */
uint8_t headersz_msb; /* 9 */
uint16_t headersz_lsb; /* A-B */
uint32_t srcaddr; /* C-F */
uint32_t destaddr; /* 10-13 */
uint32_t execaddr; /* 14-17 */
uint8_t reserved3; /* 18 */
uint8_t nandblocksize; /* 19 */
uint8_t nandbadblklocation; /* 1A */
uint8_t reserved4; /* 1B */
uint16_t reserved5; /* 1C-1D */
uint8_t ext; /* 1E */
uint8_t checksum; /* 1F */
};
/*
* Header for the optional headers, version 1 (Armada 370, Armada XP)
*/
struct opt_hdr_v1 {
uint8_t headertype;
uint8_t headersz_msb;
uint16_t headersz_lsb;
char data[0];
};
/*
* Various values for the opt_hdr_v1->headertype field, describing the
* different types of optional headers. The "secure" header contains
* informations related to secure boot (encryption keys, etc.). The
* "binary" header contains ARM binary code to be executed prior to
* executing the main payload (usually the bootloader). This is
* typically used to execute DDR3 training code. The "register" header
* allows to describe a set of (address, value) tuples that are
* generally used to configure the DRAM controller.
*/
#define OPT_HDR_V1_SECURE_TYPE 0x1
#define OPT_HDR_V1_BINARY_TYPE 0x2
#define OPT_HDR_V1_REGISTER_TYPE 0x3
#define KWBHEADER_V1_SIZE(hdr) \
(((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb)
static struct image_cfg_element *image_cfg;
static int cfgn;
......@@ -173,17 +90,6 @@ struct image_cfg_element {
#define IMAGE_CFG_ELEMENT_MAX 256
/*
* Byte 8 of the image header contains the version number. In the v0
* header, byte 8 was reserved, and always set to 0. In the v1 header,
* byte 8 has been changed to a proper field, set to 1.
*/
static unsigned int image_version(void *header)
{
unsigned char *ptr = header;
return ptr[8];
}
/*
* Utility functions to manipulate boot mode and ecc modes (convert
* them back and forth between description strings and the
......
......@@ -29,57 +29,109 @@
#define IBR_HDR_UART_ID 0x69
#define IBR_DEF_ATTRIB 0x00
enum kwbimage_cmd {
CMD_INVALID,
CMD_BOOT_FROM,
CMD_NAND_ECC_MODE,
CMD_NAND_PAGE_SIZE,
CMD_SATA_PIO_MODE,
CMD_DDR_INIT_DELAY,
CMD_DATA
};
#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1))
enum kwbimage_cmd_types {
CFG_INVALID = -1,
CFG_COMMAND,
CFG_DATA0,
CFG_DATA1
};
/* typedefs */
typedef struct bhr_t {
uint8_t blockid; /*0 */
uint8_t nandeccmode; /*1 */
/* Structure of the main header, version 0 (Kirkwood, Dove) */
struct main_hdr_v0 {
uint8_t blockid; /*0 */
uint8_t nandeccmode; /*1 */
uint16_t nandpagesize; /*2-3 */
uint32_t blocksize; /*4-7 */
uint32_t rsvd1; /*8-11 */
uint32_t srcaddr; /*12-15 */
uint32_t destaddr; /*16-19 */
uint32_t execaddr; /*20-23 */
uint8_t satapiomode; /*24 */
uint8_t rsvd3; /*25 */
uint8_t satapiomode; /*24 */
uint8_t rsvd3; /*25 */
uint16_t ddrinitdelay; /*26-27 */
uint16_t rsvd2; /*28-29 */
uint8_t ext; /*30 */
uint8_t checkSum; /*31 */
} bhr_t, *pbhr_t;
uint8_t ext; /*30 */
uint8_t checksum; /*31 */
};
struct reg_config {
struct ext_hdr_v0_reg {
uint32_t raddr;
uint32_t rdata;
};
typedef struct extbhr_t {
uint32_t dramregsoffs;
uint8_t rsrvd1[0x20 - sizeof(uint32_t)];
struct reg_config rcfg[KWBIMAGE_MAX_CONFIG];
uint8_t rsrvd2[7];
uint8_t checkSum;
} extbhr_t, *pextbhr_t;
#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg))
struct ext_hdr_v0 {
uint32_t offset;
uint8_t reserved[0x20 - sizeof(uint32_t)];
struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT];
uint8_t reserved2[7];
uint8_t checksum;
};
struct kwb_header {
bhr_t kwb_hdr;
extbhr_t kwb_exthdr;
struct main_hdr_v0 kwb_hdr;
struct ext_hdr_v0 kwb_exthdr;
};
/* Structure of the main header, version 1 (Armada 370, Armada XP) */
struct main_hdr_v1 {
uint8_t blockid; /* 0 */
uint8_t reserved1; /* 1 */
uint16_t reserved2; /* 2-3 */
uint32_t blocksize; /* 4-7 */
uint8_t version; /* 8 */
uint8_t headersz_msb; /* 9 */
uint16_t headersz_lsb; /* A-B */
uint32_t srcaddr; /* C-F */
uint32_t destaddr; /* 10-13 */
uint32_t execaddr; /* 14-17 */
uint8_t reserved3; /* 18 */
uint8_t nandblocksize; /* 19 */
uint8_t nandbadblklocation; /* 1A */
uint8_t reserved4; /* 1B */
uint16_t reserved5; /* 1C-1D */
uint8_t ext; /* 1E */
uint8_t checksum; /* 1F */
};
/*
* Header for the optional headers, version 1 (Armada 370, Armada XP)
*/
struct opt_hdr_v1 {
uint8_t headertype;
uint8_t headersz_msb;
uint16_t headersz_lsb;
char data[0];
};
/*
* Various values for the opt_hdr_v1->headertype field, describing the
* different types of optional headers. The "secure" header contains
* informations related to secure boot (encryption keys, etc.). The
* "binary" header contains ARM binary code to be executed prior to
* executing the main payload (usually the bootloader). This is
* typically used to execute DDR3 training code. The "register" header
* allows to describe a set of (address, value) tuples that are
* generally used to configure the DRAM controller.
*/
#define OPT_HDR_V1_SECURE_TYPE 0x1
#define OPT_HDR_V1_BINARY_TYPE 0x2
#define OPT_HDR_V1_REGISTER_TYPE 0x3
#define KWBHEADER_V1_SIZE(hdr) \
(((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb)
enum kwbimage_cmd {
CMD_INVALID,
CMD_BOOT_FROM,
CMD_NAND_ECC_MODE,
CMD_NAND_PAGE_SIZE,
CMD_SATA_PIO_MODE,
CMD_DDR_INIT_DELAY,
CMD_DATA
};
enum kwbimage_cmd_types {
CFG_INVALID = -1,
CFG_COMMAND,
CFG_DATA0,
CFG_DATA1
};
/*
......@@ -87,4 +139,15 @@ struct kwb_header {
*/
void init_kwb_image_type (void);
/*
* Byte 8 of the image header contains the version number. In the v0
* header, byte 8 was reserved, and always set to 0. In the v1 header,
* byte 8 has been changed to a proper field, set to 1.
*/
static inline unsigned int image_version(void *header)
{
unsigned char *ptr = header;
return ptr[8];
}
#endif /* _KWBIMAGE_H_ */
......@@ -614,9 +614,10 @@ static int
kwboot_img_patch_hdr(void *img, size_t size)
{
int rc;
bhr_t *hdr;
struct main_hdr_v1 *hdr;
uint8_t csum;
const size_t hdrsz = sizeof(*hdr);
size_t hdrsz = sizeof(*hdr);
int image_ver;
rc = -1;
hdr = img;
......@@ -626,8 +627,20 @@ kwboot_img_patch_hdr(void *img, size_t size)
goto out;
}
csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checkSum;
if (csum != hdr->checkSum) {
image_ver = image_version(img);
if (image_ver < 0) {
fprintf(stderr, "Invalid image header version\n");
errno = EINVAL;
goto out;
}
if (image_ver == 0)
hdrsz = sizeof(*hdr);
else
hdrsz = KWBHEADER_V1_SIZE(hdr);
csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checksum;
if (csum != hdr->checksum) {
errno = EINVAL;
goto out;
}
......@@ -639,14 +652,18 @@ kwboot_img_patch_hdr(void *img, size_t size)
hdr->blockid = IBR_HDR_UART_ID;
hdr->nandeccmode = IBR_HDR_ECC_DISABLED;
hdr->nandpagesize = 0;
if (image_ver == 0) {
struct main_hdr_v0 *hdr_v0 = img;
hdr->srcaddr = hdr->ext
? sizeof(struct kwb_header)
: sizeof(*hdr);
hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED;
hdr_v0->nandpagesize = 0;
hdr_v0->srcaddr = hdr_v0->ext
? sizeof(struct kwb_header)
: sizeof(*hdr_v0);
}
hdr->checkSum = kwboot_img_csum8(hdr, hdrsz) - csum;
hdr->checksum = kwboot_img_csum8(hdr, hdrsz) - csum;
rc = 0;
out:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment