uboot/board/ti/j721e/evm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Board specific initialization for J721E EVM
   4 *
   5 * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
   6 *      Lokesh Vutla <lokeshvutla@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/sys_proto.h>
  19#include <asm/arch/hardware.h>
  20#include <asm/global_data.h>
  21#include <asm/gpio.h>
  22#include <asm/io.h>
  23#include <spl.h>
  24#include <asm/arch/sys_proto.h>
  25#include <dm.h>
  26#include <dm/uclass-internal.h>
  27
  28#include "../common/board_detect.h"
  29
  30#define board_is_j721e_som()    (board_ti_k3_is("J721EX-PM1-SOM") || \
  31                                 board_ti_k3_is("J721EX-PM2-SOM"))
  32
  33#define board_is_j7200_som()    (board_ti_k3_is("J7200X-PM1-SOM") || \
  34                                 board_ti_k3_is("J7200X-PM2-SOM"))
  35
  36/* Max number of MAC addresses that are parsed/processed per daughter card */
  37#define DAUGHTER_CARD_NO_OF_MAC_ADDR    8
  38
  39DECLARE_GLOBAL_DATA_PTR;
  40
  41int board_init(void)
  42{
  43        return 0;
  44}
  45
  46int dram_init(void)
  47{
  48#ifdef CONFIG_PHYS_64BIT
  49        gd->ram_size = 0x100000000;
  50#else
  51        gd->ram_size = 0x80000000;
  52#endif
  53
  54        return 0;
  55}
  56
  57ulong board_get_usable_ram_top(ulong total_size)
  58{
  59#ifdef CONFIG_PHYS_64BIT
  60        /* Limit RAM used by U-Boot to the DDR low region */
  61        if (gd->ram_top > 0x100000000)
  62                return 0x100000000;
  63#endif
  64
  65        return gd->ram_top;
  66}
  67
  68int dram_init_banksize(void)
  69{
  70        /* Bank 0 declares the memory available in the DDR low region */
  71        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
  72        gd->bd->bi_dram[0].size = 0x80000000;
  73        gd->ram_size = 0x80000000;
  74
  75#ifdef CONFIG_PHYS_64BIT
  76        /* Bank 1 declares the memory available in the DDR high region */
  77        gd->bd->bi_dram[1].start = CONFIG_SYS_SDRAM_BASE1;
  78        gd->bd->bi_dram[1].size = 0x80000000;
  79        gd->ram_size = 0x100000000;
  80#endif
  81
  82        return 0;
  83}
  84
  85#ifdef CONFIG_SPL_LOAD_FIT
  86int board_fit_config_name_match(const char *name)
  87{
  88        if (!strcmp(name, "k3-j721e-common-proc-board"))
  89                return 0;
  90
  91        return -1;
  92}
  93#endif
  94
  95#if CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_LIBFDT)
  96/* Returns 1, if onboard mux is set to hyperflash */
  97static void __maybe_unused detect_enable_hyperflash(void *blob)
  98{
  99        struct gpio_desc desc = {0};
 100
 101        if (dm_gpio_lookup_name("6", &desc))
 102                return;
 103
 104        if (dm_gpio_request(&desc, "6"))
 105                return;
 106
 107        if (dm_gpio_set_dir_flags(&desc, GPIOD_IS_IN))
 108                return;
 109
 110        if (dm_gpio_get_value(&desc)) {
 111                int offset;
 112
 113                do_fixup_by_compat(blob, "ti,am654-hbmc", "status",
 114                                   "okay", sizeof("okay"), 0);
 115                offset = fdt_node_offset_by_compatible(blob, -1,
 116                                                       "ti,am654-ospi");
 117                fdt_setprop(blob, offset, "status", "disabled",
 118                            sizeof("disabled"));
 119        }
 120}
 121#endif
 122
 123#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_TARGET_J7200_A72_EVM)
 124void spl_perform_fixups(struct spl_image_info *spl_image)
 125{
 126        detect_enable_hyperflash(spl_image->fdt_addr);
 127}
 128#endif
 129
 130#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 131int ft_board_setup(void *blob, struct bd_info *bd)
 132{
 133        int ret;
 134
 135        ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
 136        if (ret < 0)
 137                ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
 138                                         "sram@70000000");
 139        if (ret)
 140                printf("%s: fixing up msmc ram failed %d\n", __func__, ret);
 141
 142        detect_enable_hyperflash(blob);
 143
 144        return ret;
 145}
 146#endif
 147
 148#ifdef CONFIG_TI_I2C_BOARD_DETECT
 149int do_board_detect(void)
 150{
 151        int ret;
 152
 153        ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
 154                                         CONFIG_EEPROM_CHIP_ADDRESS);
 155        if (ret)
 156                pr_err("Reading on-board EEPROM at 0x%02x failed %d\n",
 157                       CONFIG_EEPROM_CHIP_ADDRESS, ret);
 158
 159        return ret;
 160}
 161
 162int checkboard(void)
 163{
 164        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 165
 166        if (do_board_detect())
 167                /* EEPROM not populated */
 168                printf("Board: %s rev %s\n", "J721EX-PM1-SOM", "E2");
 169        else
 170                printf("Board: %s rev %s\n", ep->name, ep->version);
 171
 172        return 0;
 173}
 174
 175static void setup_board_eeprom_env(void)
 176{
 177        char *name = "j721e";
 178
 179        if (do_board_detect())
 180                goto invalid_eeprom;
 181
 182        if (board_is_j721e_som())
 183                name = "j721e";
 184        else if (board_is_j7200_som())
 185                name = "j7200";
 186        else
 187                printf("Unidentified board claims %s in eeprom header\n",
 188                       board_ti_get_name());
 189
 190invalid_eeprom:
 191        set_board_info_env_am6(name);
 192}
 193
 194static void setup_serial(void)
 195{
 196        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 197        unsigned long board_serial;
 198        char *endp;
 199        char serial_string[17] = { 0 };
 200
 201        if (env_get("serial#"))
 202                return;
 203
 204        board_serial = hextoul(ep->serial, &endp);
 205        if (*endp != '\0') {
 206                pr_err("Error: Can't set serial# to %s\n", ep->serial);
 207                return;
 208        }
 209
 210        snprintf(serial_string, sizeof(serial_string), "%016lx", board_serial);
 211        env_set("serial#", serial_string);
 212}
 213
 214/*
 215 * Declaration of daughtercards to probe. Note that when adding more
 216 * cards they should be grouped by the 'i2c_addr' field to allow for a
 217 * more efficient probing process.
 218 */
 219static const struct {
 220        u8 i2c_addr;            /* I2C address of card EEPROM */
 221        char *card_name;        /* EEPROM-programmed card name */
 222        char *dtbo_name;        /* Device tree overlay to apply */
 223        u8 eth_offset;          /* ethXaddr MAC address index offset */
 224} ext_cards[] = {
 225        {
 226                0x51,
 227                "J7X-BASE-CPB",
 228                "",             /* No dtbo for this board */
 229                0,
 230        },
 231        {
 232                0x52,
 233                "J7X-INFOTAN-EXP",
 234                "",             /* No dtbo for this board */
 235                0,
 236        },
 237        {
 238                0x52,
 239                "J7X-GESI-EXP",
 240                "",             /* No dtbo for this board */
 241                5,              /* Start populating from eth5addr */
 242        },
 243        {
 244                0x54,
 245                "J7X-VSC8514-ETH",
 246                "",             /* No dtbo for this board */
 247                1,              /* Start populating from eth1addr */
 248        },
 249};
 250
 251static bool daughter_card_detect_flags[ARRAY_SIZE(ext_cards)];
 252
 253const char *board_fit_get_additionnal_images(int index, const char *type)
 254{
 255        int i, j;
 256
 257        if (strcmp(type, FIT_FDT_PROP))
 258                return NULL;
 259
 260        j = 0;
 261        for (i = 0; i < ARRAY_SIZE(ext_cards); i++) {
 262                if (daughter_card_detect_flags[i]) {
 263                        if (j == index) {
 264                                /*
 265                                 * Return dtbo name only if populated,
 266                                 * otherwise stop parsing here.
 267                                 */
 268                                if (strlen(ext_cards[i].dtbo_name))
 269                                        return ext_cards[i].dtbo_name;
 270                                else
 271                                        return NULL;
 272                        };
 273
 274                        j++;
 275                }
 276        }
 277
 278        return NULL;
 279}
 280
 281static int probe_daughtercards(void)
 282{
 283        char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
 284        bool eeprom_read_success;
 285        struct ti_am6_eeprom ep;
 286        u8 previous_i2c_addr;
 287        u8 mac_addr_cnt;
 288        int i;
 289        int ret;
 290
 291        /* Mark previous I2C address variable as not populated */
 292        previous_i2c_addr = 0xff;
 293
 294        /* No EEPROM data was read yet */
 295        eeprom_read_success = false;
 296
 297        /* Iterate through list of daughtercards */
 298        for (i = 0; i < ARRAY_SIZE(ext_cards); i++) {
 299                /* Obtain card-specific I2C address */
 300                u8 i2c_addr = ext_cards[i].i2c_addr;
 301
 302                /* Read card EEPROM if not already read previously */
 303                if (i2c_addr != previous_i2c_addr) {
 304                        /* Store I2C address so we can avoid reading twice */
 305                        previous_i2c_addr = i2c_addr;
 306
 307                        /* Get and parse the daughter card EEPROM record */
 308                        ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS,
 309                                                    i2c_addr,
 310                                                    &ep,
 311                                                    (char **)mac_addr,
 312                                                    DAUGHTER_CARD_NO_OF_MAC_ADDR,
 313                                                    &mac_addr_cnt);
 314                        if (ret) {
 315                                debug("%s: No daughtercard EEPROM at 0x%02x found %d\n",
 316                                      __func__, i2c_addr, ret);
 317                                eeprom_read_success = false;
 318                                /* Skip to the next daughtercard to probe */
 319                                continue;
 320                        }
 321
 322                        /* EEPROM read successful, okay to further process. */
 323                        eeprom_read_success = true;
 324                }
 325
 326                /* Only continue processing if EEPROM data was read */
 327                if (!eeprom_read_success)
 328                        continue;
 329
 330                /* Only process the parsed data if we found a match */
 331                if (strncmp(ep.name, ext_cards[i].card_name, sizeof(ep.name)))
 332                        continue;
 333
 334                printf("Detected: %s rev %s\n", ep.name, ep.version);
 335                daughter_card_detect_flags[i] = true;
 336
 337#ifndef CONFIG_SPL_BUILD
 338                int j;
 339                /*
 340                 * Populate any MAC addresses from daughtercard into the U-Boot
 341                 * environment, starting with a card-specific offset so we can
 342                 * have multiple ext_cards contribute to the MAC pool in a well-
 343                 * defined manner.
 344                 */
 345                for (j = 0; j < mac_addr_cnt; j++) {
 346                        if (!is_valid_ethaddr((u8 *)mac_addr[j]))
 347                                continue;
 348
 349                        eth_env_set_enetaddr_by_index("eth",
 350                                                      ext_cards[i].eth_offset + j,
 351                                                      (uchar *)mac_addr[j]);
 352                }
 353#endif
 354        }
 355#ifndef CONFIG_SPL_BUILD
 356        char name_overlays[1024] = { 0 };
 357
 358        for (i = 0; i < ARRAY_SIZE(ext_cards); i++) {
 359                if (!daughter_card_detect_flags[i])
 360                        continue;
 361
 362                /* Skip if no overlays are to be added */
 363                if (!strlen(ext_cards[i].dtbo_name))
 364                        continue;
 365
 366                /*
 367                 * Make sure we are not running out of buffer space by checking
 368                 * if we can fit the new overlay, a trailing space to be used
 369                 * as a separator, plus the terminating zero.
 370                 */
 371                if (strlen(name_overlays) + strlen(ext_cards[i].dtbo_name) + 2 >
 372                    sizeof(name_overlays))
 373                        return -ENOMEM;
 374
 375                /* Append to our list of overlays */
 376                strcat(name_overlays, ext_cards[i].dtbo_name);
 377                strcat(name_overlays, " ");
 378        }
 379
 380        /* Apply device tree overlay(s) to the U-Boot environment, if any */
 381        if (strlen(name_overlays))
 382                return env_set("name_overlays", name_overlays);
 383#endif
 384
 385        return 0;
 386}
 387#endif
 388
 389void configure_serdes_torrent(void)
 390{
 391        struct udevice *dev;
 392        struct phy serdes;
 393        int ret;
 394
 395        if (!IS_ENABLED(CONFIG_PHY_CADENCE_TORRENT))
 396                return;
 397
 398        ret = uclass_get_device_by_driver(UCLASS_PHY,
 399                                          DM_DRIVER_GET(torrent_phy_provider),
 400                                          &dev);
 401        if (ret)
 402                printf("Torrent init failed:%d\n", ret);
 403
 404        serdes.dev = dev;
 405        serdes.id = 0;
 406
 407        ret = generic_phy_init(&serdes);
 408        if (ret)
 409                printf("phy_init failed!!\n");
 410
 411        ret = generic_phy_power_on(&serdes);
 412        if (ret)
 413                printf("phy_power_on failed !!\n");
 414}
 415
 416int board_late_init(void)
 417{
 418        if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT)) {
 419                setup_board_eeprom_env();
 420                setup_serial();
 421
 422                /* Check for and probe any plugged-in daughtercards */
 423                probe_daughtercards();
 424        }
 425
 426        if (board_is_j7200_som())
 427                configure_serdes_torrent();
 428
 429        return 0;
 430}
 431
 432void spl_board_init(void)
 433{
 434#if defined(CONFIG_ESM_K3) || defined(CONFIG_ESM_PMIC)
 435        struct udevice *dev;
 436        int ret;
 437#endif
 438
 439        if ((IS_ENABLED(CONFIG_TARGET_J721E_A72_EVM) ||
 440             IS_ENABLED(CONFIG_TARGET_J7200_A72_EVM)) &&
 441            IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
 442                probe_daughtercards();
 443
 444#ifdef CONFIG_ESM_K3
 445        if (board_ti_k3_is("J721EX-PM2-SOM")) {
 446                ret = uclass_get_device_by_driver(UCLASS_MISC,
 447                                                  DM_DRIVER_GET(k3_esm), &dev);
 448                if (ret)
 449                        printf("ESM init failed: %d\n", ret);
 450        }
 451#endif
 452
 453#ifdef CONFIG_ESM_PMIC
 454        if (board_ti_k3_is("J721EX-PM2-SOM")) {
 455                ret = uclass_get_device_by_driver(UCLASS_MISC,
 456                                                  DM_DRIVER_GET(pmic_esm),
 457                                                  &dev);
 458                if (ret)
 459                        printf("ESM PMIC init failed: %d\n", ret);
 460        }
 461#endif
 462}
 463