uboot/board/ti/j721s2/evm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Board specific initialization for J721S2 EVM
   4 *
   5 * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
   6 *      David Huang <d-huang@ti.com>
   7 *
   8 */
   9
  10#include <common.h>
  11#include <env.h>
  12#include <fdt_support.h>
  13#include <generic-phy.h>
  14#include <image.h>
  15#include <init.h>
  16#include <log.h>
  17#include <net.h>
  18#include <asm/arch/hardware.h>
  19#include <asm/gpio.h>
  20#include <asm/io.h>
  21#include <spl.h>
  22#include <dm.h>
  23#include <dm/uclass-internal.h>
  24#include <dm/root.h>
  25
  26#include "../common/board_detect.h"
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30int board_init(void)
  31{
  32        return 0;
  33}
  34
  35int dram_init(void)
  36{
  37#ifdef CONFIG_PHYS_64BIT
  38        gd->ram_size = 0x100000000;
  39#else
  40        gd->ram_size = 0x80000000;
  41#endif
  42
  43        return 0;
  44}
  45
  46phys_size_t board_get_usable_ram_top(phys_size_t total_size)
  47{
  48#ifdef CONFIG_PHYS_64BIT
  49        /* Limit RAM used by U-Boot to the DDR low region */
  50        if (gd->ram_top > 0x100000000)
  51                return 0x100000000;
  52#endif
  53
  54        return gd->ram_top;
  55}
  56
  57int dram_init_banksize(void)
  58{
  59        /* Bank 0 declares the memory available in the DDR low region */
  60        gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
  61        gd->bd->bi_dram[0].size = 0x7fffffff;
  62        gd->ram_size = 0x80000000;
  63
  64#ifdef CONFIG_PHYS_64BIT
  65        /* Bank 1 declares the memory available in the DDR high region */
  66        gd->bd->bi_dram[1].start = CFG_SYS_SDRAM_BASE1;
  67        gd->bd->bi_dram[1].size = 0x37fffffff;
  68        gd->ram_size = 0x400000000;
  69#endif
  70
  71        return 0;
  72}
  73
  74#ifdef CONFIG_TI_I2C_BOARD_DETECT
  75/*
  76 * Functions specific to EVM and SK designs of J721S2/AM68 family.
  77 */
  78
  79#define board_is_j721s2_som()   board_ti_k3_is("J721S2X-PM1-SOM")
  80
  81#define board_is_am68_sk_som() board_ti_k3_is("AM68-SK-SOM")
  82
  83int do_board_detect(void)
  84{
  85        int ret;
  86
  87        if (board_ti_was_eeprom_read())
  88                return 0;
  89
  90        ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
  91                                         CONFIG_EEPROM_CHIP_ADDRESS);
  92        if (ret) {
  93                printf("EEPROM not available at 0x%02x, trying to read at 0x%02x\n",
  94                       CONFIG_EEPROM_CHIP_ADDRESS, CONFIG_EEPROM_CHIP_ADDRESS + 1);
  95                ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
  96                                                 CONFIG_EEPROM_CHIP_ADDRESS + 1);
  97                if (ret)
  98                        pr_err("Reading on-board EEPROM at 0x%02x failed %d\n",
  99                                CONFIG_EEPROM_CHIP_ADDRESS + 1, ret);
 100        }
 101
 102        return ret;
 103}
 104
 105int checkboard(void)
 106{
 107        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 108
 109        if (do_board_detect())
 110                /* EEPROM not populated */
 111                printf("Board: %s rev %s\n", "J721S2X-PM1-SOM", "E1");
 112        else
 113                printf("Board: %s rev %s\n", ep->name, ep->version);
 114
 115        return 0;
 116}
 117
 118static void setup_board_eeprom_env(void)
 119{
 120        char *name = "j721s2";
 121
 122        if (do_board_detect())
 123                goto invalid_eeprom;
 124
 125        if (board_is_j721s2_som())
 126                name = "j721s2";
 127        else if (board_is_am68_sk_som())
 128                name = "am68-sk";
 129        else
 130                printf("Unidentified board claims %s in eeprom header\n",
 131                       board_ti_get_name());
 132
 133invalid_eeprom:
 134        set_board_info_env_am6(name);
 135}
 136
 137static void setup_serial(void)
 138{
 139        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 140        unsigned long board_serial;
 141        char *endp;
 142        char serial_string[17] = { 0 };
 143
 144        if (env_get("serial#"))
 145                return;
 146
 147        board_serial = simple_strtoul(ep->serial, &endp, 16);
 148        if (*endp != '\0') {
 149                pr_err("Error: Can't set serial# to %s\n", ep->serial);
 150                return;
 151        }
 152
 153        snprintf(serial_string, sizeof(serial_string), "%016lx", board_serial);
 154        env_set("serial#", serial_string);
 155}
 156
 157/*
 158 * Declaration of daughtercards to probe. Note that when adding more
 159 * cards they should be grouped by the 'i2c_addr' field to allow for a
 160 * more efficient probing process.
 161 */
 162static const struct {
 163        u8 i2c_addr;            /* I2C address of card EEPROM */
 164        char *card_name;        /* EEPROM-programmed card name */
 165        char *dtbo_name;        /* Device tree overlay to apply */
 166        u8 eth_offset;          /* ethXaddr MAC address index offset */
 167} ext_cards[] = {
 168        {
 169                0x52,
 170                "J7X-GESI-EXP",
 171                "k3-j721s2-gesi-exp-board.dtbo",
 172                1,              /* Start populating from eth1addr */
 173        },
 174};
 175
 176#define DAUGHTER_CARD_NO_OF_MAC_ADDR    5
 177static bool daughter_card_detect_flags[ARRAY_SIZE(ext_cards)];
 178
 179static int probe_daughtercards(void)
 180{
 181        char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
 182        bool eeprom_read_success;
 183        struct ti_am6_eeprom ep;
 184        u8 previous_i2c_addr;
 185        u8 mac_addr_cnt;
 186        int i;
 187        int ret;
 188
 189        /* Mark previous I2C address variable as not populated */
 190        previous_i2c_addr = 0xff;
 191
 192        /* No EEPROM data was read yet */
 193        eeprom_read_success = false;
 194
 195        /* Iterate through list of daughtercards */
 196        for (i = 0; i < ARRAY_SIZE(ext_cards); i++) {
 197                /* Obtain card-specific I2C address */
 198                u8 i2c_addr = ext_cards[i].i2c_addr;
 199
 200                /* Read card EEPROM if not already read previously */
 201                if (i2c_addr != previous_i2c_addr) {
 202                        /* Store I2C address so we can avoid reading twice */
 203                        previous_i2c_addr = i2c_addr;
 204
 205                        /* Get and parse the daughter card EEPROM record */
 206                        ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS,
 207                                                    i2c_addr,
 208                                                    &ep,
 209                                                    (char **)mac_addr,
 210                                                    DAUGHTER_CARD_NO_OF_MAC_ADDR,
 211                                                    &mac_addr_cnt);
 212                        if (ret) {
 213                                debug("%s: No daughtercard EEPROM at 0x%02x found %d\n",
 214                                      __func__, i2c_addr, ret);
 215                                eeprom_read_success = false;
 216                                /* Skip to the next daughtercard to probe */
 217                                continue;
 218                        }
 219
 220                        /* EEPROM read successful, okay to further process. */
 221                        eeprom_read_success = true;
 222                }
 223
 224                /* Only continue processing if EEPROM data was read */
 225                if (!eeprom_read_success)
 226                        continue;
 227
 228                /* Only process the parsed data if we found a match */
 229                if (strncmp(ep.name, ext_cards[i].card_name, sizeof(ep.name)))
 230                        continue;
 231
 232                printf("Detected: %s rev %s\n", ep.name, ep.version);
 233                daughter_card_detect_flags[i] = true;
 234
 235                if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
 236                        int j;
 237                        /*
 238                         * Populate any MAC addresses from daughtercard into the U-Boot
 239                         * environment, starting with a card-specific offset so we can
 240                         * have multiple ext_cards contribute to the MAC pool in a well-
 241                         * defined manner.
 242                         */
 243                        for (j = 0; j < mac_addr_cnt; j++) {
 244                                if (!is_valid_ethaddr((u8 *)mac_addr[j]))
 245                                        continue;
 246
 247                                eth_env_set_enetaddr_by_index("eth", ext_cards[i].eth_offset + j,
 248                                                              (uchar *)mac_addr[j]);
 249                        }
 250                }
 251        }
 252
 253        if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
 254                char name_overlays[1024] = { 0 };
 255
 256                for (i = 0; i < ARRAY_SIZE(ext_cards); i++) {
 257                        if (!daughter_card_detect_flags[i])
 258                                continue;
 259
 260                        /* Skip if no overlays are to be added */
 261                        if (!strlen(ext_cards[i].dtbo_name))
 262                                continue;
 263
 264                        /*
 265                         * Make sure we are not running out of buffer space by checking
 266                         * if we can fit the new overlay, a trailing space to be used
 267                         * as a separator, plus the terminating zero.
 268                         */
 269                        if (strlen(name_overlays) + strlen(ext_cards[i].dtbo_name) + 2 >
 270                            sizeof(name_overlays))
 271                                return -ENOMEM;
 272
 273                        /* Append to our list of overlays */
 274                        strcat(name_overlays, ext_cards[i].dtbo_name);
 275                        strcat(name_overlays, " ");
 276                }
 277
 278                /* Apply device tree overlay(s) to the U-Boot environment, if any */
 279                if (strlen(name_overlays))
 280                        return env_set("name_overlays", name_overlays);
 281        }
 282
 283        return 0;
 284}
 285#endif
 286
 287/*
 288 * This function chooses the right dtb based on the board name read from
 289 * EEPROM if the EEPROM is programmed. Also, by default the boot chooses
 290 * the EVM DTB if there is no EEPROM is programmed or not detected.
 291 */
 292#ifdef CONFIG_SPL_LOAD_FIT
 293int board_fit_config_name_match(const char *name)
 294{
 295        bool eeprom_read = board_ti_was_eeprom_read();
 296
 297        if (!eeprom_read || board_is_j721s2_som()) {
 298                if (!strcmp(name, "k3-j721s2-common-proc-board"))
 299                        return 0;
 300        } else if (!eeprom_read || board_is_am68_sk_som()) {
 301                if (!strcmp(name, "k3-am68-sk-base-board"))
 302                        return 0;
 303        }
 304
 305        return -1;
 306}
 307#endif
 308
 309int board_late_init(void)
 310{
 311        if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT)) {
 312                setup_board_eeprom_env();
 313                setup_serial();
 314                probe_daughtercards();
 315        }
 316
 317        return 0;
 318}
 319
 320void spl_board_init(void)
 321{
 322}
 323