uboot/board/ti/common/board_detect.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Library to support early TI EVM EEPROM handling
   4 *
   5 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
   6 *      Lokesh Vutla
   7 *      Steve Kipisz
   8 */
   9
  10#include <common.h>
  11#include <asm/omap_common.h>
  12#include <dm/uclass.h>
  13#include <i2c.h>
  14
  15#include "board_detect.h"
  16
  17#if !defined(CONFIG_DM_I2C)
  18/**
  19 * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device
  20 * @i2c_bus: i2c bus number to initialize
  21 * @dev_addr: Device address to probe for
  22 *
  23 * Return: 0 on success or corresponding error on failure.
  24 */
  25static int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr)
  26{
  27        int rc;
  28
  29        if (i2c_bus >= 0) {
  30                rc = i2c_set_bus_num(i2c_bus);
  31                if (rc)
  32                        return rc;
  33        }
  34
  35        return i2c_probe(dev_addr);
  36}
  37
  38/**
  39 * ti_i2c_eeprom_read - Read data from an EEPROM
  40 * @dev_addr: The device address of the EEPROM
  41 * @offset: Offset to start reading in the EEPROM
  42 * @ep: Pointer to a buffer to read into
  43 * @epsize: Size of buffer
  44 *
  45 * Return: 0 on success or corresponding result of i2c_read
  46 */
  47static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset,
  48                                             uchar *ep, int epsize)
  49{
  50        return i2c_read(dev_addr, offset, 2, ep, epsize);
  51}
  52#endif
  53
  54/**
  55 * ti_eeprom_string_cleanup() - Handle eeprom programming errors
  56 * @s:  eeprom string (should be NULL terminated)
  57 *
  58 * Some Board manufacturers do not add a NULL termination at the
  59 * end of string, instead some binary information is kludged in, hence
  60 * convert the string to just printable characters of ASCII chart.
  61 */
  62static void __maybe_unused ti_eeprom_string_cleanup(char *s)
  63{
  64        int i, l;
  65
  66        l = strlen(s);
  67        for (i = 0; i < l; i++, s++)
  68                if (*s < ' ' || *s > '~') {
  69                        *s = 0;
  70                        break;
  71                }
  72}
  73
  74__weak void gpi2c_init(void)
  75{
  76}
  77
  78static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr,
  79                                            u32 header, u32 size, uint8_t *ep)
  80{
  81        u32 hdr_read;
  82        int rc;
  83
  84#if defined(CONFIG_DM_I2C)
  85        struct udevice *dev;
  86        struct udevice *bus;
  87
  88        rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
  89        if (rc)
  90                return rc;
  91        rc = i2c_get_chip(bus, dev_addr, 1, &dev);
  92        if (rc)
  93                return rc;
  94
  95        /*
  96         * Read the header first then only read the other contents.
  97         */
  98        rc = i2c_set_chip_offset_len(dev, 2);
  99        if (rc)
 100                return rc;
 101
 102        rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
 103        if (rc)
 104                return rc;
 105
 106        /* Corrupted data??? */
 107        if (hdr_read != header) {
 108                rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
 109                /*
 110                 * read the eeprom header using i2c again, but use only a
 111                 * 1 byte address (some legacy boards need this..)
 112                 */
 113                if (rc) {
 114                        rc =  i2c_set_chip_offset_len(dev, 1);
 115                        if (rc)
 116                                return rc;
 117
 118                        rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
 119                }
 120                if (rc)
 121                        return rc;
 122        }
 123        if (hdr_read != header)
 124                return -1;
 125
 126        rc = dm_i2c_read(dev, 0, ep, size);
 127        if (rc)
 128                return rc;
 129#else
 130        u32 byte;
 131
 132        gpi2c_init();
 133        rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
 134        if (rc)
 135                return rc;
 136
 137        /*
 138         * Read the header first then only read the other contents.
 139         */
 140        byte = 2;
 141
 142        rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
 143        if (rc)
 144                return rc;
 145
 146        /* Corrupted data??? */
 147        if (hdr_read != header) {
 148                rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
 149                /*
 150                 * read the eeprom header using i2c again, but use only a
 151                 * 1 byte address (some legacy boards need this..)
 152                 */
 153                byte = 1;
 154                if (rc) {
 155                        rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read,
 156                                      4);
 157                }
 158                if (rc)
 159                        return rc;
 160        }
 161        if (hdr_read != header)
 162                return -1;
 163
 164        rc = i2c_read(dev_addr, 0x0, byte, ep, size);
 165        if (rc)
 166                return rc;
 167#endif
 168        return 0;
 169}
 170
 171int __maybe_unused ti_i2c_eeprom_am_set(const char *name, const char *rev)
 172{
 173        struct ti_common_eeprom *ep;
 174
 175        if (!name || !rev)
 176                return -1;
 177
 178        ep = TI_EEPROM_DATA;
 179        if (ep->header == TI_EEPROM_HEADER_MAGIC)
 180                goto already_set;
 181
 182        /* Set to 0 all fields */
 183        memset(ep, 0, sizeof(*ep));
 184        strncpy(ep->name, name, TI_EEPROM_HDR_NAME_LEN);
 185        strncpy(ep->version, rev, TI_EEPROM_HDR_REV_LEN);
 186        /* Some dummy serial number to identify the platform */
 187        strncpy(ep->serial, "0000", TI_EEPROM_HDR_SERIAL_LEN);
 188        /* Mark it with a valid header */
 189        ep->header = TI_EEPROM_HEADER_MAGIC;
 190
 191already_set:
 192        return 0;
 193}
 194
 195int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
 196{
 197        int rc;
 198        struct ti_am_eeprom am_ep;
 199        struct ti_common_eeprom *ep;
 200
 201        ep = TI_EEPROM_DATA;
 202#ifndef CONFIG_SPL_BUILD
 203        if (ep->header == TI_EEPROM_HEADER_MAGIC)
 204                return 0; /* EEPROM has already been read */
 205#endif
 206
 207        /* Initialize with a known bad marker for i2c fails.. */
 208        ep->header = TI_DEAD_EEPROM_MAGIC;
 209        ep->name[0] = 0x0;
 210        ep->version[0] = 0x0;
 211        ep->serial[0] = 0x0;
 212        ep->config[0] = 0x0;
 213
 214        rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
 215                               sizeof(am_ep), (uint8_t *)&am_ep);
 216        if (rc)
 217                return rc;
 218
 219        ep->header = am_ep.header;
 220        strlcpy(ep->name, am_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
 221        ti_eeprom_string_cleanup(ep->name);
 222
 223        /* BeagleBone Green '1' eeprom, board_rev: 0x1a 0x00 0x00 0x00 */
 224        if (am_ep.version[0] == 0x1a && am_ep.version[1] == 0x00 &&
 225            am_ep.version[2] == 0x00 && am_ep.version[3] == 0x00)
 226                strlcpy(ep->version, "BBG1", TI_EEPROM_HDR_REV_LEN + 1);
 227        else
 228                strlcpy(ep->version, am_ep.version, TI_EEPROM_HDR_REV_LEN + 1);
 229        ti_eeprom_string_cleanup(ep->version);
 230        strlcpy(ep->serial, am_ep.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
 231        ti_eeprom_string_cleanup(ep->serial);
 232        strlcpy(ep->config, am_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
 233        ti_eeprom_string_cleanup(ep->config);
 234
 235        memcpy(ep->mac_addr, am_ep.mac_addr,
 236               TI_EEPROM_HDR_NO_OF_MAC_ADDR * TI_EEPROM_HDR_ETH_ALEN);
 237
 238        return 0;
 239}
 240
 241int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr)
 242{
 243        int rc, offset = 0;
 244        struct dra7_eeprom dra7_ep;
 245        struct ti_common_eeprom *ep;
 246
 247        ep = TI_EEPROM_DATA;
 248#ifndef CONFIG_SPL_BUILD
 249        if (ep->header == DRA7_EEPROM_HEADER_MAGIC)
 250                return 0; /* EEPROM has already been read */
 251#endif
 252
 253        /* Initialize with a known bad marker for i2c fails.. */
 254        ep->header = TI_DEAD_EEPROM_MAGIC;
 255        ep->name[0] = 0x0;
 256        ep->version[0] = 0x0;
 257        ep->serial[0] = 0x0;
 258        ep->config[0] = 0x0;
 259        ep->emif1_size = 0;
 260        ep->emif2_size = 0;
 261
 262        rc = ti_i2c_eeprom_get(bus_addr, dev_addr, DRA7_EEPROM_HEADER_MAGIC,
 263                               sizeof(dra7_ep), (uint8_t *)&dra7_ep);
 264        if (rc)
 265                return rc;
 266
 267        ep->header = dra7_ep.header;
 268        strlcpy(ep->name, dra7_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
 269        ti_eeprom_string_cleanup(ep->name);
 270
 271        offset = dra7_ep.version_major - 1;
 272
 273        /* Rev F is skipped */
 274        if (offset >= 5)
 275                offset = offset + 1;
 276        snprintf(ep->version, TI_EEPROM_HDR_REV_LEN + 1, "%c.%d",
 277                 'A' + offset, dra7_ep.version_minor);
 278        ti_eeprom_string_cleanup(ep->version);
 279        ep->emif1_size = (u64)dra7_ep.emif1_size;
 280        ep->emif2_size = (u64)dra7_ep.emif2_size;
 281        strlcpy(ep->config, dra7_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
 282        ti_eeprom_string_cleanup(ep->config);
 283
 284        return 0;
 285}
 286
 287bool __maybe_unused board_ti_is(char *name_tag)
 288{
 289        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 290
 291        if (ep->header == TI_DEAD_EEPROM_MAGIC)
 292                return false;
 293        return !strncmp(ep->name, name_tag, TI_EEPROM_HDR_NAME_LEN);
 294}
 295
 296bool __maybe_unused board_ti_rev_is(char *rev_tag, int cmp_len)
 297{
 298        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 299        int l;
 300
 301        if (ep->header == TI_DEAD_EEPROM_MAGIC)
 302                return false;
 303
 304        l = cmp_len > TI_EEPROM_HDR_REV_LEN ? TI_EEPROM_HDR_REV_LEN : cmp_len;
 305        return !strncmp(ep->version, rev_tag, l);
 306}
 307
 308char * __maybe_unused board_ti_get_rev(void)
 309{
 310        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 311
 312        /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
 313        return ep->version;
 314}
 315
 316char * __maybe_unused board_ti_get_config(void)
 317{
 318        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 319
 320        /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
 321        return ep->config;
 322}
 323
 324char * __maybe_unused board_ti_get_name(void)
 325{
 326        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 327
 328        /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
 329        return ep->name;
 330}
 331
 332void __maybe_unused
 333board_ti_get_eth_mac_addr(int index,
 334                          u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
 335{
 336        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 337
 338        if (ep->header == TI_DEAD_EEPROM_MAGIC)
 339                goto fail;
 340
 341        if (index < 0 || index >= TI_EEPROM_HDR_NO_OF_MAC_ADDR)
 342                goto fail;
 343
 344        memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
 345        return;
 346
 347fail:
 348        memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
 349}
 350
 351u64 __maybe_unused board_ti_get_emif1_size(void)
 352{
 353        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 354
 355        if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
 356                return 0;
 357
 358        return ep->emif1_size;
 359}
 360
 361u64 __maybe_unused board_ti_get_emif2_size(void)
 362{
 363        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 364
 365        if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
 366                return 0;
 367
 368        return ep->emif2_size;
 369}
 370
 371void __maybe_unused set_board_info_env(char *name)
 372{
 373        char *unknown = "unknown";
 374        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 375
 376        if (name)
 377                env_set("board_name", name);
 378        else if (ep->name)
 379                env_set("board_name", ep->name);
 380        else
 381                env_set("board_name", unknown);
 382
 383        if (ep->version)
 384                env_set("board_rev", ep->version);
 385        else
 386                env_set("board_rev", unknown);
 387
 388        if (ep->serial)
 389                env_set("board_serial", ep->serial);
 390        else
 391                env_set("board_serial", unknown);
 392}
 393
 394static u64 mac_to_u64(u8 mac[6])
 395{
 396        int i;
 397        u64 addr = 0;
 398
 399        for (i = 0; i < 6; i++) {
 400                addr <<= 8;
 401                addr |= mac[i];
 402        }
 403
 404        return addr;
 405}
 406
 407static void u64_to_mac(u64 addr, u8 mac[6])
 408{
 409        mac[5] = addr;
 410        mac[4] = addr >> 8;
 411        mac[3] = addr >> 16;
 412        mac[2] = addr >> 24;
 413        mac[1] = addr >> 32;
 414        mac[0] = addr >> 40;
 415}
 416
 417void board_ti_set_ethaddr(int index)
 418{
 419        uint8_t mac_addr[6];
 420        int i;
 421        u64 mac1, mac2;
 422        u8 mac_addr1[6], mac_addr2[6];
 423        int num_macs;
 424        /*
 425         * Export any Ethernet MAC addresses from EEPROM.
 426         * The 2 MAC addresses in EEPROM define the address range.
 427         */
 428        board_ti_get_eth_mac_addr(0, mac_addr1);
 429        board_ti_get_eth_mac_addr(1, mac_addr2);
 430
 431        if (is_valid_ethaddr(mac_addr1) && is_valid_ethaddr(mac_addr2)) {
 432                mac1 = mac_to_u64(mac_addr1);
 433                mac2 = mac_to_u64(mac_addr2);
 434
 435                /* must contain an address range */
 436                num_macs = mac2 - mac1 + 1;
 437                if (num_macs <= 0)
 438                        return;
 439
 440                if (num_macs > 50) {
 441                        printf("%s: Too many MAC addresses: %d. Limiting to 50\n",
 442                               __func__, num_macs);
 443                        num_macs = 50;
 444                }
 445
 446                for (i = 0; i < num_macs; i++) {
 447                        u64_to_mac(mac1 + i, mac_addr);
 448                        if (is_valid_ethaddr(mac_addr)) {
 449                                eth_env_set_enetaddr_by_index("eth", i + index,
 450                                                              mac_addr);
 451                        }
 452                }
 453        }
 454}
 455
 456bool __maybe_unused board_ti_was_eeprom_read(void)
 457{
 458        struct ti_common_eeprom *ep = TI_EEPROM_DATA;
 459
 460        if (ep->header == TI_EEPROM_HEADER_MAGIC)
 461                return true;
 462        else
 463                return false;
 464}
 465