uboot/board/freescale/common/qixis.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2011 Freescale Semiconductor
   4 * Copyright 2020 NXP
   5 * Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
   6 *
   7 * This file provides support for the QIXIS of some Freescale reference boards.
   8 */
   9
  10#include <common.h>
  11#include <command.h>
  12#include <asm/io.h>
  13#include <linux/compiler.h>
  14#include <linux/time.h>
  15#include <i2c.h>
  16#include "qixis.h"
  17
  18#ifndef QIXIS_LBMAP_BRDCFG_REG
  19/*
  20 * For consistency with existing platforms
  21 */
  22#define QIXIS_LBMAP_BRDCFG_REG 0x00
  23#endif
  24
  25#ifndef QIXIS_RCFG_CTL_RECONFIG_IDLE
  26#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20
  27#endif
  28#ifndef QIXIS_RCFG_CTL_RECONFIG_START
  29#define QIXIS_RCFG_CTL_RECONFIG_START 0x21
  30#endif
  31
  32#ifdef CONFIG_SYS_I2C_FPGA_ADDR
  33u8 qixis_read_i2c(unsigned int reg)
  34{
  35#ifndef CONFIG_DM_I2C
  36        return i2c_reg_read(CONFIG_SYS_I2C_FPGA_ADDR, reg);
  37#else
  38        struct udevice *dev;
  39
  40        if (i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_FPGA_ADDR, 1, &dev))
  41                return 0xff;
  42
  43        return dm_i2c_reg_read(dev, reg);
  44#endif
  45}
  46
  47void qixis_write_i2c(unsigned int reg, u8 value)
  48{
  49        u8 val = value;
  50#ifndef CONFIG_DM_I2C
  51        i2c_reg_write(CONFIG_SYS_I2C_FPGA_ADDR, reg, val);
  52#else
  53        struct udevice *dev;
  54
  55        if (!i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_FPGA_ADDR, 1, &dev))
  56                dm_i2c_reg_write(dev, reg, val);
  57#endif
  58
  59}
  60#endif
  61
  62#ifdef QIXIS_BASE
  63u8 qixis_read(unsigned int reg)
  64{
  65        void *p = (void *)QIXIS_BASE;
  66
  67        return in_8(p + reg);
  68}
  69
  70void qixis_write(unsigned int reg, u8 value)
  71{
  72        void *p = (void *)QIXIS_BASE;
  73
  74        out_8(p + reg, value);
  75}
  76#endif
  77
  78u16 qixis_read_minor(void)
  79{
  80        u16 minor;
  81
  82        /* this data is in little endian */
  83        QIXIS_WRITE(tagdata, 5);
  84        minor = QIXIS_READ(tagdata);
  85        QIXIS_WRITE(tagdata, 6);
  86        minor += QIXIS_READ(tagdata) << 8;
  87
  88        return minor;
  89}
  90
  91char *qixis_read_time(char *result)
  92{
  93        time_t time = 0;
  94        int i;
  95
  96        /* timestamp is in 32-bit big endian */
  97        for (i = 8; i <= 11; i++) {
  98                QIXIS_WRITE(tagdata, i);
  99                time =  (time << 8) + QIXIS_READ(tagdata);
 100        }
 101
 102        return ctime_r(&time, result);
 103}
 104
 105char *qixis_read_tag(char *buf)
 106{
 107        int i;
 108        char tag, *ptr = buf;
 109
 110        for (i = 16; i <= 63; i++) {
 111                QIXIS_WRITE(tagdata, i);
 112                tag = QIXIS_READ(tagdata);
 113                *(ptr++) = tag;
 114                if (!tag)
 115                        break;
 116        }
 117        if (i > 63)
 118                *ptr = '\0';
 119
 120        return buf;
 121}
 122
 123/*
 124 * return the string of binary of u8 in the format of
 125 * 1010 10_0. The masked bit is filled as underscore.
 126 */
 127const char *byte_to_binary_mask(u8 val, u8 mask, char *buf)
 128{
 129        char *ptr;
 130        int i;
 131
 132        ptr = buf;
 133        for (i = 0x80; i > 0x08 ; i >>= 1, ptr++)
 134                *ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
 135        *(ptr++) = ' ';
 136        for (i = 0x08; i > 0 ; i >>= 1, ptr++)
 137                *ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
 138
 139        *ptr = '\0';
 140
 141        return buf;
 142}
 143
 144#ifdef QIXIS_RST_FORCE_MEM
 145void board_assert_mem_reset(void)
 146{
 147        u8 rst;
 148
 149        rst = QIXIS_READ(rst_frc[0]);
 150        if (!(rst & QIXIS_RST_FORCE_MEM))
 151                QIXIS_WRITE(rst_frc[0], rst | QIXIS_RST_FORCE_MEM);
 152}
 153
 154void board_deassert_mem_reset(void)
 155{
 156        u8 rst;
 157
 158        rst = QIXIS_READ(rst_frc[0]);
 159        if (rst & QIXIS_RST_FORCE_MEM)
 160                QIXIS_WRITE(rst_frc[0], rst & ~QIXIS_RST_FORCE_MEM);
 161}
 162#endif
 163
 164#ifndef CONFIG_SPL_BUILD
 165static void qixis_reset(void)
 166{
 167        QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET);
 168}
 169
 170#ifdef QIXIS_LBMAP_ALTBANK
 171static void qixis_bank_reset(void)
 172{
 173        QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
 174        QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
 175}
 176#endif
 177
 178static void __maybe_unused set_lbmap(int lbmap)
 179{
 180        u8 reg;
 181
 182        reg = QIXIS_READ(brdcfg[QIXIS_LBMAP_BRDCFG_REG]);
 183        reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap;
 184        QIXIS_WRITE(brdcfg[QIXIS_LBMAP_BRDCFG_REG], reg);
 185}
 186
 187static void __maybe_unused set_rcw_src(int rcw_src)
 188{
 189#ifdef CONFIG_NXP_LSCH3_2
 190        QIXIS_WRITE(dutcfg[0], (rcw_src & 0xff));
 191#else
 192        u8 reg;
 193
 194        reg = QIXIS_READ(dutcfg[1]);
 195        reg = (reg & ~1) | (rcw_src & 1);
 196        QIXIS_WRITE(dutcfg[1], reg);
 197        QIXIS_WRITE(dutcfg[0], (rcw_src >> 1) & 0xff);
 198#endif
 199}
 200
 201static void qixis_dump_regs(void)
 202{
 203        int i;
 204
 205        printf("id      = %02x\n", QIXIS_READ(id));
 206        printf("arch    = %02x\n", QIXIS_READ(arch));
 207        printf("scver   = %02x\n", QIXIS_READ(scver));
 208        printf("model   = %02x\n", QIXIS_READ(model));
 209        printf("rst_ctl = %02x\n", QIXIS_READ(rst_ctl));
 210        printf("aux     = %02x\n", QIXIS_READ(aux));
 211        for (i = 0; i < 16; i++)
 212                printf("brdcfg%02d = %02x\n", i, QIXIS_READ(brdcfg[i]));
 213        for (i = 0; i < 16; i++)
 214                printf("dutcfg%02d = %02x\n", i, QIXIS_READ(dutcfg[i]));
 215        printf("sclk    = %02x%02x%02x\n", QIXIS_READ(sclk[0]),
 216                QIXIS_READ(sclk[1]), QIXIS_READ(sclk[2]));
 217        printf("dclk    = %02x%02x%02x\n", QIXIS_READ(dclk[0]),
 218                QIXIS_READ(dclk[1]), QIXIS_READ(dclk[2]));
 219        printf("aux     = %02x\n", QIXIS_READ(aux));
 220        printf("watch   = %02x\n", QIXIS_READ(watch));
 221        printf("ctl_sys = %02x\n", QIXIS_READ(ctl_sys));
 222        printf("rcw_ctl = %02x\n", QIXIS_READ(rcw_ctl));
 223        printf("present = %02x\n", QIXIS_READ(present));
 224        printf("present2 = %02x\n", QIXIS_READ(present2));
 225        printf("clk_spd = %02x\n", QIXIS_READ(clk_spd));
 226        printf("stat_dut = %02x\n", QIXIS_READ(stat_dut));
 227        printf("stat_sys = %02x\n", QIXIS_READ(stat_sys));
 228        printf("stat_alrm = %02x\n", QIXIS_READ(stat_alrm));
 229}
 230
 231void __weak qixis_dump_switch(void)
 232{
 233        puts("Reverse engineering switch is not implemented for this board\n");
 234}
 235
 236static int qixis_reset_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
 237                           char *const argv[])
 238{
 239        int i;
 240
 241        if (argc <= 1) {
 242                set_lbmap(QIXIS_LBMAP_DFLTBANK);
 243                qixis_reset();
 244        } else if (strcmp(argv[1], "altbank") == 0) {
 245#ifdef QIXIS_LBMAP_ALTBANK
 246                set_lbmap(QIXIS_LBMAP_ALTBANK);
 247                qixis_bank_reset();
 248#else
 249                printf("No Altbank!\n");
 250#endif
 251        } else if (strcmp(argv[1], "nand") == 0) {
 252#ifdef QIXIS_LBMAP_NAND
 253                QIXIS_WRITE(rst_ctl, 0x30);
 254                QIXIS_WRITE(rcfg_ctl, 0);
 255                set_lbmap(QIXIS_LBMAP_NAND);
 256                set_rcw_src(QIXIS_RCW_SRC_NAND);
 257                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
 258                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
 259#else
 260                printf("Not implemented\n");
 261#endif
 262        } else if (strcmp(argv[1], "sd") == 0) {
 263#ifdef QIXIS_LBMAP_SD
 264                QIXIS_WRITE(rst_ctl, 0x30);
 265                QIXIS_WRITE(rcfg_ctl, 0);
 266#ifdef NON_EXTENDED_DUTCFG
 267                QIXIS_WRITE(dutcfg[0], QIXIS_RCW_SRC_SD);
 268#else
 269                set_lbmap(QIXIS_LBMAP_SD);
 270                set_rcw_src(QIXIS_RCW_SRC_SD);
 271#endif
 272                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
 273                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
 274#else
 275                printf("Not implemented\n");
 276#endif
 277        } else if (strcmp(argv[1], "ifc") == 0) {
 278#ifdef QIXIS_LBMAP_IFC
 279                QIXIS_WRITE(rst_ctl, 0x30);
 280                QIXIS_WRITE(rcfg_ctl, 0);
 281                set_lbmap(QIXIS_LBMAP_IFC);
 282                set_rcw_src(QIXIS_RCW_SRC_IFC);
 283                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
 284                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
 285#else
 286                printf("Not implemented\n");
 287#endif
 288        } else if (strcmp(argv[1], "emmc") == 0) {
 289#ifdef QIXIS_LBMAP_EMMC
 290                QIXIS_WRITE(rst_ctl, 0x30);
 291                QIXIS_WRITE(rcfg_ctl, 0);
 292#ifndef NON_EXTENDED_DUTCFG
 293                set_lbmap(QIXIS_LBMAP_EMMC);
 294#endif
 295                set_rcw_src(QIXIS_RCW_SRC_EMMC);
 296                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
 297                QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
 298#else
 299                printf("Not implemented\n");
 300#endif
 301        } else if (strcmp(argv[1], "sd_qspi") == 0) {
 302#ifdef QIXIS_LBMAP_SD_QSPI
 303                QIXIS_WRITE(rst_ctl, 0x30);
 304                QIXIS_WRITE(rcfg_ctl, 0);
 305                set_lbmap(QIXIS_LBMAP_SD_QSPI);
 306                set_rcw_src(QIXIS_RCW_SRC_SD);
 307                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 308                                QIXIS_RCFG_CTL_RECONFIG_IDLE);
 309                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 310                                QIXIS_RCFG_CTL_RECONFIG_START);
 311#else
 312                printf("Not implemented\n");
 313#endif
 314        } else if (strcmp(argv[1], "qspi") == 0) {
 315#ifdef QIXIS_LBMAP_QSPI
 316                QIXIS_WRITE(rst_ctl, 0x30);
 317                QIXIS_WRITE(rcfg_ctl, 0);
 318                set_lbmap(QIXIS_LBMAP_QSPI);
 319                set_rcw_src(QIXIS_RCW_SRC_QSPI);
 320                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 321                                QIXIS_RCFG_CTL_RECONFIG_IDLE);
 322                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 323                                QIXIS_RCFG_CTL_RECONFIG_START);
 324#else
 325                printf("Not implemented\n");
 326#endif
 327        } else if (strcmp(argv[1], "xspi") == 0) {
 328#ifdef QIXIS_LBMAP_XSPI
 329                QIXIS_WRITE(rst_ctl, 0x30);
 330                QIXIS_WRITE(rcfg_ctl, 0);
 331                set_lbmap(QIXIS_LBMAP_XSPI);
 332                set_rcw_src(QIXIS_RCW_SRC_XSPI);
 333                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 334                                QIXIS_RCFG_CTL_RECONFIG_IDLE);
 335                qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
 336                                QIXIS_RCFG_CTL_RECONFIG_START);
 337#else
 338                printf("Not implemented\n");
 339#endif
 340        } else if (strcmp(argv[1], "watchdog") == 0) {
 341                static char *period[9] = {"2s", "4s", "8s", "16s", "32s",
 342                                          "1min", "2min", "4min", "8min"};
 343                u8 rcfg = QIXIS_READ(rcfg_ctl);
 344
 345                if (argv[2] == NULL) {
 346                        printf("qixis watchdog <watchdog_period>\n");
 347                        return 0;
 348                }
 349                for (i = 0; i < ARRAY_SIZE(period); i++) {
 350                        if (strcmp(argv[2], period[i]) == 0) {
 351                                /* disable watchdog */
 352                                QIXIS_WRITE(rcfg_ctl,
 353                                        rcfg & ~QIXIS_RCFG_CTL_WATCHDOG_ENBLE);
 354                                QIXIS_WRITE(watch, ((i<<2) - 1));
 355                                QIXIS_WRITE(rcfg_ctl, rcfg);
 356                                return 0;
 357                        }
 358                }
 359        } else if (strcmp(argv[1], "dump") == 0) {
 360                qixis_dump_regs();
 361                return 0;
 362        } else if (strcmp(argv[1], "switch") == 0) {
 363                qixis_dump_switch();
 364                return 0;
 365        } else {
 366                printf("Invalid option: %s\n", argv[1]);
 367                return 1;
 368        }
 369
 370        return 0;
 371}
 372
 373U_BOOT_CMD(
 374        qixis_reset, CONFIG_SYS_MAXARGS, 1, qixis_reset_cmd,
 375        "Reset the board using the FPGA sequencer",
 376        "- hard reset to default bank\n"
 377        "qixis_reset altbank - reset to alternate bank\n"
 378        "qixis_reset nand - reset to nand\n"
 379        "qixis_reset sd - reset to sd\n"
 380        "qixis_reset sd_qspi - reset to sd with qspi support\n"
 381        "qixis_reset qspi - reset to qspi\n"
 382        "qixis watchdog <watchdog_period> - set the watchdog period\n"
 383        "       period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n"
 384        "qixis_reset dump - display the QIXIS registers\n"
 385        "qixis_reset emmc - reset to emmc\n"
 386        "qixis_reset switch - display switch\n"
 387        );
 388#endif
 389