diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/powerpc/cpu/mpc8xxx | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/powerpc/cpu/mpc8xxx')
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/Makefile | 27 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/cpu.c | 375 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/fdt.c | 162 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c | 156 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c | 442 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/law.c | 356 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/pamu_table.c | 64 | ||||
-rw-r--r-- | roms/u-boot/arch/powerpc/cpu/mpc8xxx/srio.c | 448 |
8 files changed, 2030 insertions, 0 deletions
diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/Makefile b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/Makefile new file mode 100644 index 000000000..bec891d54 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/Makefile @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2009-2010 Freescale Semiconductor, Inc. + +MINIMAL= + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_SPL_INIT_MINIMAL +MINIMAL=y +endif +endif + +ifdef MINIMAL + +obj-$(CONFIG_FSL_LAW) += law.o + +else +obj-$(CONFIG_MPC85xx) += cpu.o +obj-$(CONFIG_MPC86xx) += cpu.o + +obj-$(CONFIG_OF_LIBFDT) += fdt.o +obj-$(CONFIG_FSL_LBC) += fsl_lbc.o +obj-$(CONFIG_SYS_SRIO) += srio.o +obj-$(CONFIG_FSL_LAW) += law.o +obj-$(CONFIG_FSL_CORENET) += fsl_pamu.o pamu_table.o + +endif diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/cpu.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/cpu.c new file mode 100644 index 000000000..eda64861e --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/cpu.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2009-2012 Freescale Semiconductor, Inc. + * + * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and + * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains + * cpu specific common code for 85xx/86xx processors. + */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <cpu_func.h> +#include <init.h> +#include <net.h> +#include <tsec.h> +#include <fm_eth.h> +#include <netdev.h> +#include <asm/cache.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <vsc9953.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct cpu_type cpu_type_list[] = { +#if defined(CONFIG_MPC85xx) + CPU_TYPE_ENTRY(8533, 8533, 1), + CPU_TYPE_ENTRY(8535, 8535, 1), + CPU_TYPE_ENTRY(8536, 8536, 1), + CPU_TYPE_ENTRY(8540, 8540, 1), + CPU_TYPE_ENTRY(8541, 8541, 1), + CPU_TYPE_ENTRY(8543, 8543, 1), + CPU_TYPE_ENTRY(8544, 8544, 1), + CPU_TYPE_ENTRY(8545, 8545, 1), + CPU_TYPE_ENTRY(8547, 8547, 1), + CPU_TYPE_ENTRY(8548, 8548, 1), + CPU_TYPE_ENTRY(8555, 8555, 1), + CPU_TYPE_ENTRY(8560, 8560, 1), + CPU_TYPE_ENTRY(8567, 8567, 1), + CPU_TYPE_ENTRY(8568, 8568, 1), + CPU_TYPE_ENTRY(8569, 8569, 1), + CPU_TYPE_ENTRY(8572, 8572, 2), + CPU_TYPE_ENTRY(P1010, P1010, 1), + CPU_TYPE_ENTRY(P1011, P1011, 1), + CPU_TYPE_ENTRY(P1012, P1012, 1), + CPU_TYPE_ENTRY(P1013, P1013, 1), + CPU_TYPE_ENTRY(P1014, P1014, 1), + CPU_TYPE_ENTRY(P1017, P1017, 1), + CPU_TYPE_ENTRY(P1020, P1020, 2), + CPU_TYPE_ENTRY(P1021, P1021, 2), + CPU_TYPE_ENTRY(P1022, P1022, 2), + CPU_TYPE_ENTRY(P1023, P1023, 2), + CPU_TYPE_ENTRY(P1024, P1024, 2), + CPU_TYPE_ENTRY(P1025, P1025, 2), + CPU_TYPE_ENTRY(P2010, P2010, 1), + CPU_TYPE_ENTRY(P2020, P2020, 2), + CPU_TYPE_ENTRY(P2040, P2040, 4), + CPU_TYPE_ENTRY(P2041, P2041, 4), + CPU_TYPE_ENTRY(P3041, P3041, 4), + CPU_TYPE_ENTRY(P4040, P4040, 4), + CPU_TYPE_ENTRY(P4080, P4080, 8), + CPU_TYPE_ENTRY(P5010, P5010, 1), + CPU_TYPE_ENTRY(P5020, P5020, 2), + CPU_TYPE_ENTRY(P5021, P5021, 2), + CPU_TYPE_ENTRY(P5040, P5040, 4), + CPU_TYPE_ENTRY(T4240, T4240, 0), + CPU_TYPE_ENTRY(T4120, T4120, 0), + CPU_TYPE_ENTRY(T4160, T4160, 0), + CPU_TYPE_ENTRY(T4080, T4080, 4), + CPU_TYPE_ENTRY(B4860, B4860, 0), + CPU_TYPE_ENTRY(G4860, G4860, 0), + CPU_TYPE_ENTRY(B4440, B4440, 0), + CPU_TYPE_ENTRY(B4460, B4460, 0), + CPU_TYPE_ENTRY(G4440, G4440, 0), + CPU_TYPE_ENTRY(B4420, B4420, 0), + CPU_TYPE_ENTRY(B4220, B4220, 0), + CPU_TYPE_ENTRY(T1040, T1040, 0), + CPU_TYPE_ENTRY(T1041, T1041, 0), + CPU_TYPE_ENTRY(T1042, T1042, 0), + CPU_TYPE_ENTRY(T1020, T1020, 0), + CPU_TYPE_ENTRY(T1021, T1021, 0), + CPU_TYPE_ENTRY(T1022, T1022, 0), + CPU_TYPE_ENTRY(T1024, T1024, 0), + CPU_TYPE_ENTRY(T1023, T1023, 0), + CPU_TYPE_ENTRY(T1014, T1014, 0), + CPU_TYPE_ENTRY(T1013, T1013, 0), + CPU_TYPE_ENTRY(T2080, T2080, 0), + CPU_TYPE_ENTRY(T2081, T2081, 0), + CPU_TYPE_ENTRY(BSC9130, 9130, 1), + CPU_TYPE_ENTRY(BSC9131, 9131, 1), + CPU_TYPE_ENTRY(BSC9132, 9132, 2), + CPU_TYPE_ENTRY(BSC9232, 9232, 2), + CPU_TYPE_ENTRY(C291, C291, 1), + CPU_TYPE_ENTRY(C292, C292, 1), + CPU_TYPE_ENTRY(C293, C293, 1), +#elif defined(CONFIG_MPC86xx) + CPU_TYPE_ENTRY(8610, 8610, 1), + CPU_TYPE_ENTRY(8641, 8641, 2), + CPU_TYPE_ENTRY(8641D, 8641D, 2), +#endif +}; + +#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 +static inline u32 init_type(u32 cluster, int init_id) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK; + u32 type = in_be32(&gur->tp_ityp[idx]); + + if (type & TP_ITYP_AV) + return type; + + return 0; +} + +u32 compute_ppc_cpumask(void) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, type, mask = 0; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = init_type(cluster, j); + if (type) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_PPC) + mask |= 1 << count; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return mask; +} + +#ifdef CONFIG_HETROGENOUS_CLUSTERS +u32 compute_dsp_cpumask(void) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int i = CONFIG_DSP_CLUSTER_START, count = 0; + u32 cluster, type, dsp_mask = 0; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = init_type(cluster, j); + if (type) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_SC) + dsp_mask |= 1 << count; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return dsp_mask; +} + +int fsl_qoriq_dsp_core_to_cluster(unsigned int core) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int count = 0, i = CONFIG_DSP_CLUSTER_START; + u32 cluster; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + if (init_type(cluster, j)) { + if (count == core) + return i; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return -1; /* cannot identify the cluster */ +} +#endif + +int fsl_qoriq_core_to_cluster(unsigned int core) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + if (init_type(cluster, j)) { + if (count == core) + return i; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return -1; /* cannot identify the cluster */ +} + +#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ +/* + * Before chassis genenration 2, the cpumask should be hard-coded. + * In case of cpu type unknown or cpumask unset, use 1 as fail save. + */ +#define compute_ppc_cpumask() 1 +#define fsl_qoriq_core_to_cluster(x) x +#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ + +static struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 0); + +struct cpu_type *identify_cpu(u32 ver) +{ + int i; + for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) { + if (cpu_type_list[i].soc_ver == ver) + return &cpu_type_list[i]; + } + return &cpu_type_unknown; +} + +#define MPC8xxx_PICFRR_NCPU_MASK 0x00001f00 +#define MPC8xxx_PICFRR_NCPU_SHIFT 8 + +/* + * Return a 32-bit mask indicating which cores are present on this SOC. + */ +__weak u32 cpu_mask(void) +{ + ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR; + struct cpu_type *cpu = gd->arch.cpu; + + /* better to query feature reporting register than just assume 1 */ + if (cpu == &cpu_type_unknown) + return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> + MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + + if (cpu->num_cores == 0) + return compute_ppc_cpumask(); + + return cpu->mask; +} + +#ifdef CONFIG_HETROGENOUS_CLUSTERS +__weak u32 cpu_dsp_mask(void) +{ + ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR; + struct cpu_type *cpu = gd->arch.cpu; + + /* better to query feature reporting register than just assume 1 */ + if (cpu == &cpu_type_unknown) + return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> + MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + + if (cpu->dsp_num_cores == 0) + return compute_dsp_cpumask(); + + return cpu->dsp_mask; +} + +/* + * Return the number of SC/DSP cores on this SOC. + */ +__weak int cpu_num_dspcores(void) +{ + struct cpu_type *cpu = gd->arch.cpu; + + /* + * Report # of cores in terms of the cpu_mask if we haven't + * figured out how many there are yet + */ + if (cpu->dsp_num_cores == 0) + return hweight32(cpu_dsp_mask()); + + return cpu->dsp_num_cores; +} +#endif + +/* + * Return the number of PPC cores on this SOC. + */ +__weak int cpu_numcores(void) +{ + struct cpu_type *cpu = gd->arch.cpu; + + /* + * Report # of cores in terms of the cpu_mask if we haven't + * figured out how many there are yet + */ + if (cpu->num_cores == 0) + return hweight32(cpu_mask()); + + return cpu->num_cores; +} + + +/* + * Check if the given core ID is valid + * + * Returns zero if it isn't, 1 if it is. + */ +int is_core_valid(unsigned int core) +{ + return !!((1 << core) & cpu_mask()); +} + +int arch_cpu_init(void) +{ + uint svr; + uint ver; + + svr = get_svr(); + ver = SVR_SOC_VER(svr); + + gd->arch.cpu = identify_cpu(ver); + + return 0; +} + +/* Once in memory, compute mask & # cores once and save them off */ +int fixup_cpu(void) +{ + struct cpu_type *cpu = gd->arch.cpu; + + if (cpu->num_cores == 0) { + cpu->mask = cpu_mask(); + cpu->num_cores = cpu_numcores(); + } + +#ifdef CONFIG_HETROGENOUS_CLUSTERS + if (cpu->dsp_num_cores == 0) { + cpu->dsp_mask = cpu_dsp_mask(); + cpu->dsp_num_cores = cpu_num_dspcores(); + } +#endif + return 0; +} + +#ifndef CONFIG_DM_ETH +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(struct bd_info *bis) +{ +#if defined(CONFIG_ETHER_ON_FCC) + fec_initialize(bis); +#endif + +#if defined(CONFIG_UEC_ETH) + uec_standard_init(bis); +#endif + +#if defined(CONFIG_TSEC_ENET) || defined(CONFIG_MPC85XX_FEC) + tsec_standard_init(bis); +#endif + +#ifdef CONFIG_FMAN_ENET + fm_standard_init(bis); +#endif + +#ifdef CONFIG_VSC9953 + vsc9953_init(bis); +#endif + return 0; +} +#endif diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fdt.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fdt.c new file mode 100644 index 000000000..67f8b1000 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fdt.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2009-2014 Freescale Semiconductor, Inc. + * Copyright 2020 NXP + * + * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and + * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains + * cpu specific common code for 85xx/86xx processors. + */ + +#include <common.h> +#include <cpu_func.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <asm/mp.h> +#include <asm/fsl_serdes.h> +#include <phy.h> +#include <hwconfig.h> + +#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT +#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 +#endif + +#if defined(CONFIG_MP) && (defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)) +static int ft_del_cpuhandle(void *blob, int cpuhandle) +{ + int off, ret = -FDT_ERR_NOTFOUND; + + /* if we find a match, we'll delete at it which point the offsets are + * invalid so we start over from the beginning + */ + off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle", + &cpuhandle, 4); + while (off != -FDT_ERR_NOTFOUND) { + fdt_delprop(blob, off, "cpu-handle"); + ret = 1; + off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle", + &cpuhandle, 4); + } + + return ret; +} + +void ft_fixup_num_cores(void *blob) { + int off, num_cores, del_cores; + + del_cores = 0; + num_cores = cpu_numcores(); + + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); + u32 phys_cpu_id = thread_to_core(*reg); + + if (!is_core_valid(phys_cpu_id) || is_core_disabled(phys_cpu_id)) { + int ph = fdt_get_phandle(blob, off); + + /* Delete the cpu node once there are no cpu handles */ + if (-FDT_ERR_NOTFOUND == ft_del_cpuhandle(blob, ph)) { + fdt_del_node(blob, off); + del_cores++; + } + /* either we deleted some cpu handles or the cpu node + * so we reset the offset back to the start since we + * can't trust the offsets anymore + */ + off = -1; + } + off = fdt_node_offset_by_prop_value(blob, off, + "device_type", "cpu", 4); + } + debug ("%x core system found\n", num_cores); + debug ("deleted %d extra core entry entries from device tree\n", + del_cores); +} +#endif /* defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) */ + +int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) +{ + const char *conn; + + /* Do NOT apply fixup for backplane modes specified in DT */ + if (phyc == PHY_INTERFACE_MODE_XGMII) { + conn = fdt_getprop(blob, offset, "phy-connection-type", NULL); + if (is_backplane_mode(conn)) + return 0; + } + return fdt_setprop_string(blob, offset, "phy-connection-type", + phy_string_for_interface(phyc)); +} + +#ifdef CONFIG_SYS_SRIO +static inline void ft_disable_srio_port(void *blob, int srio_off, int port) +{ + int off = fdt_node_offset_by_prop_value(blob, srio_off, + "cell-index", &port, 4); + if (off >= 0) { + off = fdt_setprop_string(blob, off, "status", "disabled"); + if (off > 0) + printf("WARNING unable to set status for fsl,srio " + "port %d: %s\n", port, fdt_strerror(off)); + } +} + +static inline void ft_disable_rman(void *blob) +{ + int off = fdt_node_offset_by_compatible(blob, -1, "fsl,rman"); + if (off >= 0) { + off = fdt_setprop_string(blob, off, "status", "disabled"); + if (off > 0) + printf("WARNING unable to set status for fsl,rman %s\n", + fdt_strerror(off)); + } +} + +static inline void ft_disable_rmu(void *blob) +{ + int off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio-rmu"); + if (off >= 0) { + off = fdt_setprop_string(blob, off, "status", "disabled"); + if (off > 0) + printf("WARNING unable to set status for " + "fsl,srio-rmu %s\n", fdt_strerror(off)); + } +} + +void ft_srio_setup(void *blob) +{ + int srio1_used = 0, srio2_used = 0; + int srio_off; + + /* search for srio node, if doesn't exist just return - nothing todo */ + srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio"); + if (srio_off < 0) + return ; + +#ifdef CONFIG_SRIO1 + if (is_serdes_configured(SRIO1)) + srio1_used = 1; +#endif +#ifdef CONFIG_SRIO2 + if (is_serdes_configured(SRIO2)) + srio2_used = 1; +#endif + + /* mark port1 disabled */ + if (!srio1_used) + ft_disable_srio_port(blob, srio_off, 1); + + /* mark port2 disabled */ + if (!srio2_used) + ft_disable_srio_port(blob, srio_off, 2); + + /* if both ports not used, disable controller, rmu and rman */ + if (!srio1_used && !srio2_used) { + fdt_setprop_string(blob, srio_off, "status", "disabled"); + + ft_disable_rman(blob); + ft_disable_rmu(blob); + } +} +#endif diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c new file mode 100644 index 000000000..29489b46e --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2010-2011 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <hang.h> +#include <init.h> +#include <asm/fsl_lbc.h> + +#ifdef CONFIG_MPC83xx +#include "../mpc83xx/elbc/elbc.h" +#endif + +#ifdef CONFIG_MPC85xx +/* Boards should provide their own version of this if they use lbc sdram */ +static void __lbc_sdram_init(void) +{ + /* Do nothing */ +} +void lbc_sdram_init(void) __attribute__((weak, alias("__lbc_sdram_init"))); +#endif + + +void print_lbc_regs(void) +{ + int i; + + printf("\nLocal Bus Controller Registers\n"); + for (i = 0; i < 8; i++) { + printf("BR%d\t0x%08X\tOR%d\t0x%08X\n", + i, get_lbc_br(i), i, get_lbc_or(i)); + } + printf("LBCR\t0x%08X\tLCRR\t0x%08X\n", + get_lbc_lbcr(), get_lbc_lcrr()); +} + +void init_early_memctl_regs(void) +{ + uint init_br1 = 1; + +#ifdef CONFIG_SYS_FSL_ERRATUM_ELBC_A001 + /* Set the local bus monitor timeout value to the maximum */ + clrsetbits_be32(&(LBC_BASE_ADDR)->lbcr, LBCR_BMT|LBCR_BMTPS, 0xf); +#endif + +#ifdef CONFIG_MPC85xx + /* if cs1 is already set via debugger, leave cs0/cs1 alone */ + if (get_lbc_br(1) & BR_V) + init_br1 = 0; +#endif + + /* + * Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at + * preliminary addresses - these have to be modified later + * when FLASH size has been determined + */ +#if defined(CONFIG_SYS_OR0_REMAP) + set_lbc_or(0, CONFIG_SYS_OR0_REMAP); +#endif +#if defined(CONFIG_SYS_OR1_REMAP) + set_lbc_or(1, CONFIG_SYS_OR1_REMAP); +#endif + /* now restrict to preliminary range */ + if (init_br1) { +#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM) + set_lbc_br(0, CONFIG_SYS_BR0_PRELIM); + set_lbc_or(0, CONFIG_SYS_OR0_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM) + set_lbc_or(1, CONFIG_SYS_OR1_PRELIM); + set_lbc_br(1, CONFIG_SYS_BR1_PRELIM); +#endif + } + +#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM) + set_lbc_or(2, CONFIG_SYS_OR2_PRELIM); + set_lbc_br(2, CONFIG_SYS_BR2_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM) + set_lbc_or(3, CONFIG_SYS_OR3_PRELIM); + set_lbc_br(3, CONFIG_SYS_BR3_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM) + set_lbc_or(4, CONFIG_SYS_OR4_PRELIM); + set_lbc_br(4, CONFIG_SYS_BR4_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM) + set_lbc_or(5, CONFIG_SYS_OR5_PRELIM); + set_lbc_br(5, CONFIG_SYS_BR5_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM) + set_lbc_or(6, CONFIG_SYS_OR6_PRELIM); + set_lbc_br(6, CONFIG_SYS_BR6_PRELIM); +#endif + +#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM) + set_lbc_or(7, CONFIG_SYS_OR7_PRELIM); + set_lbc_br(7, CONFIG_SYS_BR7_PRELIM); +#endif +} + +/* + * Configures a UPM. The function requires the respective MxMR to be set + * before calling this function. "size" is the number or entries, not a sizeof. + */ +void upmconfig(uint upm, uint *table, uint size) +{ + fsl_lbc_t *lbc = LBC_BASE_ADDR; + int i, mad, old_mad = 0; + u32 mask = (~MxMR_OP_MSK & ~MxMR_MAD_MSK); + u32 msel = BR_UPMx_TO_MSEL(upm); + u32 *mxmr = &lbc->mamr + upm; + volatile u8 *dummy = NULL; + + if (upm < UPMA || upm > UPMC) { + printf("Error: %s() Bad UPM index %d\n", __func__, upm); + hang(); + } + + /* + * Find the address for the dummy write - scan all of the BRs until we + * find one matching the UPM and extract the base address bits from it. + */ + for (i = 0; i < 8; i++) { + if ((get_lbc_br(i) & (BR_V | BR_MSEL)) == (BR_V | msel)) { + dummy = (volatile u8 *)(get_lbc_br(i) & BR_BA); + break; + } + } + + if (!dummy) { + printf("Error: %s() No matching BR\n", __func__); + hang(); + } + + /* Program UPM using steps outlined by the reference manual */ + for (i = 0; i < size; i++) { + out_be32(mxmr, (in_be32(mxmr) & mask) | MxMR_OP_WARR | i); + out_be32(&lbc->mdr, table[i]); + (void)in_be32(&lbc->mdr); + *dummy = 0; + do { + mad = in_be32(mxmr) & MxMR_MAD_MSK; + } while (mad <= old_mad && !(!mad && i == (size-1))); + old_mad = mad; + } + + /* Return to normal operation */ + out_be32(mxmr, (in_be32(mxmr) & mask) | MxMR_OP_NORM); +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c new file mode 100644 index 000000000..522994995 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FSL PAMU driver + * + * Copyright 2012-2016 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <log.h> +#include <linux/bitops.h> +#include <linux/log2.h> +#include <malloc.h> +#include <asm/fsl_pamu.h> + +struct paace *ppaact; +struct paace *sec; +unsigned long fspi; + +static inline int __ilog2_roundup_64(uint64_t val) +{ + if ((val & (val - 1)) == 0) + return __ilog2_u64(val); + else + return __ilog2_u64(val) + 1; +} + + +static inline int count_lsb_zeroes(unsigned long val) +{ + return ffs(val) - 1; +} + +static unsigned int map_addrspace_size_to_wse(uint64_t addrspace_size) +{ + /* window size is 2^(WSE+1) bytes */ + return count_lsb_zeroes(addrspace_size >> PAMU_PAGE_SHIFT) + + PAMU_PAGE_SHIFT - 1; +} + +static unsigned int map_subwindow_cnt_to_wce(uint32_t subwindow_cnt) +{ + /* window count is 2^(WCE+1) bytes */ + return count_lsb_zeroes(subwindow_cnt) - 1; +} + +static void pamu_setup_default_xfer_to_host_ppaace(struct paace *ppaace) +{ + set_bf(ppaace->addr_bitfields, PAACE_AF_PT, PAACE_PT_PRIMARY); + set_bf(ppaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR, + PAACE_M_COHERENCE_REQ); +} + +static void pamu_setup_default_xfer_to_host_spaace(struct paace *spaace) +{ + set_bf(spaace->addr_bitfields, PAACE_AF_PT, PAACE_PT_SECONDARY); + set_bf(spaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR, + PAACE_M_COHERENCE_REQ); +} + +/** Sets up PPAACE entry for specified liodn + * + * @param[in] liodn Logical IO device number + * @param[in] win_addr starting address of DSA window + * @param[in] win-size size of DSA window + * @param[in] omi Operation mapping index -- if ~omi == 0 then omi + not defined + * @param[in] stashid cache stash id for associated cpu -- if ~stashid == 0 + then stashid not defined + * @param[in] snoopid snoop id for hardware coherency -- if ~snoopid == 0 + then snoopid not defined + * @param[in] subwin_cnt number of sub-windows + * + * @return Returns 0 upon success else error code < 0 returned + */ +static int pamu_config_ppaace(uint32_t liodn, uint64_t win_addr, + uint64_t win_size, uint32_t omi, + uint32_t snoopid, uint32_t stashid, + uint32_t subwin_cnt) +{ + struct paace *ppaace; + + if ((win_size & (win_size - 1)) || win_size < PAMU_PAGE_SIZE) + return -1; + + if (win_addr & (win_size - 1)) + return -2; + + if (liodn > NUM_PPAACT_ENTRIES) { + printf("Entries in PPACT not sufficient\n"); + return -3; + } + + ppaace = &ppaact[liodn]; + + /* window size is 2^(WSE+1) bytes */ + set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, + map_addrspace_size_to_wse(win_size)); + + pamu_setup_default_xfer_to_host_ppaace(ppaace); + + if (sizeof(phys_addr_t) > 4) + ppaace->wbah = (u64)win_addr >> (PAMU_PAGE_SHIFT + 20); + else + ppaace->wbah = 0; + + set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, + (win_addr >> PAMU_PAGE_SHIFT)); + + /* set up operation mapping if it's configured */ + if (omi < OME_NUMBER_ENTRIES) { + set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED); + ppaace->op_encode.index_ot.omi = omi; + } else if (~omi != 0) { + return -3; + } + + /* configure stash id */ + if (~stashid != 0) + set_bf(ppaace->impl_attr, PAACE_IA_CID, stashid); + + /* configure snoop id */ + if (~snoopid != 0) + ppaace->domain_attr.to_host.snpid = snoopid; + + if (subwin_cnt) { + /* window count is 2^(WCE+1) bytes */ + set_bf(ppaace->impl_attr, PAACE_IA_WCE, + map_subwindow_cnt_to_wce(subwin_cnt)); + set_bf(ppaace->addr_bitfields, PPAACE_AF_MW, 0x1); + ppaace->fspi = fspi; + fspi = fspi + DEFAULT_NUM_SUBWINDOWS - 1; + } else { + set_bf(ppaace->addr_bitfields, PAACE_AF_AP, PAACE_AP_PERMS_ALL); + } + + sync(); + /* Mark the ppace entry valid */ + ppaace->addr_bitfields |= PAACE_V_VALID; + sync(); + + return 0; +} + +static int pamu_config_spaace(uint32_t liodn, + uint64_t subwin_size, uint64_t subwin_addr, uint64_t size, + uint32_t omi, uint32_t snoopid, uint32_t stashid) +{ + struct paace *paace; + /* Align start addr of subwin to subwindoe size */ + uint64_t sec_addr = subwin_addr & ~(subwin_size - 1); + uint64_t end_addr = subwin_addr + size; + int size_shift = __ilog2_u64(subwin_size); + uint64_t win_size = 0; + uint32_t index, swse; + unsigned long fspi_idx; + + /* Recalculate the size */ + size = end_addr - sec_addr; + + if (!subwin_size) + return -1; + + if (liodn > NUM_PPAACT_ENTRIES) { + printf("LIODN No programmed %d > no. of PPAACT entries %d\n", + liodn, NUM_PPAACT_ENTRIES); + return -1; + } + + while (sec_addr < end_addr) { + debug("sec_addr < end_addr is %llx < %llx\n", sec_addr, + end_addr); + paace = &ppaact[liodn]; + if (!paace) + return -1; + fspi_idx = paace->fspi; + + /* Calculating the win_size here as if we map in index 0, + paace entry woudl need to be programmed for SWSE */ + win_size = end_addr - sec_addr; + win_size = 1 << __ilog2_roundup_64(win_size); + + if (win_size > subwin_size) + win_size = subwin_size; + else if (win_size < PAMU_PAGE_SIZE) + win_size = PAMU_PAGE_SIZE; + + debug("win_size is %llx\n", win_size); + + swse = map_addrspace_size_to_wse(win_size); + index = sec_addr >> size_shift; + + if (index == 0) { + set_bf(paace->win_bitfields, PAACE_WIN_SWSE, swse); + set_bf(paace->addr_bitfields, PAACE_AF_AP, + PAACE_AP_PERMS_ALL); + sec_addr += subwin_size; + continue; + } + + paace = sec + fspi_idx + index - 1; + + debug("SPAACT:Writing at location %p, index %d\n", paace, + index); + + pamu_setup_default_xfer_to_host_spaace(paace); + set_bf(paace->addr_bitfields, SPAACE_AF_LIODN, liodn); + set_bf(paace->addr_bitfields, PAACE_AF_AP, PAACE_AP_PERMS_ALL); + + /* configure snoop id */ + if (~snoopid != 0) + paace->domain_attr.to_host.snpid = snoopid; + + if (paace->addr_bitfields & PAACE_V_VALID) { + debug("Reached overlap condition\n"); + debug("%d < %d\n", get_bf(paace->win_bitfields, + PAACE_WIN_SWSE), swse); + if (get_bf(paace->win_bitfields, PAACE_WIN_SWSE) < swse) + set_bf(paace->win_bitfields, PAACE_WIN_SWSE, + swse); + } else { + set_bf(paace->win_bitfields, PAACE_WIN_SWSE, swse); + } + + paace->addr_bitfields |= PAACE_V_VALID; + sec_addr += subwin_size; + } + + return 0; +} + +int pamu_init(void) +{ + u32 base_addr = CONFIG_SYS_PAMU_ADDR; + struct ccsr_pamu *regs; + u32 i = 0; + u64 ppaact_phys, ppaact_lim, ppaact_size; + u64 spaact_phys, spaact_lim, spaact_size; + + ppaact_size = sizeof(struct paace) * NUM_PPAACT_ENTRIES; + spaact_size = sizeof(struct paace) * NUM_SPAACT_ENTRIES; + + /* Allocate space for Primary PAACT Table */ +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_PPAACT_ADDR)) + ppaact = (void *)CONFIG_SPL_PPAACT_ADDR; +#else + ppaact = memalign(PAMU_TABLE_ALIGNMENT, ppaact_size); + if (!ppaact) + return -1; +#endif + memset(ppaact, 0, ppaact_size); + + /* Allocate space for Secondary PAACT Table */ +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SPAACT_ADDR)) + sec = (void *)CONFIG_SPL_SPAACT_ADDR; +#else + sec = memalign(PAMU_TABLE_ALIGNMENT, spaact_size); + if (!sec) + return -1; +#endif + memset(sec, 0, spaact_size); + + ppaact_phys = virt_to_phys((void *)ppaact); + ppaact_lim = ppaact_phys + ppaact_size; + + spaact_phys = (uint64_t)virt_to_phys((void *)sec); + spaact_lim = spaact_phys + spaact_size; + + /* Configure all PAMU's */ + for (i = 0; i < CONFIG_NUM_PAMU; i++) { + regs = (struct ccsr_pamu *)base_addr; + + out_be32(®s->ppbah, ppaact_phys >> 32); + out_be32(®s->ppbal, (uint32_t)ppaact_phys); + + out_be32(®s->pplah, (ppaact_lim) >> 32); + out_be32(®s->pplal, (uint32_t)ppaact_lim); + + if (sec != NULL) { + out_be32(®s->spbah, spaact_phys >> 32); + out_be32(®s->spbal, (uint32_t)spaact_phys); + out_be32(®s->splah, spaact_lim >> 32); + out_be32(®s->splal, (uint32_t)spaact_lim); + } + sync(); + + base_addr += PAMU_OFFSET; + } + + return 0; +} + +void pamu_enable(void) +{ + u32 i = 0; + u32 base_addr = CONFIG_SYS_PAMU_ADDR; + for (i = 0; i < CONFIG_NUM_PAMU; i++) { + setbits_be32((void *)base_addr + PAMU_PCR_OFFSET, + PAMU_PCR_PE); + sync(); + base_addr += PAMU_OFFSET; + } +} + +void pamu_reset(void) +{ + u32 i = 0; + u32 base_addr = CONFIG_SYS_PAMU_ADDR; + struct ccsr_pamu *regs; + + for (i = 0; i < CONFIG_NUM_PAMU; i++) { + regs = (struct ccsr_pamu *)base_addr; + /* Clear PPAACT Base register */ + out_be32(®s->ppbah, 0); + out_be32(®s->ppbal, 0); + out_be32(®s->pplah, 0); + out_be32(®s->pplal, 0); + out_be32(®s->spbah, 0); + out_be32(®s->spbal, 0); + out_be32(®s->splah, 0); + out_be32(®s->splal, 0); + + clrbits_be32((void *)regs + PAMU_PCR_OFFSET, PAMU_PCR_PE); + sync(); + base_addr += PAMU_OFFSET; + } +} + +void pamu_disable(void) +{ + u32 i = 0; + u32 base_addr = CONFIG_SYS_PAMU_ADDR; + + + for (i = 0; i < CONFIG_NUM_PAMU; i++) { + clrbits_be32((void *)base_addr + PAMU_PCR_OFFSET, PAMU_PCR_PE); + sync(); + base_addr += PAMU_OFFSET; + } +} + + +static uint64_t find_max(uint64_t arr[], int num) +{ + int i = 0; + int max = 0; + for (i = 1 ; i < num; i++) + if (arr[max] < arr[i]) + max = i; + + return arr[max]; +} + +static uint64_t find_min(uint64_t arr[], int num) +{ + int i = 0; + int min = 0; + for (i = 1 ; i < num; i++) + if (arr[min] > arr[i]) + min = i; + + return arr[min]; +} + +static uint32_t get_win_cnt(uint64_t size) +{ + uint32_t win_cnt = DEFAULT_NUM_SUBWINDOWS; + + while (win_cnt && (size/win_cnt) < PAMU_PAGE_SIZE) + win_cnt >>= 1; + + return win_cnt; +} + +int config_pamu(struct pamu_addr_tbl *tbl, int num_entries, uint32_t liodn) +{ + int i = 0; + int ret = 0; + uint32_t num_sec_windows = 0; + uint32_t num_windows = 0; + uint64_t min_addr, max_addr; + uint64_t size; + uint64_t subwin_size; + int sizebit; + + min_addr = find_min(tbl->start_addr, num_entries); + max_addr = find_max(tbl->end_addr, num_entries); + size = max_addr - min_addr + 1; + + if (!size) + return -1; + + sizebit = __ilog2_roundup_64(size); + size = 1ull << sizebit; + debug("min start_addr is %llx\n", min_addr); + debug("max end_addr is %llx\n", max_addr); + debug("size found is %llx\n", size); + + if (size < PAMU_PAGE_SIZE) + size = PAMU_PAGE_SIZE; + + while (1) { + min_addr = min_addr & ~(size - 1); + if (min_addr + size > max_addr) + break; + size <<= 1; + if (!size) + return -1; + } + debug("PAACT :Base addr is %llx\n", min_addr); + debug("PAACT : Size is %llx\n", size); + num_windows = get_win_cnt(size); + /* For a single window, no spaact entries are required + * sec_sub_window count = 0 */ + if (num_windows > 1) + num_sec_windows = num_windows; + else + num_sec_windows = 0; + + ret = pamu_config_ppaace(liodn, min_addr, + size , -1, -1, -1, num_sec_windows); + + if (ret < 0) + return ret; + + debug("configured ppace\n"); + + if (num_sec_windows) { + subwin_size = size >> count_lsb_zeroes(num_sec_windows); + debug("subwin_size is %llx\n", subwin_size); + + for (i = 0; i < num_entries; i++) { + ret = pamu_config_spaace(liodn, + subwin_size, tbl->start_addr[i] - min_addr, + tbl->size[i], -1, -1, -1); + + if (ret < 0) + return ret; + } + } + + return ret; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/law.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/law.c new file mode 100644 index 000000000..cf03f4101 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/law.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <common.h> +#include <asm/bitops.h> +#include <asm/global_data.h> +#include <linux/compiler.h> +#include <asm/fsl_law.h> +#include <asm/io.h> +#include <linux/log2.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS + +#ifdef CONFIG_FSL_CORENET +#define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR) +#define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar) +#define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh) +#define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl) +#define LAWBAR_SHIFT 0 +#else +#define LAW_BASE (CONFIG_SYS_IMMR + 0xc08) +#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2) +#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x) +#define LAWBAR_SHIFT 12 +#endif + + +static inline phys_addr_t get_law_base_addr(int idx) +{ +#ifdef CONFIG_FSL_CORENET + return (phys_addr_t) + ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) | + in_be32(LAWBARL_ADDR(idx)); +#else + return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT; +#endif +} + +static inline void set_law_base_addr(int idx, phys_addr_t addr) +{ +#ifdef CONFIG_FSL_CORENET + out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff); + out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32); +#else + out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT); +#endif +} + +void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + gd->arch.used_laws |= (1 << idx); + + out_be32(LAWAR_ADDR(idx), 0); + set_law_base_addr(idx, addr); + out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz); + + /* Read back so that we sync the writes */ + in_be32(LAWAR_ADDR(idx)); +} + +void disable_law(u8 idx) +{ + gd->arch.used_laws &= ~(1 << idx); + + out_be32(LAWAR_ADDR(idx), 0); + set_law_base_addr(idx, 0); + + /* Read back so that we sync the writes */ + in_be32(LAWAR_ADDR(idx)); + + return; +} + +#if !defined(CONFIG_NAND_SPL) && \ + (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL)) +static int get_law_entry(u8 i, struct law_entry *e) +{ + u32 lawar; + + lawar = in_be32(LAWAR_ADDR(i)); + + if (!(lawar & LAW_EN)) + return 0; + + e->addr = get_law_base_addr(i); + e->size = lawar & 0x3f; + e->trgt_id = (lawar >> 20) & 0xff; + + return 1; +} +#endif + +int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx = ffz(gd->arch.used_laws); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; +} + +#if !defined(CONFIG_NAND_SPL) && \ + (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL)) +int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx; + + /* we have no LAWs free */ + if (gd->arch.used_laws == -1) + return -1; + + /* grab the last free law */ + idx = __ilog2(~(gd->arch.used_laws)); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; +} + +struct law_entry find_law(phys_addr_t addr) +{ + struct law_entry entry; + int i; + + entry.index = -1; + entry.addr = 0; + entry.size = 0; + entry.trgt_id = 0; + + for (i = 0; i < FSL_HW_NUM_LAWS; i++) { + u64 upper; + + if (!get_law_entry(i, &entry)) + continue; + + upper = entry.addr + (2ull << entry.size); + if ((addr >= entry.addr) && (addr < upper)) { + entry.index = i; + break; + } + } + + return entry; +} + +void print_laws(void) +{ + int i; + u32 lawar; + + printf("\nLocal Access Window Configuration\n"); + for (i = 0; i < FSL_HW_NUM_LAWS; i++) { + lawar = in_be32(LAWAR_ADDR(i)); +#ifdef CONFIG_FSL_CORENET + printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x", + i, in_be32(LAWBARH_ADDR(i)), + i, in_be32(LAWBARL_ADDR(i))); +#else + printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i))); +#endif + printf(" LAWAR%02d: 0x%08x\n", i, lawar); + printf("\t(EN: %d TGT: 0x%02x SIZE: ", + (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff); + print_size(lawar_size(lawar), ")\n"); + } + + return; +} + +/* use up to 2 LAWs for DDR, used the last available LAWs */ +int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id) +{ + u64 start_align, law_sz; + int law_sz_enc; + + if (start == 0) + start_align = 1ull << (LAW_SIZE_32G + 1); + else + start_align = 1ull << (__ffs64(start)); + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + if (set_last_law(start, law_sz_enc, id) < 0) + return -1; + + /* recalculate size based on what was actually covered by the law */ + law_sz = 1ull << __ilog2_u64(law_sz); + + /* do we still have anything to map */ + sz = sz - law_sz; + if (sz) { + start += law_sz; + + start_align = 1ull << (__ffs64(start)); + law_sz = min(start_align, sz); + law_sz_enc = __ilog2_u64(law_sz) - 1; + + if (set_last_law(start, law_sz_enc, id) < 0) + return -1; + } else { + return 0; + } + + /* do we still have anything to map */ + sz = sz - law_sz; + if (sz) + return 1; + + return 0; +} +#endif /* not SPL */ + +void disable_non_ddr_laws(void) +{ + int i; + int id; + for (i = 0; i < FSL_HW_NUM_LAWS; i++) { + u32 lawar = in_be32(LAWAR_ADDR(i)); + + if (lawar & LAW_EN) { + id = (lawar & ~LAW_EN) >> 20; + switch (id) { + case LAW_TRGT_IF_DDR_1: + case LAW_TRGT_IF_DDR_2: + case LAW_TRGT_IF_DDR_3: + case LAW_TRGT_IF_DDR_4: + case LAW_TRGT_IF_DDR_INTRLV: + case LAW_TRGT_IF_DDR_INTLV_34: + case LAW_TRGT_IF_DDR_INTLV_123: + case LAW_TRGT_IF_DDR_INTLV_1234: + continue; + default: + disable_law(i); + } + } + } +} + +void init_laws(void) +{ + int i; + +#if FSL_HW_NUM_LAWS < 32 + gd->arch.used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1); +#elif FSL_HW_NUM_LAWS == 32 + gd->arch.used_laws = 0; +#else +#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes +#endif + +#if defined(CONFIG_NXP_ESBC) && defined(CONFIG_E500) && \ + !defined(CONFIG_E500MC) + /* ISBC (Boot ROM) creates a LAW 0 entry for non PBL platforms, + * which is not disabled before transferring the control to uboot. + * Disable the LAW 0 entry here. + */ + disable_law(0); +#endif + +#if !defined(CONFIG_NXP_ESBC) + /* + * if any non DDR LAWs has been created earlier, remove them before + * LAW table is parsed. + */ + disable_non_ddr_laws(); +#endif + + /* + * Any LAWs that were set up before we booted assume they are meant to + * be around and mark them used. + */ + for (i = 0; i < FSL_HW_NUM_LAWS; i++) { + u32 lawar = in_be32(LAWAR_ADDR(i)); + + if (lawar & LAW_EN) + gd->arch.used_laws |= (1 << i); + } + + for (i = 0; i < num_law_entries; i++) { + if (law_table[i].index == -1) + set_next_law(law_table[i].addr, law_table[i].size, + law_table[i].trgt_id); + else + set_law(law_table[i].index, law_table[i].addr, + law_table[i].size, law_table[i].trgt_id); + } + +#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE + /* check RCW to get which port is used for boot */ + ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; + u32 bootloc = in_be32(&gur->rcwsr[6]); + /* + * in SRIO or PCIE boot we need to set specail LAWs for + * SRIO or PCIE interfaces. + */ + switch ((bootloc & FSL_CORENET_RCWSR6_BOOT_LOC) >> 23) { + case 0x0: /* boot from PCIE1 */ + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_1); + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_1); + break; + case 0x1: /* boot from PCIE2 */ + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_2); + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_2); + break; + case 0x2: /* boot from PCIE3 */ + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_3); + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_PCIE_3); + break; + case 0x8: /* boot from SRIO1 */ + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_RIO_1); + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_RIO_1); + break; + case 0x9: /* boot from SRIO2 */ + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_RIO_2); + set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS, + LAW_SIZE_1M, + LAW_TRGT_IF_RIO_2); + break; + default: + break; + } +#endif + + return ; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/pamu_table.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/pamu_table.c new file mode 100644 index 000000000..d917e9dfb --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/pamu_table.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2012-2016 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <log.h> +#include <asm/fsl_pamu.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +void construct_pamu_addr_table(struct pamu_addr_tbl *tbl, int *num_entries) +{ + int i = 0; + int j; + + tbl->start_addr[i] = + (uint64_t)virt_to_phys((void *)CONFIG_SYS_SDRAM_BASE); + tbl->size[i] = (phys_size_t)(min(gd->ram_size, CONFIG_MAX_MEM_MAPPED)); + tbl->end_addr[i] = tbl->start_addr[i] + tbl->size[i] - 1; + + i++; +#ifdef CONFIG_SYS_FLASH_BASE_PHYS + tbl->start_addr[i] = + (uint64_t)virt_to_phys((void *)CONFIG_SYS_FLASH_BASE_PHYS); + tbl->size[i] = 256 * 1024 * 1024; /* 256MB flash */ + tbl->end_addr[i] = tbl->start_addr[i] + tbl->size[i] - 1; + + i++; +#endif +#if (defined(CONFIG_SPL_BUILD) && (CONFIG_SYS_INIT_L3_VADDR)) + tbl->start_addr[i] = + (uint64_t)virt_to_phys((void *)CONFIG_SYS_INIT_L3_VADDR); + tbl->size[i] = 256 * 1024; /* 256K CPC flash */ + tbl->end_addr[i] = tbl->start_addr[i] + tbl->size[i] - 1; + + i++; +#endif + debug("PAMU address\t\t\tsize\n"); + for (j = 0; j < i ; j++) + debug("%llx \t\t\t%llx\n", tbl->start_addr[j], tbl->size[j]); + + *num_entries = i; +} + +int sec_config_pamu_table(uint32_t liodn_ns, uint32_t liodn_s) +{ + struct pamu_addr_tbl tbl; + int num_entries = 0; + int ret = 0; + + construct_pamu_addr_table(&tbl, &num_entries); + + ret = config_pamu(&tbl, num_entries, liodn_ns); + if (ret) + return ret; + + ret = config_pamu(&tbl, num_entries, liodn_s); + if (ret) + return ret; + + return ret; +} diff --git a/roms/u-boot/arch/powerpc/cpu/mpc8xxx/srio.c b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/srio.c new file mode 100644 index 000000000..c73cf9319 --- /dev/null +++ b/roms/u-boot/arch/powerpc/cpu/mpc8xxx/srio.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <config.h> +#include <log.h> +#include <time.h> +#include <asm/fsl_law.h> +#include <asm/fsl_serdes.h> +#include <asm/fsl_srio.h> +#include <linux/delay.h> +#include <linux/errno.h> + +#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER +#define SRIO_PORT_ACCEPT_ALL 0x10000001 +#define SRIO_IB_ATMU_AR 0x80f55000 +#define SRIO_OB_ATMU_AR_MAINT 0x80077000 +#define SRIO_OB_ATMU_AR_RW 0x80045000 +#define SRIO_LCSBA1CSR_OFFSET 0x5c +#define SRIO_MAINT_WIN_SIZE 0x1000000 /* 16M */ +#define SRIO_RW_WIN_SIZE 0x100000 /* 1M */ +#define SRIO_LCSBA1CSR 0x60000000 +#endif + +#if defined(CONFIG_FSL_CORENET) +#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 + #define _DEVDISR_SRIO1 FSL_CORENET_DEVDISR3_SRIO1 + #define _DEVDISR_SRIO2 FSL_CORENET_DEVDISR3_SRIO2 +#else + #define _DEVDISR_SRIO1 FSL_CORENET_DEVDISR_SRIO1 + #define _DEVDISR_SRIO2 FSL_CORENET_DEVDISR_SRIO2 +#endif + #define _DEVDISR_RMU FSL_CORENET_DEVDISR_RMU + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR +#elif defined(CONFIG_MPC85xx) + #define _DEVDISR_SRIO1 MPC85xx_DEVDISR_SRIO + #define _DEVDISR_SRIO2 MPC85xx_DEVDISR_SRIO + #define _DEVDISR_RMU MPC85xx_DEVDISR_RMSG + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR +#elif defined(CONFIG_MPC86xx) + #define _DEVDISR_SRIO1 MPC86xx_DEVDISR_SRIO + #define _DEVDISR_SRIO2 MPC86xx_DEVDISR_SRIO + #define _DEVDISR_RMU MPC86xx_DEVDISR_RMSG + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ + (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) +#else +#error "No defines for DEVDISR_SRIO" +#endif + +#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 +/* + * Erratum A-004034 + * Affects: SRIO + * Description: During port initialization, the SRIO port performs + * lane synchronization (detecting valid symbols on a lane) and + * lane alignment (coordinating multiple lanes to receive valid data + * across lanes). Internal errors in lane synchronization and lane + * alignment may cause failure to achieve link initialization at + * the configured port width. + * An SRIO port configured as a 4x port may see one of these scenarios: + * 1. One or more lanes fails to achieve lane synchronization. Depending + * on which lanes fail, this may result in downtraining from 4x to 1x + * on lane 0, 4x to 1x on lane R (redundant lane). + * 2. The link may fail to achieve lane alignment as a 4x, even though + * all 4 lanes achieve lane synchronization, and downtrain to a 1x. + * An SRIO port configured as a 1x port may fail to complete port + * initialization (PnESCSR[PU] never deasserts) because of scenario 1. + * Impact: SRIO port may downtrain to 1x, or may fail to complete + * link initialization. Once a port completes link initialization + * successfully, it will operate normally. + */ +static int srio_erratum_a004034(u8 port) +{ + serdes_corenet_t *srds_regs; + u32 conf_lane; + u32 init_lane; + int idx, first, last; + u32 i; + unsigned long long end_tick; + struct ccsr_rio *srio_regs = (void *)CONFIG_SYS_FSL_SRIO_ADDR; + + srds_regs = (void *)(CONFIG_SYS_FSL_CORENET_SERDES_ADDR); + conf_lane = (in_be32((void *)&srds_regs->srdspccr0) + >> (12 - port * 4)) & 0x3; + init_lane = (in_be32((void *)&srio_regs->lp_serial + .port[port].pccsr) >> 27) & 0x7; + + /* + * Start a counter set to ~2 ms after the SERDES reset is + * complete (SERDES SRDSBnRSTCTL[RST_DONE]=1 for n + * corresponding to the SERDES bank/PLL for the SRIO port). + */ + if (in_be32((void *)&srds_regs->bank[0].rstctl) + & SRDS_RSTCTL_RSTDONE) { + /* + * Poll the port uninitialized status (SRIO PnESCSR[PO]) until + * PO=1 or the counter expires. If the counter expires, the + * port has failed initialization: go to recover steps. If PO=1 + * and the desired port width is 1x, go to normal steps. If + * PO = 1 and the desired port width is 4x, go to recover steps. + */ + end_tick = usec2ticks(2000) + get_ticks(); + do { + if (in_be32((void *)&srio_regs->lp_serial + .port[port].pescsr) & 0x2) { + if (conf_lane == 0x1) + goto host_ok; + else { + if (init_lane == 0x2) + goto host_ok; + else + break; + } + } + } while (end_tick > get_ticks()); + + /* recover at most 3 times */ + for (i = 0; i < 3; i++) { + /* Set SRIO PnCCSR[PD]=1 */ + setbits_be32((void *)&srio_regs->lp_serial + .port[port].pccsr, + 0x800000); + /* + * Set SRIO PnPCR[OBDEN] on the host to + * enable the discarding of any pending packets. + */ + setbits_be32((void *)&srio_regs->impl.port[port].pcr, + 0x04); + /* Wait 50 us */ + udelay(50); + /* Run sync command */ + isync(); + + if (port) + first = serdes_get_first_lane(SRIO2); + else + first = serdes_get_first_lane(SRIO1); + if (unlikely(first < 0)) + return -ENODEV; + if (conf_lane == 0x1) + last = first; + else + last = first + 3; + /* + * Set SERDES BnGCRm0[RRST]=0 for each SRIO + * bank n and lane m. + */ + for (idx = first; idx <= last; idx++) + clrbits_be32(&srds_regs->lane[idx].gcr0, + SRDS_GCR0_RRST); + /* + * Read SERDES BnGCRm0 for each SRIO + * bank n and lane m + */ + for (idx = first; idx <= last; idx++) + in_be32(&srds_regs->lane[idx].gcr0); + /* Run sync command */ + isync(); + /* Wait >= 100 ns */ + udelay(1); + /* + * Set SERDES BnGCRm0[RRST]=1 for each SRIO + * bank n and lane m. + */ + for (idx = first; idx <= last; idx++) + setbits_be32(&srds_regs->lane[idx].gcr0, + SRDS_GCR0_RRST); + /* + * Read SERDES BnGCRm0 for each SRIO + * bank n and lane m + */ + for (idx = first; idx <= last; idx++) + in_be32(&srds_regs->lane[idx].gcr0); + /* Run sync command */ + isync(); + /* Wait >= 300 ns */ + udelay(1); + + /* Write 1 to clear all bits in SRIO PnSLCSR */ + out_be32((void *)&srio_regs->impl.port[port].slcsr, + 0xffffffff); + /* Clear SRIO PnPCR[OBDEN] on the host */ + clrbits_be32((void *)&srio_regs->impl.port[port].pcr, + 0x04); + /* Set SRIO PnCCSR[PD]=0 */ + clrbits_be32((void *)&srio_regs->lp_serial + .port[port].pccsr, + 0x800000); + /* Wait >= 24 ms */ + udelay(24000); + /* Poll the state of the port again */ + init_lane = + (in_be32((void *)&srio_regs->lp_serial + .port[port].pccsr) >> 27) & 0x7; + if (in_be32((void *)&srio_regs->lp_serial + .port[port].pescsr) & 0x2) { + if (conf_lane == 0x1) + goto host_ok; + else { + if (init_lane == 0x2) + goto host_ok; + } + } + if (i == 2) + return -ENODEV; + } + } else + return -ENODEV; + +host_ok: + /* Poll PnESCSR[OES] on the host until it is clear */ + end_tick = usec2ticks(1000000) + get_ticks(); + do { + if (!(in_be32((void *)&srio_regs->lp_serial.port[port].pescsr) + & 0x10000)) { + out_be32(((void *)&srio_regs->lp_serial + .port[port].pescsr), 0xffffffff); + out_be32(((void *)&srio_regs->phys_err + .port[port].edcsr), 0); + out_be32(((void *)&srio_regs->logical_err.ltledcsr), 0); + return 0; + } + } while (end_tick > get_ticks()); + + return -ENODEV; +} +#endif + +void srio_init(void) +{ + ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; + int srio1_used = 0, srio2_used = 0; + u32 *devdisr; + +#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 + devdisr = &gur->devdisr3; +#else + devdisr = &gur->devdisr; +#endif + if (is_serdes_configured(SRIO1)) { + set_next_law(CONFIG_SYS_SRIO1_MEM_PHYS, + law_size_bits(CONFIG_SYS_SRIO1_MEM_SIZE), + LAW_TRGT_IF_RIO_1); + srio1_used = 1; +#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 + if (srio_erratum_a004034(0) < 0) + printf("SRIO1: enabled but port error\n"); + else +#endif + printf("SRIO1: enabled\n"); + } else { + printf("SRIO1: disabled\n"); + } + +#ifdef CONFIG_SRIO2 + if (is_serdes_configured(SRIO2)) { + set_next_law(CONFIG_SYS_SRIO2_MEM_PHYS, + law_size_bits(CONFIG_SYS_SRIO2_MEM_SIZE), + LAW_TRGT_IF_RIO_2); + srio2_used = 1; +#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 + if (srio_erratum_a004034(1) < 0) + printf("SRIO2: enabled but port error\n"); + else +#endif + printf("SRIO2: enabled\n"); + + } else { + printf("SRIO2: disabled\n"); + } +#endif + +#ifdef CONFIG_FSL_CORENET + /* On FSL_CORENET devices we can disable individual ports */ + if (!srio1_used) + setbits_be32(devdisr, _DEVDISR_SRIO1); + if (!srio2_used) + setbits_be32(devdisr, _DEVDISR_SRIO2); +#endif + + /* neither port is used - disable everything */ + if (!srio1_used && !srio2_used) { + setbits_be32(devdisr, _DEVDISR_SRIO1); + setbits_be32(devdisr, _DEVDISR_SRIO2); + setbits_be32(devdisr, _DEVDISR_RMU); + } +} + +#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER +void srio_boot_master(int port) +{ + struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR; + + /* set port accept-all */ + out_be32((void *)&srio->impl.port[port - 1].ptaacr, + SRIO_PORT_ACCEPT_ALL); + + debug("SRIOBOOT - MASTER: Master port [ %d ] for srio boot.\n", port); + /* configure inbound window for slave's u-boot image */ + debug("SRIOBOOT - MASTER: Inbound window for slave's image; " + "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, + CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwtar, + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwbar, + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1 >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwar, + SRIO_IB_ATMU_AR + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE)); + + /* configure inbound window for slave's u-boot image */ + debug("SRIOBOOT - MASTER: Inbound window for slave's image; " + "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, + CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwtar, + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwbar, + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2 >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwar, + SRIO_IB_ATMU_AR + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE)); + + /* configure inbound window for slave's ucode and ENV */ + debug("SRIOBOOT - MASTER: Inbound window for slave's ucode and ENV; " + "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", + (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwtar, + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwbar, + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwar, + SRIO_IB_ATMU_AR + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE)); +} + +void srio_boot_master_release_slave(int port) +{ + struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR; + u32 escsr; + debug("SRIOBOOT - MASTER: " + "Check the port status and release slave core ...\n"); + + escsr = in_be32((void *)&srio->lp_serial.port[port - 1].pescsr); + if (escsr & 0x2) { + if (escsr & 0x10100) { + debug("SRIOBOOT - MASTER: Port [ %d ] is error.\n", + port); + } else { + debug("SRIOBOOT - MASTER: " + "Port [ %d ] is ready, now release slave's core ...\n", + port); + /* + * configure outbound window + * with maintenance attribute to set slave's LCSBA1CSR + */ + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[1].rowtar, 0); + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[1].rowtear, 0); + if (port - 1) + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[1].rowbar, + CONFIG_SYS_SRIO2_MEM_PHYS >> 12); + else + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[1].rowbar, + CONFIG_SYS_SRIO1_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[1].rowar, + SRIO_OB_ATMU_AR_MAINT + | atmu_size_mask(SRIO_MAINT_WIN_SIZE)); + + /* + * configure outbound window + * with R/W attribute to set slave's BRR + */ + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[2].rowtar, + SRIO_LCSBA1CSR >> 9); + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[2].rowtear, 0); + if (port - 1) + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[2].rowbar, + (CONFIG_SYS_SRIO2_MEM_PHYS + + SRIO_MAINT_WIN_SIZE) >> 12); + else + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[2].rowbar, + (CONFIG_SYS_SRIO1_MEM_PHYS + + SRIO_MAINT_WIN_SIZE) >> 12); + out_be32((void *)&srio->atmu.port[port - 1] + .outbw[2].rowar, + SRIO_OB_ATMU_AR_RW + | atmu_size_mask(SRIO_RW_WIN_SIZE)); + + /* + * Set the LCSBA1CSR register in slave + * by the maint-outbound window + */ + if (port - 1) { + out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT + + SRIO_LCSBA1CSR_OFFSET, + SRIO_LCSBA1CSR); + while (in_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT + + SRIO_LCSBA1CSR_OFFSET) + != SRIO_LCSBA1CSR) + ; + /* + * And then set the BRR register + * to release slave core + */ + out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT + + SRIO_MAINT_WIN_SIZE + + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET, + CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); + } else { + out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT + + SRIO_LCSBA1CSR_OFFSET, + SRIO_LCSBA1CSR); + while (in_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT + + SRIO_LCSBA1CSR_OFFSET) + != SRIO_LCSBA1CSR) + ; + /* + * And then set the BRR register + * to release slave core + */ + out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT + + SRIO_MAINT_WIN_SIZE + + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET, + CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); + } + debug("SRIOBOOT - MASTER: " + "Release slave successfully! Now the slave should start up!\n"); + } + } else + debug("SRIOBOOT - MASTER: Port [ %d ] is not ready.\n", port); +} +#endif |