uboot/board/siemens/iot2050/board.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Board specific initialization for IOT2050
   4 * Copyright (c) Siemens AG, 2018-2021
   5 *
   6 * Authors:
   7 *   Le Jin <le.jin@siemens.com>
   8 *   Jan Kiszka <jan.kiszka@siemens.com>
   9 */
  10
  11#include <common.h>
  12#include <bootstage.h>
  13#include <dm.h>
  14#include <i2c.h>
  15#include <led.h>
  16#include <malloc.h>
  17#include <net.h>
  18#include <phy.h>
  19#include <spl.h>
  20#include <version.h>
  21#include <linux/delay.h>
  22#include <asm/arch/sys_proto.h>
  23#include <asm/arch/hardware.h>
  24#include <asm/gpio.h>
  25#include <asm/io.h>
  26
  27#define IOT2050_INFO_MAGIC              0x20502050
  28
  29struct iot2050_info {
  30        u32 magic;
  31        u16 size;
  32        char name[20 + 1];
  33        char serial[16 + 1];
  34        char mlfb[18 + 1];
  35        char uuid[32 + 1];
  36        char a5e[18 + 1];
  37        u8 mac_addr_cnt;
  38        u8 mac_addr[8][ARP_HLEN];
  39        char seboot_version[40 + 1];
  40} __packed;
  41
  42/*
  43 * Scratch SRAM (available before DDR RAM) contains extracted EEPROM data.
  44 */
  45#define IOT2050_INFO_DATA ((struct iot2050_info *) \
  46                             TI_SRAM_SCRATCH_BOARD_EEPROM_START)
  47
  48DECLARE_GLOBAL_DATA_PTR;
  49
  50static bool board_is_advanced(void)
  51{
  52        struct iot2050_info *info = IOT2050_INFO_DATA;
  53
  54        return info->magic == IOT2050_INFO_MAGIC &&
  55                strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
  56}
  57
  58static bool board_is_sr1(void)
  59{
  60        struct iot2050_info *info = IOT2050_INFO_DATA;
  61
  62        return info->magic == IOT2050_INFO_MAGIC &&
  63                !strstr((char *)info->name, "-PG2");
  64}
  65
  66static void remove_mmc1_target(void)
  67{
  68        char *boot_targets = strdup(env_get("boot_targets"));
  69        char *mmc1 = strstr(boot_targets, "mmc1");
  70
  71        if (mmc1) {
  72                memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
  73                env_set("boot_targets", boot_targets);
  74        }
  75
  76        free(boot_targets);
  77}
  78
  79void set_board_info_env(void)
  80{
  81        struct iot2050_info *info = IOT2050_INFO_DATA;
  82        u8 __maybe_unused mac_cnt;
  83        const char *fdtfile;
  84
  85        if (info->magic != IOT2050_INFO_MAGIC) {
  86                pr_err("IOT2050: Board info parsing error!\n");
  87                return;
  88        }
  89
  90        if (env_get("board_uuid"))
  91                return;
  92
  93        env_set("board_name", info->name);
  94        env_set("board_serial", info->serial);
  95        env_set("mlfb", info->mlfb);
  96        env_set("board_uuid", info->uuid);
  97        env_set("board_a5e", info->a5e);
  98        env_set("fw_version", PLAIN_VERSION);
  99        env_set("seboot_version", info->seboot_version);
 100
 101        if (IS_ENABLED(CONFIG_NET)) {
 102                /* set MAC addresses to ensure forwarding to the OS */
 103                for (mac_cnt = 0; mac_cnt < info->mac_addr_cnt; mac_cnt++) {
 104                        if (is_valid_ethaddr(info->mac_addr[mac_cnt]))
 105                                eth_env_set_enetaddr_by_index("eth",
 106                                                              mac_cnt + 1,
 107                                                              info->mac_addr[mac_cnt]);
 108                }
 109        }
 110
 111        if (board_is_advanced()) {
 112                if (board_is_sr1())
 113                        fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
 114                else
 115                        fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
 116        } else {
 117                if (board_is_sr1())
 118                        fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
 119                else
 120                        fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
 121                /* remove the unavailable eMMC (mmc1) from the list */
 122                remove_mmc1_target();
 123        }
 124        env_set("fdtfile", fdtfile);
 125
 126        env_save();
 127}
 128
 129int board_init(void)
 130{
 131        return 0;
 132}
 133
 134int dram_init(void)
 135{
 136        if (board_is_advanced())
 137                gd->ram_size = SZ_2G;
 138        else
 139                gd->ram_size = SZ_1G;
 140
 141        return 0;
 142}
 143
 144int dram_init_banksize(void)
 145{
 146        dram_init();
 147
 148        /* Bank 0 declares the memory available in the DDR low region */
 149        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
 150        gd->bd->bi_dram[0].size = gd->ram_size;
 151
 152        /* Bank 1 declares the memory available in the DDR high region */
 153        gd->bd->bi_dram[1].start = 0;
 154        gd->bd->bi_dram[1].size = 0;
 155
 156        return 0;
 157}
 158
 159#ifdef CONFIG_SPL_LOAD_FIT
 160int board_fit_config_name_match(const char *name)
 161{
 162        struct iot2050_info *info = IOT2050_INFO_DATA;
 163        char upper_name[32];
 164
 165        if (info->magic != IOT2050_INFO_MAGIC ||
 166            strlen(name) >= sizeof(upper_name))
 167                return -1;
 168
 169        str_to_upper(name, upper_name, sizeof(upper_name));
 170        if (!strcmp(upper_name, (char *)info->name))
 171                return 0;
 172
 173        return -1;
 174}
 175#endif
 176
 177int do_board_detect(void)
 178{
 179        return 0;
 180}
 181
 182#ifdef CONFIG_IOT2050_BOOT_SWITCH
 183static bool user_button_pressed(void)
 184{
 185        struct udevice *red_led = NULL;
 186        unsigned long count = 0;
 187        struct gpio_desc gpio;
 188
 189        memset(&gpio, 0, sizeof(gpio));
 190
 191        if (dm_gpio_lookup_name("25", &gpio) < 0 ||
 192            dm_gpio_request(&gpio, "USER button") < 0 ||
 193            dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
 194                return false;
 195
 196        if (dm_gpio_get_value(&gpio) == 1)
 197                return false;
 198
 199        printf("USER button pressed - booting from external media only\n");
 200
 201        led_get_by_label("status-led-red", &red_led);
 202
 203        if (red_led)
 204                led_set_state(red_led, LEDST_ON);
 205
 206        while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
 207                mdelay(1);
 208
 209        if (red_led)
 210                led_set_state(red_led, LEDST_OFF);
 211
 212        return true;
 213}
 214#endif
 215
 216#define SERDES0_LANE_SELECT     0x00104080
 217
 218int board_late_init(void)
 219{
 220        /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
 221        writel(0x3, SERDES0_LANE_SELECT);
 222
 223        set_board_info_env();
 224
 225        /* remove the eMMC if requested via button */
 226        if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
 227            user_button_pressed())
 228                remove_mmc1_target();
 229
 230        return 0;
 231}
 232
 233#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 234int ft_board_setup(void *blob, struct bd_info *bd)
 235{
 236        int ret;
 237
 238        ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
 239        if (ret < 0)
 240                ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
 241                                         "sram@70000000");
 242        if (ret)
 243                pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
 244
 245        return ret;
 246}
 247#endif
 248
 249void spl_board_init(void)
 250{
 251}
 252
 253#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
 254/*
 255 * Indicate any error or (accidental?) entering of CLI via the red status LED.
 256 */
 257void show_boot_progress(int progress)
 258{
 259        struct udevice *dev;
 260        int ret;
 261
 262        if ((progress < 0 && progress != -BOOTSTAGE_ID_NET_ETH_START) ||
 263            progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
 264                ret = led_get_by_label("status-led-green", &dev);
 265                if (ret == 0)
 266                        led_set_state(dev, LEDST_OFF);
 267
 268                ret = led_get_by_label("status-led-red", &dev);
 269                if (ret == 0)
 270                        led_set_state(dev, LEDST_ON);
 271        }
 272}
 273#endif
 274