blob: cbea880878f92df90845b572d2e941e78c49aa24 [file] [log] [blame]
/*
*(C) Copyright 2018 ASR Microelectronics (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <pxa_amp.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_ASR1901
#define DMCU_ADDR_BASE 0xC0000000
#else
#define DMCU_ADDR_BASE 0xC0100000
#endif
#define DMCU_CH0_MMAP0 (DMCU_ADDR_BASE + 0x200)
#define DMCU_CH0_MMAP1 (DMCU_ADDR_BASE + 0x208)
#define DMCU_CH0_PMAP0 (DMCU_ADDR_BASE + 0x220)
#define DMCU_CH0_PMAP1 (DMCU_ADDR_BASE + 0x224)
#define DMCU_CH0_DRAM_CFG_0 (DMCU_ADDR_BASE + 0x44)
extern int get_ramdump_flag_f(void);
int DMCU_sdram_base(int cs, ulong *base)
{
u32 mmap;
switch (cs) {
case 0:
mmap = readl(DMCU_CH0_MMAP0);
break;
case 1:
mmap = readl(DMCU_CH0_MMAP1);
break;
default:
return -1;
}
if (!(0x1 & mmap))
return -1;
else
*base = 0xFF800000 & mmap;
return 0;
}
int DMCU_sdram_size(int cs, ulong *size)
{
u32 mmap, _size, pmap, dram_cfg_0;
u32 bank_bits, row_bits, col_bits, width_bits;
switch (cs) {
case 0:
mmap = readl(DMCU_CH0_MMAP0);
pmap = readl(DMCU_CH0_PMAP0);
break;
case 1:
mmap = readl(DMCU_CH0_MMAP1);
pmap = readl(DMCU_CH0_PMAP1);
break;
default:
return -1;
}
if (!(0x1 & mmap))
return -1;
dram_cfg_0 = readl(DMCU_CH0_DRAM_CFG_0);
_size = (mmap >> 16) & 0x1F;
if (_size < 0x7) {
printf("Unknown dram size!\n");
return -1;
} else {
width_bits = ((dram_cfg_0 & (0x7 << 8)) >> 8) - 1;
bank_bits = ((pmap & 0x3) >> 0) + 1;
row_bits = ((pmap & (0xf << 8)) >> 8) + 10;
col_bits = ((pmap & (0xf << 4)) >> 4) + 7;
*size = (0x1 << (width_bits + bank_bits + row_bits + col_bits));
}
return 0;
}
#ifndef CONFIG_SYS_BOARD_DRAM_INIT
/* dram init when bd not avaliable */
int dram_init(void)
{
int i;
unsigned int reloc_end;
ulong start, size, ddr_st_offset = 0x0;
gd->ram_size = 0;
/* find ddr map start address */
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
if (!DMCU_sdram_base(i, &ddr_st_offset))
break;
}
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
if (DMCU_sdram_base(i, &start))
continue;
if (start != (gd->ram_size + ddr_st_offset)) {
printf("error: unspported not-continous ram\n");
hang();
}
if (DMCU_sdram_size(i, &size)) {
printf("Read dram size error for chip %d.\n", i);
hang();
}
gd->ram_size += size;
}
/* extend 64MB ddr space to 128MB in ap ramdump mode */
if (get_ramdump_flag_f() && (gd->ram_size == (64 * 1024 * 1024)))
gd->ram_size = (128 * 1024 * 1024);
/*
* limit the uboot ddr usage between CONFIG_SYS_TEXT_BASE and
* CONFIG_SYS_RELOC_END, which reside in ion range
* and won't impact emmddump.
*/
debug("gd->ram_size = 0x%lx\n\n",gd->ram_size);
reloc_end = pxa_amp_reloc_end();
if ((gd->ram_size + ddr_st_offset) < reloc_end)
hang();
else
gd->ram_size = (reloc_end - ddr_st_offset);
return 0;
}
/*
* If this function is not defined here,
* board.c alters dram bank zero configuration defined above.
* read from mck register again and skip error as already
* checked before
*/
void dram_init_banksize(void)
{
int i, b = 0;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
if (!DMCU_sdram_base(i, &gd->bd->bi_dram[b].start))
DMCU_sdram_size(i, &gd->bd->bi_dram[b++].size);
}
/*
* If there are banks that are not valid, we need to set
* their start address and size to 0. Otherwise other
* u-boot functions and Linux kernel gets wrong values which
* could result in crash.
*/
for (; b < CONFIG_NR_DRAM_BANKS; b++) {
gd->bd->bi_dram[b].start = 0;
gd->bd->bi_dram[b].size = 0;
}
if (gd->bd->bi_dram[0].size < CONFIG_TZ_HYPERVISOR_SIZE) {
printf("Cannot meet requirement for TrustZone!\n");
} else {
gd->bd->bi_dram[0].start += CONFIG_TZ_HYPERVISOR_SIZE;
gd->bd->bi_dram[0].size -= CONFIG_TZ_HYPERVISOR_SIZE;
gd->ram_size -= CONFIG_TZ_HYPERVISOR_SIZE;
}
}
#endif /* CONFIG_SYS_BOARD_DRAM_INIT */