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