uboot/board/ti/am65x/evm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Board specific initialization for AM654 EVM
   4 *
   5 * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
   6 *      Lokesh Vutla <lokeshvutla@ti.com>
   7 *
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <init.h>
  13#include <asm/arch/sys_proto.h>
  14#include <asm/arch/hardware.h>
  15#include <asm/gpio.h>
  16#include <asm/io.h>
  17#include <asm/omap_common.h>
  18#include <env.h>
  19#include <spl.h>
  20#include <asm/arch/sys_proto.h>
  21
  22#include "../common/board_detect.h"
  23
  24#define board_is_am65x_base_board()     board_ti_is("AM6-COMPROCEVM")
  25
  26/* Daughter card presence detection signals */
  27enum {
  28        AM65X_EVM_APP_BRD_DET,
  29        AM65X_EVM_LCD_BRD_DET,
  30        AM65X_EVM_SERDES_BRD_DET,
  31        AM65X_EVM_HDMI_GPMC_BRD_DET,
  32        AM65X_EVM_BRD_DET_COUNT,
  33};
  34
  35/* Max number of MAC addresses that are parsed/processed per daughter card */
  36#define DAUGHTER_CARD_NO_OF_MAC_ADDR    8
  37
  38DECLARE_GLOBAL_DATA_PTR;
  39
  40int board_init(void)
  41{
  42        return 0;
  43}
  44
  45int dram_init(void)
  46{
  47#ifdef CONFIG_PHYS_64BIT
  48        gd->ram_size = 0x100000000;
  49#else
  50        gd->ram_size = 0x80000000;
  51#endif
  52
  53        return 0;
  54}
  55
  56ulong board_get_usable_ram_top(ulong total_size)
  57{
  58#ifdef CONFIG_PHYS_64BIT
  59        /* Limit RAM used by U-Boot to the DDR low region */
  60        if (gd->ram_top > 0x100000000)
  61                return 0x100000000;
  62#endif
  63
  64        return gd->ram_top;
  65}
  66
  67int dram_init_banksize(void)
  68{
  69        /* Bank 0 declares the memory available in the DDR low region */
  70        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
  71        gd->bd->bi_dram[0].size = 0x80000000;
  72
  73#ifdef CONFIG_PHYS_64BIT
  74        /* Bank 1 declares the memory available in the DDR high region */
  75        gd->bd->bi_dram[1].start = CONFIG_SYS_SDRAM_BASE1;
  76        gd->bd->bi_dram[1].size = 0x80000000;
  77#endif
  78
  79        return 0;
  80}
  81
  82#ifdef CONFIG_SPL_LOAD_FIT
  83int board_fit_config_name_match(const char *name)
  84{
  85#ifdef CONFIG_TARGET_AM654_A53_EVM
  86        if (!strcmp(name, "k3-am654-base-board"))
  87                return 0;
  88#endif
  89
  90        return -1;
  91}
  92#endif
  93
  94#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
  95int ft_board_setup(void *blob, bd_t *bd)
  96{
  97        int ret;
  98
  99        ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000", "sram@70000000");
 100        if (ret) {
 101                printf("%s: fixing up msmc ram failed %d\n", __func__, ret);
 102                return ret;
 103        }
 104
 105#if defined(CONFIG_TI_SECURE_DEVICE)
 106        /* Make HW RNG reserved for secure world use */
 107        ret = fdt_disable_node(blob, "/interconnect@100000/trng@4e10000");
 108        if (ret) {
 109                printf("%s: disabling TRGN failed %d\n", __func__, ret);
 110                return ret;
 111        }
 112#endif
 113
 114        return 0;
 115}
 116#endif
 117
 118int do_board_detect(void)
 119{
 120        int ret;
 121
 122        ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
 123                                         CONFIG_EEPROM_CHIP_ADDRESS);
 124        if (ret)
 125                pr_err("Reading on-board EEPROM at 0x%02x failed %d\n",
 126                       CONFIG_EEPROM_CHIP_ADDRESS, ret);
 127
 128        return ret;
 129}
 130
 131int checkboard(void)
 132{
 133        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 134
 135        if (do_board_detect())
 136                /* EEPROM not populated */
 137                printf("Board: %s rev %s\n", "AM6-COMPROCEVM", "E3");
 138        else
 139                printf("Board: %s rev %s\n", ep->name, ep->version);
 140
 141        return 0;
 142}
 143
 144static void setup_board_eeprom_env(void)
 145{
 146        char *name = "am65x";
 147
 148        if (do_board_detect())
 149                goto invalid_eeprom;
 150
 151        if (board_is_am65x_base_board())
 152                name = "am65x";
 153        else
 154                printf("Unidentified board claims %s in eeprom header\n",
 155                       board_ti_get_name());
 156
 157invalid_eeprom:
 158        set_board_info_env_am6(name);
 159}
 160
 161static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc)
 162{
 163        int ret;
 164
 165        memset(desc, 0, sizeof(*desc));
 166
 167        ret = dm_gpio_lookup_name(gpio_name, desc);
 168        if (ret < 0)
 169                return ret;
 170
 171        /* Request GPIO, simply re-using the name as label */
 172        ret = dm_gpio_request(desc, gpio_name);
 173        if (ret < 0)
 174                return ret;
 175
 176        return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN);
 177}
 178
 179static int probe_daughtercards(void)
 180{
 181        struct ti_am6_eeprom ep;
 182        struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT];
 183        char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
 184        u8 mac_addr_cnt;
 185        char name_overlays[1024] = { 0 };
 186        int i, j;
 187        int ret;
 188
 189        /*
 190         * Daughter card presence detection signal name to GPIO (via I2C I/O
 191         * expander @ address 0x38) name and EEPROM I2C address mapping.
 192         */
 193        const struct {
 194                char *gpio_name;
 195                u8 i2c_addr;
 196        } slot_map[AM65X_EVM_BRD_DET_COUNT] = {
 197                { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */
 198                { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */
 199                { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */
 200                { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */
 201        };
 202
 203        /* Declaration of daughtercards to probe */
 204        const struct {
 205                u8 slot_index;          /* Slot the card is installed */
 206                char *card_name;        /* EEPROM-programmed card name */
 207                char *dtbo_name;        /* Device tree overlay to apply */
 208                u8 eth_offset;          /* ethXaddr MAC address index offset */
 209        } cards[] = {
 210                {
 211                        AM65X_EVM_APP_BRD_DET,
 212                        "AM6-GPAPPEVM",
 213                        "k3-am654-gp.dtbo",
 214                        0,
 215                },
 216                {
 217                        AM65X_EVM_APP_BRD_DET,
 218                        "AM6-IDKAPPEVM",
 219                        "k3-am654-idk.dtbo",
 220                        3,
 221                },
 222                {
 223                        AM65X_EVM_SERDES_BRD_DET,
 224                        "SER-PCIE2LEVM",
 225                        "k3-am654-pcie-usb2.dtbo",
 226                        0,
 227                },
 228                {
 229                        AM65X_EVM_SERDES_BRD_DET,
 230                        "SER-PCIEUSBEVM",
 231                        "k3-am654-pcie-usb3.dtbo",
 232                        0,
 233                },
 234                {
 235                        AM65X_EVM_LCD_BRD_DET,
 236                        "OLDI-LCD1EVM",
 237                        "k3-am654-evm-oldi-lcd1evm.dtbo",
 238                        0,
 239                },
 240        };
 241
 242        /*
 243         * Initialize GPIO used for daughtercard slot presence detection and
 244         * keep the resulting handles in local array for easier access.
 245         */
 246        for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) {
 247                ret = init_daughtercard_det_gpio(slot_map[i].gpio_name,
 248                                                 &board_det_gpios[i]);
 249                if (ret < 0)
 250                        return ret;
 251        }
 252
 253        for (i = 0; i < ARRAY_SIZE(cards); i++) {
 254                /* Obtain card-specific slot index and associated I2C address */
 255                u8 slot_index = cards[i].slot_index;
 256                u8 i2c_addr = slot_map[slot_index].i2c_addr;
 257
 258                /*
 259                 * The presence detection signal is active-low, hence skip
 260                 * over this card slot if anything other than 0 is returned.
 261                 */
 262                ret = dm_gpio_get_value(&board_det_gpios[slot_index]);
 263                if (ret < 0)
 264                        return ret;
 265                else if (ret)
 266                        continue;
 267
 268                /* Get and parse the daughter card EEPROM record */
 269                ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr,
 270                                            &ep,
 271                                            (char **)mac_addr,
 272                                            DAUGHTER_CARD_NO_OF_MAC_ADDR,
 273                                            &mac_addr_cnt);
 274                if (ret) {
 275                        pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n",
 276                               i2c_addr, ret);
 277                        /*
 278                         * Even this is pretty serious let's just skip over
 279                         * this particular daughtercard, rather than ending
 280                         * the probing process altogether.
 281                         */
 282                        continue;
 283                }
 284
 285                /* Only process the parsed data if we found a match */
 286                if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
 287                        continue;
 288
 289                printf("Detected: %s rev %s\n", ep.name, ep.version);
 290
 291                /*
 292                 * Populate any MAC addresses from daughtercard into the U-Boot
 293                 * environment, starting with a card-specific offset so we can
 294                 * have multiple cards contribute to the MAC pool in a well-
 295                 * defined manner.
 296                 */
 297                for (j = 0; j < mac_addr_cnt; j++) {
 298                        if (!is_valid_ethaddr((u8 *)mac_addr[j]))
 299                                continue;
 300
 301                        eth_env_set_enetaddr_by_index("eth",
 302                                                      cards[i].eth_offset + j,
 303                                                      (uchar *)mac_addr[j]);
 304                }
 305
 306                /* Skip if no overlays are to be added */
 307                if (!strlen(cards[i].dtbo_name))
 308                        continue;
 309
 310                /*
 311                 * Make sure we are not running out of buffer space by checking
 312                 * if we can fit the new overlay, a trailing space to be used
 313                 * as a separator, plus the terminating zero.
 314                 */
 315                if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 >
 316                    sizeof(name_overlays))
 317                        return -ENOMEM;
 318
 319                /* Append to our list of overlays */
 320                strcat(name_overlays, cards[i].dtbo_name);
 321                strcat(name_overlays, " ");
 322        }
 323
 324        /* Apply device tree overlay(s) to the U-Boot environment, if any */
 325        if (strlen(name_overlays))
 326                return env_set("name_overlays", name_overlays);
 327
 328        return 0;
 329}
 330
 331int board_late_init(void)
 332{
 333        struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
 334
 335        setup_board_eeprom_env();
 336
 337        /*
 338         * The first MAC address for ethernet a.k.a. ethernet0 comes from
 339         * efuse populated via the am654 gigabit eth switch subsystem driver.
 340         * All the other ones are populated via EEPROM, hence continue with
 341         * an index of 1.
 342         */
 343        board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt);
 344
 345        /* Check for and probe any plugged-in daughtercards */
 346        probe_daughtercards();
 347
 348        return 0;
 349}
 350