diff options
Diffstat (limited to 'roms/u-boot/board/gardena/smart-gateway-mt7688')
4 files changed, 332 insertions, 0 deletions
diff --git a/roms/u-boot/board/gardena/smart-gateway-mt7688/Kconfig b/roms/u-boot/board/gardena/smart-gateway-mt7688/Kconfig new file mode 100644 index 000000000..3653f8aad --- /dev/null +++ b/roms/u-boot/board/gardena/smart-gateway-mt7688/Kconfig @@ -0,0 +1,12 @@ +if BOARD_GARDENA_SMART_GATEWAY_MT7688 + +config SYS_BOARD + default "smart-gateway-mt7688" + +config SYS_VENDOR + default "gardena" + +config SYS_CONFIG_NAME + default "gardena-smart-gateway-mt7688" + +endif diff --git a/roms/u-boot/board/gardena/smart-gateway-mt7688/MAINTAINERS b/roms/u-boot/board/gardena/smart-gateway-mt7688/MAINTAINERS new file mode 100644 index 000000000..bbb491c1c --- /dev/null +++ b/roms/u-boot/board/gardena/smart-gateway-mt7688/MAINTAINERS @@ -0,0 +1,8 @@ +GARDENA_SMART_GATEWAY_MT7688 BOARD +M: Stefan Roese <sr@denx.de> +S: Maintained +F: board/gardena/smart-gateway-mt7688 +F: include/configs/gardena-smart-gateway-mt7688.h +F: configs/gardena-smart-gateway-mt7688_defconfig +F: configs/gardena-smart-gateway-mt7688-ram_defconfig +F: arch/mips/dts/gardena-smart-gateway-mt7688.dts diff --git a/roms/u-boot/board/gardena/smart-gateway-mt7688/Makefile b/roms/u-boot/board/gardena/smart-gateway-mt7688/Makefile new file mode 100644 index 000000000..70cd7a8e5 --- /dev/null +++ b/roms/u-boot/board/gardena/smart-gateway-mt7688/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += board.o diff --git a/roms/u-boot/board/gardena/smart-gateway-mt7688/board.c b/roms/u-boot/board/gardena/smart-gateway-mt7688/board.c new file mode 100644 index 000000000..8a3a6e348 --- /dev/null +++ b/roms/u-boot/board/gardena/smart-gateway-mt7688/board.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <command.h> +#include <env.h> +#include <env_internal.h> +#include <flash.h> +#include <init.h> +#include <led.h> +#include <log.h> +#include <malloc.h> +#include <net.h> +#include <spi.h> +#include <spi_flash.h> +#include <linux/delay.h> +#include <linux/stringify.h> +#include <u-boot/crc.h> +#include <uuid.h> +#include <linux/ctype.h> +#include <linux/io.h> + +#define MT76XX_AGPIO_CFG 0x1000003c + +#define FACTORY_DATA_OFFS 0xc0000 +#define FACTORY_DATA_SECT_SIZE 0x10000 +#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE) > FACTORY_DATA_OFFS) +#error "U-Boot image with environment too big (overlapping with factory-data)!" +#endif +#define FACTORY_DATA_USER_OFFS 0x140 +#define FACTORY_DATA_SIZE 0x1f0 +#define FACTORY_DATA_CRC_LEN (FACTORY_DATA_SIZE - \ + FACTORY_DATA_USER_OFFS - sizeof(u32)) + +#define FACTORY_DATA_MAGIC 0xCAFEBABE + +struct factory_data_values { + u8 pad_1[4]; + u8 wifi_mac[6]; /* offs: 0x004: binary value */ + u8 pad_2[30]; + u8 eth_mac[6]; /* offs: 0x028: binary value */ + u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6]; + /* User values start here at offset 0x140 */ + u32 crc; + u32 magic; + u32 version; + char ipr_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */ + char hqv_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */ + char unielec_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */ +}; + +int board_early_init_f(void) +{ + void __iomem *gpio_mode; + + /* Configure digital vs analog GPIOs */ + gpio_mode = ioremap_nocache(MT76XX_AGPIO_CFG, 0x100); + iowrite32(0x00fe01ff, gpio_mode); + + return 0; +} + +static bool prepare_uuid_var(const char *fd_ptr, const char *env_var_name, + char errorchar) +{ + char str[UUID_STR_LEN + 1] = { 0 }; /* Enough for UUID stuff */ + bool env_updated = false; + char *env; + int i; + + memcpy(str, fd_ptr, UUID_STR_LEN); + + /* Convert non-ascii character to 'X' */ + for (i = 0; i < UUID_STR_LEN; i++) { + if (!(isascii(str[i]) && isprint(str[i]))) + str[i] = errorchar; + } + + env = env_get(env_var_name); + if (strcmp(env, str)) { + env_set(env_var_name, str); + env_updated = true; + } + + return env_updated; +} + +static void factory_data_env_config(void) +{ + struct factory_data_values *fd; + struct spi_flash *sf; + int env_updated = 0; + char str[UUID_STR_LEN + 1]; /* Enough for UUID stuff */ + char *env; + u8 *buf; + u32 crc; + int ret; + u8 *ptr; + + buf = malloc(FACTORY_DATA_SIZE); + if (!buf) { + printf("F-Data:Unable to allocate buffer\n"); + return; + } + + /* + * Get values from factory-data area in SPI NOR + */ + sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + if (!sf) { + printf("F-Data:Unable to access SPI NOR flash\n"); + goto err_free; + } + + ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE, + (void *)buf); + if (ret) { + printf("F-Data:Unable to read factory-data from SPI NOR\n"); + goto err_spi_flash; + } + + fd = (struct factory_data_values *)buf; + + if (fd->magic != FACTORY_DATA_MAGIC) + printf("F-Data:Magic value not correct\n"); + + crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN); + if (crc != fd->crc) + printf("F-Data:CRC not correct\n"); + else + printf("F-Data:factory-data version %x detected\n", + fd->version); + + /* Handle wifi_mac env variable */ + ptr = fd->wifi_mac; + sprintf(str, "%pM", ptr); + if (!is_valid_ethaddr(ptr)) + printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str); + + env = env_get("wifiaddr"); + if (strcmp(env, str)) { + env_set("wifiaddr", str); + env_updated = 1; + } + + /* Handle eth_mac env variable */ + ptr = fd->eth_mac; + sprintf(str, "%pM", ptr); + if (!is_valid_ethaddr(ptr)) + printf("F-Data:Invalid MAC addr: eth_mac %s\n", str); + + env = env_get("ethaddr"); + if (strcmp(env, str)) { + env_set("ethaddr", str); + env_updated = 1; + } + + /* Handle UUID env variables */ + env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X'); + env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0'); + env_updated |= prepare_uuid_var(fd->unielec_id, + "linuxmoduleunielecid", '\0'); + + /* Check if the environment was updated and needs to get stored */ + if (env_updated != 0) { + printf("F-Data:Values don't match env values -> saving\n"); + env_save(); + } else { + debug("F-Data:Values match current env values\n"); + } + +err_spi_flash: + spi_flash_free(sf); + +err_free: + free(buf); +} + +int board_late_init(void) +{ + if (IS_ENABLED(CONFIG_LED)) + led_default_state(); + + factory_data_env_config(); + + return 0; +} + +static void copy_or_generate_uuid(char *fd_ptr, const char *env_var_name) +{ + char str[UUID_STR_LEN + 1] = { 0 }; /* Enough for UUID stuff */ + char *env; + + /* Don't use the UUID dest place, as the \0 char won't fit */ + env = env_get(env_var_name); + if (env) + strncpy(str, env, UUID_STR_LEN); + else + gen_rand_uuid_str(str, UUID_STR_FORMAT_STD); + + memcpy(fd_ptr, str, UUID_STR_LEN); +} + +/* + * Helper function to provide some sane factory-data values for testing + * purpose, when these values are not programmed correctly + */ +int do_fd_write(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct factory_data_values *fd; + struct spi_flash *sf; + u8 *buf; + int ret = CMD_RET_FAILURE; + + buf = malloc(FACTORY_DATA_SECT_SIZE); + if (!buf) { + printf("F-Data:Unable to allocate buffer\n"); + return CMD_RET_FAILURE; + } + + sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + if (!sf) { + printf("F-Data:Unable to access SPI NOR flash\n"); + goto err_free; + } + + /* Generate the factory-data struct */ + + /* Fist read complete sector into buffer */ + ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE, + (void *)buf); + if (ret) { + printf("F-Data:spi_flash_read failed (%d)\n", ret); + goto err_spi_flash; + } + + fd = (struct factory_data_values *)buf; + fd->magic = FACTORY_DATA_MAGIC; + fd->version = 0x1; + + /* Use existing MAC and UUID values or generate some random ones */ + if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) { + net_random_ethaddr(fd->wifi_mac); + /* to get a different seed value for the MAC address */ + mdelay(10); + } + + if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac)) + net_random_ethaddr(fd->eth_mac); + + copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid"); + copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid"); + copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid"); + + printf("New factory-data values:\n"); + printf("wifiaddr=%pM\n", fd->wifi_mac); + printf("ethaddr=%pM\n", fd->eth_mac); + + /* + * We don't have the \0 char at the end, so we need to specify the + * length in the printf format instead + */ + printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id); + printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n", + fd->hqv_id); + printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n", + fd->unielec_id); + + fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN); + + ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE); + if (ret) { + printf("F-Data:spi_flash_erase failed (%d)\n", ret); + goto err_spi_flash; + } + + ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE, + buf); + if (ret) { + printf("F-Data:spi_flash_write failed (%d)\n", ret); + goto err_spi_flash; + } + + printf("F-Data:factory-data values written to SPI NOR flash\n"); + +err_spi_flash: + spi_flash_free(sf); + +err_free: + free(buf); + + return ret; +} + +#ifndef CONFIG_SPL_BUILD +U_BOOT_CMD( + fd_write, 1, 0, do_fd_write, + "Write test factory-data values to SPI NOR", + "\n" +); +#endif |