avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
34
u-boot/arch/arm/cpu/armv8/fsl-layerscape/Makefile
Normal file
34
u-boot/arch/arm/cpu/armv8/fsl-layerscape/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Copyright 2014-2015, Freescale Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += cpu.o
|
||||
obj-y += lowlevel.o
|
||||
obj-y += soc.o
|
||||
obj-$(CONFIG_MP) += mp.o
|
||||
obj-$(CONFIG_OF_LIBFDT) += fdt.o
|
||||
obj-$(CONFIG_SPL) += spl.o
|
||||
|
||||
ifneq ($(CONFIG_FSL_LSCH3),)
|
||||
obj-y += fsl_lsch3_speed.o
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o
|
||||
else
|
||||
ifneq ($(CONFIG_FSL_LSCH2),)
|
||||
obj-y += fsl_lsch2_speed.o
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch2_serdes.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_LS2080A),)
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += ls2080a_serdes.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_LS1043A),)
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += ls1043a_serdes.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_LS1012A),)
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += ls1012a_serdes.o
|
||||
endif
|
||||
710
u-boot/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
Normal file
710
u-boot/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
Normal file
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/speed.h>
|
||||
#ifdef CONFIG_MP
|
||||
#include <asm/arch/mp.h>
|
||||
#endif
|
||||
#include <fm_eth.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#include <fsl_esdhc.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static struct mm_region layerscape_mem_map[] = {
|
||||
{
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
struct mm_region *mem_map = layerscape_mem_map;
|
||||
|
||||
void cpu_name(char *name)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
unsigned int i, svr, ver;
|
||||
|
||||
svr = gur_in32(&gur->svr);
|
||||
ver = SVR_SOC_VER(svr);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
|
||||
if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) {
|
||||
strcpy(name, cpu_type_list[i].name);
|
||||
|
||||
if (IS_E_PROCESSOR(svr))
|
||||
strcat(name, "E");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(cpu_type_list))
|
||||
strcpy(name, "unknown");
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||
static void set_pgtable_section(u64 *page_table, u64 index, u64 section,
|
||||
u64 memory_type, u64 attribute)
|
||||
{
|
||||
u64 value;
|
||||
|
||||
value = section | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
|
||||
value |= PMD_ATTRINDX(memory_type);
|
||||
value |= attribute;
|
||||
page_table[index] = value;
|
||||
}
|
||||
|
||||
static void set_pgtable_table(u64 *page_table, u64 index, u64 *table_addr)
|
||||
{
|
||||
u64 value;
|
||||
|
||||
value = (u64)table_addr | PTE_TYPE_TABLE;
|
||||
page_table[index] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the block entries according to the information of the table.
|
||||
*/
|
||||
static int set_block_entry(const struct sys_mmu_table *list,
|
||||
struct table_info *table)
|
||||
{
|
||||
u64 block_size = 0, block_shift = 0;
|
||||
u64 block_addr, index;
|
||||
int j;
|
||||
|
||||
if (table->entry_size == BLOCK_SIZE_L1) {
|
||||
block_size = BLOCK_SIZE_L1;
|
||||
block_shift = SECTION_SHIFT_L1;
|
||||
} else if (table->entry_size == BLOCK_SIZE_L2) {
|
||||
block_size = BLOCK_SIZE_L2;
|
||||
block_shift = SECTION_SHIFT_L2;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
block_addr = list->phys_addr;
|
||||
index = (list->virt_addr - table->table_base) >> block_shift;
|
||||
|
||||
for (j = 0; j < (list->size >> block_shift); j++) {
|
||||
set_pgtable_section(table->ptr,
|
||||
index,
|
||||
block_addr,
|
||||
list->memory_type,
|
||||
list->attribute);
|
||||
block_addr += block_size;
|
||||
index++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the corresponding table entry for the list.
|
||||
*/
|
||||
static int find_table(const struct sys_mmu_table *list,
|
||||
struct table_info *table, u64 *level0_table)
|
||||
{
|
||||
u64 index = 0, level = 0;
|
||||
u64 *level_table = level0_table;
|
||||
u64 temp_base = 0, block_size = 0, block_shift = 0;
|
||||
|
||||
while (level < 3) {
|
||||
if (level == 0) {
|
||||
block_size = BLOCK_SIZE_L0;
|
||||
block_shift = SECTION_SHIFT_L0;
|
||||
} else if (level == 1) {
|
||||
block_size = BLOCK_SIZE_L1;
|
||||
block_shift = SECTION_SHIFT_L1;
|
||||
} else if (level == 2) {
|
||||
block_size = BLOCK_SIZE_L2;
|
||||
block_shift = SECTION_SHIFT_L2;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (list->virt_addr >= temp_base) {
|
||||
index++;
|
||||
temp_base += block_size;
|
||||
}
|
||||
|
||||
temp_base -= block_size;
|
||||
|
||||
if ((level_table[index - 1] & PTE_TYPE_MASK) ==
|
||||
PTE_TYPE_TABLE) {
|
||||
level_table = (u64 *)(level_table[index - 1] &
|
||||
~PTE_TYPE_MASK);
|
||||
level++;
|
||||
continue;
|
||||
} else {
|
||||
if (level == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if ((list->phys_addr + list->size) >
|
||||
(temp_base + block_size * NUM_OF_ENTRY))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Check the address and size of the list member is
|
||||
* aligned with the block size.
|
||||
*/
|
||||
if (((list->phys_addr & (block_size - 1)) != 0) ||
|
||||
((list->size & (block_size - 1)) != 0))
|
||||
return -EINVAL;
|
||||
|
||||
table->ptr = level_table;
|
||||
table->table_base = temp_base -
|
||||
((index - 1) << block_shift);
|
||||
table->entry_size = block_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* To start MMU before DDR is available, we create MMU table in SRAM.
|
||||
* The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three
|
||||
* levels of translation tables here to cover 40-bit address space.
|
||||
* We use 4KB granule size, with 40 bits physical address, T0SZ=24
|
||||
* Level 0 IA[39], table address @0
|
||||
* Level 1 IA[38:30], table address @0x1000, 0x2000
|
||||
* Level 2 IA[29:21], table address @0x3000, 0x4000
|
||||
* Address above 0x5000 is free for other purpose.
|
||||
*/
|
||||
static inline void early_mmu_setup(void)
|
||||
{
|
||||
unsigned int el, i;
|
||||
u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE;
|
||||
u64 *level1_table0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000);
|
||||
u64 *level1_table1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000);
|
||||
u64 *level2_table0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000);
|
||||
u64 *level2_table1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x4000);
|
||||
|
||||
struct table_info table = {level0_table, 0, BLOCK_SIZE_L0};
|
||||
|
||||
/* Invalidate all table entries */
|
||||
memset(level0_table, 0, 0x5000);
|
||||
|
||||
/* Fill in the table entries */
|
||||
set_pgtable_table(level0_table, 0, level1_table0);
|
||||
set_pgtable_table(level0_table, 1, level1_table1);
|
||||
set_pgtable_table(level1_table0, 0, level2_table0);
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
set_pgtable_table(level1_table0,
|
||||
CONFIG_SYS_FLASH_BASE >> SECTION_SHIFT_L1,
|
||||
level2_table1);
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
set_pgtable_table(level1_table0, 1, level2_table1);
|
||||
#endif
|
||||
/* Find the table and fill in the block entries */
|
||||
for (i = 0; i < ARRAY_SIZE(early_mmu_table); i++) {
|
||||
if (find_table(&early_mmu_table[i],
|
||||
&table, level0_table) == 0) {
|
||||
/*
|
||||
* If find_table() returns error, it cannot be dealt
|
||||
* with here. Breakpoint can be added for debugging.
|
||||
*/
|
||||
set_block_entry(&early_mmu_table[i], &table);
|
||||
/*
|
||||
* If set_block_entry() returns error, it cannot be
|
||||
* dealt with here too.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
el = current_el();
|
||||
|
||||
set_ttbr_tcr_mair(el, (u64)level0_table, LAYERSCAPE_TCR,
|
||||
MEMORY_ATTRIBUTES);
|
||||
set_sctlr(get_sctlr() | CR_M);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
|
||||
/*
|
||||
* Called from final mmu setup. The phys_addr is new, non-existing
|
||||
* address. A new sub table is created @level2_table_secure to cover
|
||||
* size of CONFIG_SYS_MEM_RESERVE_SECURE memory.
|
||||
*/
|
||||
static inline int final_secure_ddr(u64 *level0_table,
|
||||
u64 *level2_table_secure,
|
||||
phys_addr_t phys_addr)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct table_info table = {};
|
||||
struct sys_mmu_table ddr_entry = {
|
||||
0, 0, BLOCK_SIZE_L1, MT_NORMAL,
|
||||
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
|
||||
};
|
||||
u64 index;
|
||||
|
||||
/* Need to create a new table */
|
||||
ddr_entry.virt_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
|
||||
ddr_entry.phys_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
|
||||
ret = find_table(&ddr_entry, &table, level0_table);
|
||||
if (ret)
|
||||
return ret;
|
||||
index = (ddr_entry.virt_addr - table.table_base) >> SECTION_SHIFT_L1;
|
||||
set_pgtable_table(table.ptr, index, level2_table_secure);
|
||||
table.ptr = level2_table_secure;
|
||||
table.table_base = ddr_entry.virt_addr;
|
||||
table.entry_size = BLOCK_SIZE_L2;
|
||||
ret = set_block_entry(&ddr_entry, &table);
|
||||
if (ret) {
|
||||
printf("MMU error: could not fill non-secure ddr block entries\n");
|
||||
return ret;
|
||||
}
|
||||
ddr_entry.virt_addr = phys_addr;
|
||||
ddr_entry.phys_addr = phys_addr;
|
||||
ddr_entry.size = CONFIG_SYS_MEM_RESERVE_SECURE;
|
||||
ddr_entry.attribute = PTE_BLOCK_OUTER_SHARE;
|
||||
ret = find_table(&ddr_entry, &table, level0_table);
|
||||
if (ret) {
|
||||
printf("MMU error: could not find secure ddr table\n");
|
||||
return ret;
|
||||
}
|
||||
ret = set_block_entry(&ddr_entry, &table);
|
||||
if (ret)
|
||||
printf("MMU error: could not set secure ddr block entry\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The final tables look similar to early tables, but different in detail.
|
||||
* These tables are in DRAM. Sub tables are added to enable cache for
|
||||
* QBMan and OCRAM.
|
||||
*
|
||||
* Put the MMU table in secure memory if gd->secure_ram is valid.
|
||||
* OCRAM will be not used for this purpose so gd->secure_ram can't be 0.
|
||||
*
|
||||
* Level 1 table 0 contains 512 entries for each 1GB from 0 to 512GB.
|
||||
* Level 1 table 1 contains 512 entries for each 1GB from 512GB to 1TB.
|
||||
* Level 2 table 0 contains 512 entries for each 2MB from 0 to 1GB.
|
||||
*
|
||||
* For LSCH3:
|
||||
* Level 2 table 1 contains 512 entries for each 2MB from 32GB to 33GB.
|
||||
* For LSCH2:
|
||||
* Level 2 table 1 contains 512 entries for each 2MB from 1GB to 2GB.
|
||||
* Level 2 table 2 contains 512 entries for each 2MB from 20GB to 21GB.
|
||||
*/
|
||||
static inline void final_mmu_setup(void)
|
||||
{
|
||||
unsigned int el = current_el();
|
||||
unsigned int i;
|
||||
u64 *level0_table = (u64 *)gd->arch.tlb_addr;
|
||||
u64 *level1_table0;
|
||||
u64 *level1_table1;
|
||||
u64 *level2_table0;
|
||||
u64 *level2_table1;
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
u64 *level2_table2;
|
||||
#endif
|
||||
struct table_info table = {NULL, 0, BLOCK_SIZE_L0};
|
||||
|
||||
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
|
||||
u64 *level2_table_secure;
|
||||
|
||||
if (el == 3) {
|
||||
/*
|
||||
* Only use gd->secure_ram if the address is recalculated
|
||||
* Align to 4KB for MMU table
|
||||
*/
|
||||
if (gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED)
|
||||
level0_table = (u64 *)(gd->secure_ram & ~0xfff);
|
||||
else
|
||||
printf("MMU warning: gd->secure_ram is not maintained, disabled.\n");
|
||||
}
|
||||
#endif
|
||||
level1_table0 = level0_table + 512;
|
||||
level1_table1 = level1_table0 + 512;
|
||||
level2_table0 = level1_table1 + 512;
|
||||
level2_table1 = level2_table0 + 512;
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
level2_table2 = level2_table1 + 512;
|
||||
#endif
|
||||
table.ptr = level0_table;
|
||||
|
||||
/* Invalidate all table entries */
|
||||
memset(level0_table, 0, PGTABLE_SIZE);
|
||||
|
||||
/* Fill in the table entries */
|
||||
set_pgtable_table(level0_table, 0, level1_table0);
|
||||
set_pgtable_table(level0_table, 1, level1_table1);
|
||||
set_pgtable_table(level1_table0, 0, level2_table0);
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
set_pgtable_table(level1_table0,
|
||||
CONFIG_SYS_FSL_QBMAN_BASE >> SECTION_SHIFT_L1,
|
||||
level2_table1);
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
set_pgtable_table(level1_table0, 1, level2_table1);
|
||||
set_pgtable_table(level1_table0,
|
||||
CONFIG_SYS_FSL_QBMAN_BASE >> SECTION_SHIFT_L1,
|
||||
level2_table2);
|
||||
#endif
|
||||
|
||||
/* Find the table and fill in the block entries */
|
||||
for (i = 0; i < ARRAY_SIZE(final_mmu_table); i++) {
|
||||
if (find_table(&final_mmu_table[i],
|
||||
&table, level0_table) == 0) {
|
||||
if (set_block_entry(&final_mmu_table[i],
|
||||
&table) != 0) {
|
||||
printf("MMU error: could not set block entry for %p\n",
|
||||
&final_mmu_table[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("MMU error: could not find the table for %p\n",
|
||||
&final_mmu_table[i]);
|
||||
}
|
||||
}
|
||||
/* Set the secure memory to secure in MMU */
|
||||
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
|
||||
if (el == 3 && gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
level2_table_secure = level2_table1 + 512;
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
level2_table_secure = level2_table2 + 512;
|
||||
#endif
|
||||
if (!final_secure_ddr(level0_table,
|
||||
level2_table_secure,
|
||||
gd->secure_ram & ~0x3)) {
|
||||
gd->secure_ram |= MEM_RESERVE_SECURE_SECURED;
|
||||
debug("Now MMU table is in secured memory at 0x%llx\n",
|
||||
gd->secure_ram & ~0x3);
|
||||
} else {
|
||||
printf("MMU warning: Failed to secure DDR\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* flush new MMU table */
|
||||
flush_dcache_range((ulong)level0_table,
|
||||
(ulong)level0_table + gd->arch.tlb_size);
|
||||
|
||||
/* point TTBR to the new table */
|
||||
set_ttbr_tcr_mair(el, (u64)level0_table, LAYERSCAPE_TCR_FINAL,
|
||||
MEMORY_ATTRIBUTES);
|
||||
/*
|
||||
* MMU is already enabled, just need to invalidate TLB to load the
|
||||
* new table. The new table is compatible with the current table, if
|
||||
* MMU somehow walks through the new table before invalidation TLB,
|
||||
* it still works. So we don't need to turn off MMU here.
|
||||
*/
|
||||
}
|
||||
|
||||
u64 get_page_table_size(void)
|
||||
{
|
||||
return 0x10000;
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
icache_enable();
|
||||
__asm_invalidate_dcache_all();
|
||||
__asm_invalidate_tlb_all();
|
||||
early_mmu_setup();
|
||||
set_sctlr(get_sctlr() | CR_C);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called from lib/board.c.
|
||||
* It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
|
||||
* There is no need to disable d-cache for this operation.
|
||||
*/
|
||||
void enable_caches(void)
|
||||
{
|
||||
final_mmu_setup();
|
||||
__asm_invalidate_tlb_all();
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline u32 initiator_type(u32 cluster, int init_id)
|
||||
{
|
||||
struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK;
|
||||
u32 type = 0;
|
||||
|
||||
type = gur_in32(&gur->tp_ityp[idx]);
|
||||
if (type & TP_ITYP_AV)
|
||||
return type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 cpu_mask(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
int i = 0, count = 0;
|
||||
u32 cluster, type, mask = 0;
|
||||
|
||||
do {
|
||||
int j;
|
||||
|
||||
cluster = gur_in32(&gur->tp_cluster[i].lower);
|
||||
for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
|
||||
type = initiator_type(cluster, j);
|
||||
if (type) {
|
||||
if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
|
||||
mask |= 1 << count;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while ((cluster & TP_CLUSTER_EOC) == 0x0);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of cores on this SOC.
|
||||
*/
|
||||
int cpu_numcores(void)
|
||||
{
|
||||
return hweight32(cpu_mask());
|
||||
}
|
||||
|
||||
int fsl_qoriq_core_to_cluster(unsigned int core)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur =
|
||||
(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
int i = 0, count = 0;
|
||||
u32 cluster;
|
||||
|
||||
do {
|
||||
int j;
|
||||
|
||||
cluster = gur_in32(&gur->tp_cluster[i].lower);
|
||||
for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
|
||||
if (initiator_type(cluster, j)) {
|
||||
if (count == core)
|
||||
return i;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while ((cluster & TP_CLUSTER_EOC) == 0x0);
|
||||
|
||||
return -1; /* cannot identify the cluster */
|
||||
}
|
||||
|
||||
u32 fsl_qoriq_core_to_type(unsigned int core)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur =
|
||||
(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
int i = 0, count = 0;
|
||||
u32 cluster, type;
|
||||
|
||||
do {
|
||||
int j;
|
||||
|
||||
cluster = gur_in32(&gur->tp_cluster[i].lower);
|
||||
for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
|
||||
type = initiator_type(cluster, j);
|
||||
if (type) {
|
||||
if (count == core)
|
||||
return type;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while ((cluster & TP_CLUSTER_EOC) == 0x0);
|
||||
|
||||
return -1; /* cannot identify the cluster */
|
||||
}
|
||||
|
||||
uint get_svr(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
|
||||
return gur_in32(&gur->svr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DISPLAY_CPUINFO
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
struct sys_info sysinfo;
|
||||
char buf[32];
|
||||
unsigned int i, core;
|
||||
u32 type, rcw, svr = gur_in32(&gur->svr);
|
||||
|
||||
puts("SoC: ");
|
||||
|
||||
cpu_name(buf);
|
||||
printf(" %s (0x%x)\n", buf, svr);
|
||||
memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
|
||||
get_sys_info(&sysinfo);
|
||||
puts("Clock Configuration:");
|
||||
for_each_cpu(i, core, cpu_numcores(), cpu_mask()) {
|
||||
if (!(i % 3))
|
||||
puts("\n ");
|
||||
type = TP_ITYP_VER(fsl_qoriq_core_to_type(core));
|
||||
printf("CPU%d(%s):%-4s MHz ", core,
|
||||
type == TY_ITYP_VER_A7 ? "A7 " :
|
||||
(type == TY_ITYP_VER_A53 ? "A53" :
|
||||
(type == TY_ITYP_VER_A57 ? "A57" : " ")),
|
||||
strmhz(buf, sysinfo.freq_processor[core]));
|
||||
}
|
||||
printf("\n Bus: %-4s MHz ",
|
||||
strmhz(buf, sysinfo.freq_systembus));
|
||||
printf("DDR: %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus));
|
||||
#ifdef CONFIG_SYS_DPAA_FMAN
|
||||
printf(" FMAN: %-4s MHz", strmhz(buf, sysinfo.freq_fman[0]));
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
if (soc_has_dp_ddr()) {
|
||||
printf(" DP-DDR: %-4s MT/s",
|
||||
strmhz(buf, sysinfo.freq_ddrbus2));
|
||||
}
|
||||
#endif
|
||||
puts("\n");
|
||||
|
||||
/*
|
||||
* Display the RCW, so that no one gets confused as to what RCW
|
||||
* we're actually using for this boot.
|
||||
*/
|
||||
puts("Reset Configuration Word (RCW):");
|
||||
for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) {
|
||||
rcw = gur_in32(&gur->rcwsr[i]);
|
||||
if ((i % 4) == 0)
|
||||
printf("\n %08x:", i * 4);
|
||||
printf(" %08x", rcw);
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
int cpu_mmc_init(bd_t *bis)
|
||||
{
|
||||
return fsl_esdhc_mmc_init(bis);
|
||||
}
|
||||
#endif
|
||||
|
||||
int cpu_eth_init(bd_t *bis)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
error = fsl_mc_ldpaa_init(bis);
|
||||
#endif
|
||||
#ifdef CONFIG_FMAN_ENET
|
||||
fm_standard_init(bis);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
int arch_early_init_r(void)
|
||||
{
|
||||
#ifdef CONFIG_MP
|
||||
int rv = 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
|
||||
erratum_a009635();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
rv = fsl_layerscape_wake_seconday_cores();
|
||||
if (rv)
|
||||
printf("Did not wake secondary cores\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_HAS_SERDES
|
||||
fsl_serdes_init();
|
||||
#endif
|
||||
#ifdef CONFIG_FMAN_ENET
|
||||
fman_enet_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
|
||||
#endif
|
||||
#ifdef CONFIG_LS2080A
|
||||
u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
|
||||
#endif
|
||||
#ifdef COUNTER_FREQUENCY_REAL
|
||||
unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
|
||||
|
||||
/* Update with accurate clock frequency */
|
||||
asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
/* Enable timebase for all clusters.
|
||||
* It is safe to do so even some clusters are not enabled.
|
||||
*/
|
||||
out_le32(cltbenr, 0xf);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LS2080A
|
||||
/*
|
||||
* In certain Layerscape SoCs, the clock for each core's
|
||||
* has an enable bit in the PMU Physical Core Time Base Enable
|
||||
* Register (PCTBENR), which allows the watchdog to operate.
|
||||
*/
|
||||
setbits_le32(pctbenr, 0xff);
|
||||
#endif
|
||||
|
||||
/* Enable clock for timer
|
||||
* This is a global setting.
|
||||
*/
|
||||
out_le32(cntcr, 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR;
|
||||
u32 val;
|
||||
|
||||
/* Raise RESET_REQ_B */
|
||||
val = scfg_in32(rstcr);
|
||||
val |= 0x02;
|
||||
scfg_out32(rstcr, val);
|
||||
}
|
||||
|
||||
phys_size_t board_reserve_ram_top(phys_size_t ram_size)
|
||||
{
|
||||
phys_size_t ram_top = ram_size;
|
||||
|
||||
#ifdef CONFIG_SYS_MEM_TOP_HIDE
|
||||
#error CONFIG_SYS_MEM_TOP_HIDE not to be used together with this function
|
||||
#endif
|
||||
/* Carve the Debug Server private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
ram_top -= debug_server_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
/* Carve the MC private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
ram_top -= mc_get_dram_block_size();
|
||||
ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1);
|
||||
#endif
|
||||
|
||||
return ram_top;
|
||||
}
|
||||
8
u-boot/arch/arm/cpu/armv8/fsl-layerscape/cpu.h
Normal file
8
u-boot/arch/arm/cpu/armv8/fsl-layerscape/cpu.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2014-2015, Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
int fsl_qoriq_core_to_cluster(unsigned int core);
|
||||
u32 cpu_mask(void);
|
||||
10
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
Normal file
10
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright 2015 Freescale Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
Freescale LayerScape with Chassis Generation 2
|
||||
|
||||
This architecture supports Freescale ARMv8 SoCs with Chassis generation 2,
|
||||
for example LS1043A.
|
||||
354
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
Normal file
354
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
Normal file
@@ -0,0 +1,354 @@
|
||||
#
|
||||
# Copyright 2014-2015 Freescale Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
Freescale LayerScape with Chassis Generation 3
|
||||
|
||||
This architecture supports Freescale ARMv8 SoCs with Chassis generation 3,
|
||||
for example LS2080A.
|
||||
|
||||
DDR Layout
|
||||
============
|
||||
Entire DDR region splits into two regions.
|
||||
- Region 1 is at address 0x8000_0000 to 0xffff_ffff.
|
||||
- Region 2 is at 0x80_8000_0000 to the top of total memory,
|
||||
for example 16GB, 0x83_ffff_ffff.
|
||||
|
||||
All DDR memory is marked as cache-enabled.
|
||||
|
||||
When MC and Debug server is enabled, they carve 512MB away from the high
|
||||
end of DDR. For example, if the total DDR is 16GB, it shrinks to 15.5GB
|
||||
with MC and Debug server enabled. Linux only sees 15.5GB.
|
||||
|
||||
The reserved 512MB layout looks like
|
||||
|
||||
+---------------+ <-- top/end of memory
|
||||
| 256MB | debug server
|
||||
+---------------+
|
||||
| 256MB | MC
|
||||
+---------------+
|
||||
| ... |
|
||||
|
||||
MC requires the memory to be aligned with 512MB, so even debug server is
|
||||
not enabled, 512MB is reserved, not 256MB.
|
||||
|
||||
Flash Layout
|
||||
============
|
||||
|
||||
(1) A typical layout of various images (including Linux and other firmware images)
|
||||
is shown below considering a 32MB NOR flash device present on most
|
||||
pre-silicon platforms (simulator and emulator):
|
||||
|
||||
-------------------------
|
||||
| FIT Image |
|
||||
| (linux + DTB + RFS) |
|
||||
------------------------- ----> 0x0120_0000
|
||||
| Debug Server FW |
|
||||
------------------------- ----> 0x00C0_0000
|
||||
| AIOP FW |
|
||||
------------------------- ----> 0x0070_0000
|
||||
| MC FW |
|
||||
------------------------- ----> 0x006C_0000
|
||||
| MC DPL Blob |
|
||||
------------------------- ----> 0x0020_0000
|
||||
| BootLoader + Env|
|
||||
------------------------- ----> 0x0000_1000
|
||||
| PBI |
|
||||
------------------------- ----> 0x0000_0080
|
||||
| RCW |
|
||||
------------------------- ----> 0x0000_0000
|
||||
|
||||
32-MB NOR flash layout for pre-silicon platforms (simulator and emulator)
|
||||
|
||||
(2) A typical layout of various images (including Linux and other firmware images)
|
||||
is shown below considering a 128MB NOR flash device present on QDS and RDB
|
||||
boards:
|
||||
----------------------------------------- ----> 0x5_8800_0000 ---
|
||||
| .. Unused .. (7M) | |
|
||||
----------------------------------------- ----> 0x5_8790_0000 |
|
||||
| FIT Image (linux + DTB + RFS) (40M) | |
|
||||
----------------------------------------- ----> 0x5_8510_0000 |
|
||||
| PHY firmware (2M) | |
|
||||
----------------------------------------- ----> 0x5_84F0_0000 | 64K
|
||||
| Debug Server FW (2M) | | Alt
|
||||
----------------------------------------- ----> 0x5_84D0_0000 | Bank
|
||||
| AIOP FW (4M) | |
|
||||
----------------------------------------- ----> 0x5_8490_0000 (vbank4)
|
||||
| MC DPC Blob (1M) | |
|
||||
----------------------------------------- ----> 0x5_8480_0000 |
|
||||
| MC DPL Blob (1M) | |
|
||||
----------------------------------------- ----> 0x5_8470_0000 |
|
||||
| MC FW (4M) | |
|
||||
----------------------------------------- ----> 0x5_8430_0000 |
|
||||
| BootLoader Environment (1M) | |
|
||||
----------------------------------------- ----> 0x5_8420_0000 |
|
||||
| BootLoader (1M) | |
|
||||
----------------------------------------- ----> 0x5_8410_0000 |
|
||||
| RCW and PBI (1M) | |
|
||||
----------------------------------------- ----> 0x5_8400_0000 ---
|
||||
| .. Unused .. (7M) | |
|
||||
----------------------------------------- ----> 0x5_8390_0000 |
|
||||
| FIT Image (linux + DTB + RFS) (40M) | |
|
||||
----------------------------------------- ----> 0x5_8110_0000 |
|
||||
| PHY firmware (2M) | |
|
||||
----------------------------------------- ----> 0x5_80F0_0000 | 64K
|
||||
| Debug Server FW (2M) | | Bank
|
||||
----------------------------------------- ----> 0x5_80D0_0000 |
|
||||
| AIOP FW (4M) | |
|
||||
----------------------------------------- ----> 0x5_8090_0000 (vbank0)
|
||||
| MC DPC Blob (1M) | |
|
||||
----------------------------------------- ----> 0x5_8080_0000 |
|
||||
| MC DPL Blob (1M) | |
|
||||
----------------------------------------- ----> 0x5_8070_0000 |
|
||||
| MC FW (4M) | |
|
||||
----------------------------------------- ----> 0x5_8030_0000 |
|
||||
| BootLoader Environment (1M) | |
|
||||
----------------------------------------- ----> 0x5_8020_0000 |
|
||||
| BootLoader (1M) | |
|
||||
----------------------------------------- ----> 0x5_8010_0000 |
|
||||
| RCW and PBI (1M) | |
|
||||
----------------------------------------- ----> 0x5_8000_0000 ---
|
||||
|
||||
128-MB NOR flash layout for QDS and RDB boards
|
||||
|
||||
Environment Variables
|
||||
=====================
|
||||
mcboottimeout: MC boot timeout in milliseconds. If this variable is not defined
|
||||
the value CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS will be assumed.
|
||||
|
||||
mcmemsize: MC DRAM block size. If this variable is not defined, the value
|
||||
CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE will be assumed.
|
||||
|
||||
mcinitcmd: This environment variable is defined to initiate MC and DPL deployment
|
||||
from the location where it is stored(NOR, NAND, SD, SATA, USB)during
|
||||
u-boot booting.If this variable is not defined then MC_BOOT_ENV_VAR
|
||||
will be null and MC will not be booted and DPL will not be applied
|
||||
during U-boot booting.However the MC, DPC and DPL can be applied from
|
||||
console independently.
|
||||
The variable needs to be set from the console once and then on
|
||||
rebooting the parameters set in the varible will automatically be
|
||||
executed. The commmand is demostrated taking an example of mc boot
|
||||
using NOR Flash i.e. MC, DPL, and DPC is stored in the NOR flash:
|
||||
|
||||
cp.b 0xa0000000 0x580300000 $filesize
|
||||
cp.b 0x80000000 0x580800000 $filesize
|
||||
cp.b 0x90000000 0x580700000 $filesize
|
||||
|
||||
setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000'
|
||||
|
||||
If only linux is to be booted then the mcinitcmd environment should be set as
|
||||
|
||||
setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000'
|
||||
|
||||
Here the addresses 0xa0000000, 0x80000000, 0x80000000 are of DDR to where
|
||||
MC binary, DPC binary and DPL binary are stored and 0x580300000, 0x580800000
|
||||
and 0x580700000 are addresses in NOR where these are copied. It is to be
|
||||
noted that these addresses in 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000'
|
||||
can be replaced with the addresses of DDR to
|
||||
which these will be copied in case of these binaries being stored in other
|
||||
devices like SATA, USB, NAND, SD etc.
|
||||
|
||||
Booting from NAND
|
||||
-------------------
|
||||
Booting from NAND requires two images, RCW and u-boot-with-spl.bin.
|
||||
The difference between NAND boot RCW image and NOR boot image is the PBI
|
||||
command sequence. Below is one example for PBI commands for QDS which uses
|
||||
NAND device with 2KB/page, block size 128KB.
|
||||
|
||||
1) CCSR 4-byte write to 0x00e00404, data=0x00000000
|
||||
2) CCSR 4-byte write to 0x00e00400, data=0x1800a000
|
||||
The above two commands set bootloc register to 0x00000000_1800a000 where
|
||||
the u-boot code will be running in OCRAM.
|
||||
|
||||
3) Block Copy: SRC=0x0107, SRC_ADDR=0x00020000, DEST_ADDR=0x1800a000,
|
||||
BLOCK_SIZE=0x00014000
|
||||
This command copies u-boot image from NAND device into OCRAM. The values need
|
||||
to adjust accordingly.
|
||||
|
||||
SRC should match the cfg_rcw_src, the reset config pins. It depends
|
||||
on the NAND device. See reference manual for cfg_rcw_src.
|
||||
SRC_ADDR is the offset of u-boot-with-spl.bin image in NAND device. In
|
||||
the example above, 128KB. For easy maintenance, we put it at
|
||||
the beginning of next block from RCW.
|
||||
DEST_ADDR is fixed at 0x1800a000, matching bootloc set above.
|
||||
BLOCK_SIZE is the size to be copied by PBI.
|
||||
|
||||
RCW image should be written to the beginning of NAND device. Example of using
|
||||
u-boot command
|
||||
|
||||
nand write <rcw image in memory> 0 <size of rcw image>
|
||||
|
||||
To form the NAND image, build u-boot with NAND config, for example,
|
||||
ls2080aqds_nand_defconfig. The image needed is u-boot-with-spl.bin.
|
||||
The u-boot image should be written to match SRC_ADDR, in above example 0x20000.
|
||||
|
||||
nand write <u-boot image in memory> 200000 <size of u-boot image>
|
||||
|
||||
With these two images in NAND device, the board can boot from NAND.
|
||||
|
||||
Another example for RDB boards,
|
||||
|
||||
1) CCSR 4-byte write to 0x00e00404, data=0x00000000
|
||||
2) CCSR 4-byte write to 0x00e00400, data=0x1800a000
|
||||
3) Block Copy: SRC=0x0119, SRC_ADDR=0x00080000, DEST_ADDR=0x1800a000,
|
||||
BLOCK_SIZE=0x00014000
|
||||
|
||||
nand write <rcw image in memory> 0 <size of rcw image>
|
||||
nand write <u-boot image in memory> 80000 <size of u-boot image>
|
||||
|
||||
Notice the difference from QDS is SRC, SRC_ADDR and the offset of u-boot image
|
||||
to match board NAND device with 4KB/page, block size 512KB.
|
||||
|
||||
MMU Translation Tables
|
||||
======================
|
||||
|
||||
(1) Early MMU Tables:
|
||||
|
||||
Level 0 Level 1 Level 2
|
||||
------------------ ------------------ ------------------
|
||||
| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 |
|
||||
------------------ ------------------ ------------------
|
||||
| 0x80_0000_0000 | --| | 0x00_4000_0000 | | 0x00_0020_0000 |
|
||||
------------------ | ------------------ ------------------
|
||||
| invalid | | | 0x00_8000_0000 | | 0x00_0040_0000 |
|
||||
------------------ | ------------------ ------------------
|
||||
| | 0x00_c000_0000 | | 0x00_0060_0000 |
|
||||
| ------------------ ------------------
|
||||
| | 0x01_0000_0000 | | 0x00_0080_0000 |
|
||||
| ------------------ ------------------
|
||||
| ... ...
|
||||
| ------------------
|
||||
| | 0x05_8000_0000 | --|
|
||||
| ------------------ |
|
||||
| | 0x05_c000_0000 | |
|
||||
| ------------------ |
|
||||
| ... |
|
||||
| ------------------ | ------------------
|
||||
|--> | 0x80_0000_0000 | |-> | 0x00_3000_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_4000_0000 | | 0x00_3020_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_8000_0000 | | 0x00_3040_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_c000_0000 | | 0x00_3060_0000 |
|
||||
------------------ ------------------
|
||||
| 0x81_0000_0000 | | 0x00_3080_0000 |
|
||||
------------------ ------------------
|
||||
... ...
|
||||
|
||||
(2) Final MMU Tables:
|
||||
|
||||
Level 0 Level 1 Level 2
|
||||
------------------ ------------------ ------------------
|
||||
| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 |
|
||||
------------------ ------------------ ------------------
|
||||
| 0x80_0000_0000 | --| | 0x00_4000_0000 | | 0x00_0020_0000 |
|
||||
------------------ | ------------------ ------------------
|
||||
| invalid | | | 0x00_8000_0000 | | 0x00_0040_0000 |
|
||||
------------------ | ------------------ ------------------
|
||||
| | 0x00_c000_0000 | | 0x00_0060_0000 |
|
||||
| ------------------ ------------------
|
||||
| | 0x01_0000_0000 | | 0x00_0080_0000 |
|
||||
| ------------------ ------------------
|
||||
| ... ...
|
||||
| ------------------
|
||||
| | 0x08_0000_0000 | --|
|
||||
| ------------------ |
|
||||
| | 0x08_4000_0000 | |
|
||||
| ------------------ |
|
||||
| ... |
|
||||
| ------------------ | ------------------
|
||||
|--> | 0x80_0000_0000 | |--> | 0x08_0000_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_4000_0000 | | 0x08_0020_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_8000_0000 | | 0x08_0040_0000 |
|
||||
------------------ ------------------
|
||||
| 0x80_c000_0000 | | 0x08_0060_0000 |
|
||||
------------------ ------------------
|
||||
| 0x81_0000_0000 | | 0x08_0080_0000 |
|
||||
------------------ ------------------
|
||||
... ...
|
||||
|
||||
|
||||
DPAA2 commands to manage Management Complex (MC)
|
||||
------------------------------------------------
|
||||
DPAA2 commands has been introduced to manage Management Complex
|
||||
(MC). These commands are used to start mc, aiop and apply DPL
|
||||
from u-boot command prompt.
|
||||
|
||||
Please note Management complex Firmware(MC), DPL and DPC are no
|
||||
more deployed during u-boot boot-sequence.
|
||||
|
||||
Commands:
|
||||
a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
|
||||
b) fsl_mc apply DPL <DPL_addr> - Apply DPL file
|
||||
c) fsl_mc start aiop <FW_addr> - Start AIOP
|
||||
|
||||
How to use commands :-
|
||||
1. Command sequence for u-boot ethernet:
|
||||
a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
|
||||
b) DPMAC net-devices are now available for use
|
||||
|
||||
Example-
|
||||
Assumption: MC firmware, DPL and DPC dtb is already programmed
|
||||
on NOR flash.
|
||||
|
||||
=> fsl_mc start mc 580300000 580800000
|
||||
=> setenv ethact DPMAC1@xgmii
|
||||
=> ping $serverip
|
||||
|
||||
2. Command sequence for Linux boot:
|
||||
a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
|
||||
b) fsl_mc apply DPL <DPL_addr> - Apply DPL file
|
||||
c) No DPMAC net-devices are available for use in u-boot
|
||||
d) boot Linux
|
||||
|
||||
Example-
|
||||
Assumption: MC firmware, DPL and DPC dtb is already programmed
|
||||
on NOR flash.
|
||||
|
||||
=> fsl_mc start mc 580300000 580800000
|
||||
=> setenv ethact DPMAC1@xgmii
|
||||
=> tftp a0000000 kernel.itb
|
||||
=> fsl_mc apply dpl 580700000
|
||||
=> bootm a0000000
|
||||
|
||||
3. Command sequence for AIOP boot:
|
||||
a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
|
||||
b) fsl_mc start aiop <FW_addr> - Start AIOP
|
||||
c) fsl_mc apply DPL <DPL_addr> - Apply DPL file
|
||||
d) No DPMAC net-devices are availabe for use in u-boot
|
||||
Please note actual AIOP start will happen during DPL parsing of
|
||||
Management complex
|
||||
|
||||
Example-
|
||||
Assumption: MC firmware, DPL, DPC dtb and AIOP firmware is already
|
||||
programmed on NOR flash.
|
||||
|
||||
=> fsl_mc start mc 580300000 580800000
|
||||
=> fsl_mc start aiop 0x580900000
|
||||
=> setenv ethact DPMAC1@xgmii
|
||||
=> fsl_mc apply dpl 580700000
|
||||
|
||||
Errata A009635
|
||||
---------------
|
||||
If the core runs at higher than x3 speed of the platform, there is
|
||||
possiblity about sev instruction to getting missed by other cores.
|
||||
This is because of SoC Run Control block may not able to sample
|
||||
the EVENTI(Sev) signals.
|
||||
|
||||
Workaround: Configure Run Control and EPU to periodically send out EVENTI signals to
|
||||
wake up A57 cores
|
||||
|
||||
Errata workaround uses Env variable "a009635_interval_val". It uses decimal
|
||||
value.
|
||||
- Default value of env variable is platform clock (MHz)
|
||||
|
||||
- User can modify default value by updating the env variable
|
||||
setenv a009635_interval_val 600; saveenv;
|
||||
It configure platform clock as 600 MHz
|
||||
|
||||
- Env variable as 0 signifies no workaround
|
||||
129
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
Normal file
129
u-boot/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
Normal file
@@ -0,0 +1,129 @@
|
||||
SoC overview
|
||||
|
||||
1. LS1043A
|
||||
2. LS2080A
|
||||
3. LS1012A
|
||||
|
||||
LS1043A
|
||||
---------
|
||||
The LS1043A integrated multicore processor combines four ARM Cortex-A53
|
||||
processor cores with datapath acceleration optimized for L2/3 packet
|
||||
processing, single pass security offload and robust traffic management
|
||||
and quality of service.
|
||||
|
||||
The LS1043A SoC includes the following function and features:
|
||||
- Four 64-bit ARM Cortex-A53 CPUs
|
||||
- 1 MB unified L2 Cache
|
||||
- One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving
|
||||
support
|
||||
- Data Path Acceleration Architecture (DPAA) incorporating acceleration the
|
||||
the following functions:
|
||||
- Packet parsing, classification, and distribution (FMan)
|
||||
- Queue management for scheduling, packet sequencing, and congestion
|
||||
management (QMan)
|
||||
- Hardware buffer management for buffer allocation and de-allocation (BMan)
|
||||
- Cryptography acceleration (SEC)
|
||||
- Ethernet interfaces by FMan
|
||||
- Up to 1 x XFI supporting 10G interface
|
||||
- Up to 1 x QSGMII
|
||||
- Up to 4 x SGMII supporting 1000Mbps
|
||||
- Up to 2 x SGMII supporting 2500Mbps
|
||||
- Up to 2 x RGMII supporting 1000Mbps
|
||||
- High-speed peripheral interfaces
|
||||
- Three PCIe 2.0 controllers, one supporting x4 operation
|
||||
- One serial ATA (SATA 3.0) controllers
|
||||
- Additional peripheral interfaces
|
||||
- Three high-speed USB 3.0 controllers with integrated PHY
|
||||
- Enhanced secure digital host controller (eSDXC/eMMC)
|
||||
- Quad Serial Peripheral Interface (QSPI) Controller
|
||||
- Serial peripheral interface (SPI) controller
|
||||
- Four I2C controllers
|
||||
- Two DUARTs
|
||||
- Integrated flash controller supporting NAND and NOR flash
|
||||
- QorIQ platform's trust architecture 2.1
|
||||
|
||||
LS2080A
|
||||
--------
|
||||
The LS2080A integrated multicore processor combines eight ARM Cortex-A57
|
||||
processor cores with high-performance data path acceleration logic and network
|
||||
and peripheral bus interfaces required for networking, telecom/datacom,
|
||||
wireless infrastructure, and mil/aerospace applications.
|
||||
|
||||
The LS2080A SoC includes the following function and features:
|
||||
|
||||
- Eight 64-bit ARM Cortex-A57 CPUs
|
||||
- 1 MB platform cache with ECC
|
||||
- Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
|
||||
- One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
|
||||
the AIOP
|
||||
- Data path acceleration architecture (DPAA2) incorporating acceleration for
|
||||
the following functions:
|
||||
- Packet parsing, classification, and distribution (WRIOP)
|
||||
- Queue and Hardware buffer management for scheduling, packet sequencing, and
|
||||
congestion management, buffer allocation and de-allocation (QBMan)
|
||||
- Cryptography acceleration (SEC) at up to 10 Gbps
|
||||
- RegEx pattern matching acceleration (PME) at up to 10 Gbps
|
||||
- Decompression/compression acceleration (DCE) at up to 20 Gbps
|
||||
- Accelerated I/O processing (AIOP) at up to 20 Gbps
|
||||
- QDMA engine
|
||||
- 16 SerDes lanes at up to 10.3125 GHz
|
||||
- Ethernet interfaces
|
||||
- Up to eight 10 Gbps Ethernet MACs
|
||||
- Up to eight 1 / 2.5 Gbps Ethernet MACs
|
||||
- High-speed peripheral interfaces
|
||||
- Four PCIe 3.0 controllers, one supporting SR-IOV
|
||||
- Additional peripheral interfaces
|
||||
- Two serial ATA (SATA 3.0) controllers
|
||||
- Two high-speed USB 3.0 controllers with integrated PHY
|
||||
- Enhanced secure digital host controller (eSDXC/eMMC)
|
||||
- Serial peripheral interface (SPI) controller
|
||||
- Quad Serial Peripheral Interface (QSPI) Controller
|
||||
- Four I2C controllers
|
||||
- Two DUARTs
|
||||
- Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
|
||||
- Support for hardware virtualization and partitioning enforcement
|
||||
- QorIQ platform's trust architecture 3.0
|
||||
- Service processor (SP) provides pre-boot initialization and secure-boot
|
||||
capabilities
|
||||
|
||||
LS1012A
|
||||
--------
|
||||
The LS1012A features an advanced 64-bit ARM v8 Cortex-
|
||||
A53 processor, with 32 KB of parity protected L1-I cache,
|
||||
32 KB of ECC protected L1-D cache, as well as 256 KB of
|
||||
ECC protected L2 cache.
|
||||
|
||||
The LS1012A SoC includes the following function and features:
|
||||
- One 64-bit ARM v8 Cortex-A53 core with the following capabilities:
|
||||
- ARM v8 cryptography extensions
|
||||
- One 16-bit DDR3L SDRAM memory controller, Up to 1.0 GT/s, Supports
|
||||
16-/8-bit operation (no ECC support)
|
||||
- ARM core-link CCI-400 cache coherent interconnect
|
||||
- Packet Forwarding Engine (PFE)
|
||||
- Cryptography acceleration (SEC)
|
||||
- Ethernet interfaces supported by PFE:
|
||||
- One Configurable x3 SerDes:
|
||||
Two Serdes PLLs supported for usage by any SerDes data lane
|
||||
Support for up to 6 GBaud operation
|
||||
- High-speed peripheral interfaces:
|
||||
- One PCI Express Gen2 controller, supporting x1 operation
|
||||
- One serial ATA (SATA Gen 3.0) controller
|
||||
- One USB 3.0/2.0 controller with integrated PHY
|
||||
- One USB 2.0 controller with ULPI interface. .
|
||||
- Additional peripheral interfaces:
|
||||
- One quad serial peripheral interface (QuadSPI) controller
|
||||
- One serial peripheral interface (SPI) controller
|
||||
- Two enhanced secure digital host controllers
|
||||
- Two I2C controllers
|
||||
- One 16550 compliant DUART (two UART interfaces)
|
||||
- Two general purpose IOs (GPIO)
|
||||
- Two FlexTimers
|
||||
- Five synchronous audio interfaces (SAI)
|
||||
- Pre-boot loader (PBL) provides pre-boot initialization and RCW loading
|
||||
- Single-source clocking solution enabling generation of core, platform,
|
||||
DDR, SerDes, and USB clocks from a single external crystal and internal
|
||||
crystaloscillator
|
||||
- Thermal monitor unit (TMU) with +/- 3C accuracy
|
||||
- Two WatchDog timers
|
||||
- ARM generic timer
|
||||
- QorIQ platform's trust architecture 2.1
|
||||
120
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
Normal file
120
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include <phy.h>
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
#include <asm/arch/fdt.h>
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#include <fsl_esdhc.h>
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DPAA_FMAN
|
||||
#include <fsl_fman.h>
|
||||
#endif
|
||||
#ifdef CONFIG_MP
|
||||
#include <asm/arch/mp.h>
|
||||
#endif
|
||||
#include <fsl_sec.h>
|
||||
#include <asm/arch-fsl-layerscape/soc.h>
|
||||
|
||||
int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
|
||||
{
|
||||
return fdt_setprop_string(blob, offset, "phy-connection-type",
|
||||
phy_string_for_interface(phyc));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
void ft_fixup_cpu(void *blob)
|
||||
{
|
||||
int off;
|
||||
__maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr();
|
||||
fdt32_t *reg;
|
||||
int addr_cells;
|
||||
u64 val, core_id;
|
||||
size_t *boot_code_size = &(__secondary_boot_code_size);
|
||||
|
||||
off = fdt_path_offset(blob, "/cpus");
|
||||
if (off < 0) {
|
||||
puts("couldn't find /cpus node\n");
|
||||
return;
|
||||
}
|
||||
of_bus_default_count_cells(blob, off, &addr_cells, NULL);
|
||||
|
||||
off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
|
||||
while (off != -FDT_ERR_NOTFOUND) {
|
||||
reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
|
||||
if (reg) {
|
||||
core_id = of_read_number(reg, addr_cells);
|
||||
if (core_id == 0 || (is_core_online(core_id))) {
|
||||
val = spin_tbl_addr;
|
||||
val += id_to_core(core_id) *
|
||||
SPIN_TABLE_ELEM_SIZE;
|
||||
val = cpu_to_fdt64(val);
|
||||
fdt_setprop_string(blob, off, "enable-method",
|
||||
"spin-table");
|
||||
fdt_setprop(blob, off, "cpu-release-addr",
|
||||
&val, sizeof(val));
|
||||
} else {
|
||||
debug("skipping offline core\n");
|
||||
}
|
||||
} else {
|
||||
puts("Warning: found cpu node without reg property\n");
|
||||
}
|
||||
off = fdt_node_offset_by_prop_value(blob, off, "device_type",
|
||||
"cpu", 4);
|
||||
}
|
||||
|
||||
fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
|
||||
*boot_code_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ft_cpu_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
unsigned int svr = in_be32(&gur->svr);
|
||||
|
||||
/* delete crypto node if not on an E-processor */
|
||||
if (!IS_E_PROCESSOR(svr))
|
||||
fdt_fixup_crypto_node(blob, 0);
|
||||
#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
|
||||
else {
|
||||
ccsr_sec_t __iomem *sec;
|
||||
|
||||
sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
|
||||
fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
ft_fixup_cpu(blob);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_NS16550
|
||||
do_fixup_by_compat_u32(blob, "fsl,ns16550",
|
||||
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
|
||||
#endif
|
||||
|
||||
do_fixup_by_compat_u32(blob, "fixed-clock",
|
||||
"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
ft_pci_setup(blob, bd);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
fdt_fixup_esdhc(blob, bd);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_DPAA_FMAN
|
||||
fdt_fixup_fman_firmware(blob);
|
||||
#endif
|
||||
}
|
||||
117
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
Normal file
117
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
|
||||
#endif
|
||||
|
||||
int is_serdes_configured(enum srds_prtcl device)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
ret |= serdes1_prtcl_map[device];
|
||||
#endif
|
||||
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 cfg = gur_in32(&gur->rcwsr[4]);
|
||||
int i;
|
||||
|
||||
switch (sd) {
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
case FSL_SRDS_1:
|
||||
cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
|
||||
cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("invalid SerDes%d\n", sd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is serdes enabled at all? */
|
||||
if (unlikely(cfg == 0))
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < SRDS_MAX_LANES; i++) {
|
||||
if (serdes_get_prtcl(sd, cfg, i) == device)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int get_serdes_protocol(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 cfg = gur_in32(&gur->rcwsr[4]) &
|
||||
FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
|
||||
cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
const char *serdes_clock_to_string(u32 clock)
|
||||
{
|
||||
switch (clock) {
|
||||
case SRDS_PLLCR0_RFCK_SEL_100:
|
||||
return "100";
|
||||
case SRDS_PLLCR0_RFCK_SEL_125:
|
||||
return "125";
|
||||
case SRDS_PLLCR0_RFCK_SEL_156_25:
|
||||
return "156.25";
|
||||
default:
|
||||
return "100";
|
||||
}
|
||||
}
|
||||
|
||||
void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
|
||||
u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 cfg;
|
||||
int lane;
|
||||
|
||||
memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
|
||||
|
||||
cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
|
||||
cfg >>= sd_prctl_shift;
|
||||
printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
|
||||
|
||||
if (!is_serdes_prtcl_valid(sd, cfg))
|
||||
printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
|
||||
|
||||
for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
|
||||
enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
|
||||
|
||||
if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
|
||||
debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
|
||||
else
|
||||
serdes_prtcl_map[lane_prtcl] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void fsl_serdes_init(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
serdes_init(FSL_SRDS_1,
|
||||
CONFIG_SYS_FSL_SERDES_ADDR,
|
||||
FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
|
||||
FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
|
||||
serdes1_prtcl_map);
|
||||
#endif
|
||||
}
|
||||
200
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
Normal file
200
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include "cpu.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
|
||||
#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
|
||||
#endif
|
||||
|
||||
void get_sys_info(struct sys_info *sys_info)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
#ifdef CONFIG_FSL_IFC
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 ccr;
|
||||
#endif
|
||||
#if (defined(CONFIG_FSL_ESDHC) &&\
|
||||
defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\
|
||||
defined(CONFIG_SYS_DPAA_FMAN)
|
||||
|
||||
u32 rcw_tmp;
|
||||
#endif
|
||||
struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
|
||||
unsigned int cpu;
|
||||
const u8 core_cplx_pll[8] = {
|
||||
[0] = 0, /* CC1 PPL / 1 */
|
||||
[1] = 0, /* CC1 PPL / 2 */
|
||||
[4] = 1, /* CC2 PPL / 1 */
|
||||
[5] = 1, /* CC2 PPL / 2 */
|
||||
};
|
||||
|
||||
const u8 core_cplx_pll_div[8] = {
|
||||
[0] = 1, /* CC1 PPL / 1 */
|
||||
[1] = 2, /* CC1 PPL / 2 */
|
||||
[4] = 1, /* CC2 PPL / 1 */
|
||||
[5] = 2, /* CC2 PPL / 2 */
|
||||
};
|
||||
|
||||
uint i, cluster;
|
||||
uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||
uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||
unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
|
||||
|
||||
sys_info->freq_systembus = sysclk;
|
||||
#ifdef CONFIG_DDR_CLK_FREQ
|
||||
sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
|
||||
#else
|
||||
sys_info->freq_ddrbus = sysclk;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LS1012A
|
||||
sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
|
||||
#else
|
||||
sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
|
||||
sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
|
||||
ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
|
||||
if (ratio[i] > 4)
|
||||
freq_c_pll[i] = sysclk * ratio[i];
|
||||
else
|
||||
freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
|
||||
}
|
||||
|
||||
for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
|
||||
cluster = fsl_qoriq_core_to_cluster(cpu);
|
||||
u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27)
|
||||
& 0xf;
|
||||
u32 cplx_pll = core_cplx_pll[c_pll_sel];
|
||||
|
||||
sys_info->freq_processor[cpu] =
|
||||
freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LS1012A
|
||||
sys_info->freq_systembus = sys_info->freq_ddrbus / 2;
|
||||
sys_info->freq_ddrbus *= 2;
|
||||
#endif
|
||||
|
||||
#define HWA_CGA_M1_CLK_SEL 0xe0000000
|
||||
#define HWA_CGA_M1_CLK_SHIFT 29
|
||||
#ifdef CONFIG_SYS_DPAA_FMAN
|
||||
rcw_tmp = in_be32(&gur->rcwsr[7]);
|
||||
switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) {
|
||||
case 2:
|
||||
sys_info->freq_fman[0] = freq_c_pll[0] / 2;
|
||||
break;
|
||||
case 3:
|
||||
sys_info->freq_fman[0] = freq_c_pll[0] / 3;
|
||||
break;
|
||||
case 6:
|
||||
sys_info->freq_fman[0] = freq_c_pll[1] / 2;
|
||||
break;
|
||||
case 7:
|
||||
sys_info->freq_fman[0] = freq_c_pll[1] / 3;
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unknown FMan1 clock select!\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HWA_CGA_M2_CLK_SEL 0x00000007
|
||||
#define HWA_CGA_M2_CLK_SHIFT 0
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
|
||||
rcw_tmp = in_be32(&gur->rcwsr[15]);
|
||||
rcw_tmp = (rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT;
|
||||
sys_info->freq_sdhc = freq_c_pll[1] / rcw_tmp;
|
||||
#else
|
||||
sys_info->freq_sdhc = sys_info->freq_systembus;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FSL_IFC)
|
||||
ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr);
|
||||
ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
|
||||
|
||||
sys_info->freq_localbus = sys_info->freq_systembus / ccr;
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
struct sys_info sys_info;
|
||||
|
||||
get_sys_info(&sys_info);
|
||||
gd->cpu_clk = sys_info.freq_processor[0];
|
||||
gd->bus_clk = sys_info.freq_systembus;
|
||||
gd->mem_clk = sys_info.freq_ddrbus;
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
gd->arch.sdhc_clk = sys_info.freq_sdhc;
|
||||
#endif
|
||||
|
||||
if (gd->cpu_clk != 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
ulong get_ddr_freq(ulong dummy)
|
||||
{
|
||||
return gd->mem_clk;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
int get_sdhc_freq(ulong dummy)
|
||||
{
|
||||
return gd->arch.sdhc_clk;
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case MXC_I2C_CLK:
|
||||
return get_bus_freq(0);
|
||||
#if defined(CONFIG_FSL_ESDHC)
|
||||
case MXC_ESDHC_CLK:
|
||||
return get_sdhc_freq(0);
|
||||
#endif
|
||||
case MXC_DSPI_CLK:
|
||||
return get_bus_freq(0);
|
||||
case MXC_UART_CLK:
|
||||
return get_bus_freq(0);
|
||||
default:
|
||||
printf("Unsupported clock\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
167
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
Normal file
167
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <fsl-mc/ldpaa_wriop.h>
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_2
|
||||
static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
int xfi_dpmac[XFI8 + 1];
|
||||
int sgmii_dpmac[SGMII16 + 1];
|
||||
#endif
|
||||
|
||||
int is_serdes_configured(enum srds_prtcl device)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
ret |= serdes1_prtcl_map[device];
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_2
|
||||
ret |= serdes2_prtcl_map[device];
|
||||
#endif
|
||||
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 cfg = gur_in32(&gur->rcwsr[28]);
|
||||
int i;
|
||||
|
||||
switch (sd) {
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
case FSL_SRDS_1:
|
||||
cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
|
||||
cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_2
|
||||
case FSL_SRDS_2:
|
||||
cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
|
||||
cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("invalid SerDes%d\n", sd);
|
||||
break;
|
||||
}
|
||||
/* Is serdes enabled at all? */
|
||||
if (cfg == 0)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < SRDS_MAX_LANES; i++) {
|
||||
if (serdes_get_prtcl(sd, cfg, i) == device)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
|
||||
u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 cfg;
|
||||
int lane;
|
||||
|
||||
memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
|
||||
|
||||
cfg = gur_in32(&gur->rcwsr[28]) & sd_prctl_mask;
|
||||
cfg >>= sd_prctl_shift;
|
||||
printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
|
||||
|
||||
if (!is_serdes_prtcl_valid(sd, cfg))
|
||||
printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
|
||||
|
||||
for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
|
||||
enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
|
||||
if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
|
||||
debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
|
||||
else {
|
||||
serdes_prtcl_map[lane_prtcl] = 1;
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
switch (lane_prtcl) {
|
||||
case QSGMII_A:
|
||||
wriop_init_dpmac(sd, 5, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 6, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 7, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 8, (int)lane_prtcl);
|
||||
break;
|
||||
case QSGMII_B:
|
||||
wriop_init_dpmac(sd, 1, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 2, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 3, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 4, (int)lane_prtcl);
|
||||
break;
|
||||
case QSGMII_C:
|
||||
wriop_init_dpmac(sd, 13, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 14, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 15, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 16, (int)lane_prtcl);
|
||||
break;
|
||||
case QSGMII_D:
|
||||
wriop_init_dpmac(sd, 9, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 10, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 11, (int)lane_prtcl);
|
||||
wriop_init_dpmac(sd, 12, (int)lane_prtcl);
|
||||
break;
|
||||
default:
|
||||
if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
|
||||
wriop_init_dpmac(sd,
|
||||
xfi_dpmac[lane_prtcl],
|
||||
(int)lane_prtcl);
|
||||
|
||||
if (lane_prtcl >= SGMII1 &&
|
||||
lane_prtcl <= SGMII16)
|
||||
wriop_init_dpmac(sd, sgmii_dpmac[
|
||||
lane_prtcl],
|
||||
(int)lane_prtcl);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fsl_serdes_init(void)
|
||||
{
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
int i , j;
|
||||
|
||||
for (i = XFI1, j = 1; i <= XFI8; i++, j++)
|
||||
xfi_dpmac[i] = j;
|
||||
|
||||
for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
|
||||
sgmii_dpmac[i] = j;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_1
|
||||
serdes_init(FSL_SRDS_1,
|
||||
CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
|
||||
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK,
|
||||
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT,
|
||||
serdes1_prtcl_map);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_SRDS_2
|
||||
serdes_init(FSL_SRDS_2,
|
||||
CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
|
||||
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK,
|
||||
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT,
|
||||
serdes2_prtcl_map);
|
||||
#endif
|
||||
}
|
||||
204
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
Normal file
204
u-boot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2014-2015, Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Derived from arch/power/cpu/mpc85xx/speed.c
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch-fsl-layerscape/immap_lsch3.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include "cpu.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
|
||||
#define CONFIG_SYS_FSL_NUM_CC_PLLS 6
|
||||
#endif
|
||||
|
||||
|
||||
void get_sys_info(struct sys_info *sys_info)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
#ifdef CONFIG_FSL_IFC
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 ccr;
|
||||
#endif
|
||||
struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
|
||||
(void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
|
||||
(void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
|
||||
};
|
||||
struct ccsr_clk_ctrl __iomem *clk_ctrl =
|
||||
(void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
|
||||
unsigned int cpu;
|
||||
const u8 core_cplx_pll[16] = {
|
||||
[0] = 0, /* CC1 PPL / 1 */
|
||||
[1] = 0, /* CC1 PPL / 2 */
|
||||
[2] = 0, /* CC1 PPL / 4 */
|
||||
[4] = 1, /* CC2 PPL / 1 */
|
||||
[5] = 1, /* CC2 PPL / 2 */
|
||||
[6] = 1, /* CC2 PPL / 4 */
|
||||
[8] = 2, /* CC3 PPL / 1 */
|
||||
[9] = 2, /* CC3 PPL / 2 */
|
||||
[10] = 2, /* CC3 PPL / 4 */
|
||||
[12] = 3, /* CC4 PPL / 1 */
|
||||
[13] = 3, /* CC4 PPL / 2 */
|
||||
[14] = 3, /* CC4 PPL / 4 */
|
||||
};
|
||||
|
||||
const u8 core_cplx_pll_div[16] = {
|
||||
[0] = 1, /* CC1 PPL / 1 */
|
||||
[1] = 2, /* CC1 PPL / 2 */
|
||||
[2] = 4, /* CC1 PPL / 4 */
|
||||
[4] = 1, /* CC2 PPL / 1 */
|
||||
[5] = 2, /* CC2 PPL / 2 */
|
||||
[6] = 4, /* CC2 PPL / 4 */
|
||||
[8] = 1, /* CC3 PPL / 1 */
|
||||
[9] = 2, /* CC3 PPL / 2 */
|
||||
[10] = 4, /* CC3 PPL / 4 */
|
||||
[12] = 1, /* CC4 PPL / 1 */
|
||||
[13] = 2, /* CC4 PPL / 2 */
|
||||
[14] = 4, /* CC4 PPL / 4 */
|
||||
};
|
||||
|
||||
uint i, cluster;
|
||||
uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||
uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||
unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
|
||||
int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
|
||||
u32 c_pll_sel, cplx_pll;
|
||||
void *offset;
|
||||
|
||||
sys_info->freq_systembus = sysclk;
|
||||
#ifdef CONFIG_DDR_CLK_FREQ
|
||||
sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
|
||||
#endif
|
||||
#else
|
||||
sys_info->freq_ddrbus = sysclk;
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
sys_info->freq_ddrbus2 = sysclk;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
|
||||
/* Platform clock is half of platform PLL */
|
||||
sys_info->freq_systembus /= 2;
|
||||
sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
if (soc_has_dp_ddr()) {
|
||||
sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
|
||||
} else {
|
||||
sys_info->freq_ddrbus2 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
|
||||
/*
|
||||
* fixme: prefer to combine the following into one line, but
|
||||
* cannot pass compiling without warning about in_le32.
|
||||
*/
|
||||
offset = (void *)((size_t)clk_grp[i/3] +
|
||||
offsetof(struct ccsr_clk_cluster_group,
|
||||
pllngsr[i%3].gsr));
|
||||
ratio[i] = (in_le32(offset) >> 1) & 0x3f;
|
||||
freq_c_pll[i] = sysclk * ratio[i];
|
||||
}
|
||||
|
||||
for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
|
||||
cluster = fsl_qoriq_core_to_cluster(cpu);
|
||||
c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
|
||||
& 0xf;
|
||||
cplx_pll = core_cplx_pll[c_pll_sel];
|
||||
cplx_pll += cc_group[cluster] - 1;
|
||||
sys_info->freq_processor[cpu] =
|
||||
freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FSL_IFC)
|
||||
ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr);
|
||||
ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
|
||||
|
||||
sys_info->freq_localbus = sys_info->freq_systembus / ccr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
struct sys_info sys_info;
|
||||
get_sys_info(&sys_info);
|
||||
gd->cpu_clk = sys_info.freq_processor[0];
|
||||
gd->bus_clk = sys_info.freq_systembus;
|
||||
gd->mem_clk = sys_info.freq_ddrbus;
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
gd->arch.mem2_clk = sys_info.freq_ddrbus2;
|
||||
#endif
|
||||
#if defined(CONFIG_FSL_ESDHC)
|
||||
gd->arch.sdhc_clk = gd->bus_clk / 2;
|
||||
#endif /* defined(CONFIG_FSL_ESDHC) */
|
||||
|
||||
if (gd->cpu_clk != 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* get_bus_freq
|
||||
* return system bus freq in Hz
|
||||
*********************************************/
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
if (!gd->bus_clk)
|
||||
get_clocks();
|
||||
|
||||
return gd->bus_clk;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* get_ddr_freq
|
||||
* return ddr bus freq in Hz
|
||||
*********************************************/
|
||||
ulong get_ddr_freq(ulong ctrl_num)
|
||||
{
|
||||
if (!gd->mem_clk)
|
||||
get_clocks();
|
||||
|
||||
/*
|
||||
* DDR controller 0 & 1 are on memory complex 0
|
||||
* DDR controller 2 is on memory complext 1
|
||||
*/
|
||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||
if (ctrl_num >= 2)
|
||||
return gd->arch.mem2_clk;
|
||||
#endif
|
||||
|
||||
return gd->mem_clk;
|
||||
}
|
||||
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case MXC_I2C_CLK:
|
||||
return get_bus_freq(0) / 2;
|
||||
case MXC_DSPI_CLK:
|
||||
return get_bus_freq(0) / 2;
|
||||
default:
|
||||
printf("Unsupported clock\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
375
u-boot/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
Normal file
375
u-boot/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* (C) Copyright 2014-2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Extracted from armv8/start.S
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/macro.h>
|
||||
#ifdef CONFIG_MP
|
||||
#include <asm/arch/mp.h>
|
||||
#endif
|
||||
|
||||
ENTRY(lowlevel_init)
|
||||
mov x29, lr /* Save LR */
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
|
||||
/* Set Wuo bit for RN-I 20 */
|
||||
#ifdef CONFIG_LS2080A
|
||||
ldr x0, =CCI_AUX_CONTROL_BASE(20)
|
||||
ldr x1, =0x00000010
|
||||
bl ccn504_set_aux
|
||||
#endif
|
||||
|
||||
/* Add fully-coherent masters to DVM domain */
|
||||
ldr x0, =CCI_MN_BASE
|
||||
ldr x1, =CCI_MN_RNF_NODEID_LIST
|
||||
ldr x2, =CCI_MN_DVM_DOMAIN_CTL_SET
|
||||
bl ccn504_add_masters_to_dvm
|
||||
|
||||
/* Set all RN-I ports to QoS of 15 */
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(0)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(0)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(0)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(2)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(2)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(2)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(6)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(6)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(6)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(12)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(12)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(12)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(16)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(16)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(16)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
|
||||
ldr x0, =CCI_S0_QOS_CONTROL_BASE(20)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S1_QOS_CONTROL_BASE(20)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
ldr x0, =CCI_S2_QOS_CONTROL_BASE(20)
|
||||
ldr x1, =0x00FF000C
|
||||
bl ccn504_set_qos
|
||||
#endif
|
||||
|
||||
#ifdef SMMU_BASE
|
||||
/* Set the SMMU page size in the sACR register */
|
||||
ldr x1, =SMMU_BASE
|
||||
ldr w0, [x1, #0x10]
|
||||
orr w0, w0, #1 << 16 /* set sACR.pagesize to indicate 64K page */
|
||||
str w0, [x1, #0x10]
|
||||
#endif
|
||||
|
||||
/* Initialize GIC Secure Bank Status */
|
||||
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
|
||||
branch_if_slave x0, 1f
|
||||
ldr x0, =GICD_BASE
|
||||
bl gic_init_secure
|
||||
1:
|
||||
#ifdef CONFIG_GICV3
|
||||
ldr x0, =GICR_BASE
|
||||
bl gic_init_secure_percpu
|
||||
#elif defined(CONFIG_GICV2)
|
||||
ldr x0, =GICD_BASE
|
||||
ldr x1, =GICC_BASE
|
||||
bl gic_init_secure_percpu
|
||||
#endif
|
||||
#endif
|
||||
|
||||
branch_if_master x0, x1, 2f
|
||||
|
||||
#if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY)
|
||||
ldr x0, =secondary_boot_func
|
||||
blr x0
|
||||
#endif
|
||||
|
||||
2:
|
||||
#ifdef CONFIG_FSL_TZPC_BP147
|
||||
/* Set Non Secure access for all devices protected via TZPC */
|
||||
ldr x1, =TZPCDECPROT_0_SET_BASE /* Decode Protection-0 Set Reg */
|
||||
orr w0, w0, #1 << 3 /* DCFG_RESET is accessible from NS world */
|
||||
str w0, [x1]
|
||||
|
||||
isb
|
||||
dsb sy
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_TZASC_400
|
||||
/* Set TZASC so that:
|
||||
* a. We use only Region0 whose global secure write/read is EN
|
||||
* b. We use only Region0 whose NSAID write/read is EN
|
||||
*
|
||||
* NOTE: As per the CCSR map doc, TZASC 3 and TZASC 4 are just
|
||||
* placeholders.
|
||||
*/
|
||||
ldr x1, =TZASC_GATE_KEEPER(0)
|
||||
ldr x0, [x1] /* Filter 0 Gate Keeper Register */
|
||||
orr x0, x0, #1 << 0 /* Set open_request for Filter 0 */
|
||||
str x0, [x1]
|
||||
|
||||
ldr x1, =TZASC_GATE_KEEPER(1)
|
||||
ldr x0, [x1] /* Filter 0 Gate Keeper Register */
|
||||
orr x0, x0, #1 << 0 /* Set open_request for Filter 0 */
|
||||
str x0, [x1]
|
||||
|
||||
ldr x1, =TZASC_REGION_ATTRIBUTES_0(0)
|
||||
ldr x0, [x1] /* Region-0 Attributes Register */
|
||||
orr x0, x0, #1 << 31 /* Set Sec global write en, Bit[31] */
|
||||
orr x0, x0, #1 << 30 /* Set Sec global read en, Bit[30] */
|
||||
str x0, [x1]
|
||||
|
||||
ldr x1, =TZASC_REGION_ATTRIBUTES_0(1)
|
||||
ldr x0, [x1] /* Region-1 Attributes Register */
|
||||
orr x0, x0, #1 << 31 /* Set Sec global write en, Bit[31] */
|
||||
orr x0, x0, #1 << 30 /* Set Sec global read en, Bit[30] */
|
||||
str x0, [x1]
|
||||
|
||||
ldr x1, =TZASC_REGION_ID_ACCESS_0(0)
|
||||
ldr w0, [x1] /* Region-0 Access Register */
|
||||
mov w0, #0xFFFFFFFF /* Set nsaid_wr_en and nsaid_rd_en */
|
||||
str w0, [x1]
|
||||
|
||||
ldr x1, =TZASC_REGION_ID_ACCESS_0(1)
|
||||
ldr w0, [x1] /* Region-1 Attributes Register */
|
||||
mov w0, #0xFFFFFFFF /* Set nsaid_wr_en and nsaid_rd_en */
|
||||
str w0, [x1]
|
||||
|
||||
isb
|
||||
dsb sy
|
||||
#endif
|
||||
mov lr, x29 /* Restore LR */
|
||||
ret
|
||||
ENDPROC(lowlevel_init)
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
hnf_pstate_poll:
|
||||
/* x0 has the desired status, return 0 for success, 1 for timeout
|
||||
* clobber x1, x2, x3, x4, x6, x7
|
||||
*/
|
||||
mov x1, x0
|
||||
mov x7, #0 /* flag for timeout */
|
||||
mrs x3, cntpct_el0 /* read timer */
|
||||
add x3, x3, #1200 /* timeout after 100 microseconds */
|
||||
mov x0, #0x18
|
||||
movk x0, #0x420, lsl #16 /* HNF0_PSTATE_STATUS */
|
||||
mov w6, #8 /* HN-F node count */
|
||||
1:
|
||||
ldr x2, [x0]
|
||||
cmp x2, x1 /* check status */
|
||||
b.eq 2f
|
||||
mrs x4, cntpct_el0
|
||||
cmp x4, x3
|
||||
b.ls 1b
|
||||
mov x7, #1 /* timeout */
|
||||
b 3f
|
||||
2:
|
||||
add x0, x0, #0x10000 /* move to next node */
|
||||
subs w6, w6, #1
|
||||
cbnz w6, 1b
|
||||
3:
|
||||
mov x0, x7
|
||||
ret
|
||||
|
||||
hnf_set_pstate:
|
||||
/* x0 has the desired state, clobber x1, x2, x6 */
|
||||
mov x1, x0
|
||||
/* power state to SFONLY */
|
||||
mov w6, #8 /* HN-F node count */
|
||||
mov x0, #0x10
|
||||
movk x0, #0x420, lsl #16 /* HNF0_PSTATE_REQ */
|
||||
1: /* set pstate to sfonly */
|
||||
ldr x2, [x0]
|
||||
and x2, x2, #0xfffffffffffffffc /* & HNFPSTAT_MASK */
|
||||
orr x2, x2, x1
|
||||
str x2, [x0]
|
||||
add x0, x0, #0x10000 /* move to next node */
|
||||
subs w6, w6, #1
|
||||
cbnz w6, 1b
|
||||
|
||||
ret
|
||||
|
||||
ENTRY(__asm_flush_l3_cache)
|
||||
/*
|
||||
* Return status in x0
|
||||
* success 0
|
||||
* tmeout 1 for setting SFONLY, 2 for FAM, 3 for both
|
||||
*/
|
||||
mov x29, lr
|
||||
mov x8, #0
|
||||
|
||||
dsb sy
|
||||
mov x0, #0x1 /* HNFPSTAT_SFONLY */
|
||||
bl hnf_set_pstate
|
||||
|
||||
mov x0, #0x4 /* SFONLY status */
|
||||
bl hnf_pstate_poll
|
||||
cbz x0, 1f
|
||||
mov x8, #1 /* timeout */
|
||||
1:
|
||||
dsb sy
|
||||
mov x0, #0x3 /* HNFPSTAT_FAM */
|
||||
bl hnf_set_pstate
|
||||
|
||||
mov x0, #0xc /* FAM status */
|
||||
bl hnf_pstate_poll
|
||||
cbz x0, 1f
|
||||
add x8, x8, #0x2
|
||||
1:
|
||||
mov x0, x8
|
||||
mov lr, x29
|
||||
ret
|
||||
ENDPROC(__asm_flush_l3_cache)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
/* Keep literals not used by the secondary boot code outside it */
|
||||
.ltorg
|
||||
|
||||
/* Using 64 bit alignment since the spin table is accessed as data */
|
||||
.align 4
|
||||
.global secondary_boot_code
|
||||
/* Secondary Boot Code starts here */
|
||||
secondary_boot_code:
|
||||
.global __spin_table
|
||||
__spin_table:
|
||||
.space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE
|
||||
|
||||
.align 2
|
||||
ENTRY(secondary_boot_func)
|
||||
/*
|
||||
* MPIDR_EL1 Fields:
|
||||
* MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1)
|
||||
* MPIDR[7:2] = AFF0_RES
|
||||
* MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3)
|
||||
* MPIDR[23:16] = AFF2_CLUSTERID
|
||||
* MPIDR[24] = MT
|
||||
* MPIDR[29:25] = RES0
|
||||
* MPIDR[30] = U
|
||||
* MPIDR[31] = ME
|
||||
* MPIDR[39:32] = AFF3
|
||||
*
|
||||
* Linear Processor ID (LPID) calculation from MPIDR_EL1:
|
||||
* (We only use AFF0_CPUID and AFF1_CLUSTERID for now
|
||||
* until AFF2_CLUSTERID and AFF3 have non-zero values)
|
||||
*
|
||||
* LPID = MPIDR[15:8] | MPIDR[1:0]
|
||||
*/
|
||||
mrs x0, mpidr_el1
|
||||
ubfm x1, x0, #8, #15
|
||||
ubfm x2, x0, #0, #1
|
||||
orr x10, x2, x1, lsl #2 /* x10 has LPID */
|
||||
ubfm x9, x0, #0, #15 /* x9 contains MPIDR[15:0] */
|
||||
/*
|
||||
* offset of the spin table element for this core from start of spin
|
||||
* table (each elem is padded to 64 bytes)
|
||||
*/
|
||||
lsl x1, x10, #6
|
||||
ldr x0, =__spin_table
|
||||
/* physical address of this cpus spin table element */
|
||||
add x11, x1, x0
|
||||
|
||||
ldr x0, =__real_cntfrq
|
||||
ldr x0, [x0]
|
||||
msr cntfrq_el0, x0 /* set with real frequency */
|
||||
str x9, [x11, #16] /* LPID */
|
||||
mov x4, #1
|
||||
str x4, [x11, #8] /* STATUS */
|
||||
dsb sy
|
||||
#if defined(CONFIG_GICV3)
|
||||
gic_wait_for_interrupt_m x0
|
||||
#elif defined(CONFIG_GICV2)
|
||||
ldr x0, =GICC_BASE
|
||||
gic_wait_for_interrupt_m x0, w1
|
||||
#endif
|
||||
|
||||
bl secondary_switch_to_el2
|
||||
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
|
||||
bl secondary_switch_to_el1
|
||||
#endif
|
||||
|
||||
slave_cpu:
|
||||
wfe
|
||||
ldr x0, [x11]
|
||||
cbz x0, slave_cpu
|
||||
#ifndef CONFIG_ARMV8_SWITCH_TO_EL1
|
||||
mrs x1, sctlr_el2
|
||||
#else
|
||||
mrs x1, sctlr_el1
|
||||
#endif
|
||||
tbz x1, #25, cpu_is_le
|
||||
rev x0, x0 /* BE to LE conversion */
|
||||
cpu_is_le:
|
||||
br x0 /* branch to the given address */
|
||||
ENDPROC(secondary_boot_func)
|
||||
|
||||
ENTRY(secondary_switch_to_el2)
|
||||
switch_el x0, 1f, 0f, 0f
|
||||
0: ret
|
||||
1: armv8_switch_to_el2_m x0
|
||||
ENDPROC(secondary_switch_to_el2)
|
||||
|
||||
ENTRY(secondary_switch_to_el1)
|
||||
switch_el x0, 0f, 1f, 0f
|
||||
0: ret
|
||||
1: armv8_switch_to_el1_m x0, x1
|
||||
ENDPROC(secondary_switch_to_el1)
|
||||
|
||||
/* Ensure that the literals used by the secondary boot code are
|
||||
* assembled within it (this is required so that we can protect
|
||||
* this area with a single memreserve region
|
||||
*/
|
||||
.ltorg
|
||||
|
||||
/* 64 bit alignment for elements accessed as data */
|
||||
.align 4
|
||||
.global __real_cntfrq
|
||||
__real_cntfrq:
|
||||
.quad COUNTER_FREQUENCY
|
||||
.globl __secondary_boot_code_size
|
||||
.type __secondary_boot_code_size, %object
|
||||
/* Secondary Boot Code ends here */
|
||||
__secondary_boot_code_size:
|
||||
.quad .-secondary_boot_code
|
||||
#endif
|
||||
74
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
Normal file
74
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2016 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/immap_lsch2.h>
|
||||
|
||||
struct serdes_config {
|
||||
u32 protocol;
|
||||
u8 lanes[SRDS_MAX_LANES];
|
||||
};
|
||||
|
||||
static struct serdes_config serdes1_cfg_tbl[] = {
|
||||
{0x2208, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, SATA1} },
|
||||
{0x0008, {NONE, NONE, NONE, SATA1} },
|
||||
{0x3508, {SGMII_FM1_DTSEC1, PCIE1, NONE, SATA1} },
|
||||
{0x3305, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
|
||||
{0x2205, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, PCIE1} },
|
||||
{0x2305, {SGMII_2500_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
|
||||
{0x9508, {TX_CLK, PCIE1, NONE, SATA1} },
|
||||
{0x3905, {SGMII_FM1_DTSEC1, TX_CLK, NONE, PCIE1} },
|
||||
{0x9305, {TX_CLK, SGMII_FM1_DTSEC2, NONE, PCIE1} },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct serdes_config *serdes_cfg_tbl[] = {
|
||||
serdes1_cfg_tbl,
|
||||
};
|
||||
|
||||
enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
|
||||
{
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == cfg)
|
||||
return ptr->lanes[lane];
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_serdes_prtcl_valid(int serdes, u32 prtcl)
|
||||
{
|
||||
int i;
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == prtcl)
|
||||
break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (!ptr->protocol)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < SRDS_MAX_LANES; i++) {
|
||||
if (ptr->lanes[i] != NONE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
86
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c
Normal file
86
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/immap_lsch2.h>
|
||||
|
||||
struct serdes_config {
|
||||
u32 protocol;
|
||||
u8 lanes[SRDS_MAX_LANES];
|
||||
};
|
||||
|
||||
static struct serdes_config serdes1_cfg_tbl[] = {
|
||||
/* SerDes 1 */
|
||||
{0x1555, {XFI_FM1_MAC9, PCIE1, PCIE2, PCIE3} },
|
||||
{0x2555, {SGMII_2500_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} },
|
||||
{0x4555, {QSGMII_FM1_A, PCIE1, PCIE2, PCIE3} },
|
||||
{0x4558, {QSGMII_FM1_A, PCIE1, PCIE2, SATA1} },
|
||||
{0x1355, {XFI_FM1_MAC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
|
||||
{0x2355, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
|
||||
{0x3335, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5,
|
||||
PCIE3} },
|
||||
{0x3355, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
|
||||
{0x3358, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, SATA1} },
|
||||
{0x3555, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} },
|
||||
{0x3558, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, SATA1} },
|
||||
{0x7000, {PCIE1, PCIE1, PCIE1, PCIE1} },
|
||||
{0x9998, {PCIE1, PCIE2, PCIE3, SATA1} },
|
||||
{0x6058, {PCIE1, PCIE1, PCIE2, SATA1} },
|
||||
{0x1455, {XFI_FM1_MAC9, QSGMII_FM1_A, PCIE2, PCIE3} },
|
||||
{0x2455, {SGMII_2500_FM1_DTSEC9, QSGMII_FM1_A, PCIE2, PCIE3} },
|
||||
{0x2255, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC2, PCIE2, PCIE3} },
|
||||
{0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5,
|
||||
SGMII_FM1_DTSEC6} },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct serdes_config *serdes_cfg_tbl[] = {
|
||||
serdes1_cfg_tbl,
|
||||
};
|
||||
|
||||
enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
|
||||
{
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == cfg)
|
||||
return ptr->lanes[lane];
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_serdes_prtcl_valid(int serdes, u32 prtcl)
|
||||
{
|
||||
int i;
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == prtcl)
|
||||
break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (!ptr->protocol)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < SRDS_MAX_LANES; i++) {
|
||||
if (ptr->lanes[i] != NONE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
116
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c
Normal file
116
u-boot/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
|
||||
struct serdes_config {
|
||||
u8 protocol;
|
||||
u8 lanes[SRDS_MAX_LANES];
|
||||
};
|
||||
|
||||
static struct serdes_config serdes1_cfg_tbl[] = {
|
||||
/* SerDes 1 */
|
||||
{0x03, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
|
||||
{0x05, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII4, SGMII3, SGMII2, SGMII1 } },
|
||||
{0x07, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
|
||||
SGMII1 } },
|
||||
{0x09, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
|
||||
SGMII1 } },
|
||||
{0x0A, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
|
||||
SGMII1 } },
|
||||
{0x0C, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
|
||||
SGMII1 } },
|
||||
{0x0E, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
|
||||
SGMII1 } },
|
||||
{0x26, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, XFI2, XFI1 } },
|
||||
{0x28, {SGMII8, SGMII7, SGMII6, SGMII5, XFI4, XFI3, XFI2, XFI1 } },
|
||||
{0x2A, {XFI8, XFI7, XFI6, XFI5, XFI4, XFI3, XFI2, XFI1 } },
|
||||
{0x2B, {SGMII8, SGMII7, SGMII6, SGMII5, XAUI1, XAUI1, XAUI1, XAUI1 } },
|
||||
{0x32, {XAUI2, XAUI2, XAUI2, XAUI2, XAUI1, XAUI1, XAUI1, XAUI1 } },
|
||||
{0x33, {PCIE2, PCIE2, PCIE2, PCIE2, QSGMII_D, QSGMII_C, QSGMII_B,
|
||||
QSGMII_A} },
|
||||
{0x35, {QSGMII_D, QSGMII_C, QSGMII_B, PCIE2, XFI4, XFI3, XFI2, XFI1 } },
|
||||
{}
|
||||
};
|
||||
static struct serdes_config serdes2_cfg_tbl[] = {
|
||||
/* SerDes 2 */
|
||||
{0x07, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x09, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x0A, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x0C, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x0E, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x3D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
|
||||
{0x3E, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
|
||||
{0x3F, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
|
||||
{0x40, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
|
||||
{0x41, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
|
||||
{0x42, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
|
||||
{0x43, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
|
||||
{0x44, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
|
||||
{0x45, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4,
|
||||
PCIE4 } },
|
||||
{0x47, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x49, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
|
||||
SATA2 } },
|
||||
{0x4A, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
|
||||
SATA2 } },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct serdes_config *serdes_cfg_tbl[] = {
|
||||
serdes1_cfg_tbl,
|
||||
serdes2_cfg_tbl,
|
||||
};
|
||||
|
||||
enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
|
||||
{
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == cfg)
|
||||
return ptr->lanes[lane];
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_serdes_prtcl_valid(int serdes, u32 prtcl)
|
||||
{
|
||||
int i;
|
||||
struct serdes_config *ptr;
|
||||
|
||||
if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
|
||||
return 0;
|
||||
|
||||
ptr = serdes_cfg_tbl[serdes];
|
||||
while (ptr->protocol) {
|
||||
if (ptr->protocol == prtcl)
|
||||
break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (!ptr->protocol)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < SRDS_MAX_LANES; i++) {
|
||||
if (ptr->lanes[i] != NONE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
203
u-boot/arch/arm/cpu/armv8/fsl-layerscape/mp.c
Normal file
203
u-boot/arch/arm/cpu/armv8/fsl-layerscape/mp.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/mp.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void *get_spin_tbl_addr(void)
|
||||
{
|
||||
return &__spin_table;
|
||||
}
|
||||
|
||||
phys_addr_t determine_mp_bootpg(void)
|
||||
{
|
||||
return (phys_addr_t)&secondary_boot_code;
|
||||
}
|
||||
|
||||
int fsl_layerscape_wake_seconday_cores(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
struct ccsr_reset __iomem *rst = (void *)(CONFIG_SYS_FSL_RST_ADDR);
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
|
||||
#endif
|
||||
u32 cores, cpu_up_mask = 1;
|
||||
int i, timeout = 10;
|
||||
u64 *table = get_spin_tbl_addr();
|
||||
|
||||
#ifdef COUNTER_FREQUENCY_REAL
|
||||
/* update for secondary cores */
|
||||
__real_cntfrq = COUNTER_FREQUENCY_REAL;
|
||||
flush_dcache_range((unsigned long)&__real_cntfrq,
|
||||
(unsigned long)&__real_cntfrq + 8);
|
||||
#endif
|
||||
|
||||
cores = cpu_mask();
|
||||
/* Clear spin table so that secondary processors
|
||||
* observe the correct value after waking up from wfe.
|
||||
*/
|
||||
memset(table, 0, CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE);
|
||||
flush_dcache_range((unsigned long)table,
|
||||
(unsigned long)table +
|
||||
(CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE));
|
||||
|
||||
printf("Waking secondary cores to start from %lx\n", gd->relocaddr);
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
gur_out32(&gur->bootlocptrh, (u32)(gd->relocaddr >> 32));
|
||||
gur_out32(&gur->bootlocptrl, (u32)gd->relocaddr);
|
||||
gur_out32(&gur->scratchrw[6], 1);
|
||||
asm volatile("dsb st" : : : "memory");
|
||||
rst->brrl = cores;
|
||||
asm volatile("dsb st" : : : "memory");
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
scfg_out32(&scfg->scratchrw[0], (u32)(gd->relocaddr >> 32));
|
||||
scfg_out32(&scfg->scratchrw[1], (u32)gd->relocaddr);
|
||||
asm volatile("dsb st" : : : "memory");
|
||||
gur_out32(&gur->brrl, cores);
|
||||
asm volatile("dsb st" : : : "memory");
|
||||
|
||||
/* Bootup online cores */
|
||||
scfg_out32(&scfg->corebcr, cores);
|
||||
#endif
|
||||
/* This is needed as a precautionary measure.
|
||||
* If some code before this has accidentally released the secondary
|
||||
* cores then the pre-bootloader code will trap them in a "wfe" unless
|
||||
* the scratchrw[6] is set. In this case we need a sev here to get these
|
||||
* cores moving again.
|
||||
*/
|
||||
asm volatile("sev");
|
||||
|
||||
while (timeout--) {
|
||||
flush_dcache_range((unsigned long)table, (unsigned long)table +
|
||||
CONFIG_MAX_CPUS * 64);
|
||||
for (i = 1; i < CONFIG_MAX_CPUS; i++) {
|
||||
if (table[i * WORDS_PER_SPIN_TABLE_ENTRY +
|
||||
SPIN_TABLE_ELEM_STATUS_IDX])
|
||||
cpu_up_mask |= 1 << i;
|
||||
}
|
||||
if (hweight32(cpu_up_mask) == hweight32(cores))
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
printf("Not all cores (0x%x) are up (0x%x)\n",
|
||||
cores, cpu_up_mask);
|
||||
return 1;
|
||||
}
|
||||
printf("All (%d) cores are up.\n", hweight32(cores));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_core_valid(unsigned int core)
|
||||
{
|
||||
return !!((1 << core) & cpu_mask());
|
||||
}
|
||||
|
||||
int is_core_online(u64 cpu_id)
|
||||
{
|
||||
u64 *table;
|
||||
int pos = id_to_core(cpu_id);
|
||||
table = (u64 *)get_spin_tbl_addr() + pos * WORDS_PER_SPIN_TABLE_ENTRY;
|
||||
return table[SPIN_TABLE_ELEM_STATUS_IDX] == 1;
|
||||
}
|
||||
|
||||
int cpu_reset(int nr)
|
||||
{
|
||||
puts("Feature is not implemented.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_disable(int nr)
|
||||
{
|
||||
puts("Feature is not implemented.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int core_to_pos(int nr)
|
||||
{
|
||||
u32 cores = cpu_mask();
|
||||
int i, count = 0;
|
||||
|
||||
if (nr == 0) {
|
||||
return 0;
|
||||
} else if (nr >= hweight32(cores)) {
|
||||
puts("Not a valid core number.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i < 32; i++) {
|
||||
if (is_core_valid(i)) {
|
||||
count++;
|
||||
if (count == nr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int cpu_status(int nr)
|
||||
{
|
||||
u64 *table;
|
||||
int pos;
|
||||
|
||||
if (nr == 0) {
|
||||
table = (u64 *)get_spin_tbl_addr();
|
||||
printf("table base @ 0x%p\n", table);
|
||||
} else {
|
||||
pos = core_to_pos(nr);
|
||||
if (pos < 0)
|
||||
return -1;
|
||||
table = (u64 *)get_spin_tbl_addr() + pos *
|
||||
WORDS_PER_SPIN_TABLE_ENTRY;
|
||||
printf("table @ 0x%p\n", table);
|
||||
printf(" addr - 0x%016llx\n",
|
||||
table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX]);
|
||||
printf(" status - 0x%016llx\n",
|
||||
table[SPIN_TABLE_ELEM_STATUS_IDX]);
|
||||
printf(" lpid - 0x%016llx\n",
|
||||
table[SPIN_TABLE_ELEM_LPID_IDX]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_release(int nr, int argc, char * const argv[])
|
||||
{
|
||||
u64 boot_addr;
|
||||
u64 *table = (u64 *)get_spin_tbl_addr();
|
||||
int pos;
|
||||
|
||||
pos = core_to_pos(nr);
|
||||
if (pos <= 0)
|
||||
return -1;
|
||||
|
||||
table += pos * WORDS_PER_SPIN_TABLE_ENTRY;
|
||||
boot_addr = simple_strtoull(argv[0], NULL, 16);
|
||||
table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX] = boot_addr;
|
||||
flush_dcache_range((unsigned long)table,
|
||||
(unsigned long)table + SPIN_TABLE_ELEM_SIZE);
|
||||
asm volatile("dsb st");
|
||||
smp_kick_all_cpus(); /* only those with entry addr set will run */
|
||||
/*
|
||||
* When the first release command runs, all cores are set to go. Those
|
||||
* without a valid entry address will be trapped by "wfe". "sev" kicks
|
||||
* them off to check the address again. When set, they continue to run.
|
||||
*/
|
||||
asm volatile("sev");
|
||||
|
||||
return 0;
|
||||
}
|
||||
343
u-boot/arch/arm/cpu/armv8/fsl-layerscape/soc.c
Normal file
343
u-boot/arch/arm/cpu/armv8/fsl-layerscape/soc.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <ahci.h>
|
||||
#include <scsi.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/arch-fsl-layerscape/config.h>
|
||||
#ifdef CONFIG_SYS_FSL_DDR
|
||||
#include <fsl_ddr_sdram.h>
|
||||
#include <fsl_ddr.h>
|
||||
#endif
|
||||
#ifdef CONFIG_CHAIN_OF_TRUST
|
||||
#include <fsl_validate.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
bool soc_has_dp_ddr(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 svr = gur_in32(&gur->svr);
|
||||
|
||||
/* LS2085A has DP_DDR */
|
||||
if (SVR_SOC_VER(svr) == SVR_LS2085A)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool soc_has_aiop(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 svr = gur_in32(&gur->svr);
|
||||
|
||||
/* LS2085A has AIOP */
|
||||
if (SVR_SOC_VER(svr) == SVR_LS2085A)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LS2080A
|
||||
/*
|
||||
* This erratum requires setting a value to eddrtqcr1 to
|
||||
* optimal the DDR performance.
|
||||
*/
|
||||
static void erratum_a008336(void)
|
||||
{
|
||||
u32 *eddrtqcr1;
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008336
|
||||
#ifdef CONFIG_SYS_FSL_DCSR_DDR_ADDR
|
||||
eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR_ADDR + 0x800;
|
||||
out_le32(eddrtqcr1, 0x63b30002);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_DCSR_DDR2_ADDR
|
||||
eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR2_ADDR + 0x800;
|
||||
out_le32(eddrtqcr1, 0x63b30002);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This erratum requires a register write before being Memory
|
||||
* controller 3 being enabled.
|
||||
*/
|
||||
static void erratum_a008514(void)
|
||||
{
|
||||
u32 *eddrtqcr1;
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008514
|
||||
#ifdef CONFIG_SYS_FSL_DCSR_DDR3_ADDR
|
||||
eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR3_ADDR + 0x800;
|
||||
out_le32(eddrtqcr1, 0x63b20002);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
|
||||
#define PLATFORM_CYCLE_ENV_VAR "a009635_interval_val"
|
||||
|
||||
static unsigned long get_internval_val_mhz(void)
|
||||
{
|
||||
char *interval = getenv(PLATFORM_CYCLE_ENV_VAR);
|
||||
/*
|
||||
* interval is the number of platform cycles(MHz) between
|
||||
* wake up events generated by EPU.
|
||||
*/
|
||||
ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
|
||||
|
||||
if (interval)
|
||||
interval_mhz = simple_strtoul(interval, NULL, 10);
|
||||
|
||||
return interval_mhz;
|
||||
}
|
||||
|
||||
void erratum_a009635(void)
|
||||
{
|
||||
u32 val;
|
||||
unsigned long interval_mhz = get_internval_val_mhz();
|
||||
|
||||
if (!interval_mhz)
|
||||
return;
|
||||
|
||||
val = in_le32(DCSR_CGACRE5);
|
||||
writel(val | 0x00000200, DCSR_CGACRE5);
|
||||
|
||||
val = in_le32(EPU_EPCMPR5);
|
||||
writel(interval_mhz, EPU_EPCMPR5);
|
||||
val = in_le32(EPU_EPCCR5);
|
||||
writel(val | 0x82820000, EPU_EPCCR5);
|
||||
val = in_le32(EPU_EPSMCR5);
|
||||
writel(val | 0x002f0000, EPU_EPSMCR5);
|
||||
val = in_le32(EPU_EPECR5);
|
||||
writel(val | 0x20000000, EPU_EPECR5);
|
||||
val = in_le32(EPU_EPGCR);
|
||||
writel(val | 0x80000000, EPU_EPGCR);
|
||||
}
|
||||
#endif /* CONFIG_SYS_FSL_ERRATUM_A009635 */
|
||||
|
||||
static void erratum_rcw_src(void)
|
||||
{
|
||||
#if defined(CONFIG_SPL)
|
||||
u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
|
||||
u32 __iomem *dcfg_dcsr = (u32 __iomem *)DCFG_DCSR_BASE;
|
||||
u32 val;
|
||||
|
||||
val = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4);
|
||||
val &= ~DCFG_PORSR1_RCW_SRC;
|
||||
val |= DCFG_PORSR1_RCW_SRC_NOR;
|
||||
out_le32(dcfg_dcsr + DCFG_DCSR_PORCR1 / 4, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define I2C_DEBUG_REG 0x6
|
||||
#define I2C_GLITCH_EN 0x8
|
||||
/*
|
||||
* This erratum requires setting glitch_en bit to enable
|
||||
* digital glitch filter to improve clock stability.
|
||||
*/
|
||||
static void erratum_a009203(void)
|
||||
{
|
||||
u8 __iomem *ptr;
|
||||
#ifdef CONFIG_SYS_I2C
|
||||
#ifdef I2C1_BASE_ADDR
|
||||
ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG);
|
||||
|
||||
writeb(I2C_GLITCH_EN, ptr);
|
||||
#endif
|
||||
#ifdef I2C2_BASE_ADDR
|
||||
ptr = (u8 __iomem *)(I2C2_BASE_ADDR + I2C_DEBUG_REG);
|
||||
|
||||
writeb(I2C_GLITCH_EN, ptr);
|
||||
#endif
|
||||
#ifdef I2C3_BASE_ADDR
|
||||
ptr = (u8 __iomem *)(I2C3_BASE_ADDR + I2C_DEBUG_REG);
|
||||
|
||||
writeb(I2C_GLITCH_EN, ptr);
|
||||
#endif
|
||||
#ifdef I2C4_BASE_ADDR
|
||||
ptr = (u8 __iomem *)(I2C4_BASE_ADDR + I2C_DEBUG_REG);
|
||||
|
||||
writeb(I2C_GLITCH_EN, ptr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
void bypass_smmu(void)
|
||||
{
|
||||
u32 val;
|
||||
val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
|
||||
out_le32(SMMU_SCR0, val);
|
||||
val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
|
||||
out_le32(SMMU_NSCR0, val);
|
||||
}
|
||||
void fsl_lsch3_early_init_f(void)
|
||||
{
|
||||
erratum_rcw_src();
|
||||
init_early_memctl_regs(); /* tighten IFC timing */
|
||||
erratum_a009203();
|
||||
erratum_a008514();
|
||||
erratum_a008336();
|
||||
#ifdef CONFIG_CHAIN_OF_TRUST
|
||||
/* In case of Secure Boot, the IBR configures the SMMU
|
||||
* to allow only Secure transactions.
|
||||
* SMMU must be reset in bypass mode.
|
||||
* Set the ClientPD bit and Clear the USFCFG Bit
|
||||
*/
|
||||
if (fsl_check_boot_mode_secure() == 1)
|
||||
bypass_smmu();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_AHCI_PLAT
|
||||
int sata_init(void)
|
||||
{
|
||||
struct ccsr_ahci __iomem *ccsr_ahci;
|
||||
|
||||
ccsr_ahci = (void *)CONFIG_SYS_SATA2;
|
||||
out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG);
|
||||
out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG);
|
||||
|
||||
ccsr_ahci = (void *)CONFIG_SYS_SATA1;
|
||||
out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG);
|
||||
out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG);
|
||||
|
||||
ahci_init((void __iomem *)CONFIG_SYS_SATA1);
|
||||
scsi_scan(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
#ifdef CONFIG_SCSI_AHCI_PLAT
|
||||
int sata_init(void)
|
||||
{
|
||||
struct ccsr_ahci __iomem *ccsr_ahci = (void *)CONFIG_SYS_SATA;
|
||||
|
||||
out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG);
|
||||
out_le32(&ccsr_ahci->pp2c, AHCI_PORT_PHY_2_CFG);
|
||||
out_le32(&ccsr_ahci->pp3c, AHCI_PORT_PHY_3_CFG);
|
||||
out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG);
|
||||
|
||||
ahci_init((void __iomem *)CONFIG_SYS_SATA);
|
||||
scsi_scan(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void erratum_a009929(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A009929
|
||||
struct ccsr_gur *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
u32 __iomem *dcsr_cop_ccp = (void *)CONFIG_SYS_DCSR_COP_CCP_ADDR;
|
||||
u32 rstrqmr1 = gur_in32(&gur->rstrqmr1);
|
||||
|
||||
rstrqmr1 |= 0x00000400;
|
||||
gur_out32(&gur->rstrqmr1, rstrqmr1);
|
||||
writel(0x01000000, dcsr_cop_ccp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This erratum requires setting a value to eddrtqcr1 to optimal
|
||||
* the DDR performance. The eddrtqcr1 register is in SCFG space
|
||||
* of LS1043A and the offset is 0x157_020c.
|
||||
*/
|
||||
#if defined(CONFIG_SYS_FSL_ERRATUM_A009660) \
|
||||
&& defined(CONFIG_SYS_FSL_ERRATUM_A008514)
|
||||
#error A009660 and A008514 can not be both enabled.
|
||||
#endif
|
||||
|
||||
static void erratum_a009660(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A009660
|
||||
u32 *eddrtqcr1 = (void *)CONFIG_SYS_FSL_SCFG_ADDR + 0x20c;
|
||||
out_be32(eddrtqcr1, 0x63b20042);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void erratum_a008850_early(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
|
||||
/* part 1 of 2 */
|
||||
struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR;
|
||||
struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
|
||||
|
||||
/* disables propagation of barrier transactions to DDRC from CCI400 */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
|
||||
|
||||
/* disable the re-ordering in DDRC */
|
||||
ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
|
||||
#endif
|
||||
}
|
||||
|
||||
void erratum_a008850_post(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
|
||||
/* part 2 of 2 */
|
||||
struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR;
|
||||
struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
|
||||
u32 tmp;
|
||||
|
||||
/* enable propagation of barrier transactions to DDRC from CCI400 */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
|
||||
|
||||
/* enable the re-ordering in DDRC */
|
||||
tmp = ddr_in32(&ddr->eor);
|
||||
tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
|
||||
ddr_out32(&ddr->eor, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fsl_lsch2_early_init_f(void)
|
||||
{
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
|
||||
#ifdef CONFIG_FSL_IFC
|
||||
init_early_memctl_regs(); /* tighten IFC timing */
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FSL_QSPI) && !defined(CONFIG_QSPI_BOOT)
|
||||
out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL);
|
||||
#endif
|
||||
/* Make SEC reads and writes snoopable */
|
||||
setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SECRDSNP |
|
||||
SCFG_SNPCNFGCR_SECWRSNP);
|
||||
|
||||
/*
|
||||
* Enable snoop requests and DVM message requests for
|
||||
* Slave insterface S4 (A53 core cluster)
|
||||
*/
|
||||
out_le32(&cci->slave[4].snoop_ctrl,
|
||||
CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
|
||||
|
||||
/* Erratum */
|
||||
erratum_a008850_early(); /* part 1 of 2 */
|
||||
erratum_a009929();
|
||||
erratum_a009660();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
int board_late_init(void)
|
||||
{
|
||||
#ifdef CONFIG_SCSI_AHCI_PLAT
|
||||
sata_init();
|
||||
#endif
|
||||
#ifdef CONFIG_CHAIN_OF_TRUST
|
||||
fsl_setenv_chain_of_trust();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
74
u-boot/arch/arm/cpu/armv8/fsl-layerscape/spl.c
Normal file
74
u-boot/arch/arm/cpu/armv8/fsl-layerscape/spl.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <fsl_csu.h>
|
||||
#include <i2c.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||
return BOOT_DEVICE_MMC1;
|
||||
#endif
|
||||
#ifdef CONFIG_SPL_NAND_SUPPORT
|
||||
return BOOT_DEVICE_NAND;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 spl_boot_mode(const u32 boot_device)
|
||||
{
|
||||
switch (spl_boot_device()) {
|
||||
case BOOT_DEVICE_MMC1:
|
||||
#ifdef CONFIG_SPL_FAT_SUPPORT
|
||||
return MMCSD_MODE_FS;
|
||||
#else
|
||||
return MMCSD_MODE_RAW;
|
||||
#endif
|
||||
case BOOT_DEVICE_NAND:
|
||||
return 0;
|
||||
default:
|
||||
puts("spl: error: unsupported device\n");
|
||||
hang();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
/* Clear global data */
|
||||
memset((void *)gd, 0, sizeof(gd_t));
|
||||
#ifdef CONFIG_LS2080A
|
||||
arch_cpu_init();
|
||||
#endif
|
||||
board_early_init_f();
|
||||
timer_init();
|
||||
#ifdef CONFIG_LS2080A
|
||||
env_init();
|
||||
#endif
|
||||
get_clocks();
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
#ifdef CONFIG_SPL_I2C_SUPPORT
|
||||
i2c_init_all();
|
||||
#endif
|
||||
dram_init();
|
||||
|
||||
/* Clear the BSS */
|
||||
memset(__bss_start, 0, __bss_end - __bss_start);
|
||||
|
||||
#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
|
||||
enable_layerscape_ns_access();
|
||||
#endif
|
||||
board_init_r(NULL, 0);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user