uboot/board/ge/b1x5v2/b1x5v2.c
<<
>>
Prefs
   1/*
   2 * GE B105v2, B125v2, B155v2
   3 *
   4 * Copyright 2018-2020 GE Inc.
   5 * Copyright 2018-2020 Collabora Ltd.
   6 *
   7 * SPDX-License-Identifier:    GPL-2.0+
   8 */
   9
  10#include <asm/arch/clock.h>
  11#include <asm/arch/crm_regs.h>
  12#include <asm/arch/imx-regs.h>
  13#include <asm/arch/iomux.h>
  14#include <asm/arch/sys_proto.h>
  15#include <asm/global_data.h>
  16#include <asm/gpio.h>
  17#include <asm/io.h>
  18#include <asm/mach-imx/video.h>
  19#include <command.h>
  20#include <common.h>
  21#include <i2c.h>
  22#include <input.h>
  23#include <ipu_pixfmt.h>
  24#include <linux/delay.h>
  25#include <linux/fb.h>
  26#include <malloc.h>
  27#include <miiphy.h>
  28#include <micrel.h>
  29#include <netdev.h>
  30#include <panel.h>
  31#include <rtc.h>
  32#include <spi_flash.h>
  33#include <version_string.h>
  34
  35#include "../common/vpd_reader.h"
  36
  37DECLARE_GLOBAL_DATA_PTR;
  38
  39#ifndef CONFIG_SPL_BUILD
  40
  41#define B1X5V2_GE_VPD_OFFSET    0x0100000
  42#define B1X5V2_GE_VPD_SIZE      1022
  43
  44#define VPD_TYPE_INVALID        0x00
  45#define VPD_BLOCK_NETWORK       0x20
  46#define VPD_BLOCK_HWID          0x44
  47#define VPD_MAC_ADDRESS_LENGTH  6
  48
  49#define VPD_FLAG_VALID_MAC      BIT(1)
  50
  51#define AR8035_PHY_ID                   0x004dd072
  52#define AR8035_PHY_DEBUG_ADDR_REG       0x1d
  53#define AR8035_PHY_DEBUG_DATA_REG       0x1e
  54#define AR8035_HIB_CTRL_REG             0xb
  55#define AR8035_HIBERNATE_EN             (1 << 15)
  56
  57static struct vpd_cache {
  58        bool is_read;
  59        u8 product_id;
  60        unsigned char mac[VPD_MAC_ADDRESS_LENGTH];
  61        u32 flags;
  62} vpd;
  63
  64enum product_type {
  65        PRODUCT_TYPE_B105V2 = 6,
  66        PRODUCT_TYPE_B105PV2 = 7,
  67        PRODUCT_TYPE_B125V2 = 8,
  68        PRODUCT_TYPE_B125PV2 = 9,
  69        PRODUCT_TYPE_B155V2 = 10,
  70
  71        PRODUCT_TYPE_INVALID = 0,
  72};
  73
  74int dram_init(void) {
  75        gd->ram_size = imx_ddr_size();
  76        return 0;
  77}
  78
  79int power_init_board(void)
  80{
  81        /* all required PMIC configuration happens via DT */
  82        return 0;
  83}
  84
  85static int disable_phy_hibernation(struct phy_device *phydev)
  86{
  87        unsigned short val;
  88
  89        if (phydev->drv->uid == AR8035_PHY_ID) {
  90                /* Disable hibernation, other configuration has been done by PHY driver */
  91                phy_write(phydev, MDIO_DEVAD_NONE, AR8035_PHY_DEBUG_ADDR_REG, AR8035_HIB_CTRL_REG);
  92                val = phy_read(phydev, MDIO_DEVAD_NONE, AR8035_PHY_DEBUG_DATA_REG);
  93                val &= ~AR8035_HIBERNATE_EN;
  94                phy_write(phydev, MDIO_DEVAD_NONE, AR8035_PHY_DEBUG_DATA_REG, val);
  95        } else {
  96                printf("Unknown PHY: %08x\n", phydev->drv->uid);
  97        }
  98
  99        return 0;
 100}
 101
 102int board_phy_config(struct phy_device *phydev)
 103{
 104        if (phydev->drv->config)
 105                phydev->drv->config(phydev);
 106
 107        disable_phy_hibernation(phydev);
 108
 109        return 0;
 110}
 111
 112static int auo_g101evn01_detect(const struct display_info_t *info)
 113{
 114        char *dev = env_get("devicetype");
 115        return !strcmp(dev, "B105v2") || !strcmp(dev, "B105Pv2");
 116}
 117
 118static int auo_g121ean01_detect(const struct display_info_t *info)
 119{
 120        char *dev = env_get("devicetype");
 121        return !strcmp(dev, "B125v2") || !strcmp(dev, "B125Pv2");;
 122}
 123
 124static int auo_g156xtn01_detect(const struct display_info_t *info)
 125{
 126        char *dev = env_get("devicetype");
 127        return !strcmp(dev, "B155v2");
 128}
 129
 130static void b1x5v2_backlight_enable(int percent)
 131{
 132        struct udevice *panel;
 133        int ret;
 134
 135        ret = uclass_get_device(UCLASS_PANEL, 0, &panel);
 136        if (ret) {
 137                printf("Could not find panel: %d\n", ret);
 138                return;
 139        }
 140
 141        panel_set_backlight(panel, percent);
 142        panel_enable_backlight(panel);
 143
 144}
 145
 146static void lcd_enable(const struct display_info_t *info)
 147{
 148        printf("Enable backlight...\n");
 149        b1x5v2_backlight_enable(100);
 150}
 151
 152struct display_info_t const displays[] = {
 153{
 154        .di = 0,
 155        .bus = -1,
 156        .addr = -1,
 157        .pixfmt = IPU_PIX_FMT_RGB24,
 158        .detect = auo_g156xtn01_detect,
 159        .enable = lcd_enable,
 160        .mode = {
 161                .name = "AUO G156XTN01",
 162                .refresh = 60,
 163                .xres = 1368, /* because of i.MX6 limitation, actually 1366 */
 164                .yres = 768,
 165                .pixclock = 13158, /* 76 MHz in ps */
 166                .left_margin = 33,
 167                .right_margin = 67,
 168                .upper_margin = 4,
 169                .lower_margin = 4,
 170                .hsync_len = 94,
 171                .vsync_len = 30,
 172                .sync = FB_SYNC_EXT,
 173                .vmode = FB_VMODE_NONINTERLACED
 174        }
 175},
 176{
 177        .di = 0,
 178        .bus = -1,
 179        .addr = -1,
 180        .pixfmt = IPU_PIX_FMT_RGB24,
 181        .detect = auo_g121ean01_detect,
 182        .enable = lcd_enable,
 183        .mode = {
 184                .name = "AUO G121EAN01.4",
 185                .refresh = 60,
 186                .xres = 1280,
 187                .yres = 800,
 188                .pixclock = 14992, /* 66.7 MHz in ps */
 189                .left_margin = 8,
 190                .right_margin = 58,
 191                .upper_margin = 6,
 192                .lower_margin = 4,
 193                .hsync_len = 70,
 194                .vsync_len = 10,
 195                .sync = FB_SYNC_EXT,
 196                .vmode = FB_VMODE_NONINTERLACED
 197        }
 198},
 199{
 200        .di = 0,
 201        .bus = -1,
 202        .addr = -1,
 203        .pixfmt = IPU_PIX_FMT_RGB24,
 204        .detect = auo_g101evn01_detect,
 205        .enable = lcd_enable,
 206        .mode = {
 207                .name = "AUO G101EVN01.3",
 208                .refresh = 60,
 209                .xres = 1280,
 210                .yres = 800,
 211                .pixclock = 14992, /* 66.7 MHz in ps */
 212                .left_margin = 8,
 213                .right_margin = 58,
 214                .upper_margin = 6,
 215                .lower_margin = 4,
 216                .hsync_len = 70,
 217                .vsync_len = 10,
 218                .sync = FB_SYNC_EXT,
 219                .vmode = FB_VMODE_NONINTERLACED
 220        }
 221}
 222};
 223size_t display_count = ARRAY_SIZE(displays);
 224
 225static void enable_videopll(void)
 226{
 227        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 228        s32 timeout = 100000;
 229
 230        setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
 231
 232        /* PLL_VIDEO  455MHz (24MHz * (37+11/12) / 2)
 233         *   |
 234         * PLL5
 235         *   |
 236         * CS2CDR[LDB_DI0_CLK_SEL]
 237         *   |
 238         *   +----> LDB_DI0_SERIAL_CLK_ROOT
 239         *   |
 240         *   +--> CSCMR2[LDB_DI0_IPU_DIV] --> LDB_DI0_IPU  455 / 7 = 65 MHz
 241         */
 242
 243        clrsetbits_le32(&ccm->analog_pll_video,
 244                        BM_ANADIG_PLL_VIDEO_DIV_SELECT |
 245                        BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
 246                        BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) |
 247                        BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1));
 248
 249        writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
 250        writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
 251
 252        clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
 253
 254        while (timeout--)
 255                if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
 256                        break;
 257
 258        if (timeout < 0)
 259                printf("Warning: video pll lock timeout!\n");
 260
 261        clrsetbits_le32(&ccm->analog_pll_video,
 262                        BM_ANADIG_PLL_VIDEO_BYPASS,
 263                        BM_ANADIG_PLL_VIDEO_ENABLE);
 264}
 265
 266static void setup_display(void)
 267{
 268        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 269        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 270
 271        enable_videopll();
 272
 273        /* When a reset/reboot is performed the display power needs to be turned
 274         * off for atleast 500ms. The boot time is ~300ms, we need to wait for
 275         * an additional 200ms here. Unfortunately we use external PMIC for
 276         * doing the reset, so can not differentiate between POR vs soft reset
 277         */
 278        mdelay(200);
 279
 280        /* CCM_CSCMR2 -> ldb_di0_ipu_div [IMX6SDLRM page 839] */
 281        /* divide IPU clock by 7 */
 282        setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
 283
 284        /* CCM_CHSCCDR -> ipu1_di0_clk_sel [IMX6SDLRM page 849] */
 285        /* Set LDB_DI0 as clock source for IPU_DI0 */
 286        clrsetbits_le32(&mxc_ccm->chsccdr,
 287                        MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
 288                        (CHSCCDR_CLK_SEL_LDB_DI0 <<
 289                        MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
 290
 291        /* Turn on IPU LDB DI0 clocks */
 292        setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
 293
 294        enable_ipu_clock();
 295
 296        /* IOMUXC_GPR2 [IMX6SDLRM page 2049] */
 297        /* Set LDB Channel 0 in SPWG 24 Bit mode */
 298        writel(IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_HIGH |
 299               IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
 300               IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
 301               IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
 302               &iomux->gpr[2]);
 303
 304        /* IOMUXC_GPR3 [IMX6SDLRM page 2051] */
 305        /* LVDS0 is connected to IPU DI0 */
 306        clrsetbits_le32(&iomux->gpr[3],
 307                        IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
 308                       (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
 309                        IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET));
 310}
 311
 312/*
 313 * Do not overwrite the console
 314 * Use always serial for U-Boot console
 315 */
 316int overwrite_console(void)
 317{
 318        return 1;
 319}
 320
 321int board_early_init_f(void)
 322{
 323        select_ldb_di_clock_source(MXC_PLL5_CLK);
 324
 325        return 0;
 326}
 327
 328static int eeti_touch_get_model(struct udevice *dev, char *result) {
 329        u8 query[68] = {0x67, 0x00, 0x42, 0x00, 0x03, 0x01, 'E', 0x00, 0x00, 0x00};
 330        struct i2c_msg qmsg = {
 331                .addr = 0x2a,
 332                .flags = 0,
 333                .len = sizeof(query),
 334                .buf = query,
 335        };
 336        u8 reply[66] = {0};
 337        struct i2c_msg rmsg = {
 338                .addr = 0x2a,
 339                .flags = I2C_M_RD,
 340                .len = sizeof(reply),
 341                .buf = reply,
 342        };
 343        int err;
 344
 345        err = dm_i2c_xfer(dev, &qmsg, 1);
 346        if (err)
 347                return err;
 348
 349        /*
 350         * device sends IRQ when its ok to read. To keep the code
 351         * simple we just wait an arbitrary, long enough time period.
 352         */
 353        mdelay(10);
 354
 355        err = dm_i2c_xfer(dev, &rmsg, 1);
 356        if (err)
 357                return err;
 358
 359        if (reply[0] != 0x42 || reply[1] != 0x00 ||
 360            reply[2] != 0x03 || reply[4] != 'E')
 361                return -EPROTO;
 362
 363        memcpy(result, reply+5, 10);
 364        return 0;
 365}
 366
 367static bool b1x5v2_board_is_p_model(void)
 368{
 369        struct udevice *bus = NULL;
 370        struct udevice *dev = NULL;
 371        int err;
 372
 373        err = uclass_get_device_by_name(UCLASS_I2C, "i2c@21a0000", &bus);
 374        if (err || !bus) {
 375                printf("Could not get I2C bus: %d\n", err);
 376                return true;
 377        }
 378
 379        /* The P models do not have this port expander */
 380        err = dm_i2c_probe(bus, 0x21, 0, &dev);
 381        if (err || !dev) {
 382                return true;
 383        }
 384
 385        return false;
 386}
 387
 388static enum product_type b1x5v2_board_type(void)
 389{
 390        struct udevice *bus = NULL;
 391        struct udevice *dev = NULL;
 392        char model[11] = {0};
 393        int err;
 394        int retry;
 395
 396        err = uclass_get_device_by_name(UCLASS_I2C, "i2c@21a8000", &bus);
 397        if (err) {
 398                printf("Could not get I2C bus: %d\n", err);
 399                return PRODUCT_TYPE_INVALID;
 400        }
 401
 402        err = dm_i2c_probe(bus, 0x41, 0, &dev);
 403        if (!err && dev) { /* Ilitek Touchscreen */
 404                if (b1x5v2_board_is_p_model()) {
 405                        return PRODUCT_TYPE_B105PV2;
 406                } else {
 407                        return PRODUCT_TYPE_B105V2;
 408                }
 409        }
 410
 411        err = dm_i2c_probe(bus, 0x2a, 0, &dev);
 412        if (err || !dev) {
 413                printf("Could not find touchscreen: %d\n", err);
 414                return PRODUCT_TYPE_INVALID;
 415        }
 416
 417        for (retry = 0; retry < 3; ++retry) {
 418                err = eeti_touch_get_model(dev, model);
 419                if (!err)
 420                        break;
 421                printf("Retry %d read EETI touchscreen model: %d\n", retry + 1, err);
 422        }
 423        if (err) {
 424                printf("Could not read EETI touchscreen model: %d\n", err);
 425                return PRODUCT_TYPE_INVALID;
 426        }
 427
 428        if (!strcmp(model, "Orion_1320")) { /* EETI EXC80H60 */
 429                if (b1x5v2_board_is_p_model()) {
 430                        return PRODUCT_TYPE_B125PV2;
 431                } else {
 432                        return PRODUCT_TYPE_B125V2;
 433                }
 434        } else if (!strcmp(model, "Orion_1343")) { /* EETI EXC80H84 */
 435                return PRODUCT_TYPE_B155V2;
 436        }
 437
 438        printf("Unknown EETI touchscreen model: %s\n", model);
 439        return PRODUCT_TYPE_INVALID;
 440}
 441
 442static void set_env_per_board_type(enum product_type type)
 443{
 444        switch (type) {
 445        case PRODUCT_TYPE_B105V2:
 446                env_set("resolution", "1280x800");
 447                env_set("devicetype", "B105v2");
 448                env_set("fdtfile", "imx6dl-b105v2.dtb");
 449                break;
 450        case PRODUCT_TYPE_B105PV2:
 451                env_set("resolution", "1280x800");
 452                env_set("devicetype", "B105Pv2");
 453                env_set("fdtfile", "imx6dl-b105pv2.dtb");
 454                break;
 455        case PRODUCT_TYPE_B125V2:
 456                env_set("resolution", "1280x800");
 457                env_set("devicetype", "B125v2");
 458                env_set("fdtfile", "imx6dl-b125v2.dtb");
 459                break;
 460        case PRODUCT_TYPE_B125PV2:
 461                env_set("resolution", "1280x800");
 462                env_set("devicetype", "B125Pv2");
 463                env_set("fdtfile", "imx6dl-b125pv2.dtb");
 464                break;
 465        case PRODUCT_TYPE_B155V2:
 466                env_set("resolution", "1366x768");
 467                env_set("devicetype", "B155v2");
 468                env_set("fdtfile", "imx6dl-b155v2.dtb");
 469                break;
 470        default:
 471                break;
 472        }
 473}
 474
 475static int b1x5v2_board_type_autodetect(void)
 476{
 477        enum product_type product = b1x5v2_board_type();
 478        if (product != PRODUCT_TYPE_INVALID) {
 479                set_env_per_board_type(product);
 480                return 0;
 481        }
 482        return -1;
 483}
 484
 485/*
 486 * Extracts MAC and product information from the VPD.
 487 */
 488static int vpd_callback(struct vpd_cache *vpd, u8 id, u8 version, u8 type,
 489                        size_t size, u8 const *data)
 490{
 491        if (type == VPD_TYPE_INVALID)
 492                return 0;
 493
 494        if (id == VPD_BLOCK_HWID && version == 1 && size >= 1) {
 495                vpd->product_id = data[0];
 496        } else if (id == VPD_BLOCK_NETWORK && version == 1) {
 497                if (size >= VPD_MAC_ADDRESS_LENGTH) {
 498                        memcpy(vpd->mac, data, VPD_MAC_ADDRESS_LENGTH);
 499                        vpd->flags |= VPD_FLAG_VALID_MAC;
 500                }
 501        }
 502
 503        return 0;
 504}
 505
 506static int read_spi_vpd(struct vpd_cache *cache,
 507                 int (*process_block)(struct vpd_cache *, u8 id, u8 version,
 508                                      u8 type, size_t size, u8 const *data))
 509{
 510        static const int size = B1X5V2_GE_VPD_SIZE;
 511        struct udevice *dev;
 512        int ret;
 513        u8 *data;
 514
 515        ret = uclass_get_device_by_name(UCLASS_SPI_FLASH, "m25p80@0", &dev);
 516        if (ret)
 517                return ret;
 518
 519        data = malloc(size);
 520        if (!data)
 521                return -ENOMEM;
 522
 523        ret = spi_flash_read_dm(dev, B1X5V2_GE_VPD_OFFSET, size, data);
 524        if (ret) {
 525                free(data);
 526                return ret;
 527        }
 528
 529        ret = vpd_reader(size, data, cache, process_block);
 530
 531        free(data);
 532
 533        return ret;
 534}
 535
 536int board_init(void)
 537{
 538        if (!read_spi_vpd(&vpd, vpd_callback)) {
 539                vpd.is_read = true;
 540        }
 541
 542        /* address of boot parameters */
 543        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 544        setup_display();
 545
 546        return 0;
 547}
 548
 549static void init_bootcause(void)
 550{
 551        const char *cause;
 552
 553        /* We care about WDOG only, treating everything else as
 554         * a power-on-reset.
 555         */
 556        if (get_imx_reset_cause() & 0x0010)
 557                cause = "WDOG";
 558        else
 559                cause = "POR";
 560
 561        env_set("bootcause", cause);
 562}
 563
 564int misc_init_r(void)
 565{
 566        init_bootcause();
 567
 568        return 0;
 569}
 570
 571#define M41T62_REG_FLAGS        0xf
 572#define M41T62_FLAGS_OF         (1 << 2)
 573static void check_time(void)
 574{
 575        struct udevice *rtc = NULL;
 576        struct rtc_time tm;
 577        u8 val;
 578        int ret;
 579
 580        ret = uclass_get_device_by_name(UCLASS_RTC, "m41t62@68", &rtc);
 581        if (ret) {
 582                printf("Could not get RTC: %d\n", ret);
 583                env_set("rtc_status", "FAIL");
 584                return;
 585        }
 586
 587        ret = dm_i2c_read(rtc, M41T62_REG_FLAGS, &val, sizeof(val));
 588        if (ret) {
 589                printf("Could not read RTC register: %d\n", ret);
 590                env_set("rtc_status", "FAIL");
 591                return;
 592        }
 593
 594        ret = dm_rtc_reset(rtc);
 595        if (ret) {
 596                printf("Could not reset RTC: %d\n", ret);
 597                env_set("rtc_status", "FAIL");
 598                return;
 599        }
 600
 601        if (val & M41T62_FLAGS_OF) {
 602                env_set("rtc_status", "STOP");
 603                return;
 604        }
 605
 606        ret = dm_rtc_get(rtc, &tm);
 607        if (ret) {
 608                printf("Could not read RTC: %d\n", ret);
 609                env_set("rtc_status", "FAIL");
 610                return;
 611        }
 612
 613        if (tm.tm_year > 2037) {
 614                tm.tm_sec  = 0;
 615                tm.tm_min  = 0;
 616                tm.tm_hour = 0;
 617                tm.tm_mday = 1;
 618                tm.tm_wday = 2;
 619                tm.tm_mon  = 1;
 620                tm.tm_year = 2036;
 621
 622                ret = dm_rtc_set(rtc, &tm);
 623                if (ret) {
 624                        printf("Could not update RTC: %d\n", ret);
 625                        env_set("rtc_status", "FAIL");
 626                        return;
 627                }
 628
 629                printf("RTC behind 2037, capped to 2036 for userspace handling\n");
 630                env_set("rtc_status", "2038");
 631                return;
 632        }
 633
 634        env_set("rtc_status", "OK");
 635}
 636
 637static void process_vpd(struct vpd_cache *vpd)
 638{
 639        if (!vpd->is_read) {
 640                printf("VPD wasn't read\n");
 641                return;
 642        }
 643
 644        if (vpd->flags & VPD_FLAG_VALID_MAC) {
 645                eth_env_set_enetaddr_by_index("eth", 0, vpd->mac);
 646                env_set("ethact", "eth0");
 647        }
 648}
 649
 650int board_late_init(void)
 651{
 652        process_vpd(&vpd);
 653
 654        if (vpd.product_id >= PRODUCT_TYPE_B105V2 &&
 655            vpd.product_id <= PRODUCT_TYPE_B155V2) {
 656                set_env_per_board_type((enum product_type)vpd.product_id);
 657        } else {
 658                b1x5v2_board_type_autodetect();
 659        }
 660
 661        printf("Board: GE %s\n", env_get("devicetype"));
 662
 663        check_time();
 664
 665        return 0;
 666}
 667
 668#ifdef CONFIG_OF_BOARD_SETUP
 669int ft_board_setup(void *blob, struct bd_info *bd)
 670{
 671        char *rtc_status = env_get("rtc_status");
 672
 673        fdt_setprop(blob, 0, "ge,boot-ver", version_string,
 674                                            strlen(version_string) + 1);
 675        fdt_setprop(blob, 0, "ge,rtc-status", rtc_status,
 676                                            strlen(rtc_status) + 1);
 677
 678        return 0;
 679}
 680#endif
 681
 682static int do_b1x5v2_autodetect(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 683{
 684        int err;
 685
 686        err = b1x5v2_board_type_autodetect();
 687        if (!err)
 688                printf("Identified %s\n", env_get("devicetype"));
 689
 690        return 0;
 691}
 692
 693U_BOOT_CMD(
 694       autodetect_devtype, 1,      1,      do_b1x5v2_autodetect,
 695       "autodetect b1x5v2 device type",
 696       ""
 697);
 698
 699#endif // CONFIG_SPL_BUILD
 700