Merge branch 'master' of git://git.denx.de/u-boot
This commit is contained in:
commit
08ca213aca
5
README
5
README
@ -1003,6 +1003,7 @@ The following options need to be configured:
|
||||
CONFIG_CMD_ECHO echo arguments
|
||||
CONFIG_CMD_EDITENV edit env variable
|
||||
CONFIG_CMD_EEPROM * EEPROM read/write support
|
||||
CONFIG_CMD_EEPROM_LAYOUT* EEPROM layout aware commands
|
||||
CONFIG_CMD_ELF * bootelf, bootvx
|
||||
CONFIG_CMD_ENV_CALLBACK * display details about env callbacks
|
||||
CONFIG_CMD_ENV_FLAGS * display details about env flags
|
||||
@ -1066,7 +1067,7 @@ The following options need to be configured:
|
||||
CONFIG_CMD_RUN run command in env variable
|
||||
CONFIG_CMD_SANDBOX * sb command to access sandbox features
|
||||
CONFIG_CMD_SAVES * save S record dump
|
||||
CONFIG_CMD_SCSI * SCSI Support
|
||||
CONFIG_SCSI * SCSI Support
|
||||
CONFIG_CMD_SDRAM * print SDRAM configuration information
|
||||
(requires CONFIG_CMD_I2C)
|
||||
CONFIG_CMD_SETGETDCR Support for DCR Register access
|
||||
@ -1254,7 +1255,7 @@ The following options need to be configured:
|
||||
CONFIG_MTD_PARTITIONS Memory Technology Device partition table.
|
||||
|
||||
If IDE or SCSI support is enabled (CONFIG_CMD_IDE or
|
||||
CONFIG_CMD_SCSI) you must configure support for at
|
||||
CONFIG_SCSI) you must configure support for at
|
||||
least one non-MTD partition type as well.
|
||||
|
||||
- IDE Reset method:
|
||||
|
58
api/api.c
58
api/api.c
@ -52,7 +52,7 @@ static int API_getc(va_list ap)
|
||||
{
|
||||
int *c;
|
||||
|
||||
if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
*c = getc();
|
||||
@ -68,7 +68,7 @@ static int API_tstc(va_list ap)
|
||||
{
|
||||
int *t;
|
||||
|
||||
if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
*t = tstc();
|
||||
@ -84,7 +84,7 @@ static int API_putc(va_list ap)
|
||||
{
|
||||
char *c;
|
||||
|
||||
if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
putc(*c);
|
||||
@ -100,7 +100,7 @@ static int API_puts(va_list ap)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
puts(s);
|
||||
@ -132,7 +132,7 @@ static int API_get_sys_info(va_list ap)
|
||||
{
|
||||
struct sys_info *si;
|
||||
|
||||
si = (struct sys_info *)va_arg(ap, u_int32_t);
|
||||
si = (struct sys_info *)va_arg(ap, uintptr_t);
|
||||
if (si == NULL)
|
||||
return API_ENOMEM;
|
||||
|
||||
@ -148,7 +148,7 @@ static int API_udelay(va_list ap)
|
||||
{
|
||||
unsigned long *d;
|
||||
|
||||
if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
udelay(*d);
|
||||
@ -164,11 +164,11 @@ static int API_get_timer(va_list ap)
|
||||
{
|
||||
unsigned long *base, *cur;
|
||||
|
||||
cur = (unsigned long *)va_arg(ap, u_int32_t);
|
||||
cur = (unsigned long *)va_arg(ap, unsigned long);
|
||||
if (cur == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
base = (unsigned long *)va_arg(ap, u_int32_t);
|
||||
base = (unsigned long *)va_arg(ap, unsigned long);
|
||||
if (base == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -199,7 +199,7 @@ static int API_dev_enum(va_list ap)
|
||||
struct device_info *di;
|
||||
|
||||
/* arg is ptr to the device_info struct we are going to fill out */
|
||||
di = (struct device_info *)va_arg(ap, u_int32_t);
|
||||
di = (struct device_info *)va_arg(ap, uintptr_t);
|
||||
if (di == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -233,7 +233,7 @@ static int API_dev_open(va_list ap)
|
||||
int err = 0;
|
||||
|
||||
/* arg is ptr to the device_info struct */
|
||||
di = (struct device_info *)va_arg(ap, u_int32_t);
|
||||
di = (struct device_info *)va_arg(ap, uintptr_t);
|
||||
if (di == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -265,7 +265,7 @@ static int API_dev_close(va_list ap)
|
||||
int err = 0;
|
||||
|
||||
/* arg is ptr to the device_info struct */
|
||||
di = (struct device_info *)va_arg(ap, u_int32_t);
|
||||
di = (struct device_info *)va_arg(ap, uintptr_t);
|
||||
if (di == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -319,7 +319,7 @@ static int API_dev_write(va_list ap)
|
||||
int err = 0;
|
||||
|
||||
/* 1. arg is ptr to the device_info struct */
|
||||
di = (struct device_info *)va_arg(ap, u_int32_t);
|
||||
di = (struct device_info *)va_arg(ap, uintptr_t);
|
||||
if (di == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -329,12 +329,12 @@ static int API_dev_write(va_list ap)
|
||||
return API_ENODEV;
|
||||
|
||||
/* 2. arg is ptr to buffer from where to get data to write */
|
||||
buf = (void *)va_arg(ap, u_int32_t);
|
||||
buf = (void *)va_arg(ap, uintptr_t);
|
||||
if (buf == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
/* 3. arg is length of buffer */
|
||||
len = (int *)va_arg(ap, u_int32_t);
|
||||
len = (int *)va_arg(ap, uintptr_t);
|
||||
if (len == NULL)
|
||||
return API_EINVAL;
|
||||
if (*len <= 0)
|
||||
@ -387,7 +387,7 @@ static int API_dev_read(va_list ap)
|
||||
int *len_net, *act_len_net;
|
||||
|
||||
/* 1. arg is ptr to the device_info struct */
|
||||
di = (struct device_info *)va_arg(ap, u_int32_t);
|
||||
di = (struct device_info *)va_arg(ap, uintptr_t);
|
||||
if (di == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -397,23 +397,23 @@ static int API_dev_read(va_list ap)
|
||||
return API_ENODEV;
|
||||
|
||||
/* 2. arg is ptr to buffer from where to put the read data */
|
||||
buf = (void *)va_arg(ap, u_int32_t);
|
||||
buf = (void *)va_arg(ap, uintptr_t);
|
||||
if (buf == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
if (di->type & DEV_TYP_STOR) {
|
||||
/* 3. arg - ptr to var with # of blocks to read */
|
||||
len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
|
||||
len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
|
||||
if (!len_stor)
|
||||
return API_EINVAL;
|
||||
if (*len_stor <= 0)
|
||||
return API_EINVAL;
|
||||
|
||||
/* 4. arg - ptr to var with start block */
|
||||
start = (lbastart_t *)va_arg(ap, u_int32_t);
|
||||
start = (lbastart_t *)va_arg(ap, uintptr_t);
|
||||
|
||||
/* 5. arg - ptr to var where to put the len actually read */
|
||||
act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
|
||||
act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
|
||||
if (!act_len_stor)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -422,14 +422,14 @@ static int API_dev_read(va_list ap)
|
||||
} else if (di->type & DEV_TYP_NET) {
|
||||
|
||||
/* 3. arg points to the var with length of packet to read */
|
||||
len_net = (int *)va_arg(ap, u_int32_t);
|
||||
len_net = (int *)va_arg(ap, uintptr_t);
|
||||
if (!len_net)
|
||||
return API_EINVAL;
|
||||
if (*len_net <= 0)
|
||||
return API_EINVAL;
|
||||
|
||||
/* 4. - ptr to var where to put the len actually read */
|
||||
act_len_net = (int *)va_arg(ap, u_int32_t);
|
||||
act_len_net = (int *)va_arg(ap, uintptr_t);
|
||||
if (!act_len_net)
|
||||
return API_EINVAL;
|
||||
|
||||
@ -453,9 +453,9 @@ static int API_env_get(va_list ap)
|
||||
{
|
||||
char *name, **value;
|
||||
|
||||
if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
*value = getenv(name);
|
||||
@ -476,9 +476,9 @@ static int API_env_set(va_list ap)
|
||||
{
|
||||
char *name, *value;
|
||||
|
||||
if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
setenv(name, value);
|
||||
@ -498,9 +498,9 @@ static int API_env_enum(va_list ap)
|
||||
int i, n;
|
||||
char *last, **next;
|
||||
|
||||
last = (char *)va_arg(ap, u_int32_t);
|
||||
last = (char *)va_arg(ap, unsigned long);
|
||||
|
||||
if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
|
||||
if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
|
||||
return API_EINVAL;
|
||||
|
||||
if (last == NULL)
|
||||
@ -662,14 +662,14 @@ void api_init(void)
|
||||
}
|
||||
|
||||
setenv_hex("api_address", (unsigned long)sig);
|
||||
debugf("API sig @ 0x%08x\n", sig);
|
||||
debugf("API sig @ 0x%lX\n", (unsigned long)sig);
|
||||
memcpy(sig->magic, API_SIG_MAGIC, 8);
|
||||
sig->version = API_SIG_VERSION;
|
||||
sig->syscall = &syscall;
|
||||
sig->checksum = 0;
|
||||
sig->checksum = crc32(0, (unsigned char *)sig,
|
||||
sizeof(struct api_signature));
|
||||
debugf("syscall entry: 0x%08x\n", sig->syscall);
|
||||
debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
|
||||
}
|
||||
|
||||
void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
|
||||
|
@ -67,7 +67,7 @@ void dev_stor_init(void)
|
||||
specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA;
|
||||
specs[ENUM_SATA].name = "sata";
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_SCSI)
|
||||
#if defined(CONFIG_SCSI)
|
||||
specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE;
|
||||
specs[ENUM_SCSI].enum_started = 0;
|
||||
specs[ENUM_SCSI].enum_ended = 0;
|
||||
|
@ -216,7 +216,7 @@ WEAK(lowlevel_init)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ARMV8_MULTIENTRY
|
||||
#ifdef CONFIG_ARMV8_MULTIENTRY
|
||||
branch_if_master x0, x1, 2f
|
||||
|
||||
/*
|
||||
|
@ -42,11 +42,11 @@
|
||||
};
|
||||
|
||||
soft-spi {
|
||||
compatible = "u-boot,soft-spi";
|
||||
cs-gpio = <&gpy4 3 0>;
|
||||
sclk-gpio = <&gpy3 1 0>;
|
||||
mosi-gpio = <&gpy3 3 0>;
|
||||
miso-gpio = <&gpy3 0 0>;
|
||||
compatible = "spi-gpio";
|
||||
cs-gpios = <&gpy4 3 0>;
|
||||
gpio-sck = <&gpy3 1 0>;
|
||||
gpio-mosi = <&gpy3 3 0>;
|
||||
gpio-miso = <&gpy3 0 0>;
|
||||
spi-delay-us = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -40,10 +40,6 @@
|
||||
nvidia,panel = <&lcd_panel>;
|
||||
};
|
||||
};
|
||||
|
||||
dc@54240000 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
/* This is not used in U-Boot, but is expected to be in kernel .dts */
|
||||
|
@ -82,7 +82,7 @@
|
||||
/* SATA */
|
||||
#define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000)
|
||||
#define CONFIG_BOARD_LATE_INIT
|
||||
#define CONFIG_CMD_SCSI
|
||||
#define CONFIG_SCSI
|
||||
#define CONFIG_LIBATA
|
||||
#define CONFIG_SCSI_AHCI
|
||||
#define CONFIG_SCSI_AHCI_PLAT
|
||||
|
@ -372,14 +372,29 @@ _start:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for
|
||||
the first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
bsr board_init_f_alloc_reserve
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
bsr board_init_f_init_reserve
|
||||
|
||||
bsr cpu_init_f /* run low-level CPU init code (from flash) */
|
||||
clr.l %sp@-
|
||||
bsr board_init_f /* run low-level board init code (from flash) */
|
||||
|
||||
/* board_init_f() does not return */
|
||||
|
@ -134,17 +134,34 @@ _start:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for the
|
||||
first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
move.l #board_init_f_alloc_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
move.l #board_init_f_init_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* run low-level CPU init code (from flash) */
|
||||
move.l #cpu_init_f, %a1
|
||||
jsr (%a1)
|
||||
/* run low-level board init code (from flash) */
|
||||
clr.l %sp@-
|
||||
move.l #board_init_f, %a1
|
||||
jsr (%a1)
|
||||
|
||||
|
@ -192,16 +192,34 @@ _after_flashbar_copy:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for the first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
move.l #board_init_f_alloc_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
move.l #board_init_f_init_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* run low-level CPU init code (from flash) */
|
||||
move.l #cpu_init_f, %a1
|
||||
jsr (%a1)
|
||||
/* run low-level board init code (from flash) */
|
||||
clr.l %sp@-
|
||||
move.l #board_init_f, %a1
|
||||
jsr (%a1)
|
||||
|
||||
|
@ -142,7 +142,7 @@ int cpu_init_r(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_port_conf(void)
|
||||
void uart_port_conf(int port)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -126,21 +126,32 @@ _start:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/*
|
||||
* set stackpointer to internal sram end - 80
|
||||
* (global data struct size + some bytes)
|
||||
* get some stackspace for the first c-code,
|
||||
*/
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
bsr board_init_f_alloc_reserve
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
bsr board_init_f_init_reserve
|
||||
|
||||
/* run low-level CPU init code (from flash) */
|
||||
bsr cpu_init_f
|
||||
|
||||
/* run low-level board init code (from flash) */
|
||||
clr.l %sp@-
|
||||
bsr board_init_f
|
||||
|
||||
/* board_init_f() does not return */
|
||||
|
@ -148,17 +148,34 @@ _start:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for the
|
||||
first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
move.l #board_init_f_alloc_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
move.l #board_init_f_init_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* run low-level CPU init code (from flash) */
|
||||
move.l #cpu_init_f, %a1
|
||||
jsr (%a1)
|
||||
/* run low-level board init code (from flash) */
|
||||
clr.l %sp@-
|
||||
move.l #board_init_f, %a1
|
||||
jsr (%a1)
|
||||
|
||||
|
@ -657,17 +657,34 @@ _start:
|
||||
movec %d0, %RAMBAR1
|
||||
#endif
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for
|
||||
the first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
move.l #board_init_f_alloc_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
move.l #board_init_f_init_reserve, %a1
|
||||
jsr (%a1)
|
||||
|
||||
/* run low-level CPU init code (from flash) */
|
||||
move.l #cpu_init_f, %a1
|
||||
jsr (%a1)
|
||||
/* run low-level board init code (from flash) */
|
||||
clr.l %sp@-
|
||||
move.l #board_init_f, %a1
|
||||
jsr (%a1)
|
||||
|
||||
|
@ -141,14 +141,29 @@ _start:
|
||||
move.l %d0, (%a1)
|
||||
move.l %d0, (%a2)
|
||||
|
||||
/* set stackpointer to end of internal ram to get some stackspace for the
|
||||
first c-code */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
|
||||
clr.l %sp@-
|
||||
/* put relocation table address to a5 */
|
||||
move.l #__got_start, %a5
|
||||
|
||||
move.l #__got_start, %a5 /* put relocation table address to a5 */
|
||||
/* setup stack initially on top of internal static ram */
|
||||
move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
|
||||
|
||||
/*
|
||||
* if configured, malloc_f arena will be reserved first,
|
||||
* then (and always) gd struct space will be reserved
|
||||
*/
|
||||
move.l %sp, -(%sp)
|
||||
bsr board_init_f_alloc_reserve
|
||||
|
||||
/* update stack and frame-pointers */
|
||||
move.l %d0, %sp
|
||||
move.l %sp, %fp
|
||||
|
||||
/* initialize reserved area */
|
||||
move.l %d0, -(%sp)
|
||||
bsr board_init_f_init_reserve
|
||||
|
||||
jbsr cpu_init_f /* run low-level CPU init code (from flash) */
|
||||
clr.l %sp@-
|
||||
jbsr board_init_f /* run low-level board init code (from flash) */
|
||||
|
||||
/* board_init_f() does not return */
|
||||
|
@ -7,8 +7,6 @@
|
||||
#ifndef _ASM_CONFIG_H_
|
||||
#define _ASM_CONFIG_H_
|
||||
|
||||
#define CONFIG_SYS_GENERIC_GLOBAL_DATA
|
||||
|
||||
#define CONFIG_NEEDS_MANUAL_RELOC
|
||||
|
||||
#define CONFIG_LMB
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
typedef struct fsl_i2c {
|
||||
typedef struct fsl_i2c_base {
|
||||
|
||||
u8 adr; /* I2C slave address */
|
||||
u8 res0[3];
|
||||
|
@ -5,8 +5,8 @@ config SYS_ARCH
|
||||
default "mips"
|
||||
|
||||
config SYS_CPU
|
||||
default "mips32" if CPU_MIPS32_R1 || CPU_MIPS32_R2
|
||||
default "mips64" if CPU_MIPS64_R1 || CPU_MIPS64_R2
|
||||
default "mips32" if CPU_MIPS32
|
||||
default "mips64" if CPU_MIPS64
|
||||
|
||||
choice
|
||||
prompt "Target select"
|
||||
@ -28,6 +28,7 @@ config TARGET_MALTA
|
||||
select SUPPORTS_LITTLE_ENDIAN
|
||||
select SUPPORTS_CPU_MIPS32_R1
|
||||
select SUPPORTS_CPU_MIPS32_R2
|
||||
select SUPPORTS_CPU_MIPS32_R6
|
||||
select SWAP_IO_SPACE
|
||||
select MIPS_L1_CACHE_SHIFT_6
|
||||
|
||||
@ -55,6 +56,11 @@ config TARGET_PB1X00
|
||||
select SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
select MIPS_TUNE_4KC
|
||||
|
||||
config ARCH_ATH79
|
||||
bool "Support QCA/Atheros ath79"
|
||||
select OF_CONTROL
|
||||
select DM
|
||||
|
||||
config MACH_PIC32
|
||||
bool "Support Microchip PIC32"
|
||||
select OF_CONTROL
|
||||
@ -67,6 +73,7 @@ source "board/imgtec/malta/Kconfig"
|
||||
source "board/micronas/vct/Kconfig"
|
||||
source "board/pb1x00/Kconfig"
|
||||
source "board/qemu-mips/Kconfig"
|
||||
source "arch/mips/mach-ath79/Kconfig"
|
||||
source "arch/mips/mach-pic32/Kconfig"
|
||||
|
||||
if MIPS
|
||||
@ -98,7 +105,7 @@ config CPU_MIPS32_R1
|
||||
depends on SUPPORTS_CPU_MIPS32_R1
|
||||
select 32BIT
|
||||
help
|
||||
Choose this option to build an U-Boot for release 1 or later of the
|
||||
Choose this option to build an U-Boot for release 1 through 5 of the
|
||||
MIPS32 architecture.
|
||||
|
||||
config CPU_MIPS32_R2
|
||||
@ -106,7 +113,15 @@ config CPU_MIPS32_R2
|
||||
depends on SUPPORTS_CPU_MIPS32_R2
|
||||
select 32BIT
|
||||
help
|
||||
Choose this option to build an U-Boot for release 2 or later of the
|
||||
Choose this option to build an U-Boot for release 2 through 5 of the
|
||||
MIPS32 architecture.
|
||||
|
||||
config CPU_MIPS32_R6
|
||||
bool "MIPS32 Release 6"
|
||||
depends on SUPPORTS_CPU_MIPS32_R6
|
||||
select 32BIT
|
||||
help
|
||||
Choose this option to build an U-Boot for release 6 or later of the
|
||||
MIPS32 architecture.
|
||||
|
||||
config CPU_MIPS64_R1
|
||||
@ -114,7 +129,7 @@ config CPU_MIPS64_R1
|
||||
depends on SUPPORTS_CPU_MIPS64_R1
|
||||
select 64BIT
|
||||
help
|
||||
Choose this option to build a kernel for release 1 or later of the
|
||||
Choose this option to build a kernel for release 1 through 5 of the
|
||||
MIPS64 architecture.
|
||||
|
||||
config CPU_MIPS64_R2
|
||||
@ -122,7 +137,15 @@ config CPU_MIPS64_R2
|
||||
depends on SUPPORTS_CPU_MIPS64_R2
|
||||
select 64BIT
|
||||
help
|
||||
Choose this option to build a kernel for release 2 or later of the
|
||||
Choose this option to build a kernel for release 2 through 5 of the
|
||||
MIPS64 architecture.
|
||||
|
||||
config CPU_MIPS64_R6
|
||||
bool "MIPS64 Release 6"
|
||||
depends on SUPPORTS_CPU_MIPS64_R6
|
||||
select 64BIT
|
||||
help
|
||||
Choose this option to build a kernel for release 6 or later of the
|
||||
MIPS64 architecture.
|
||||
|
||||
endchoice
|
||||
@ -169,19 +192,25 @@ config SUPPORTS_CPU_MIPS32_R1
|
||||
config SUPPORTS_CPU_MIPS32_R2
|
||||
bool
|
||||
|
||||
config SUPPORTS_CPU_MIPS32_R6
|
||||
bool
|
||||
|
||||
config SUPPORTS_CPU_MIPS64_R1
|
||||
bool
|
||||
|
||||
config SUPPORTS_CPU_MIPS64_R2
|
||||
bool
|
||||
|
||||
config SUPPORTS_CPU_MIPS64_R6
|
||||
bool
|
||||
|
||||
config CPU_MIPS32
|
||||
bool
|
||||
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
|
||||
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6
|
||||
|
||||
config CPU_MIPS64
|
||||
bool
|
||||
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
|
||||
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6
|
||||
|
||||
config MIPS_TUNE_4KC
|
||||
bool
|
||||
@ -192,6 +221,9 @@ config MIPS_TUNE_14KC
|
||||
config MIPS_TUNE_24KC
|
||||
bool
|
||||
|
||||
config MIPS_TUNE_74KC
|
||||
bool
|
||||
|
||||
config 32BIT
|
||||
bool
|
||||
|
||||
|
@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/
|
||||
libs-y += arch/mips/lib/
|
||||
|
||||
machine-$(CONFIG_SOC_AU1X00) += au1x00
|
||||
machine-$(CONFIG_ARCH_ATH79) += ath79
|
||||
machine-$(CONFIG_MACH_PIC32) += pic32
|
||||
|
||||
machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
|
||||
@ -18,13 +19,16 @@ PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
|
||||
# Optimize for MIPS architectures
|
||||
arch-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,-mips32
|
||||
arch-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,-mips32r2
|
||||
arch-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,-mips32r6
|
||||
arch-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,-mips64
|
||||
arch-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2
|
||||
arch-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,-mips64r6
|
||||
|
||||
# Allow extra optimization for specific CPUs/SoCs
|
||||
tune-$(CONFIG_MIPS_TUNE_4KC) += -mtune=4kc
|
||||
tune-$(CONFIG_MIPS_TUNE_14KC) += -mtune=14kc
|
||||
tune-$(CONFIG_MIPS_TUNE_24KC) += -mtune=24kc
|
||||
tune-$(CONFIG_MIPS_TUNE_74KC) += -mtune=74kc
|
||||
|
||||
# Include default header files
|
||||
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <netdev.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
@ -164,12 +164,14 @@ reset:
|
||||
li t0, -16
|
||||
PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR
|
||||
and sp, t1, t0 # force 16 byte alignment
|
||||
PTR_SUB sp, sp, GD_SIZE # reserve space for gd
|
||||
PTR_SUBU \
|
||||
sp, sp, GD_SIZE # reserve space for gd
|
||||
and sp, sp, t0 # force 16 byte alignment
|
||||
move k0, sp # save gd pointer
|
||||
#ifdef CONFIG_SYS_MALLOC_F_LEN
|
||||
li t2, CONFIG_SYS_MALLOC_F_LEN
|
||||
PTR_SUB sp, sp, t2 # reserve space for early malloc
|
||||
PTR_SUBU \
|
||||
sp, sp, t2 # reserve space for early malloc
|
||||
and sp, sp, t0 # force 16 byte alignment
|
||||
#endif
|
||||
move fp, sp
|
||||
@ -179,7 +181,7 @@ reset:
|
||||
1:
|
||||
PTR_S zero, 0(t0)
|
||||
blt t0, t1, 1b
|
||||
PTR_ADDI t0, PTRSIZE
|
||||
PTR_ADDIU t0, PTRSIZE
|
||||
|
||||
#ifdef CONFIG_SYS_MALLOC_F_LEN
|
||||
PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset
|
||||
@ -237,7 +239,7 @@ ENTRY(relocate_code)
|
||||
move a0, s2 # a0 <-- destination address
|
||||
|
||||
/* Jump to where we've relocated ourselves */
|
||||
PTR_ADDI t0, s2, in_ram - _start
|
||||
PTR_ADDIU t0, s2, in_ram - _start
|
||||
jr t0
|
||||
nop
|
||||
|
||||
@ -257,7 +259,7 @@ in_ram:
|
||||
PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries
|
||||
PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
|
||||
PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_
|
||||
PTR_ADDI t8, t8, 2 * PTRSIZE # skipping first two entries
|
||||
PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries
|
||||
PTR_LI t2, 2
|
||||
1:
|
||||
PTR_L t1, 0(t8)
|
||||
@ -265,16 +267,16 @@ in_ram:
|
||||
PTR_ADD t1, s1
|
||||
PTR_S t1, 0(t8)
|
||||
2:
|
||||
PTR_ADDI t2, 1
|
||||
PTR_ADDIU t2, 1
|
||||
blt t2, t3, 1b
|
||||
PTR_ADDI t8, PTRSIZE
|
||||
PTR_ADDIU t8, PTRSIZE
|
||||
|
||||
/* Update dynamic relocations */
|
||||
PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start
|
||||
PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end
|
||||
|
||||
b 2f # skip first reserved entry
|
||||
PTR_ADDI t1, 2 * PTRSIZE
|
||||
PTR_ADDIU t1, 2 * PTRSIZE
|
||||
|
||||
1:
|
||||
lw t8, -4(t1) # t8 <-- relocation info
|
||||
@ -293,7 +295,7 @@ in_ram:
|
||||
|
||||
2:
|
||||
blt t1, t2, 1b
|
||||
PTR_ADDI t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes
|
||||
PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes
|
||||
|
||||
/*
|
||||
* Clear BSS
|
||||
@ -307,7 +309,7 @@ in_ram:
|
||||
1:
|
||||
PTR_S zero, 0(t1)
|
||||
blt t1, t2, 1b
|
||||
PTR_ADDI t1, PTRSIZE
|
||||
PTR_ADDIU t1, PTRSIZE
|
||||
|
||||
move a0, s0 # a0 <-- gd
|
||||
move a1, s2
|
||||
|
@ -2,7 +2,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
|
||||
dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
|
||||
dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
|
||||
dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
|
||||
|
||||
targets += $(dtb-y)
|
||||
|
||||
|
43
arch/mips/dts/ap121.dts
Normal file
43
arch/mips/dts/ap121.dts
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "ar933x.dtsi"
|
||||
|
||||
/ {
|
||||
model = "AP121 Reference Board";
|
||||
compatible = "qca,ap121", "qca,ar933x";
|
||||
|
||||
aliases {
|
||||
spi0 = &spi0;
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
};
|
||||
|
||||
&xtal {
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
spi-max-frequency = <25000000>;
|
||||
status = "okay";
|
||||
spi-flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "spi-flash";
|
||||
memory-map = <0x9f000000 0x00800000>;
|
||||
spi-max-frequency = <25000000>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
43
arch/mips/dts/ap143.dts
Normal file
43
arch/mips/dts/ap143.dts
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "qca953x.dtsi"
|
||||
|
||||
/ {
|
||||
model = "AP143 Reference Board";
|
||||
compatible = "qca,ap143", "qca,qca953x";
|
||||
|
||||
aliases {
|
||||
spi0 = &spi0;
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
};
|
||||
|
||||
&xtal {
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
spi-max-frequency = <25000000>;
|
||||
status = "okay";
|
||||
spi-flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "spi-flash";
|
||||
memory-map = <0x9f000000 0x00800000>;
|
||||
spi-max-frequency = <25000000>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
115
arch/mips/dts/ar933x.dtsi
Normal file
115
arch/mips/dts/ar933x.dtsi
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "qca,ar933x";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "mips,mips24Kc";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
clocks {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
xtal: xtal {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "qca,ar933x-pinctrl";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x18040000 0x100>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
apb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ehci0: ehci@1b000100 {
|
||||
compatible = "generic-ehci";
|
||||
reg = <0x1b000100 0x100>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart0: uart@18020000 {
|
||||
compatible = "qca,ar9330-uart";
|
||||
reg = <0x18020000 0x20>;
|
||||
interrupts = <128 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac0: eth@0x19000000 {
|
||||
compatible = "qca,ag7240-mac";
|
||||
reg = <0x19000000 0x200>;
|
||||
phy = <&phy0>;
|
||||
phy-mode = "rmii";
|
||||
|
||||
status = "disabled";
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gmac1: eth@0x1a000000 {
|
||||
compatible = "qca,ag7240-mac";
|
||||
reg = <0x1a000000 0x200>;
|
||||
phy = <&phy0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@1f000000 {
|
||||
compatible = "qca,ar7100-spi";
|
||||
reg = <0x1f000000 0x10>;
|
||||
interrupts = <129 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
112
arch/mips/dts/ar934x.dtsi
Normal file
112
arch/mips/dts/ar934x.dtsi
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "qca,ar934x";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "mips,mips74Kc";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
clocks {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
xtal: xtal {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
};
|
||||
|
||||
ahb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
apb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ehci0: ehci@1b000100 {
|
||||
compatible = "generic-ehci";
|
||||
reg = <0x1b000100 0x100>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart0: uart@18020000 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x18020000 0x20>;
|
||||
reg-shift = <2>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac0: eth@0x19000000 {
|
||||
compatible = "qca,ag934x-mac";
|
||||
reg = <0x19000000 0x200>;
|
||||
phy = <&phy0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
status = "disabled";
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gmac1: eth@0x1a000000 {
|
||||
compatible = "qca,ag934x-mac";
|
||||
reg = <0x1a000000 0x200>;
|
||||
phy = <&phy1>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
status = "disabled";
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy1: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@1f000000 {
|
||||
compatible = "qca,ar7100-spi";
|
||||
reg = <0x1f000000 0x10>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
84
arch/mips/dts/qca953x.dtsi
Normal file
84
arch/mips/dts/qca953x.dtsi
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "qca,qca953x";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "mips,mips24Kc";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
clocks {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
xtal: xtal {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "qca,qca953x-pinctrl";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x18040000 0x100>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
apb {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
uart0: uart@18020000 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x18020000 0x20>;
|
||||
reg-shift = <2>;
|
||||
clock-frequency = <25000000>;
|
||||
interrupts = <128 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@1f000000 {
|
||||
compatible = "qca,ar7100-spi";
|
||||
reg = <0x1f000000 0x10>;
|
||||
interrupts = <129 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
53
arch/mips/dts/tplink_wdr4300.dts
Normal file
53
arch/mips/dts/tplink_wdr4300.dts
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "ar934x.dtsi"
|
||||
|
||||
/ {
|
||||
model = "TP-Link WDR4300 Board";
|
||||
compatible = "tplink,wdr4300", "qca,ar934x";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
spi0 = &spi0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
};
|
||||
|
||||
&ehci0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
phy-mode = "rgmii";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
spi-max-frequency = <25000000>;
|
||||
status = "okay";
|
||||
spi-flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "spi-flash";
|
||||
memory-map = <0x1e000000 0x00800000>;
|
||||
spi-max-frequency = <25000000>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
clock-frequency = <40000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&xtal {
|
||||
clock-frequency = <40000000>;
|
||||
};
|
@ -23,6 +23,12 @@ struct arch_global_data {
|
||||
unsigned long tbl;
|
||||
unsigned long lastinc;
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_ATH79
|
||||
unsigned long id;
|
||||
unsigned long soc;
|
||||
unsigned long rev;
|
||||
unsigned long ver;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <asm-generic/global_data.h>
|
||||
|
@ -64,7 +64,7 @@
|
||||
/* detect associativity */
|
||||
srl \sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF
|
||||
andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF)
|
||||
addi \sz, \sz, 1
|
||||
addiu \sz, \sz, 1
|
||||
|
||||
/* sz *= line_sz */
|
||||
mul \sz, \sz, \line_sz
|
||||
|
55
arch/mips/mach-ath79/Kconfig
Normal file
55
arch/mips/mach-ath79/Kconfig
Normal file
@ -0,0 +1,55 @@
|
||||
menu "QCA/Atheros 7xxx/9xxx platforms"
|
||||
depends on ARCH_ATH79
|
||||
|
||||
config SYS_SOC
|
||||
default "ath79"
|
||||
|
||||
config SOC_AR933X
|
||||
bool
|
||||
select SUPPORTS_BIG_ENDIAN
|
||||
select SUPPORTS_CPU_MIPS32_R1
|
||||
select SUPPORTS_CPU_MIPS32_R2
|
||||
select MIPS_TUNE_24KC
|
||||
help
|
||||
This supports QCA/Atheros ar933x family SOCs.
|
||||
|
||||
config SOC_AR934X
|
||||
bool
|
||||
select SUPPORTS_BIG_ENDIAN
|
||||
select SUPPORTS_CPU_MIPS32_R1
|
||||
select SUPPORTS_CPU_MIPS32_R2
|
||||
select MIPS_TUNE_74KC
|
||||
help
|
||||
This supports QCA/Atheros ar934x family SOCs.
|
||||
|
||||
config SOC_QCA953X
|
||||
bool
|
||||
select SUPPORTS_BIG_ENDIAN
|
||||
select SUPPORTS_CPU_MIPS32_R1
|
||||
select SUPPORTS_CPU_MIPS32_R2
|
||||
select MIPS_TUNE_24KC
|
||||
help
|
||||
This supports QCA/Atheros qca953x family SOCs.
|
||||
|
||||
choice
|
||||
prompt "Board select"
|
||||
|
||||
config TARGET_AP121
|
||||
bool "AP121 Reference Board"
|
||||
select SOC_AR933X
|
||||
|
||||
config TARGET_AP143
|
||||
bool "AP143 Reference Board"
|
||||
select SOC_QCA953X
|
||||
|
||||
config BOARD_TPLINK_WDR4300
|
||||
bool "TP-Link WDR4300 Board"
|
||||
select SOC_AR934X
|
||||
|
||||
endchoice
|
||||
|
||||
source "board/qca/ap121/Kconfig"
|
||||
source "board/qca/ap143/Kconfig"
|
||||
source "board/tplink/wdr4300/Kconfig"
|
||||
|
||||
endmenu
|
11
arch/mips/mach-ath79/Makefile
Normal file
11
arch/mips/mach-ath79/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += reset.o
|
||||
obj-y += cpu.o
|
||||
obj-y += dram.o
|
||||
|
||||
obj-$(CONFIG_SOC_AR933X) += ar933x/
|
||||
obj-$(CONFIG_SOC_AR934X) += ar934x/
|
||||
obj-$(CONFIG_SOC_QCA953X) += qca953x/
|
7
arch/mips/mach-ath79/ar933x/Makefile
Normal file
7
arch/mips/mach-ath79/ar933x/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += clk.o
|
||||
obj-y += ddr.o
|
||||
obj-y += lowlevel_init.o
|
89
arch/mips/mach-ath79/ar933x/clk.c
Normal file
89
arch/mips/mach-ath79/ar933x/clk.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static u32 ar933x_get_xtal(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = get_bootstrap();
|
||||
if (val & AR933X_BOOTSTRAP_REF_CLK_40)
|
||||
return 40000000;
|
||||
else
|
||||
return 25000000;
|
||||
}
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
return ar933x_get_xtal();
|
||||
}
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val, xtal, pll, div;
|
||||
|
||||
regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
xtal = ar933x_get_xtal();
|
||||
val = readl(regs + AR933X_PLL_CPU_CONFIG_REG);
|
||||
|
||||
/* VCOOUT = XTAL * DIV_INT */
|
||||
div = (val >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT)
|
||||
& AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
|
||||
pll = xtal / div;
|
||||
|
||||
/* PLLOUT = VCOOUT * (1/2^OUTDIV) */
|
||||
div = (val >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT)
|
||||
& AR933X_PLL_CPU_CONFIG_NINT_MASK;
|
||||
pll *= div;
|
||||
div = (val >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT)
|
||||
& AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
|
||||
if (!div)
|
||||
div = 1;
|
||||
pll >>= div;
|
||||
|
||||
val = readl(regs + AR933X_PLL_CLK_CTRL_REG);
|
||||
|
||||
/* CPU_CLK = PLLOUT / CPU_POST_DIV */
|
||||
div = ((val >> AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT)
|
||||
& AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1;
|
||||
gd->cpu_clk = pll / div;
|
||||
|
||||
/* DDR_CLK = PLLOUT / DDR_POST_DIV */
|
||||
div = ((val >> AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT)
|
||||
& AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1;
|
||||
gd->mem_clk = pll / div;
|
||||
|
||||
/* AHB_CLK = PLLOUT / AHB_POST_DIV */
|
||||
div = ((val >> AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT)
|
||||
& AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1;
|
||||
gd->bus_clk = pll / div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
if (!gd->bus_clk)
|
||||
get_clocks();
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
ulong get_ddr_freq(ulong dummy)
|
||||
{
|
||||
if (!gd->mem_clk)
|
||||
get_clocks();
|
||||
return gd->mem_clk;
|
||||
}
|
333
arch/mips/mach-ath79/ar933x/ddr.c
Normal file
333
arch/mips/mach-ath79/ar933x/ddr.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
* Based on Atheros LSDK/QSDK
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define DDR_CTRL_UPD_EMR3S BIT(5)
|
||||
#define DDR_CTRL_UPD_EMR2S BIT(4)
|
||||
#define DDR_CTRL_PRECHARGE BIT(3)
|
||||
#define DDR_CTRL_AUTO_REFRESH BIT(2)
|
||||
#define DDR_CTRL_UPD_EMRS BIT(1)
|
||||
#define DDR_CTRL_UPD_MRS BIT(0)
|
||||
|
||||
#define DDR_REFRESH_EN BIT(14)
|
||||
#define DDR_REFRESH_M 0x3ff
|
||||
#define DDR_REFRESH(x) ((x) & 0x3ff)
|
||||
#define DDR_REFRESH_VAL_25M (DDR_REFRESH_EN | DDR_REFRESH(390))
|
||||
#define DDR_REFRESH_VAL_40M (DDR_REFRESH_EN | DDR_REFRESH(624))
|
||||
|
||||
#define DDR_TRAS_S 0
|
||||
#define DDR_TRAS_M 0x1f
|
||||
#define DDR_TRAS(x) ((x) << DDR_TRAS_S)
|
||||
#define DDR_TRCD_M 0xf
|
||||
#define DDR_TRCD_S 5
|
||||
#define DDR_TRCD(x) ((x) << DDR_TRCD_S)
|
||||
#define DDR_TRP_M 0xf
|
||||
#define DDR_TRP_S 9
|
||||
#define DDR_TRP(x) ((x) << DDR_TRP_S)
|
||||
#define DDR_TRRD_M 0xf
|
||||
#define DDR_TRRD_S 13
|
||||
#define DDR_TRRD(x) ((x) << DDR_TRRD_S)
|
||||
#define DDR_TRFC_M 0x7f
|
||||
#define DDR_TRFC_S 17
|
||||
#define DDR_TRFC(x) ((x) << DDR_TRFC_S)
|
||||
#define DDR_TMRD_M 0xf
|
||||
#define DDR_TMRD_S 23
|
||||
#define DDR_TMRD(x) ((x) << DDR_TMRD_S)
|
||||
#define DDR_CAS_L_M 0x17
|
||||
#define DDR_CAS_L_S 27
|
||||
#define DDR_CAS_L(x) (((x) & DDR_CAS_L_M) << DDR_CAS_L_S)
|
||||
#define DDR_OPEN BIT(30)
|
||||
#define DDR_CONF_REG_VAL (DDR_TRAS(16) | DDR_TRCD(6) | \
|
||||
DDR_TRP(6) | DDR_TRRD(4) | \
|
||||
DDR_TRFC(30) | DDR_TMRD(15) | \
|
||||
DDR_CAS_L(7) | DDR_OPEN)
|
||||
|
||||
#define DDR_BURST_LEN_S 0
|
||||
#define DDR_BURST_LEN_M 0xf
|
||||
#define DDR_BURST_LEN(x) ((x) << DDR_BURST_LEN_S)
|
||||
#define DDR_BURST_TYPE BIT(4)
|
||||
#define DDR_CNTL_OE_EN BIT(5)
|
||||
#define DDR_PHASE_SEL BIT(6)
|
||||
#define DDR_CKE BIT(7)
|
||||
#define DDR_TWR_S 8
|
||||
#define DDR_TWR_M 0xf
|
||||
#define DDR_TWR(x) ((x) << DDR_TWR_S)
|
||||
#define DDR_TRTW_S 12
|
||||
#define DDR_TRTW_M 0x1f
|
||||
#define DDR_TRTW(x) ((x) << DDR_TRTW_S)
|
||||
#define DDR_TRTP_S 17
|
||||
#define DDR_TRTP_M 0xf
|
||||
#define DDR_TRTP(x) ((x) << DDR_TRTP_S)
|
||||
#define DDR_TWTR_S 21
|
||||
#define DDR_TWTR_M 0x1f
|
||||
#define DDR_TWTR(x) ((x) << DDR_TWTR_S)
|
||||
#define DDR_G_OPEN_L_S 26
|
||||
#define DDR_G_OPEN_L_M 0xf
|
||||
#define DDR_G_OPEN_L(x) ((x) << DDR_G_OPEN_L_S)
|
||||
#define DDR_HALF_WIDTH_LOW BIT(31)
|
||||
#define DDR_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \
|
||||
DDR_CKE | DDR_TWR(6) | DDR_TRTW(14) | \
|
||||
DDR_TRTP(8) | DDR_TWTR(14) | \
|
||||
DDR_G_OPEN_L(7) | DDR_HALF_WIDTH_LOW)
|
||||
|
||||
#define DDR2_CONF_TWL_S 10
|
||||
#define DDR2_CONF_TWL_M 0xf
|
||||
#define DDR2_CONF_TWL(x) (((x) & DDR2_CONF_TWL_M) << DDR2_CONF_TWL_S)
|
||||
#define DDR2_CONF_ODT BIT(9)
|
||||
#define DDR2_CONF_TFAW_S 2
|
||||
#define DDR2_CONF_TFAW_M 0x3f
|
||||
#define DDR2_CONF_TFAW(x) (((x) & DDR2_CONF_TFAW_M) << DDR2_CONF_TFAW_S)
|
||||
#define DDR2_CONF_EN BIT(0)
|
||||
#define DDR2_CONF_VAL (DDR2_CONF_TWL(2) | DDR2_CONF_ODT | \
|
||||
DDR2_CONF_TFAW(22) | DDR2_CONF_EN)
|
||||
|
||||
#define DDR1_EXT_MODE_VAL 0x02
|
||||
#define DDR2_EXT_MODE_VAL 0x402
|
||||
#define DDR2_EXT_MODE_OCD_VAL 0x382
|
||||
#define DDR1_MODE_DLL_VAL 0x133
|
||||
#define DDR2_MODE_DLL_VAL 0x100
|
||||
#define DDR1_MODE_VAL 0x33
|
||||
#define DDR2_MODE_VAL 0xa33
|
||||
#define DDR_TAP_VAL0 0x08
|
||||
#define DDR_TAP_VAL1 0x09
|
||||
|
||||
void ddr_init(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val;
|
||||
|
||||
regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
writel(DDR_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG);
|
||||
writel(DDR_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2);
|
||||
|
||||
val = get_bootstrap();
|
||||
if (val & AR933X_BOOTSTRAP_DDR2) {
|
||||
/* AHB maximum timeout */
|
||||
writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX);
|
||||
|
||||
/* Enable DDR2 */
|
||||
writel(DDR2_CONF_VAL, regs + AR933X_DDR_REG_DDR2_CONFIG);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Disable High Temperature Self-Refresh, Full Array */
|
||||
writel(0x00, regs + AR933X_DDR_REG_EMR2);
|
||||
|
||||
/* Extended Mode Register 2 Set (EMR2S) */
|
||||
writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
writel(0x00, regs + AR933X_DDR_REG_EMR3);
|
||||
|
||||
/* Extended Mode Register 3 Set (EMR3S) */
|
||||
writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Enable DLL, Full strength, ODT Disabled */
|
||||
writel(0x00, regs + AR71XX_DDR_REG_EMR);
|
||||
|
||||
/* Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Reset DLL */
|
||||
writel(DDR2_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
|
||||
/* Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Auto Refresh */
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Write recovery (WR) 6 clock, CAS Latency 3, Burst Length 8 */
|
||||
writel(DDR2_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
/* Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Enable OCD defaults, Enable DLL, Reduced Drive Strength */
|
||||
writel(DDR2_EXT_MODE_OCD_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
|
||||
/* Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* OCD exit, Enable DLL, Enable /DQS, Reduced Drive Strength */
|
||||
writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
/* Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Refresh time control */
|
||||
if (val & AR933X_BOOTSTRAP_REF_CLK_40)
|
||||
writel(DDR_REFRESH_VAL_40M, regs +
|
||||
AR71XX_DDR_REG_REFRESH);
|
||||
else
|
||||
writel(DDR_REFRESH_VAL_25M, regs +
|
||||
AR71XX_DDR_REG_REFRESH);
|
||||
|
||||
/* DQS 0 Tap Control */
|
||||
writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
|
||||
/* DQS 1 Tap Control */
|
||||
writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
|
||||
/* For 16-bit DDR */
|
||||
writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE);
|
||||
} else {
|
||||
/* AHB maximum timeout */
|
||||
writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Reset DLL, Burst Length 8, CAS Latency 3 */
|
||||
writel(DDR1_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
|
||||
/* Forces an MRS update cycle in DDR */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Enable DLL, Full strength */
|
||||
writel(DDR1_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
|
||||
/* Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Normal DLL, Burst Length 8, CAS Latency 3 */
|
||||
writel(DDR1_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
|
||||
/* Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
|
||||
/* Refresh time control */
|
||||
if (val & AR933X_BOOTSTRAP_REF_CLK_40)
|
||||
writel(DDR_REFRESH_VAL_40M, regs +
|
||||
AR71XX_DDR_REG_REFRESH);
|
||||
else
|
||||
writel(DDR_REFRESH_VAL_25M, regs +
|
||||
AR71XX_DDR_REG_REFRESH);
|
||||
|
||||
/* DQS 0 Tap Control */
|
||||
writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
|
||||
/* DQS 1 Tap Control */
|
||||
writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
|
||||
/* For 16-bit DDR */
|
||||
writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE);
|
||||
}
|
||||
}
|
||||
|
||||
void ddr_tap_tuning(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 *addr_k0, *addr_k1, *addr;
|
||||
u32 val, tap, upper, lower;
|
||||
int i, j, dir, err, done;
|
||||
|
||||
regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
/* Init memory pattern */
|
||||
addr = (void *)CKSEG0ADDR(0x2000);
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (i & (1 << j)) {
|
||||
if (j % 2)
|
||||
val |= 0xffff0000;
|
||||
else
|
||||
val |= 0x0000ffff;
|
||||
}
|
||||
|
||||
if (j % 2) {
|
||||
*addr++ = val;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
done = 0;
|
||||
dir = 1;
|
||||
tap = readl(regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
val = tap;
|
||||
while (!done) {
|
||||
err = 0;
|
||||
|
||||
/* Update new DDR tap value */
|
||||
writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
|
||||
/* Compare DDR with cache */
|
||||
for (i = 0; i < 2; i++) {
|
||||
addr_k1 = (void *)CKSEG1ADDR(0x2000);
|
||||
addr_k0 = (void *)CKSEG0ADDR(0x2000);
|
||||
addr = (void *)CKSEG0ADDR(0x3000);
|
||||
|
||||
while (addr_k0 < addr) {
|
||||
if (*addr_k1++ != *addr_k0++) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
/* Save upper/lower threshold if error */
|
||||
if (dir) {
|
||||
dir = 0;
|
||||
val--;
|
||||
upper = val;
|
||||
val = tap;
|
||||
} else {
|
||||
val++;
|
||||
lower = val;
|
||||
done = 1;
|
||||
}
|
||||
} else {
|
||||
/* Try the next value until limitation */
|
||||
if (dir) {
|
||||
if (val < 0x20) {
|
||||
val++;
|
||||
} else {
|
||||
dir = 0;
|
||||
upper = val;
|
||||
val = tap;
|
||||
}
|
||||
} else {
|
||||
if (!val) {
|
||||
lower = val;
|
||||
done = 1;
|
||||
} else {
|
||||
val--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* compute an intermediate value and write back */
|
||||
val = (upper + lower) / 2;
|
||||
writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
val++;
|
||||
writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
}
|
280
arch/mips/mach-ath79/ar933x/lowlevel_init.S
Normal file
280
arch/mips/mach-ath79/ar933x/lowlevel_init.S
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
* Based on Atheros LSDK/QSDK and u-boot_mod project
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
|
||||
#define SET_BIT(val, bit) ((val) | (1 << (bit)))
|
||||
#define SET_PLL_PD(val) SET_BIT(val, 30)
|
||||
#define AHB_DIV_TO_4(val) SET_BIT(SET_BIT(val, 15), 16)
|
||||
#define PLL_BYPASS(val) SET_BIT(val, 2)
|
||||
|
||||
#define MK_PLL_CONF(divint, refdiv, range, outdiv) \
|
||||
(((0x3F & divint) << 10) | \
|
||||
((0x1F & refdiv) << 16) | \
|
||||
((0x1 & range) << 21) | \
|
||||
((0x7 & outdiv) << 23) )
|
||||
|
||||
#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \
|
||||
(((0x3 & (cpudiv - 1)) << 5) | \
|
||||
((0x3 & (ddrdiv - 1)) << 10) | \
|
||||
((0x3 & (ahbdiv - 1)) << 15) )
|
||||
|
||||
/*
|
||||
* PLL_CPU_CONFIG_VAL
|
||||
*
|
||||
* Bit30 is set (CPU_PLLPWD = 1 -> power down control for CPU PLL)
|
||||
* After PLL configuration we need to clear this bit
|
||||
*
|
||||
* Values written into CPU PLL Configuration (CPU_PLL_CONFIG)
|
||||
*
|
||||
* bits 10..15 (6bit) DIV_INT (Integer part of the DIV to CPU PLL)
|
||||
* => 32 (0x20) VCOOUT = XTAL * DIV_INT
|
||||
* bits 16..20 (5bit) REFDIV (Reference clock divider)
|
||||
* => 1 (0x1) [Must start at values 1]
|
||||
* bits 21 (1bit) RANGE (VCO frequency range of the CPU PLL)
|
||||
* => 0 (0x0) [Doesn't impact clock values]
|
||||
* bits 23..25 (3bit) OUTDIV (Ratio between VCO and PLL output)
|
||||
* => 1 (0x1) [0 is illegal!]
|
||||
* PLLOUT = VCOOUT * (1/2^OUTDIV)
|
||||
*/
|
||||
/* DIV_INT=32 (25MHz*32/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
|
||||
#define PLL_CPU_CONFIG_VAL_40M MK_PLL_CONF(20, 1, 0, 1)
|
||||
/* DIV_INT=20 (40MHz*20/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
|
||||
#define PLL_CPU_CONFIG_VAL_25M MK_PLL_CONF(32, 1, 0, 1)
|
||||
|
||||
/*
|
||||
* PLL_CLK_CONTROL_VAL
|
||||
*
|
||||
* In PLL_CLK_CONTROL_VAL bit 2 is set (BYPASS = 1 -> bypass PLL)
|
||||
* After PLL configuration we need to clear this bit
|
||||
*
|
||||
* Values written into CPU Clock Control Register CLOCK_CONTROL
|
||||
*
|
||||
* bits 2 (1bit) BYPASS (Bypass PLL. This defaults to 1 for test.
|
||||
* Software must enable the CPU PLL for normal and
|
||||
* then set this bit to 0)
|
||||
* bits 5..6 (2bit) CPU_POST_DIV => 0 (DEFAULT, Ratio = 1)
|
||||
* CPU_CLK = PLLOUT / CPU_POST_DIV
|
||||
* bits 10..11 (2bit) DDR_POST_DIV => 0 (DEFAULT, Ratio = 1)
|
||||
* DDR_CLK = PLLOUT / DDR_POST_DIV
|
||||
* bits 15..16 (2bit) AHB_POST_DIV => 1 (DEFAULT, Ratio = 2)
|
||||
* AHB_CLK = PLLOUT / AHB_POST_DIV
|
||||
*
|
||||
*/
|
||||
#define PLL_CLK_CONTROL_VAL MK_CLK_CNTL(1, 1, 2)
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
|
||||
LEAF(lowlevel_init)
|
||||
/* These three WLAN_RESET will avoid original issue */
|
||||
li t3, 0x03
|
||||
1:
|
||||
li t0, CKSEG1ADDR(AR71XX_RESET_BASE)
|
||||
lw t1, AR933X_RESET_REG_RESET_MODULE(t0)
|
||||
ori t1, t1, 0x0800
|
||||
sw t1, AR933X_RESET_REG_RESET_MODULE(t0)
|
||||
nop
|
||||
lw t1, AR933X_RESET_REG_RESET_MODULE(t0)
|
||||
li t2, 0xfffff7ff
|
||||
and t1, t1, t2
|
||||
sw t1, AR933X_RESET_REG_RESET_MODULE(t0)
|
||||
nop
|
||||
addi t3, t3, -1
|
||||
bnez t3, 1b
|
||||
nop
|
||||
|
||||
li t2, 0x20
|
||||
2:
|
||||
beqz t2, 1b
|
||||
nop
|
||||
addi t2, t2, -1
|
||||
lw t5, AR933X_RESET_REG_BOOTSTRAP(t0)
|
||||
andi t1, t5, 0x10
|
||||
bnez t1, 2b
|
||||
nop
|
||||
|
||||
li t1, 0x02110E
|
||||
sw t1, AR933X_RESET_REG_BOOTSTRAP(t0)
|
||||
nop
|
||||
|
||||
/* RTC Force Wake */
|
||||
li t0, CKSEG1ADDR(AR933X_RTC_BASE)
|
||||
li t1, 0x03
|
||||
sw t1, AR933X_RTC_REG_FORCE_WAKE(t0)
|
||||
nop
|
||||
nop
|
||||
|
||||
/* RTC Reset */
|
||||
li t1, 0x00
|
||||
sw t1, AR933X_RTC_REG_RESET(t0)
|
||||
nop
|
||||
nop
|
||||
|
||||
li t1, 0x01
|
||||
sw t1, AR933X_RTC_REG_RESET(t0)
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Wait for RTC in on state */
|
||||
1:
|
||||
lw t1, AR933X_RTC_REG_STATUS(t0)
|
||||
andi t1, t1, 0x02
|
||||
beqz t1, 1b
|
||||
nop
|
||||
|
||||
/* Program ki/kd */
|
||||
li t0, CKSEG1ADDR(AR933X_SRIF_BASE)
|
||||
andi t1, t5, 0x01 # t5 BOOT_STRAP
|
||||
bnez t1, 1f
|
||||
nop
|
||||
li t1, 0x19e82f01
|
||||
b 2f
|
||||
nop
|
||||
1:
|
||||
li t1, 0x18e82f01
|
||||
2:
|
||||
sw t1, AR933X_SRIF_DDR_DPLL2_REG(t0)
|
||||
|
||||
/* Program phase shift */
|
||||
lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
li t2, 0xc07fffff
|
||||
and t1, t1, t2
|
||||
li t2, 0x800000
|
||||
or t1, t1, t2
|
||||
sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
nop
|
||||
|
||||
/* in some cases, the SoC doesn't start with higher clock on AHB */
|
||||
li t0, CKSEG1ADDR(AR71XX_PLL_BASE)
|
||||
li t1, AHB_DIV_TO_4(PLL_BYPASS(PLL_CLK_CONTROL_VAL))
|
||||
sw t1, AR933X_PLL_CLK_CTRL_REG(t0)
|
||||
nop
|
||||
|
||||
/* Set SETTLE_TIME in CPU PLL */
|
||||
andi t1, t5, 0x01 # t5 BOOT_STRAP
|
||||
bnez t1, 1f
|
||||
nop
|
||||
li t1, 0x0352
|
||||
b 2f
|
||||
nop
|
||||
1:
|
||||
li t1, 0x0550
|
||||
2:
|
||||
sw t1, AR71XX_PLL_REG_SEC_CONFIG(t0)
|
||||
nop
|
||||
|
||||
/* Set nint, frac, refdiv, outdiv, range according to xtal */
|
||||
0:
|
||||
andi t1, t5, 0x01 # t5 BOOT_STRAP
|
||||
bnez t1, 1f
|
||||
nop
|
||||
li t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_25M)
|
||||
b 2f
|
||||
nop
|
||||
1:
|
||||
li t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_40M)
|
||||
2:
|
||||
sw t1, AR933X_PLL_CPU_CONFIG_REG(t0)
|
||||
nop
|
||||
1:
|
||||
lw t1, AR933X_PLL_CPU_CONFIG_REG(t0)
|
||||
li t2, 0x80000000
|
||||
and t1, t1, t2
|
||||
bnez t1, 1b
|
||||
nop
|
||||
|
||||
/* Put frac bit19:10 configuration */
|
||||
li t1, 0x1003E8
|
||||
sw t1, AR933X_PLL_DITHER_FRAC_REG(t0)
|
||||
nop
|
||||
|
||||
/* Clear PLL power down bit in CPU PLL configuration */
|
||||
andi t1, t5, 0x01 # t5 BOOT_STRAP
|
||||
bnez t1, 1f
|
||||
nop
|
||||
li t1, PLL_CPU_CONFIG_VAL_25M
|
||||
b 2f
|
||||
nop
|
||||
1:
|
||||
li t1, PLL_CPU_CONFIG_VAL_40M
|
||||
2:
|
||||
sw t1, AR933X_PLL_CPU_CONFIG_REG(t0)
|
||||
nop
|
||||
|
||||
/* Wait for PLL update -> bit 31 in CPU_PLL_CONFIG should be 0 */
|
||||
1:
|
||||
lw t1, AR933X_PLL_CPU_CONFIG_REG(t0)
|
||||
li t2, 0x80000000
|
||||
and t1, t1, t2
|
||||
bnez t1, 1b
|
||||
nop
|
||||
|
||||
/* Confirm DDR PLL lock */
|
||||
li t3, 100
|
||||
li t4, 0
|
||||
|
||||
2:
|
||||
addi t4, t4, 1
|
||||
bgt t4, t3, 0b
|
||||
nop
|
||||
|
||||
li t3, 5
|
||||
3:
|
||||
/* Clear do_meas */
|
||||
li t0, CKSEG1ADDR(AR933X_SRIF_BASE)
|
||||
lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
li t2, 0xBFFFFFFF
|
||||
and t1, t1, t2
|
||||
sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
nop
|
||||
|
||||
li t2, 10
|
||||
1:
|
||||
subu t2, t2, 1
|
||||
bnez t2, 1b
|
||||
nop
|
||||
|
||||
/* Set do_meas */
|
||||
li t2, 0x40000000
|
||||
or t1, t1, t2
|
||||
sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
nop
|
||||
|
||||
/* Check meas_done */
|
||||
1:
|
||||
lw t1, AR933X_SRIF_DDR_DPLL4_REG(t0)
|
||||
andi t1, t1, 0x8
|
||||
beqz t1, 1b
|
||||
nop
|
||||
|
||||
lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
|
||||
li t2, 0x007FFFF8
|
||||
and t1, t1, t2
|
||||
srl t1, t1, 3
|
||||
li t2, 0x4000
|
||||
bgt t1, t2, 2b
|
||||
nop
|
||||
addi t3, t3, -1
|
||||
bnez t3, 3b
|
||||
nop
|
||||
|
||||
/* clear PLL bypass (bit 2) in CPU CLOCK CONTROL register */
|
||||
li t0, CKSEG1ADDR(AR71XX_PLL_BASE)
|
||||
li t1, PLL_CLK_CONTROL_VAL
|
||||
sw t1, AR933X_PLL_CLK_CTRL_REG(t0)
|
||||
nop
|
||||
|
||||
nop
|
||||
jr ra
|
||||
nop
|
||||
END(lowlevel_init)
|
7
arch/mips/mach-ath79/ar934x/Makefile
Normal file
7
arch/mips/mach-ath79/ar934x/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += cpu.o
|
||||
obj-y += clk.o
|
||||
obj-y += ddr.o
|
334
arch/mips/mach-ath79/ar934x/clk.c
Normal file
334
arch/mips/mach-ath79/ar934x/clk.c
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
#include <wait_bit.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* The math for calculating PLL:
|
||||
* NFRAC * 2^8
|
||||
* NINT + -------------
|
||||
* XTAL [MHz] 2^(18 - 1)
|
||||
* PLL [MHz] = ------------ * ----------------------
|
||||
* REFDIV 2^OUTDIV
|
||||
*
|
||||
* Unfortunatelly, there is no way to reliably compute the variables.
|
||||
* The vendor U-Boot port contains macros for various combinations of
|
||||
* CPU PLL / DDR PLL / AHB bus speed and there is no obvious pattern
|
||||
* in those numbers.
|
||||
*/
|
||||
struct ar934x_pll_config {
|
||||
u8 range;
|
||||
u8 refdiv;
|
||||
u8 outdiv;
|
||||
/* Index 0 is for XTAL=25MHz , Index 1 is for XTAL=40MHz */
|
||||
u8 nint[2];
|
||||
};
|
||||
|
||||
struct ar934x_clock_config {
|
||||
u16 cpu_freq;
|
||||
u16 ddr_freq;
|
||||
u16 ahb_freq;
|
||||
|
||||
struct ar934x_pll_config cpu_pll;
|
||||
struct ar934x_pll_config ddr_pll;
|
||||
};
|
||||
|
||||
static const struct ar934x_clock_config ar934x_clock_config[] = {
|
||||
{ 300, 300, 150, { 1, 1, 1, { 24, 15 } }, { 1, 1, 1, { 24, 15 } } },
|
||||
{ 400, 200, 200, { 1, 1, 1, { 32, 20 } }, { 1, 1, 2, { 32, 20 } } },
|
||||
{ 400, 400, 200, { 0, 1, 1, { 32, 20 } }, { 0, 1, 1, { 32, 20 } } },
|
||||
{ 500, 400, 200, { 1, 1, 0, { 20, 12 } }, { 0, 1, 1, { 32, 20 } } },
|
||||
{ 533, 400, 200, { 1, 1, 0, { 21, 13 } }, { 0, 1, 1, { 32, 20 } } },
|
||||
{ 533, 500, 250, { 1, 1, 0, { 21, 13 } }, { 0, 1, 0, { 20, 12 } } },
|
||||
{ 560, 480, 240, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 12 } } },
|
||||
{ 566, 400, 200, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 16, 10 } } },
|
||||
{ 566, 450, 225, { 1, 1, 0, { 22, 14 } }, { 0, 1, 1, { 36, 22 } } },
|
||||
{ 566, 475, 237, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 11 } } },
|
||||
{ 566, 500, 250, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 20, 12 } } },
|
||||
{ 566, 525, 262, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 21, 13 } } },
|
||||
{ 566, 550, 275, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 22, 13 } } },
|
||||
{ 600, 266, 133, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } },
|
||||
{ 600, 266, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } },
|
||||
{ 600, 300, 150, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 24, 15 } } },
|
||||
{ 600, 332, 166, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } },
|
||||
{ 600, 332, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } },
|
||||
{ 600, 400, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 32, 20 } } },
|
||||
{ 600, 450, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 18, 20 } } },
|
||||
{ 600, 500, 250, { 0, 1, 0, { 24, 15 } }, { 1, 1, 0, { 20, 12 } } },
|
||||
{ 600, 525, 262, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 21, 20 } } },
|
||||
{ 600, 550, 275, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 22, 20 } } },
|
||||
{ 600, 575, 287, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 23, 14 } } },
|
||||
{ 600, 600, 300, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 24, 20 } } },
|
||||
{ 600, 650, 325, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 26, 20 } } },
|
||||
{ 650, 600, 300, { 0, 1, 0, { 26, 15 } }, { 0, 1, 0, { 24, 20 } } },
|
||||
{ 700, 400, 200, { 3, 1, 0, { 28, 17 } }, { 0, 1, 1, { 32, 20 } } },
|
||||
};
|
||||
|
||||
static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
|
||||
{
|
||||
u32 reg;
|
||||
do {
|
||||
writel(0x10810f00, pll_reg_base + 0x4);
|
||||
writel(srif_val, pll_reg_base + 0x0);
|
||||
writel(0xd0810f00, pll_reg_base + 0x4);
|
||||
writel(0x03000000, pll_reg_base + 0x8);
|
||||
writel(0xd0800f00, pll_reg_base + 0x4);
|
||||
|
||||
clrbits_be32(pll_reg_base + 0x8, BIT(30));
|
||||
udelay(5);
|
||||
setbits_be32(pll_reg_base + 0x8, BIT(30));
|
||||
udelay(5);
|
||||
|
||||
wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0);
|
||||
|
||||
clrbits_be32(pll_reg_base + 0x8, BIT(30));
|
||||
udelay(5);
|
||||
|
||||
/* Check if CPU SRIF PLL locked. */
|
||||
reg = readl(pll_reg_base + 0x8);
|
||||
reg = (reg & 0x7ffff8) >> 3;
|
||||
} while (reg >= 0x40000);
|
||||
}
|
||||
|
||||
void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz)
|
||||
{
|
||||
void __iomem *srif_regs = map_physmem(AR934X_SRIF_BASE,
|
||||
AR934X_SRIF_SIZE, MAP_NOCACHE);
|
||||
void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
|
||||
AR71XX_PLL_SIZE, MAP_NOCACHE);
|
||||
const struct ar934x_pll_config *pll_cfg;
|
||||
int i, pll_nint, pll_refdiv, xtal_40 = 0;
|
||||
u32 reg, cpu_pll, cpu_srif, ddr_pll, ddr_srif;
|
||||
|
||||
/* Configure SRIF PLL with initial values. */
|
||||
writel(0x13210f00, srif_regs + AR934X_SRIF_CPU_DPLL2_REG);
|
||||
writel(0x03000000, srif_regs + AR934X_SRIF_CPU_DPLL3_REG);
|
||||
writel(0x13210f00, srif_regs + AR934X_SRIF_DDR_DPLL2_REG);
|
||||
writel(0x03000000, srif_regs + AR934X_SRIF_DDR_DPLL3_REG);
|
||||
writel(0x03000000, srif_regs + 0x188); /* Undocumented reg :-) */
|
||||
|
||||
/* Test for 40MHz XTAL */
|
||||
reg = get_bootstrap();
|
||||
if (reg & AR934X_BOOTSTRAP_REF_CLK_40) {
|
||||
xtal_40 = 1;
|
||||
cpu_srif = 0x41c00000;
|
||||
ddr_srif = 0x41680000;
|
||||
} else {
|
||||
xtal_40 = 0;
|
||||
cpu_srif = 0x29c00000;
|
||||
ddr_srif = 0x29680000;
|
||||
}
|
||||
|
||||
/* Locate CPU/DDR PLL configuration */
|
||||
for (i = 0; i < ARRAY_SIZE(ar934x_clock_config); i++) {
|
||||
if (cpu_mhz != ar934x_clock_config[i].cpu_freq)
|
||||
continue;
|
||||
if (ddr_mhz != ar934x_clock_config[i].ddr_freq)
|
||||
continue;
|
||||
if (ahb_mhz != ar934x_clock_config[i].ahb_freq)
|
||||
continue;
|
||||
|
||||
/* Entry found */
|
||||
pll_cfg = &ar934x_clock_config[i].cpu_pll;
|
||||
pll_nint = pll_cfg->nint[xtal_40];
|
||||
pll_refdiv = pll_cfg->refdiv;
|
||||
cpu_pll =
|
||||
(pll_nint << AR934X_PLL_CPU_CONFIG_NINT_SHIFT) |
|
||||
(pll_refdiv << AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) |
|
||||
(pll_cfg->range << AR934X_PLL_CPU_CONFIG_RANGE_SHIFT) |
|
||||
(pll_cfg->outdiv << AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT);
|
||||
|
||||
pll_cfg = &ar934x_clock_config[i].ddr_pll;
|
||||
pll_nint = pll_cfg->nint[xtal_40];
|
||||
pll_refdiv = pll_cfg->refdiv;
|
||||
ddr_pll =
|
||||
(pll_nint << AR934X_PLL_DDR_CONFIG_NINT_SHIFT) |
|
||||
(pll_refdiv << AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) |
|
||||
(pll_cfg->range << AR934X_PLL_DDR_CONFIG_RANGE_SHIFT) |
|
||||
(pll_cfg->outdiv << AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT);
|
||||
break;
|
||||
}
|
||||
|
||||
/* PLL configuration not found, hang. */
|
||||
if (i == ARRAY_SIZE(ar934x_clock_config))
|
||||
hang();
|
||||
|
||||
/* Set PLL Bypass */
|
||||
setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
|
||||
setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
|
||||
setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
|
||||
|
||||
/* Configure CPU PLL */
|
||||
writel(cpu_pll | AR934X_PLL_CPU_CONFIG_PLLPWD,
|
||||
pll_regs + AR934X_PLL_CPU_CONFIG_REG);
|
||||
/* Configure DDR PLL */
|
||||
writel(ddr_pll | AR934X_PLL_DDR_CONFIG_PLLPWD,
|
||||
pll_regs + AR934X_PLL_DDR_CONFIG_REG);
|
||||
/* Configure PLL routing */
|
||||
writel(AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS |
|
||||
AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS |
|
||||
AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS |
|
||||
(0 << AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) |
|
||||
(0 << AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) |
|
||||
(1 << AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) |
|
||||
AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL |
|
||||
AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL |
|
||||
AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL,
|
||||
pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
|
||||
|
||||
/* Configure SRIF PLLs, which is completely undocumented :-) */
|
||||
ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_CPU_DPLL1_REG, cpu_srif);
|
||||
ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_DDR_DPLL1_REG, ddr_srif);
|
||||
|
||||
/* Unset PLL Bypass */
|
||||
clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
|
||||
clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
|
||||
clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG,
|
||||
AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
|
||||
|
||||
/* Enable PLL dithering */
|
||||
writel((1 << AR934X_PLL_DDR_DIT_FRAC_STEP_SHIFT) |
|
||||
(0xf << AR934X_PLL_DDR_DIT_UPD_CNT_SHIFT),
|
||||
pll_regs + AR934X_PLL_DDR_DIT_FRAC_REG);
|
||||
writel(48 << AR934X_PLL_CPU_DIT_UPD_CNT_SHIFT,
|
||||
pll_regs + AR934X_PLL_CPU_DIT_FRAC_REG);
|
||||
}
|
||||
|
||||
static u32 ar934x_get_xtal(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = get_bootstrap();
|
||||
if (val & AR934X_BOOTSTRAP_REF_CLK_40)
|
||||
return 40000000;
|
||||
else
|
||||
return 25000000;
|
||||
}
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
return ar934x_get_xtal();
|
||||
}
|
||||
|
||||
static u32 ar934x_cpupll_to_hz(const u32 regval)
|
||||
{
|
||||
const u32 outdiv = (regval >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
|
||||
AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
|
||||
const u32 refdiv = (regval >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
|
||||
AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
|
||||
const u32 nint = (regval >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
|
||||
AR934X_PLL_CPU_CONFIG_NINT_MASK;
|
||||
const u32 nfrac = (regval >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
|
||||
AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
|
||||
const u32 xtal = ar934x_get_xtal();
|
||||
|
||||
return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
|
||||
}
|
||||
|
||||
static u32 ar934x_ddrpll_to_hz(const u32 regval)
|
||||
{
|
||||
const u32 outdiv = (regval >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
|
||||
AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
|
||||
const u32 refdiv = (regval >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
|
||||
AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
|
||||
const u32 nint = (regval >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
|
||||
AR934X_PLL_DDR_CONFIG_NINT_MASK;
|
||||
const u32 nfrac = (regval >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
|
||||
AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
|
||||
const u32 xtal = ar934x_get_xtal();
|
||||
|
||||
return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
|
||||
}
|
||||
|
||||
static void ar934x_update_clock(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 ctrl, cpu, cpupll, ddr, ddrpll;
|
||||
u32 cpudiv, ddrdiv, busdiv;
|
||||
u32 cpuclk, ddrclk, busclk;
|
||||
|
||||
regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
cpu = readl(regs + AR934X_PLL_CPU_CONFIG_REG);
|
||||
ddr = readl(regs + AR934X_PLL_DDR_CONFIG_REG);
|
||||
ctrl = readl(regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
|
||||
|
||||
cpupll = ar934x_cpupll_to_hz(cpu);
|
||||
ddrpll = ar934x_ddrpll_to_hz(ddr);
|
||||
|
||||
if (ctrl & AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
|
||||
cpuclk = ar934x_get_xtal();
|
||||
else if (ctrl & AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
|
||||
cpuclk = cpupll;
|
||||
else
|
||||
cpuclk = ddrpll;
|
||||
|
||||
if (ctrl & AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
|
||||
ddrclk = ar934x_get_xtal();
|
||||
else if (ctrl & AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
|
||||
ddrclk = ddrpll;
|
||||
else
|
||||
ddrclk = cpupll;
|
||||
|
||||
if (ctrl & AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
|
||||
busclk = ar934x_get_xtal();
|
||||
else if (ctrl & AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
|
||||
busclk = ddrpll;
|
||||
else
|
||||
busclk = cpupll;
|
||||
|
||||
cpudiv = (ctrl >> AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
|
||||
AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
|
||||
ddrdiv = (ctrl >> AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
|
||||
AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
|
||||
busdiv = (ctrl >> AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
|
||||
AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
|
||||
|
||||
gd->cpu_clk = cpuclk / (cpudiv + 1);
|
||||
gd->mem_clk = ddrclk / (ddrdiv + 1);
|
||||
gd->bus_clk = busclk / (busdiv + 1);
|
||||
}
|
||||
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
ar934x_update_clock();
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
ulong get_ddr_freq(ulong dummy)
|
||||
{
|
||||
ar934x_update_clock();
|
||||
return gd->mem_clk;
|
||||
}
|
||||
|
||||
int do_ar934x_showclk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
ar934x_update_clock();
|
||||
printf("CPU: %8ld MHz\n", gd->cpu_clk / 1000000);
|
||||
printf("Memory: %8ld MHz\n", gd->mem_clk / 1000000);
|
||||
printf("AHB: %8ld MHz\n", gd->bus_clk / 1000000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
clocks, CONFIG_SYS_MAXARGS, 1, do_ar934x_showclk,
|
||||
"display clocks",
|
||||
""
|
||||
);
|
10
arch/mips/mach-ath79/ar934x/cpu.c
Normal file
10
arch/mips/mach-ath79/ar934x/cpu.c
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/* The lowlevel_init() is not needed on AR934x */
|
||||
void lowlevel_init(void) {}
|
163
arch/mips/mach-ath79/ar934x/ddr.c
Normal file
163
arch/mips/mach-ath79/ar934x/ddr.c
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* Based on RAM init sequence by Piotr Dymacz <pepe2k@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
enum {
|
||||
AR934X_SDRAM = 0,
|
||||
AR934X_DDR1,
|
||||
AR934X_DDR2,
|
||||
};
|
||||
|
||||
struct ar934x_mem_config {
|
||||
u32 config1;
|
||||
u32 config2;
|
||||
u32 mode;
|
||||
u32 extmode;
|
||||
u32 tap;
|
||||
};
|
||||
|
||||
static const struct ar934x_mem_config ar934x_mem_config[] = {
|
||||
[AR934X_SDRAM] = { 0x7fbe8cd0, 0x959f66a8, 0x33, 0, 0x1f1f },
|
||||
[AR934X_DDR1] = { 0x7fd48cd0, 0x99d0e6a8, 0x33, 0, 0x14 },
|
||||
[AR934X_DDR2] = { 0xc7d48cd0, 0x9dd0e6a8, 0x33, 0, 0x10012 },
|
||||
};
|
||||
|
||||
void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz)
|
||||
{
|
||||
void __iomem *ddr_regs;
|
||||
const struct ar934x_mem_config *memcfg;
|
||||
int memtype;
|
||||
u32 reg, cycle, ctl;
|
||||
|
||||
ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
reg = get_bootstrap();
|
||||
if (reg & AR934X_BOOTSTRAP_SDRAM_DISABLED) { /* DDR */
|
||||
if (reg & AR934X_BOOTSTRAP_DDR1) { /* DDR 1 */
|
||||
memtype = AR934X_DDR1;
|
||||
cycle = 0xffff;
|
||||
} else { /* DDR 2 */
|
||||
memtype = AR934X_DDR2;
|
||||
if (gd->arch.rev) {
|
||||
ctl = BIT(6); /* Undocumented bit :-( */
|
||||
if (reg & BIT(3))
|
||||
cycle = 0xff;
|
||||
else
|
||||
cycle = 0xffff;
|
||||
} else {
|
||||
/* Force DDR2/x16 configuratio on old chips. */
|
||||
ctl = 0;
|
||||
cycle = 0xffff; /* DDR2 16bit */
|
||||
}
|
||||
|
||||
writel(0xe59, ddr_regs + AR934X_DDR_REG_DDR2_CONFIG);
|
||||
udelay(100);
|
||||
|
||||
writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(ctl, ddr_regs + AR934X_DDR_REG_CTL_CONF);
|
||||
udelay(10);
|
||||
}
|
||||
} else { /* SDRAM */
|
||||
memtype = AR934X_SDRAM;
|
||||
cycle = 0xffffffff;
|
||||
|
||||
writel(0x13b, ddr_regs + AR934X_DDR_REG_CTL_CONF);
|
||||
udelay(100);
|
||||
|
||||
/* Undocumented register */
|
||||
writel(0x13b, ddr_regs + 0x118);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
memcfg = &ar934x_mem_config[memtype];
|
||||
|
||||
writel(memcfg->config1, ddr_regs + AR71XX_DDR_REG_CONFIG);
|
||||
udelay(100);
|
||||
|
||||
writel(memcfg->config2, ddr_regs + AR71XX_DDR_REG_CONFIG2);
|
||||
udelay(100);
|
||||
|
||||
writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(memcfg->mode | 0x100, ddr_regs + AR71XX_DDR_REG_MODE);
|
||||
mdelay(1);
|
||||
|
||||
writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
if (memtype == AR934X_DDR2) {
|
||||
writel(memcfg->mode | 0x100, ddr_regs + AR71XX_DDR_REG_EMR);
|
||||
udelay(100);
|
||||
|
||||
writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (memtype != AR934X_SDRAM)
|
||||
writel(0x402, ddr_regs + AR71XX_DDR_REG_EMR);
|
||||
|
||||
udelay(100);
|
||||
|
||||
writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(memcfg->mode, ddr_regs + AR71XX_DDR_REG_MODE);
|
||||
udelay(100);
|
||||
|
||||
writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
|
||||
writel(0x412c /* FIXME */, ddr_regs + AR71XX_DDR_REG_REFRESH);
|
||||
udelay(100);
|
||||
|
||||
writel(memcfg->tap, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
writel(memcfg->tap, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
|
||||
if (memtype != AR934X_SDRAM) {
|
||||
if ((gd->arch.rev && (reg & BIT(3))) || !gd->arch.rev) {
|
||||
writel(memcfg->tap,
|
||||
ddr_regs + AR934X_DDR_REG_TAP_CTRL2);
|
||||
writel(memcfg->tap,
|
||||
ddr_regs + AR934X_DDR_REG_TAP_CTRL3);
|
||||
}
|
||||
}
|
||||
|
||||
writel(cycle, ddr_regs + AR71XX_DDR_REG_RD_CYCLE);
|
||||
udelay(100);
|
||||
|
||||
writel(0x74444444, ddr_regs + AR934X_DDR_REG_BURST);
|
||||
udelay(100);
|
||||
|
||||
writel(0x222, ddr_regs + AR934X_DDR_REG_BURST2);
|
||||
udelay(100);
|
||||
|
||||
writel(0xfffff, ddr_regs + AR934X_DDR_REG_TIMEOUT_MAX);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
void ddr_tap_tuning(void)
|
||||
{
|
||||
}
|
142
arch/mips/mach-ath79/cpu.c
Normal file
142
arch/mips/mach-ath79/cpu.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ath79.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
|
||||
struct ath79_soc_desc {
|
||||
const enum ath79_soc_type soc;
|
||||
const char *chip;
|
||||
const int major;
|
||||
const int minor;
|
||||
};
|
||||
|
||||
static const struct ath79_soc_desc desc[] = {
|
||||
{ATH79_SOC_AR7130, "7130",
|
||||
REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7130},
|
||||
{ATH79_SOC_AR7141, "7141",
|
||||
REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7141},
|
||||
{ATH79_SOC_AR7161, "7161",
|
||||
REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7161},
|
||||
{ATH79_SOC_AR7240, "7240", REV_ID_MAJOR_AR7240, 0},
|
||||
{ATH79_SOC_AR7241, "7241", REV_ID_MAJOR_AR7241, 0},
|
||||
{ATH79_SOC_AR7242, "7242", REV_ID_MAJOR_AR7242, 0},
|
||||
{ATH79_SOC_AR9130, "9130",
|
||||
REV_ID_MAJOR_AR913X, AR913X_REV_ID_MINOR_AR9130},
|
||||
{ATH79_SOC_AR9132, "9132",
|
||||
REV_ID_MAJOR_AR913X, AR913X_REV_ID_MINOR_AR9132},
|
||||
{ATH79_SOC_AR9330, "9330", REV_ID_MAJOR_AR9330, 0},
|
||||
{ATH79_SOC_AR9331, "9331", REV_ID_MAJOR_AR9331, 0},
|
||||
{ATH79_SOC_AR9341, "9341", REV_ID_MAJOR_AR9341, 0},
|
||||
{ATH79_SOC_AR9342, "9342", REV_ID_MAJOR_AR9342, 0},
|
||||
{ATH79_SOC_AR9344, "9344", REV_ID_MAJOR_AR9344, 0},
|
||||
{ATH79_SOC_QCA9533, "9533", REV_ID_MAJOR_QCA9533, 0},
|
||||
{ATH79_SOC_QCA9533, "9533",
|
||||
REV_ID_MAJOR_QCA9533_V2, 0},
|
||||
{ATH79_SOC_QCA9556, "9556", REV_ID_MAJOR_QCA9556, 0},
|
||||
{ATH79_SOC_QCA9558, "9558", REV_ID_MAJOR_QCA9558, 0},
|
||||
{ATH79_SOC_TP9343, "9343", REV_ID_MAJOR_TP9343, 0},
|
||||
{ATH79_SOC_QCA9561, "9561", REV_ID_MAJOR_QCA9561, 0},
|
||||
};
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
|
||||
u32 id, major, minor = 0;
|
||||
u32 rev = 0, ver = 1;
|
||||
int i;
|
||||
|
||||
base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
id = readl(base + AR71XX_RESET_REG_REV_ID);
|
||||
major = id & REV_ID_MAJOR_MASK;
|
||||
switch (major) {
|
||||
case REV_ID_MAJOR_AR71XX:
|
||||
case REV_ID_MAJOR_AR913X:
|
||||
minor = id & AR71XX_REV_ID_MINOR_MASK;
|
||||
rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
|
||||
rev &= AR71XX_REV_ID_REVISION_MASK;
|
||||
break;
|
||||
|
||||
case REV_ID_MAJOR_QCA9533_V2:
|
||||
ver = 2;
|
||||
/* drop through */
|
||||
|
||||
case REV_ID_MAJOR_AR9341:
|
||||
case REV_ID_MAJOR_AR9342:
|
||||
case REV_ID_MAJOR_AR9344:
|
||||
case REV_ID_MAJOR_QCA9533:
|
||||
case REV_ID_MAJOR_QCA9556:
|
||||
case REV_ID_MAJOR_QCA9558:
|
||||
case REV_ID_MAJOR_TP9343:
|
||||
case REV_ID_MAJOR_QCA9561:
|
||||
rev = id & AR71XX_REV_ID_REVISION2_MASK;
|
||||
break;
|
||||
default:
|
||||
rev = id & AR71XX_REV_ID_REVISION_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(desc); i++) {
|
||||
if ((desc[i].major == major) &&
|
||||
(desc[i].minor == minor)) {
|
||||
soc = desc[i].soc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gd->arch.id = id;
|
||||
gd->arch.soc = soc;
|
||||
gd->arch.rev = rev;
|
||||
gd->arch.ver = ver;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
|
||||
const char *chip = "????";
|
||||
u32 id, rev, ver;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(desc); i++) {
|
||||
if (desc[i].soc == gd->arch.soc) {
|
||||
chip = desc[i].chip;
|
||||
soc = desc[i].soc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
id = gd->arch.id;
|
||||
rev = gd->arch.rev;
|
||||
ver = gd->arch.ver;
|
||||
|
||||
switch (soc) {
|
||||
case ATH79_SOC_QCA9533:
|
||||
case ATH79_SOC_QCA9556:
|
||||
case ATH79_SOC_QCA9558:
|
||||
case ATH79_SOC_QCA9561:
|
||||
printf("Qualcomm Atheros QCA%s ver %u rev %u\n", chip,
|
||||
ver, rev);
|
||||
break;
|
||||
case ATH79_SOC_TP9343:
|
||||
printf("Qualcomm Atheros TP%s rev %u\n", chip, rev);
|
||||
break;
|
||||
case ATH79_SOC_UNKNOWN:
|
||||
printf("ATH79: unknown SoC, id:0x%08x", id);
|
||||
break;
|
||||
default:
|
||||
printf("Atheros AR%s rev %u\n", chip, rev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
16
arch/mips/mach-ath79/dram.c
Normal file
16
arch/mips/mach-ath79/dram.c
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <mach/ddr.h>
|
||||
|
||||
phys_size_t initdram(int board_type)
|
||||
{
|
||||
ddr_tap_tuning();
|
||||
return get_ram_size((void *)KSEG1, SZ_256M);
|
||||
}
|
1263
arch/mips/mach-ath79/include/mach/ar71xx_regs.h
Normal file
1263
arch/mips/mach-ath79/include/mach/ar71xx_regs.h
Normal file
File diff suppressed because it is too large
Load Diff
149
arch/mips/mach-ath79/include/mach/ath79.h
Normal file
149
arch/mips/mach-ath79/include/mach/ath79.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Atheros AR71XX/AR724X/AR913X common definitions
|
||||
*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
|
||||
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_ATH79_H
|
||||
#define __ASM_MACH_ATH79_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
enum ath79_soc_type {
|
||||
ATH79_SOC_UNKNOWN,
|
||||
ATH79_SOC_AR7130,
|
||||
ATH79_SOC_AR7141,
|
||||
ATH79_SOC_AR7161,
|
||||
ATH79_SOC_AR7240,
|
||||
ATH79_SOC_AR7241,
|
||||
ATH79_SOC_AR7242,
|
||||
ATH79_SOC_AR9130,
|
||||
ATH79_SOC_AR9132,
|
||||
ATH79_SOC_AR9330,
|
||||
ATH79_SOC_AR9331,
|
||||
ATH79_SOC_AR9341,
|
||||
ATH79_SOC_AR9342,
|
||||
ATH79_SOC_AR9344,
|
||||
ATH79_SOC_QCA9533,
|
||||
ATH79_SOC_QCA9556,
|
||||
ATH79_SOC_QCA9558,
|
||||
ATH79_SOC_TP9343,
|
||||
ATH79_SOC_QCA9561,
|
||||
};
|
||||
|
||||
static inline int soc_is_ar71xx(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR7130 ||
|
||||
gd->arch.soc == ATH79_SOC_AR7141 ||
|
||||
gd->arch.soc == ATH79_SOC_AR7161;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar724x(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR7240 ||
|
||||
gd->arch.soc == ATH79_SOC_AR7241 ||
|
||||
gd->arch.soc == ATH79_SOC_AR7242;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar7240(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR7240;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar7241(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR7241;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar7242(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR7242;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar913x(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR9130 ||
|
||||
gd->arch.soc == ATH79_SOC_AR9132;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar933x(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR9330 ||
|
||||
gd->arch.soc == ATH79_SOC_AR9331;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar9341(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR9341;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar9342(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR9342;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar9344(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_AR9344;
|
||||
}
|
||||
|
||||
static inline int soc_is_ar934x(void)
|
||||
{
|
||||
return soc_is_ar9341() ||
|
||||
soc_is_ar9342() ||
|
||||
soc_is_ar9344();
|
||||
}
|
||||
|
||||
static inline int soc_is_qca9533(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_QCA9533;
|
||||
}
|
||||
|
||||
static inline int soc_is_qca953x(void)
|
||||
{
|
||||
return soc_is_qca9533();
|
||||
}
|
||||
|
||||
static inline int soc_is_qca9556(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_QCA9556;
|
||||
}
|
||||
|
||||
static inline int soc_is_qca9558(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_QCA9558;
|
||||
}
|
||||
|
||||
static inline int soc_is_qca955x(void)
|
||||
{
|
||||
return soc_is_qca9556() || soc_is_qca9558();
|
||||
}
|
||||
|
||||
static inline int soc_is_tp9343(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_TP9343;
|
||||
}
|
||||
|
||||
static inline int soc_is_qca9561(void)
|
||||
{
|
||||
return gd->arch.soc == ATH79_SOC_QCA9561;
|
||||
}
|
||||
|
||||
static inline int soc_is_qca956x(void)
|
||||
{
|
||||
return soc_is_tp9343() || soc_is_qca9561();
|
||||
}
|
||||
|
||||
int ath79_eth_reset(void);
|
||||
int ath79_usb_reset(void);
|
||||
|
||||
void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
|
||||
void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
|
||||
|
||||
#endif /* __ASM_MACH_ATH79_H */
|
13
arch/mips/mach-ath79/include/mach/ddr.h
Normal file
13
arch/mips/mach-ath79/include/mach/ddr.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_DDR_H
|
||||
#define __ASM_MACH_DDR_H
|
||||
|
||||
void ddr_init(void);
|
||||
void ddr_tap_tuning(void);
|
||||
|
||||
#endif /* __ASM_MACH_DDR_H */
|
14
arch/mips/mach-ath79/include/mach/reset.h
Normal file
14
arch/mips/mach-ath79/include/mach/reset.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_RESET_H
|
||||
#define __ASM_MACH_RESET_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
u32 get_bootstrap(void);
|
||||
|
||||
#endif /* __ASM_MACH_RESET_H */
|
7
arch/mips/mach-ath79/qca953x/Makefile
Normal file
7
arch/mips/mach-ath79/qca953x/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += clk.o
|
||||
obj-y += ddr.o
|
||||
obj-y += lowlevel_init.o
|
111
arch/mips/mach-ath79/qca953x/clk.c
Normal file
111
arch/mips/mach-ath79/qca953x/clk.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static u32 qca953x_get_xtal(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = get_bootstrap();
|
||||
if (val & QCA953X_BOOTSTRAP_REF_CLK_40)
|
||||
return 40000000;
|
||||
else
|
||||
return 25000000;
|
||||
}
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
return qca953x_get_xtal();
|
||||
}
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val, ctrl, xtal, pll, div;
|
||||
|
||||
regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
xtal = qca953x_get_xtal();
|
||||
ctrl = readl(regs + QCA953X_PLL_CLK_CTRL_REG);
|
||||
val = readl(regs + QCA953X_PLL_CPU_CONFIG_REG);
|
||||
|
||||
/* VCOOUT = XTAL * DIV_INT */
|
||||
div = (val >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT)
|
||||
& QCA953X_PLL_CPU_CONFIG_REFDIV_MASK;
|
||||
pll = xtal / div;
|
||||
|
||||
/* PLLOUT = VCOOUT * (1/2^OUTDIV) */
|
||||
div = (val >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT)
|
||||
& QCA953X_PLL_CPU_CONFIG_NINT_MASK;
|
||||
pll *= div;
|
||||
div = (val >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT)
|
||||
& QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
|
||||
if (!div)
|
||||
div = 1;
|
||||
pll >>= div;
|
||||
|
||||
/* CPU_CLK = PLLOUT / CPU_POST_DIV */
|
||||
div = ((ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT)
|
||||
& QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1;
|
||||
gd->cpu_clk = pll / div;
|
||||
|
||||
|
||||
val = readl(regs + QCA953X_PLL_DDR_CONFIG_REG);
|
||||
/* VCOOUT = XTAL * DIV_INT */
|
||||
div = (val >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT)
|
||||
& QCA953X_PLL_DDR_CONFIG_REFDIV_MASK;
|
||||
pll = xtal / div;
|
||||
|
||||
/* PLLOUT = VCOOUT * (1/2^OUTDIV) */
|
||||
div = (val >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT)
|
||||
& QCA953X_PLL_DDR_CONFIG_NINT_MASK;
|
||||
pll *= div;
|
||||
div = (val >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT)
|
||||
& QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
|
||||
if (!div)
|
||||
div = 1;
|
||||
pll >>= div;
|
||||
|
||||
/* DDR_CLK = PLLOUT / DDR_POST_DIV */
|
||||
div = ((ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT)
|
||||
& QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1;
|
||||
gd->mem_clk = pll / div;
|
||||
|
||||
div = ((ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT)
|
||||
& QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1;
|
||||
if (ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) {
|
||||
/* AHB_CLK = DDR_CLK / AHB_POST_DIV */
|
||||
gd->bus_clk = gd->mem_clk / (div + 1);
|
||||
} else {
|
||||
/* AHB_CLK = CPU_CLK / AHB_POST_DIV */
|
||||
gd->bus_clk = gd->cpu_clk / (div + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
if (!gd->bus_clk)
|
||||
get_clocks();
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
ulong get_ddr_freq(ulong dummy)
|
||||
{
|
||||
if (!gd->mem_clk)
|
||||
get_clocks();
|
||||
return gd->mem_clk;
|
||||
}
|
472
arch/mips/mach-ath79/qca953x/ddr.c
Normal file
472
arch/mips/mach-ath79/qca953x/ddr.c
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
* Based on Atheros LSDK/QSDK
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define DDR_CTRL_UPD_EMR3S BIT(5)
|
||||
#define DDR_CTRL_UPD_EMR2S BIT(4)
|
||||
#define DDR_CTRL_PRECHARGE BIT(3)
|
||||
#define DDR_CTRL_AUTO_REFRESH BIT(2)
|
||||
#define DDR_CTRL_UPD_EMRS BIT(1)
|
||||
#define DDR_CTRL_UPD_MRS BIT(0)
|
||||
|
||||
#define DDR_REFRESH_EN BIT(14)
|
||||
#define DDR_REFRESH_M 0x3ff
|
||||
#define DDR_REFRESH(x) ((x) & DDR_REFRESH_M)
|
||||
#define DDR_REFRESH_VAL (DDR_REFRESH_EN | DDR_REFRESH(312))
|
||||
|
||||
#define DDR_TRAS_S 0
|
||||
#define DDR_TRAS_M 0x1f
|
||||
#define DDR_TRAS(x) (((x) & DDR_TRAS_M) << DDR_TRAS_S)
|
||||
#define DDR_TRCD_M 0xf
|
||||
#define DDR_TRCD_S 5
|
||||
#define DDR_TRCD(x) (((x) & DDR_TRCD_M) << DDR_TRCD_S)
|
||||
#define DDR_TRP_M 0xf
|
||||
#define DDR_TRP_S 9
|
||||
#define DDR_TRP(x) (((x) & DDR_TRP_M) << DDR_TRP_S)
|
||||
#define DDR_TRRD_M 0xf
|
||||
#define DDR_TRRD_S 13
|
||||
#define DDR_TRRD(x) (((x) & DDR_TRRD_M) << DDR_TRRD_S)
|
||||
#define DDR_TRFC_M 0x7f
|
||||
#define DDR_TRFC_S 17
|
||||
#define DDR_TRFC(x) (((x) & DDR_TRFC_M) << DDR_TRFC_S)
|
||||
#define DDR_TMRD_M 0xf
|
||||
#define DDR_TMRD_S 23
|
||||
#define DDR_TMRD(x) (((x) & DDR_TMRD_M) << DDR_TMRD_S)
|
||||
#define DDR_CAS_L_M 0x17
|
||||
#define DDR_CAS_L_S 27
|
||||
#define DDR_CAS_L(x) (((x) & DDR_CAS_L_M) << DDR_CAS_L_S)
|
||||
#define DDR_OPEN BIT(30)
|
||||
#define DDR1_CONF_REG_VAL (DDR_TRAS(16) | DDR_TRCD(6) | \
|
||||
DDR_TRP(6) | DDR_TRRD(4) | \
|
||||
DDR_TRFC(7) | DDR_TMRD(5) | \
|
||||
DDR_CAS_L(7) | DDR_OPEN)
|
||||
#define DDR2_CONF_REG_VAL (DDR_TRAS(27) | DDR_TRCD(9) | \
|
||||
DDR_TRP(9) | DDR_TRRD(7) | \
|
||||
DDR_TRFC(21) | DDR_TMRD(15) | \
|
||||
DDR_CAS_L(17) | DDR_OPEN)
|
||||
|
||||
#define DDR_BURST_LEN_S 0
|
||||
#define DDR_BURST_LEN_M 0xf
|
||||
#define DDR_BURST_LEN(x) ((x) << DDR_BURST_LEN_S)
|
||||
#define DDR_BURST_TYPE BIT(4)
|
||||
#define DDR_CNTL_OE_EN BIT(5)
|
||||
#define DDR_PHASE_SEL BIT(6)
|
||||
#define DDR_CKE BIT(7)
|
||||
#define DDR_TWR_S 8
|
||||
#define DDR_TWR_M 0xf
|
||||
#define DDR_TWR(x) (((x) & DDR_TWR_M) << DDR_TWR_S)
|
||||
#define DDR_TRTW_S 12
|
||||
#define DDR_TRTW_M 0x1f
|
||||
#define DDR_TRTW(x) (((x) & DDR_TRTW_M) << DDR_TRTW_S)
|
||||
#define DDR_TRTP_S 17
|
||||
#define DDR_TRTP_M 0xf
|
||||
#define DDR_TRTP(x) (((x) & DDR_TRTP_M) << DDR_TRTP_S)
|
||||
#define DDR_TWTR_S 21
|
||||
#define DDR_TWTR_M 0x1f
|
||||
#define DDR_TWTR(x) (((x) & DDR_TWTR_M) << DDR_TWTR_S)
|
||||
#define DDR_G_OPEN_L_S 26
|
||||
#define DDR_G_OPEN_L_M 0xf
|
||||
#define DDR_G_OPEN_L(x) ((x) << DDR_G_OPEN_L_S)
|
||||
#define DDR_HALF_WIDTH_LOW BIT(31)
|
||||
#define DDR1_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \
|
||||
DDR_CKE | DDR_TWR(13) | DDR_TRTW(14) | \
|
||||
DDR_TRTP(8) | DDR_TWTR(14) | \
|
||||
DDR_G_OPEN_L(6) | DDR_HALF_WIDTH_LOW)
|
||||
#define DDR2_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \
|
||||
DDR_CKE | DDR_TWR(1) | DDR_TRTW(14) | \
|
||||
DDR_TRTP(9) | DDR_TWTR(21) | \
|
||||
DDR_G_OPEN_L(8) | DDR_HALF_WIDTH_LOW)
|
||||
|
||||
#define DDR_TWR_MSB BIT(3)
|
||||
#define DDR_TRAS_MSB BIT(2)
|
||||
#define DDR_TRFC_MSB_M 0x3
|
||||
#define DDR_TRFC_MSB(x) (x)
|
||||
#define DDR1_CONF3_REG_VAL 0
|
||||
#define DDR2_CONF3_REG_VAL (DDR_TWR_MSB | DDR_TRFC_MSB(2))
|
||||
|
||||
#define DDR_CTL_SRAM_TSEL BIT(30)
|
||||
#define DDR_CTL_SRAM_GE0_SYNC BIT(20)
|
||||
#define DDR_CTL_SRAM_GE1_SYNC BIT(19)
|
||||
#define DDR_CTL_SRAM_USB_SYNC BIT(18)
|
||||
#define DDR_CTL_SRAM_PCIE_SYNC BIT(17)
|
||||
#define DDR_CTL_SRAM_WMAC_SYNC BIT(16)
|
||||
#define DDR_CTL_SRAM_MISC1_SYNC BIT(15)
|
||||
#define DDR_CTL_SRAM_MISC2_SYNC BIT(14)
|
||||
#define DDR_CTL_PAD_DDR2_SEL BIT(6)
|
||||
#define DDR_CTL_HALF_WIDTH BIT(1)
|
||||
#define DDR_CTL_CONFIG_VAL (DDR_CTL_SRAM_TSEL | \
|
||||
DDR_CTL_SRAM_GE0_SYNC | \
|
||||
DDR_CTL_SRAM_GE1_SYNC | \
|
||||
DDR_CTL_SRAM_USB_SYNC | \
|
||||
DDR_CTL_SRAM_PCIE_SYNC | \
|
||||
DDR_CTL_SRAM_WMAC_SYNC | \
|
||||
DDR_CTL_HALF_WIDTH)
|
||||
|
||||
#define DDR_BURST_GE0_MAX_BL_S 0
|
||||
#define DDR_BURST_GE0_MAX_BL_M 0xf
|
||||
#define DDR_BURST_GE0_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_GE0_MAX_BL_M) << DDR_BURST_GE0_MAX_BL_S)
|
||||
#define DDR_BURST_GE1_MAX_BL_S 4
|
||||
#define DDR_BURST_GE1_MAX_BL_M 0xf
|
||||
#define DDR_BURST_GE1_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_GE1_MAX_BL_M) << DDR_BURST_GE1_MAX_BL_S)
|
||||
#define DDR_BURST_PCIE_MAX_BL_S 8
|
||||
#define DDR_BURST_PCIE_MAX_BL_M 0xf
|
||||
#define DDR_BURST_PCIE_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_PCIE_MAX_BL_M) << DDR_BURST_PCIE_MAX_BL_S)
|
||||
#define DDR_BURST_USB_MAX_BL_S 12
|
||||
#define DDR_BURST_USB_MAX_BL_M 0xf
|
||||
#define DDR_BURST_USB_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_USB_MAX_BL_M) << DDR_BURST_USB_MAX_BL_S)
|
||||
#define DDR_BURST_CPU_MAX_BL_S 16
|
||||
#define DDR_BURST_CPU_MAX_BL_M 0xf
|
||||
#define DDR_BURST_CPU_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_CPU_MAX_BL_M) << DDR_BURST_CPU_MAX_BL_S)
|
||||
#define DDR_BURST_RD_MAX_BL_S 20
|
||||
#define DDR_BURST_RD_MAX_BL_M 0xf
|
||||
#define DDR_BURST_RD_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_RD_MAX_BL_M) << DDR_BURST_RD_MAX_BL_S)
|
||||
#define DDR_BURST_WR_MAX_BL_S 24
|
||||
#define DDR_BURST_WR_MAX_BL_M 0xf
|
||||
#define DDR_BURST_WR_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_WR_MAX_BL_M) << DDR_BURST_WR_MAX_BL_S)
|
||||
#define DDR_BURST_RWP_MASK_EN_S 28
|
||||
#define DDR_BURST_RWP_MASK_EN_M 0x3
|
||||
#define DDR_BURST_RWP_MASK_EN(x) \
|
||||
(((x) & DDR_BURST_RWP_MASK_EN_M) << DDR_BURST_RWP_MASK_EN_S)
|
||||
#define DDR_BURST_CPU_PRI_BE BIT(30)
|
||||
#define DDR_BURST_CPU_PRI BIT(31)
|
||||
#define DDR_BURST_VAL (DDR_BURST_CPU_PRI_BE | \
|
||||
DDR_BURST_RWP_MASK_EN(3) | \
|
||||
DDR_BURST_WR_MAX_BL(4) | \
|
||||
DDR_BURST_RD_MAX_BL(4) | \
|
||||
DDR_BURST_CPU_MAX_BL(4) | \
|
||||
DDR_BURST_USB_MAX_BL(4) | \
|
||||
DDR_BURST_PCIE_MAX_BL(4) | \
|
||||
DDR_BURST_GE1_MAX_BL(4) | \
|
||||
DDR_BURST_GE0_MAX_BL(4))
|
||||
|
||||
#define DDR_BURST_WMAC_MAX_BL_S 0
|
||||
#define DDR_BURST_WMAC_MAX_BL_M 0xf
|
||||
#define DDR_BURST_WMAC_MAX_BL(x) \
|
||||
(((x) & DDR_BURST_WMAC_MAX_BL_M) << DDR_BURST_WMAC_MAX_BL_S)
|
||||
#define DDR_BURST2_VAL DDR_BURST_WMAC_MAX_BL(4)
|
||||
|
||||
#define DDR2_CONF_TWL_S 10
|
||||
#define DDR2_CONF_TWL_M 0xf
|
||||
#define DDR2_CONF_TWL(x) \
|
||||
(((x) & DDR2_CONF_TWL_M) << DDR2_CONF_TWL_S)
|
||||
#define DDR2_CONF_ODT BIT(9)
|
||||
#define DDR2_CONF_TFAW_S 2
|
||||
#define DDR2_CONF_TFAW_M 0x3f
|
||||
#define DDR2_CONF_TFAW(x) \
|
||||
(((x) & DDR2_CONF_TFAW_M) << DDR2_CONF_TFAW_S)
|
||||
#define DDR2_CONF_EN BIT(0)
|
||||
#define DDR2_CONF_VAL (DDR2_CONF_TWL(5) | \
|
||||
DDR2_CONF_TFAW(31) | \
|
||||
DDR2_CONF_ODT | \
|
||||
DDR2_CONF_EN)
|
||||
|
||||
#define DDR1_EXT_MODE_VAL 0
|
||||
#define DDR2_EXT_MODE_VAL 0x402
|
||||
#define DDR2_EXT_MODE_OCD_VAL 0x782
|
||||
#define DDR1_MODE_DLL_VAL 0x133
|
||||
#define DDR2_MODE_DLL_VAL 0x143
|
||||
#define DDR1_MODE_VAL 0x33
|
||||
#define DDR2_MODE_VAL 0x43
|
||||
#define DDR1_TAP_VAL 0x20
|
||||
#define DDR2_TAP_VAL 0x10
|
||||
|
||||
#define DDR_REG_BIST_MASK_ADDR_0 0x2c
|
||||
#define DDR_REG_BIST_MASK_ADDR_1 0x30
|
||||
#define DDR_REG_BIST_MASK_AHB_GE0_0 0x34
|
||||
#define DDR_REG_BIST_COMP_AHB_GE0_0 0x38
|
||||
#define DDR_REG_BIST_MASK_AHB_GE1_0 0x3c
|
||||
#define DDR_REG_BIST_COMP_AHB_GE1_0 0x40
|
||||
#define DDR_REG_BIST_COMP_ADDR_0 0x64
|
||||
#define DDR_REG_BIST_COMP_ADDR_1 0x68
|
||||
#define DDR_REG_BIST_MASK_AHB_GE0_1 0x6c
|
||||
#define DDR_REG_BIST_COMP_AHB_GE0_1 0x70
|
||||
#define DDR_REG_BIST_MASK_AHB_GE1_1 0x74
|
||||
#define DDR_REG_BIST_COMP_AHB_GE1_1 0x78
|
||||
#define DDR_REG_BIST 0x11c
|
||||
#define DDR_REG_BIST_STATUS 0x120
|
||||
|
||||
#define DDR_BIST_COMP_CNT_S 1
|
||||
#define DDR_BIST_COMP_CNT_M 0xff
|
||||
#define DDR_BIST_COMP_CNT(x) \
|
||||
(((x) & DDR_BIST_COMP_CNT_M) << DDR_BIST_COMP_CNT_S)
|
||||
#define DDR_BIST_COMP_CNT_MASK \
|
||||
(DDR_BIST_COMP_CNT_M << DDR_BIST_COMP_CNT_S)
|
||||
#define DDR_BIST_TEST_START BIT(0)
|
||||
#define DDR_BIST_STATUS_DONE BIT(0)
|
||||
|
||||
/* 4 Row Address Bits, 4 Column Address Bits, 2 BA bits */
|
||||
#define DDR_BIST_MASK_ADDR_VAL 0xfa5de83f
|
||||
|
||||
#define DDR_TAP_MAGIC_VAL 0xaa55aa55
|
||||
#define DDR_TAP_MAX_VAL 0x40
|
||||
|
||||
void ddr_init(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val;
|
||||
|
||||
regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
val = get_bootstrap();
|
||||
if (val & QCA953X_BOOTSTRAP_DDR1) {
|
||||
writel(DDR_CTL_CONFIG_VAL, regs + QCA953X_DDR_REG_CTL_CONF);
|
||||
udelay(10);
|
||||
|
||||
/* For 16-bit DDR */
|
||||
writel(0xffff, regs + AR71XX_DDR_REG_RD_CYCLE);
|
||||
udelay(100);
|
||||
|
||||
/* Burst size */
|
||||
writel(DDR_BURST_VAL, regs + QCA953X_DDR_REG_BURST);
|
||||
udelay(100);
|
||||
writel(DDR_BURST2_VAL, regs + QCA953X_DDR_REG_BURST2);
|
||||
udelay(100);
|
||||
|
||||
/* AHB maximum timeout */
|
||||
writel(0xfffff, regs + QCA953X_DDR_REG_TIMEOUT_MAX);
|
||||
udelay(100);
|
||||
|
||||
/* DRAM timing */
|
||||
writel(DDR1_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG);
|
||||
udelay(100);
|
||||
writel(DDR1_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2);
|
||||
udelay(100);
|
||||
writel(DDR1_CONF3_REG_VAL, regs + QCA953X_DDR_REG_CONFIG3);
|
||||
udelay(100);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* ODT disable, Full strength, Enable DLL */
|
||||
writel(DDR1_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Reset DLL, CAS Latency 3, Burst Length 8 */
|
||||
writel(DDR1_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
udelay(100);
|
||||
|
||||
/* Update Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Auto Refresh */
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Normal DLL, CAS Latency 3, Burst Length 8 */
|
||||
writel(DDR1_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
udelay(100);
|
||||
|
||||
/* Update Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Refresh time control */
|
||||
writel(DDR_REFRESH_VAL, regs + AR71XX_DDR_REG_REFRESH);
|
||||
udelay(100);
|
||||
|
||||
/* DQS 0 Tap Control */
|
||||
writel(DDR1_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
|
||||
/* DQS 1 Tap Control */
|
||||
writel(DDR1_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
} else {
|
||||
writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(10);
|
||||
writel(DDR_CTL_CONFIG_VAL | DDR_CTL_PAD_DDR2_SEL,
|
||||
regs + QCA953X_DDR_REG_CTL_CONF);
|
||||
udelay(10);
|
||||
|
||||
/* For 16-bit DDR */
|
||||
writel(0xffff, regs + AR71XX_DDR_REG_RD_CYCLE);
|
||||
udelay(100);
|
||||
|
||||
/* Burst size */
|
||||
writel(DDR_BURST_VAL, regs + QCA953X_DDR_REG_BURST);
|
||||
udelay(100);
|
||||
writel(DDR_BURST2_VAL, regs + QCA953X_DDR_REG_BURST2);
|
||||
udelay(100);
|
||||
|
||||
/* AHB maximum timeout */
|
||||
writel(0xfffff, regs + QCA953X_DDR_REG_TIMEOUT_MAX);
|
||||
udelay(100);
|
||||
|
||||
/* DRAM timing */
|
||||
writel(DDR2_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG);
|
||||
udelay(100);
|
||||
writel(DDR2_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2);
|
||||
udelay(100);
|
||||
writel(DDR2_CONF3_REG_VAL, regs + QCA953X_DDR_REG_CONFIG3);
|
||||
udelay(100);
|
||||
|
||||
/* Enable DDR2 */
|
||||
writel(DDR2_CONF_VAL, regs + QCA953X_DDR_REG_DDR2_CONFIG);
|
||||
udelay(100);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register 2 Set (EMR2S) */
|
||||
writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register 3 Set (EMR3S) */
|
||||
writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* 150 ohm, Reduced strength, Enable DLL */
|
||||
writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Reset DLL, CAS Latency 4, Burst Length 8 */
|
||||
writel(DDR2_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
udelay(100);
|
||||
|
||||
/* Update Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Precharge All */
|
||||
writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Auto Refresh */
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Normal DLL, CAS Latency 4, Burst Length 8 */
|
||||
writel(DDR2_MODE_VAL, regs + AR71XX_DDR_REG_MODE);
|
||||
udelay(100);
|
||||
|
||||
/* Mode Register Set (MRS) */
|
||||
writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Enable OCD, Enable DLL, Reduced Drive Strength */
|
||||
writel(DDR2_EXT_MODE_OCD_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* OCD diable, Enable DLL, Reduced Drive Strength */
|
||||
writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR);
|
||||
udelay(100);
|
||||
|
||||
/* Update Extended Mode Register Set (EMRS) */
|
||||
writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
/* Refresh time control */
|
||||
writel(DDR_REFRESH_VAL, regs + AR71XX_DDR_REG_REFRESH);
|
||||
udelay(100);
|
||||
|
||||
/* DQS 0 Tap Control */
|
||||
writel(DDR2_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
|
||||
/* DQS 1 Tap Control */
|
||||
writel(DDR2_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
}
|
||||
}
|
||||
|
||||
void ddr_tap_tuning(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val, pass, tap, cnt, tap_val, last, first;
|
||||
|
||||
regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
tap_val = readl(regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
first = DDR_TAP_MAGIC_VAL;
|
||||
last = 0;
|
||||
cnt = 0;
|
||||
tap = 0;
|
||||
|
||||
do {
|
||||
writel(tap, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
writel(tap, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
|
||||
writel(DDR_BIST_COMP_CNT(8), regs + DDR_REG_BIST_COMP_ADDR_1);
|
||||
writel(DDR_BIST_MASK_ADDR_VAL, regs + DDR_REG_BIST_MASK_ADDR_0);
|
||||
writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE0_1);
|
||||
writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE1_0);
|
||||
writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE1_1);
|
||||
writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE0_0);
|
||||
writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE0_1);
|
||||
writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE1_0);
|
||||
writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE1_1);
|
||||
writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE0_0);
|
||||
|
||||
/* Start BIST test */
|
||||
writel(DDR_BIST_TEST_START, regs + DDR_REG_BIST);
|
||||
|
||||
do {
|
||||
val = readl(regs + DDR_REG_BIST_STATUS);
|
||||
} while (!(val & DDR_BIST_STATUS_DONE));
|
||||
|
||||
/* Stop BIST test */
|
||||
writel(0, regs + DDR_REG_BIST);
|
||||
|
||||
pass = val & DDR_BIST_COMP_CNT_MASK;
|
||||
pass ^= DDR_BIST_COMP_CNT(8);
|
||||
if (!pass) {
|
||||
if (first != DDR_TAP_MAGIC_VAL) {
|
||||
last = tap;
|
||||
} else {
|
||||
first = tap;
|
||||
last = tap;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
tap++;
|
||||
} while (tap < DDR_TAP_MAX_VAL);
|
||||
|
||||
if (cnt) {
|
||||
tap_val = (first + last) / 2;
|
||||
tap_val %= DDR_TAP_MAX_VAL;
|
||||
}
|
||||
|
||||
writel(tap_val, regs + AR71XX_DDR_REG_TAP_CTRL0);
|
||||
writel(tap_val, regs + AR71XX_DDR_REG_TAP_CTRL1);
|
||||
}
|
186
arch/mips/mach-ath79/qca953x/lowlevel_init.S
Normal file
186
arch/mips/mach-ath79/qca953x/lowlevel_init.S
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
* Based on Atheros LSDK/QSDK
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
|
||||
#define MK_PLL_CONF(divint, refdiv, range, outdiv) \
|
||||
(((0x3F & divint) << 10) | \
|
||||
((0x1F & refdiv) << 16) | \
|
||||
((0x1 & range) << 21) | \
|
||||
((0x7 & outdiv) << 23) )
|
||||
|
||||
#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \
|
||||
(((0x3 & (cpudiv - 1)) << 5) | \
|
||||
((0x3 & (ddrdiv - 1)) << 10) | \
|
||||
((0x3 & (ahbdiv - 1)) << 15) )
|
||||
|
||||
#define SET_FIELD(name, v) (((v) & QCA953X_##name##_MASK) << \
|
||||
QCA953X_##name##_SHIFT)
|
||||
|
||||
#define DPLL2_KI(v) SET_FIELD(SRIF_DPLL2_KI, v)
|
||||
#define DPLL2_KD(v) SET_FIELD(SRIF_DPLL2_KD, v)
|
||||
#define DPLL2_PWD QCA953X_SRIF_DPLL2_PWD
|
||||
#define MK_DPLL2(ki, kd) (DPLL2_KI(ki) | DPLL2_KD(kd) | DPLL2_PWD)
|
||||
|
||||
#define PLL_CPU_NFRAC(v) SET_FIELD(PLL_CPU_CONFIG_NFRAC, v)
|
||||
#define PLL_CPU_NINT(v) SET_FIELD(PLL_CPU_CONFIG_NINT, v)
|
||||
#define PLL_CPU_REFDIV(v) SET_FIELD(PLL_CPU_CONFIG_REFDIV, v)
|
||||
#define PLL_CPU_OUTDIV(v) SET_FIELD(PLL_CPU_CONFIG_OUTDIV, v)
|
||||
#define MK_PLL_CPU_CONF(frac, nint, ref, outdiv) \
|
||||
(PLL_CPU_NFRAC(frac) | \
|
||||
PLL_CPU_NINT(nint) | \
|
||||
PLL_CPU_REFDIV(ref) | \
|
||||
PLL_CPU_OUTDIV(outdiv))
|
||||
|
||||
#define PLL_DDR_NFRAC(v) SET_FIELD(PLL_DDR_CONFIG_NFRAC, v)
|
||||
#define PLL_DDR_NINT(v) SET_FIELD(PLL_DDR_CONFIG_NINT, v)
|
||||
#define PLL_DDR_REFDIV(v) SET_FIELD(PLL_DDR_CONFIG_REFDIV, v)
|
||||
#define PLL_DDR_OUTDIV(v) SET_FIELD(PLL_DDR_CONFIG_OUTDIV, v)
|
||||
#define MK_PLL_DDR_CONF(frac, nint, ref, outdiv) \
|
||||
(PLL_DDR_NFRAC(frac) | \
|
||||
PLL_DDR_REFDIV(ref) | \
|
||||
PLL_DDR_NINT(nint) | \
|
||||
PLL_DDR_OUTDIV(outdiv) | \
|
||||
QCA953X_PLL_CONFIG_PWD)
|
||||
|
||||
#define PLL_CPU_CONF_VAL MK_PLL_CPU_CONF(0, 26, 1, 0)
|
||||
#define PLL_DDR_CONF_VAL MK_PLL_DDR_CONF(0, 15, 1, 0)
|
||||
|
||||
#define PLL_CLK_CTRL_PLL_BYPASS (QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS | \
|
||||
QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS | \
|
||||
QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
|
||||
|
||||
#define PLL_CLK_CTRL_CPU_DIV(v) SET_FIELD(PLL_CLK_CTRL_CPU_POST_DIV, v)
|
||||
#define PLL_CLK_CTRL_DDR_DIV(v) SET_FIELD(PLL_CLK_CTRL_DDR_POST_DIV, v)
|
||||
#define PLL_CLK_CTRL_AHB_DIV(v) SET_FIELD(PLL_CLK_CTRL_AHB_POST_DIV, v)
|
||||
#define MK_PLL_CLK_CTRL(cpu, ddr, ahb) \
|
||||
(PLL_CLK_CTRL_CPU_DIV(cpu) | \
|
||||
PLL_CLK_CTRL_DDR_DIV(ddr) | \
|
||||
PLL_CLK_CTRL_AHB_DIV(ahb))
|
||||
#define PLL_CLK_CTRL_VAL (MK_PLL_CLK_CTRL(0, 0, 2) | \
|
||||
PLL_CLK_CTRL_PLL_BYPASS | \
|
||||
QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL | \
|
||||
QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
|
||||
|
||||
#define PLL_DDR_DIT_FRAC_MAX(v) SET_FIELD(PLL_DDR_DIT_FRAC_MAX, v)
|
||||
#define PLL_DDR_DIT_FRAC_MIN(v) SET_FIELD(PLL_DDR_DIT_FRAC_MIN, v)
|
||||
#define PLL_DDR_DIT_FRAC_STEP(v) SET_FIELD(PLL_DDR_DIT_FRAC_STEP, v)
|
||||
#define PLL_DDR_DIT_UPD_CNT(v) SET_FIELD(PLL_DDR_DIT_UPD_CNT, v)
|
||||
#define PLL_CPU_DIT_FRAC_MAX(v) SET_FIELD(PLL_CPU_DIT_FRAC_MAX, v)
|
||||
#define PLL_CPU_DIT_FRAC_MIN(v) SET_FIELD(PLL_CPU_DIT_FRAC_MIN, v)
|
||||
#define PLL_CPU_DIT_FRAC_STEP(v) SET_FIELD(PLL_CPU_DIT_FRAC_STEP, v)
|
||||
#define PLL_CPU_DIT_UPD_CNT(v) SET_FIELD(PLL_CPU_DIT_UPD_CNT, v)
|
||||
#define MK_PLL_DDR_DIT_FRAC(max, min, step, cnt) \
|
||||
(QCA953X_PLL_DIT_FRAC_EN | \
|
||||
PLL_DDR_DIT_FRAC_MAX(max) | \
|
||||
PLL_DDR_DIT_FRAC_MIN(min) | \
|
||||
PLL_DDR_DIT_FRAC_STEP(step) | \
|
||||
PLL_DDR_DIT_UPD_CNT(cnt))
|
||||
#define MK_PLL_CPU_DIT_FRAC(max, min, step, cnt) \
|
||||
(QCA953X_PLL_DIT_FRAC_EN | \
|
||||
PLL_CPU_DIT_FRAC_MAX(max) | \
|
||||
PLL_CPU_DIT_FRAC_MIN(min) | \
|
||||
PLL_CPU_DIT_FRAC_STEP(step) | \
|
||||
PLL_CPU_DIT_UPD_CNT(cnt))
|
||||
#define PLL_CPU_DIT_FRAC_VAL MK_PLL_CPU_DIT_FRAC(63, 0, 1, 15)
|
||||
#define PLL_DDR_DIT_FRAC_VAL MK_PLL_DDR_DIT_FRAC(763, 635, 1, 15)
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
|
||||
LEAF(lowlevel_init)
|
||||
/* RTC Reset */
|
||||
li t0, CKSEG1ADDR(AR71XX_RESET_BASE)
|
||||
lw t1, QCA953X_RESET_REG_RESET_MODULE(t0)
|
||||
li t2, 0x08000000
|
||||
or t1, t1, t2
|
||||
sw t1, QCA953X_RESET_REG_RESET_MODULE(t0)
|
||||
nop
|
||||
lw t1, QCA953X_RESET_REG_RESET_MODULE(t0)
|
||||
li t2, 0xf7ffffff
|
||||
and t1, t1, t2
|
||||
sw t1, QCA953X_RESET_REG_RESET_MODULE(t0)
|
||||
nop
|
||||
|
||||
/* RTC Force Wake */
|
||||
li t0, CKSEG1ADDR(QCA953X_RTC_BASE)
|
||||
li t1, 0x01
|
||||
sw t1, QCA953X_RTC_REG_SYNC_RESET(t0)
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Wait for RTC in on state */
|
||||
1:
|
||||
lw t1, QCA953X_RTC_REG_SYNC_STATUS(t0)
|
||||
andi t1, t1, 0x02
|
||||
beqz t1, 1b
|
||||
nop
|
||||
|
||||
li t0, CKSEG1ADDR(QCA953X_SRIF_BASE)
|
||||
li t1, MK_DPLL2(2, 16)
|
||||
sw t1, QCA953X_SRIF_BB_DPLL2_REG(t0)
|
||||
sw t1, QCA953X_SRIF_PCIE_DPLL2_REG(t0)
|
||||
sw t1, QCA953X_SRIF_DDR_DPLL2_REG(t0)
|
||||
sw t1, QCA953X_SRIF_CPU_DPLL2_REG(t0)
|
||||
|
||||
li t0, CKSEG1ADDR(AR71XX_PLL_BASE)
|
||||
lw t1, QCA953X_PLL_CLK_CTRL_REG(t0)
|
||||
ori t1, PLL_CLK_CTRL_PLL_BYPASS
|
||||
sw t1, QCA953X_PLL_CLK_CTRL_REG(t0)
|
||||
nop
|
||||
|
||||
li t1, PLL_CPU_CONF_VAL
|
||||
sw t1, QCA953X_PLL_CPU_CONFIG_REG(t0)
|
||||
nop
|
||||
|
||||
li t1, PLL_DDR_CONF_VAL
|
||||
sw t1, QCA953X_PLL_DDR_CONFIG_REG(t0)
|
||||
nop
|
||||
|
||||
li t1, PLL_CLK_CTRL_VAL
|
||||
sw t1, QCA953X_PLL_CLK_CTRL_REG(t0)
|
||||
nop
|
||||
|
||||
lw t1, QCA953X_PLL_CPU_CONFIG_REG(t0)
|
||||
li t2, ~QCA953X_PLL_CONFIG_PWD
|
||||
and t1, t1, t2
|
||||
sw t1, QCA953X_PLL_CPU_CONFIG_REG(t0)
|
||||
nop
|
||||
|
||||
lw t1, QCA953X_PLL_DDR_CONFIG_REG(t0)
|
||||
li t2, ~QCA953X_PLL_CONFIG_PWD
|
||||
and t1, t1, t2
|
||||
sw t1, QCA953X_PLL_DDR_CONFIG_REG(t0)
|
||||
nop
|
||||
|
||||
lw t1, QCA953X_PLL_CLK_CTRL_REG(t0)
|
||||
li t2, ~PLL_CLK_CTRL_PLL_BYPASS
|
||||
and t1, t1, t2
|
||||
sw t1, QCA953X_PLL_CLK_CTRL_REG(t0)
|
||||
nop
|
||||
|
||||
li t1, PLL_DDR_DIT_FRAC_VAL
|
||||
sw t1, QCA953X_PLL_DDR_DIT_FRAC_REG(t0)
|
||||
nop
|
||||
|
||||
li t1, PLL_CPU_DIT_FRAC_VAL
|
||||
sw t1, QCA953X_PLL_CPU_DIT_FRAC_REG(t0)
|
||||
nop
|
||||
|
||||
li t0, CKSEG1ADDR(AR71XX_RESET_BASE)
|
||||
lui t1, 0x03fc
|
||||
sw t1, 0xb4(t0)
|
||||
|
||||
nop
|
||||
jr ra
|
||||
nop
|
||||
END(lowlevel_init)
|
208
arch/mips/mach-ath79/reset.c
Normal file
208
arch/mips/mach-ath79/reset.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ath79.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
|
||||
void _machine_restart(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
u32 reg = 0;
|
||||
|
||||
base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
if (soc_is_ar71xx())
|
||||
reg = AR71XX_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_ar724x())
|
||||
reg = AR724X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_ar913x())
|
||||
reg = AR913X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_ar933x())
|
||||
reg = AR933X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_ar934x())
|
||||
reg = AR934X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_qca953x())
|
||||
reg = QCA953X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_qca955x())
|
||||
reg = QCA955X_RESET_REG_RESET_MODULE;
|
||||
else if (soc_is_qca956x())
|
||||
reg = QCA956X_RESET_REG_RESET_MODULE;
|
||||
else
|
||||
puts("Reset register not defined for this SOC\n");
|
||||
|
||||
if (reg)
|
||||
setbits_be32(base + reg, AR71XX_RESET_FULL_CHIP);
|
||||
|
||||
while (1)
|
||||
/* NOP */;
|
||||
}
|
||||
|
||||
u32 get_bootstrap(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
u32 reg = 0;
|
||||
|
||||
base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
if (soc_is_ar933x())
|
||||
reg = AR933X_RESET_REG_BOOTSTRAP;
|
||||
else if (soc_is_ar934x())
|
||||
reg = AR934X_RESET_REG_BOOTSTRAP;
|
||||
else if (soc_is_qca953x())
|
||||
reg = QCA953X_RESET_REG_BOOTSTRAP;
|
||||
else if (soc_is_qca955x())
|
||||
reg = QCA955X_RESET_REG_BOOTSTRAP;
|
||||
else if (soc_is_qca956x())
|
||||
reg = QCA956X_RESET_REG_BOOTSTRAP;
|
||||
else
|
||||
puts("Bootstrap register not defined for this SOC\n");
|
||||
|
||||
if (reg)
|
||||
return readl(base + reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eth_init_ar933x(void)
|
||||
{
|
||||
void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
void __iomem *gregs = map_physmem(AR933X_GMAC_BASE, AR933X_GMAC_SIZE,
|
||||
MAP_NOCACHE);
|
||||
const u32 mask = AR933X_RESET_GE0_MAC | AR933X_RESET_GE0_MDIO |
|
||||
AR933X_RESET_GE1_MAC | AR933X_RESET_GE1_MDIO |
|
||||
AR933X_RESET_ETH_SWITCH;
|
||||
|
||||
/* Clear MDIO slave EN bit. */
|
||||
clrbits_be32(rregs + AR933X_RESET_REG_BOOTSTRAP, BIT(17));
|
||||
mdelay(10);
|
||||
|
||||
/* Get Atheros S26 PHY out of reset. */
|
||||
clrsetbits_be32(pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG,
|
||||
0x1f, 0x10);
|
||||
mdelay(10);
|
||||
|
||||
setbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask);
|
||||
mdelay(10);
|
||||
clrbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask);
|
||||
mdelay(10);
|
||||
|
||||
/* Configure AR93xx GMAC register. */
|
||||
clrsetbits_be32(gregs + AR933X_GMAC_REG_ETH_CFG,
|
||||
AR933X_ETH_CFG_MII_GE0_MASTER |
|
||||
AR933X_ETH_CFG_MII_GE0_SLAVE,
|
||||
AR933X_ETH_CFG_MII_GE0_SLAVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eth_init_ar934x(void)
|
||||
{
|
||||
void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
void __iomem *gregs = map_physmem(AR934X_GMAC_BASE, AR934X_GMAC_SIZE,
|
||||
MAP_NOCACHE);
|
||||
const u32 mask = AR934X_RESET_GE0_MAC | AR934X_RESET_GE0_MDIO |
|
||||
AR934X_RESET_GE1_MAC | AR934X_RESET_GE1_MDIO |
|
||||
AR934X_RESET_ETH_SWITCH_ANALOG;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(rregs + AR934X_RESET_REG_BOOTSTRAP);
|
||||
if (reg & AR934X_BOOTSTRAP_REF_CLK_40)
|
||||
writel(0x570, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
|
||||
else
|
||||
writel(0x271, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
|
||||
writel(BIT(26) | BIT(25), pregs + AR934X_PLL_ETH_XMII_CONTROL_REG);
|
||||
|
||||
setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
|
||||
mdelay(1);
|
||||
clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
|
||||
mdelay(1);
|
||||
|
||||
/* Configure AR934x GMAC register. */
|
||||
writel(AR934X_ETH_CFG_RGMII_GMAC0, gregs + AR934X_GMAC_REG_ETH_CFG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath79_eth_reset(void)
|
||||
{
|
||||
/*
|
||||
* Un-reset ethernet. DM still doesn't have any notion of reset
|
||||
* framework, so we do it by hand here.
|
||||
*/
|
||||
if (soc_is_ar933x())
|
||||
return eth_init_ar933x();
|
||||
if (soc_is_ar934x())
|
||||
return eth_init_ar934x();
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int usb_reset_ar933x(void __iomem *reset_regs)
|
||||
{
|
||||
/* Ungate the USB block */
|
||||
setbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE,
|
||||
AR933X_RESET_USBSUS_OVERRIDE);
|
||||
mdelay(1);
|
||||
clrbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE,
|
||||
AR933X_RESET_USB_HOST);
|
||||
mdelay(1);
|
||||
clrbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE,
|
||||
AR933X_RESET_USB_PHY);
|
||||
mdelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_reset_ar934x(void __iomem *reset_regs)
|
||||
{
|
||||
/* Ungate the USB block */
|
||||
setbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE,
|
||||
AR934X_RESET_USBSUS_OVERRIDE);
|
||||
mdelay(1);
|
||||
clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE,
|
||||
AR934X_RESET_USB_PHY);
|
||||
mdelay(1);
|
||||
clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE,
|
||||
AR934X_RESET_USB_PHY_ANALOG);
|
||||
mdelay(1);
|
||||
clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE,
|
||||
AR934X_RESET_USB_HOST);
|
||||
mdelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath79_usb_reset(void)
|
||||
{
|
||||
void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
|
||||
AR71XX_USB_CTRL_SIZE,
|
||||
MAP_NOCACHE);
|
||||
void __iomem *reset_regs = map_physmem(AR71XX_RESET_BASE,
|
||||
AR71XX_RESET_SIZE,
|
||||
MAP_NOCACHE);
|
||||
/*
|
||||
* Turn on the Buff and Desc swap bits.
|
||||
* NOTE: This write into an undocumented register in mandatory to
|
||||
* get the USB controller operational in BigEndian mode.
|
||||
*/
|
||||
writel(0xf0000, usbc_regs + AR71XX_USB_CTRL_REG_CONFIG);
|
||||
|
||||
if (soc_is_ar933x())
|
||||
return usb_reset_ar933x(reset_regs);
|
||||
if (soc_is_ar934x())
|
||||
return usb_reset_ar934x(reset_regs);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
typedef struct fsl_i2c {
|
||||
typedef struct fsl_i2c_base {
|
||||
|
||||
u8 adr; /* I2C slave address */
|
||||
u8 res0[3];
|
||||
@ -68,4 +68,14 @@ typedef struct fsl_i2c {
|
||||
u8 res6[0xE8];
|
||||
} fsl_i2c_t;
|
||||
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct fsl_i2c_dev {
|
||||
struct fsl_i2c_base __iomem *base; /* register base */
|
||||
u32 i2c_clk;
|
||||
u32 index;
|
||||
u8 slaveadd;
|
||||
uint speed;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_I2C_H_ */
|
||||
|
@ -120,8 +120,8 @@ typedef struct ccsr_local_ecm {
|
||||
|
||||
/* I2C Registers */
|
||||
typedef struct ccsr_i2c {
|
||||
struct fsl_i2c i2c[1];
|
||||
u8 res[4096 - 1 * sizeof(struct fsl_i2c)];
|
||||
struct fsl_i2c_base i2c[1];
|
||||
u8 res[4096 - 1 * sizeof(struct fsl_i2c_base)];
|
||||
} ccsr_i2c_t;
|
||||
|
||||
#if defined(CONFIG_MPC8540) \
|
||||
|
@ -92,8 +92,8 @@ typedef struct ccsr_local_mcm {
|
||||
|
||||
/* Daul I2C Registers(0x3000-0x4000) */
|
||||
typedef struct ccsr_i2c {
|
||||
struct fsl_i2c i2c[2];
|
||||
u8 res[4096 - 2 * sizeof(struct fsl_i2c)];
|
||||
struct fsl_i2c_base i2c[2];
|
||||
u8 res[4096 - 2 * sizeof(struct fsl_i2c_base)];
|
||||
} ccsr_i2c_t;
|
||||
|
||||
/* DUART Registers(0x4000-0x5000) */
|
||||
|
@ -56,6 +56,21 @@ void outl(unsigned int value, unsigned int addr);
|
||||
void outw(unsigned int value, unsigned int addr);
|
||||
void outb(unsigned int value, unsigned int addr);
|
||||
|
||||
static inline void _insw(volatile u16 *port, void *buf, int ns)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void _outsw(volatile u16 *port, const void *buf, int ns)
|
||||
{
|
||||
}
|
||||
|
||||
#define insw(port, buf, ns) _insw((u16 *)port, buf, ns)
|
||||
#define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns)
|
||||
|
||||
/* For systemace.c */
|
||||
#define out16(addr, val)
|
||||
#define in16(addr) 0
|
||||
|
||||
#include <iotrace.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
|
@ -47,6 +47,9 @@ source "arch/x86/cpu/queensbay/Kconfig"
|
||||
|
||||
# architecture-specific options below
|
||||
|
||||
config AHCI
|
||||
default y
|
||||
|
||||
config SYS_MALLOC_F_LEN
|
||||
default 0x800
|
||||
|
||||
|
@ -261,7 +261,7 @@ static const struct udevice_id broadwell_ahci_ids[] = {
|
||||
|
||||
U_BOOT_DRIVER(ahci_broadwell_drv) = {
|
||||
.name = "ahci_broadwell",
|
||||
.id = UCLASS_DISK,
|
||||
.id = UCLASS_AHCI,
|
||||
.of_match = broadwell_ahci_ids,
|
||||
.ofdata_to_platdata = broadwell_sata_ofdata_to_platdata,
|
||||
.probe = broadwell_sata_probe,
|
||||
|
@ -58,7 +58,7 @@ int cpu_common_init(void)
|
||||
return -ENODEV;
|
||||
|
||||
/* Cause the SATA device to do its early init */
|
||||
uclass_first_device(UCLASS_DISK, &dev);
|
||||
uclass_first_device(UCLASS_AHCI, &dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ static int bd82x6x_probe(struct udevice *dev)
|
||||
return 0;
|
||||
|
||||
/* Cause the SATA device to do its init */
|
||||
uclass_first_device(UCLASS_DISK, &dev);
|
||||
uclass_first_device(UCLASS_AHCI, &dev);
|
||||
|
||||
ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev);
|
||||
if (ret)
|
||||
|
@ -233,7 +233,7 @@ static const struct udevice_id bd82x6x_ahci_ids[] = {
|
||||
|
||||
U_BOOT_DRIVER(ahci_ivybridge_drv) = {
|
||||
.name = "ahci_ivybridge",
|
||||
.id = UCLASS_DISK,
|
||||
.id = UCLASS_AHCI,
|
||||
.of_match = bd82x6x_ahci_ids,
|
||||
.probe = bd82x6x_sata_probe,
|
||||
};
|
||||
|
@ -105,7 +105,7 @@ static int load_rescue_image(ulong addr)
|
||||
|
||||
/* Detect storage device */
|
||||
for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
|
||||
if (stor_dev->type != DEV_TYPE_UNKNOWN)
|
||||
break;
|
||||
}
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <eeprom_layout.h>
|
||||
#include <eeprom_field.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "eeprom.h"
|
||||
|
||||
#ifndef CONFIG_SYS_I2C_EEPROM_ADDR
|
||||
@ -181,3 +184,344 @@ int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus)
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
/**
|
||||
* eeprom_field_print_bin_ver() - print a "version field" which contains binary
|
||||
* data
|
||||
*
|
||||
* Treat the field data as simple binary data, and print it formatted as a
|
||||
* version number (2 digits after decimal point).
|
||||
* The field size must be exactly 2 bytes.
|
||||
*
|
||||
* Sample output:
|
||||
* Field Name 123.45
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_bin_ver(const struct eeprom_field *field)
|
||||
{
|
||||
if ((field->buf[0] == 0xff) && (field->buf[1] == 0xff)) {
|
||||
field->buf[0] = 0;
|
||||
field->buf[1] = 0;
|
||||
}
|
||||
|
||||
printf(PRINT_FIELD_SEGMENT, field->name);
|
||||
int major = (field->buf[1] << 8 | field->buf[0]) / 100;
|
||||
int minor = (field->buf[1] << 8 | field->buf[0]) - major * 100;
|
||||
printf("%d.%02d\n", major, minor);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_bin_ver() - update a "version field" which contains
|
||||
* binary data
|
||||
*
|
||||
* This function takes a version string in the form of x.y (x and y are both
|
||||
* decimal values, y is limited to two digits), translates it to the binary
|
||||
* form, then writes it to the field. The field size must be exactly 2 bytes.
|
||||
*
|
||||
* This function strictly enforces the data syntax, and will not update the
|
||||
* field if there's any deviation from it. It also protects from overflow.
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a version string
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int eeprom_field_update_bin_ver(struct eeprom_field *field, char *value)
|
||||
{
|
||||
char *endptr;
|
||||
char *tok = strtok(value, ".");
|
||||
if (tok == NULL)
|
||||
return -1;
|
||||
|
||||
int num = simple_strtol(tok, &endptr, 0);
|
||||
if (*endptr != '\0')
|
||||
return -1;
|
||||
|
||||
tok = strtok(NULL, "");
|
||||
if (tok == NULL)
|
||||
return -1;
|
||||
|
||||
int remainder = simple_strtol(tok, &endptr, 0);
|
||||
if (*endptr != '\0')
|
||||
return -1;
|
||||
|
||||
num = num * 100 + remainder;
|
||||
if (num >> 16)
|
||||
return -1;
|
||||
|
||||
field->buf[0] = (unsigned char)num;
|
||||
field->buf[1] = num >> 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
/**
|
||||
* eeprom_field_print_date() - print a field which contains date data
|
||||
*
|
||||
* Treat the field data as simple binary data, and print it formatted as a date.
|
||||
* Sample output:
|
||||
* Field Name 07/Feb/2014
|
||||
* Field Name 56/BAD/9999
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_date(const struct eeprom_field *field)
|
||||
{
|
||||
printf(PRINT_FIELD_SEGMENT, field->name);
|
||||
printf("%02d/", field->buf[0]);
|
||||
if (field->buf[1] >= 1 && field->buf[1] <= 12)
|
||||
printf("%s", months[field->buf[1] - 1]);
|
||||
else
|
||||
printf("BAD");
|
||||
|
||||
printf("/%d\n", field->buf[3] << 8 | field->buf[2]);
|
||||
}
|
||||
|
||||
static int validate_date(unsigned char day, unsigned char month,
|
||||
unsigned int year)
|
||||
{
|
||||
int days_in_february;
|
||||
|
||||
switch (month) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
if (day > 31)
|
||||
return -1;
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 8:
|
||||
case 10:
|
||||
if (day > 30)
|
||||
return -1;
|
||||
break;
|
||||
case 1:
|
||||
days_in_february = 28;
|
||||
if (year % 4 == 0) {
|
||||
if (year % 100 != 0)
|
||||
days_in_february = 29;
|
||||
else if (year % 400 == 0)
|
||||
days_in_february = 29;
|
||||
}
|
||||
|
||||
if (day > days_in_february)
|
||||
return -1;
|
||||
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_date() - update a date field which contains binary data
|
||||
*
|
||||
* This function takes a date string in the form of x/Mon/y (x and y are both
|
||||
* decimal values), translates it to the binary representation, then writes it
|
||||
* to the field.
|
||||
*
|
||||
* This function strictly enforces the data syntax, and will not update the
|
||||
* field if there's any deviation from it. It also protects from overflow in the
|
||||
* year value, and checks the validity of the date.
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a date string
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int eeprom_field_update_date(struct eeprom_field *field, char *value)
|
||||
{
|
||||
char *endptr;
|
||||
char *tok1 = strtok(value, "/");
|
||||
char *tok2 = strtok(NULL, "/");
|
||||
char *tok3 = strtok(NULL, "/");
|
||||
|
||||
if (tok1 == NULL || tok2 == NULL || tok3 == NULL) {
|
||||
printf("%s: syntax error\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char day = (unsigned char)simple_strtol(tok1, &endptr, 0);
|
||||
if (*endptr != '\0' || day == 0) {
|
||||
printf("%s: invalid day\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char month;
|
||||
for (month = 1; month <= 12; month++)
|
||||
if (!strcmp(tok2, months[month - 1]))
|
||||
break;
|
||||
|
||||
unsigned int year = simple_strtol(tok3, &endptr, 0);
|
||||
if (*endptr != '\0') {
|
||||
printf("%s: invalid year\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (validate_date(day, month - 1, year)) {
|
||||
printf("%s: invalid date\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (year >> 16) {
|
||||
printf("%s: year overflow\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
field->buf[0] = day;
|
||||
field->buf[1] = month;
|
||||
field->buf[2] = (unsigned char)year;
|
||||
field->buf[3] = (unsigned char)(year >> 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LAYOUT_VERSION_LEGACY 1
|
||||
#define LAYOUT_VERSION_VER1 2
|
||||
#define LAYOUT_VERSION_VER2 3
|
||||
#define LAYOUT_VERSION_VER3 4
|
||||
|
||||
extern struct eeprom_field layout_unknown[1];
|
||||
|
||||
#define DEFINE_PRINT_UPDATE(x) eeprom_field_print_##x, eeprom_field_update_##x
|
||||
|
||||
#ifdef CONFIG_CM_T3X
|
||||
struct eeprom_field layout_legacy[5] = {
|
||||
{ "MAC address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Board Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin) },
|
||||
{ "Serial Number", 8, NULL, DEFINE_PRINT_UPDATE(bin) },
|
||||
{ "Board Configuration", 64, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ RESERVED_FIELDS, 176, NULL, eeprom_field_print_reserved,
|
||||
eeprom_field_update_ascii },
|
||||
};
|
||||
#else
|
||||
#define layout_legacy layout_unknown
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CM_T3X) || defined(CONFIG_CM_T3517)
|
||||
struct eeprom_field layout_v1[12] = {
|
||||
{ "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
|
||||
{ "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
|
||||
{ RESERVED_FIELDS, 96, NULL, DEFINE_PRINT_UPDATE(reserved) },
|
||||
{ "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
|
||||
eeprom_field_update_ascii },
|
||||
};
|
||||
#else
|
||||
#define layout_v1 layout_unknown
|
||||
#endif
|
||||
|
||||
struct eeprom_field layout_v2[15] = {
|
||||
{ "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
|
||||
{ "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
|
||||
{ "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) },
|
||||
{ RESERVED_FIELDS, 83, NULL, DEFINE_PRINT_UPDATE(reserved) },
|
||||
{ "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
|
||||
eeprom_field_update_ascii },
|
||||
};
|
||||
|
||||
struct eeprom_field layout_v3[16] = {
|
||||
{ "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
|
||||
{ "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
|
||||
{ "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
|
||||
{ "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
|
||||
{ "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) },
|
||||
{ "CompuLab EEPROM ID", 3, NULL, DEFINE_PRINT_UPDATE(bin) },
|
||||
{ RESERVED_FIELDS, 80, NULL, DEFINE_PRINT_UPDATE(reserved) },
|
||||
{ "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
|
||||
{ RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
|
||||
eeprom_field_update_ascii },
|
||||
};
|
||||
|
||||
void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version)
|
||||
{
|
||||
switch (layout->layout_version) {
|
||||
case LAYOUT_VERSION_LEGACY:
|
||||
layout->fields = layout_legacy;
|
||||
layout->num_of_fields = ARRAY_SIZE(layout_legacy);
|
||||
break;
|
||||
case LAYOUT_VERSION_VER1:
|
||||
layout->fields = layout_v1;
|
||||
layout->num_of_fields = ARRAY_SIZE(layout_v1);
|
||||
break;
|
||||
case LAYOUT_VERSION_VER2:
|
||||
layout->fields = layout_v2;
|
||||
layout->num_of_fields = ARRAY_SIZE(layout_v2);
|
||||
break;
|
||||
case LAYOUT_VERSION_VER3:
|
||||
layout->fields = layout_v3;
|
||||
layout->num_of_fields = ARRAY_SIZE(layout_v3);
|
||||
break;
|
||||
default:
|
||||
__eeprom_layout_assign(layout, layout_version);
|
||||
}
|
||||
}
|
||||
|
||||
int eeprom_parse_layout_version(char *str)
|
||||
{
|
||||
if (!strcmp(str, "legacy"))
|
||||
return LAYOUT_VERSION_LEGACY;
|
||||
else if (!strcmp(str, "v1"))
|
||||
return LAYOUT_VERSION_VER1;
|
||||
else if (!strcmp(str, "v2"))
|
||||
return LAYOUT_VERSION_VER2;
|
||||
else if (!strcmp(str, "v3"))
|
||||
return LAYOUT_VERSION_VER3;
|
||||
else
|
||||
return LAYOUT_VERSION_UNRECOGNIZED;
|
||||
}
|
||||
|
||||
int eeprom_layout_detect(unsigned char *data)
|
||||
{
|
||||
switch (data[EEPROM_LAYOUT_VER_OFFSET]) {
|
||||
case 0xff:
|
||||
case 0:
|
||||
return LAYOUT_VERSION_VER1;
|
||||
case 2:
|
||||
return LAYOUT_VERSION_VER2;
|
||||
case 3:
|
||||
return LAYOUT_VERSION_VER3;
|
||||
}
|
||||
|
||||
if (data[EEPROM_LAYOUT_VER_OFFSET] >= 0x20)
|
||||
return LAYOUT_VERSION_LEGACY;
|
||||
|
||||
return LAYOUT_VERSION_UNRECOGNIZED;
|
||||
}
|
||||
#endif
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.set mips32
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
@ -13,31 +13,33 @@
|
||||
|
||||
static void i2c_write_start_seq(void)
|
||||
{
|
||||
struct fsl_i2c *dev;
|
||||
dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
|
||||
struct fsl_i2c_base *base;
|
||||
base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
|
||||
CONFIG_SYS_I2C_OFFSET);
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
|
||||
out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
out_8(&dev->cr, (I2C_CR_MEN));
|
||||
out_8(&base->cr, (I2C_CR_MEN));
|
||||
}
|
||||
|
||||
int i2c_make_abort(void)
|
||||
{
|
||||
struct fsl_i2c *dev;
|
||||
dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
|
||||
struct fsl_i2c_base *base;
|
||||
base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
|
||||
CONFIG_SYS_I2C_OFFSET);
|
||||
uchar last;
|
||||
int nbr_read = 0;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* wait after each operation to finsh with a delay */
|
||||
out_8(&dev->cr, (I2C_CR_MSTA));
|
||||
out_8(&base->cr, (I2C_CR_MSTA));
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
|
||||
out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
in_8(&dev->dr);
|
||||
in_8(&base->dr);
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
last = in_8(&dev->dr);
|
||||
last = in_8(&base->dr);
|
||||
nbr_read++;
|
||||
|
||||
/*
|
||||
@ -47,7 +49,7 @@ int i2c_make_abort(void)
|
||||
while (((last & 0x01) != 0x01) &&
|
||||
(nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) {
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
last = in_8(&dev->dr);
|
||||
last = in_8(&base->dr);
|
||||
nbr_read++;
|
||||
}
|
||||
if ((last & 0x01) != 0x01)
|
||||
@ -56,10 +58,10 @@ int i2c_make_abort(void)
|
||||
printf("[INFO] i2c abort after %d bytes (0x%02x)\n",
|
||||
nbr_read, last);
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
out_8(&dev->cr, (I2C_CR_MEN));
|
||||
out_8(&base->cr, (I2C_CR_MEN));
|
||||
udelay(DELAY_ABORT_SEQ);
|
||||
/* clear status reg */
|
||||
out_8(&dev->sr, 0);
|
||||
out_8(&base->sr, 0);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
i2c_write_start_seq();
|
||||
|
@ -32,8 +32,8 @@ Changed files:
|
||||
- include/cmd_bsp.h added PIP405 commands definitions
|
||||
- include/cmd_condefs.h added Floppy and SCSI support
|
||||
- include/cmd_disk.h changed to work with block device description
|
||||
- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI
|
||||
- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI
|
||||
- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_SCSI
|
||||
- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_SCSI
|
||||
- include/flash.h added INTEL_ID_28F320C3T 0x88C488C4
|
||||
- include/i2c.h added "defined(CONFIG_PIP405)"
|
||||
- include/image.h added IH_OS_U_BOOT, IH_TYPE_FIRMWARE
|
||||
@ -86,7 +86,7 @@ section "Changes".
|
||||
|
||||
New Commands:
|
||||
-------------
|
||||
CONFIG_CMD_SCSI SCSI Support
|
||||
CONFIG_SCSI SCSI Support
|
||||
CONFIG_CMF_FDC Floppy disk support
|
||||
|
||||
IDE additions:
|
||||
|
12
board/qca/ap121/Kconfig
Normal file
12
board/qca/ap121/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
if TARGET_AP121
|
||||
|
||||
config SYS_VENDOR
|
||||
default "qca"
|
||||
|
||||
config SYS_BOARD
|
||||
default "ap121"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "ap121"
|
||||
|
||||
endif
|
6
board/qca/ap121/MAINTAINERS
Normal file
6
board/qca/ap121/MAINTAINERS
Normal file
@ -0,0 +1,6 @@
|
||||
AP121 BOARD
|
||||
M: Wills Wang <wills.wang@live.com>
|
||||
S: Maintained
|
||||
F: board/qca/ap121/
|
||||
F: include/configs/ap121.h
|
||||
F: configs/ap121_defconfig
|
5
board/qca/ap121/Makefile
Normal file
5
board/qca/ap121/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y = ap121.o
|
50
board/qca/ap121/ap121.c
Normal file
50
board/qca/ap121/ap121.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/ddr.h>
|
||||
#include <debug_uart.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val;
|
||||
|
||||
regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
/*
|
||||
* GPIO9 as input, GPIO10 as output
|
||||
*/
|
||||
val = readl(regs + AR71XX_GPIO_REG_OE);
|
||||
val &= ~AR933X_GPIO(9);
|
||||
val |= AR933X_GPIO(10);
|
||||
writel(val, regs + AR71XX_GPIO_REG_OE);
|
||||
|
||||
/*
|
||||
* Enable UART, GPIO9 as UART_SI, GPIO10 as UART_SO
|
||||
*/
|
||||
val = readl(regs + AR71XX_GPIO_REG_FUNC);
|
||||
val |= AR933X_GPIO_FUNC_UART_EN | AR933X_GPIO_FUNC_RES_TRUE;
|
||||
writel(val, regs + AR71XX_GPIO_REG_FUNC);
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
debug_uart_init();
|
||||
#endif
|
||||
ddr_init();
|
||||
return 0;
|
||||
}
|
12
board/qca/ap143/Kconfig
Normal file
12
board/qca/ap143/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
if TARGET_AP143
|
||||
|
||||
config SYS_VENDOR
|
||||
default "qca"
|
||||
|
||||
config SYS_BOARD
|
||||
default "ap143"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "ap143"
|
||||
|
||||
endif
|
6
board/qca/ap143/MAINTAINERS
Normal file
6
board/qca/ap143/MAINTAINERS
Normal file
@ -0,0 +1,6 @@
|
||||
AP143 BOARD
|
||||
M: Wills Wang <wills.wang@live.com>
|
||||
S: Maintained
|
||||
F: board/qca/ap143/
|
||||
F: include/configs/ap143.h
|
||||
F: configs/ap143_defconfig
|
5
board/qca/ap143/Makefile
Normal file
5
board/qca/ap143/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y = ap143.o
|
66
board/qca/ap143/ap143.c
Normal file
66
board/qca/ap143/ap143.c
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/ddr.h>
|
||||
#include <debug_uart.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
u32 val;
|
||||
|
||||
regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
/*
|
||||
* GPIO9 as input, GPIO10 as output
|
||||
*/
|
||||
val = readl(regs + AR71XX_GPIO_REG_OE);
|
||||
val |= QCA953X_GPIO(9);
|
||||
val &= ~QCA953X_GPIO(10);
|
||||
writel(val, regs + AR71XX_GPIO_REG_OE);
|
||||
|
||||
/*
|
||||
* Enable GPIO10 as UART0_SOUT
|
||||
*/
|
||||
val = readl(regs + QCA953X_GPIO_REG_OUT_FUNC2);
|
||||
val &= ~QCA953X_GPIO_MUX_MASK(16);
|
||||
val |= QCA953X_GPIO_OUT_MUX_UART0_SOUT << 16;
|
||||
writel(val, regs + QCA953X_GPIO_REG_OUT_FUNC2);
|
||||
|
||||
/*
|
||||
* Enable GPIO9 as UART0_SIN
|
||||
*/
|
||||
val = readl(regs + QCA953X_GPIO_REG_IN_ENABLE0);
|
||||
val &= ~QCA953X_GPIO_MUX_MASK(8);
|
||||
val |= QCA953X_GPIO_IN_MUX_UART0_SIN << 8;
|
||||
writel(val, regs + QCA953X_GPIO_REG_IN_ENABLE0);
|
||||
|
||||
/*
|
||||
* Enable GPIO10 output
|
||||
*/
|
||||
val = readl(regs + AR71XX_GPIO_REG_OUT);
|
||||
val |= QCA953X_GPIO(10);
|
||||
writel(val, regs + AR71XX_GPIO_REG_OUT);
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
debug_uart_init();
|
||||
#endif
|
||||
ddr_init();
|
||||
return 0;
|
||||
}
|
@ -4,3 +4,10 @@ S: Maintained
|
||||
F: board/sandbox/
|
||||
F: include/configs/sandbox.h
|
||||
F: configs/sandbox_defconfig
|
||||
|
||||
SANDBOX_NOBLK BOARD
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: board/sandbox/
|
||||
F: include/configs/sandbox.h
|
||||
F: configs/sandbox_noblk_defconfig
|
||||
|
15
board/tplink/wdr4300/Kconfig
Normal file
15
board/tplink/wdr4300/Kconfig
Normal file
@ -0,0 +1,15 @@
|
||||
if BOARD_TPLINK_WDR4300
|
||||
|
||||
config SYS_VENDOR
|
||||
default "tplink"
|
||||
|
||||
config SYS_SOC
|
||||
default "ath79"
|
||||
|
||||
config SYS_BOARD
|
||||
default "wdr4300"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "tplink_wdr4300"
|
||||
|
||||
endif
|
6
board/tplink/wdr4300/MAINTAINERS
Normal file
6
board/tplink/wdr4300/MAINTAINERS
Normal file
@ -0,0 +1,6 @@
|
||||
TPLINK_WDR4300 BOARD
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
S: Maintained
|
||||
F: board/tplink/wdr4300/
|
||||
F: include/configs/tplink_wdr4300.h
|
||||
F: configs/tplink_wdr4300_defconfig
|
5
board/tplink/wdr4300/Makefile
Normal file
5
board/tplink/wdr4300/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y = wdr4300.o
|
74
board/tplink/wdr4300/wdr4300.c
Normal file
74
board/tplink/wdr4300/wdr4300.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include <mach/ath79.h>
|
||||
#include <mach/ar71xx_regs.h>
|
||||
#include <mach/ddr.h>
|
||||
#include <debug_uart.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_USB
|
||||
static void wdr4300_usb_start(void)
|
||||
{
|
||||
void __iomem *gpio_regs = map_physmem(AR71XX_GPIO_BASE,
|
||||
AR71XX_GPIO_SIZE, MAP_NOCACHE);
|
||||
if (!gpio_regs)
|
||||
return;
|
||||
|
||||
/* Power up the USB HUB. */
|
||||
clrbits_be32(gpio_regs + AR71XX_GPIO_REG_OE, BIT(21) | BIT(22));
|
||||
writel(BIT(21) | BIT(22), gpio_regs + AR71XX_GPIO_REG_SET);
|
||||
mdelay(1);
|
||||
|
||||
ath79_usb_reset();
|
||||
}
|
||||
#else
|
||||
static inline void wdr4300_usb_start(void) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOARD_EARLY_INIT_F
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
void __iomem *regs;
|
||||
|
||||
regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
|
||||
MAP_NOCACHE);
|
||||
|
||||
/* Assure JTAG is not disconnected. */
|
||||
writel(0x40, regs + AR934X_GPIO_REG_FUNC);
|
||||
|
||||
/* Configure default GPIO input/output regs. */
|
||||
writel(0x3031b, regs + AR71XX_GPIO_REG_OE);
|
||||
writel(0x0f804, regs + AR71XX_GPIO_REG_OUT);
|
||||
|
||||
/* Configure pin multiplexing. */
|
||||
writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC0);
|
||||
writel(0x0b0a0980, regs + AR934X_GPIO_REG_OUT_FUNC1);
|
||||
writel(0x00180000, regs + AR934X_GPIO_REG_OUT_FUNC2);
|
||||
writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC3);
|
||||
writel(0x0000004d, regs + AR934X_GPIO_REG_OUT_FUNC4);
|
||||
writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC5);
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
debug_uart_init();
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
ar934x_pll_init(560, 480, 240);
|
||||
ar934x_ddr_init(560, 480, 240);
|
||||
#endif
|
||||
|
||||
wdr4300_usb_start();
|
||||
ath79_eth_reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
@ -112,7 +112,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
|
||||
obj-$(CONFIG_SANDBOX) += host.o
|
||||
obj-$(CONFIG_CMD_SATA) += sata.o
|
||||
obj-$(CONFIG_CMD_SF) += sf.o
|
||||
obj-$(CONFIG_CMD_SCSI) += scsi.o
|
||||
obj-$(CONFIG_SCSI) += scsi.o
|
||||
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
|
||||
obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
|
||||
obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o
|
||||
@ -155,12 +155,6 @@ obj-$(CONFIG_CMD_PMIC) += pmic.o
|
||||
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
|
||||
endif # !CONFIG_SPL_BUILD
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
ifdef CONFIG_SPL_SATA_SUPPORT
|
||||
obj-$(CONFIG_CMD_SCSI) += scsi.o
|
||||
endif
|
||||
endif # CONFIG_SPL_BUILD
|
||||
|
||||
obj-$(CONFIG_CMD_BLOB) += blob.o
|
||||
|
||||
# core command
|
||||
|
@ -341,6 +341,8 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
print_eth(0);
|
||||
printf("ip_addr = %s\n", getenv("ipaddr"));
|
||||
printf("baudrate = %u bps\n", gd->baudrate);
|
||||
print_num("relocaddr", gd->relocaddr);
|
||||
print_num("reloc off", gd->reloc_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <command.h>
|
||||
#include <part.h>
|
||||
|
||||
#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \
|
||||
#if defined(CONFIG_CMD_IDE) || defined(CONFIG_SCSI) || \
|
||||
defined(CONFIG_USB_STORAGE)
|
||||
int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
|
||||
char *const argv[])
|
||||
|
267
cmd/eeprom.c
267
cmd/eeprom.c
@ -24,6 +24,7 @@
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <i2c.h>
|
||||
#include <eeprom_layout.h>
|
||||
|
||||
#ifndef CONFIG_SYS_I2C_SPEED
|
||||
#define CONFIG_SYS_I2C_SPEED 50000
|
||||
@ -72,7 +73,7 @@ void eeprom_init(int bus)
|
||||
#endif
|
||||
|
||||
/* I2C EEPROM */
|
||||
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT)
|
||||
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
|
||||
#if defined(CONFIG_SYS_I2C)
|
||||
if (bus >= 0)
|
||||
i2c_set_bus_num(bus);
|
||||
@ -207,63 +208,243 @@ int eeprom_write(unsigned dev_addr, unsigned offset,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
static int parse_numeric_param(char *str)
|
||||
{
|
||||
const char *const fmt =
|
||||
"\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... ";
|
||||
char * const *args = &argv[2];
|
||||
int rcode;
|
||||
ulong dev_addr, addr, off, cnt;
|
||||
int bus_addr;
|
||||
char *endptr;
|
||||
int value = simple_strtol(str, &endptr, 16);
|
||||
|
||||
return (*endptr != '\0') ? -1 : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters
|
||||
*
|
||||
* @i2c_bus: address to store the i2c bus
|
||||
* @i2c_addr: address to store the device i2c address
|
||||
* @argc: count of command line arguments left to parse
|
||||
* @argv: command line arguments left to parse
|
||||
* @argc_no_bus_addr: argc value we expect to see when bus & addr aren't given
|
||||
*
|
||||
* @returns: number of arguments parsed or CMD_RET_USAGE if error
|
||||
*/
|
||||
static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
|
||||
char * const argv[], int argc_no_bus_addr)
|
||||
{
|
||||
int argc_no_bus = argc_no_bus_addr + 1;
|
||||
int argc_bus_addr = argc_no_bus_addr + 2;
|
||||
|
||||
switch (argc) {
|
||||
#ifdef CONFIG_SYS_DEF_EEPROM_ADDR
|
||||
case 5:
|
||||
bus_addr = -1;
|
||||
dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
|
||||
break;
|
||||
if (argc == argc_no_bus_addr) {
|
||||
*i2c_bus = -1;
|
||||
*i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
case 6:
|
||||
bus_addr = -1;
|
||||
dev_addr = simple_strtoul(*args++, NULL, 16);
|
||||
break;
|
||||
case 7:
|
||||
bus_addr = simple_strtoul(*args++, NULL, 16);
|
||||
dev_addr = simple_strtoul(*args++, NULL, 16);
|
||||
break;
|
||||
default:
|
||||
return CMD_RET_USAGE;
|
||||
if (argc == argc_no_bus) {
|
||||
*i2c_bus = -1;
|
||||
*i2c_addr = parse_numeric_param(argv[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr = simple_strtoul(*args++, NULL, 16);
|
||||
off = simple_strtoul(*args++, NULL, 16);
|
||||
cnt = simple_strtoul(*args++, NULL, 16);
|
||||
if (argc == argc_bus_addr) {
|
||||
*i2c_bus = parse_numeric_param(argv[0]);
|
||||
*i2c_addr = parse_numeric_param(argv[1]);
|
||||
|
||||
eeprom_init(bus_addr);
|
||||
|
||||
if (strcmp(argv[1], "read") == 0) {
|
||||
printf(fmt, dev_addr, argv[1], addr, off, cnt);
|
||||
|
||||
rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt);
|
||||
|
||||
puts("done\n");
|
||||
return rcode;
|
||||
} else if (strcmp(argv[1], "write") == 0) {
|
||||
printf(fmt, dev_addr, argv[1], addr, off, cnt);
|
||||
|
||||
rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt);
|
||||
|
||||
puts("done\n");
|
||||
return rcode;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
|
||||
__weak int eeprom_parse_layout_version(char *str)
|
||||
{
|
||||
return LAYOUT_VERSION_UNRECOGNIZED;
|
||||
}
|
||||
|
||||
static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
|
||||
|
||||
#ifndef CONFIG_EEPROM_LAYOUT_HELP_STRING
|
||||
#define CONFIG_EEPROM_LAYOUT_HELP_STRING "<not defined>"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
enum eeprom_action {
|
||||
EEPROM_READ,
|
||||
EEPROM_WRITE,
|
||||
EEPROM_PRINT,
|
||||
EEPROM_UPDATE,
|
||||
EEPROM_ACTION_INVALID,
|
||||
};
|
||||
|
||||
static enum eeprom_action parse_action(char *cmd)
|
||||
{
|
||||
if (!strncmp(cmd, "read", 4))
|
||||
return EEPROM_READ;
|
||||
if (!strncmp(cmd, "write", 5))
|
||||
return EEPROM_WRITE;
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
if (!strncmp(cmd, "print", 5))
|
||||
return EEPROM_PRINT;
|
||||
if (!strncmp(cmd, "update", 6))
|
||||
return EEPROM_UPDATE;
|
||||
#endif
|
||||
|
||||
return EEPROM_ACTION_INVALID;
|
||||
}
|
||||
|
||||
static int eeprom_execute_command(enum eeprom_action action, int i2c_bus,
|
||||
ulong i2c_addr, int layout_ver, char *key,
|
||||
char *value, ulong addr, ulong off, ulong cnt)
|
||||
{
|
||||
int rcode = 0;
|
||||
const char *const fmt =
|
||||
"\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... ";
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
struct eeprom_layout layout;
|
||||
#endif
|
||||
|
||||
if (action == EEPROM_ACTION_INVALID)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
eeprom_init(i2c_bus);
|
||||
if (action == EEPROM_READ) {
|
||||
printf(fmt, i2c_addr, "read", addr, off, cnt);
|
||||
|
||||
rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt);
|
||||
|
||||
puts("done\n");
|
||||
return rcode;
|
||||
} else if (action == EEPROM_WRITE) {
|
||||
printf(fmt, i2c_addr, "write", addr, off, cnt);
|
||||
|
||||
rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt);
|
||||
|
||||
puts("done\n");
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
|
||||
if (rcode < 0)
|
||||
return rcode;
|
||||
|
||||
eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
|
||||
layout_ver);
|
||||
|
||||
if (action == EEPROM_PRINT) {
|
||||
layout.print(&layout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
layout.update(&layout, key, value);
|
||||
|
||||
rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE);
|
||||
#endif
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#define NEXT_PARAM(argc, index) { (argc)--; (index)++; }
|
||||
int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int layout_ver = LAYOUT_VERSION_AUTODETECT;
|
||||
enum eeprom_action action = EEPROM_ACTION_INVALID;
|
||||
int i2c_bus = -1, index = 0;
|
||||
ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0;
|
||||
int ret;
|
||||
char *field_name = "";
|
||||
char *field_value = "";
|
||||
|
||||
if (argc <= 1)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
NEXT_PARAM(argc, index); /* Skip program name */
|
||||
|
||||
action = parse_action(argv[index]);
|
||||
NEXT_PARAM(argc, index);
|
||||
|
||||
if (action == EEPROM_ACTION_INVALID)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
if (action == EEPROM_PRINT || action == EEPROM_UPDATE) {
|
||||
if (!strcmp(argv[index], "-l")) {
|
||||
NEXT_PARAM(argc, index);
|
||||
layout_ver = eeprom_parse_layout_version(argv[index]);
|
||||
NEXT_PARAM(argc, index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (action) {
|
||||
case EEPROM_READ:
|
||||
case EEPROM_WRITE:
|
||||
ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
|
||||
argv + index, 3);
|
||||
break;
|
||||
case EEPROM_PRINT:
|
||||
ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
|
||||
argv + index, 0);
|
||||
break;
|
||||
case EEPROM_UPDATE:
|
||||
ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
|
||||
argv + index, 2);
|
||||
break;
|
||||
default:
|
||||
/* Get compiler to stop whining */
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (ret == CMD_RET_USAGE)
|
||||
return ret;
|
||||
|
||||
while (ret--)
|
||||
NEXT_PARAM(argc, index);
|
||||
|
||||
if (action == EEPROM_READ || action == EEPROM_WRITE) {
|
||||
addr = parse_numeric_param(argv[index]);
|
||||
NEXT_PARAM(argc, index);
|
||||
off = parse_numeric_param(argv[index]);
|
||||
NEXT_PARAM(argc, index);
|
||||
cnt = parse_numeric_param(argv[index]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
if (action == EEPROM_UPDATE) {
|
||||
field_name = argv[index];
|
||||
NEXT_PARAM(argc, index);
|
||||
field_value = argv[index];
|
||||
NEXT_PARAM(argc, index);
|
||||
}
|
||||
#endif
|
||||
|
||||
return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver,
|
||||
field_name, field_value, addr, off, cnt);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
eeprom, 7, 1, do_eeprom,
|
||||
eeprom, 8, 1, do_eeprom,
|
||||
"EEPROM sub-system",
|
||||
"read <bus> <devaddr> addr off cnt\n"
|
||||
"eeprom write <bus> <devaddr> addr off cnt\n"
|
||||
" - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
|
||||
#ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
"\n"
|
||||
"eeprom print [-l <layout_version>] <bus> <devaddr>\n"
|
||||
" - Print layout fields and their data in human readable format\n"
|
||||
"eeprom update [-l <layout_version>] <bus> <devaddr> field_name field_value\n"
|
||||
" - Update a specific eeprom field with new data.\n"
|
||||
" The new data must be written in the same human readable format as shown by the print command.\n"
|
||||
"\n"
|
||||
"LAYOUT VERSIONS\n"
|
||||
"The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n"
|
||||
"If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n"
|
||||
"The values which can be provided with the -l option are:\n"
|
||||
CONFIG_EEPROM_LAYOUT_HELP_STRING"\n"
|
||||
#endif
|
||||
)
|
||||
|
18
cmd/mmc.c
18
cmd/mmc.c
@ -314,12 +314,14 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
|
||||
}
|
||||
/* Switch to the RPMB partition */
|
||||
original_part = mmc->block_dev.hwpart;
|
||||
if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0)
|
||||
if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
|
||||
0)
|
||||
return CMD_RET_FAILURE;
|
||||
ret = cp->cmd(cmdtp, flag, argc, argv);
|
||||
|
||||
/* Return to original partition */
|
||||
if (mmc_select_hwpart(curr_device, original_part) != 0)
|
||||
if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
|
||||
0)
|
||||
return CMD_RET_FAILURE;
|
||||
return ret;
|
||||
}
|
||||
@ -346,7 +348,7 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
|
||||
printf("\nMMC read: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
|
||||
n = blk_dread(&mmc->block_dev, blk, cnt, addr);
|
||||
n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
|
||||
/* flush cache after read */
|
||||
flush_cache((ulong)addr, cnt * 512); /* FIXME */
|
||||
printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
@ -378,7 +380,7 @@ static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
|
||||
printf("Error: card is write protected!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
n = blk_dwrite(&mmc->block_dev, blk, cnt, addr);
|
||||
n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
|
||||
printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
||||
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
|
||||
@ -406,7 +408,7 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
|
||||
printf("Error: card is write protected!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
n = blk_derase(&mmc->block_dev, blk, cnt);
|
||||
n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
|
||||
printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
||||
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
|
||||
@ -432,7 +434,7 @@ static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
mmc_dev = mmc_get_dev(curr_device);
|
||||
mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
|
||||
if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
part_print(mmc_dev);
|
||||
return CMD_RET_SUCCESS;
|
||||
@ -467,7 +469,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
ret = mmc_select_hwpart(dev, part);
|
||||
ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
|
||||
printf("switch to partitions #%d, %s\n",
|
||||
part, (!ret) ? "OK" : "ERROR");
|
||||
if (ret)
|
||||
@ -478,7 +480,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
|
||||
printf("mmc%d is current device\n", curr_device);
|
||||
else
|
||||
printf("mmc%d(part %d) is current device\n",
|
||||
curr_device, mmc->block_dev.hwpart);
|
||||
curr_device, mmc_get_blk_desc(mmc)->hwpart);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
142
cmd/sata.c
142
cmd/sata.c
@ -16,70 +16,6 @@
|
||||
#include <sata.h>
|
||||
|
||||
static int sata_curr_device = -1;
|
||||
struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
|
||||
|
||||
static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *dst)
|
||||
{
|
||||
return sata_read(block_dev->devnum, start, blkcnt, dst);
|
||||
}
|
||||
|
||||
static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
return sata_write(block_dev->devnum, start, blkcnt, buffer);
|
||||
}
|
||||
|
||||
int __sata_initialize(void)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
|
||||
memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
|
||||
sata_dev_desc[i].if_type = IF_TYPE_SATA;
|
||||
sata_dev_desc[i].devnum = i;
|
||||
sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
|
||||
sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
|
||||
sata_dev_desc[i].lba = 0;
|
||||
sata_dev_desc[i].blksz = 512;
|
||||
sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
|
||||
sata_dev_desc[i].block_read = sata_bread;
|
||||
sata_dev_desc[i].block_write = sata_bwrite;
|
||||
|
||||
rc = init_sata(i);
|
||||
if (!rc) {
|
||||
rc = scan_sata(i);
|
||||
if (!rc && (sata_dev_desc[i].lba > 0) &&
|
||||
(sata_dev_desc[i].blksz > 0))
|
||||
part_init(&sata_dev_desc[i]);
|
||||
}
|
||||
}
|
||||
sata_curr_device = 0;
|
||||
return rc;
|
||||
}
|
||||
int sata_initialize(void) __attribute__((weak,alias("__sata_initialize")));
|
||||
|
||||
__weak int __sata_stop(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
|
||||
err |= reset_sata(i);
|
||||
|
||||
if (err)
|
||||
printf("Could not reset some SATA devices\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
|
||||
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
struct blk_desc *sata_get_dev(int dev)
|
||||
{
|
||||
return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
@ -105,69 +41,40 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
case 1:
|
||||
return CMD_RET_USAGE;
|
||||
case 2:
|
||||
if (strncmp(argv[1],"inf", 3) == 0) {
|
||||
int i;
|
||||
putc('\n');
|
||||
for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) {
|
||||
if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN)
|
||||
continue;
|
||||
printf ("SATA device %d: ", i);
|
||||
dev_print(&sata_dev_desc[i]);
|
||||
if (strncmp(argv[1], "inf", 3) == 0) {
|
||||
blk_list_devices(IF_TYPE_SATA);
|
||||
return 0;
|
||||
} else if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
if (blk_print_device_num(IF_TYPE_SATA,
|
||||
sata_curr_device)) {
|
||||
printf("\nno SATA devices available\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
} else if (strncmp(argv[1],"dev", 3) == 0) {
|
||||
if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) {
|
||||
} else if (strncmp(argv[1], "part", 4) == 0) {
|
||||
if (blk_list_part(IF_TYPE_SATA))
|
||||
puts("\nno SATA devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf("\nSATA device %d: ", sata_curr_device);
|
||||
dev_print(&sata_dev_desc[sata_curr_device]);
|
||||
return 0;
|
||||
} else if (strncmp(argv[1],"part",4) == 0) {
|
||||
int dev, ok;
|
||||
|
||||
for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) {
|
||||
if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
|
||||
++ok;
|
||||
if (dev)
|
||||
putc ('\n');
|
||||
part_print(&sata_dev_desc[dev]);
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
puts("\nno SATA devices available\n");
|
||||
rc ++;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
return CMD_RET_USAGE;
|
||||
case 3:
|
||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
printf("\nSATA device %d: ", dev);
|
||||
if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
|
||||
puts ("unknown device\n");
|
||||
return 1;
|
||||
if (!blk_show_device(IF_TYPE_SATA, dev)) {
|
||||
sata_curr_device = dev;
|
||||
printf("... is now current device\n");
|
||||
} else {
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
dev_print(&sata_dev_desc[dev]);
|
||||
|
||||
if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
|
||||
sata_curr_device = dev;
|
||||
|
||||
puts("... is now current device\n");
|
||||
|
||||
return 0;
|
||||
} else if (strncmp(argv[1], "part", 4) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
|
||||
part_print(&sata_dev_desc[dev]);
|
||||
} else {
|
||||
printf("\nSATA device %d not available\n", dev);
|
||||
rc = 1;
|
||||
if (blk_print_part_devnum(IF_TYPE_SATA, dev)) {
|
||||
printf("\nSATA device %d not available\n",
|
||||
dev);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -183,11 +90,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
printf("\nSATA read: device %d block # %ld, count %ld ... ",
|
||||
sata_curr_device, blk, cnt);
|
||||
|
||||
n = blk_dread(&sata_dev_desc[sata_curr_device],
|
||||
blk, cnt, (u32 *)addr);
|
||||
|
||||
/* flush cache after read */
|
||||
flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz);
|
||||
n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk,
|
||||
cnt, (ulong *)addr);
|
||||
|
||||
printf("%ld blocks read: %s\n",
|
||||
n, (n==cnt) ? "OK" : "ERROR");
|
||||
@ -202,8 +106,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
printf("\nSATA write: device %d block # %ld, count %ld ... ",
|
||||
sata_curr_device, blk, cnt);
|
||||
|
||||
n = blk_dwrite(&sata_dev_desc[sata_curr_device],
|
||||
blk, cnt, (u32 *)addr);
|
||||
n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device,
|
||||
blk, cnt, (ulong *)addr);
|
||||
|
||||
printf("%ld blocks written: %s\n",
|
||||
n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
753
cmd/scsi.c
753
cmd/scsi.c
@ -10,361 +10,108 @@
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <inttypes.h>
|
||||
#include <asm/processor.h>
|
||||
#include <scsi.h>
|
||||
#include <image.h>
|
||||
#include <pci.h>
|
||||
|
||||
#ifdef CONFIG_SCSI_DEV_LIST
|
||||
#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
|
||||
#else
|
||||
#ifdef CONFIG_SCSI_SYM53C8XX
|
||||
#define SCSI_VEND_ID 0x1000
|
||||
#ifndef CONFIG_SCSI_DEV_ID
|
||||
#define SCSI_DEV_ID 0x0001
|
||||
#else
|
||||
#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID
|
||||
#endif
|
||||
#elif defined CONFIG_SATA_ULI5288
|
||||
|
||||
#define SCSI_VEND_ID 0x10b9
|
||||
#define SCSI_DEV_ID 0x5288
|
||||
|
||||
#elif !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
#error no scsi device defined
|
||||
#endif
|
||||
#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
|
||||
#endif
|
||||
static ccb tempccb; /* temporary scsi command buffer */
|
||||
|
||||
static unsigned char tempbuff[512]; /* temporary data buffer */
|
||||
|
||||
static int scsi_max_devs; /* number of highest available scsi device */
|
||||
|
||||
static int scsi_curr_dev; /* current device */
|
||||
|
||||
static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
|
||||
|
||||
/********************************************************************************
|
||||
* forward declerations of some Setup Routines
|
||||
*/
|
||||
void scsi_setup_test_unit_ready(ccb * pccb);
|
||||
void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks);
|
||||
void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks);
|
||||
void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks);
|
||||
|
||||
static void scsi_setup_write_ext(ccb *pccb, lbaint_t start,
|
||||
unsigned short blocks);
|
||||
void scsi_setup_inquiry(ccb * pccb);
|
||||
void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
|
||||
|
||||
|
||||
static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity,
|
||||
unsigned long *blksz);
|
||||
static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, void *buffer);
|
||||
static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, const void *buffer);
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
* (re)-scan the scsi bus and reports scsi device info
|
||||
* to the user if mode = 1
|
||||
*/
|
||||
void scsi_scan(int mode)
|
||||
{
|
||||
unsigned char i,perq,modi,lun;
|
||||
lbaint_t capacity;
|
||||
unsigned long blksz;
|
||||
ccb* pccb=(ccb *)&tempccb;
|
||||
|
||||
if(mode==1) {
|
||||
printf("scanning bus for devices...\n");
|
||||
}
|
||||
for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) {
|
||||
scsi_dev_desc[i].target=0xff;
|
||||
scsi_dev_desc[i].lun=0xff;
|
||||
scsi_dev_desc[i].lba=0;
|
||||
scsi_dev_desc[i].blksz=0;
|
||||
scsi_dev_desc[i].log2blksz =
|
||||
LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz));
|
||||
scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN;
|
||||
scsi_dev_desc[i].vendor[0]=0;
|
||||
scsi_dev_desc[i].product[0]=0;
|
||||
scsi_dev_desc[i].revision[0]=0;
|
||||
scsi_dev_desc[i].removable = false;
|
||||
scsi_dev_desc[i].if_type=IF_TYPE_SCSI;
|
||||
scsi_dev_desc[i].devnum = i;
|
||||
scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
|
||||
scsi_dev_desc[i].block_read=scsi_read;
|
||||
scsi_dev_desc[i].block_write = scsi_write;
|
||||
}
|
||||
scsi_max_devs=0;
|
||||
for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) {
|
||||
pccb->target=i;
|
||||
for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) {
|
||||
pccb->lun=lun;
|
||||
pccb->pdata=(unsigned char *)&tempbuff;
|
||||
pccb->datalen=512;
|
||||
scsi_setup_inquiry(pccb);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
if(pccb->contr_stat==SCSI_SEL_TIME_OUT) {
|
||||
debug ("Selection timeout ID %d\n",pccb->target);
|
||||
continue; /* selection timeout => assuming no device present */
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
perq=tempbuff[0];
|
||||
modi=tempbuff[1];
|
||||
if((perq & 0x1f)==0x1f) {
|
||||
continue; /* skip unknown devices */
|
||||
}
|
||||
if((modi&0x80)==0x80) /* drive is removable */
|
||||
scsi_dev_desc[scsi_max_devs].removable=true;
|
||||
/* get info for this device */
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0],
|
||||
&tempbuff[8], 8);
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0],
|
||||
&tempbuff[16], 16);
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0],
|
||||
&tempbuff[32], 4);
|
||||
scsi_dev_desc[scsi_max_devs].target=pccb->target;
|
||||
scsi_dev_desc[scsi_max_devs].lun=pccb->lun;
|
||||
|
||||
pccb->datalen=0;
|
||||
scsi_setup_test_unit_ready(pccb);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
if (scsi_dev_desc[scsi_max_devs].removable == true) {
|
||||
scsi_dev_desc[scsi_max_devs].type=perq;
|
||||
goto removable;
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
if (scsi_read_capacity(pccb, &capacity, &blksz)) {
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
scsi_dev_desc[scsi_max_devs].lba=capacity;
|
||||
scsi_dev_desc[scsi_max_devs].blksz=blksz;
|
||||
scsi_dev_desc[scsi_max_devs].log2blksz =
|
||||
LOG2(scsi_dev_desc[scsi_max_devs].blksz);
|
||||
scsi_dev_desc[scsi_max_devs].type=perq;
|
||||
part_init(&scsi_dev_desc[scsi_max_devs]);
|
||||
removable:
|
||||
if(mode==1) {
|
||||
printf (" Device %d: ", scsi_max_devs);
|
||||
dev_print(&scsi_dev_desc[scsi_max_devs]);
|
||||
} /* if mode */
|
||||
scsi_max_devs++;
|
||||
} /* next LUN */
|
||||
}
|
||||
if(scsi_max_devs>0)
|
||||
scsi_curr_dev=0;
|
||||
else
|
||||
scsi_curr_dev = -1;
|
||||
|
||||
printf("Found %d device(s).\n", scsi_max_devs);
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
setenv_ulong("scsidevs", scsi_max_devs);
|
||||
#endif
|
||||
}
|
||||
|
||||
int scsi_get_disk_count(void)
|
||||
{
|
||||
return scsi_max_devs;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
void scsi_init(void)
|
||||
{
|
||||
int busdevfunc = -1;
|
||||
int i;
|
||||
/*
|
||||
* Find a device from the list, this driver will support a single
|
||||
* controller.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
|
||||
/* get PCI Device ID */
|
||||
#ifdef CONFIG_DM_PCI
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = dm_pci_find_device(scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device, 0, &dev);
|
||||
if (!ret) {
|
||||
busdevfunc = dm_pci_get_bdf(dev);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
busdevfunc = pci_find_device(scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device,
|
||||
0);
|
||||
#endif
|
||||
if (busdevfunc != -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (busdevfunc == -1) {
|
||||
printf("Error: SCSI Controller(s) ");
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
|
||||
printf("%04X:%04X ",
|
||||
scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device);
|
||||
}
|
||||
printf("not found\n");
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
|
||||
scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device,
|
||||
(busdevfunc >> 16) & 0xFF,
|
||||
(busdevfunc >> 11) & 0x1F,
|
||||
(busdevfunc >> 8) & 0x7);
|
||||
}
|
||||
#endif
|
||||
bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
|
||||
scsi_low_level_init(busdevfunc);
|
||||
scsi_scan(1);
|
||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
struct blk_desc *scsi_get_dev(int dev)
|
||||
{
|
||||
return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
/******************************************************************************
|
||||
/*
|
||||
* scsi boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
return common_diskboot(cmdtp, "scsi", argc, argv);
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
/*
|
||||
* scsi command intepreter
|
||||
*/
|
||||
int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
switch (argc) {
|
||||
case 0:
|
||||
case 1:
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
case 2:
|
||||
if (strncmp(argv[1],"res",3) == 0) {
|
||||
printf("\nReset SCSI\n");
|
||||
scsi_bus_reset();
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
if (strncmp(argv[1], "res", 3) == 0) {
|
||||
printf("\nReset SCSI\n");
|
||||
scsi_bus_reset();
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "inf", 3) == 0) {
|
||||
blk_list_devices(IF_TYPE_SCSI);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) {
|
||||
printf("\nno SCSI devices available\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
if (strncmp(argv[1],"inf",3) == 0) {
|
||||
int i;
|
||||
for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) {
|
||||
if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN)
|
||||
continue; /* list only known devices */
|
||||
printf ("SCSI dev. %d: ", i);
|
||||
dev_print(&scsi_dev_desc[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"dev",3) == 0) {
|
||||
if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) {
|
||||
printf("\nno SCSI devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\n Device %d: ", scsi_curr_dev);
|
||||
dev_print(&scsi_dev_desc[scsi_curr_dev]);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"scan",4) == 0) {
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"part",4) == 0) {
|
||||
int dev, ok;
|
||||
for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) {
|
||||
if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
if (dev)
|
||||
printf("\n");
|
||||
debug ("print_part of %x\n",dev);
|
||||
part_print(&scsi_dev_desc[dev]);
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
printf("\nno SCSI devices available\n");
|
||||
return 1;
|
||||
}
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "scan", 4) == 0) {
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "part", 4) == 0) {
|
||||
if (blk_list_part(IF_TYPE_SCSI))
|
||||
printf("\nno SCSI devices available\n");
|
||||
return 0;
|
||||
}
|
||||
return CMD_RET_USAGE;
|
||||
case 3:
|
||||
if (strncmp(argv[1],"dev",3) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
printf ("\nSCSI device %d: ", dev);
|
||||
if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) {
|
||||
printf("unknown device\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\n Device %d: ", dev);
|
||||
dev_print(&scsi_dev_desc[dev]);
|
||||
if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
|
||||
return 1;
|
||||
}
|
||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
if (!blk_show_device(IF_TYPE_SCSI, dev)) {
|
||||
scsi_curr_dev = dev;
|
||||
printf("... is now current device\n");
|
||||
return 0;
|
||||
} else {
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
if (strncmp(argv[1],"part",4) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) {
|
||||
part_print(&scsi_dev_desc[dev]);
|
||||
}
|
||||
else {
|
||||
printf ("\nSCSI device %d not available\n", dev);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return CMD_RET_USAGE;
|
||||
default:
|
||||
/* at least 4 args */
|
||||
if (strcmp(argv[1],"read") == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong blk = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
ulong n;
|
||||
printf ("\nSCSI read: device %d block # %ld, count %ld ... ",
|
||||
scsi_curr_dev, blk, cnt);
|
||||
n = scsi_read(&scsi_dev_desc[scsi_curr_dev],
|
||||
blk, cnt, (ulong *)addr);
|
||||
printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "write") == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong blk = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
ulong n;
|
||||
printf("\nSCSI write: device %d block # %ld, "
|
||||
"count %ld ... ",
|
||||
scsi_curr_dev, blk, cnt);
|
||||
n = scsi_write(&scsi_dev_desc[scsi_curr_dev],
|
||||
blk, cnt, (ulong *)addr);
|
||||
printf("%ld blocks written: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "part", 4) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) {
|
||||
printf("\nSCSI device %d not available\n",
|
||||
dev);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return CMD_RET_USAGE;
|
||||
default:
|
||||
/* at least 4 args */
|
||||
if (strcmp(argv[1], "read") == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong blk = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
ulong n;
|
||||
|
||||
printf("\nSCSI read: device %d block # %ld, count %ld ... ",
|
||||
scsi_curr_dev, blk, cnt);
|
||||
n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
|
||||
cnt, (ulong *)addr);
|
||||
printf("%ld blocks read: %s\n", n,
|
||||
n == cnt ? "OK" : "ERROR");
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "write") == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong blk = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
ulong n;
|
||||
|
||||
printf("\nSCSI write: device %d block # %ld, count %ld ... ",
|
||||
scsi_curr_dev, blk, cnt);
|
||||
n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
|
||||
cnt, (ulong *)addr);
|
||||
printf("%ld blocks written: %s\n", n,
|
||||
n == cnt ? "OK" : "ERROR");
|
||||
return 0;
|
||||
}
|
||||
} /* switch */
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
@ -388,347 +135,3 @@ U_BOOT_CMD(
|
||||
"boot from SCSI device",
|
||||
"loadAddr dev:part"
|
||||
);
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* scsi_read
|
||||
*/
|
||||
|
||||
/* almost the maximum amount of the scsi_ext command.. */
|
||||
#define SCSI_MAX_READ_BLK 0xFFFF
|
||||
#define SCSI_LBA48_READ 0xFFFFFFF
|
||||
|
||||
static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, void *buffer)
|
||||
{
|
||||
int device = block_dev->devnum;
|
||||
lbaint_t start, blks;
|
||||
uintptr_t buf_addr;
|
||||
unsigned short smallblks = 0;
|
||||
ccb* pccb=(ccb *)&tempccb;
|
||||
device&=0xff;
|
||||
/* Setup device
|
||||
*/
|
||||
pccb->target=scsi_dev_desc[device].target;
|
||||
pccb->lun=scsi_dev_desc[device].lun;
|
||||
buf_addr=(unsigned long)buffer;
|
||||
start=blknr;
|
||||
blks=blkcnt;
|
||||
debug("\nscsi_read: dev %d startblk " LBAF
|
||||
", blccnt " LBAF " buffer %lx\n",
|
||||
device, start, blks, (unsigned long)buffer);
|
||||
do {
|
||||
pccb->pdata=(unsigned char *)buf_addr;
|
||||
#ifdef CONFIG_SYS_64BIT_LBA
|
||||
if (start > SCSI_LBA48_READ) {
|
||||
unsigned long blocks;
|
||||
blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
|
||||
pccb->datalen = scsi_dev_desc[device].blksz * blocks;
|
||||
scsi_setup_read16(pccb, start, blocks);
|
||||
start += blocks;
|
||||
blks -= blocks;
|
||||
} else
|
||||
#endif
|
||||
if (blks > SCSI_MAX_READ_BLK) {
|
||||
pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK;
|
||||
smallblks=SCSI_MAX_READ_BLK;
|
||||
scsi_setup_read_ext(pccb,start,smallblks);
|
||||
start+=SCSI_MAX_READ_BLK;
|
||||
blks-=SCSI_MAX_READ_BLK;
|
||||
}
|
||||
else {
|
||||
pccb->datalen=scsi_dev_desc[device].blksz * blks;
|
||||
smallblks=(unsigned short) blks;
|
||||
scsi_setup_read_ext(pccb,start,smallblks);
|
||||
start+=blks;
|
||||
blks=0;
|
||||
}
|
||||
debug("scsi_read_ext: startblk " LBAF
|
||||
", blccnt %x buffer %" PRIXPTR "\n",
|
||||
start, smallblks, buf_addr);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
scsi_print_error(pccb);
|
||||
blkcnt-=blks;
|
||||
break;
|
||||
}
|
||||
buf_addr+=pccb->datalen;
|
||||
} while(blks!=0);
|
||||
debug("scsi_read_ext: end startblk " LBAF
|
||||
", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
|
||||
return(blkcnt);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* scsi_write
|
||||
*/
|
||||
|
||||
/* Almost the maximum amount of the scsi_ext command.. */
|
||||
#define SCSI_MAX_WRITE_BLK 0xFFFF
|
||||
|
||||
static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
int device = block_dev->devnum;
|
||||
lbaint_t start, blks;
|
||||
uintptr_t buf_addr;
|
||||
unsigned short smallblks;
|
||||
ccb* pccb = (ccb *)&tempccb;
|
||||
device &= 0xff;
|
||||
/* Setup device
|
||||
*/
|
||||
pccb->target = scsi_dev_desc[device].target;
|
||||
pccb->lun = scsi_dev_desc[device].lun;
|
||||
buf_addr = (unsigned long)buffer;
|
||||
start = blknr;
|
||||
blks = blkcnt;
|
||||
debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
|
||||
__func__, device, start, blks, (unsigned long)buffer);
|
||||
do {
|
||||
pccb->pdata = (unsigned char *)buf_addr;
|
||||
if (blks > SCSI_MAX_WRITE_BLK) {
|
||||
pccb->datalen = (scsi_dev_desc[device].blksz *
|
||||
SCSI_MAX_WRITE_BLK);
|
||||
smallblks = SCSI_MAX_WRITE_BLK;
|
||||
scsi_setup_write_ext(pccb, start, smallblks);
|
||||
start += SCSI_MAX_WRITE_BLK;
|
||||
blks -= SCSI_MAX_WRITE_BLK;
|
||||
} else {
|
||||
pccb->datalen = scsi_dev_desc[device].blksz * blks;
|
||||
smallblks = (unsigned short)blks;
|
||||
scsi_setup_write_ext(pccb, start, smallblks);
|
||||
start += blks;
|
||||
blks = 0;
|
||||
}
|
||||
debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
|
||||
__func__, start, smallblks, buf_addr);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
scsi_print_error(pccb);
|
||||
blkcnt -= blks;
|
||||
break;
|
||||
}
|
||||
buf_addr += pccb->datalen;
|
||||
} while (blks != 0);
|
||||
debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
|
||||
__func__, start, smallblks, buf_addr);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/* copy src to dest, skipping leading and trailing blanks
|
||||
* and null terminate the string
|
||||
*/
|
||||
void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len)
|
||||
{
|
||||
int start,end;
|
||||
|
||||
start=0;
|
||||
while(start<len) {
|
||||
if(src[start]!=' ')
|
||||
break;
|
||||
start++;
|
||||
}
|
||||
end=len-1;
|
||||
while(end>start) {
|
||||
if(src[end]!=' ')
|
||||
break;
|
||||
end--;
|
||||
}
|
||||
for( ; start<=end; start++) {
|
||||
*dest++=src[start];
|
||||
}
|
||||
*dest='\0';
|
||||
}
|
||||
|
||||
|
||||
/* Trim trailing blanks, and NUL-terminate string
|
||||
*/
|
||||
void scsi_trim_trail (unsigned char *str, unsigned int len)
|
||||
{
|
||||
unsigned char *p = str + len - 1;
|
||||
|
||||
while (len-- > 0) {
|
||||
*p-- = '\0';
|
||||
if (*p != ' ') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
|
||||
{
|
||||
*capacity = 0;
|
||||
|
||||
memset(pccb->cmd, 0, sizeof(pccb->cmd));
|
||||
pccb->cmd[0] = SCSI_RD_CAPAC10;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmdlen = 10;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
|
||||
pccb->datalen = 8;
|
||||
if (scsi_exec(pccb) != true)
|
||||
return 1;
|
||||
|
||||
*capacity = ((lbaint_t)pccb->pdata[0] << 24) |
|
||||
((lbaint_t)pccb->pdata[1] << 16) |
|
||||
((lbaint_t)pccb->pdata[2] << 8) |
|
||||
((lbaint_t)pccb->pdata[3]);
|
||||
|
||||
if (*capacity != 0xffffffff) {
|
||||
/* Read capacity (10) was sufficient for this drive. */
|
||||
*blksz = ((unsigned long)pccb->pdata[4] << 24) |
|
||||
((unsigned long)pccb->pdata[5] << 16) |
|
||||
((unsigned long)pccb->pdata[6] << 8) |
|
||||
((unsigned long)pccb->pdata[7]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read capacity (10) was insufficient. Use read capacity (16). */
|
||||
|
||||
memset(pccb->cmd, 0, sizeof(pccb->cmd));
|
||||
pccb->cmd[0] = SCSI_RD_CAPAC16;
|
||||
pccb->cmd[1] = 0x10;
|
||||
pccb->cmdlen = 16;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
|
||||
pccb->datalen = 16;
|
||||
if (scsi_exec(pccb) != true)
|
||||
return 1;
|
||||
|
||||
*capacity = ((uint64_t)pccb->pdata[0] << 56) |
|
||||
((uint64_t)pccb->pdata[1] << 48) |
|
||||
((uint64_t)pccb->pdata[2] << 40) |
|
||||
((uint64_t)pccb->pdata[3] << 32) |
|
||||
((uint64_t)pccb->pdata[4] << 24) |
|
||||
((uint64_t)pccb->pdata[5] << 16) |
|
||||
((uint64_t)pccb->pdata[6] << 8) |
|
||||
((uint64_t)pccb->pdata[7]);
|
||||
|
||||
*blksz = ((uint64_t)pccb->pdata[8] << 56) |
|
||||
((uint64_t)pccb->pdata[9] << 48) |
|
||||
((uint64_t)pccb->pdata[10] << 40) |
|
||||
((uint64_t)pccb->pdata[11] << 32) |
|
||||
((uint64_t)pccb->pdata[12] << 24) |
|
||||
((uint64_t)pccb->pdata[13] << 16) |
|
||||
((uint64_t)pccb->pdata[14] << 8) |
|
||||
((uint64_t)pccb->pdata[15]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
* Some setup (fill-in) routines
|
||||
*/
|
||||
void scsi_setup_test_unit_ready(ccb * pccb)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_TST_U_RDY;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=0;
|
||||
pccb->cmd[3]=0;
|
||||
pccb->cmd[4]=0;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_64BIT_LBA
|
||||
void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_READ16;
|
||||
pccb->cmd[1] = pccb->lun<<5;
|
||||
pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff;
|
||||
pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff;
|
||||
pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff;
|
||||
pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff;
|
||||
pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff;
|
||||
pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff;
|
||||
pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff;
|
||||
pccb->cmd[9] = ((unsigned char) (start)) & 0xff;
|
||||
pccb->cmd[10] = 0;
|
||||
pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff;
|
||||
pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff;
|
||||
pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff;
|
||||
pccb->cmd[14] = (unsigned char) blocks & 0xff;
|
||||
pccb->cmd[15] = 0;
|
||||
pccb->cmdlen = 16;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug ("scsi_setup_read16: cmd: %02X %02X "
|
||||
"startblk %02X%02X%02X%02X%02X%02X%02X%02X "
|
||||
"blccnt %02X%02X%02X%02X\n",
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
|
||||
pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
|
||||
pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_READ10;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=((unsigned char) (start>>24))&0xff;
|
||||
pccb->cmd[3]=((unsigned char) (start>>16))&0xff;
|
||||
pccb->cmd[4]=((unsigned char) (start>>8))&0xff;
|
||||
pccb->cmd[5]=((unsigned char) (start))&0xff;
|
||||
pccb->cmd[6]=0;
|
||||
pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff;
|
||||
pccb->cmd[8]=(unsigned char) blocks & 0xff;
|
||||
pccb->cmd[6]=0;
|
||||
pccb->cmdlen=10;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
|
||||
pccb->cmd[0],pccb->cmd[1],
|
||||
pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5],
|
||||
pccb->cmd[7],pccb->cmd[8]);
|
||||
}
|
||||
|
||||
void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_WRITE10;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff;
|
||||
pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff;
|
||||
pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff;
|
||||
pccb->cmd[5] = ((unsigned char) (start)) & 0xff;
|
||||
pccb->cmd[6] = 0;
|
||||
pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff;
|
||||
pccb->cmd[8] = (unsigned char)blocks & 0xff;
|
||||
pccb->cmd[9] = 0;
|
||||
pccb->cmdlen = 10;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
|
||||
__func__,
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
|
||||
pccb->cmd[7], pccb->cmd[8]);
|
||||
}
|
||||
|
||||
void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_READ6;
|
||||
pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f);
|
||||
pccb->cmd[2]=((unsigned char) (start>>8))&0xff;
|
||||
pccb->cmd[3]=((unsigned char) (start))&0xff;
|
||||
pccb->cmd[4]=(unsigned char) blocks & 0xff;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
|
||||
pccb->cmd[0],pccb->cmd[1],
|
||||
pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]);
|
||||
}
|
||||
|
||||
|
||||
void scsi_setup_inquiry(ccb * pccb)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_INQUIRY;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=0;
|
||||
pccb->cmd[3]=0;
|
||||
if(pccb->datalen>255)
|
||||
pccb->cmd[4]=255;
|
||||
else
|
||||
pccb->cmd[4]=(unsigned char)pccb->datalen;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
16
cmd/usb.c
16
cmd/usb.c
@ -723,7 +723,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
int devno, ok = 0;
|
||||
if (argc == 2) {
|
||||
for (devno = 0; ; ++devno) {
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
|
||||
devno);
|
||||
if (stor_dev == NULL)
|
||||
break;
|
||||
if (stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
@ -736,7 +737,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
}
|
||||
} else {
|
||||
devno = simple_strtoul(argv[2], NULL, 16);
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
|
||||
if (stor_dev != NULL &&
|
||||
stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
@ -762,7 +763,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
unsigned long n;
|
||||
printf("\nUSB read: device %d block # %ld, count %ld"
|
||||
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
|
||||
usb_stor_curr_dev);
|
||||
n = blk_dread(stor_dev, blk, cnt, (ulong *)addr);
|
||||
printf("%ld blocks read: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
@ -783,7 +785,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
unsigned long n;
|
||||
printf("\nUSB write: device %d block # %ld, count %ld"
|
||||
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
|
||||
usb_stor_curr_dev);
|
||||
n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr);
|
||||
printf("%ld blocks write: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
@ -796,7 +799,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
if (argc == 3) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
printf("\nUSB device %d: ", dev);
|
||||
stor_dev = usb_stor_get_dev(dev);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev);
|
||||
if (stor_dev == NULL) {
|
||||
printf("unknown device\n");
|
||||
return 1;
|
||||
@ -810,7 +813,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
return 0;
|
||||
} else {
|
||||
printf("\nUSB device %d: ", usb_stor_curr_dev);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
|
||||
usb_stor_curr_dev);
|
||||
dev_print(stor_dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
|
@ -84,6 +84,8 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
|
||||
obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
|
||||
obj-$(CONFIG_LYNXKDI) += lynxkdi.o
|
||||
obj-$(CONFIG_MENU) += menu.o
|
||||
obj-$(CONFIG_CMD_SATA) += sata.o
|
||||
obj-$(CONFIG_SCSI) += scsi.o
|
||||
obj-$(CONFIG_UPDATE_TFTP) += update.o
|
||||
obj-$(CONFIG_DFU_TFTP) += update.o
|
||||
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
|
||||
@ -112,6 +114,9 @@ obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
|
||||
obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
|
||||
obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
|
||||
endif
|
||||
ifdef CONFIG_SPL_SATA_SUPPORT
|
||||
obj-$(CONFIG_SCSI) += scsi.o
|
||||
endif
|
||||
endif
|
||||
#environment
|
||||
obj-y += env_common.o
|
||||
@ -130,6 +135,7 @@ obj-y += dlmalloc.o
|
||||
ifdef CONFIG_SYS_MALLOC_F_LEN
|
||||
obj-y += malloc_simple.o
|
||||
endif
|
||||
obj-$(CONFIG_CMD_IDE) += ide.o
|
||||
obj-y += image.o
|
||||
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
|
||||
obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o
|
||||
@ -150,6 +156,9 @@ obj-y += fb_nand.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CMD_EEPROM_LAYOUT
|
||||
obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o
|
||||
endif
|
||||
# We always have this since drivers/ddr/fs/interactive.c needs it
|
||||
obj-$(CONFIG_CMDLINE) += cli_simple.o
|
||||
|
||||
|
@ -620,7 +620,7 @@ static int initr_ambapp_print(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_SCSI)
|
||||
#if defined(CONFIG_SCSI)
|
||||
static int initr_scsi(void)
|
||||
{
|
||||
puts("SCSI: ");
|
||||
@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = {
|
||||
initr_ambapp_print,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_CMD_SCSI
|
||||
#ifdef CONFIG_SCSI
|
||||
INIT_FUNC_WATCHDOG_RESET
|
||||
initr_scsi,
|
||||
#endif
|
||||
|
@ -1909,6 +1909,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
|
||||
* fulfill the user's request.
|
||||
*/
|
||||
if (m == NULL) {
|
||||
size_t extra, extra2;
|
||||
/*
|
||||
* Use bytes not nb, since mALLOc internally calls request2size too, and
|
||||
* each call increases the size to allocate, to account for the header.
|
||||
@ -1917,9 +1918,27 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
|
||||
/* Aligned -> return it */
|
||||
if ((((unsigned long)(m)) % alignment) == 0)
|
||||
return m;
|
||||
/* Otherwise, fail */
|
||||
/*
|
||||
* Otherwise, try again, requesting enough extra space to be able to
|
||||
* acquire alignment.
|
||||
*/
|
||||
fREe(m);
|
||||
m = NULL;
|
||||
/* Add in extra bytes to match misalignment of unexpanded allocation */
|
||||
extra = alignment - (((unsigned long)(m)) % alignment);
|
||||
m = (char*)(mALLOc(bytes + extra));
|
||||
/*
|
||||
* m might not be the same as before. Validate that the previous value of
|
||||
* extra still works for the current value of m.
|
||||
* If (!m), extra2=alignment so
|
||||
*/
|
||||
if (m) {
|
||||
extra2 = alignment - (((unsigned long)(m)) % alignment);
|
||||
if (extra2 > extra) {
|
||||
fREe(m);
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
/* Fall through to original NULL check and chunk splitting logic */
|
||||
}
|
||||
|
||||
if (m == NULL) return NULL; /* propagate failure */
|
||||
|
250
common/eeprom/eeprom_field.c
Normal file
250
common/eeprom/eeprom_field.c
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* (C) Copyright 2009-2016 CompuLab, Ltd.
|
||||
*
|
||||
* Authors: Nikita Kiryanov <nikita@compulab.co.il>
|
||||
* Igor Grinberg <grinberg@compulab.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/string.h>
|
||||
#include <eeprom_field.h>
|
||||
|
||||
static void __eeprom_field_print_bin(const struct eeprom_field *field,
|
||||
char *delimiter, bool reverse)
|
||||
{
|
||||
int i;
|
||||
int from = reverse ? field->size - 1 : 0;
|
||||
int to = reverse ? 0 : field->size - 1;
|
||||
|
||||
printf(PRINT_FIELD_SEGMENT, field->name);
|
||||
for (i = from; i != to; reverse ? i-- : i++)
|
||||
printf("%02x%s", field->buf[i], delimiter);
|
||||
|
||||
printf("%02x\n", field->buf[i]);
|
||||
}
|
||||
|
||||
static int __eeprom_field_update_bin(struct eeprom_field *field,
|
||||
const char *value, bool reverse)
|
||||
{
|
||||
int len = strlen(value);
|
||||
int k, j, i = reverse ? len - 1 : 0;
|
||||
unsigned char byte;
|
||||
char *endptr;
|
||||
|
||||
/* each two characters in the string fit in one byte */
|
||||
if (len > field->size * 2)
|
||||
return -1;
|
||||
|
||||
memset(field->buf, 0, field->size);
|
||||
|
||||
/* i - string iterator, j - buf iterator */
|
||||
for (j = 0; j < field->size; j++) {
|
||||
byte = 0;
|
||||
char tmp[3] = { 0, 0, 0 };
|
||||
|
||||
if ((reverse && i < 0) || (!reverse && i >= len))
|
||||
break;
|
||||
|
||||
for (k = 0; k < 2; k++) {
|
||||
if (reverse && i == 0) {
|
||||
tmp[k] = value[i];
|
||||
break;
|
||||
}
|
||||
|
||||
tmp[k] = value[reverse ? i - 1 + k : i + k];
|
||||
}
|
||||
|
||||
byte = simple_strtoul(tmp, &endptr, 0);
|
||||
if (*endptr != '\0' || byte < 0)
|
||||
return -1;
|
||||
|
||||
field->buf[j] = byte;
|
||||
i = reverse ? i - 2 : i + 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __eeprom_field_update_bin_delim(struct eeprom_field *field,
|
||||
char *value, char *delimiter)
|
||||
{
|
||||
int count = 0;
|
||||
int i, val;
|
||||
const char *tmp = value;
|
||||
char *tok;
|
||||
char *endptr;
|
||||
|
||||
tmp = strstr(tmp, delimiter);
|
||||
while (tmp != NULL) {
|
||||
count++;
|
||||
tmp++;
|
||||
tmp = strstr(tmp, delimiter);
|
||||
}
|
||||
|
||||
if (count > field->size)
|
||||
return -1;
|
||||
|
||||
tok = strtok(value, delimiter);
|
||||
for (i = 0; tok && i < field->size; i++) {
|
||||
val = simple_strtoul(tok, &endptr, 0);
|
||||
if (*endptr != '\0')
|
||||
return -1;
|
||||
|
||||
/* here we assume that each tok is no more than byte long */
|
||||
field->buf[i] = (unsigned char)val;
|
||||
tok = strtok(NULL, delimiter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_print_bin() - print a field which contains binary data
|
||||
*
|
||||
* Treat the field data as simple binary data, and print it as two digit
|
||||
* hexadecimal values.
|
||||
* Sample output:
|
||||
* Field Name 0102030405060708090a
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_bin(const struct eeprom_field *field)
|
||||
{
|
||||
__eeprom_field_print_bin(field, "", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_bin() - Update field with new data in binary form
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a string of values (i.e. "10b234a")
|
||||
*/
|
||||
int eeprom_field_update_bin(struct eeprom_field *field, char *value)
|
||||
{
|
||||
return __eeprom_field_update_bin(field, value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_reserved() - Update reserved field with new data in
|
||||
* binary form
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a space delimited string of byte values (i.e. "1 02 3 0x4")
|
||||
*/
|
||||
int eeprom_field_update_reserved(struct eeprom_field *field, char *value)
|
||||
{
|
||||
return __eeprom_field_update_bin_delim(field, value, " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_print_bin_rev() - print a field which contains binary data in
|
||||
* reverse order
|
||||
*
|
||||
* Treat the field data as simple binary data, and print it in reverse order
|
||||
* as two digit hexadecimal values.
|
||||
*
|
||||
* Data in field:
|
||||
* 0102030405060708090a
|
||||
* Sample output:
|
||||
* Field Name 0a090807060504030201
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_bin_rev(const struct eeprom_field *field)
|
||||
{
|
||||
__eeprom_field_print_bin(field, "", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_bin_rev() - Update field with new data in binary form,
|
||||
* storing it in reverse
|
||||
*
|
||||
* This function takes a string of byte values, and stores them
|
||||
* in the field in the reverse order. i.e. if the input string was "1234",
|
||||
* "3412" will be written to the field.
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a string of byte values
|
||||
*/
|
||||
int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value)
|
||||
{
|
||||
return __eeprom_field_update_bin(field, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_print_mac_addr() - print a field which contains a mac address
|
||||
*
|
||||
* Treat the field data as simple binary data, and print it formatted as a MAC
|
||||
* address.
|
||||
* Sample output:
|
||||
* Field Name 01:02:03:04:05:06
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_mac(const struct eeprom_field *field)
|
||||
{
|
||||
__eeprom_field_print_bin(field, ":", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_mac() - Update a mac address field which contains binary
|
||||
* data
|
||||
*
|
||||
* @field: an initialized field
|
||||
* @value: a colon delimited string of byte values (i.e. "1:02:3:ff")
|
||||
*/
|
||||
int eeprom_field_update_mac(struct eeprom_field *field, char *value)
|
||||
{
|
||||
return __eeprom_field_update_bin_delim(field, value, ":");
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_print_ascii() - print a field which contains ASCII data
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_ascii(const struct eeprom_field *field)
|
||||
{
|
||||
char format[8];
|
||||
|
||||
sprintf(format, "%%.%ds\n", field->size);
|
||||
printf(PRINT_FIELD_SEGMENT, field->name);
|
||||
printf(format, field->buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_update_ascii() - Update field with new data in ASCII form
|
||||
* @field: an initialized field
|
||||
* @value: the new string data
|
||||
*
|
||||
* Returns 0 on success, -1 of failure (new string too long).
|
||||
*/
|
||||
int eeprom_field_update_ascii(struct eeprom_field *field, char *value)
|
||||
{
|
||||
if (strlen(value) >= field->size) {
|
||||
printf("%s: new data too long\n", field->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy((char *)field->buf, value, field->size - 1);
|
||||
field->buf[field->size - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eeprom_field_print_reserved() - print the "Reserved fields" field
|
||||
*
|
||||
* Print a notice that the following field_size bytes are reserved.
|
||||
*
|
||||
* Sample output:
|
||||
* Reserved fields (64 bytes)
|
||||
*
|
||||
* @field: an initialized field to print
|
||||
*/
|
||||
void eeprom_field_print_reserved(const struct eeprom_field *field)
|
||||
{
|
||||
printf(PRINT_FIELD_SEGMENT, "Reserved fields\t");
|
||||
printf("(%d bytes)\n", field->size);
|
||||
}
|
125
common/eeprom/eeprom_layout.c
Normal file
125
common/eeprom/eeprom_layout.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* (C) Copyright 2009-2016 CompuLab, Ltd.
|
||||
*
|
||||
* Authors: Nikita Kiryanov <nikita@compulab.co.il>
|
||||
* Igor Grinberg <grinberg@compulab.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <eeprom_layout.h>
|
||||
#include <eeprom_field.h>
|
||||
|
||||
#define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n"
|
||||
|
||||
struct eeprom_field layout_unknown[1] = {
|
||||
{ NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin,
|
||||
eeprom_field_update_bin },
|
||||
};
|
||||
|
||||
/*
|
||||
* eeprom_layout_detect() - detect layout based on the contents of the data.
|
||||
* @data: Pointer to the data to be analyzed.
|
||||
*
|
||||
* Returns: the detected layout version.
|
||||
*/
|
||||
__weak int eeprom_layout_detect(unsigned char *data)
|
||||
{
|
||||
return LAYOUT_VERSION_UNRECOGNIZED;
|
||||
}
|
||||
|
||||
/*
|
||||
* __eeprom_layout_assign() - set the layout fields
|
||||
* @layout: A pointer to an existing struct layout.
|
||||
* @layout_version: The version number of the desired layout
|
||||
*/
|
||||
__weak void __eeprom_layout_assign(struct eeprom_layout *layout,
|
||||
int layout_version)
|
||||
{
|
||||
layout->fields = layout_unknown;
|
||||
layout->num_of_fields = ARRAY_SIZE(layout_unknown);
|
||||
}
|
||||
void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \
|
||||
__attribute__((weak, alias("__eeprom_layout_assign")));
|
||||
|
||||
/*
|
||||
* eeprom_layout_print() - print the layout and the data which is assigned to it
|
||||
* @layout: A pointer to an existing struct layout.
|
||||
*/
|
||||
static void eeprom_layout_print(const struct eeprom_layout *layout)
|
||||
{
|
||||
int i;
|
||||
struct eeprom_field *fields = layout->fields;
|
||||
|
||||
for (i = 0; i < layout->num_of_fields; i++)
|
||||
fields[i].print(&fields[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* eeprom_layout_update_field() - update a single field in the layout data.
|
||||
* @layout: A pointer to an existing struct layout.
|
||||
* @field_name: The name of the field to update.
|
||||
* @new_data: The new field data (a string. Format depends on the field)
|
||||
*
|
||||
* Returns: 0 on success, negative error value on failure.
|
||||
*/
|
||||
static int eeprom_layout_update_field(struct eeprom_layout *layout,
|
||||
char *field_name, char *new_data)
|
||||
{
|
||||
int i, err;
|
||||
struct eeprom_field *fields = layout->fields;
|
||||
|
||||
if (new_data == NULL)
|
||||
return 0;
|
||||
|
||||
if (field_name == NULL)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < layout->num_of_fields; i++) {
|
||||
if (fields[i].name == RESERVED_FIELDS ||
|
||||
strcmp(fields[i].name, field_name))
|
||||
continue;
|
||||
|
||||
err = fields[i].update(&fields[i], new_data);
|
||||
if (err)
|
||||
printf("Invalid data for field %s\n", field_name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
printf("No such field '%s'\n", field_name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* eeprom_layout_setup() - setup layout struct with the layout data and
|
||||
* metadata as dictated by layout_version
|
||||
* @layout: A pointer to an existing struct layout.
|
||||
* @buf: A buffer initialized with the eeprom data.
|
||||
* @buf_size: Size of buf in bytes.
|
||||
* @layout version: The version number of the layout.
|
||||
*/
|
||||
void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf,
|
||||
unsigned int buf_size, int layout_version)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (layout_version == LAYOUT_VERSION_AUTODETECT)
|
||||
layout->layout_version = eeprom_layout_detect(buf);
|
||||
else
|
||||
layout->layout_version = layout_version;
|
||||
|
||||
eeprom_layout_assign(layout, layout_version);
|
||||
layout->data = buf;
|
||||
for (i = 0; i < layout->num_of_fields; i++) {
|
||||
layout->fields[i].buf = buf;
|
||||
buf += layout->fields[i].size;
|
||||
}
|
||||
|
||||
layout->data_size = buf_size;
|
||||
layout->print = eeprom_layout_print;
|
||||
layout->update = eeprom_layout_update_field;
|
||||
}
|
@ -86,8 +86,8 @@ static int mmc_set_env_part(struct mmc *mmc)
|
||||
dev = 0;
|
||||
#endif
|
||||
|
||||
env_mmc_orig_hwpart = mmc->block_dev.hwpart;
|
||||
ret = mmc_select_hwpart(dev, part);
|
||||
env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart;
|
||||
ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
|
||||
if (ret)
|
||||
puts("MMC partition switch failed\n");
|
||||
|
||||
@ -119,7 +119,7 @@ static void fini_mmc_for_env(struct mmc *mmc)
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
dev = 0;
|
||||
#endif
|
||||
mmc_select_hwpart(dev, env_mmc_orig_hwpart);
|
||||
blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
1231
common/ide.c
Normal file
1231
common/ide.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -886,9 +886,9 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
|
||||
ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
|
||||
sizeof(uint32_t));
|
||||
if (ret) {
|
||||
printf("Can't set '%s' property for '%s' node (%s)\n",
|
||||
FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
|
||||
fdt_strerror(ret));
|
||||
debug("Can't set '%s' property for '%s' node (%s)\n",
|
||||
FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
|
||||
fdt_strerror(ret));
|
||||
return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
|
||||
}
|
||||
|
||||
|
115
common/sata.c
Normal file
115
common/sata.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2000-2005, DENX Software Engineering
|
||||
* Wolfgang Denk <wd@denx.de>
|
||||
* Copyright (C) Procsys. All rights reserved.
|
||||
* Mushtaq Khan <mushtaq_k@procsys.com>
|
||||
* <mushtaqk_921@yahoo.co.in>
|
||||
* Copyright (C) 2008 Freescale Semiconductor, Inc.
|
||||
* Dave Liu <daveliu@freescale.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <sata.h>
|
||||
|
||||
struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
|
||||
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
struct blk_desc *sata_get_dev(int dev)
|
||||
{
|
||||
return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static unsigned long sata_bread(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *dst)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#else
|
||||
static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *dst)
|
||||
{
|
||||
return sata_read(block_dev->devnum, start, blkcnt, dst);
|
||||
}
|
||||
|
||||
static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
return sata_write(block_dev->devnum, start, blkcnt, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __sata_initialize(void)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
|
||||
memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
|
||||
sata_dev_desc[i].if_type = IF_TYPE_SATA;
|
||||
sata_dev_desc[i].devnum = i;
|
||||
sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
|
||||
sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
|
||||
sata_dev_desc[i].lba = 0;
|
||||
sata_dev_desc[i].blksz = 512;
|
||||
sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
|
||||
#ifndef CONFIG_BLK
|
||||
sata_dev_desc[i].block_read = sata_bread;
|
||||
sata_dev_desc[i].block_write = sata_bwrite;
|
||||
#endif
|
||||
rc = init_sata(i);
|
||||
if (!rc) {
|
||||
rc = scan_sata(i);
|
||||
if (!rc && sata_dev_desc[i].lba > 0 &&
|
||||
sata_dev_desc[i].blksz > 0)
|
||||
part_init(&sata_dev_desc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
int sata_initialize(void) __attribute__((weak, alias("__sata_initialize")));
|
||||
|
||||
__weak int __sata_stop(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
|
||||
err |= reset_sata(i);
|
||||
|
||||
if (err)
|
||||
printf("Could not reset some SATA devices\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static const struct blk_ops sata_blk_ops = {
|
||||
.read = sata_bread,
|
||||
.write = sata_bwrite,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sata_blk) = {
|
||||
.name = "sata_blk",
|
||||
.id = UCLASS_BLK,
|
||||
.ops = &sata_blk_ops,
|
||||
};
|
||||
#else
|
||||
U_BOOT_LEGACY_BLK(sata) = {
|
||||
.if_typename = "sata",
|
||||
.if_type = IF_TYPE_SATA,
|
||||
.max_devs = CONFIG_SYS_SATA_MAX_DEVICE,
|
||||
.desc = sata_dev_desc,
|
||||
};
|
||||
#endif
|
592
common/scsi.c
Normal file
592
common/scsi.c
Normal file
@ -0,0 +1,592 @@
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <inttypes.h>
|
||||
#include <pci.h>
|
||||
#include <scsi.h>
|
||||
|
||||
#ifdef CONFIG_SCSI_DEV_LIST
|
||||
#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
|
||||
#else
|
||||
#ifdef CONFIG_SCSI_SYM53C8XX
|
||||
#define SCSI_VEND_ID 0x1000
|
||||
#ifndef CONFIG_SCSI_DEV_ID
|
||||
#define SCSI_DEV_ID 0x0001
|
||||
#else
|
||||
#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID
|
||||
#endif
|
||||
#elif defined CONFIG_SATA_ULI5288
|
||||
|
||||
#define SCSI_VEND_ID 0x10b9
|
||||
#define SCSI_DEV_ID 0x5288
|
||||
|
||||
#elif !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
#error no scsi device defined
|
||||
#endif
|
||||
#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
|
||||
#endif
|
||||
static ccb tempccb; /* temporary scsi command buffer */
|
||||
|
||||
static unsigned char tempbuff[512]; /* temporary data buffer */
|
||||
|
||||
static int scsi_max_devs; /* number of highest available scsi device */
|
||||
|
||||
static int scsi_curr_dev; /* current device */
|
||||
|
||||
static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
|
||||
|
||||
/* almost the maximum amount of the scsi_ext command.. */
|
||||
#define SCSI_MAX_READ_BLK 0xFFFF
|
||||
#define SCSI_LBA48_READ 0xFFFFFFF
|
||||
|
||||
#ifdef CONFIG_SYS_64BIT_LBA
|
||||
void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_READ16;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff;
|
||||
pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff;
|
||||
pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff;
|
||||
pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff;
|
||||
pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff;
|
||||
pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff;
|
||||
pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff;
|
||||
pccb->cmd[9] = (unsigned char)start & 0xff;
|
||||
pccb->cmd[10] = 0;
|
||||
pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff;
|
||||
pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff;
|
||||
pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff;
|
||||
pccb->cmd[14] = (unsigned char)blocks & 0xff;
|
||||
pccb->cmd[15] = 0;
|
||||
pccb->cmdlen = 16;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n",
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
|
||||
pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9],
|
||||
pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void scsi_setup_read_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_READ10;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
|
||||
pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
|
||||
pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
|
||||
pccb->cmd[5] = (unsigned char)start & 0xff;
|
||||
pccb->cmd[6] = 0;
|
||||
pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
|
||||
pccb->cmd[8] = (unsigned char)blocks & 0xff;
|
||||
pccb->cmd[6] = 0;
|
||||
pccb->cmdlen = 10;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
|
||||
pccb->cmd[7], pccb->cmd[8]);
|
||||
}
|
||||
|
||||
void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_WRITE10;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
|
||||
pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
|
||||
pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
|
||||
pccb->cmd[5] = (unsigned char)start & 0xff;
|
||||
pccb->cmd[6] = 0;
|
||||
pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff;
|
||||
pccb->cmd[8] = (unsigned char)blocks & 0xff;
|
||||
pccb->cmd[9] = 0;
|
||||
pccb->cmdlen = 10;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
|
||||
__func__,
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5],
|
||||
pccb->cmd[7], pccb->cmd[8]);
|
||||
}
|
||||
|
||||
void scsi_setup_read6(ccb *pccb, lbaint_t start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_READ6;
|
||||
pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f);
|
||||
pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff;
|
||||
pccb->cmd[3] = (unsigned char)start & 0xff;
|
||||
pccb->cmd[4] = (unsigned char)blocks & 0xff;
|
||||
pccb->cmd[5] = 0;
|
||||
pccb->cmdlen = 6;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
|
||||
pccb->cmd[0], pccb->cmd[1],
|
||||
pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]);
|
||||
}
|
||||
|
||||
|
||||
void scsi_setup_inquiry(ccb *pccb)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_INQUIRY;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = 0;
|
||||
pccb->cmd[3] = 0;
|
||||
if (pccb->datalen > 255)
|
||||
pccb->cmd[4] = 255;
|
||||
else
|
||||
pccb->cmd[4] = (unsigned char)pccb->datalen;
|
||||
pccb->cmd[5] = 0;
|
||||
pccb->cmdlen = 6;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
|
||||
void *buffer)
|
||||
#else
|
||||
static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, void *buffer)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_BLK
|
||||
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||
#endif
|
||||
int device = block_dev->devnum;
|
||||
lbaint_t start, blks;
|
||||
uintptr_t buf_addr;
|
||||
unsigned short smallblks = 0;
|
||||
ccb *pccb = (ccb *)&tempccb;
|
||||
device &= 0xff;
|
||||
|
||||
/* Setup device */
|
||||
pccb->target = scsi_dev_desc[device].target;
|
||||
pccb->lun = scsi_dev_desc[device].lun;
|
||||
buf_addr = (unsigned long)buffer;
|
||||
start = blknr;
|
||||
blks = blkcnt;
|
||||
debug("\nscsi_read: dev %d startblk " LBAF
|
||||
", blccnt " LBAF " buffer %lx\n",
|
||||
device, start, blks, (unsigned long)buffer);
|
||||
do {
|
||||
pccb->pdata = (unsigned char *)buf_addr;
|
||||
#ifdef CONFIG_SYS_64BIT_LBA
|
||||
if (start > SCSI_LBA48_READ) {
|
||||
unsigned long blocks;
|
||||
blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK);
|
||||
pccb->datalen = scsi_dev_desc[device].blksz * blocks;
|
||||
scsi_setup_read16(pccb, start, blocks);
|
||||
start += blocks;
|
||||
blks -= blocks;
|
||||
} else
|
||||
#endif
|
||||
if (blks > SCSI_MAX_READ_BLK) {
|
||||
pccb->datalen = scsi_dev_desc[device].blksz *
|
||||
SCSI_MAX_READ_BLK;
|
||||
smallblks = SCSI_MAX_READ_BLK;
|
||||
scsi_setup_read_ext(pccb, start, smallblks);
|
||||
start += SCSI_MAX_READ_BLK;
|
||||
blks -= SCSI_MAX_READ_BLK;
|
||||
} else {
|
||||
pccb->datalen = scsi_dev_desc[device].blksz * blks;
|
||||
smallblks = (unsigned short)blks;
|
||||
scsi_setup_read_ext(pccb, start, smallblks);
|
||||
start += blks;
|
||||
blks = 0;
|
||||
}
|
||||
debug("scsi_read_ext: startblk " LBAF
|
||||
", blccnt %x buffer %" PRIXPTR "\n",
|
||||
start, smallblks, buf_addr);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
scsi_print_error(pccb);
|
||||
blkcnt -= blks;
|
||||
break;
|
||||
}
|
||||
buf_addr += pccb->datalen;
|
||||
} while (blks != 0);
|
||||
debug("scsi_read_ext: end startblk " LBAF
|
||||
", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* scsi_write
|
||||
*/
|
||||
|
||||
/* Almost the maximum amount of the scsi_ext command.. */
|
||||
#define SCSI_MAX_WRITE_BLK 0xFFFF
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
|
||||
const void *buffer)
|
||||
#else
|
||||
static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_BLK
|
||||
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||
#endif
|
||||
int device = block_dev->devnum;
|
||||
lbaint_t start, blks;
|
||||
uintptr_t buf_addr;
|
||||
unsigned short smallblks;
|
||||
ccb *pccb = (ccb *)&tempccb;
|
||||
|
||||
device &= 0xff;
|
||||
|
||||
/* Setup device */
|
||||
pccb->target = scsi_dev_desc[device].target;
|
||||
pccb->lun = scsi_dev_desc[device].lun;
|
||||
buf_addr = (unsigned long)buffer;
|
||||
start = blknr;
|
||||
blks = blkcnt;
|
||||
debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
|
||||
__func__, device, start, blks, (unsigned long)buffer);
|
||||
do {
|
||||
pccb->pdata = (unsigned char *)buf_addr;
|
||||
if (blks > SCSI_MAX_WRITE_BLK) {
|
||||
pccb->datalen = (scsi_dev_desc[device].blksz *
|
||||
SCSI_MAX_WRITE_BLK);
|
||||
smallblks = SCSI_MAX_WRITE_BLK;
|
||||
scsi_setup_write_ext(pccb, start, smallblks);
|
||||
start += SCSI_MAX_WRITE_BLK;
|
||||
blks -= SCSI_MAX_WRITE_BLK;
|
||||
} else {
|
||||
pccb->datalen = scsi_dev_desc[device].blksz * blks;
|
||||
smallblks = (unsigned short)blks;
|
||||
scsi_setup_write_ext(pccb, start, smallblks);
|
||||
start += blks;
|
||||
blks = 0;
|
||||
}
|
||||
debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
|
||||
__func__, start, smallblks, buf_addr);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
scsi_print_error(pccb);
|
||||
blkcnt -= blks;
|
||||
break;
|
||||
}
|
||||
buf_addr += pccb->datalen;
|
||||
} while (blks != 0);
|
||||
debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n",
|
||||
__func__, start, smallblks, buf_addr);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
int scsi_get_disk_count(void)
|
||||
{
|
||||
return scsi_max_devs;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
|
||||
void scsi_init(void)
|
||||
{
|
||||
int busdevfunc = -1;
|
||||
int i;
|
||||
/*
|
||||
* Find a device from the list, this driver will support a single
|
||||
* controller.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
|
||||
/* get PCI Device ID */
|
||||
#ifdef CONFIG_DM_PCI
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = dm_pci_find_device(scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device, 0, &dev);
|
||||
if (!ret) {
|
||||
busdevfunc = dm_pci_get_bdf(dev);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
busdevfunc = pci_find_device(scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device,
|
||||
0);
|
||||
#endif
|
||||
if (busdevfunc != -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (busdevfunc == -1) {
|
||||
printf("Error: SCSI Controller(s) ");
|
||||
for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {
|
||||
printf("%04X:%04X ",
|
||||
scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device);
|
||||
}
|
||||
printf("not found\n");
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",
|
||||
scsi_device_list[i].vendor,
|
||||
scsi_device_list[i].device,
|
||||
(busdevfunc >> 16) & 0xFF,
|
||||
(busdevfunc >> 11) & 0x1F,
|
||||
(busdevfunc >> 8) & 0x7);
|
||||
}
|
||||
#endif
|
||||
bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
|
||||
scsi_low_level_init(busdevfunc);
|
||||
scsi_scan(1);
|
||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* copy src to dest, skipping leading and trailing blanks
|
||||
* and null terminate the string
|
||||
*/
|
||||
void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len)
|
||||
{
|
||||
int start, end;
|
||||
|
||||
start = 0;
|
||||
while (start < len) {
|
||||
if (src[start] != ' ')
|
||||
break;
|
||||
start++;
|
||||
}
|
||||
end = len-1;
|
||||
while (end > start) {
|
||||
if (src[end] != ' ')
|
||||
break;
|
||||
end--;
|
||||
}
|
||||
for (; start <= end; start++)
|
||||
*dest ++= src[start];
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* Trim trailing blanks, and NUL-terminate string
|
||||
*/
|
||||
void scsi_trim_trail(unsigned char *str, unsigned int len)
|
||||
{
|
||||
unsigned char *p = str + len - 1;
|
||||
|
||||
while (len-- > 0) {
|
||||
*p-- = '\0';
|
||||
if (*p != ' ')
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
|
||||
{
|
||||
*capacity = 0;
|
||||
|
||||
memset(pccb->cmd, '\0', sizeof(pccb->cmd));
|
||||
pccb->cmd[0] = SCSI_RD_CAPAC10;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmdlen = 10;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
|
||||
pccb->datalen = 8;
|
||||
if (scsi_exec(pccb) != true)
|
||||
return 1;
|
||||
|
||||
*capacity = ((lbaint_t)pccb->pdata[0] << 24) |
|
||||
((lbaint_t)pccb->pdata[1] << 16) |
|
||||
((lbaint_t)pccb->pdata[2] << 8) |
|
||||
((lbaint_t)pccb->pdata[3]);
|
||||
|
||||
if (*capacity != 0xffffffff) {
|
||||
/* Read capacity (10) was sufficient for this drive. */
|
||||
*blksz = ((unsigned long)pccb->pdata[4] << 24) |
|
||||
((unsigned long)pccb->pdata[5] << 16) |
|
||||
((unsigned long)pccb->pdata[6] << 8) |
|
||||
((unsigned long)pccb->pdata[7]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read capacity (10) was insufficient. Use read capacity (16). */
|
||||
memset(pccb->cmd, '\0', sizeof(pccb->cmd));
|
||||
pccb->cmd[0] = SCSI_RD_CAPAC16;
|
||||
pccb->cmd[1] = 0x10;
|
||||
pccb->cmdlen = 16;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
|
||||
pccb->datalen = 16;
|
||||
if (scsi_exec(pccb) != true)
|
||||
return 1;
|
||||
|
||||
*capacity = ((uint64_t)pccb->pdata[0] << 56) |
|
||||
((uint64_t)pccb->pdata[1] << 48) |
|
||||
((uint64_t)pccb->pdata[2] << 40) |
|
||||
((uint64_t)pccb->pdata[3] << 32) |
|
||||
((uint64_t)pccb->pdata[4] << 24) |
|
||||
((uint64_t)pccb->pdata[5] << 16) |
|
||||
((uint64_t)pccb->pdata[6] << 8) |
|
||||
((uint64_t)pccb->pdata[7]);
|
||||
|
||||
*blksz = ((uint64_t)pccb->pdata[8] << 56) |
|
||||
((uint64_t)pccb->pdata[9] << 48) |
|
||||
((uint64_t)pccb->pdata[10] << 40) |
|
||||
((uint64_t)pccb->pdata[11] << 32) |
|
||||
((uint64_t)pccb->pdata[12] << 24) |
|
||||
((uint64_t)pccb->pdata[13] << 16) |
|
||||
((uint64_t)pccb->pdata[14] << 8) |
|
||||
((uint64_t)pccb->pdata[15]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Some setup (fill-in) routines
|
||||
*/
|
||||
void scsi_setup_test_unit_ready(ccb *pccb)
|
||||
{
|
||||
pccb->cmd[0] = SCSI_TST_U_RDY;
|
||||
pccb->cmd[1] = pccb->lun << 5;
|
||||
pccb->cmd[2] = 0;
|
||||
pccb->cmd[3] = 0;
|
||||
pccb->cmd[4] = 0;
|
||||
pccb->cmd[5] = 0;
|
||||
pccb->cmdlen = 6;
|
||||
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
||||
/*
|
||||
* (re)-scan the scsi bus and reports scsi device info
|
||||
* to the user if mode = 1
|
||||
*/
|
||||
void scsi_scan(int mode)
|
||||
{
|
||||
unsigned char i, perq, modi, lun;
|
||||
lbaint_t capacity;
|
||||
unsigned long blksz;
|
||||
ccb *pccb = (ccb *)&tempccb;
|
||||
|
||||
if (mode == 1)
|
||||
printf("scanning bus for devices...\n");
|
||||
for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) {
|
||||
scsi_dev_desc[i].target = 0xff;
|
||||
scsi_dev_desc[i].lun = 0xff;
|
||||
scsi_dev_desc[i].lba = 0;
|
||||
scsi_dev_desc[i].blksz = 0;
|
||||
scsi_dev_desc[i].log2blksz =
|
||||
LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz));
|
||||
scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN;
|
||||
scsi_dev_desc[i].vendor[0] = 0;
|
||||
scsi_dev_desc[i].product[0] = 0;
|
||||
scsi_dev_desc[i].revision[0] = 0;
|
||||
scsi_dev_desc[i].removable = false;
|
||||
scsi_dev_desc[i].if_type = IF_TYPE_SCSI;
|
||||
scsi_dev_desc[i].devnum = i;
|
||||
scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
|
||||
#ifndef CONFIG_BLK
|
||||
scsi_dev_desc[i].block_read = scsi_read;
|
||||
scsi_dev_desc[i].block_write = scsi_write;
|
||||
#endif
|
||||
}
|
||||
scsi_max_devs = 0;
|
||||
for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
|
||||
pccb->target = i;
|
||||
for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
|
||||
pccb->lun = lun;
|
||||
pccb->pdata = (unsigned char *)&tempbuff;
|
||||
pccb->datalen = 512;
|
||||
scsi_setup_inquiry(pccb);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
if (pccb->contr_stat == SCSI_SEL_TIME_OUT) {
|
||||
/*
|
||||
* selection timeout => assuming no
|
||||
* device present
|
||||
*/
|
||||
debug("Selection timeout ID %d\n",
|
||||
pccb->target);
|
||||
continue;
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
perq = tempbuff[0];
|
||||
modi = tempbuff[1];
|
||||
if ((perq & 0x1f) == 0x1f)
|
||||
continue; /* skip unknown devices */
|
||||
if ((modi & 0x80) == 0x80) /* drive is removable */
|
||||
scsi_dev_desc[scsi_max_devs].removable = true;
|
||||
/* get info for this device */
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc
|
||||
[scsi_max_devs].vendor[0],
|
||||
&tempbuff[8], 8);
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc
|
||||
[scsi_max_devs].product[0],
|
||||
&tempbuff[16], 16);
|
||||
scsi_ident_cpy((unsigned char *)&scsi_dev_desc
|
||||
[scsi_max_devs].revision[0],
|
||||
&tempbuff[32], 4);
|
||||
scsi_dev_desc[scsi_max_devs].target = pccb->target;
|
||||
scsi_dev_desc[scsi_max_devs].lun = pccb->lun;
|
||||
|
||||
pccb->datalen = 0;
|
||||
scsi_setup_test_unit_ready(pccb);
|
||||
if (scsi_exec(pccb) != true) {
|
||||
if (scsi_dev_desc[scsi_max_devs].removable) {
|
||||
scsi_dev_desc[scsi_max_devs].type =
|
||||
perq;
|
||||
goto removable;
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
if (scsi_read_capacity(pccb, &capacity, &blksz)) {
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
scsi_dev_desc[scsi_max_devs].lba = capacity;
|
||||
scsi_dev_desc[scsi_max_devs].blksz = blksz;
|
||||
scsi_dev_desc[scsi_max_devs].log2blksz =
|
||||
LOG2(scsi_dev_desc[scsi_max_devs].blksz);
|
||||
scsi_dev_desc[scsi_max_devs].type = perq;
|
||||
part_init(&scsi_dev_desc[scsi_max_devs]);
|
||||
removable:
|
||||
if (mode == 1) {
|
||||
printf(" Device %d: ", scsi_max_devs);
|
||||
dev_print(&scsi_dev_desc[scsi_max_devs]);
|
||||
} /* if mode */
|
||||
scsi_max_devs++;
|
||||
} /* next LUN */
|
||||
}
|
||||
if (scsi_max_devs > 0)
|
||||
scsi_curr_dev = 0;
|
||||
else
|
||||
scsi_curr_dev = -1;
|
||||
|
||||
printf("Found %d device(s).\n", scsi_max_devs);
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
setenv_ulong("scsidevs", scsi_max_devs);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK
|
||||
static const struct blk_ops scsi_blk_ops = {
|
||||
.read = scsi_read,
|
||||
.write = scsi_write,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(scsi_blk) = {
|
||||
.name = "scsi_blk",
|
||||
.id = UCLASS_BLK,
|
||||
.ops = &scsi_blk_ops,
|
||||
};
|
||||
#else
|
||||
U_BOOT_LEGACY_BLK(scsi) = {
|
||||
.if_typename = "sata",
|
||||
.if_type = IF_TYPE_SCSI,
|
||||
.max_devs = CONFIG_SYS_SCSI_MAX_DEVICE,
|
||||
.desc = scsi_dev_desc,
|
||||
};
|
||||
#endif
|
@ -58,7 +58,7 @@ int spl_load_image_fat(struct blk_desc *block_dev,
|
||||
goto end;
|
||||
|
||||
err = spl_parse_image_header(header);
|
||||
if (err <= 0)
|
||||
if (err)
|
||||
goto end;
|
||||
|
||||
err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
|
||||
|
@ -39,8 +39,13 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)
|
||||
node >= 0;
|
||||
node = fdt_next_subnode(fdt, node)) {
|
||||
name = fdt_getprop(fdt, node, "description", &len);
|
||||
if (!name)
|
||||
if (!name) {
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
printf("%s: Missing FDT description in DTB\n",
|
||||
__func__);
|
||||
#endif
|
||||
return -EINVAL;
|
||||
}
|
||||
if (board_fit_config_name_match(name))
|
||||
continue;
|
||||
|
||||
|
@ -300,7 +300,7 @@ int spl_mmc_load_image(u32 boot_device)
|
||||
if (part == 7)
|
||||
part = 0;
|
||||
|
||||
err = mmc_switch_part(0, part);
|
||||
err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part);
|
||||
if (err) {
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
puts("spl: mmc partition switch failed\n");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user