gk7205v200-uboot/drivers/ddr/goke/default/ddr_training_console.c
2025-08-07 17:13:54 +08:00

255 lines
5.1 KiB
C
Executable File

/*
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
*/
#include "ddr_interface.h"
#include "ddr_training_impl.h"
#define __ddr_training_console__
#ifdef DDR_TRAINING_CONSOLE_CONFIG
#define DDR_UART_BASE_REG 0x12090000
#define UART_PL01x_FR 0x18 /* Flag register (Read only). */
#define UART_PL01x_FR_RXFE 0x10
#define UART_PL01x_DR 0x00 /* Data read or written from the interface. */
#define UART_PL01x_ECR 0x04 /* Error clear register (Write). */
#define isprint(c) ((c) >= ' ' && (c) <= '~')
#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define isxdigit(c) (isdigit(c) \
|| ((c) >= 'A' && (c) <= 'F') \
|| ((c) >= 'a' && (c) <= 'f'))
#define CMD(_p, _c0, _c1, _do_cmd) \
if (_p[0] == _c0 && _p[1] == _c1) { \
if (!_do_cmd(_p + 2)) \
continue; \
}
/* DDR console get char */
static int ddr_console_getc(void)
{
unsigned int data;
/* Wait until there is data in the FIFO */
while (ddr_read(DDR_UART_BASE_REG + UART_PL01x_FR) & UART_PL01x_FR_RXFE) {
}
data = ddr_read(DDR_UART_BASE_REG + UART_PL01x_DR);
/* Check for an error flag */
if (data & 0xFFFFFF00) {
/* Clear the error */
ddr_write(0xFFFFFFFF, DDR_UART_BASE_REG + UART_PL01x_ECR);
return -1;
}
return (int) data;
}
/* DDR read line */
static char *ddr_readline(char *str, int len)
{
unsigned int c;
char *p = str;
while (len > 0) {
c = ddr_console_getc();
switch (c) {
case '\r':
case '\n':
*p = '\0';
DDR_PUTC('\r');
DDR_PUTC('\n');
return str;
case 0x08:
case 0x7F:
if (p > str) {
p--;
len++;
DDR_PUTC('\b');
DDR_PUTC(' ');
DDR_PUTC('\b');
}
break;
default:
if (isprint(c)) {
(*p++) = (char)c;
len--;
DDR_PUTC(c);
}
break;
}
}
(*--p) = '\0';
return str;
}
/* HEX to INT */
static int hex2int(char **ss, unsigned int *n)
{
unsigned char *s = (unsigned char *)(*ss);
while (isspace(*s)) s++;
if (!(*s))
return -1;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
s += 2;
for ((*n) = 0; isxdigit(*s); s++) {
(*n) = ((*n) << 4);
if ((*s) >= '0' && (*s) <= '9')
(*n) |= ((*s) - '0');
else if ((*s) >= 'a' && (*s) <= 'f')
(*n) |= ((*s) + 10 - 'a');
else if ((*s) >= 'A' && (*s) <= 'F')
(*n) |= ((*s) + 10 - 'A');
}
if (isspace(*s) || !(*s)) {
while (isspace(*s)) s++;
(*ss) = (char *)s;
return 0;
}
return -2;
}
/**
* DDR do memory write.
* mw address value [count]
*/
static int ddr_do_memory_write(char *cmd)
{
unsigned int address;
unsigned int value;
unsigned int count = 4;
if (hex2int(&cmd, &address))
return -1;
if (hex2int(&cmd, &value))
return -1;
if ((*cmd) && hex2int(&cmd, &count))
return -1;
if (address & 0x03 || count & 0x03) {
DDR_INFO("parameter should align with 4 bytes.\n");
return -1;
}
for (;count > 0; count -= 4, address += 4)
ddr_write(value, address);
return 0;
}
/**
* DDR do memory display.
* md address [count]
*/
static int ddr_do_memory_display(char *cmd)
{
unsigned int ix;
unsigned int loop;
unsigned int address;
unsigned int count = 64;
if (hex2int(&cmd, &address))
return -1;
if ((*cmd) && hex2int(&cmd, &count))
return -1;
if (count < 4)
count = 4;
address &= ~0x03;
loop = (count & ~0x03);
while (loop > 0) {
DDR_PUTC('0');
DDR_PUTC('x');
DDR_PUT_HEX(address);
DDR_PUTC(':');
for (ix = 0;
ix < 4 && loop > 0;
ix++, loop -= 4, address += 4) {
DDR_PUTC(' '); DDR_PUT_HEX(ddr_read(address));
}
DDR_PUTC('\r');
DDR_PUTC('\n');
}
return 0;
}
#ifdef DDR_TRAINING_CMD
extern struct ddr_training_result_st ddrt_result_sram;
#endif
static int ddr_do_sw_training(char *cmd)
{
int result;
struct ddr_cfg_st ddr_cfg;
struct ddr_cfg_st *cfg = &ddr_cfg;
ddr_training_cfg_init(cfg);
#ifdef DDR_TRAINING_CMD
cfg->res_st = (void *)&ddrt_result_sram;
#endif
result = ddr_training_all(cfg);
result += ddr_dcc_training_func(cfg);
return 0;
}
static int ddr_do_hw_training(char *cmd)
{
int result;
result = ddr_hw_training_func();
return 0;
}
/* Do DDR training console if sw training or hw training fail */
static int ddr_training_console(void *args)
{
char str[256];
char *p = NULL;
unsigned int cmd=0;
while (1) {
DDR_PUTC('d');
DDR_PUTC('d');
DDR_PUTC('r');
DDR_PUTC('#');
p = ddr_readline(str, sizeof(str));
while (isspace(*p)) p++;
if (p[0] == 'q')
break;
CMD(p, 'm', 'w', ddr_do_memory_write) else
CMD(p, 'm', 'd', ddr_do_memory_display) else
CMD(p, 's', 'w', ddr_do_sw_training) else
CMD(p, 'h', 'w', ddr_do_hw_training)
}
return 0;
}
#else
static int ddr_training_console(void *args)
{
DDR_WARNING("Not support DDR training console.");
return 0;
}
#endif /* DDR_TRAINING_CONSOLE_CONFIG */
int ddr_training_console_if(void *args)
{
return DDR_TRAINING_CONSOLE(args);
}