[U-Boot] [PATCH 00/16] Updates / improvements to bx50v3 support

This series improves the support on the bx50v3 devices (b540v3, b650v3 and b850v3) and utilising features recently added as part of the PPD implementation.
NOTE: This series requires the PPD series: https://lists.denx.de/pipermail/u-boot/2017-November/310865.html
Changes outside of the bx50v3/ppd specifc areas:
- Added driver for RX8010SJ RTC. - Added functionality to e1000 driver to enable wrting of EEPROM/MAC address.
Hannu Lounento (5): net: e1000: add support for writing to EEPROM net: e1000: split e1000_read_mac_addr net: e1000: implement eth_write_hwaddr board: ge: bx50v3: program MAC address to I210 board: ge: bx50v3: mount rootfs read-only
Ian Ray (5): configs: Add network device support for bx50v3 products board: ge: bx50v3: Support FIT and select configuration based on VPD config: ge_bx50v3: read boot script configs: ge_bx50v3: enable bootcount configs: ge_bx50v3: automatic partition selection and video output failure message
Martyn Welch (4): board: ge: mx53ppd: Move check_time() to common location board: ge: Enable access to i2c bus 1 and 2 board: ge: bx50v3: move FEC MAC address programming to driver board: ge: bx50v3: Enable hardware watchdog
Nandor Han (2): rtc: adding RX8010SJ rtc driver board,ge,bx50v3 - rtc time validation
board/ge/bx50v3/bx50v3.c | 130 ++++++++++----- board/ge/common/Makefile | 2 +- board/ge/common/ge_common.c | 55 +++++++ board/ge/common/ge_common.h | 7 + board/ge/mx53ppd/mx53ppd.c | 47 +----- configs/ge_b450v3_defconfig | 7 +- configs/ge_b650v3_defconfig | 7 +- configs/ge_b850v3_defconfig | 8 +- drivers/net/e1000.c | 292 +++++++++++++++++++++++++++++++--- drivers/net/e1000.h | 3 + drivers/rtc/Kconfig | 6 + drivers/rtc/Makefile | 1 + drivers/rtc/rx8010sj.c | 378 ++++++++++++++++++++++++++++++++++++++++++++ include/configs/ge_bx50v3.h | 190 +++++++++------------- 14 files changed, 911 insertions(+), 222 deletions(-) create mode 100644 board/ge/common/ge_common.c create mode 100644 board/ge/common/ge_common.h create mode 100644 drivers/rtc/rx8010sj.c

We are going to be using check_time() on more than the mx53ppd, move this function to a common location.
Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/common/Makefile | 2 +- board/ge/common/ge_common.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ board/ge/common/ge_common.h | 7 ++++++ board/ge/mx53ppd/mx53ppd.c | 47 +------------------------------------- 4 files changed, 64 insertions(+), 47 deletions(-) create mode 100644 board/ge/common/ge_common.c create mode 100644 board/ge/common/ge_common.h
diff --git a/board/ge/common/Makefile b/board/ge/common/Makefile index 93e6c01..f5be11b 100644 --- a/board/ge/common/Makefile +++ b/board/ge/common/Makefile @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y := vpd_reader.o +obj-y := vpd_reader.o ge_common.o diff --git a/board/ge/common/ge_common.c b/board/ge/common/ge_common.c new file mode 100644 index 0000000..c826096 --- /dev/null +++ b/board/ge/common/ge_common.c @@ -0,0 +1,55 @@ +/* + * Copyright 2017 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <rtc.h> + +void check_time(void) +{ + int ret, i; + struct rtc_time tm; + u8 retry = 3; + + unsigned int current_i2c_bus = i2c_get_bus_num(); + + ret = i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); + if (ret < 0) + return; + + rtc_init(); + + for (i = 0; i < retry; i++) { + ret = rtc_get(&tm); + if (!ret || ret == -EINVAL) + break; + } + + if (ret < 0) + env_set("rtc_status", "RTC_ERROR"); + + if (tm.tm_year > 2037) { + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + tm.tm_mday = 1; + tm.tm_wday = 2; + tm.tm_mon = 1; + tm.tm_year = 2036; + + for (i = 0; i < retry; i++) { + ret = rtc_set(&tm); + if (!ret) + break; + } + + if (ret < 0) + env_set("rtc_status", "RTC_ERROR"); + } + + i2c_set_bus_num(current_i2c_bus); +} + diff --git a/board/ge/common/ge_common.h b/board/ge/common/ge_common.h new file mode 100644 index 0000000..b28aada --- /dev/null +++ b/board/ge/common/ge_common.h @@ -0,0 +1,7 @@ +/* + * Copyright 2017 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void check_time(void); diff --git a/board/ge/mx53ppd/mx53ppd.c b/board/ge/mx53ppd/mx53ppd.c index 6a8a29d..90dbccc 100644 --- a/board/ge/mx53ppd/mx53ppd.c +++ b/board/ge/mx53ppd/mx53ppd.c @@ -33,8 +33,8 @@ #include <watchdog.h> #include "ppd_gpio.h" #include <stdlib.h> +#include "../../ge/common/ge_common.h" #include "../../ge/common/vpd_reader.h" -#include <rtc.h>
#define MX53PPD_LCD_POWER IMX_GPIO_NR(3, 24)
@@ -357,51 +357,6 @@ static int read_vpd(uint eeprom_bus) return res; }
-static void check_time(void) -{ - int ret, i; - struct rtc_time tm; - u8 retry = 3; - - unsigned int current_i2c_bus = i2c_get_bus_num(); - - ret = i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); - if (ret < 0) - return; - - rtc_init(); - - for (i = 0; i < retry; i++) { - ret = rtc_get(&tm); - if (!ret || ret == -EINVAL) - break; - } - - if (ret < 0) - env_set("rtc_status", "RTC_ERROR"); - - if (tm.tm_year > 2037) { - tm.tm_sec = 0; - tm.tm_min = 0; - tm.tm_hour = 0; - tm.tm_mday = 1; - tm.tm_wday = 2; - tm.tm_mon = 1; - tm.tm_year = 2036; - - for (i = 0; i < retry; i++) { - ret = rtc_set(&tm); - if (!ret) - break; - } - - if (ret < 0) - env_set("rtc_status", "RTC_ERROR"); - } - - i2c_set_bus_num(current_i2c_bus); -} - int board_init(void) { gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;

From: Hannu Lounento hannu.lounento@ge.com
Port functions for writing to EEPROM, updating the checksum and committing data to flash from the Linux kernel igb driver.
Functions were ported from Linux 4.8-rc2 (694d0d0bb20).
Signed-off-by: Hannu Lounento hannu.lounento@ge.com CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- drivers/net/e1000.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++- drivers/net/e1000.h | 3 + 2 files changed, 172 insertions(+), 2 deletions(-)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 875682b..7aecdb9 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -150,6 +150,7 @@ static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#ifndef CONFIG_E1000_NO_NVM static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); +static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw); static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); @@ -862,6 +863,62 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, }
/****************************************************************************** + * e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR + * @hw: pointer to the HW structure + * @offset: offset within the Shadow Ram to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the Shadow Ram + * + * Writes data to Shadow Ram at offset using EEWR register. + * + * If e1000_update_eeprom_checksum_i210 is not called after this function, the + * Shadow Ram will most likely contain an invalid checksum. + *****************************************************************************/ +static int32_t e1000_write_eeprom_srwr(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) +{ + struct e1000_eeprom_info *eeprom = &hw->eeprom; + uint32_t i, k, eewr = 0; + uint32_t attempts = 100000; + int32_t ret_val = 0; + + /* A check for invalid values: offset too large, too many words, + * too many words for the offset, and not enough words. + */ + if ((offset >= eeprom->word_size) || + (words > (eeprom->word_size - offset)) || (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_EEPROM; + goto out; + } + + for (i = 0; i < words; i++) { + eewr = ((offset + i) << E1000_EEPROM_RW_ADDR_SHIFT) + | (data[i] << E1000_EEPROM_RW_REG_DATA) | + E1000_EEPROM_RW_REG_START; + + E1000_WRITE_REG(hw, I210_EEWR, eewr); + + for (k = 0; k < attempts; k++) { + if (E1000_EEPROM_RW_REG_DONE & + E1000_READ_REG(hw, I210_EEWR)) { + ret_val = 0; + break; + } + udelay(5); + } + + if (ret_val) { + DEBUGOUT("Shadow RAM write EEWR timed out\n"); + break; + } + } + +out: + return ret_val; +} + +/****************************************************************************** * Verifies that the EEPROM has a valid checksum * * hw - Struct containing variables accessed by shared code @@ -907,6 +964,116 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
return -E1000_ERR_EEPROM; } + +/****************************************************************************** + * e1000_pool_flash_update_done_i210 - Pool FLUDONE status. + * @hw: pointer to the HW structure + * + *****************************************************************************/ +static int32_t e1000_pool_flash_update_done_i210(struct e1000_hw *hw) +{ + int32_t ret_val = -E1000_ERR_EEPROM; + uint32_t i, reg; + + for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { + reg = E1000_READ_REG(hw, EECD); + if (reg & E1000_EECD_FLUDONE_I210) { + ret_val = 0; + break; + } + udelay(5); + } + + return ret_val; +} + +/****************************************************************************** + * e1000_update_flash_i210 - Commit EEPROM to the flash + * @hw: pointer to the HW structure + * + *****************************************************************************/ +static int32_t e1000_update_flash_i210(struct e1000_hw *hw) +{ + int32_t ret_val = 0; + uint32_t flup; + + ret_val = e1000_pool_flash_update_done_i210(hw); + if (ret_val == -E1000_ERR_EEPROM) { + DEBUGOUT("Flash update time out\n"); + goto out; + } + + flup = E1000_READ_REG(hw, EECD) | E1000_EECD_FLUPD_I210; + E1000_WRITE_REG(hw, EECD, flup); + + ret_val = e1000_pool_flash_update_done_i210(hw); + if (ret_val) + DEBUGOUT("Flash update time out\n"); + else + DEBUGOUT("Flash update complete\n"); + +out: + return ret_val; +} + +/****************************************************************************** + * e1000_update_eeprom_checksum_i210 - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. Next commit EEPROM data onto the Flash. + *****************************************************************************/ +static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw) +{ + int32_t ret_val = 0; + uint16_t checksum = 0; + uint16_t i, nvm_data; + + /* Read the first word from the EEPROM. If this times out or fails, do + * not continue or we could be in for a very long wait while every + * EEPROM read fails + */ + ret_val = e1000_read_eeprom_eerd(hw, 0, 1, &nvm_data); + if (ret_val) { + DEBUGOUT("EEPROM read failed\n"); + goto out; + } + + if (!(e1000_get_hw_eeprom_semaphore(hw))) { + /* Do not use hw->nvm.ops.write, hw->nvm.ops.read + * because we do not want to take the synchronization + * semaphores twice here. + */ + + for (i = 0; i < EEPROM_CHECKSUM_REG; i++) { + ret_val = e1000_read_eeprom_eerd(hw, i, 1, &nvm_data); + if (ret_val) { + e1000_put_hw_eeprom_semaphore(hw); + DEBUGOUT("EEPROM Read Error while updating checksum.\n"); + goto out; + } + checksum += nvm_data; + } + checksum = (uint16_t)EEPROM_SUM - checksum; + ret_val = e1000_write_eeprom_srwr(hw, EEPROM_CHECKSUM_REG, 1, + &checksum); + if (ret_val) { + e1000_put_hw_eeprom_semaphore(hw); + DEBUGOUT("EEPROM Write Error while updating checksum.\n"); + goto out; + } + + e1000_put_hw_eeprom_semaphore(hw); + + ret_val = e1000_update_flash_i210(hw); + } else { + ret_val = -E1000_ERR_SWFW_SYNC; + } + +out: + return ret_val; +} #endif /* CONFIG_E1000_NO_NVM */
/***************************************************************************** @@ -970,7 +1137,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
DEBUGFUNC();
- if (hw->mac_type != e1000_80003es2lan) + if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb) return E1000_SUCCESS;
while (timeout) { @@ -1044,7 +1211,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) if (!hw->eeprom_semaphore_present) return E1000_SUCCESS;
- if (hw->mac_type == e1000_80003es2lan) { + if (hw->mac_type == e1000_80003es2lan || hw->mac_type == e1000_igb) { /* Get the SW semaphore. */ if (e1000_get_software_semaphore(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index fcb7df0..6376de1 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -1242,6 +1242,9 @@ struct e1000_hw { #define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ #define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ #define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ +#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ +#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ +#define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ #define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */

On 08/11/2017 16:59, Martyn Welch wrote:
From: Hannu Lounento hannu.lounento@ge.com
Port functions for writing to EEPROM, updating the checksum and committing data to flash from the Linux kernel igb driver.
Functions were ported from Linux 4.8-rc2 (694d0d0bb20).
Signed-off-by: Hannu Lounento hannu.lounento@ge.com CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk
drivers/net/e1000.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++- drivers/net/e1000.h | 3 + 2 files changed, 172 insertions(+), 2 deletions(-)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 875682b..7aecdb9 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -150,6 +150,7 @@ static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#ifndef CONFIG_E1000_NO_NVM static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); +static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw); static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); @@ -862,6 +863,62 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, }
/******************************************************************************
- e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR
- @hw: pointer to the HW structure
- @offset: offset within the Shadow Ram to be written to
- @words: number of words to write
- @data: 16 bit word(s) to be written to the Shadow Ram
- Writes data to Shadow Ram at offset using EEWR register.
- If e1000_update_eeprom_checksum_i210 is not called after this function, the
- Shadow Ram will most likely contain an invalid checksum.
- *****************************************************************************/
+static int32_t e1000_write_eeprom_srwr(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data)
+{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- uint32_t i, k, eewr = 0;
- uint32_t attempts = 100000;
- int32_t ret_val = 0;
- /* A check for invalid values: offset too large, too many words,
* too many words for the offset, and not enough words.
*/
- if ((offset >= eeprom->word_size) ||
(words > (eeprom->word_size - offset)) || (words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
ret_val = -E1000_ERR_EEPROM;
goto out;
- }
- for (i = 0; i < words; i++) {
eewr = ((offset + i) << E1000_EEPROM_RW_ADDR_SHIFT)
| (data[i] << E1000_EEPROM_RW_REG_DATA) |
E1000_EEPROM_RW_REG_START;
E1000_WRITE_REG(hw, I210_EEWR, eewr);
for (k = 0; k < attempts; k++) {
if (E1000_EEPROM_RW_REG_DONE &
E1000_READ_REG(hw, I210_EEWR)) {
ret_val = 0;
break;
}
udelay(5);
}
if (ret_val) {
DEBUGOUT("Shadow RAM write EEWR timed out\n");
break;
}
- }
+out:
- return ret_val;
+}
+/******************************************************************************
- Verifies that the EEPROM has a valid checksum
- hw - Struct containing variables accessed by shared code
@@ -907,6 +964,116 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
return -E1000_ERR_EEPROM; }
+/******************************************************************************
- e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
- @hw: pointer to the HW structure
- *****************************************************************************/
+static int32_t e1000_pool_flash_update_done_i210(struct e1000_hw *hw) +{
- int32_t ret_val = -E1000_ERR_EEPROM;
- uint32_t i, reg;
- for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
reg = E1000_READ_REG(hw, EECD);
if (reg & E1000_EECD_FLUDONE_I210) {
ret_val = 0;
break;
}
udelay(5);
- }
- return ret_val;
+}
+/******************************************************************************
- e1000_update_flash_i210 - Commit EEPROM to the flash
- @hw: pointer to the HW structure
- *****************************************************************************/
+static int32_t e1000_update_flash_i210(struct e1000_hw *hw) +{
- int32_t ret_val = 0;
- uint32_t flup;
- ret_val = e1000_pool_flash_update_done_i210(hw);
- if (ret_val == -E1000_ERR_EEPROM) {
DEBUGOUT("Flash update time out\n");
goto out;
- }
- flup = E1000_READ_REG(hw, EECD) | E1000_EECD_FLUPD_I210;
- E1000_WRITE_REG(hw, EECD, flup);
- ret_val = e1000_pool_flash_update_done_i210(hw);
- if (ret_val)
DEBUGOUT("Flash update time out\n");
- else
DEBUGOUT("Flash update complete\n");
+out:
- return ret_val;
+}
+/******************************************************************************
- e1000_update_eeprom_checksum_i210 - Update EEPROM checksum
- @hw: pointer to the HW structure
- Updates the EEPROM checksum by reading/adding each word of the EEPROM
- up to the checksum. Then calculates the EEPROM checksum and writes the
- value to the EEPROM. Next commit EEPROM data onto the Flash.
- *****************************************************************************/
+static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw) +{
- int32_t ret_val = 0;
- uint16_t checksum = 0;
- uint16_t i, nvm_data;
- /* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
- ret_val = e1000_read_eeprom_eerd(hw, 0, 1, &nvm_data);
- if (ret_val) {
DEBUGOUT("EEPROM read failed\n");
goto out;
- }
- if (!(e1000_get_hw_eeprom_semaphore(hw))) {
/* Do not use hw->nvm.ops.write, hw->nvm.ops.read
* because we do not want to take the synchronization
* semaphores twice here.
*/
for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
ret_val = e1000_read_eeprom_eerd(hw, i, 1, &nvm_data);
if (ret_val) {
e1000_put_hw_eeprom_semaphore(hw);
DEBUGOUT("EEPROM Read Error while updating checksum.\n");
goto out;
}
checksum += nvm_data;
}
checksum = (uint16_t)EEPROM_SUM - checksum;
ret_val = e1000_write_eeprom_srwr(hw, EEPROM_CHECKSUM_REG, 1,
&checksum);
if (ret_val) {
e1000_put_hw_eeprom_semaphore(hw);
DEBUGOUT("EEPROM Write Error while updating checksum.\n");
goto out;
}
e1000_put_hw_eeprom_semaphore(hw);
ret_val = e1000_update_flash_i210(hw);
- } else {
ret_val = -E1000_ERR_SWFW_SYNC;
- }
+out:
- return ret_val;
+} #endif /* CONFIG_E1000_NO_NVM */
/***************************************************************************** @@ -970,7 +1137,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
DEBUGFUNC();
- if (hw->mac_type != e1000_80003es2lan)
if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb) return E1000_SUCCESS;
while (timeout) {
@@ -1044,7 +1211,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) if (!hw->eeprom_semaphore_present) return E1000_SUCCESS;
- if (hw->mac_type == e1000_80003es2lan) {
- if (hw->mac_type == e1000_80003es2lan || hw->mac_type == e1000_igb) { /* Get the SW semaphore. */ if (e1000_get_software_semaphore(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM;
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index fcb7df0..6376de1 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -1242,6 +1242,9 @@ struct e1000_hw { #define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ #define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ #define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ +#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ +#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ +#define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ #define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
Reviewed-by: Stefano Babic sbabic@denx.de
Best regards, Stefano

On Wed, Nov 8, 2017 at 9:59 AM, Martyn Welch martyn.welch@collabora.co.uk wrote:
From: Hannu Lounento hannu.lounento@ge.com
Port functions for writing to EEPROM, updating the checksum and committing data to flash from the Linux kernel igb driver.
Functions were ported from Linux 4.8-rc2 (694d0d0bb20).
Signed-off-by: Hannu Lounento hannu.lounento@ge.com CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk
Acked-by: Joe Hershberger joe.hershberger@ni.com

From: Hannu Lounento hannu.lounento@ge.com
Split the implementation of e1000_read_mac_addr into eeprom and register versions called by e1000_read_mac_addr.
This allows for calling e1000_read_mac_addr when MAC address is needed with no constraints where it is read from, and for calling the register and, especially, the eeprom version directly in order to specify where to read the address from.
Signed-off-by: Hannu Lounento hannu.lounento@ge.com CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- drivers/net/e1000.c | 81 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 18 deletions(-)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 7aecdb9..9a3e8f8 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -1311,33 +1311,21 @@ static bool e1000_is_second_port(struct e1000_hw *hw)
#ifndef CONFIG_E1000_NO_NVM /****************************************************************************** - * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the - * second function of dual function devices + * Reads the adapter's MAC address from the EEPROM * - * nic - Struct containing variables accessed by shared code + * hw - Struct containing variables accessed by shared code + * enetaddr - buffering where the MAC address will be stored *****************************************************************************/ -static int -e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6]) +static int e1000_read_mac_addr_from_eeprom(struct e1000_hw *hw, + unsigned char enetaddr[6]) { uint16_t offset; uint16_t eeprom_data; - uint32_t reg_data = 0; int i;
- DEBUGFUNC(); - for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { offset = i >> 1; - if (hw->mac_type == e1000_igb) { - /* i210 preloads MAC address into RAL/RAH registers */ - if (offset == 0) - reg_data = E1000_READ_REG_ARRAY(hw, RA, 0); - else if (offset == 1) - reg_data >>= 16; - else if (offset == 2) - reg_data = E1000_READ_REG_ARRAY(hw, RA, 1); - eeprom_data = reg_data & 0xffff; - } else if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { + if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -1345,6 +1333,63 @@ e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6]) enetaddr[i + 1] = (eeprom_data >> 8) & 0xff; }
+ return 0; +} + +/****************************************************************************** + * Reads the adapter's MAC address from the RAL/RAH registers + * + * hw - Struct containing variables accessed by shared code + * enetaddr - buffering where the MAC address will be stored + *****************************************************************************/ +static int e1000_read_mac_addr_from_regs(struct e1000_hw *hw, + unsigned char enetaddr[6]) +{ + uint16_t offset, tmp; + uint32_t reg_data = 0; + int i; + + if (hw->mac_type != e1000_igb) + return -E1000_ERR_MAC_TYPE; + + for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { + offset = i >> 1; + + if (offset == 0) + reg_data = E1000_READ_REG_ARRAY(hw, RA, 0); + else if (offset == 1) + reg_data >>= 16; + else if (offset == 2) + reg_data = E1000_READ_REG_ARRAY(hw, RA, 1); + tmp = reg_data & 0xffff; + + enetaddr[i] = tmp & 0xff; + enetaddr[i + 1] = (tmp >> 8) & 0xff; + } + + return 0; +} + +/****************************************************************************** + * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the + * second function of dual function devices + * + * hw - Struct containing variables accessed by shared code + * enetaddr - buffering where the MAC address will be stored + *****************************************************************************/ +static int e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6]) +{ + int ret_val; + + if (hw->mac_type == e1000_igb) { + /* i210 preloads MAC address into RAL/RAH registers */ + ret_val = e1000_read_mac_addr_from_regs(hw, enetaddr); + } else { + ret_val = e1000_read_mac_addr_from_eeprom(hw, enetaddr); + } + if (ret_val) + return ret_val; + /* Invert the last bit if this is the second device */ if (e1000_is_second_port(hw)) enetaddr[5] ^= 1;

From: Hannu Lounento hannu.lounento@ge.com
Implement programming MAC address to the hardware, i.e. external flash seen as EEPROM.
MAC address is only written if it differs from what is already stored in flash or if reading the current MAC address fails.
Signed-off-by: Hannu Lounento hannu.lounento@ge.com CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- drivers/net/e1000.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 9a3e8f8..d0028fc 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -5647,6 +5647,45 @@ e1000_poll(struct eth_device *nic) return len ? 1 : 0; }
+static int e1000_write_hwaddr(struct eth_device *dev) +{ +#ifndef CONFIG_E1000_NO_NVM + unsigned char *mac = dev->enetaddr; + unsigned char current_mac[6]; + struct e1000_hw *hw = dev->priv; + uint16_t data[3]; + int ret_val, i; + + DEBUGOUT("%s: mac=%pM\n", __func__, mac); + + memset(current_mac, 0, 6); + + /* Read from EEPROM, not from registers, to make sure + * the address is persistently configured + */ + ret_val = e1000_read_mac_addr_from_eeprom(hw, current_mac); + DEBUGOUT("%s: current mac=%pM\n", __func__, current_mac); + + /* Only write to EEPROM if the given address is different or + * reading the current address failed + */ + if (!ret_val && memcmp(current_mac, mac, 6) == 0) + return 0; + + for (i = 0; i < 3; ++i) + data[i] = mac[i * 2 + 1] << 8 | mac[i * 2]; + + ret_val = e1000_write_eeprom_srwr(hw, 0x0, 3, data); + + if (!ret_val) + ret_val = e1000_update_eeprom_checksum_i210(hw); + + return ret_val; +#else + return 0; +#endif +} + /************************************************************************** PROBE - Look for an adapter, this routine's visible to the outside You should omit the last argument struct pci_device * for a non-PCI NIC @@ -5696,6 +5735,7 @@ e1000_initialize(bd_t * bis) nic->recv = e1000_poll; nic->send = e1000_transmit; nic->halt = e1000_disable; + nic->write_hwaddr = e1000_write_hwaddr; eth_register(nic); }

From: Nandor Han nandor.han@ge.com
Add a new driver for RX8010SJ rtc chip. The driver implements both formats of U-Boot driver model.
Signed-off-by: Nandor Han nandor.han@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- drivers/rtc/Kconfig | 6 + drivers/rtc/Makefile | 1 + drivers/rtc/rx8010sj.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 385 insertions(+) create mode 100644 drivers/rtc/rx8010sj.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2964bb2..95ac031 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -30,6 +30,12 @@ config RTC_DS1307 Support for Dallas Semiconductor (now Maxim) DS1307 and DS1338/9 and compatible Real Time Clock devices.
+config RTC_RX8010SJ + bool "Enable RX8010SJ driver" + depends on DM_RTC + help + Support for Epson RX8010SJ Real Time Clock devices. + config RTC_S35392A bool "Enable S35392A driver" select BITREVERSE diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7a8f97a..9723fb7 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o obj-$(CONFIG_RTC_RV3029) += rv3029.o obj-$(CONFIG_RTC_RX8025) += rx8025.o +obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o obj-$(CONFIG_RTC_S35392A) += s35392a.o obj-$(CONFIG_SANDBOX) += sandbox_rtc.o diff --git a/drivers/rtc/rx8010sj.c b/drivers/rtc/rx8010sj.c new file mode 100644 index 0000000..81560e1 --- /dev/null +++ b/drivers/rtc/rx8010sj.c @@ -0,0 +1,378 @@ +/* + * Epson RX8010 RTC driver. + * + * Copyright (c) 2017, General Electric Company + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see http://www.gnu.org/licenses/. + */ + +#include <command.h> +#include <common.h> +#include <dm.h> +#include <i2c.h> +#include <rtc.h> + +/*---------------------------------------------------------------------*/ +/* #undef DEBUG_RTC */ + +#ifdef DEBUG_RTC +#define DEBUGR(fmt, args...) printf(fmt, ##args) +#else +#define DEBUGR(fmt, args...) +#endif +/*---------------------------------------------------------------------*/ + +#ifndef CONFIG_SYS_I2C_RTC_ADDR +# define CONFIG_SYS_I2C_RTC_ADDR 0x32 +#endif + +/* + * RTC register addresses + */ +#define RX8010_SEC 0x10 +#define RX8010_MIN 0x11 +#define RX8010_HOUR 0x12 +#define RX8010_WDAY 0x13 +#define RX8010_MDAY 0x14 +#define RX8010_MONTH 0x15 +#define RX8010_YEAR 0x16 +#define RX8010_YEAR 0x16 +#define RX8010_RESV17 0x17 +#define RX8010_ALMIN 0x18 +#define RX8010_ALHOUR 0x19 +#define RX8010_ALWDAY 0x1A +#define RX8010_TCOUNT0 0x1B +#define RX8010_TCOUNT1 0x1C +#define RX8010_EXT 0x1D +#define RX8010_FLAG 0x1E +#define RX8010_CTRL 0x1F +/* 0x20 to 0x2F are user registers */ +#define RX8010_RESV30 0x30 +#define RX8010_RESV31 0x32 +#define RX8010_IRQ 0x32 + +#define RX8010_EXT_WADA BIT(3) + +#define RX8010_FLAG_VLF BIT(1) +#define RX8010_FLAG_AF BIT(3) +#define RX8010_FLAG_TF BIT(4) +#define RX8010_FLAG_UF BIT(5) + +#define RX8010_CTRL_AIE BIT(3) +#define RX8010_CTRL_UIE BIT(5) +#define RX8010_CTRL_STOP BIT(6) +#define RX8010_CTRL_TEST BIT(7) + +#define RX8010_ALARM_AE BIT(7) + +#ifdef CONFIG_DM_RTC + +#define DEV_TYPE struct udevice + +#else + +/* Local udevice */ +struct ludevice { + u8 chip; +}; + +#define DEV_TYPE struct ludevice + +#endif + +static int rx8010sj_rtc_read8(DEV_TYPE *dev, unsigned int reg) +{ + u8 val; + int ret; + +#ifdef CONFIG_DM_RTC + ret = dm_i2c_read(dev, reg, &val, sizeof(val)); +#else + ret = i2c_read(dev->chip, reg, 1, &val, 1); +#endif + + return ret < 0 ? ret : val; +} + +static int rx8010sj_rtc_write8(DEV_TYPE *dev, unsigned int reg, int val) +{ + int ret; + u8 lval = val; + +#ifdef CONFIG_DM_RTC + ret = dm_i2c_write(dev, reg, &lval, 1); +#else + ret = i2c_write(dev->chip, reg, 1, &lval, 1); +#endif + + return ret < 0 ? ret : 0; +} + +static int validate_time(const struct rtc_time *tm) +{ + if ((tm->tm_year < 2000) || (tm->tm_year > 2099)) + return -EINVAL; + + if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) + return -EINVAL; + + if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) + return -EINVAL; + + if ((tm->tm_wday < 0) || (tm->tm_wday > 6)) + return -EINVAL; + + if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) + return -EINVAL; + + if ((tm->tm_min < 0) || (tm->tm_min > 59)) + return -EINVAL; + + if ((tm->tm_sec < 0) || (tm->tm_sec > 59)) + return -EINVAL; + + return 0; +} + +void rx8010sj_rtc_init(DEV_TYPE *dev) +{ + u8 ctrl[2]; + int need_clear = 0, ret = 0; + + /* Initialize reserved registers as specified in datasheet */ + ret = rx8010sj_rtc_write8(dev, RX8010_RESV17, 0xD8); + if (ret < 0) + goto error; + + ret = rx8010sj_rtc_write8(dev, RX8010_RESV30, 0x00); + if (ret < 0) + goto error; + + ret = rx8010sj_rtc_write8(dev, RX8010_RESV31, 0x08); + if (ret < 0) + goto error; + + ret = rx8010sj_rtc_write8(dev, RX8010_IRQ, 0x00); + if (ret < 0) + goto error; + + for (int i = 0; i < 2; i++) { + ret = rx8010sj_rtc_read8(dev, RX8010_FLAG + i); + if (ret < 0) + goto error; + + ctrl[i] = ret; + } + + if (ctrl[0] & RX8010_FLAG_VLF) + printf("RTC low voltage detected\n"); + + if (ctrl[0] & RX8010_FLAG_AF) { + printf("Alarm was detected\n"); + need_clear = 1; + } + + if (ctrl[0] & RX8010_FLAG_TF) + need_clear = 1; + + if (ctrl[0] & RX8010_FLAG_UF) + need_clear = 1; + + if (need_clear) { + ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF); + ret = rx8010sj_rtc_write8(dev, RX8010_FLAG, ctrl[0]); + if (ret < 0) + goto error; + } + + return; + +error: + printf("Error rtc init.\n"); +} + +/* Get the current time from the RTC */ +static int rx8010sj_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp) +{ + u8 date[7]; + int flagreg; + int ret; + + flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG); + if (flagreg < 0) { + DEBUGR("Error reading from RTC. err: %d\n", flagreg); + return -EIO; + } + + if (flagreg & RX8010_FLAG_VLF) { + DEBUGR("RTC low voltage detected\n"); + return -EINVAL; + } + + for (int i = 0; i < 7; i++) { + ret = rx8010sj_rtc_read8(dev, RX8010_SEC + i); + if (ret < 0) { + DEBUGR("Error reading from RTC. err: %d\n", ret); + return -EIO; + } + date[i] = ret; + } + + tmp->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f); + tmp->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f); + tmp->tm_hour = bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f); + tmp->tm_mday = bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f); + tmp->tm_mon = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f); + tmp->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 2000; + tmp->tm_wday = 0; + tmp->tm_yday = 0; + tmp->tm_isdst = 0; + + DEBUGR("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + return 0; +} + +/* Set the RTC */ +static int rx8010sj_rtc_set(DEV_TYPE *dev, const struct rtc_time *tm) +{ + u8 date[7]; + int ctrl, flagreg; + int ret; + + ret = validate_time(tm); + if (ret < 0) + return -EINVAL; + + /* set STOP bit before changing clock/calendar */ + ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL); + if (ctrl < 0) + return ctrl; + ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl | RX8010_CTRL_STOP); + if (ret < 0) + return ret; + + date[RX8010_SEC - RX8010_SEC] = bin2bcd(tm->tm_sec); + date[RX8010_MIN - RX8010_SEC] = bin2bcd(tm->tm_min); + date[RX8010_HOUR - RX8010_SEC] = bin2bcd(tm->tm_hour); + date[RX8010_MDAY - RX8010_SEC] = bin2bcd(tm->tm_mday); + date[RX8010_MONTH - RX8010_SEC] = bin2bcd(tm->tm_mon); + date[RX8010_YEAR - RX8010_SEC] = bin2bcd(tm->tm_year - 2000); + date[RX8010_WDAY - RX8010_SEC] = bin2bcd(tm->tm_wday); + + for (int i = 0; i < 7; i++) { + ret = rx8010sj_rtc_write8(dev, RX8010_SEC + i, date[i]); + if (ret < 0) { + DEBUGR("Error writing to RTC. err: %d\n", ret); + return -EIO; + } + } + + /* clear STOP bit after changing clock/calendar */ + ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL); + if (ctrl < 0) + return ctrl; + + ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl & ~RX8010_CTRL_STOP); + if (ret < 0) + return ret; + + flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG); + if (flagreg < 0) + return flagreg; + + if (flagreg & RX8010_FLAG_VLF) + ret = rx8010sj_rtc_write8(dev, RX8010_FLAG, + flagreg & ~RX8010_FLAG_VLF); + + return 0; +} + +/* Reset the RTC. */ +static int rx8010sj_rtc_reset(DEV_TYPE *dev) +{ + /* Not needed */ + return 0; +} + +#ifndef CONFIG_DM_RTC + +int rtc_get(struct rtc_time *tm) +{ + struct ludevice dev = { + .chip = CONFIG_SYS_I2C_RTC_ADDR, + }; + + return rx8010sj_rtc_get(&dev, tm); +} + +int rtc_set(struct rtc_time *tm) +{ + struct ludevice dev = { + .chip = CONFIG_SYS_I2C_RTC_ADDR, + }; + + return rx8010sj_rtc_set(&dev, tm); +} + +void rtc_reset(void) +{ + struct ludevice dev = { + .chip = CONFIG_SYS_I2C_RTC_ADDR, + }; + + rx8010sj_rtc_reset(&dev); +} + +void rtc_init(void) +{ + struct ludevice dev = { + .chip = CONFIG_SYS_I2C_RTC_ADDR, + }; + + rx8010sj_rtc_init(&dev); +} + +#else + +static int rx8010sj_probe(struct udevice *dev) +{ + rx8010sj_rtc_init(&dev); + + return 0; +} + +static const struct rtc_ops rx8010sj_rtc_ops = { + .get = rx8010sj_rtc_get, + .set = rx8010sj_rtc_set, + .read8 = rx8010sj_rtc_read8, + .write8 = rx8010sj_rtc_write8, + .reset = rx8010sj_rtc_reset, +}; + +static const struct udevice_id rx8010sj_rtc_ids[] = { + { .compatible = "epson,rx8010sj-rtc" }, + { } +}; + +U_BOOT_DRIVER(rx8010sj_rtc) = { + .name = "rx8010sj_rtc", + .id = UCLASS_RTC, + .probe = rx8010sj_probe, + .of_match = rx8010sj_rtc_ids, + .ops = &rx8010sj_rtc_ops, +}; + +#endif

The change in i2c configuration added to support access to the VPD has inadvertantly caused access to i2c buses 1 & 2 to be lost. This has resulted in the configuration for the PMIC to be attempted on the wrong bus and thus isn't taking effect.
Add the required configuration to return access to buses 1 & 2. In order to ensure that any users of the bus numbering prior to addition in VPD patches work, add buses before configuration related to mux on bus 0 and tweak VPD bus usage to fit new numbering scheme.
Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 2 +- include/configs/ge_bx50v3.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index 37de990..cb4deb0 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -37,7 +37,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif
#ifndef CONFIG_SYS_I2C_EEPROM_BUS -#define CONFIG_SYS_I2C_EEPROM_BUS 2 +#define CONFIG_SYS_I2C_EEPROM_BUS 4 #endif
#define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 33f5101..eb8f923 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -299,9 +299,11 @@ #define CONFIG_SYS_I2C_MXC_I2C2 #define CONFIG_SYS_I2C_MXC_I2C3
-#define CONFIG_SYS_NUM_I2C_BUSES 9 +#define CONFIG_SYS_NUM_I2C_BUSES 11 #define CONFIG_SYS_I2C_MAX_HOPS 1 #define CONFIG_SYS_I2C_BUSES { {0, {I2C_NULL_HOP} }, \ + {1, {I2C_NULL_HOP} }, \ + {2, {I2C_NULL_HOP} }, \ {0, {{I2C_MUX_PCA9547, 0x70, 0} } }, \ {0, {{I2C_MUX_PCA9547, 0x70, 1} } }, \ {0, {{I2C_MUX_PCA9547, 0x70, 2} } }, \

From: Ian Ray ian.ray@ge.com
Modify b450v3, b650v3 and b850v3 defconfigs to enable the network devices found in these products.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- configs/ge_b450v3_defconfig | 6 +++++- configs/ge_b650v3_defconfig | 6 +++++- configs/ge_b850v3_defconfig | 6 +++++- include/configs/ge_bx50v3.h | 4 ++-- 4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/configs/ge_b450v3_defconfig b/configs/ge_b450v3_defconfig index 43a6c12..f95c3cd 100644 --- a/configs/ge_b450v3_defconfig +++ b/configs/ge_b450v3_defconfig @@ -15,7 +15,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y -# CONFIG_CMD_NET is not set # CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y CONFIG_CMD_EXT2=y @@ -28,3 +27,8 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_OF_LIBFDT=y # CONFIG_EFI_LOADER is not set +CONFIG_NETDEVICES=y +CONFIG_CMD_NET=y +CONFIG_CMD_PCI=y +CONFIG_E1000=y +CONFIG_CMD_E1000=y diff --git a/configs/ge_b650v3_defconfig b/configs/ge_b650v3_defconfig index 4e22e95..3af0630 100644 --- a/configs/ge_b650v3_defconfig +++ b/configs/ge_b650v3_defconfig @@ -15,7 +15,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y -# CONFIG_CMD_NET is not set # CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y CONFIG_CMD_EXT2=y @@ -28,3 +27,8 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_OF_LIBFDT=y # CONFIG_EFI_LOADER is not set +CONFIG_NETDEVICES=y +CONFIG_CMD_NET=y +CONFIG_CMD_PCI=y +CONFIG_E1000=y +CONFIG_CMD_E1000=y diff --git a/configs/ge_b850v3_defconfig b/configs/ge_b850v3_defconfig index cb5899d..5f008ea 100644 --- a/configs/ge_b850v3_defconfig +++ b/configs/ge_b850v3_defconfig @@ -15,7 +15,6 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y -# CONFIG_CMD_NET is not set # CONFIG_CMD_NFS is not set CONFIG_CMD_CACHE=y CONFIG_CMD_EXT2=y @@ -28,3 +27,8 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_OF_LIBFDT=y # CONFIG_EFI_LOADER is not set +CONFIG_NETDEVICES=y +CONFIG_CMD_NET=y +CONFIG_CMD_PCI=y +CONFIG_E1000=y +CONFIG_CMD_E1000=y diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index eb8f923..4526d2f 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -284,12 +284,12 @@ #define CONFIG_PWM_IMX #define CONFIG_IMX6_PWM_PER_CLK 66000000
-#ifdef CONFIG_CMD_PCI +#define CONFIG_PCI +#define CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW #define CONFIG_PCIE_IMX #define CONFIG_PCIE_IMX_PERST_GPIO IMX_GPIO_NR(7, 12) #define CONFIG_PCIE_IMX_POWER_GPIO IMX_GPIO_NR(1, 5) -#endif
/* I2C Configs */ #define CONFIG_SYS_I2C

Instead of programming the hardware directly in the board implementation, follow the flow documented in doc/README.enetaddr: set the enet[0-9]*addr environment variable and let the driver program the hardware.
This avoids duplicating the implementation as it already exists in the driver (drivers/net/fec_mxc.c: fec_set_hwaddr).
The mapping from the driver's index to the environment variable's name is documented in README: Note for Redundant Ethernet Interfaces. It is assumed that eth_devices for the controllers on the board are always indexed in the same order, i.e. FEC always has the index 2.
The FEC driver does *not* set the flag Set MAC Address on Transmit (bit set_eth0_mac_address used to do but this is unnecessary as the Linux networking stack fills in the MAC address.
Signed-off-by: Hannu Lounento hannu.lounento@ge.com Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 79 ++++++++++++++++++++++----------------------- include/configs/ge_bx50v3.h | 2 ++ 2 files changed, 41 insertions(+), 40 deletions(-)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index cb4deb0..0468dcf 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -19,6 +19,7 @@ #include <mmc.h> #include <fsl_esdhc.h> #include <miiphy.h> +#include <net.h> #include <netdev.h> #include <asm/arch/mxc_hdmi.h> #include <asm/arch/crm_regs.h> @@ -546,63 +547,54 @@ int overwrite_console(void) #define VPD_PRODUCT_B850 1 #define VPD_PRODUCT_B650 2 #define VPD_PRODUCT_B450 3 +#define VPD_HAS_MAC1 0x1 +#define VPD_MAC_ADDRESS_LENGTH 6
struct vpd_cache { - uint8_t product_id; - uint8_t macbits; - unsigned char mac1[6]; + u8 product_id; + u8 has; + unsigned char mac1[VPD_MAC_ADDRESS_LENGTH]; };
/* * 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) +static int vpd_callback(void *userdata, u8 id, u8 version, u8 type, + size_t size, u8 const *data) { struct vpd_cache *vpd = (struct vpd_cache *)userdata;
- if ( id == VPD_BLOCK_HWID - && version == 1 - && type != VPD_TYPE_INVALID - && size >= 1) { + 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); + } else if (id == VPD_BLOCK_NETWORK && version == 1 && + type != VPD_TYPE_INVALID) { + if (size >= 6) { + vpd->has |= VPD_HAS_MAC1; + memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH); + } }
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); - } + int fec_index = -1; + + switch (vpd->product_id) { + case VPD_PRODUCT_B450: + /* fall thru */ + case VPD_PRODUCT_B650: + fec_index = 1; + break; + case VPD_PRODUCT_B850: + fec_index = 2; + break; } + + if (fec_index >= 0 && (vpd->has & VPD_HAS_MAC1)) + eth_env_set_enetaddr_by_index("eth", fec_index, vpd->mac1); }
static int read_vpd(uint eeprom_bus) @@ -694,8 +686,6 @@ 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; }
@@ -761,6 +751,8 @@ void pmic_init(void)
int board_late_init(void) { + read_vpd(CONFIG_SYS_I2C_EEPROM_BUS); + #ifdef CONFIG_CMD_BMODE add_board_boot_modes(board_boot_modes); #endif @@ -788,6 +780,13 @@ int board_late_init(void) return 0; }
+int last_stage_init(void) +{ + env_set("ethaddr", NULL); + + return 0; +} + int checkboard(void) { printf("BOARD: %s\n", CONFIG_BOARD_NAME); diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 4526d2f..94e406c 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -44,6 +44,8 @@ #define CONFIG_REVISION_TAG #define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M)
+#define CONFIG_LAST_STAGE_INIT + #define CONFIG_MXC_GPIO #define CONFIG_MXC_UART

From: Hannu Lounento hannu.lounento@ge.com
There are two I210s on the b850v3 and one on the b450v3 and b650v3. One is connected to Marvell 88e6240 which is already programmed.
Follow the flow documented in doc/README.enetaddr: set the enet[0-9]*addr environment variable and let the driver program the hardware.
The mapping from the driver's index to the environment variable's name is documented in README: Note for Redundant Ethernet Interfaces. It is assumed that eth_devices for the controllers on the board are always indexed in the same order.
The environment variables are removed after programming the hardware because the variables seem to influence MAC addresses also after U-Boot. Specifically the MAC address of FEC (MC interface) would be incorrectly set: 'ethaddr', which maps to the first I210 chip and is set to I210's default address read from the driver by eth_write_hwaddr in eth_legacy.c because the variable is undefined (not set even by bx50v3.c), would result in the eth0 interface's MAC address to be set to I210's default address.
Signed-off-by: Hannu Lounento hannu.lounento@ge.com Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index 0468dcf..07b4298 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -30,6 +30,7 @@ #include <pwm.h> #include <stdlib.h> #include "../common/vpd_reader.h" +#include "../../../drivers/net/e1000.h" DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_SYS_I2C_EEPROM_ADDR @@ -548,12 +549,14 @@ int overwrite_console(void) #define VPD_PRODUCT_B650 2 #define VPD_PRODUCT_B450 3 #define VPD_HAS_MAC1 0x1 +#define VPD_HAS_MAC2 0x2 #define VPD_MAC_ADDRESS_LENGTH 6
struct vpd_cache { u8 product_id; u8 has; unsigned char mac1[VPD_MAC_ADDRESS_LENGTH]; + unsigned char mac2[VPD_MAC_ADDRESS_LENGTH]; };
/* @@ -573,6 +576,10 @@ static int vpd_callback(void *userdata, u8 id, u8 version, u8 type, vpd->has |= VPD_HAS_MAC1; memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH); } + if (size >= 12) { + vpd->has |= VPD_HAS_MAC2; + memcpy(vpd->mac2, data + 6, VPD_MAC_ADDRESS_LENGTH); + } }
return 0; @@ -581,20 +588,26 @@ static int vpd_callback(void *userdata, u8 id, u8 version, u8 type, static void process_vpd(struct vpd_cache *vpd) { int fec_index = -1; + int i210_index = -1;
switch (vpd->product_id) { case VPD_PRODUCT_B450: /* fall thru */ case VPD_PRODUCT_B650: + i210_index = 0; fec_index = 1; break; case VPD_PRODUCT_B850: + i210_index = 1; fec_index = 2; break; }
if (fec_index >= 0 && (vpd->has & VPD_HAS_MAC1)) eth_env_set_enetaddr_by_index("eth", fec_index, vpd->mac1); + + if (i210_index >= 0 && (vpd->has & VPD_HAS_MAC2)) + eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2); }
static int read_vpd(uint eeprom_bus) @@ -633,6 +646,8 @@ int board_eth_init(bd_t *bis) setup_iomux_enet(); setup_pcie();
+ e1000_initialize(bis); + return cpu_eth_init(bis); }
@@ -780,9 +795,29 @@ int board_late_init(void) return 0; }
+/* + * Removes the 'eth[0-9]*addr' environment variable with the given index + * + * @param index [in] the index of the eth_device whose variable is to be removed + */ +static void remove_ethaddr_env_var(int index) +{ + char env_var_name[9]; + + sprintf(env_var_name, index == 0 ? "ethaddr" : "eth%daddr", index); + env_set(env_var_name, NULL); +} + int last_stage_init(void) { - env_set("ethaddr", NULL); + int i; + + /* + * Remove first three ethaddr which may have been created by + * function process_vpd(). + */ + for (i = 0; i < 3; ++i) + remove_ethaddr_env_var(i);
return 0; }

Enable the hardware watchdog on bx50v3 to cause it to reset in the event the board hangs.
Configure GPIO_9 pin as WDOG1_B so that a watchdog timeout results in a full system reset.
The watchdog is used and reconfigured by systemd approximately 1.7 seconds into boot. Adding a few seconds for U-Boot and a few more seconds as a safety margin.
Note that the PCIe controller is _not_ put back into a safe state prior to board reset. This is a problem if board reset is implemented as CPU reset.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 1 + include/configs/ge_bx50v3.h | 4 ++++ 2 files changed, 5 insertions(+)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index 07b4298..48c26e0 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -659,6 +659,7 @@ static iomux_v3_cfg_t const misc_pads[] = { MX6_PAD_EIM_OE__GPIO2_IO25 | MUX_PAD_CTRL(NC_PAD_CTRL), MX6_PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NC_PAD_CTRL), MX6_PAD_GPIO_1__GPIO1_IO01 | MUX_PAD_CTRL(NC_PAD_CTRL), + MX6_PAD_GPIO_9__WDOG1_B | MUX_PAD_CTRL(NC_PAD_CTRL), }; #define SUS_S3_OUT IMX_GPIO_NR(4, 11) #define WIFI_EN IMX_GPIO_NR(6, 14) diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 94e406c..162e915 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -44,6 +44,10 @@ #define CONFIG_REVISION_TAG #define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M)
+#define CONFIG_HW_WATCHDOG +#define CONFIG_IMX_WATCHDOG +#define CONFIG_WATCHDOG_TIMEOUT_MSECS 6000 + #define CONFIG_LAST_STAGE_INIT
#define CONFIG_MXC_GPIO

From: Ian Ray ian.ray@ge.com
Modify configuration to support FIT. Set variable `confidx' from VPD, in order to load the correct device tree. Modify/simplify U-Boot environment to support loading FIT image.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 12 +++++++ configs/ge_b450v3_defconfig | 1 + configs/ge_b650v3_defconfig | 1 + configs/ge_b850v3_defconfig | 1 + include/configs/ge_bx50v3.h | 88 +++------------------------------------------ 5 files changed, 20 insertions(+), 83 deletions(-)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index 48c26e0..e35afa03 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -592,6 +592,18 @@ static void process_vpd(struct vpd_cache *vpd)
switch (vpd->product_id) { case VPD_PRODUCT_B450: + env_set("confidx", "1"); + break; + case VPD_PRODUCT_B650: + env_set("confidx", "2"); + break; + case VPD_PRODUCT_B850: + env_set("confidx", "3"); + break; + } + + switch (vpd->product_id) { + case VPD_PRODUCT_B450: /* fall thru */ case VPD_PRODUCT_B650: i210_index = 0; diff --git a/configs/ge_b450v3_defconfig b/configs/ge_b450v3_defconfig index f95c3cd..76cc407 100644 --- a/configs/ge_b450v3_defconfig +++ b/configs/ge_b450v3_defconfig @@ -32,3 +32,4 @@ CONFIG_CMD_NET=y CONFIG_CMD_PCI=y CONFIG_E1000=y CONFIG_CMD_E1000=y +CONFIG_FIT=y diff --git a/configs/ge_b650v3_defconfig b/configs/ge_b650v3_defconfig index 3af0630..e82abe2 100644 --- a/configs/ge_b650v3_defconfig +++ b/configs/ge_b650v3_defconfig @@ -32,3 +32,4 @@ CONFIG_CMD_NET=y CONFIG_CMD_PCI=y CONFIG_E1000=y CONFIG_CMD_E1000=y +CONFIG_FIT=y diff --git a/configs/ge_b850v3_defconfig b/configs/ge_b850v3_defconfig index 5f008ea..4f9d77c 100644 --- a/configs/ge_b850v3_defconfig +++ b/configs/ge_b850v3_defconfig @@ -32,3 +32,4 @@ CONFIG_CMD_NET=y CONFIG_CMD_PCI=y CONFIG_E1000=y CONFIG_CMD_E1000=y +CONFIG_FIT=y diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 162e915..55719dd 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -112,95 +112,24 @@
#define CONFIG_EXTRA_ENV_SETTINGS \ "script=boot.scr\0" \ - "image=/boot/uImage\0" \ - "uboot=u-boot.imx\0" \ - "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ - "fdt_addr=0x18000000\0" \ - "boot_fdt=yes\0" \ - "ip_dyn=yes\0" \ + "image=/boot/fitImage\0" \ "console=" CONSOLE_DEV "\0" \ "fdt_high=0xffffffff\0" \ - "initrd_high=0xffffffff\0" \ "sddev=0\0" \ "emmcdev=1\0" \ "partnum=1\0" \ - "update_sd_firmware=" \ - "if test ${ip_dyn} = yes; then " \ - "setenv get_cmd dhcp; " \ - "else " \ - "setenv get_cmd tftp; " \ - "fi; " \ - "if mmc dev ${mmcdev}; then " \ - "if ${get_cmd} ${update_sd_firmware_filename}; then " \ - "setexpr fw_sz ${filesize} / 0x200; " \ - "setexpr fw_sz ${fw_sz} + 1; " \ - "mmc write ${loadaddr} 0x2 ${fw_sz}; " \ - "fi; " \ - "fi\0" \ - "update_sf_uboot=" \ - "if tftp $loadaddr $uboot; then " \ - "sf probe; " \ - "sf erase 0 0xC0000; " \ - "sf write $loadaddr 0x400 $filesize; " \ - "echo 'U-Boot upgraded. Please reset'; " \ - "fi\0" \ "setargs=setenv bootargs console=${console},${baudrate} " \ "root=/dev/${rootdev} rw rootwait cma=128M " \ BX50V3_BOOTARGS_EXTRA "\0" \ - "loadbootscript=" \ - "ext2load ${dev} ${devnum}:${partnum} ${loadaddr} ${script};\0" \ - "bootscript=echo Running bootscript from ${dev}:${devnum}:${partnum};" \ - " source\0" \ "loadimage=" \ "ext2load ${dev} ${devnum}:${partnum} ${loadaddr} ${image}\0" \ - "loadfdt=ext2load ${dev} ${devnum}:${partnum} ${fdt_addr} ${fdt_file}\0" \ "tryboot=" \ - "if run loadbootscript; then " \ - "run bootscript; " \ - "else " \ - "if run loadimage; then " \ - "run doboot; " \ - "fi; " \ + "if run loadimage; then " \ + "run doboot; " \ "fi;\0" \ "doboot=echo Booting from ${dev}:${devnum}:${partnum} ...; " \ "run setargs; " \ - "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \ - "if run loadfdt; then " \ - "bootm ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "if test ${boot_fdt} = try; then " \ - "bootm; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "fi; " \ - "else " \ - "bootm; " \ - "fi;\0" \ - "netargs=setenv bootargs console=${console},${baudrate} " \ - "root=/dev/nfs " \ - "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \ - "netboot=echo Booting from net ...; " \ - "run netargs; " \ - "if test ${ip_dyn} = yes; then " \ - "setenv get_cmd dhcp; " \ - "else " \ - "setenv get_cmd tftp; " \ - "fi; " \ - "${get_cmd} ${image}; " \ - "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \ - "if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \ - "bootm ${loadaddr} - ${fdt_addr}; " \ - "else " \ - "if test ${boot_fdt} = try; then " \ - "bootm; " \ - "else " \ - "echo WARN: Cannot load the DT; " \ - "fi; " \ - "fi; " \ - "else " \ - "bootm; " \ - "fi;\0" \ + "bootm ${loadaddr}#conf@${confidx};\0 " \
#define CONFIG_MMCBOOTCOMMAND \ "setenv dev mmc; " \ @@ -218,14 +147,7 @@ "fi; " \
#define CONFIG_USBBOOTCOMMAND \ - "usb start; " \ - "setenv dev usb; " \ - "setenv devnum 0; " \ - "setenv rootdev sda${partnum}; " \ - "run tryboot; " \ - \ - CONFIG_MMCBOOTCOMMAND \ - "bmode usb; " \ + "echo Unsupported; " \
#ifdef CONFIG_CMD_USB #define CONFIG_BOOTCOMMAND CONFIG_USBBOOTCOMMAND

From: Ian Ray ian.ray@ge.com
Read boot script from shared partition, if available.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- include/configs/ge_bx50v3.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 55719dd..ac69e85 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -133,15 +133,15 @@
#define CONFIG_MMCBOOTCOMMAND \ "setenv dev mmc; " \ - "setenv rootdev mmcblk0p${partnum}; " \ + "setenv devnum ${emmcdev}; " \ \ - "setenv devnum ${sddev}; " \ - "if mmc dev ${devnum}; then " \ - "run tryboot; " \ - "setenv rootdev mmcblk1p${partnum}; " \ + "if ext2load ${dev} ${devnum}:5 0x7000A000 /boot/active/boot.img ; " \ + "then " \ + "source 0x7000A000; " \ "fi; " \ \ - "setenv devnum ${emmcdev}; " \ + "setenv rootdev mmcblk0p${partnum}; " \ + \ "if mmc dev ${devnum}; then " \ "run tryboot; " \ "fi; " \

From: Ian Ray ian.ray@ge.com
Enable bootcount using an EXT file.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- include/configs/ge_bx50v3.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index ac69e85..ee5f6ab 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -112,6 +112,7 @@
#define CONFIG_EXTRA_ENV_SETTINGS \ "script=boot.scr\0" \ + "bootlimit=10\0" \ "image=/boot/fitImage\0" \ "console=" CONSOLE_DEV "\0" \ "fdt_high=0xffffffff\0" \ @@ -244,4 +245,11 @@
#define CONFIG_BCH
+#define CONFIG_BOOTCOUNT_LIMIT +#define CONFIG_BOOTCOUNT_EXT +#define CONFIG_SYS_BOOTCOUNT_EXT_INTERFACE "mmc" +#define CONFIG_SYS_BOOTCOUNT_EXT_DEVPART "1:5" +#define CONFIG_SYS_BOOTCOUNT_EXT_NAME "/boot/failures" +#define CONFIG_SYS_BOOTCOUNT_ADDR 0x7000A000 + #endif /* __GE_BX50V3_CONFIG_H */

From: Hannu Lounento hannu.lounento@ge.com
Change the kernel command line to mount the root filesystem read-only in order to be able to run filesystem check on it on boot.
Signed-off-by: Hannu Lounento hannu.lounento@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- include/configs/ge_bx50v3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index ee5f6ab..d15470f 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -120,7 +120,7 @@ "emmcdev=1\0" \ "partnum=1\0" \ "setargs=setenv bootargs console=${console},${baudrate} " \ - "root=/dev/${rootdev} rw rootwait cma=128M " \ + "root=/dev/${rootdev} ro rootwait cma=128M " \ BX50V3_BOOTARGS_EXTRA "\0" \ "loadimage=" \ "ext2load ${dev} ${devnum}:${partnum} ${loadaddr} ${image}\0" \

From: Ian Ray ian.ray@ge.com
The exact definition of a successful boot is defined by user-space. Determine the boot partition automatically. A partition is selected if file `/boot/bootcause/firstboot' exists (meaning that the partition has freshly installed software) OR if file `/boot/fitImage' exists.
When userspace determines that new software was successfully installed, it must (1) delete `/boot/fitImage' on the _inactive_ partition and (2) remove `/boot/bootcause/firstboot'.
Enable video, but do not display logos or other version information. Silence kernel console logging by default.
Print a message to VGA screen in case of boot failure and reset bootcount to allow the user to attempt boot again.
Signed-off-by: Ian Ray ian.ray@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- include/configs/ge_bx50v3.h | 82 +++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 29 deletions(-)
diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index d15470f..90ea030 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -111,39 +111,62 @@ #define CONFIG_SYS_TEXT_BASE 0x17800000
#define CONFIG_EXTRA_ENV_SETTINGS \ - "script=boot.scr\0" \ + "bootcause=POR\0" \ "bootlimit=10\0" \ "image=/boot/fitImage\0" \ + "fdt_high=0xffffffff\0" \ + "dev=mmc\0" \ + "devnum=1\0" \ + "rootdev=mmcblk0p\0" \ + "quiet=quiet loglevel=0\0" \ "console=" CONSOLE_DEV "\0" \ - "fdt_high=0xffffffff\0" \ - "sddev=0\0" \ - "emmcdev=1\0" \ - "partnum=1\0" \ - "setargs=setenv bootargs console=${console},${baudrate} " \ - "root=/dev/${rootdev} ro rootwait cma=128M " \ + "setargs=setenv bootargs root=/dev/${rootdev}${partnum} " \ + "ro rootwait cma=128M " \ + "bootcause=${bootcause} " \ + "${quiet} console=${console} " \ BX50V3_BOOTARGS_EXTRA "\0" \ + "doquiet=" \ + "if ext2load ${dev} ${devnum}:5 0x7000A000 /boot/console; " \ + "then setenv quiet; fi\0" \ + "hasfirstboot=" \ + "ext2load ${dev} ${devnum}:${partnum} 0x7000A000 " \ + "/boot/bootcause/firstboot\0" \ + "swappartitions=" \ + "setexpr partnum 3 - ${partnum}\0" \ + "failbootcmd=" \ + "msg="Monitor failed to start. Try again, or contact GE Service for support."; " \ + "echo $msg; " \ + "setenv stdout vga; " \ + "echo "\n\n\n\n " $msg; " \ + "setenv stdout serial; " \ + "mw.b 0x7000A000 0xbc; " \ + "mw.b 0x7000A001 0x00; " \ + "ext4write ${dev} ${devnum}:5 0x7000A000 /boot/failures 2\0" \ + "altbootcmd=" \ + "run doquiet; " \ + "setenv partnum 1; run hasfirstboot || setenv partnum 2; " \ + "run hasfirstboot || setenv partnum 0; " \ + "if test ${partnum} != 0; then " \ + "setenv bootcause REVERT; " \ + "run swappartitions loadimage doboot; " \ + "fi; " \ + "run failbootcmd\0" \ "loadimage=" \ "ext2load ${dev} ${devnum}:${partnum} ${loadaddr} ${image}\0" \ - "tryboot=" \ - "if run loadimage; then " \ - "run doboot; " \ - "fi;\0" \ - "doboot=echo Booting from ${dev}:${devnum}:${partnum} ...; " \ + "doboot=" \ + "echo Booting from ${dev}:${devnum}:${partnum} ...; " \ "run setargs; " \ - "bootm ${loadaddr}#conf@${confidx};\0 " \ + "bootm ${loadaddr}#conf@${confidx}\0" \ + "tryboot=" \ + "setenv partnum 1; run hasfirstboot || setenv partnum 2; " \ + "run loadimage || run swappartitions && run loadimage || " \ + "setenv partnum 0 && echo MISSING IMAGE;" \ + "run doboot; " \ + "run failbootcmd\0" \
#define CONFIG_MMCBOOTCOMMAND \ - "setenv dev mmc; " \ - "setenv devnum ${emmcdev}; " \ - \ - "if ext2load ${dev} ${devnum}:5 0x7000A000 /boot/active/boot.img ; " \ - "then " \ - "source 0x7000A000; " \ - "fi; " \ - \ - "setenv rootdev mmcblk0p${partnum}; " \ - \ "if mmc dev ${devnum}; then " \ + "run doquiet; " \ "run tryboot; " \ "fi; " \
@@ -198,16 +221,17 @@ #define CONFIG_SYS_FSL_USDHC_NUM 3
/* Framebuffer */ +#define CONFIG_VIDEO #ifdef CONFIG_VIDEO #define CONFIG_VIDEO_IPUV3 -#define CONFIG_VIDEO_BMP_RLE8 -#define CONFIG_SPLASH_SCREEN -#define CONFIG_SPLASH_SCREEN_ALIGN -#define CONFIG_BMP_16BPP -#define CONFIG_VIDEO_LOGO -#define CONFIG_VIDEO_BMP_LOGO +#define CONFIG_CFB_CONSOLE +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_SYS_CONSOLE_FG_COL 0xFF +#define CONFIG_SYS_CONSOLE_BG_COL 0x00 +#define CONFIG_HIDE_LOGO_VERSION #define CONFIG_IMX_HDMI #define CONFIG_IMX_VIDEO_SKIP +#define CONFIG_CMD_BMP #endif
#define CONFIG_PWM_IMX

From: Nandor Han nandor.han@ge.com
Validate the time at startup: - in case rtc error add to kernel command line RTC_ERROR - clamp date to 1-Jan-2036
Signed-off-by: Nandor Han nandor.han@ge.com Signed-off-by: Martyn Welch martyn.welch@collabora.co.uk --- board/ge/bx50v3/bx50v3.c | 3 +++ configs/ge_b850v3_defconfig | 1 + include/configs/ge_bx50v3.h | 6 +++++- 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index e35afa03..c7a2918 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -29,6 +29,7 @@ #include <input.h> #include <pwm.h> #include <stdlib.h> +#include "../common/ge_common.h" #include "../common/vpd_reader.h" #include "../../../drivers/net/e1000.h" DECLARE_GLOBAL_DATA_PTR; @@ -805,6 +806,8 @@ int board_late_init(void) /* board specific pmic init */ pmic_init();
+ check_time(); + return 0; }
diff --git a/configs/ge_b850v3_defconfig b/configs/ge_b850v3_defconfig index 4f9d77c..b786675 100644 --- a/configs/ge_b850v3_defconfig +++ b/configs/ge_b850v3_defconfig @@ -13,6 +13,7 @@ CONFIG_CMD_BOOTZ=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y +CONFIG_RTC_RX8010SJ=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y # CONFIG_CMD_NFS is not set diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index 90ea030..9d6afdd 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -123,7 +123,7 @@ "setargs=setenv bootargs root=/dev/${rootdev}${partnum} " \ "ro rootwait cma=128M " \ "bootcause=${bootcause} " \ - "${quiet} console=${console} " \ + "${quiet} console=${console} ${rtc_status} " \ BX50V3_BOOTARGS_EXTRA "\0" \ "doquiet=" \ "if ext2load ${dev} ${devnum}:5 0x7000A000 /boot/console; " \ @@ -244,6 +244,10 @@ #define CONFIG_PCIE_IMX_PERST_GPIO IMX_GPIO_NR(7, 12) #define CONFIG_PCIE_IMX_POWER_GPIO IMX_GPIO_NR(1, 5)
+#define CONFIG_RTC_RX8010SJ +#define CONFIG_SYS_RTC_BUS_NUM 2 +#define CONFIG_SYS_I2C_RTC_ADDR 0x32 + /* I2C Configs */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC

Hi Martyn,
On 08/11/2017 16:59, Martyn Welch wrote:
This series improves the support on the bx50v3 devices (b540v3, b650v3 and b850v3) and utilising features recently added as part of the PPD implementation.
NOTE: This series requires the PPD series: https://lists.denx.de/pipermail/u-boot/2017-November/310865.html
Changes outside of the bx50v3/ppd specifc areas:
- Added driver for RX8010SJ RTC.
- Added functionality to e1000 driver to enable wrting of EEPROM/MAC address.
Hannu Lounento (5): net: e1000: add support for writing to EEPROM net: e1000: split e1000_read_mac_addr net: e1000: implement eth_write_hwaddr board: ge: bx50v3: program MAC address to I210 board: ge: bx50v3: mount rootfs read-only
Ian Ray (5): configs: Add network device support for bx50v3 products board: ge: bx50v3: Support FIT and select configuration based on VPD config: ge_bx50v3: read boot script configs: ge_bx50v3: enable bootcount configs: ge_bx50v3: automatic partition selection and video output failure message
Martyn Welch (4): board: ge: mx53ppd: Move check_time() to common location board: ge: Enable access to i2c bus 1 and 2 board: ge: bx50v3: move FEC MAC address programming to driver board: ge: bx50v3: Enable hardware watchdog
Nandor Han (2): rtc: adding RX8010SJ rtc driver board,ge,bx50v3 - rtc time validation
board/ge/bx50v3/bx50v3.c | 130 ++++++++++----- board/ge/common/Makefile | 2 +- board/ge/common/ge_common.c | 55 +++++++ board/ge/common/ge_common.h | 7 + board/ge/mx53ppd/mx53ppd.c | 47 +----- configs/ge_b450v3_defconfig | 7 +- configs/ge_b650v3_defconfig | 7 +- configs/ge_b850v3_defconfig | 8 +- drivers/net/e1000.c | 292 +++++++++++++++++++++++++++++++--- drivers/net/e1000.h | 3 + drivers/rtc/Kconfig | 6 + drivers/rtc/Makefile | 1 + drivers/rtc/rx8010sj.c | 378 ++++++++++++++++++++++++++++++++++++++++++++ include/configs/ge_bx50v3.h | 190 +++++++++------------- 14 files changed, 911 insertions(+), 222 deletions(-) create mode 100644 board/ge/common/ge_common.c create mode 100644 board/ge/common/ge_common.h create mode 100644 drivers/rtc/rx8010sj.c
Applied to u-boot-imx, thanks !
Best regards, Stefano Babic

Hi Martyn,
On 08/11/2017 16:59, Martyn Welch wrote:
This series improves the support on the bx50v3 devices (b540v3, b650v3 and b850v3) and utilising features recently added as part of the PPD implementation.
NOTE: This series requires the PPD series: https://lists.denx.de/pipermail/u-boot/2017-November/310865.html
Changes outside of the bx50v3/ppd specifc areas:
- Added driver for RX8010SJ RTC.
- Added functionality to e1000 driver to enable wrting of EEPROM/MAC address.
Hannu Lounento (5): net: e1000: add support for writing to EEPROM
See Tom's comments about this patch :
http://patchwork.ozlabs.org/patch/849710/
I moved out the series from u-boot-imx until the issues and warnings will be fixed.
Best regards, Stefano Babic
net: e1000: split e1000_read_mac_addr net: e1000: implement eth_write_hwaddr board: ge: bx50v3: program MAC address to I210 board: ge: bx50v3: mount rootfs read-only
Ian Ray (5): configs: Add network device support for bx50v3 products board: ge: bx50v3: Support FIT and select configuration based on VPD config: ge_bx50v3: read boot script configs: ge_bx50v3: enable bootcount configs: ge_bx50v3: automatic partition selection and video output failure message
Martyn Welch (4): board: ge: mx53ppd: Move check_time() to common location board: ge: Enable access to i2c bus 1 and 2 board: ge: bx50v3: move FEC MAC address programming to driver board: ge: bx50v3: Enable hardware watchdog
Nandor Han (2): rtc: adding RX8010SJ rtc driver board,ge,bx50v3 - rtc time validation
board/ge/bx50v3/bx50v3.c | 130 ++++++++++----- board/ge/common/Makefile | 2 +- board/ge/common/ge_common.c | 55 +++++++ board/ge/common/ge_common.h | 7 + board/ge/mx53ppd/mx53ppd.c | 47 +----- configs/ge_b450v3_defconfig | 7 +- configs/ge_b650v3_defconfig | 7 +- configs/ge_b850v3_defconfig | 8 +- drivers/net/e1000.c | 292 +++++++++++++++++++++++++++++++--- drivers/net/e1000.h | 3 + drivers/rtc/Kconfig | 6 + drivers/rtc/Makefile | 1 + drivers/rtc/rx8010sj.c | 378 ++++++++++++++++++++++++++++++++++++++++++++ include/configs/ge_bx50v3.h | 190 +++++++++------------- 14 files changed, 911 insertions(+), 222 deletions(-) create mode 100644 board/ge/common/ge_common.c create mode 100644 board/ge/common/ge_common.h create mode 100644 drivers/rtc/rx8010sj.c
participants (3)
-
Joe Hershberger
-
Martyn Welch
-
Stefano Babic