Skip to content
Snippets Groups Projects
Commit e884656c authored by Tom Rini's avatar Tom Rini
Browse files
parents 975f97b4 031426a7
Branches
Tags
No related merge requests found
Showing
with 450 additions and 67 deletions
......@@ -6,3 +6,10 @@
*/
#include <asm/mach-imx/sys_proto.h>
#define USBPHY_PWD 0x00000000
#define USBPHY_PWD_RXPWDRX (1 << 20) /* receiver block power down */
#define is_usbotg_phy_active(void) (!(readl(USB_PHY0_BASE_ADDR + USBPHY_PWD) & \
USBPHY_PWD_RXPWDRX))
......@@ -318,9 +318,9 @@ struct clk_root_map {
};
enum enet_freq {
ENET_25MHz,
ENET_50MHz,
ENET_125MHz,
ENET_25MHZ,
ENET_50MHZ,
ENET_125MHZ,
};
u32 get_root_clk(enum clk_root_index clock_id);
......
......@@ -966,15 +966,15 @@ int set_clk_enet(enum enet_freq type)
clock_enable(CCGR_ENET2, 0);
switch (type) {
case ENET_125MHz:
case ENET_125MHZ:
enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK;
enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK;
break;
case ENET_50MHz:
case ENET_50MHZ:
enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK;
enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK;
break;
case ENET_25MHz:
case ENET_25MHZ:
enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK;
enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK;
break;
......
......@@ -14,6 +14,7 @@
#include <asm/spl.h>
#include <spl.h>
#include <asm/mach-imx/hab.h>
#include <g_dnl.h>
DECLARE_GLOBAL_DATA_PTR;
......@@ -31,6 +32,18 @@ u32 spl_boot_device(void)
if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */
return BOOT_DEVICE_BOARD;
/*
* The above method does not detect that the boot ROM used
* serial downloader in case the boot ROM decided to use the
* serial downloader as a fall back (primary boot source failed).
*
* Infer that the boot ROM used the USB serial downloader by
* checking whether the USB PHY is currently active... This
* assumes that SPL did not (yet) initialize the USB PHY...
*/
if (is_usbotg_phy_active())
return BOOT_DEVICE_BOARD;
/* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */
switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) {
/* EIM: See 8.5.1, Table 8-9 */
......@@ -82,6 +95,15 @@ u32 spl_boot_device(void)
}
return BOOT_DEVICE_NONE;
}
#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
{
put_unaligned(CONFIG_G_DNL_PRODUCT_NUM + 0xfff, &dev->idProduct);
return 0;
}
#endif
#endif
#if defined(CONFIG_SPL_MMC_SUPPORT)
......
......@@ -151,10 +151,4 @@ void board_init_f(ulong dummy)
/* configure MMDC for SDRAM width/size and per-model calibration */
ot1200_spl_dram_init();
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
/* load/boot image from boot device */
board_init_r(NULL, 0);
}
......@@ -336,9 +336,6 @@ void board_init_f(ulong dummy)
puts("!!!ERROR!!! DRAM detection failed!!!\n");
hang();
}
memset(__bss_start, 0, __bss_end - __bss_start);
board_init_r(NULL, 0);
}
void board_boot_order(u32 *spl_boot_list)
......
......@@ -384,10 +384,4 @@ void board_init_f(ulong dummy)
/* DDR initialization */
spl_dram_init();
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
/* load/boot image from boot device */
board_init_r(NULL, 0);
}
......@@ -260,7 +260,7 @@ static int setup_fec(void)
(IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK |
IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0);
return set_clk_enet(ENET_125MHz);
return set_clk_enet(ENET_125MHZ);
}
......
......@@ -626,9 +626,6 @@ void board_init_f(ulong dummy)
spl_dram_init(8 << ventana_info.sdram_width,
16 << ventana_info.sdram_size,
board_model);
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
}
void board_boot_order(u32 *spl_boot_list)
......
......@@ -5,4 +5,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y := bx50v3.o
obj-y := bx50v3.o vpd_reader.o
......@@ -26,8 +26,19 @@
#include <asm/arch/sys_proto.h>
#include <i2c.h>
#include <pwm.h>
#include <stdlib.h>
#include "vpd_reader.h"
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_SYS_I2C_EEPROM_ADDR
# define CONFIG_SYS_I2C_EEPROM_ADDR 0x50
# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
#endif
#ifndef CONFIG_SYS_I2C_EEPROM_BUS
#define CONFIG_SYS_I2C_EEPROM_BUS 2
#endif
#define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
PAD_CTL_HYS)
......@@ -528,6 +539,102 @@ int overwrite_console(void)
return 1;
}
#define VPD_TYPE_INVALID 0x00
#define VPD_BLOCK_NETWORK 0x20
#define VPD_BLOCK_HWID 0x44
#define VPD_PRODUCT_B850 1
#define VPD_PRODUCT_B650 2
#define VPD_PRODUCT_B450 3
struct vpd_cache {
uint8_t product_id;
uint8_t macbits;
unsigned char mac1[6];
};
/*
* Extracts MAC and product information from the VPD.
*/
static int vpd_callback(
void *userdata,
uint8_t id,
uint8_t version,
uint8_t type,
size_t size,
uint8_t const *data)
{
struct vpd_cache *vpd = (struct vpd_cache *)userdata;
if ( id == VPD_BLOCK_HWID
&& version == 1
&& type != VPD_TYPE_INVALID
&& size >= 1) {
vpd->product_id = data[0];
} else if ( id == VPD_BLOCK_NETWORK
&& version == 1
&& type != VPD_TYPE_INVALID
&& size >= 6) {
vpd->macbits |= 1;
memcpy(vpd->mac1, data, 6);
}
return 0;
}
static void set_eth0_mac_address(unsigned char * mac)
{
uint32_t *ENET_TCR = (uint32_t*)0x21880c4;
uint32_t *ENET_PALR = (uint32_t*)0x21880e4;
uint32_t *ENET_PAUR = (uint32_t*)0x21880e8;
*ENET_TCR |= 0x100; /* ADDINS */
*ENET_PALR |= (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
*ENET_PAUR |= (mac[4] << 24) | (mac[5] << 16);
}
static void process_vpd(struct vpd_cache *vpd)
{
if ( vpd->product_id == VPD_PRODUCT_B850
|| vpd->product_id == VPD_PRODUCT_B650
|| vpd->product_id == VPD_PRODUCT_B450) {
if (vpd->macbits & 1) {
set_eth0_mac_address(vpd->mac1);
}
}
}
static int read_vpd(uint eeprom_bus)
{
struct vpd_cache vpd;
int res;
int size = 1024;
uint8_t *data;
unsigned int current_i2c_bus = i2c_get_bus_num();
res = i2c_set_bus_num(eeprom_bus);
if (res < 0)
return res;
data = (uint8_t *)malloc(size);
if (!data)
return -ENOMEM;
res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
CONFIG_SYS_I2C_EEPROM_ADDR_LEN, data, size);
if (res == 0) {
memset(&vpd, 0, sizeof(vpd));
vpd_reader(size, data, &vpd, vpd_callback);
process_vpd(&vpd);
}
free(data);
i2c_set_bus_num(current_i2c_bus);
return res;
}
int board_eth_init(bd_t *bis)
{
setup_iomux_enet();
......@@ -586,6 +693,8 @@ int board_init(void)
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
read_vpd(CONFIG_SYS_I2C_EEPROM_BUS);
return 0;
}
......
/*
* Copyright 2016 General Electric Company
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "vpd_reader.h"
#include <linux/bch.h>
#include <stdlib.h>
/* BCH configuration */
const struct {
int header_ecc_capability_bits;
int data_ecc_capability_bits;
unsigned int prim_poly;
struct {
int min;
int max;
} galois_field_order;
} bch_configuration = {
.header_ecc_capability_bits = 4,
.data_ecc_capability_bits = 16,
.prim_poly = 0,
.galois_field_order = {
.min = 5,
.max = 15,
},
};
static int calculate_galois_field_order(size_t source_length)
{
int gfo = bch_configuration.galois_field_order.min;
for (; gfo < bch_configuration.galois_field_order.max &&
((((1 << gfo) - 1) - ((int)source_length * 8)) < 0);
gfo++) {
}
if (gfo == bch_configuration.galois_field_order.max) {
return -1;
}
return gfo + 1;
}
static int verify_bch(int ecc_bits, unsigned int prim_poly,
uint8_t * data, size_t data_length,
const uint8_t * ecc, size_t ecc_length)
{
int gfo = calculate_galois_field_order(data_length);
if (gfo < 0) {
return -1;
}
struct bch_control * bch = init_bch(gfo, ecc_bits, prim_poly);
if (!bch) {
return -1;
}
if (bch->ecc_bytes != ecc_length) {
free_bch(bch);
return -1;
}
unsigned * errloc = (unsigned *)calloc(data_length, sizeof(unsigned));
int errors = decode_bch(
bch, data, data_length, ecc, NULL, NULL, errloc);
free_bch(bch);
if (errors < 0) {
free(errloc);
return -1;
}
if (errors > 0) {
for (int n = 0; n < errors; n++) {
if (errloc[n] >= 8 * data_length) {
/* n-th error located in ecc (no need for data correction) */
} else {
/* n-th error located in data */
data[errloc[n] / 8] ^= 1 << (errloc[n] % 8);
}
}
}
free(errloc);
return 0;
}
static const int ID = 0;
static const int LEN = 1;
static const int VER = 2;
static const int TYP = 3;
static const int BLOCK_SIZE = 4;
static const uint8_t HEADER_BLOCK_ID = 0x00;
static const uint8_t HEADER_BLOCK_LEN = 18;
static const uint32_t HEADER_BLOCK_MAGIC = 0xca53ca53;
static const size_t HEADER_BLOCK_VERIFY_LEN = 14;
static const size_t HEADER_BLOCK_ECC_OFF = 14;
static const size_t HEADER_BLOCK_ECC_LEN = 4;
static const uint8_t ECC_BLOCK_ID = 0xFF;
int vpd_reader(
size_t size,
uint8_t * data,
void * userdata,
int (*fn)(
void * userdata,
uint8_t id,
uint8_t version,
uint8_t type,
size_t size,
uint8_t const * data))
{
if ( size < HEADER_BLOCK_LEN
|| data == NULL
|| fn == NULL) {
return -EINVAL;
}
/*
* +--------------------+--------------------+--//--+--------------------+
* | header block | data block | ... | ecc block |
* +--------------------+--------------------+--//--+--------------------+
* : : :
* +------+-------+-----+ +------+-------------+
* | id | magic | ecc | | ... | ecc |
* | len | off | | +------+-------------+
* | ver | size | | :
* | type | | | :
* +------+-------+-----+ :
* : : : :
* <----- [1] ----> <----------- [2] ----------->
*
* Repair (if necessary) the contents of header block [1] by using a
* 4 byte ECC located at the end of the header block. A successful
* return value means that we can trust the header.
*/
int ret = verify_bch(
bch_configuration.header_ecc_capability_bits,
bch_configuration.prim_poly,
data,
HEADER_BLOCK_VERIFY_LEN,
&data[HEADER_BLOCK_ECC_OFF],
HEADER_BLOCK_ECC_LEN);
if (ret < 0) {
return ret;
}
/* Validate header block { id, length, version, type }. */
if ( data[ID] != HEADER_BLOCK_ID
|| data[LEN] != HEADER_BLOCK_LEN
|| data[VER] != 0
|| data[TYP] != 0
|| ntohl(*(uint32_t *)(&data[4])) != HEADER_BLOCK_MAGIC) {
return -EINVAL;
}
uint32_t offset = ntohl(*(uint32_t *)(&data[8]));
uint16_t size_bits = ntohs(*(uint16_t *)(&data[12]));
/* Check that ECC header fits. */
if (offset + 3 >= size) {
return -EINVAL;
}
/* Validate ECC block. */
uint8_t * ecc = &data[offset];
if ( ecc[ID] != ECC_BLOCK_ID
|| ecc[LEN] < BLOCK_SIZE
|| ecc[LEN] + offset > size
|| ecc[LEN] - BLOCK_SIZE != size_bits / 8
|| ecc[VER] != 1
|| ecc[TYP] != 1) {
return -EINVAL;
}
/*
* Use the header block to locate the ECC block and verify the data
* blocks [2] against the ecc block ECC.
*/
ret = verify_bch(
bch_configuration.data_ecc_capability_bits,
bch_configuration.prim_poly,
&data[data[LEN]],
offset - data[LEN],
&data[offset + BLOCK_SIZE],
ecc[LEN] - BLOCK_SIZE);
if (ret < 0) {
return ret;
}
/* Stop after ECC. Ignore possible zero padding. */
size = offset;
for (;;) {
/* Move to next block. */
size -= data[LEN];
data += data[LEN];
if (size == 0) {
/* Finished iterating through blocks. */
return 0;
}
if ( size < BLOCK_SIZE
|| data[LEN] < BLOCK_SIZE) {
/* Not enough data for a header, or short header. */
return -EINVAL;
}
ret = fn(
userdata,
data[ID],
data[VER],
data[TYP],
data[LEN] - BLOCK_SIZE,
&data[BLOCK_SIZE]);
if (ret) {
return ret;
}
}
}
/*
* Copyright 2016 General Electric Company
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "common.h"
/*
* Read VPD from given data, verify content, and call callback
* for each vital product data block.
*
* Returns Non-zero on error. Negative numbers encode errno.
*/
int vpd_reader(
size_t size,
uint8_t * data,
void * userdata,
int (*fn)(
void * userdata,
uint8_t id,
uint8_t version,
uint8_t type,
size_t size,
uint8_t const * data));
......@@ -596,10 +596,4 @@ void board_init_f(ulong dummy)
udelay(100);
mmdc_do_write_level_calibration(&novena_ddr_info);
mmdc_do_dqs_calibration(&novena_ddr_info);
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
/* load/boot image from boot device */
board_init_r(NULL, 0);
}
......@@ -296,11 +296,5 @@ void board_init_f(ulong dummy)
/* DDR initialization */
spl_dram_init();
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
/* load/boot image from boot device */
board_init_r(NULL, 0);
}
#endif
......@@ -349,6 +349,7 @@ static bool is_hummingboard(void)
* Machine selection -
* Machine val1, val2
* -------------------------
* HB2 x x
* HB rev 3.x x 0
* CBi 0 1
* HB 1 1
......@@ -362,9 +363,37 @@ static bool is_hummingboard(void)
return true;
}
static bool is_hummingboard2(void)
{
int val1;
SETUP_IOMUX_PADS(hb_cbi_sense);
gpio_direction_input(IMX_GPIO_NR(2, 8));
val1 = gpio_get_value(IMX_GPIO_NR(2, 8));
/*
* Machine selection -
* Machine val1
* -------------------
* HB2 0
* HB rev 3.x x
* CBi x
* HB x
*/
if (val1 == 0)
return true;
else
return false;
}
int checkboard(void)
{
if (is_hummingboard())
if (is_hummingboard2())
puts("Board: MX6 Hummingboard2\n");
else if (is_hummingboard())
puts("Board: MX6 Hummingboard\n");
else
puts("Board: MX6 Cubox-i\n");
......@@ -375,7 +404,9 @@ int checkboard(void)
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
if (is_hummingboard())
if (is_hummingboard2())
env_set("board_name", "HUMMINGBOARD2");
else if (is_hummingboard())
env_set("board_name", "HUMMINGBOARD");
else
env_set("board_name", "CUBOXI");
......
......@@ -47,3 +47,20 @@ Remove power from the pico board.
Put pico board into normal boot mode.
Power up the board and the new updated U-Boot should boot from eMMC.
Building U-Boot to boot with NXP 4.1 kernel:
The NXP 4.1 kernel boots only in secure boot mode on mx7.
Follow the next steps to enable secure boot:
$ make mrproper
$ make pico-imx7d_defconfig
$ make menuconfig
-> ARM architecture
-> [*] Enable support for booting in non-secure mode
-> [*] Boot in secure mode by default
-> Exit
$ make
Flash u-boot.imx using the imx_usb_loader tool.
......@@ -182,7 +182,7 @@ static int setup_fec(void)
(IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK |
IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0);
return set_clk_enet(ENET_125MHz);
return set_clk_enet(ENET_125MHZ);
}
int board_phy_config(struct phy_device *phydev)
......
......@@ -29,7 +29,6 @@
#include <dm/platform_data/serial_mxc.h>
#include <dm/platdata.h>
#include <fsl_esdhc.h>
#include <g_dnl.h>
#include <i2c.h>
#include <imx_thermal.h>
#include <linux/errno.h>
......@@ -1224,18 +1223,6 @@ void reset_cpu(ulong addr)
{
}
#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
{
unsigned short usb_pid;
usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
put_unaligned(usb_pid, &dev->idProduct);
return 0;
}
#endif
#endif
static struct mxc_serial_platdata mxc_serial_plat = {
......
......@@ -28,7 +28,6 @@
#include <dm/platform_data/serial_mxc.h>
#include <dm/platdata.h>
#include <fsl_esdhc.h>
#include <g_dnl.h>
#include <i2c.h>
#include <imx_thermal.h>
#include <linux/errno.h>
......@@ -1108,18 +1107,6 @@ void reset_cpu(ulong addr)
{
}
#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
{
unsigned short usb_pid;
usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
put_unaligned(usb_pid, &dev->idProduct);
return 0;
}
#endif
#endif
static struct mxc_serial_platdata mxc_serial_plat = {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment