mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-21 10:43:06 +00:00
65cc0e2a65
The rest of the unmigrated CONFIG symbols in the CONFIG_SYS namespace do not easily transition to Kconfig. In many cases they likely should come from the device tree instead. Move these out of CONFIG namespace and in to CFG namespace. Signed-off-by: Tom Rini <trini@konsulko.com> Reviewed-by: Simon Glass <sjg@chromium.org>
388 lines
9.4 KiB
C
388 lines
9.4 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright 2011 Freescale Semiconductor
|
|
* Copyright 2020 NXP
|
|
* Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
|
|
*
|
|
* This file provides support for the QIXIS of some Freescale reference boards.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <asm/io.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/time.h>
|
|
#include <i2c.h>
|
|
#include "qixis.h"
|
|
|
|
#ifndef QIXIS_LBMAP_BRDCFG_REG
|
|
/*
|
|
* For consistency with existing platforms
|
|
*/
|
|
#define QIXIS_LBMAP_BRDCFG_REG 0x00
|
|
#endif
|
|
|
|
#ifndef QIXIS_RCFG_CTL_RECONFIG_IDLE
|
|
#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20
|
|
#endif
|
|
#ifndef QIXIS_RCFG_CTL_RECONFIG_START
|
|
#define QIXIS_RCFG_CTL_RECONFIG_START 0x21
|
|
#endif
|
|
|
|
#ifdef CFG_SYS_I2C_FPGA_ADDR
|
|
u8 qixis_read_i2c(unsigned int reg)
|
|
{
|
|
#if !CONFIG_IS_ENABLED(DM_I2C)
|
|
return i2c_reg_read(CFG_SYS_I2C_FPGA_ADDR, reg);
|
|
#else
|
|
struct udevice *dev;
|
|
|
|
if (i2c_get_chip_for_busnum(0, CFG_SYS_I2C_FPGA_ADDR, 1, &dev))
|
|
return 0xff;
|
|
|
|
return dm_i2c_reg_read(dev, reg);
|
|
#endif
|
|
}
|
|
|
|
void qixis_write_i2c(unsigned int reg, u8 value)
|
|
{
|
|
u8 val = value;
|
|
#if !CONFIG_IS_ENABLED(DM_I2C)
|
|
i2c_reg_write(CFG_SYS_I2C_FPGA_ADDR, reg, val);
|
|
#else
|
|
struct udevice *dev;
|
|
|
|
if (!i2c_get_chip_for_busnum(0, CFG_SYS_I2C_FPGA_ADDR, 1, &dev))
|
|
dm_i2c_reg_write(dev, reg, val);
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
#ifdef QIXIS_BASE
|
|
u8 qixis_read(unsigned int reg)
|
|
{
|
|
void *p = (void *)QIXIS_BASE;
|
|
|
|
return in_8(p + reg);
|
|
}
|
|
|
|
void qixis_write(unsigned int reg, u8 value)
|
|
{
|
|
void *p = (void *)QIXIS_BASE;
|
|
|
|
out_8(p + reg, value);
|
|
}
|
|
#endif
|
|
|
|
u16 qixis_read_minor(void)
|
|
{
|
|
u16 minor;
|
|
|
|
/* this data is in little endian */
|
|
QIXIS_WRITE(tagdata, 5);
|
|
minor = QIXIS_READ(tagdata);
|
|
QIXIS_WRITE(tagdata, 6);
|
|
minor += QIXIS_READ(tagdata) << 8;
|
|
|
|
return minor;
|
|
}
|
|
|
|
char *qixis_read_time(char *result)
|
|
{
|
|
time_t time = 0;
|
|
int i;
|
|
|
|
/* timestamp is in 32-bit big endian */
|
|
for (i = 8; i <= 11; i++) {
|
|
QIXIS_WRITE(tagdata, i);
|
|
time = (time << 8) + QIXIS_READ(tagdata);
|
|
}
|
|
|
|
return ctime_r(&time, result);
|
|
}
|
|
|
|
char *qixis_read_tag(char *buf)
|
|
{
|
|
int i;
|
|
char tag, *ptr = buf;
|
|
|
|
for (i = 16; i <= 63; i++) {
|
|
QIXIS_WRITE(tagdata, i);
|
|
tag = QIXIS_READ(tagdata);
|
|
*(ptr++) = tag;
|
|
if (!tag)
|
|
break;
|
|
}
|
|
if (i > 63)
|
|
*ptr = '\0';
|
|
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
* return the string of binary of u8 in the format of
|
|
* 1010 10_0. The masked bit is filled as underscore.
|
|
*/
|
|
const char *byte_to_binary_mask(u8 val, u8 mask, char *buf)
|
|
{
|
|
char *ptr;
|
|
int i;
|
|
|
|
ptr = buf;
|
|
for (i = 0x80; i > 0x08 ; i >>= 1, ptr++)
|
|
*ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
|
|
*(ptr++) = ' ';
|
|
for (i = 0x08; i > 0 ; i >>= 1, ptr++)
|
|
*ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
|
|
|
|
*ptr = '\0';
|
|
|
|
return buf;
|
|
}
|
|
|
|
#ifdef QIXIS_RST_FORCE_MEM
|
|
void board_assert_mem_reset(void)
|
|
{
|
|
u8 rst;
|
|
|
|
rst = QIXIS_READ(rst_frc[0]);
|
|
if (!(rst & QIXIS_RST_FORCE_MEM))
|
|
QIXIS_WRITE(rst_frc[0], rst | QIXIS_RST_FORCE_MEM);
|
|
}
|
|
|
|
void board_deassert_mem_reset(void)
|
|
{
|
|
u8 rst;
|
|
|
|
rst = QIXIS_READ(rst_frc[0]);
|
|
if (rst & QIXIS_RST_FORCE_MEM)
|
|
QIXIS_WRITE(rst_frc[0], rst & ~QIXIS_RST_FORCE_MEM);
|
|
}
|
|
#endif
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
static void qixis_reset(void)
|
|
{
|
|
QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET);
|
|
}
|
|
|
|
#ifdef QIXIS_LBMAP_ALTBANK
|
|
static void qixis_bank_reset(void)
|
|
{
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
|
}
|
|
#endif
|
|
|
|
static void __maybe_unused set_lbmap(int lbmap)
|
|
{
|
|
u8 reg;
|
|
|
|
reg = QIXIS_READ(brdcfg[QIXIS_LBMAP_BRDCFG_REG]);
|
|
reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap;
|
|
QIXIS_WRITE(brdcfg[QIXIS_LBMAP_BRDCFG_REG], reg);
|
|
}
|
|
|
|
static void __maybe_unused set_rcw_src(int rcw_src)
|
|
{
|
|
#ifdef CONFIG_NXP_LSCH3_2
|
|
QIXIS_WRITE(dutcfg[0], (rcw_src & 0xff));
|
|
#else
|
|
u8 reg;
|
|
|
|
reg = QIXIS_READ(dutcfg[1]);
|
|
reg = (reg & ~1) | (rcw_src & 1);
|
|
QIXIS_WRITE(dutcfg[1], reg);
|
|
QIXIS_WRITE(dutcfg[0], (rcw_src >> 1) & 0xff);
|
|
#endif
|
|
}
|
|
|
|
static void qixis_dump_regs(void)
|
|
{
|
|
int i;
|
|
|
|
printf("id = %02x\n", QIXIS_READ(id));
|
|
printf("arch = %02x\n", QIXIS_READ(arch));
|
|
printf("scver = %02x\n", QIXIS_READ(scver));
|
|
printf("model = %02x\n", QIXIS_READ(model));
|
|
printf("rst_ctl = %02x\n", QIXIS_READ(rst_ctl));
|
|
printf("aux = %02x\n", QIXIS_READ(aux));
|
|
for (i = 0; i < 16; i++)
|
|
printf("brdcfg%02d = %02x\n", i, QIXIS_READ(brdcfg[i]));
|
|
for (i = 0; i < 16; i++)
|
|
printf("dutcfg%02d = %02x\n", i, QIXIS_READ(dutcfg[i]));
|
|
printf("sclk = %02x%02x%02x\n", QIXIS_READ(sclk[0]),
|
|
QIXIS_READ(sclk[1]), QIXIS_READ(sclk[2]));
|
|
printf("dclk = %02x%02x%02x\n", QIXIS_READ(dclk[0]),
|
|
QIXIS_READ(dclk[1]), QIXIS_READ(dclk[2]));
|
|
printf("aux = %02x\n", QIXIS_READ(aux));
|
|
printf("watch = %02x\n", QIXIS_READ(watch));
|
|
printf("ctl_sys = %02x\n", QIXIS_READ(ctl_sys));
|
|
printf("rcw_ctl = %02x\n", QIXIS_READ(rcw_ctl));
|
|
printf("present = %02x\n", QIXIS_READ(present));
|
|
printf("present2 = %02x\n", QIXIS_READ(present2));
|
|
printf("clk_spd = %02x\n", QIXIS_READ(clk_spd));
|
|
printf("stat_dut = %02x\n", QIXIS_READ(stat_dut));
|
|
printf("stat_sys = %02x\n", QIXIS_READ(stat_sys));
|
|
printf("stat_alrm = %02x\n", QIXIS_READ(stat_alrm));
|
|
}
|
|
|
|
void __weak qixis_dump_switch(void)
|
|
{
|
|
puts("Reverse engineering switch is not implemented for this board\n");
|
|
}
|
|
|
|
static int qixis_reset_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
int i;
|
|
|
|
if (argc <= 1) {
|
|
set_lbmap(QIXIS_LBMAP_DFLTBANK);
|
|
qixis_reset();
|
|
} else if (strcmp(argv[1], "altbank") == 0) {
|
|
#ifdef QIXIS_LBMAP_ALTBANK
|
|
set_lbmap(QIXIS_LBMAP_ALTBANK);
|
|
qixis_bank_reset();
|
|
#else
|
|
printf("No Altbank!\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "nand") == 0) {
|
|
#ifdef QIXIS_LBMAP_NAND
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
set_lbmap(QIXIS_LBMAP_NAND);
|
|
set_rcw_src(QIXIS_RCW_SRC_NAND);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "sd") == 0) {
|
|
#ifdef QIXIS_LBMAP_SD
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
#ifdef NON_EXTENDED_DUTCFG
|
|
QIXIS_WRITE(dutcfg[0], QIXIS_RCW_SRC_SD);
|
|
#else
|
|
set_lbmap(QIXIS_LBMAP_SD);
|
|
set_rcw_src(QIXIS_RCW_SRC_SD);
|
|
#endif
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "ifc") == 0) {
|
|
#ifdef QIXIS_LBMAP_IFC
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
set_lbmap(QIXIS_LBMAP_IFC);
|
|
set_rcw_src(QIXIS_RCW_SRC_IFC);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "emmc") == 0) {
|
|
#ifdef QIXIS_LBMAP_EMMC
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
#ifndef NON_EXTENDED_DUTCFG
|
|
set_lbmap(QIXIS_LBMAP_EMMC);
|
|
#endif
|
|
set_rcw_src(QIXIS_RCW_SRC_EMMC);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "sd_qspi") == 0) {
|
|
#ifdef QIXIS_LBMAP_SD_QSPI
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
set_lbmap(QIXIS_LBMAP_SD_QSPI);
|
|
set_rcw_src(QIXIS_RCW_SRC_SD);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "qspi") == 0) {
|
|
#ifdef QIXIS_LBMAP_QSPI
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
set_lbmap(QIXIS_LBMAP_QSPI);
|
|
set_rcw_src(QIXIS_RCW_SRC_QSPI);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "xspi") == 0) {
|
|
#ifdef QIXIS_LBMAP_XSPI
|
|
QIXIS_WRITE(rst_ctl, 0x30);
|
|
QIXIS_WRITE(rcfg_ctl, 0);
|
|
set_lbmap(QIXIS_LBMAP_XSPI);
|
|
set_rcw_src(QIXIS_RCW_SRC_XSPI);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
|
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
|
QIXIS_RCFG_CTL_RECONFIG_START);
|
|
#else
|
|
printf("Not implemented\n");
|
|
#endif
|
|
} else if (strcmp(argv[1], "watchdog") == 0) {
|
|
static char *period[9] = {"2s", "4s", "8s", "16s", "32s",
|
|
"1min", "2min", "4min", "8min"};
|
|
u8 rcfg = QIXIS_READ(rcfg_ctl);
|
|
|
|
if (argv[2] == NULL) {
|
|
printf("qixis watchdog <watchdog_period>\n");
|
|
return 0;
|
|
}
|
|
for (i = 0; i < ARRAY_SIZE(period); i++) {
|
|
if (strcmp(argv[2], period[i]) == 0) {
|
|
/* disable watchdog */
|
|
QIXIS_WRITE(rcfg_ctl,
|
|
rcfg & ~QIXIS_RCFG_CTL_WATCHDOG_ENBLE);
|
|
QIXIS_WRITE(watch, ((i<<2) - 1));
|
|
QIXIS_WRITE(rcfg_ctl, rcfg);
|
|
return 0;
|
|
}
|
|
}
|
|
} else if (strcmp(argv[1], "dump") == 0) {
|
|
qixis_dump_regs();
|
|
return 0;
|
|
} else if (strcmp(argv[1], "switch") == 0) {
|
|
qixis_dump_switch();
|
|
return 0;
|
|
} else {
|
|
printf("Invalid option: %s\n", argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
qixis_reset, CONFIG_SYS_MAXARGS, 1, qixis_reset_cmd,
|
|
"Reset the board using the FPGA sequencer",
|
|
"- hard reset to default bank\n"
|
|
"qixis_reset altbank - reset to alternate bank\n"
|
|
"qixis_reset nand - reset to nand\n"
|
|
"qixis_reset sd - reset to sd\n"
|
|
"qixis_reset sd_qspi - reset to sd with qspi support\n"
|
|
"qixis_reset qspi - reset to qspi\n"
|
|
"qixis watchdog <watchdog_period> - set the watchdog period\n"
|
|
" period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n"
|
|
"qixis_reset dump - display the QIXIS registers\n"
|
|
"qixis_reset emmc - reset to emmc\n"
|
|
"qixis_reset switch - display switch\n"
|
|
);
|
|
#endif
|