mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
This commit is contained in:
commit
3f6dcdb9cd
164 changed files with 11691 additions and 710 deletions
13
README
13
README
|
@ -690,6 +690,14 @@ The following options need to be configured:
|
|||
exists, unlike the similar options in the Linux kernel. Do not
|
||||
set these options unless they apply!
|
||||
|
||||
COUNTER_FREQUENCY
|
||||
Generic timer clock source frequency.
|
||||
|
||||
COUNTER_FREQUENCY_REAL
|
||||
Generic timer clock source frequency if the real clock is
|
||||
different from COUNTER_FREQUENCY, and can only be determined
|
||||
at run time.
|
||||
|
||||
NOTE: The following can be machine specific errata. These
|
||||
do have ability to provide rudimentary version and machine
|
||||
specific checks, but expect no product checks.
|
||||
|
@ -2395,6 +2403,8 @@ CBFS (Coreboot Filesystem) support
|
|||
- define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE
|
||||
If those defines are not set, default value is 100000
|
||||
for speed, and 0 for slave.
|
||||
- enable bus 3 with CONFIG_SYS_I2C_MXC_I2C3
|
||||
- enable bus 4 with CONFIG_SYS_I2C_MXC_I2C4
|
||||
|
||||
- drivers/i2c/rcar_i2c.c:
|
||||
- activate this driver with CONFIG_SYS_I2C_RCAR
|
||||
|
@ -4882,6 +4892,9 @@ Low Level (hardware related) configuration options:
|
|||
- CONFIG_FSL_DDR_SYNC_REFRESH
|
||||
Enable sync of refresh for multiple controllers.
|
||||
|
||||
- CONFIG_FSL_DDR_BIST
|
||||
Enable built-in memory test for Freescale DDR controllers.
|
||||
|
||||
- CONFIG_SYS_83XX_DDR_USES_CS0
|
||||
Only for 83xx systems. If specified, then DDR should
|
||||
be configured using CS0 and CS1 instead of CS2 and CS3.
|
||||
|
|
|
@ -690,6 +690,28 @@ config TARGET_LS2085A_SIMU
|
|||
select ARM64
|
||||
select ARMV8_MULTIENTRY
|
||||
|
||||
config TARGET_LS2085AQDS
|
||||
bool "Support ls2085aqds"
|
||||
select ARM64
|
||||
select ARMV8_MULTIENTRY
|
||||
select SUPPORT_SPL
|
||||
help
|
||||
Support for Freescale LS2085AQDS platform
|
||||
The LS2085A Development System (QDS) is a high-performance
|
||||
development platform that supports the QorIQ LS2085A
|
||||
Layerscape Architecture processor.
|
||||
|
||||
config TARGET_LS2085ARDB
|
||||
bool "Support ls2085ardb"
|
||||
select ARM64
|
||||
select ARMV8_MULTIENTRY
|
||||
select SUPPORT_SPL
|
||||
help
|
||||
Support for Freescale LS2085ARDB platform.
|
||||
The LS2085A Reference design board (RDB) is a high-performance
|
||||
development platform that supports the QorIQ LS2085A
|
||||
Layerscape Architecture processor.
|
||||
|
||||
config TARGET_LS1021AQDS
|
||||
bool "Support ls1021aqds"
|
||||
select CPU_V7
|
||||
|
@ -849,6 +871,8 @@ source "board/denx/m53evk/Kconfig"
|
|||
source "board/embest/mx6boards/Kconfig"
|
||||
source "board/esg/ima3-mx53/Kconfig"
|
||||
source "board/freescale/ls2085a/Kconfig"
|
||||
source "board/freescale/ls2085aqds/Kconfig"
|
||||
source "board/freescale/ls2085ardb/Kconfig"
|
||||
source "board/freescale/ls1021aqds/Kconfig"
|
||||
source "board/freescale/ls1021atwr/Kconfig"
|
||||
source "board/freescale/mx23evk/Kconfig"
|
||||
|
|
|
@ -20,7 +20,7 @@ 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;
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 ccr;
|
||||
#endif
|
||||
struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR);
|
||||
|
@ -74,7 +74,7 @@ void get_sys_info(struct sys_info *sys_info)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_FSL_IFC)
|
||||
ccr = in_be32(&ifc_regs->ifc_ccr);
|
||||
ccr = in_be32(&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;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
obj-y += cpu.o
|
||||
obj-y += lowlevel.o
|
||||
obj-y += soc.o
|
||||
obj-y += speed.o
|
||||
obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o ls2085a_serdes.o
|
||||
obj-$(CONFIG_MP) += mp.o
|
||||
obj-$(CONFIG_OF_LIBFDT) += fdt.o
|
||||
|
|
|
@ -8,3 +8,141 @@ Freescale LayerScape with Chassis Generation 3
|
|||
|
||||
This architecture supports Freescale ARMv8 SoCs with Chassis generation 3,
|
||||
for example LS2085A.
|
||||
|
||||
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.
|
||||
|
||||
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,
|
||||
ls2085aqds_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.
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#include <fsl_esdhc.h>
|
||||
#endif
|
||||
#include "cpu.h"
|
||||
#include "mp.h"
|
||||
#include "speed.h"
|
||||
|
@ -24,8 +29,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
* 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[31:30], table address @01000, 0x2000
|
||||
* Level 2 IA[29:21], table address @0x3000
|
||||
* Level 1 IA[31:30], table address @0x1000, 0x2000
|
||||
* Level 2 IA[29:21], table address @0x3000, 0x4000
|
||||
* Address above 0x5000 is free for other purpose.
|
||||
*/
|
||||
|
||||
#define SECTION_SHIFT_L0 39UL
|
||||
|
@ -60,12 +66,12 @@ static inline void early_mmu_setup(void)
|
|||
{
|
||||
int el;
|
||||
u64 i;
|
||||
u64 section_l1t0, section_l1t1, section_l2;
|
||||
u64 section_l1t0, section_l1t1, section_l2t0, section_l2t1;
|
||||
u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE;
|
||||
u64 *level1_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000);
|
||||
u64 *level1_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000);
|
||||
u64 *level2_table = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000);
|
||||
|
||||
u64 *level2_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000);
|
||||
u64 *level2_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x4000);
|
||||
|
||||
level0_table[0] =
|
||||
(u64)level1_table_0 | PMD_TYPE_TABLE;
|
||||
|
@ -79,21 +85,25 @@ static inline void early_mmu_setup(void)
|
|||
*/
|
||||
section_l1t0 = 0;
|
||||
section_l1t1 = BLOCK_SIZE_L0;
|
||||
section_l2 = 0;
|
||||
section_l2t0 = 0;
|
||||
section_l2t1 = CONFIG_SYS_FLASH_BASE;
|
||||
for (i = 0; i < 512; i++) {
|
||||
set_pgtable_section(level1_table_0, i, section_l1t0,
|
||||
MT_DEVICE_NGNRNE);
|
||||
set_pgtable_section(level1_table_1, i, section_l1t1,
|
||||
MT_NORMAL);
|
||||
set_pgtable_section(level2_table, i, section_l2,
|
||||
set_pgtable_section(level2_table_0, i, section_l2t0,
|
||||
MT_DEVICE_NGNRNE);
|
||||
set_pgtable_section(level2_table_1, i, section_l2t1,
|
||||
MT_DEVICE_NGNRNE);
|
||||
section_l1t0 += BLOCK_SIZE_L1;
|
||||
section_l1t1 += BLOCK_SIZE_L1;
|
||||
section_l2 += BLOCK_SIZE_L2;
|
||||
section_l2t0 += BLOCK_SIZE_L2;
|
||||
section_l2t1 += BLOCK_SIZE_L2;
|
||||
}
|
||||
|
||||
level1_table_0[0] =
|
||||
(u64)level2_table | PMD_TYPE_TABLE;
|
||||
(u64)level2_table_0 | PMD_TYPE_TABLE;
|
||||
level1_table_0[1] =
|
||||
0x40000000 | PMD_SECT_AF | PMD_TYPE_SECT |
|
||||
PMD_ATTRINDX(MT_DEVICE_NGNRNE);
|
||||
|
@ -104,17 +114,34 @@ static inline void early_mmu_setup(void)
|
|||
0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT |
|
||||
PMD_ATTRINDX(MT_NORMAL);
|
||||
|
||||
/* Rewrite table to enable cache */
|
||||
set_pgtable_section(level2_table,
|
||||
/* Rewerite table to enable cache for OCRAM */
|
||||
set_pgtable_section(level2_table_0,
|
||||
CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2,
|
||||
CONFIG_SYS_FSL_OCRAM_BASE,
|
||||
MT_NORMAL);
|
||||
for (i = CONFIG_SYS_IFC_BASE >> SECTION_SHIFT_L2;
|
||||
i < (CONFIG_SYS_IFC_BASE + CONFIG_SYS_IFC_SIZE)
|
||||
>> SECTION_SHIFT_L2; i++) {
|
||||
section_l2 = i << SECTION_SHIFT_L2;
|
||||
set_pgtable_section(level2_table, i,
|
||||
section_l2, MT_NORMAL);
|
||||
|
||||
#if defined(CONFIG_SYS_NOR0_CSPR_EARLY) && defined(CONFIG_SYS_NOR_AMASK_EARLY)
|
||||
/* Rewrite table to enable cache for two entries (4MB) */
|
||||
section_l2t1 = CONFIG_SYS_IFC_BASE;
|
||||
set_pgtable_section(level2_table_0,
|
||||
section_l2t1 >> SECTION_SHIFT_L2,
|
||||
section_l2t1,
|
||||
MT_NORMAL);
|
||||
section_l2t1 += BLOCK_SIZE_L2;
|
||||
set_pgtable_section(level2_table_0,
|
||||
section_l2t1 >> SECTION_SHIFT_L2,
|
||||
section_l2t1,
|
||||
MT_NORMAL);
|
||||
#endif
|
||||
|
||||
/* Create a mapping for 256MB IFC region to final flash location */
|
||||
level1_table_0[CONFIG_SYS_FLASH_BASE >> SECTION_SHIFT_L1] =
|
||||
(u64)level2_table_1 | PMD_TYPE_TABLE;
|
||||
section_l2t1 = CONFIG_SYS_IFC_BASE;
|
||||
for (i = 0; i < 0x10000000 >> SECTION_SHIFT_L2; i++) {
|
||||
set_pgtable_section(level2_table_1, i,
|
||||
section_l2t1, MT_DEVICE_NGNRNE);
|
||||
section_l2t1 += BLOCK_SIZE_L2;
|
||||
}
|
||||
|
||||
el = current_el();
|
||||
|
@ -347,6 +374,7 @@ u32 fsl_qoriq_core_to_type(unsigned int core)
|
|||
#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;
|
||||
|
@ -370,21 +398,40 @@ int print_cpuinfo(void)
|
|||
printf(" DP-DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus2));
|
||||
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++) {
|
||||
u32 rcw = in_le32(&gur->rcwsr[i]);
|
||||
|
||||
if ((i % 4) == 0)
|
||||
printf("\n %02x:", 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 = mc_init(bis);
|
||||
error = fsl_mc_ldpaa_init(bis);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int arch_early_init_r(void)
|
||||
{
|
||||
int rv;
|
||||
|
@ -393,5 +440,43 @@ int arch_early_init_r(void)
|
|||
if (rv)
|
||||
printf("Did not wake secondary cores\n");
|
||||
|
||||
#ifdef CONFIG_SYS_HAS_SERDES
|
||||
fsl_serdes_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
|
||||
u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
|
||||
#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
|
||||
|
||||
/* Enable timebase for all clusters.
|
||||
* It is safe to do so even some clusters are not enabled.
|
||||
*/
|
||||
out_le32(cltbenr, 0xf);
|
||||
|
||||
/* 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 = in_le32(rstcr);
|
||||
val |= 0x02;
|
||||
out_le32(rstcr, val);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <common.h>
|
||||
#include <libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#include <fsl_esdhc.h>
|
||||
#endif
|
||||
#include "mp.h"
|
||||
|
||||
#ifdef CONFIG_MP
|
||||
|
@ -62,7 +65,11 @@ void ft_cpu_setup(void *blob, bd_t *bd)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_NS16550
|
||||
do_fixup_by_compat_u32(blob, "ns16550",
|
||||
do_fixup_by_compat_u32(blob, "fsl,ns16550",
|
||||
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FSL_ESDHC)
|
||||
fdt_fixup_esdhc(blob, bd);
|
||||
#endif
|
||||
}
|
||||
|
|
115
arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
Normal file
115
arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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-fsl-lsch3/immap_lsch3.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
|
||||
|
||||
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 = in_le32(&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(serdes_prtcl_map));
|
||||
|
||||
cfg = in_le32(&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
|
||||
wriop_init_dpmac(sd, lane + 1, (int)lane_prtcl);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fsl_serdes_init(void)
|
||||
{
|
||||
#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
|
||||
}
|
|
@ -15,6 +15,15 @@
|
|||
ENTRY(lowlevel_init)
|
||||
mov x29, lr /* Save LR */
|
||||
|
||||
/* Add fully-coherent masters to DVM domain */
|
||||
ldr x1, =CCI_MN_BASE
|
||||
ldr x2, [x1, #CCI_MN_RNF_NODEID_LIST]
|
||||
str x2, [x1, #CCI_MN_DVM_DOMAIN_CTL_SET]
|
||||
1: ldr x3, [x1, #CCI_MN_DVM_DOMAIN_CTL_SET]
|
||||
mvn x0, x3
|
||||
tst x0, x3 /* Wait for domain addition to complete */
|
||||
b.ne 1b
|
||||
|
||||
/* Set the SMMU page size in the sACR register */
|
||||
ldr x1, =SMMU_BASE
|
||||
ldr w0, [x1, #0x10]
|
||||
|
@ -224,6 +233,9 @@ ENTRY(secondary_boot_func)
|
|||
/* 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 */
|
||||
|
@ -275,6 +287,9 @@ ENDPROC(secondary_switch_to_el1)
|
|||
|
||||
/* 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 */
|
||||
|
|
117
arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c
Normal file
117
arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
|
||||
|
||||
struct serdes_config {
|
||||
u8 protocol;
|
||||
u8 lanes[SRDS_MAX_LANES];
|
||||
};
|
||||
|
||||
static struct serdes_config serdes1_cfg_tbl[] = {
|
||||
/* SerDes 1 */
|
||||
{0x03, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2 } },
|
||||
{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, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15,
|
||||
SGMII16 } },
|
||||
{0x47, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4,
|
||||
PCIE4 } },
|
||||
{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;
|
||||
}
|
|
@ -31,6 +31,13 @@ int fsl_lsch3_wake_seconday_cores(void)
|
|||
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.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define id_to_core(x) ((x & 3) | (x >> 6))
|
||||
#ifndef __ASSEMBLY__
|
||||
extern u64 __spin_table[];
|
||||
extern u64 __real_cntfrq;
|
||||
extern u64 *secondary_boot_code;
|
||||
extern size_t __secondary_boot_code_size;
|
||||
int fsl_lsch3_wake_seconday_cores(void);
|
||||
|
|
107
arch/arm/cpu/armv8/fsl-lsch3/soc.c
Normal file
107
arch/arm/cpu/armv8/fsl-lsch3/soc.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <nand.h>
|
||||
#include <spl.h>
|
||||
#include <asm/arch-fsl-lsch3/soc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static void erratum_a008751(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008751
|
||||
u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
|
||||
|
||||
writel(0x27672b2a, scfg + SCFG_USB3PRM1CR / 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 fsl_lsch3_early_init_f(void)
|
||||
{
|
||||
erratum_a008751();
|
||||
erratum_rcw_src();
|
||||
init_early_memctl_regs(); /* tighten IFC timing */
|
||||
erratum_a009203();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
/* Clear global data */
|
||||
memset((void *)gd, 0, sizeof(gd_t));
|
||||
|
||||
arch_cpu_init();
|
||||
board_early_init_f();
|
||||
timer_init();
|
||||
env_init();
|
||||
gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
|
||||
|
||||
serial_init();
|
||||
console_init_f();
|
||||
dram_init();
|
||||
|
||||
/* Clear the BSS. */
|
||||
memset(__bss_start, 0, __bss_end - __bss_start);
|
||||
|
||||
board_init_r(NULL, 0);
|
||||
}
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
return BOOT_DEVICE_NAND;
|
||||
}
|
||||
#endif
|
|
@ -26,7 +26,7 @@ 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;
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 ccr;
|
||||
#endif
|
||||
struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
|
||||
|
@ -86,6 +86,8 @@ void get_sys_info(struct sys_info *sys_info)
|
|||
sys_info->freq_systembus *= (in_le32(&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 *= (in_le32(&gur->rcwsr[0]) >>
|
||||
FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
|
||||
FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
|
||||
|
@ -102,10 +104,7 @@ void get_sys_info(struct sys_info *sys_info)
|
|||
offsetof(struct ccsr_clk_cluster_group,
|
||||
pllngsr[i%3].gsr));
|
||||
ratio[i] = (in_le32(offset) >> 1) & 0x3f;
|
||||
if (ratio[i] > 4)
|
||||
freq_c_pll[i] = sysclk * ratio[i];
|
||||
else
|
||||
freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
|
||||
freq_c_pll[i] = sysclk * ratio[i];
|
||||
}
|
||||
|
||||
for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
|
||||
|
@ -119,7 +118,7 @@ void get_sys_info(struct sys_info *sys_info)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_FSL_IFC)
|
||||
ccr = in_le32(&ifc_regs->ifc_ccr);
|
||||
ccr = in_le32(&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;
|
||||
|
|
|
@ -25,7 +25,18 @@ unsigned long get_tbclk(void)
|
|||
unsigned long timer_read_counter(void)
|
||||
{
|
||||
unsigned long cntpct;
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008585
|
||||
/* This erratum number needs to be confirmed to match ARM document */
|
||||
unsigned long temp;
|
||||
#endif
|
||||
isb();
|
||||
asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008585
|
||||
asm volatile("mrs %0, cntpct_el0" : "=r" (temp));
|
||||
while (temp != cntpct) {
|
||||
asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
|
||||
asm volatile("mrs %0, cntpct_el0" : "=r" (temp));
|
||||
}
|
||||
#endif
|
||||
return cntpct;
|
||||
}
|
||||
|
|
77
arch/arm/cpu/armv8/u-boot-spl.lds
Normal file
77
arch/arm/cpu/armv8/u-boot-spl.lds
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* (C) Copyright 2013
|
||||
* David Feng <fenghua@phytium.com.cn>
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||
*
|
||||
* (C) Copyright 2010
|
||||
* Texas Instruments, <www.ti.com>
|
||||
* Aneesh V <aneesh@ti.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,
|
||||
LENGTH = CONFIG_SPL_MAX_SIZE }
|
||||
MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
|
||||
LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
|
||||
OUTPUT_ARCH(aarch64)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
. = ALIGN(8);
|
||||
*(.__image_copy_start)
|
||||
CPUDIR/start.o (.text*)
|
||||
*(.text*)
|
||||
} >.sram
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(8);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
} >.sram
|
||||
|
||||
.data : {
|
||||
. = ALIGN(8);
|
||||
*(.data*)
|
||||
} >.sram
|
||||
|
||||
.u_boot_list : {
|
||||
. = ALIGN(8);
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
} >.sram
|
||||
|
||||
.image_copy_end : {
|
||||
. = ALIGN(8);
|
||||
*(.__image_copy_end)
|
||||
} >.sram
|
||||
|
||||
.end : {
|
||||
. = ALIGN(8);
|
||||
*(.__end)
|
||||
} >.sram
|
||||
|
||||
.bss_start : {
|
||||
. = ALIGN(8);
|
||||
KEEP(*(.__bss_start));
|
||||
} >.sdram
|
||||
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
. = ALIGN(8);
|
||||
} >.sdram
|
||||
|
||||
.bss_end : {
|
||||
KEEP(*(.__bss_end));
|
||||
} >.sdram
|
||||
|
||||
/DISCARD/ : { *(.dynsym) }
|
||||
/DISCARD/ : { *(.dynstr*) }
|
||||
/DISCARD/ : { *(.dynamic*) }
|
||||
/DISCARD/ : { *(.plt*) }
|
||||
/DISCARD/ : { *(.interp*) }
|
||||
/DISCARD/ : { *(.gnu*) }
|
||||
}
|
|
@ -8,6 +8,14 @@
|
|||
#define _ASM_ARMV8_FSL_LSCH3_CONFIG_
|
||||
|
||||
#include <fsl_ddrc_version.h>
|
||||
|
||||
#define CONFIG_SYS_PAGE_SIZE 0x10000
|
||||
|
||||
#ifndef L1_CACHE_BYTES
|
||||
#define L1_CACHE_SHIFT 6
|
||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
||||
#endif
|
||||
|
||||
#define CONFIG_MP
|
||||
#define CONFIG_SYS_FSL_OCRAM_BASE 0x18000000 /* initial RAM */
|
||||
/* Link Definitions */
|
||||
|
@ -23,6 +31,7 @@
|
|||
#define CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR (CONFIG_SYS_IMMR + 0x00300000)
|
||||
#define CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR (CONFIG_SYS_IMMR + 0x00310000)
|
||||
#define CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR (CONFIG_SYS_IMMR + 0x00370000)
|
||||
#define CONFIG_SYS_FSL_ESDHC_ADDR (CONFIG_SYS_IMMR + 0x01140000)
|
||||
#define CONFIG_SYS_IFC_ADDR (CONFIG_SYS_IMMR + 0x01240000)
|
||||
#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_IMMR + 0x011C0500)
|
||||
#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_IMMR + 0x011C0600)
|
||||
|
@ -30,6 +39,20 @@
|
|||
#define CONFIG_SYS_FSL_PMU_CLTBENR (CONFIG_SYS_FSL_PMU_ADDR + \
|
||||
0x18A0)
|
||||
|
||||
#define CONFIG_SYS_FSL_WRIOP1_ADDR (CONFIG_SYS_IMMR + 0x7B80000)
|
||||
#define CONFIG_SYS_FSL_WRIOP1_MDIO1 (CONFIG_SYS_FSL_WRIOP1_ADDR + 0x16000)
|
||||
#define CONFIG_SYS_FSL_WRIOP1_MDIO2 (CONFIG_SYS_FSL_WRIOP1_ADDR + 0x17000)
|
||||
#define CONFIG_SYS_FSL_LSCH3_SERDES_ADDR (CONFIG_SYS_IMMR + 0xEA0000)
|
||||
|
||||
/* SP (Cortex-A5) related */
|
||||
#define CONFIG_SYS_FSL_SP_ADDR (CONFIG_SYS_IMMR + 0x00F00000)
|
||||
#define CONFIG_SYS_FSL_SP_VSG_GIC_ADDR (CONFIG_SYS_FSL_SP_ADDR)
|
||||
#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR1 (CONFIG_SYS_FSL_SP_ADDR)
|
||||
#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2 \
|
||||
(CONFIG_SYS_FSL_SP_ADDR + 0x0008)
|
||||
#define CONFIG_SYS_FSL_SP_LOOPBACK_DUART \
|
||||
(CONFIG_SYS_FSL_SP_ADDR + 0x1000)
|
||||
|
||||
#define CONFIG_SYS_FSL_DCSR_DDR_ADDR 0x70012c000ULL
|
||||
#define CONFIG_SYS_FSL_DCSR_DDR2_ADDR 0x70012d000ULL
|
||||
#define CONFIG_SYS_FSL_DCSR_DDR3_ADDR 0x700132000ULL
|
||||
|
@ -88,22 +111,57 @@
|
|||
#define CONFIG_MAX_MEM_MAPPED CONFIG_SYS_LS2_DDR_BLOCK1_SIZE
|
||||
#define CONFIG_SYS_FSL_DDR_VER FSL_DDR_VER_5_0
|
||||
|
||||
|
||||
#define CONFIG_SYS_FSL_ESDHC_LE
|
||||
/* IFC */
|
||||
#define CONFIG_SYS_FSL_IFC_LE
|
||||
#define CONFIG_SYS_MEMAC_LITTLE_ENDIAN
|
||||
|
||||
/* PCIe */
|
||||
#define CONFIG_SYS_PCIE1_ADDR (CONFIG_SYS_IMMR + 0x2400000)
|
||||
#define CONFIG_SYS_PCIE2_ADDR (CONFIG_SYS_IMMR + 0x2500000)
|
||||
#define CONFIG_SYS_PCIE3_ADDR (CONFIG_SYS_IMMR + 0x2600000)
|
||||
#define CONFIG_SYS_PCIE4_ADDR (CONFIG_SYS_IMMR + 0x2700000)
|
||||
#define CONFIG_SYS_PCIE1_PHYS_ADDR 0x1000000000ULL
|
||||
#define CONFIG_SYS_PCIE2_PHYS_ADDR 0x1200000000ULL
|
||||
#define CONFIG_SYS_PCIE3_PHYS_ADDR 0x1400000000ULL
|
||||
#define CONFIG_SYS_PCIE4_PHYS_ADDR 0x1600000000ULL
|
||||
|
||||
/* Cache Coherent Interconnect */
|
||||
#define CCI_MN_BASE 0x04000000
|
||||
#define CCI_MN_RNF_NODEID_LIST 0x180
|
||||
#define CCI_MN_DVM_DOMAIN_CTL 0x200
|
||||
#define CCI_MN_DVM_DOMAIN_CTL_SET 0x210
|
||||
|
||||
/* Device Configuration */
|
||||
#define DCFG_BASE 0x01e00000
|
||||
#define DCFG_PORSR1 0x000
|
||||
#define DCFG_PORSR1_RCW_SRC 0xff800000
|
||||
#define DCFG_PORSR1_RCW_SRC_NOR 0x12f00000
|
||||
|
||||
#define DCFG_DCSR_BASE 0X700100000ULL
|
||||
#define DCFG_DCSR_PORCR1 0x000
|
||||
|
||||
/* Supplemental Configuration */
|
||||
#define SCFG_BASE 0x01fc0000
|
||||
#define SCFG_USB3PRM1CR 0x000
|
||||
|
||||
#ifdef CONFIG_LS2085A
|
||||
#define CONFIG_MAX_CPUS 16
|
||||
#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
|
||||
#define CONFIG_NUM_DDR_CONTROLLERS 3
|
||||
#define CONFIG_SYS_FSL_CLUSTER_CLOCKS { 1, 1, 4, 4 }
|
||||
#define CONFIG_SYS_FSL_SRDS_1
|
||||
#define CONFIG_SYS_FSL_SRDS_2
|
||||
#else
|
||||
#error SoC not defined
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LS2085A
|
||||
#define CONFIG_SYS_FSL_ERRATUM_A008336
|
||||
#define CONFIG_SYS_FSL_ERRATUM_A008511
|
||||
#define CONFIG_SYS_FSL_ERRATUM_A008514
|
||||
#define CONFIG_SYS_FSL_ERRATUM_A008585
|
||||
#define CONFIG_SYS_FSL_ERRATUM_A008751
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_ARMV8_FSL_LSCH3_CONFIG_ */
|
||||
|
|
67
arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h
Normal file
67
arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __FSL_SERDES_H
|
||||
#define __FSL_SERDES_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define SRDS_MAX_LANES 8
|
||||
|
||||
enum srds_prtcl {
|
||||
NONE = 0,
|
||||
PCIE1,
|
||||
PCIE2,
|
||||
PCIE3,
|
||||
PCIE4,
|
||||
SATA1,
|
||||
SATA2,
|
||||
XAUI1,
|
||||
XAUI2,
|
||||
XFI1,
|
||||
XFI2,
|
||||
XFI3,
|
||||
XFI4,
|
||||
XFI5,
|
||||
XFI6,
|
||||
XFI7,
|
||||
XFI8,
|
||||
SGMII1,
|
||||
SGMII2,
|
||||
SGMII3,
|
||||
SGMII4,
|
||||
SGMII5,
|
||||
SGMII6,
|
||||
SGMII7,
|
||||
SGMII8,
|
||||
SGMII9,
|
||||
SGMII10,
|
||||
SGMII11,
|
||||
SGMII12,
|
||||
SGMII13,
|
||||
SGMII14,
|
||||
SGMII15,
|
||||
SGMII16,
|
||||
QSGMII_A, /* A indicates MACs 1-4 */
|
||||
QSGMII_B, /* B indicates MACs 5-8 */
|
||||
QSGMII_C, /* C indicates MACs 9-12 */
|
||||
QSGMII_D, /* D indicates MACs 12-16 */
|
||||
SERDES_PRCTL_COUNT
|
||||
};
|
||||
|
||||
enum srds {
|
||||
FSL_SRDS_1 = 0,
|
||||
FSL_SRDS_2 = 1,
|
||||
};
|
||||
|
||||
int is_serdes_configured(enum srds_prtcl device);
|
||||
void fsl_serdes_init(void);
|
||||
|
||||
int serdes_get_first_lane(u32 sd, enum srds_prtcl device);
|
||||
enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane);
|
||||
int is_serdes_prtcl_valid(int serdes, u32 prtcl);
|
||||
|
||||
#endif /* __FSL_SERDES_H */
|
|
@ -47,6 +47,30 @@ struct ccsr_gur {
|
|||
u32 devdisr5; /* Device disable control 5 */
|
||||
u32 devdisr6; /* Device disable control 6 */
|
||||
u32 devdisr7; /* Device disable control 7 */
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC1 0x00000001
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC2 0x00000002
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC3 0x00000004
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC4 0x00000008
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC5 0x00000010
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC6 0x00000020
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC7 0x00000040
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC8 0x00000080
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC9 0x00000100
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC10 0x00000200
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC11 0x00000400
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC12 0x00000800
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC13 0x00001000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC14 0x00002000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC15 0x00004000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC16 0x00008000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC17 0x00010000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC18 0x00020000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC19 0x00040000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC20 0x00080000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC21 0x00100000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC22 0x00200000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC23 0x00400000
|
||||
#define FSL_CHASSIS3_DEVDISR2_DPMAC24 0x00800000
|
||||
u8 res_08c[0x90-0x8c];
|
||||
u32 coredisru; /* uppper portion for support of 64 cores */
|
||||
u32 coredisrl; /* lower portion for support of 64 cores */
|
||||
|
@ -63,6 +87,11 @@ struct ccsr_gur {
|
|||
#define FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK 0x3f
|
||||
#define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT 18
|
||||
#define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK 0x3f
|
||||
#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK 0x00FF0000
|
||||
#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT 16
|
||||
#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK 0xFF000000
|
||||
#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT 24
|
||||
|
||||
u8 res_180[0x200-0x180];
|
||||
u32 scratchrw[32]; /* Scratch Read/Write */
|
||||
u8 res_280[0x300-0x280];
|
||||
|
|
8
arch/arm/include/asm/arch-fsl-lsch3/soc.h
Normal file
8
arch/arm/include/asm/arch-fsl-lsch3/soc.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
void fsl_lsch3_early_init_f(void);
|
||||
|
|
@ -119,10 +119,6 @@
|
|||
|
||||
#define DCU_LAYER_MAX_NUM 16
|
||||
|
||||
#define QE_MURAM_SIZE 0x6000UL
|
||||
#define MAX_QE_RISC 1
|
||||
#define QE_NUM_OF_SNUM 28
|
||||
|
||||
#define CONFIG_SYS_FSL_SRDS_1
|
||||
|
||||
#ifdef CONFIG_LS102XA
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#define SOC_VER_LS1021 0x11
|
||||
#define SOC_VER_LS1022 0x12
|
||||
|
||||
#define SOC_MAJOR_VER_1_0 0x1
|
||||
#define SOC_MAJOR_VER_2_0 0x2
|
||||
|
||||
#define CCSR_BRR_OFFSET 0xe4
|
||||
#define CCSR_SCRATCHRW1_OFFSET 0x200
|
||||
|
||||
|
|
25
arch/arm/include/asm/fsl_secure_boot.h
Normal file
25
arch/arm/include/asm/fsl_secure_boot.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __FSL_SECURE_BOOT_H
|
||||
#define __FSL_SECURE_BOOT_H
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT
|
||||
#ifndef CONFIG_FIT_SIGNATURE
|
||||
|
||||
#define CONFIG_EXTRA_ENV \
|
||||
"setenv fdt_high 0xcfffffff;" \
|
||||
"setenv initrd_high 0xcfffffff;" \
|
||||
"setenv hwconfig \'fsl_ddr:ctlr_intlv=null,bank_intlv=null\';"
|
||||
|
||||
/* The address needs to be modified according to NOR memory map */
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0x600a0000
|
||||
|
||||
#include <config_fsl_secboot.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __PCIE_LAYERSCAPE_H_
|
||||
#define __PCIE_LAYERSCAPE_H_
|
||||
|
||||
void pci_init_board(void);
|
||||
void ft_pcie_setup(void *blob, bd_t *bd);
|
||||
|
||||
#endif
|
|
@ -61,7 +61,11 @@ ENTRY(_main)
|
|||
/*
|
||||
* Set up initial C runtime environment and call board_init_f(0).
|
||||
*/
|
||||
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
|
||||
ldr x0, =(CONFIG_SPL_STACK)
|
||||
#else
|
||||
ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
|
||||
#endif
|
||||
sub x18, x0, #GD_SIZE /* allocate one GD above SP */
|
||||
bic x18, x18, #0x7 /* 8-byte alignment for GD */
|
||||
zero_gd:
|
||||
|
@ -77,6 +81,7 @@ zero_gd:
|
|||
mov x0, #0
|
||||
bl board_init_f
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
/*
|
||||
* Set up intermediate environment (new sp and gd) and call
|
||||
* relocate_code(addr_moni). Trick here is that we'll return
|
||||
|
@ -119,4 +124,6 @@ clear_loop:
|
|||
|
||||
/* NOTREACHED - board_init_r() does not return */
|
||||
|
||||
#endif /* !CONFIG_SPL_BUILD */
|
||||
|
||||
ENDPROC(_main)
|
||||
|
|
|
@ -15,7 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#ifdef CONFIG_A003399_NOR_WORKAROUND
|
||||
void setup_ifc(void)
|
||||
{
|
||||
struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 _mas0, _mas1, _mas2, _mas3, _mas7;
|
||||
phys_addr_t flash_phys = CONFIG_SYS_FLASH_BASE_PHYS;
|
||||
|
||||
|
@ -70,9 +70,9 @@ void setup_ifc(void)
|
|||
#endif
|
||||
|
||||
/* Change flash's physical address */
|
||||
ifc_out32(&(ifc_regs->cspr_cs[0].cspr), CONFIG_SYS_CSPR0);
|
||||
ifc_out32(&(ifc_regs->csor_cs[0].csor), CONFIG_SYS_CSOR0);
|
||||
ifc_out32(&(ifc_regs->amask_cs[0].amask), CONFIG_SYS_AMASK0);
|
||||
ifc_out32(&(ifc_regs.gregs->cspr_cs[0].cspr), CONFIG_SYS_CSPR0);
|
||||
ifc_out32(&(ifc_regs.gregs->csor_cs[0].csor), CONFIG_SYS_CSOR0);
|
||||
ifc_out32(&(ifc_regs.gregs->amask_cs[0].amask), CONFIG_SYS_AMASK0);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ void get_sys_info(sys_info_t *sys_info)
|
|||
{
|
||||
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||
#ifdef CONFIG_FSL_IFC
|
||||
struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
u32 ccr;
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_CORENET
|
||||
|
@ -597,7 +597,7 @@ void get_sys_info(sys_info_t *sys_info)
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_FSL_IFC)
|
||||
ccr = ifc_in32(&ifc_regs->ifc_ccr);
|
||||
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;
|
||||
|
|
|
@ -67,5 +67,24 @@
|
|||
#define CONFIG_FSL_ISBC_KEY_EXT
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FIT_SIGNATURE
|
||||
/* The bootscript header address is different for B4860 because the NOR
|
||||
* mapping is different on B4 due to reduced NOR size.
|
||||
*/
|
||||
#if defined(CONFIG_B4860QDS)
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xecc00000
|
||||
#elif defined(CONFIG_FSL_CORENET)
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xe8e00000
|
||||
#elif defined(CONFIG_BSC9132QDS)
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0x88020000
|
||||
#elif defined(CONFIG_C29XPCIE)
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xec020000
|
||||
#else
|
||||
#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xee020000
|
||||
#endif
|
||||
|
||||
#include <config_fsl_secboot.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -36,9 +36,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
|
||||
setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,10 +38,10 @@ int checkboard(void)
|
|||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
|
||||
/* Clock configuration to access CPLD using IFC(GPCM) */
|
||||
setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#endif
|
||||
|
||||
#include "sleep.h"
|
||||
#ifdef CONFIG_U_QE
|
||||
#include "../../../drivers/qe/qe.h"
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -72,6 +75,9 @@ static void dp_resume_prepare(void)
|
|||
board_sleep_prepare();
|
||||
armv7_init_nonsec();
|
||||
cleanup_before_linux();
|
||||
#ifdef CONFIG_U_QE
|
||||
u_qe_resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
int fsl_dp_resume(void)
|
||||
|
|
|
@ -8,6 +8,16 @@
|
|||
#include <command.h>
|
||||
#include <fsl_validate.h>
|
||||
|
||||
static int do_esbc_halt(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
printf("Core is entering spin loop.\n");
|
||||
loop:
|
||||
goto loop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_esbc_validate(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
|
@ -32,3 +42,9 @@ U_BOOT_CMD(
|
|||
"Validates signature on a given image using RSA verification",
|
||||
esbc_validate_help_text
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
esbc_halt, 1, 0, do_esbc_halt,
|
||||
"Put the core in spin loop ",
|
||||
""
|
||||
);
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <common.h>
|
||||
#include <asm/immap_85xx.h>
|
||||
#include "sleep.h"
|
||||
#ifdef CONFIG_U_QE
|
||||
#include "../../../drivers/qe/qe.h"
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -65,6 +68,11 @@ static void dp_resume_prepare(void)
|
|||
disable_cpc_sram();
|
||||
#endif
|
||||
enable_cpc();
|
||||
|
||||
#ifdef CONFIG_U_QE
|
||||
u_qe_resume();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int fsl_dp_resume(void)
|
||||
|
|
|
@ -138,24 +138,23 @@ void qixis_bank_reset(void)
|
|||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
}
|
||||
|
||||
/* Set the boot bank to the power-on default bank */
|
||||
void clear_altbank(void)
|
||||
static void __maybe_unused set_lbmap(int lbmap)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
reg = QIXIS_READ(brdcfg[0]);
|
||||
reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_DFLTBANK;
|
||||
reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap;
|
||||
QIXIS_WRITE(brdcfg[0], reg);
|
||||
}
|
||||
|
||||
/* Set the boot bank to the alternate bank */
|
||||
void set_altbank(void)
|
||||
static void __maybe_unused set_rcw_src(int rcw_src)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
reg = QIXIS_READ(brdcfg[0]);
|
||||
reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_ALTBANK;
|
||||
QIXIS_WRITE(brdcfg[0], reg);
|
||||
reg = QIXIS_READ(dutcfg[1]);
|
||||
reg = (reg & ~1) | (rcw_src & 1);
|
||||
QIXIS_WRITE(dutcfg[1], reg);
|
||||
QIXIS_WRITE(dutcfg[0], (rcw_src >> 1) & 0xff);
|
||||
}
|
||||
|
||||
static void qixis_dump_regs(void)
|
||||
|
@ -201,11 +200,22 @@ int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
int i;
|
||||
|
||||
if (argc <= 1) {
|
||||
clear_altbank();
|
||||
set_lbmap(QIXIS_LBMAP_DFLTBANK);
|
||||
qixis_reset();
|
||||
} else if (strcmp(argv[1], "altbank") == 0) {
|
||||
set_altbank();
|
||||
set_lbmap(QIXIS_LBMAP_ALTBANK);
|
||||
qixis_bank_reset();
|
||||
} else if (strcmp(argv[1], "nand") == 0) {
|
||||
#ifdef QIXIS_LBMAP_NAND
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_NAND);
|
||||
set_rcw_src(QIXIS_RCW_SRC_NAND);
|
||||
QIXIS_WRITE(rcfg_ctl, 0x20);
|
||||
QIXIS_WRITE(rcfg_ctl, 0x21);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "watchdog") == 0) {
|
||||
static char *period[9] = {"2s", "4s", "8s", "16s", "32s",
|
||||
"1min", "2min", "4min", "8min"};
|
||||
|
@ -244,6 +254,7 @@ U_BOOT_CMD(
|
|||
"Reset the board using the FPGA sequencer",
|
||||
"- hard reset to default bank\n"
|
||||
"qixis_reset altbank - reset to alternate bank\n"
|
||||
"qixis_reset nand - reset to nand\n"
|
||||
"qixis watchdog <watchdog_period> - set the watchdog period\n"
|
||||
" period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n"
|
||||
"qixis_reset dump - display the QIXIS registers\n"
|
||||
|
|
|
@ -5,6 +5,7 @@ F: board/freescale/ls1021aqds/
|
|||
F: include/configs/ls1021aqds.h
|
||||
F: configs/ls1021aqds_nor_defconfig
|
||||
F: configs/ls1021aqds_ddr4_nor_defconfig
|
||||
F: configs/ls1021aqds_ddr4_nor_lpuart_defconfig
|
||||
F: configs/ls1021aqds_nor_SECURE_BOOT_defconfig
|
||||
F: configs/ls1021aqds_nor_lpuart_defconfig
|
||||
F: configs/ls1021aqds_sdcard_defconfig
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/ls102xa_stream_id.h>
|
||||
#include <asm/pcie_layerscape.h>
|
||||
#include <hwconfig.h>
|
||||
#include <mmc.h>
|
||||
#include <fsl_esdhc.h>
|
||||
|
@ -138,6 +137,17 @@ unsigned long get_board_ddr_clk(void)
|
|||
return 66666666;
|
||||
}
|
||||
|
||||
unsigned int get_soc_major_rev(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
unsigned int svr, major;
|
||||
|
||||
svr = in_be32(&gur->svr);
|
||||
major = SVR_MAJ(svr);
|
||||
|
||||
return major;
|
||||
}
|
||||
|
||||
int select_i2c_ch_pca9547(u8 ch)
|
||||
{
|
||||
int ret;
|
||||
|
@ -181,6 +191,7 @@ int board_early_init_f(void)
|
|||
{
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
|
||||
unsigned int major;
|
||||
|
||||
#ifdef CONFIG_TSEC_ENET
|
||||
out_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR);
|
||||
|
@ -205,19 +216,22 @@ int board_early_init_f(void)
|
|||
out_le32(&cci->slave[4].snoop_ctrl,
|
||||
CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
|
||||
|
||||
/*
|
||||
* Set CCI-400 Slave interface S1, S2 Shareable Override Register
|
||||
* All transactions are treated as non-shareable
|
||||
*/
|
||||
out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
major = get_soc_major_rev();
|
||||
if (major == SOC_MAJOR_VER_1_0) {
|
||||
/*
|
||||
* Set CCI-400 Slave interface S1, S2 Shareable Override
|
||||
* Register All transactions are treated as non-shareable
|
||||
*/
|
||||
out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
|
||||
/* Workaround for the issue that DDR could not respond to
|
||||
* barrier transaction which is generated by executing DSB/ISB
|
||||
* instruction. Set CCI-400 control override register to
|
||||
* terminate the barrier transaction. After DDR is initialized,
|
||||
* allow barrier transaction to DDR again */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
|
||||
/* Workaround for the issue that DDR could not respond to
|
||||
* barrier transaction which is generated by executing DSB/ISB
|
||||
* instruction. Set CCI-400 control override register to
|
||||
* terminate the barrier transaction. After DDR is initialized,
|
||||
* allow barrier transaction to DDR again */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEEP_SLEEP)
|
||||
if (is_warm_boot())
|
||||
|
@ -231,6 +245,7 @@ int board_early_init_f(void)
|
|||
void board_init_f(ulong dummy)
|
||||
{
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
|
||||
unsigned int major;
|
||||
|
||||
#ifdef CONFIG_NAND_BOOT
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
|
@ -267,7 +282,10 @@ void board_init_f(ulong dummy)
|
|||
#ifdef CONFIG_SPL_I2C_SUPPORT
|
||||
i2c_init_all();
|
||||
#endif
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
|
||||
|
||||
major = get_soc_major_rev();
|
||||
if (major == SOC_MAJOR_VER_1_0)
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
|
||||
|
||||
dram_init();
|
||||
|
||||
|
@ -548,10 +566,14 @@ struct smmu_stream_id dev_stream_id[] = {
|
|||
int board_init(void)
|
||||
{
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
|
||||
unsigned int major;
|
||||
|
||||
/* Set CCI-400 control override register to
|
||||
* enable barrier transaction */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
|
||||
major = get_soc_major_rev();
|
||||
if (major == SOC_MAJOR_VER_1_0) {
|
||||
/* Set CCI-400 control override register to
|
||||
* enable barrier transaction */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
|
||||
}
|
||||
|
||||
select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
|
||||
|
||||
|
@ -580,10 +602,15 @@ int board_init(void)
|
|||
void board_sleep_prepare(void)
|
||||
{
|
||||
struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR;
|
||||
unsigned int major;
|
||||
|
||||
major = get_soc_major_rev();
|
||||
if (major == SOC_MAJOR_VER_1_0) {
|
||||
/* Set CCI-400 control override register to
|
||||
* enable barrier transaction */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
|
||||
}
|
||||
|
||||
/* Set CCI-400 control override register to
|
||||
* enable barrier transaction */
|
||||
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
|
||||
|
||||
#ifdef CONFIG_LS102XA_NS_ACCESS
|
||||
enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev));
|
||||
|
@ -595,8 +622,8 @@ int ft_board_setup(void *blob, bd_t *bd)
|
|||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
|
||||
#ifdef CONFIG_PCIE_LAYERSCAPE
|
||||
ft_pcie_setup(blob, bd);
|
||||
#ifdef CONFIG_PCI
|
||||
ft_pci_setup(blob, bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch/ls102xa_stream_id.h>
|
||||
#include <asm/pcie_layerscape.h>
|
||||
#include <hwconfig.h>
|
||||
#include <mmc.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <fsl_ifc.h>
|
||||
|
@ -54,6 +54,17 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define KEEP_STATUS 0x0
|
||||
#define NEED_RESET 0x1
|
||||
|
||||
#define SOFT_MUX_ON_I2C3_IFC 0x2
|
||||
#define SOFT_MUX_ON_CAN3_USB2 0x8
|
||||
#define SOFT_MUX_ON_QE_LCD 0x10
|
||||
|
||||
#define PIN_I2C3_IFC_MUX_I2C3 0x0
|
||||
#define PIN_I2C3_IFC_MUX_IFC 0x1
|
||||
#define PIN_CAN3_USB2_MUX_USB2 0x0
|
||||
#define PIN_CAN3_USB2_MUX_CAN3 0x1
|
||||
#define PIN_QE_LCD_MUX_LCD 0x0
|
||||
#define PIN_QE_LCD_MUX_QE 0x1
|
||||
|
||||
struct cpld_data {
|
||||
u8 cpld_ver; /* cpld revision */
|
||||
u8 cpld_ver_sub; /* cpld sub revision */
|
||||
|
@ -122,6 +133,17 @@ int checkboard(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned int get_soc_major_rev(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
unsigned int svr, major;
|
||||
|
||||
svr = in_be32(&gur->svr);
|
||||
major = SVR_MAJ(svr);
|
||||
|
||||
return major;
|
||||
}
|
||||
|
||||
void ddrmc_init(void)
|
||||
{
|
||||
struct ccsr_ddr *ddr = (struct ccsr_ddr *)CONFIG_SYS_FSL_DDR_ADDR;
|
||||
|
@ -260,10 +282,73 @@ int config_serdes_mux(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_QSPI_BOOT
|
||||
int config_board_mux(void)
|
||||
{
|
||||
struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
|
||||
int conflict_flag;
|
||||
|
||||
conflict_flag = 0;
|
||||
if (hwconfig("i2c3")) {
|
||||
conflict_flag++;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_I2C3_IFC;
|
||||
cpld_data->i2c3_ifc_mux = PIN_I2C3_IFC_MUX_I2C3;
|
||||
}
|
||||
|
||||
if (hwconfig("ifc")) {
|
||||
conflict_flag++;
|
||||
/* some signals can not enable simultaneous*/
|
||||
if (conflict_flag > 1)
|
||||
goto conflict;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_I2C3_IFC;
|
||||
cpld_data->i2c3_ifc_mux = PIN_I2C3_IFC_MUX_IFC;
|
||||
}
|
||||
|
||||
conflict_flag = 0;
|
||||
if (hwconfig("usb2")) {
|
||||
conflict_flag++;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_CAN3_USB2;
|
||||
cpld_data->can3_usb2_mux = PIN_CAN3_USB2_MUX_USB2;
|
||||
}
|
||||
|
||||
if (hwconfig("can3")) {
|
||||
conflict_flag++;
|
||||
/* some signals can not enable simultaneous*/
|
||||
if (conflict_flag > 1)
|
||||
goto conflict;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_CAN3_USB2;
|
||||
cpld_data->can3_usb2_mux = PIN_CAN3_USB2_MUX_CAN3;
|
||||
}
|
||||
|
||||
conflict_flag = 0;
|
||||
if (hwconfig("lcd")) {
|
||||
conflict_flag++;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_QE_LCD;
|
||||
cpld_data->qe_lcd_mux = PIN_QE_LCD_MUX_LCD;
|
||||
}
|
||||
|
||||
if (hwconfig("qe")) {
|
||||
conflict_flag++;
|
||||
/* some signals can not enable simultaneous*/
|
||||
if (conflict_flag > 1)
|
||||
goto conflict;
|
||||
cpld_data->soft_mux_on |= SOFT_MUX_ON_QE_LCD;
|
||||
cpld_data->qe_lcd_mux = PIN_QE_LCD_MUX_QE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
conflict:
|
||||
printf("WARNING: pin conflict! MUX setting may failed!\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
|
||||
unsigned int major;
|
||||
|
||||
#ifdef CONFIG_TSEC_ENET
|
||||
out_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR);
|
||||
|
@ -289,12 +374,15 @@ int board_early_init_f(void)
|
|||
out_le32(&cci->slave[4].snoop_ctrl,
|
||||
CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
|
||||
|
||||
/*
|
||||
* Set CCI-400 Slave interface S1, S2 Shareable Override Register
|
||||
* All transactions are treated as non-shareable
|
||||
*/
|
||||
out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
major = get_soc_major_rev();
|
||||
if (major == SOC_MAJOR_VER_1_0) {
|
||||
/*
|
||||
* Set CCI-400 Slave interface S1, S2 Shareable Override
|
||||
* Register All transactions are treated as non-shareable
|
||||
*/
|
||||
out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -465,6 +553,10 @@ int board_init(void)
|
|||
#if defined(CONFIG_MISC_INIT_R)
|
||||
int misc_init_r(void)
|
||||
{
|
||||
#ifndef CONFIG_QSPI_BOOT
|
||||
config_board_mux();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_CAAM
|
||||
return sec_init();
|
||||
#endif
|
||||
|
@ -475,8 +567,8 @@ int ft_board_setup(void *blob, bd_t *bd)
|
|||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
|
||||
#ifdef CONFIG_PCIE_LAYERSCAPE
|
||||
ft_pcie_setup(blob, bd);
|
||||
#ifdef CONFIG_PCI
|
||||
ft_pci_setup(blob, bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#include <asm/io.h>
|
||||
#include <fdt_support.h>
|
||||
#include <libfdt.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#include <environment.h>
|
||||
#include <asm/arch-fsl-lsch3/soc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -30,8 +32,7 @@ int board_init(void)
|
|||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
init_early_memctl_regs(); /* tighten IFC timing */
|
||||
|
||||
fsl_lsch3_early_init_f();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -54,29 +55,32 @@ int dram_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
#if defined(CONFIG_ARCH_MISC_INIT)
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
|
||||
u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
|
||||
|
||||
/* Enable timebase for all clusters.
|
||||
* It is safe to do so even some clusters are not enabled.
|
||||
*/
|
||||
out_le32(cltbenr, 0xf);
|
||||
|
||||
/* Enable clock for timer
|
||||
* This is a global setting.
|
||||
*/
|
||||
out_le32(cntcr, 0x1);
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
debug_server_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Board specific reset that is system reset.
|
||||
*/
|
||||
void reset_cpu(ulong addr)
|
||||
unsigned long get_dram_size_to_hide(void)
|
||||
{
|
||||
unsigned long dram_to_hide = 0;
|
||||
|
||||
/* Carve the Debug Server private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
dram_to_hide += debug_server_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
/* Carve the MC private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
dram_to_hide += mc_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
return dram_to_hide;
|
||||
}
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
|
@ -135,6 +139,7 @@ int ft_board_setup(void *blob, bd_t *bd)
|
|||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
fdt_fixup_board_enet(blob);
|
||||
fsl_mc_ldpaa_exit(bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
16
board/freescale/ls2085aqds/Kconfig
Normal file
16
board/freescale/ls2085aqds/Kconfig
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
if TARGET_LS2085AQDS
|
||||
|
||||
config SYS_BOARD
|
||||
default "ls2085aqds"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "freescale"
|
||||
|
||||
config SYS_SOC
|
||||
default "fsl-lsch3"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "ls2085aqds"
|
||||
|
||||
endif
|
8
board/freescale/ls2085aqds/MAINTAINERS
Normal file
8
board/freescale/ls2085aqds/MAINTAINERS
Normal file
|
@ -0,0 +1,8 @@
|
|||
LS2085A BOARD
|
||||
M: Prabhakar Kushwaha <prabhakar@freescale.com>
|
||||
S: Maintained
|
||||
F: board/freescale/ls2085aqds/
|
||||
F: board/freescale/ls2085a/ls2085aqds.c
|
||||
F: include/configs/ls2085aqds.h
|
||||
F: configs/ls2085aqds_defconfig
|
||||
F: configs/ls2085aqds_nand_defconfig
|
9
board/freescale/ls2085aqds/Makefile
Normal file
9
board/freescale/ls2085aqds/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Copyright 2015 Freescale Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += ls2085aqds.o
|
||||
obj-y += ddr.o
|
||||
obj-y += eth.o
|
129
board/freescale/ls2085aqds/README
Normal file
129
board/freescale/ls2085aqds/README
Normal file
|
@ -0,0 +1,129 @@
|
|||
Overview
|
||||
--------
|
||||
The LS2085A Development System (QDS) is a high-performance computing,
|
||||
evaluation, and development platform that supports the QorIQ LS2085A
|
||||
Layerscape Architecture processor. The LS2085AQDS provides validation and
|
||||
SW development platform for the Freescale LS2085A processor series, with
|
||||
a complete debugging environment.
|
||||
|
||||
LS2085A SoC Overview
|
||||
------------------
|
||||
The LS2085A 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 LS2085A 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
|
||||
|
||||
LS2085AQDS board Overview
|
||||
-----------------------
|
||||
- SERDES Connections, 16 lanes supporting:
|
||||
- PCI Express - 3.0
|
||||
- SGMII, SGMII 2.5
|
||||
- QSGMII
|
||||
- SATA 3.0
|
||||
- XAUI
|
||||
- XFI
|
||||
- DDR Controller
|
||||
- Two ports of 72-bits (8-bits ECC) DDR4. Each port supports four
|
||||
chip-selects and two DIMM connectors. Support is up to 2133MT/s.
|
||||
- One port of 40-bits (8-bits ECC) DDR4 which supports four chip-selects
|
||||
and two DIMM connectors. Support is up to 1600MT/s.
|
||||
-IFC/Local Bus
|
||||
- IFC rev. 2.0 implementation supporting Little Endian connection scheme.
|
||||
- One in-socket 128 MB NOR flash 16-bit data bus
|
||||
- One 512 MB NAND flash with ECC support
|
||||
- IFC Test Port
|
||||
- PromJet Port
|
||||
- FPGA connection
|
||||
- USB 3.0
|
||||
- Two high speed USB 3.0 ports
|
||||
- First USB 3.0 port configured as Host with Type-A connector
|
||||
- Second USB 3.0 port configured as OTG with micro-AB connector
|
||||
- SDHC: PCIe x1 Right Angle connector for supporting following cards
|
||||
- 1/4-/8-bit SD/MMC Legacy CARD supporting 3.3V devices only
|
||||
- 1-/4-/8-bit SD/MMC Card supporting 1.8V devices only
|
||||
- 4-bit eMMC Card Rev 4.4 (1.8V only)
|
||||
- 8-bit eMMC Card Rev 4.5 (1.8V only)
|
||||
- SD Card Rev 2.0 and Rev 3.0
|
||||
- DSPI: 3 high-speed flash Memory for storage
|
||||
- 16 MB high-speed flash Memory for boot code and storage (up to 108MHz)
|
||||
- 8 MB high-speed flash Memory (up to 104 MHz)
|
||||
- 512 MB low-speed flash Memory (up to 40 MHz)
|
||||
- QSPI: via NAND/QSPI Card
|
||||
- 4 I2C controllers
|
||||
- Two SATA onboard connectors
|
||||
- UART
|
||||
- Two 4-pin (HW control) or four 2-pin (SW control) serial ports at up to 115.2 Kbit/s
|
||||
- Two DB9 D-Type connectors supporting one Serial port each
|
||||
- ARM JTAG support
|
||||
|
||||
Memory map from core's view
|
||||
----------------------------
|
||||
0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom
|
||||
0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR
|
||||
0x00_1800_0000 .. 0x00_181F_FFFF OCRAM
|
||||
0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1
|
||||
0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1
|
||||
0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2
|
||||
0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2
|
||||
|
||||
Other addresses are either reserved, or not used directly by u-boot.
|
||||
This list should be updated when more addresses are used.
|
||||
|
||||
IFC region map from core's view
|
||||
-------------------------------
|
||||
During boot i.e. IFC Region #1:-
|
||||
0x30000000 - 0x37ffffff : 128MB : NOR flash
|
||||
0x38000000 - 0x3BFFFFFF : 64MB : Promjet
|
||||
0x3C000000 - 0x40000000 : 64MB : FPGA etc
|
||||
|
||||
After relocate to DDR i.e. IFC Region #2:-
|
||||
0x5_1000_0000..0x5_1fff_ffff Memory Hole
|
||||
0x5_2000_0000..0x5_3fff_ffff IFC CSx (FPGA, NAND and others 512MB)
|
||||
0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB
|
||||
0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet)
|
||||
0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet)
|
||||
|
||||
Booting Options
|
||||
---------------
|
||||
a) Promjet Boot
|
||||
b) NOR boot
|
||||
c) NAND boot
|
||||
d) SD boot
|
||||
e) QSPI boot
|
196
board/freescale/ls2085aqds/ddr.c
Normal file
196
board/freescale/ls2085aqds/ddr.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fsl_ddr_sdram.h>
|
||||
#include <fsl_ddr_dimm_params.h>
|
||||
#include "ddr.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void fsl_ddr_board_options(memctl_options_t *popts,
|
||||
dimm_params_t *pdimm,
|
||||
unsigned int ctrl_num)
|
||||
{
|
||||
u8 dq_mapping_0, dq_mapping_2, dq_mapping_3;
|
||||
const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
|
||||
ulong ddr_freq;
|
||||
int slot;
|
||||
|
||||
if (ctrl_num > 2) {
|
||||
printf("Not supported controller number %d\n", ctrl_num);
|
||||
return;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) {
|
||||
if (pdimm[slot].n_ranks)
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR)
|
||||
return;
|
||||
|
||||
/*
|
||||
* we use identical timing for all slots. If needed, change the code
|
||||
* to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
|
||||
*/
|
||||
if (popts->registered_dimm_en)
|
||||
pbsp = rdimms[ctrl_num];
|
||||
else
|
||||
pbsp = udimms[ctrl_num];
|
||||
|
||||
|
||||
/* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
|
||||
* freqency and n_banks specified in board_specific_parameters table.
|
||||
*/
|
||||
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
|
||||
while (pbsp->datarate_mhz_high) {
|
||||
if (pbsp->n_ranks == pdimm[slot].n_ranks &&
|
||||
(pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) {
|
||||
if (ddr_freq <= pbsp->datarate_mhz_high) {
|
||||
popts->clk_adjust = pbsp->clk_adjust;
|
||||
popts->wrlvl_start = pbsp->wrlvl_start;
|
||||
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
|
||||
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
|
||||
goto found;
|
||||
}
|
||||
pbsp_highest = pbsp;
|
||||
}
|
||||
pbsp++;
|
||||
}
|
||||
|
||||
if (pbsp_highest) {
|
||||
printf("Error: board specific timing not found for data rate %lu MT/s\n"
|
||||
"Trying to use the highest speed (%u) parameters\n",
|
||||
ddr_freq, pbsp_highest->datarate_mhz_high);
|
||||
popts->clk_adjust = pbsp_highest->clk_adjust;
|
||||
popts->wrlvl_start = pbsp_highest->wrlvl_start;
|
||||
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
|
||||
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
|
||||
} else {
|
||||
panic("DIMM is not supported by this board");
|
||||
}
|
||||
found:
|
||||
debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
|
||||
"\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n",
|
||||
pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
|
||||
pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
|
||||
pbsp->wrlvl_ctl_3);
|
||||
|
||||
if (ctrl_num == CONFIG_DP_DDR_CTRL) {
|
||||
/* force DDR bus width to 32 bits */
|
||||
popts->data_bus_width = 1;
|
||||
popts->otf_burst_chop_en = 0;
|
||||
popts->burst_length = DDR_BL8;
|
||||
popts->bstopre = 0; /* enable auto precharge */
|
||||
/*
|
||||
* Layout optimization results byte mapping
|
||||
* Byte 0 -> Byte ECC
|
||||
* Byte 1 -> Byte 3
|
||||
* Byte 2 -> Byte 2
|
||||
* Byte 3 -> Byte 1
|
||||
* Byte ECC -> Byte 0
|
||||
*/
|
||||
dq_mapping_0 = pdimm[slot].dq_mapping[0];
|
||||
dq_mapping_2 = pdimm[slot].dq_mapping[2];
|
||||
dq_mapping_3 = pdimm[slot].dq_mapping[3];
|
||||
pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8];
|
||||
pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9];
|
||||
pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6];
|
||||
pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7];
|
||||
pdimm[slot].dq_mapping[6] = dq_mapping_2;
|
||||
pdimm[slot].dq_mapping[7] = dq_mapping_3;
|
||||
pdimm[slot].dq_mapping[8] = dq_mapping_0;
|
||||
pdimm[slot].dq_mapping[9] = 0;
|
||||
pdimm[slot].dq_mapping[10] = 0;
|
||||
pdimm[slot].dq_mapping[11] = 0;
|
||||
pdimm[slot].dq_mapping[12] = 0;
|
||||
pdimm[slot].dq_mapping[13] = 0;
|
||||
pdimm[slot].dq_mapping[14] = 0;
|
||||
pdimm[slot].dq_mapping[15] = 0;
|
||||
pdimm[slot].dq_mapping[16] = 0;
|
||||
pdimm[slot].dq_mapping[17] = 0;
|
||||
}
|
||||
/* To work at higher than 1333MT/s */
|
||||
popts->half_strength_driver_enable = 0;
|
||||
/*
|
||||
* Write leveling override
|
||||
*/
|
||||
popts->wrlvl_override = 1;
|
||||
popts->wrlvl_sample = 0x0; /* 32 clocks */
|
||||
|
||||
/*
|
||||
* Rtt and Rtt_WR override
|
||||
*/
|
||||
popts->rtt_override = 0;
|
||||
|
||||
/* Enable ZQ calibration */
|
||||
popts->zq_en = 1;
|
||||
|
||||
if (ddr_freq < 2350) {
|
||||
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
|
||||
DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
|
||||
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
|
||||
DDR_CDR2_VREF_RANGE_2;
|
||||
} else {
|
||||
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
|
||||
DDR_CDR1_ODT(DDR_CDR_ODT_100ohm);
|
||||
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) |
|
||||
DDR_CDR2_VREF_RANGE_2;
|
||||
}
|
||||
}
|
||||
|
||||
phys_size_t initdram(int board_type)
|
||||
{
|
||||
phys_size_t dram_size;
|
||||
|
||||
#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
|
||||
return fsl_ddr_sdram_size();
|
||||
#else
|
||||
puts("Initializing DDR....using SPD\n");
|
||||
|
||||
dram_size = fsl_ddr_sdram();
|
||||
#endif
|
||||
|
||||
return dram_size;
|
||||
}
|
||||
|
||||
void dram_init_banksize(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
|
||||
phys_size_t dp_ddr_size;
|
||||
#endif
|
||||
|
||||
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
|
||||
if (gd->ram_size > CONFIG_SYS_LS2_DDR_BLOCK1_SIZE) {
|
||||
gd->bd->bi_dram[0].size = CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
|
||||
gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
|
||||
gd->bd->bi_dram[1].size = gd->ram_size -
|
||||
CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
|
||||
} else {
|
||||
gd->bd->bi_dram[0].size = gd->ram_size;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
|
||||
/* initialize DP-DDR here */
|
||||
puts("DP-DDR: ");
|
||||
/*
|
||||
* DDR controller use 0 as the base address for binding.
|
||||
* It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access.
|
||||
*/
|
||||
dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY,
|
||||
CONFIG_DP_DDR_CTRL,
|
||||
CONFIG_DP_DDR_NUM_CTRLS,
|
||||
CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR,
|
||||
NULL, NULL, NULL);
|
||||
if (dp_ddr_size) {
|
||||
gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE;
|
||||
gd->bd->bi_dram[2].size = dp_ddr_size;
|
||||
} else {
|
||||
puts("Not detected");
|
||||
}
|
||||
#endif
|
||||
}
|
92
board/freescale/ls2085aqds/ddr.h
Normal file
92
board/freescale/ls2085aqds/ddr.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __DDR_H__
|
||||
#define __DDR_H__
|
||||
struct board_specific_parameters {
|
||||
u32 n_ranks;
|
||||
u32 datarate_mhz_high;
|
||||
u32 rank_gb;
|
||||
u32 clk_adjust;
|
||||
u32 wrlvl_start;
|
||||
u32 wrlvl_ctl_2;
|
||||
u32 wrlvl_ctl_3;
|
||||
};
|
||||
|
||||
/*
|
||||
* These tables contain all valid speeds we want to override with board
|
||||
* specific parameters. datarate_mhz_high values need to be in ascending order
|
||||
* for each n_ranks group.
|
||||
*/
|
||||
|
||||
static const struct board_specific_parameters udimm0[] = {
|
||||
/*
|
||||
* memory controller 0
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,},
|
||||
{2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,},
|
||||
{2, 2300, 0, 4, 8, 0x090A0C0F, 0x1012130C,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* DP-DDR DIMM */
|
||||
static const struct board_specific_parameters udimm2[] = {
|
||||
/*
|
||||
* memory controller 2
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,},
|
||||
{2, 1666, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,},
|
||||
{2, 1900, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,},
|
||||
{2, 2200, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters rdimm0[] = {
|
||||
/*
|
||||
* memory controller 0
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,},
|
||||
{2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,},
|
||||
{2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* DP-DDR DIMM */
|
||||
static const struct board_specific_parameters rdimm2[] = {
|
||||
/*
|
||||
* memory controller 2
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 7, 0x0B0A090C, 0x0D0F100B,},
|
||||
{2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,},
|
||||
{2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters *udimms[] = {
|
||||
udimm0,
|
||||
udimm0,
|
||||
udimm2,
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters *rdimms[] = {
|
||||
rdimm0,
|
||||
rdimm0,
|
||||
rdimm2,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
380
board/freescale/ls2085aqds/eth.c
Normal file
380
board/freescale/ls2085aqds/eth.c
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <netdev.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
|
||||
#include <fsl_mdio.h>
|
||||
#include <malloc.h>
|
||||
#include <fm_eth.h>
|
||||
#include <fsl-mc/ldpaa_wriop.h>
|
||||
|
||||
#include "../common/qixis.h"
|
||||
|
||||
#include "ls2085aqds_qixis.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
/* - In LS2085A there are only 16 SERDES lanes, spread across 2 SERDES banks.
|
||||
* Bank 1 -> Lanes A, B, C, D, E, F, G, H
|
||||
* Bank 2 -> Lanes A,B, C, D, E, F, G, H
|
||||
*/
|
||||
|
||||
/* Mapping of 16 SERDES lanes to LS2085A QDS board slots. A value of '0' here
|
||||
* means that the mapping must be determined dynamically, or that the lane
|
||||
* maps to something other than a board slot.
|
||||
*/
|
||||
|
||||
static u8 lane_to_slot_fsm2[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs
|
||||
* housed.
|
||||
*/
|
||||
static int riser_phy_addr[] = {
|
||||
SGMII_CARD_PORT1_PHY_ADDR,
|
||||
SGMII_CARD_PORT2_PHY_ADDR,
|
||||
SGMII_CARD_PORT3_PHY_ADDR,
|
||||
SGMII_CARD_PORT4_PHY_ADDR,
|
||||
};
|
||||
|
||||
/* Slot2 does not have EMI connections */
|
||||
#define EMI_NONE 0xFFFFFFFF
|
||||
#define EMI1_SLOT1 0
|
||||
#define EMI1_SLOT2 1
|
||||
#define EMI1_SLOT3 2
|
||||
#define EMI1_SLOT4 3
|
||||
#define EMI1_SLOT5 4
|
||||
#define EMI1_SLOT6 5
|
||||
#define EMI2 6
|
||||
#define SFP_TX 1
|
||||
|
||||
static const char * const mdio_names[] = {
|
||||
"LS2085A_QDS_MDIO0",
|
||||
"LS2085A_QDS_MDIO1",
|
||||
"LS2085A_QDS_MDIO2",
|
||||
"LS2085A_QDS_MDIO3",
|
||||
"LS2085A_QDS_MDIO4",
|
||||
"LS2085A_QDS_MDIO5",
|
||||
DEFAULT_WRIOP_MDIO2_NAME,
|
||||
};
|
||||
|
||||
struct ls2085a_qds_mdio {
|
||||
u8 muxval;
|
||||
struct mii_dev *realbus;
|
||||
};
|
||||
|
||||
static const char *ls2085a_qds_mdio_name_for_muxval(u8 muxval)
|
||||
{
|
||||
return mdio_names[muxval];
|
||||
}
|
||||
|
||||
struct mii_dev *mii_dev_for_muxval(u8 muxval)
|
||||
{
|
||||
struct mii_dev *bus;
|
||||
const char *name = ls2085a_qds_mdio_name_for_muxval(muxval);
|
||||
|
||||
if (!name) {
|
||||
printf("No bus for muxval %x\n", muxval);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bus = miiphy_get_dev_by_name(name);
|
||||
|
||||
if (!bus) {
|
||||
printf("No bus by name %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
static void ls2085a_qds_enable_SFP_TX(u8 muxval)
|
||||
{
|
||||
u8 brdcfg9;
|
||||
|
||||
brdcfg9 = QIXIS_READ(brdcfg[9]);
|
||||
brdcfg9 &= ~BRDCFG9_SFPTX_MASK;
|
||||
brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT);
|
||||
QIXIS_WRITE(brdcfg[9], brdcfg9);
|
||||
}
|
||||
|
||||
static void ls2085a_qds_mux_mdio(u8 muxval)
|
||||
{
|
||||
u8 brdcfg4;
|
||||
|
||||
if (muxval <= 5) {
|
||||
brdcfg4 = QIXIS_READ(brdcfg[4]);
|
||||
brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
|
||||
brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
|
||||
QIXIS_WRITE(brdcfg[4], brdcfg4);
|
||||
}
|
||||
}
|
||||
|
||||
static int ls2085a_qds_mdio_read(struct mii_dev *bus, int addr,
|
||||
int devad, int regnum)
|
||||
{
|
||||
struct ls2085a_qds_mdio *priv = bus->priv;
|
||||
|
||||
ls2085a_qds_mux_mdio(priv->muxval);
|
||||
|
||||
return priv->realbus->read(priv->realbus, addr, devad, regnum);
|
||||
}
|
||||
|
||||
static int ls2085a_qds_mdio_write(struct mii_dev *bus, int addr, int devad,
|
||||
int regnum, u16 value)
|
||||
{
|
||||
struct ls2085a_qds_mdio *priv = bus->priv;
|
||||
|
||||
ls2085a_qds_mux_mdio(priv->muxval);
|
||||
|
||||
return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
|
||||
}
|
||||
|
||||
static int ls2085a_qds_mdio_reset(struct mii_dev *bus)
|
||||
{
|
||||
struct ls2085a_qds_mdio *priv = bus->priv;
|
||||
|
||||
return priv->realbus->reset(priv->realbus);
|
||||
}
|
||||
|
||||
static int ls2085a_qds_mdio_init(char *realbusname, u8 muxval)
|
||||
{
|
||||
struct ls2085a_qds_mdio *pmdio;
|
||||
struct mii_dev *bus = mdio_alloc();
|
||||
|
||||
if (!bus) {
|
||||
printf("Failed to allocate ls2085a_qds MDIO bus\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmdio = malloc(sizeof(*pmdio));
|
||||
if (!pmdio) {
|
||||
printf("Failed to allocate ls2085a_qds private data\n");
|
||||
free(bus);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bus->read = ls2085a_qds_mdio_read;
|
||||
bus->write = ls2085a_qds_mdio_write;
|
||||
bus->reset = ls2085a_qds_mdio_reset;
|
||||
sprintf(bus->name, ls2085a_qds_mdio_name_for_muxval(muxval));
|
||||
|
||||
pmdio->realbus = miiphy_get_dev_by_name(realbusname);
|
||||
|
||||
if (!pmdio->realbus) {
|
||||
printf("No bus with name %s\n", realbusname);
|
||||
free(bus);
|
||||
free(pmdio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmdio->muxval = muxval;
|
||||
bus->priv = pmdio;
|
||||
|
||||
return mdio_register(bus);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the dpmac_info array.
|
||||
*
|
||||
*/
|
||||
static void initialize_dpmac_to_slot(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
|
||||
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
|
||||
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
|
||||
int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) &
|
||||
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK)
|
||||
>> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
|
||||
|
||||
|
||||
switch (serdes1_prtcl) {
|
||||
case 0x2A:
|
||||
printf("qds: WRIOP: Supported SerDes Protocol 0x%02x\n",
|
||||
serdes1_prtcl);
|
||||
break;
|
||||
default:
|
||||
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
|
||||
serdes1_prtcl);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (serdes2_prtcl) {
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
printf("qds: WRIOP: Supported SerDes Protocol 0x%02x\n",
|
||||
serdes2_prtcl);
|
||||
lane_to_slot_fsm2[0] = EMI1_SLOT4;
|
||||
lane_to_slot_fsm2[1] = EMI1_SLOT4;
|
||||
lane_to_slot_fsm2[2] = EMI1_SLOT4;
|
||||
lane_to_slot_fsm2[3] = EMI1_SLOT4;
|
||||
/* No MDIO physical connection */
|
||||
lane_to_slot_fsm2[4] = EMI1_SLOT6;
|
||||
lane_to_slot_fsm2[5] = EMI1_SLOT6;
|
||||
lane_to_slot_fsm2[6] = EMI1_SLOT6;
|
||||
lane_to_slot_fsm2[7] = EMI1_SLOT6;
|
||||
break;
|
||||
default:
|
||||
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
|
||||
serdes2_prtcl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ls2085a_handle_phy_interface_sgmii(int dpmac_id)
|
||||
{
|
||||
int lane, slot;
|
||||
struct mii_dev *bus;
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
|
||||
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
|
||||
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
|
||||
int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) &
|
||||
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK)
|
||||
>> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
|
||||
|
||||
switch (serdes1_prtcl) {
|
||||
}
|
||||
|
||||
switch (serdes2_prtcl) {
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
lane = serdes_get_first_lane(FSL_SRDS_2, SGMII9 +
|
||||
(dpmac_id - 9));
|
||||
slot = lane_to_slot_fsm2[lane];
|
||||
|
||||
switch (++slot) {
|
||||
case 1:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
/* Slot housing a SGMII riser card? */
|
||||
wriop_set_phy_address(dpmac_id,
|
||||
riser_phy_addr[dpmac_id - 9]);
|
||||
dpmac_info[dpmac_id].board_mux = EMI1_SLOT4;
|
||||
bus = mii_dev_for_muxval(EMI1_SLOT4);
|
||||
wriop_set_mdio(dpmac_id, bus);
|
||||
dpmac_info[dpmac_id].phydev = phy_connect(
|
||||
dpmac_info[dpmac_id].bus,
|
||||
dpmac_info[dpmac_id].phy_addr,
|
||||
NULL,
|
||||
dpmac_info[dpmac_id].enet_if);
|
||||
phy_config(dpmac_info[dpmac_id].phydev);
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
/* Slot housing a SGMII riser card? */
|
||||
wriop_set_phy_address(dpmac_id,
|
||||
riser_phy_addr[dpmac_id - 13]);
|
||||
dpmac_info[dpmac_id].board_mux = EMI1_SLOT6;
|
||||
bus = mii_dev_for_muxval(EMI1_SLOT6);
|
||||
wriop_set_mdio(dpmac_id, bus);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
|
||||
serdes2_prtcl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void ls2085a_handle_phy_interface_xsgmii(int i)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
|
||||
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
|
||||
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
|
||||
|
||||
switch (serdes1_prtcl) {
|
||||
case 0x2A:
|
||||
/*
|
||||
* XFI does not need a PHY to work, but to avoid U-boot use
|
||||
* default PHY address which is zero to a MAC when it found
|
||||
* a MAC has no PHY address, we give a PHY address to XFI
|
||||
* MAC, and should not use a real XAUI PHY address, since
|
||||
* MDIO can access it successfully, and then MDIO thinks
|
||||
* the XAUI card is used for the XFI MAC, which will cause
|
||||
* error.
|
||||
*/
|
||||
wriop_set_phy_address(i, i + 4);
|
||||
ls2085a_qds_enable_SFP_TX(SFP_TX);
|
||||
|
||||
break;
|
||||
default:
|
||||
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
|
||||
serdes1_prtcl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
int error;
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
struct memac_mdio_info *memac_mdio0_info;
|
||||
struct memac_mdio_info *memac_mdio1_info;
|
||||
unsigned int i;
|
||||
|
||||
initialize_dpmac_to_slot();
|
||||
|
||||
memac_mdio0_info = (struct memac_mdio_info *)malloc(
|
||||
sizeof(struct memac_mdio_info));
|
||||
memac_mdio0_info->regs =
|
||||
(struct memac_mdio_controller *)
|
||||
CONFIG_SYS_FSL_WRIOP1_MDIO1;
|
||||
memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME;
|
||||
|
||||
/* Register the real MDIO1 bus */
|
||||
fm_memac_mdio_init(bis, memac_mdio0_info);
|
||||
|
||||
memac_mdio1_info = (struct memac_mdio_info *)malloc(
|
||||
sizeof(struct memac_mdio_info));
|
||||
memac_mdio1_info->regs =
|
||||
(struct memac_mdio_controller *)
|
||||
CONFIG_SYS_FSL_WRIOP1_MDIO2;
|
||||
memac_mdio1_info->name = DEFAULT_WRIOP_MDIO2_NAME;
|
||||
|
||||
/* Register the real MDIO2 bus */
|
||||
fm_memac_mdio_init(bis, memac_mdio1_info);
|
||||
|
||||
/* Register the muxing front-ends to the MDIO buses */
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1);
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT2);
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT3);
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT4);
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT5);
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT6);
|
||||
|
||||
ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO2_NAME, EMI2);
|
||||
|
||||
for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
|
||||
switch (wriop_get_enet_if(i)) {
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
ls2085a_handle_phy_interface_sgmii(i);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_XGMII:
|
||||
ls2085a_handle_phy_interface_xsgmii(i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
error = cpu_eth_init(bis);
|
||||
#endif
|
||||
error = pci_eth_init(bis);
|
||||
return error;
|
||||
}
|
274
board/freescale/ls2085aqds/ls2085aqds.c
Normal file
274
board/freescale/ls2085aqds/ls2085aqds.c
Normal file
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <netdev.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <fsl_ddr.h>
|
||||
#include <asm/io.h>
|
||||
#include <fdt_support.h>
|
||||
#include <libfdt.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#include <environment.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/arch-fsl-lsch3/soc.h>
|
||||
|
||||
#include "../common/qixis.h"
|
||||
#include "ls2085aqds_qixis.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
unsigned long long get_qixis_addr(void)
|
||||
{
|
||||
unsigned long long addr;
|
||||
|
||||
if (gd->flags & GD_FLG_RELOC)
|
||||
addr = QIXIS_BASE_PHYS;
|
||||
else
|
||||
addr = QIXIS_BASE_PHYS_EARLY;
|
||||
|
||||
/*
|
||||
* IFC address under 256MB is mapped to 0x30000000, any address above
|
||||
* is mapped to 0x5_10000000 up to 4GB.
|
||||
*/
|
||||
addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
char buf[64];
|
||||
u8 sw;
|
||||
static const char *const freq[] = {"100", "125", "156.25",
|
||||
"100 separate SSCG"};
|
||||
int clock;
|
||||
|
||||
sw = QIXIS_READ(arch);
|
||||
printf("Board: %s, ", CONFIG_IDENT_STRING);
|
||||
printf("Board Arch: V%d, ", sw >> 4);
|
||||
printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1);
|
||||
|
||||
sw = QIXIS_READ(brdcfg[0]);
|
||||
sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
|
||||
|
||||
if (sw < 0x8)
|
||||
printf("vBank: %d\n", sw);
|
||||
else if (sw == 0x8)
|
||||
puts("PromJet\n");
|
||||
else if (sw == 0x9)
|
||||
puts("NAND\n");
|
||||
else if (sw == 0x15)
|
||||
printf("IFCCard\n");
|
||||
else
|
||||
printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
|
||||
|
||||
printf("FPGA: v%d (%s), build %d",
|
||||
(int)QIXIS_READ(scver), qixis_read_tag(buf),
|
||||
(int)qixis_read_minor());
|
||||
/* the timestamp string contains "\n" at the end */
|
||||
printf(" on %s", qixis_read_time(buf));
|
||||
|
||||
/*
|
||||
* Display the actual SERDES reference clocks as configured by the
|
||||
* dip switches on the board. Note that the SWx registers could
|
||||
* technically be set to force the reference clocks to match the
|
||||
* values that the SERDES expects (or vice versa). For now, however,
|
||||
* we just display both values and hope the user notices when they
|
||||
* don't match.
|
||||
*/
|
||||
puts("SERDES1 Reference : ");
|
||||
sw = QIXIS_READ(brdcfg[2]);
|
||||
clock = (sw >> 6) & 3;
|
||||
printf("Clock1 = %sMHz ", freq[clock]);
|
||||
clock = (sw >> 4) & 3;
|
||||
printf("Clock2 = %sMHz", freq[clock]);
|
||||
|
||||
puts("\nSERDES2 Reference : ");
|
||||
clock = (sw >> 2) & 3;
|
||||
printf("Clock1 = %sMHz ", freq[clock]);
|
||||
clock = (sw >> 0) & 3;
|
||||
printf("Clock2 = %sMHz\n", freq[clock]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long get_board_sys_clk(void)
|
||||
{
|
||||
u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
|
||||
|
||||
switch (sysclk_conf & 0x0F) {
|
||||
case QIXIS_SYSCLK_83:
|
||||
return 83333333;
|
||||
case QIXIS_SYSCLK_100:
|
||||
return 100000000;
|
||||
case QIXIS_SYSCLK_125:
|
||||
return 125000000;
|
||||
case QIXIS_SYSCLK_133:
|
||||
return 133333333;
|
||||
case QIXIS_SYSCLK_150:
|
||||
return 150000000;
|
||||
case QIXIS_SYSCLK_160:
|
||||
return 160000000;
|
||||
case QIXIS_SYSCLK_166:
|
||||
return 166666666;
|
||||
}
|
||||
return 66666666;
|
||||
}
|
||||
|
||||
unsigned long get_board_ddr_clk(void)
|
||||
{
|
||||
u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
|
||||
|
||||
switch ((ddrclk_conf & 0x30) >> 4) {
|
||||
case QIXIS_DDRCLK_100:
|
||||
return 100000000;
|
||||
case QIXIS_DDRCLK_125:
|
||||
return 125000000;
|
||||
case QIXIS_DDRCLK_133:
|
||||
return 133333333;
|
||||
}
|
||||
return 66666666;
|
||||
}
|
||||
|
||||
int select_i2c_ch_pca9547(u8 ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
|
||||
if (ret) {
|
||||
puts("PCA: failed to select proper channel\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
init_final_memctl_regs();
|
||||
|
||||
#ifdef CONFIG_ENV_IS_NOWHERE
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
#endif
|
||||
select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
fsl_lsch3_early_init_f();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void detail_board_ddr_info(void)
|
||||
{
|
||||
puts("\nDDR ");
|
||||
print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
|
||||
print_ddr_info(0);
|
||||
if (gd->bd->bi_dram[2].size) {
|
||||
puts("\nDP-DDR ");
|
||||
print_size(gd->bd->bi_dram[2].size, "");
|
||||
print_ddr_info(CONFIG_DP_DDR_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
gd->ram_size = initdram(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MISC_INIT)
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
debug_server_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long get_dram_size_to_hide(void)
|
||||
{
|
||||
unsigned long dram_to_hide = 0;
|
||||
|
||||
/* Carve the Debug Server private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
dram_to_hide += debug_server_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
/* Carve the MC private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
dram_to_hide += mc_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
return dram_to_hide;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
void fdt_fixup_board_enet(void *fdt)
|
||||
{
|
||||
int offset;
|
||||
|
||||
offset = fdt_path_offset(fdt, "/fsl-mc");
|
||||
|
||||
if (offset < 0)
|
||||
offset = fdt_path_offset(fdt, "/fsl,dprc@0");
|
||||
|
||||
if (offset < 0) {
|
||||
printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
|
||||
__func__, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_mc_boot_status() == 0)
|
||||
fdt_status_okay(fdt, offset);
|
||||
else
|
||||
fdt_status_fail(fdt, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
phys_addr_t base;
|
||||
phys_size_t size;
|
||||
|
||||
ft_cpu_setup(blob, bd);
|
||||
|
||||
/* limit the memory size to bank 1 until Linux can handle 40-bit PA */
|
||||
base = getenv_bootm_low();
|
||||
size = getenv_bootm_size();
|
||||
fdt_fixup_memory(blob, (u64)base, (u64)size);
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
fdt_fixup_board_enet(blob);
|
||||
fsl_mc_ldpaa_exit(bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void qixis_dump_switch(void)
|
||||
{
|
||||
int i, nr_of_cfgsw;
|
||||
|
||||
QIXIS_WRITE(cms[0], 0x00);
|
||||
nr_of_cfgsw = QIXIS_READ(cms[1]);
|
||||
|
||||
puts("DIP switch settings dump:\n");
|
||||
for (i = 1; i <= nr_of_cfgsw; i++) {
|
||||
QIXIS_WRITE(cms[0], i);
|
||||
printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1]));
|
||||
}
|
||||
}
|
30
board/freescale/ls2085aqds/ls2085aqds_qixis.h
Normal file
30
board/freescale/ls2085aqds/ls2085aqds_qixis.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __LS2_QDS_QIXIS_H__
|
||||
#define __LS2_QDS_QIXIS_H__
|
||||
|
||||
/* SYSCLK */
|
||||
#define QIXIS_SYSCLK_66 0x0
|
||||
#define QIXIS_SYSCLK_83 0x1
|
||||
#define QIXIS_SYSCLK_100 0x2
|
||||
#define QIXIS_SYSCLK_125 0x3
|
||||
#define QIXIS_SYSCLK_133 0x4
|
||||
#define QIXIS_SYSCLK_150 0x5
|
||||
#define QIXIS_SYSCLK_160 0x6
|
||||
#define QIXIS_SYSCLK_166 0x7
|
||||
|
||||
/* DDRCLK */
|
||||
#define QIXIS_DDRCLK_66 0x0
|
||||
#define QIXIS_DDRCLK_100 0x1
|
||||
#define QIXIS_DDRCLK_125 0x2
|
||||
#define QIXIS_DDRCLK_133 0x3
|
||||
|
||||
#define BRDCFG4_EMISEL_MASK 0xE0
|
||||
#define BRDCFG4_EMISEL_SHIFT 5
|
||||
#define BRDCFG9_SFPTX_MASK 0x10
|
||||
#define BRDCFG9_SFPTX_SHIFT 4
|
||||
#endif /*__LS2_QDS_QIXIS_H__*/
|
16
board/freescale/ls2085ardb/Kconfig
Normal file
16
board/freescale/ls2085ardb/Kconfig
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
if TARGET_LS2085ARDB
|
||||
|
||||
config SYS_BOARD
|
||||
default "ls2085ardb"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "freescale"
|
||||
|
||||
config SYS_SOC
|
||||
default "fsl-lsch3"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "ls2085ardb"
|
||||
|
||||
endif
|
8
board/freescale/ls2085ardb/MAINTAINERS
Normal file
8
board/freescale/ls2085ardb/MAINTAINERS
Normal file
|
@ -0,0 +1,8 @@
|
|||
LS2085A BOARD
|
||||
M: Prabhakar Kushwaha <prabhakar@freescale.com>
|
||||
S: Maintained
|
||||
F: board/freescale/ls2085ardb/
|
||||
F: board/freescale/ls2085a/ls2085ardb.c
|
||||
F: include/configs/ls2085ardb.h
|
||||
F: configs/ls2085ardb_defconfig
|
||||
F: configs/ls2085ardb_nand_defconfig
|
8
board/freescale/ls2085ardb/Makefile
Normal file
8
board/freescale/ls2085ardb/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# Copyright 2015 Freescale Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += ls2085ardb.o
|
||||
obj-y += ddr.o
|
109
board/freescale/ls2085ardb/README
Normal file
109
board/freescale/ls2085ardb/README
Normal file
|
@ -0,0 +1,109 @@
|
|||
Overview
|
||||
--------
|
||||
The LS2085A Reference Design (RDB) is a high-performance computing,
|
||||
evaluation, and development platform that supports the QorIQ LS2085A
|
||||
Layerscape Architecture processor.
|
||||
|
||||
LS2085A SoC Overview
|
||||
------------------
|
||||
The LS2085A 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 LS2085A 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
|
||||
|
||||
LS2085ARDB board Overview
|
||||
-----------------------
|
||||
- SERDES Connections, 16 lanes supporting:
|
||||
- PCI Express - 3.0
|
||||
- SATA 3.0
|
||||
- XFI
|
||||
- DDR Controller
|
||||
- Two ports of 72-bits (8-bits ECC) DDR4. Each port supports four
|
||||
chip-selects and two DIMM connectors. Support is up to 2133MT/s.
|
||||
- One port of 40-bits (8-bits ECC) DDR4 which supports four chip-selects
|
||||
and two DIMM connectors. Support is up to 1600MT/s.
|
||||
-IFC/Local Bus
|
||||
- IFC rev. 2.0 implementation supporting Little Endian connection scheme.
|
||||
- 128 MB NOR flash 16-bit data bus
|
||||
- One 2 GB NAND flash with ECC support
|
||||
- CPLD connection
|
||||
- USB 3.0
|
||||
- Two high speed USB 3.0 ports
|
||||
- First USB 3.0 port configured as Host with Type-A connector
|
||||
- Second USB 3.0 port configured as OTG with micro-AB connector
|
||||
- SDHC adapter
|
||||
- SD Card Rev 2.0 and Rev 3.0
|
||||
- DSPI
|
||||
- 128 MB high-speed flash Memory for boot code and storage (up to 108MHz)
|
||||
- 4 I2C controllers
|
||||
- Two SATA onboard connectors
|
||||
- UART
|
||||
- ARM JTAG support
|
||||
|
||||
Memory map from core's view
|
||||
----------------------------
|
||||
0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom
|
||||
0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR
|
||||
0x00_1800_0000 .. 0x00_181F_FFFF OCRAM
|
||||
0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1
|
||||
0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1
|
||||
0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2
|
||||
0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2
|
||||
|
||||
Other addresses are either reserved, or not used directly by u-boot.
|
||||
This list should be updated when more addresses are used.
|
||||
|
||||
IFC region map from core's view
|
||||
-------------------------------
|
||||
During boot i.e. IFC Region #1:-
|
||||
0x30000000 - 0x37ffffff : 128MB : NOR flash
|
||||
0x3C000000 - 0x40000000 : 64MB : CPLD
|
||||
|
||||
After relocate to DDR i.e. IFC Region #2:-
|
||||
0x5_1000_0000..0x5_1fff_ffff Memory Hole
|
||||
0x5_2000_0000..0x5_3fff_ffff IFC CSx (CPLD, NAND and others 512MB)
|
||||
0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB
|
||||
0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet)
|
||||
0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet)
|
||||
|
||||
Booting Options
|
||||
---------------
|
||||
a) NOR boot
|
||||
b) NAND boot
|
196
board/freescale/ls2085ardb/ddr.c
Normal file
196
board/freescale/ls2085ardb/ddr.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fsl_ddr_sdram.h>
|
||||
#include <fsl_ddr_dimm_params.h>
|
||||
#include "ddr.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void fsl_ddr_board_options(memctl_options_t *popts,
|
||||
dimm_params_t *pdimm,
|
||||
unsigned int ctrl_num)
|
||||
{
|
||||
u8 dq_mapping_0, dq_mapping_2, dq_mapping_3;
|
||||
const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
|
||||
ulong ddr_freq;
|
||||
int slot;
|
||||
|
||||
if (ctrl_num > 2) {
|
||||
printf("Not supported controller number %d\n", ctrl_num);
|
||||
return;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) {
|
||||
if (pdimm[slot].n_ranks)
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR)
|
||||
return;
|
||||
|
||||
/*
|
||||
* we use identical timing for all slots. If needed, change the code
|
||||
* to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
|
||||
*/
|
||||
if (popts->registered_dimm_en)
|
||||
pbsp = rdimms[ctrl_num];
|
||||
else
|
||||
pbsp = udimms[ctrl_num];
|
||||
|
||||
|
||||
/* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
|
||||
* freqency and n_banks specified in board_specific_parameters table.
|
||||
*/
|
||||
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
|
||||
while (pbsp->datarate_mhz_high) {
|
||||
if (pbsp->n_ranks == pdimm[slot].n_ranks &&
|
||||
(pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) {
|
||||
if (ddr_freq <= pbsp->datarate_mhz_high) {
|
||||
popts->clk_adjust = pbsp->clk_adjust;
|
||||
popts->wrlvl_start = pbsp->wrlvl_start;
|
||||
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
|
||||
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
|
||||
goto found;
|
||||
}
|
||||
pbsp_highest = pbsp;
|
||||
}
|
||||
pbsp++;
|
||||
}
|
||||
|
||||
if (pbsp_highest) {
|
||||
printf("Error: board specific timing not found for data rate %lu MT/s\n"
|
||||
"Trying to use the highest speed (%u) parameters\n",
|
||||
ddr_freq, pbsp_highest->datarate_mhz_high);
|
||||
popts->clk_adjust = pbsp_highest->clk_adjust;
|
||||
popts->wrlvl_start = pbsp_highest->wrlvl_start;
|
||||
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
|
||||
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
|
||||
} else {
|
||||
panic("DIMM is not supported by this board");
|
||||
}
|
||||
found:
|
||||
debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
|
||||
"\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n",
|
||||
pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
|
||||
pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
|
||||
pbsp->wrlvl_ctl_3);
|
||||
|
||||
if (ctrl_num == CONFIG_DP_DDR_CTRL) {
|
||||
/* force DDR bus width to 32 bits */
|
||||
popts->data_bus_width = 1;
|
||||
popts->otf_burst_chop_en = 0;
|
||||
popts->burst_length = DDR_BL8;
|
||||
popts->bstopre = 0; /* enable auto precharge */
|
||||
/*
|
||||
* Layout optimization results byte mapping
|
||||
* Byte 0 -> Byte ECC
|
||||
* Byte 1 -> Byte 3
|
||||
* Byte 2 -> Byte 2
|
||||
* Byte 3 -> Byte 1
|
||||
* Byte ECC -> Byte 0
|
||||
*/
|
||||
dq_mapping_0 = pdimm[slot].dq_mapping[0];
|
||||
dq_mapping_2 = pdimm[slot].dq_mapping[2];
|
||||
dq_mapping_3 = pdimm[slot].dq_mapping[3];
|
||||
pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8];
|
||||
pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9];
|
||||
pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6];
|
||||
pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7];
|
||||
pdimm[slot].dq_mapping[6] = dq_mapping_2;
|
||||
pdimm[slot].dq_mapping[7] = dq_mapping_3;
|
||||
pdimm[slot].dq_mapping[8] = dq_mapping_0;
|
||||
pdimm[slot].dq_mapping[9] = 0;
|
||||
pdimm[slot].dq_mapping[10] = 0;
|
||||
pdimm[slot].dq_mapping[11] = 0;
|
||||
pdimm[slot].dq_mapping[12] = 0;
|
||||
pdimm[slot].dq_mapping[13] = 0;
|
||||
pdimm[slot].dq_mapping[14] = 0;
|
||||
pdimm[slot].dq_mapping[15] = 0;
|
||||
pdimm[slot].dq_mapping[16] = 0;
|
||||
pdimm[slot].dq_mapping[17] = 0;
|
||||
}
|
||||
/* To work at higher than 1333MT/s */
|
||||
popts->half_strength_driver_enable = 0;
|
||||
/*
|
||||
* Write leveling override
|
||||
*/
|
||||
popts->wrlvl_override = 1;
|
||||
popts->wrlvl_sample = 0x0; /* 32 clocks */
|
||||
|
||||
/*
|
||||
* Rtt and Rtt_WR override
|
||||
*/
|
||||
popts->rtt_override = 0;
|
||||
|
||||
/* Enable ZQ calibration */
|
||||
popts->zq_en = 1;
|
||||
|
||||
if (ddr_freq < 2350) {
|
||||
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
|
||||
DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
|
||||
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
|
||||
DDR_CDR2_VREF_RANGE_2;
|
||||
} else {
|
||||
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
|
||||
DDR_CDR1_ODT(DDR_CDR_ODT_100ohm);
|
||||
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) |
|
||||
DDR_CDR2_VREF_RANGE_2;
|
||||
}
|
||||
}
|
||||
|
||||
phys_size_t initdram(int board_type)
|
||||
{
|
||||
phys_size_t dram_size;
|
||||
|
||||
#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
|
||||
return fsl_ddr_sdram_size();
|
||||
#else
|
||||
puts("Initializing DDR....using SPD\n");
|
||||
|
||||
dram_size = fsl_ddr_sdram();
|
||||
#endif
|
||||
|
||||
return dram_size;
|
||||
}
|
||||
|
||||
void dram_init_banksize(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
|
||||
phys_size_t dp_ddr_size;
|
||||
#endif
|
||||
|
||||
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
|
||||
if (gd->ram_size > CONFIG_SYS_LS2_DDR_BLOCK1_SIZE) {
|
||||
gd->bd->bi_dram[0].size = CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
|
||||
gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
|
||||
gd->bd->bi_dram[1].size = gd->ram_size -
|
||||
CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
|
||||
} else {
|
||||
gd->bd->bi_dram[0].size = gd->ram_size;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
|
||||
/* initialize DP-DDR here */
|
||||
puts("DP-DDR: ");
|
||||
/*
|
||||
* DDR controller use 0 as the base address for binding.
|
||||
* It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access.
|
||||
*/
|
||||
dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY,
|
||||
CONFIG_DP_DDR_CTRL,
|
||||
CONFIG_DP_DDR_NUM_CTRLS,
|
||||
CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR,
|
||||
NULL, NULL, NULL);
|
||||
if (dp_ddr_size) {
|
||||
gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE;
|
||||
gd->bd->bi_dram[2].size = dp_ddr_size;
|
||||
} else {
|
||||
puts("Not detected");
|
||||
}
|
||||
#endif
|
||||
}
|
92
board/freescale/ls2085ardb/ddr.h
Normal file
92
board/freescale/ls2085ardb/ddr.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __DDR_H__
|
||||
#define __DDR_H__
|
||||
struct board_specific_parameters {
|
||||
u32 n_ranks;
|
||||
u32 datarate_mhz_high;
|
||||
u32 rank_gb;
|
||||
u32 clk_adjust;
|
||||
u32 wrlvl_start;
|
||||
u32 wrlvl_ctl_2;
|
||||
u32 wrlvl_ctl_3;
|
||||
};
|
||||
|
||||
/*
|
||||
* These tables contain all valid speeds we want to override with board
|
||||
* specific parameters. datarate_mhz_high values need to be in ascending order
|
||||
* for each n_ranks group.
|
||||
*/
|
||||
|
||||
static const struct board_specific_parameters udimm0[] = {
|
||||
/*
|
||||
* memory controller 0
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 8, 0x08090B0D, 0x0E10100C,},
|
||||
{2, 1900, 0, 4, 8, 0x090A0C0E, 0x1012120D,},
|
||||
{2, 2300, 0, 4, 9, 0x0A0B0C10, 0x1114140E,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* DP-DDR DIMM */
|
||||
static const struct board_specific_parameters udimm2[] = {
|
||||
/*
|
||||
* memory controller 2
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,},
|
||||
{2, 1666, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,},
|
||||
{2, 1900, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,},
|
||||
{2, 2200, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters rdimm0[] = {
|
||||
/*
|
||||
* memory controller 0
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,},
|
||||
{2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,},
|
||||
{2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* DP-DDR DIMM */
|
||||
static const struct board_specific_parameters rdimm2[] = {
|
||||
/*
|
||||
* memory controller 2
|
||||
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
|
||||
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
|
||||
*/
|
||||
{2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,},
|
||||
{2, 1666, 0, 4, 7, 0x0B0A090C, 0x0D0F100B,},
|
||||
{2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,},
|
||||
{2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters *udimms[] = {
|
||||
udimm0,
|
||||
udimm0,
|
||||
udimm2,
|
||||
};
|
||||
|
||||
static const struct board_specific_parameters *rdimms[] = {
|
||||
rdimm0,
|
||||
rdimm0,
|
||||
rdimm2,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
249
board/freescale/ls2085ardb/ls2085ardb.c
Normal file
249
board/freescale/ls2085ardb/ls2085ardb.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <netdev.h>
|
||||
#include <fsl_ifc.h>
|
||||
#include <fsl_ddr.h>
|
||||
#include <asm/io.h>
|
||||
#include <fdt_support.h>
|
||||
#include <libfdt.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#include <environment.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/arch-fsl-lsch3/soc.h>
|
||||
|
||||
#include "../common/qixis.h"
|
||||
#include "ls2085ardb_qixis.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
unsigned long long get_qixis_addr(void)
|
||||
{
|
||||
unsigned long long addr;
|
||||
|
||||
if (gd->flags & GD_FLG_RELOC)
|
||||
addr = QIXIS_BASE_PHYS;
|
||||
else
|
||||
addr = QIXIS_BASE_PHYS_EARLY;
|
||||
|
||||
/*
|
||||
* IFC address under 256MB is mapped to 0x30000000, any address above
|
||||
* is mapped to 0x5_10000000 up to 4GB.
|
||||
*/
|
||||
addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
u8 sw;
|
||||
|
||||
sw = QIXIS_READ(arch);
|
||||
printf("Board: %s, ", CONFIG_IDENT_STRING);
|
||||
printf("Board Arch: V%d, ", sw >> 4);
|
||||
printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1);
|
||||
|
||||
sw = QIXIS_READ(brdcfg[0]);
|
||||
sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
|
||||
|
||||
if (sw < 0x8)
|
||||
printf("vBank: %d\n", sw);
|
||||
else if (sw == 0x9)
|
||||
puts("NAND\n");
|
||||
else
|
||||
printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
|
||||
|
||||
printf("FPGA: v%d.%d\n", QIXIS_READ(scver), QIXIS_READ(tagdata));
|
||||
|
||||
puts("SERDES1 Reference : ");
|
||||
printf("Clock1 = 156.25MHz ");
|
||||
printf("Clock2 = 156.25MHz");
|
||||
|
||||
puts("\nSERDES2 Reference : ");
|
||||
printf("Clock1 = 100MHz ");
|
||||
printf("Clock2 = 100MHz\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long get_board_sys_clk(void)
|
||||
{
|
||||
u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
|
||||
|
||||
switch (sysclk_conf & 0x0F) {
|
||||
case QIXIS_SYSCLK_83:
|
||||
return 83333333;
|
||||
case QIXIS_SYSCLK_100:
|
||||
return 100000000;
|
||||
case QIXIS_SYSCLK_125:
|
||||
return 125000000;
|
||||
case QIXIS_SYSCLK_133:
|
||||
return 133333333;
|
||||
case QIXIS_SYSCLK_150:
|
||||
return 150000000;
|
||||
case QIXIS_SYSCLK_160:
|
||||
return 160000000;
|
||||
case QIXIS_SYSCLK_166:
|
||||
return 166666666;
|
||||
}
|
||||
return 66666666;
|
||||
}
|
||||
|
||||
int select_i2c_ch_pca9547(u8 ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
|
||||
if (ret) {
|
||||
puts("PCA: failed to select proper channel\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
init_final_memctl_regs();
|
||||
|
||||
#ifdef CONFIG_ENV_IS_NOWHERE
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
#endif
|
||||
select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
|
||||
|
||||
QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
fsl_lsch3_early_init_f();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void detail_board_ddr_info(void)
|
||||
{
|
||||
puts("\nDDR ");
|
||||
print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
|
||||
print_ddr_info(0);
|
||||
if (gd->bd->bi_dram[2].size) {
|
||||
puts("\nDP-DDR ");
|
||||
print_size(gd->bd->bi_dram[2].size, "");
|
||||
print_ddr_info(CONFIG_DP_DDR_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
gd->ram_size = initdram(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MISC_INIT)
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
debug_server_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long get_dram_size_to_hide(void)
|
||||
{
|
||||
unsigned long dram_to_hide = 0;
|
||||
|
||||
/* Carve the Debug Server private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
dram_to_hide += debug_server_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
/* Carve the MC private DRAM block from the end of DRAM */
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
dram_to_hide += mc_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
return dram_to_hide;
|
||||
}
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
error = cpu_eth_init(bis);
|
||||
#endif
|
||||
|
||||
error = pci_eth_init(bis);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
void fdt_fixup_board_enet(void *fdt)
|
||||
{
|
||||
int offset;
|
||||
|
||||
offset = fdt_path_offset(fdt, "/fsl-mc");
|
||||
|
||||
if (offset < 0)
|
||||
offset = fdt_path_offset(fdt, "/fsl,dprc@0");
|
||||
|
||||
if (offset < 0) {
|
||||
printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
|
||||
__func__, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_mc_boot_status() == 0)
|
||||
fdt_status_okay(fdt, offset);
|
||||
else
|
||||
fdt_status_fail(fdt, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
phys_addr_t base;
|
||||
phys_size_t size;
|
||||
|
||||
ft_cpu_setup(blob, bd);
|
||||
|
||||
/* limit the memory size to bank 1 until Linux can handle 40-bit PA */
|
||||
base = getenv_bootm_low();
|
||||
size = getenv_bootm_size();
|
||||
fdt_fixup_memory(blob, (u64)base, (u64)size);
|
||||
|
||||
#ifdef CONFIG_FSL_MC_ENET
|
||||
fdt_fixup_board_enet(blob);
|
||||
fsl_mc_ldpaa_exit(bd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void qixis_dump_switch(void)
|
||||
{
|
||||
int i, nr_of_cfgsw;
|
||||
|
||||
QIXIS_WRITE(cms[0], 0x00);
|
||||
nr_of_cfgsw = QIXIS_READ(cms[1]);
|
||||
|
||||
puts("DIP switch settings dump:\n");
|
||||
for (i = 1; i <= nr_of_cfgsw; i++) {
|
||||
QIXIS_WRITE(cms[0], i);
|
||||
printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1]));
|
||||
}
|
||||
}
|
20
board/freescale/ls2085ardb/ls2085ardb_qixis.h
Normal file
20
board/freescale/ls2085ardb/ls2085ardb_qixis.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __LS2_RDB_QIXIS_H__
|
||||
#define __LS2_RDB_QIXIS_H__
|
||||
|
||||
/* SYSCLK */
|
||||
#define QIXIS_SYSCLK_66 0x0
|
||||
#define QIXIS_SYSCLK_83 0x1
|
||||
#define QIXIS_SYSCLK_100 0x2
|
||||
#define QIXIS_SYSCLK_125 0x3
|
||||
#define QIXIS_SYSCLK_133 0x4
|
||||
#define QIXIS_SYSCLK_150 0x5
|
||||
#define QIXIS_SYSCLK_160 0x6
|
||||
#define QIXIS_SYSCLK_166 0x7
|
||||
|
||||
#endif /*__LS2_RDB_QIXIS_H__*/
|
|
@ -77,10 +77,9 @@ struct cpld_data {
|
|||
int board_early_init_f(void)
|
||||
{
|
||||
ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR);
|
||||
struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
|
||||
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
/* Clock configuration to access CPLD using IFC(GPCM) */
|
||||
setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
/*
|
||||
* Reset PCIe slots via GPIO4
|
||||
*/
|
||||
|
|
|
@ -23,12 +23,12 @@ void board_init_f(ulong bootflag)
|
|||
{
|
||||
u32 plat_ratio;
|
||||
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
|
||||
struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
|
||||
|
||||
console_init_f();
|
||||
|
||||
/* Clock configuration to access CPLD using IFC(GPCM) */
|
||||
setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
|
||||
|
||||
#ifdef CONFIG_P1010RDB_PB
|
||||
setbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_GPIO01_DRVVBUS);
|
||||
|
|
|
@ -702,6 +702,12 @@ init_fnc_t init_sequence_r[] = {
|
|||
/* TODO: could x86/PPC have this also perhaps? */
|
||||
#ifdef CONFIG_ARM
|
||||
initr_caches,
|
||||
/* Note: For Freescale LS2 SoCs, new MMU table is created in DDR.
|
||||
* A temporary mapping of IFC high region is since removed,
|
||||
* so environmental variables in NOR flash is not availble
|
||||
* until board_init() is called below to remap IFC to high
|
||||
* region.
|
||||
*/
|
||||
#endif
|
||||
initr_reloc_global_data,
|
||||
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
|
||||
|
|
|
@ -36,9 +36,9 @@ static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
|
|||
/* Display values from last command.
|
||||
* Memory modify remembered values are different from display memory.
|
||||
*/
|
||||
static uint dp_last_addr, dp_last_size;
|
||||
static uint dp_last_length = 0x40;
|
||||
static uint mm_last_addr, mm_last_size;
|
||||
static ulong dp_last_addr, dp_last_size;
|
||||
static ulong dp_last_length = 0x40;
|
||||
static ulong mm_last_addr, mm_last_size;
|
||||
|
||||
static ulong base_address = 0;
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
|||
typedef void __noreturn (*image_entry_noargs_t)(void);
|
||||
|
||||
image_entry_noargs_t image_entry =
|
||||
(image_entry_noargs_t) spl_image->entry_point;
|
||||
(image_entry_noargs_t)(unsigned long)spl_image->entry_point;
|
||||
|
||||
debug("image entry point: 0x%X\n", spl_image->entry_point);
|
||||
image_entry();
|
||||
|
|
|
@ -91,7 +91,7 @@ void spl_nand_load_image(void)
|
|||
sizeof(*header), (void *)header);
|
||||
spl_parse_image_header(header);
|
||||
nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
|
||||
spl_image.size, (void *)spl_image.load_addr);
|
||||
spl_image.size, (void *)(unsigned long)spl_image.load_addr);
|
||||
nand_deselect();
|
||||
}
|
||||
#endif
|
||||
|
|
3
configs/ls1021aqds_ddr4_nor_lpuart_defconfig
Normal file
3
configs/ls1021aqds_ddr4_nor_lpuart_defconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,LPUART"
|
||||
CONFIG_ARM=y
|
||||
CONFIG_TARGET_LS1021AQDS=y
|
3
configs/ls2085aqds_defconfig
Normal file
3
configs/ls2085aqds_defconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4"
|
||||
CONFIG_ARM=y
|
||||
CONFIG_TARGET_LS2085AQDS=y
|
4
configs/ls2085aqds_nand_defconfig
Normal file
4
configs/ls2085aqds_nand_defconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,NAND"
|
||||
CONFIG_SPL=y
|
||||
CONFIG_ARM=y
|
||||
CONFIG_TARGET_LS2085AQDS=y
|
3
configs/ls2085ardb_defconfig
Normal file
3
configs/ls2085ardb_defconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4"
|
||||
CONFIG_ARM=y
|
||||
CONFIG_TARGET_LS2085ARDB=y
|
4
configs/ls2085ardb_nand_defconfig
Normal file
4
configs/ls2085ardb_nand_defconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,NAND"
|
||||
CONFIG_SPL=y
|
||||
CONFIG_ARM=y
|
||||
CONFIG_TARGET_LS2085ARDB=y
|
|
@ -313,7 +313,10 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
|
|||
#ifdef CONFIG_SYS_FSL_DDR4
|
||||
/* tXP=max(4nCK, 6ns) */
|
||||
int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
|
||||
trwt_mclk = 2;
|
||||
unsigned int data_rate = get_ddr_freq(ctrl_num);
|
||||
|
||||
/* for faster clock, need more time for data setup */
|
||||
trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
|
||||
twrt_mclk = 1;
|
||||
act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
|
||||
pre_pd_exit_mclk = act_pd_exit_mclk;
|
||||
|
@ -338,7 +341,7 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
|
|||
*/
|
||||
txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
|
||||
|
||||
ip_rev = fsl_ddr_get_version();
|
||||
ip_rev = fsl_ddr_get_version(ctrl_num);
|
||||
if (ip_rev >= 0x40700) {
|
||||
/*
|
||||
* MRS_CYC = max(tMRD, tMOD)
|
||||
|
@ -544,7 +547,7 @@ static void set_timing_cfg_1(const unsigned int ctrl_num,
|
|||
* we need set extend bit for it at
|
||||
* TIMING_CFG_3[EXT_CASLAT]
|
||||
*/
|
||||
if (fsl_ddr_get_version() <= 0x40400)
|
||||
if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
|
||||
caslat_ctrl = 2 * cas_latency - 1;
|
||||
else
|
||||
caslat_ctrl = (cas_latency - 1) << 1;
|
||||
|
@ -1113,16 +1116,32 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
|
|||
int i;
|
||||
unsigned short esdmode4 = 0; /* Extended SDRAM mode 4 */
|
||||
unsigned short esdmode5; /* Extended SDRAM mode 5 */
|
||||
int rtt_park = 0;
|
||||
|
||||
esdmode5 = 0x00000400; /* Data mask enabled */
|
||||
if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
|
||||
esdmode5 = 0x00000500; /* Data mask enable, RTT_PARK CS0 */
|
||||
rtt_park = 1;
|
||||
} else {
|
||||
esdmode5 = 0x00000400; /* Data mask enabled */
|
||||
}
|
||||
|
||||
ddr->ddr_sdram_mode_9 = (0
|
||||
| ((esdmode4 & 0xffff) << 16)
|
||||
| ((esdmode5 & 0xffff) << 0)
|
||||
);
|
||||
|
||||
/* only mode_9 use 0x500, others use 0x400 */
|
||||
|
||||
debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
|
||||
if (unq_mrs_en) { /* unique mode registers are supported */
|
||||
for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
|
||||
if (!rtt_park &&
|
||||
(ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
|
||||
esdmode5 |= 0x00000500; /* RTT_PARK */
|
||||
rtt_park = 1;
|
||||
} else {
|
||||
esdmode5 = 0x00000400;
|
||||
}
|
||||
switch (i) {
|
||||
case 1:
|
||||
ddr->ddr_sdram_mode_11 = (0
|
||||
|
@ -1970,31 +1989,41 @@ static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
|
|||
const dimm_params_t *dimm_params)
|
||||
{
|
||||
unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
|
||||
int i;
|
||||
|
||||
ddr->dq_map_0 = ((dimm_params->dq_mapping[0] & 0x3F) << 26) |
|
||||
((dimm_params->dq_mapping[1] & 0x3F) << 20) |
|
||||
((dimm_params->dq_mapping[2] & 0x3F) << 14) |
|
||||
((dimm_params->dq_mapping[3] & 0x3F) << 8) |
|
||||
((dimm_params->dq_mapping[4] & 0x3F) << 2);
|
||||
for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
|
||||
if (dimm_params[i].n_ranks)
|
||||
break;
|
||||
}
|
||||
if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
|
||||
puts("DDR error: no DIMM found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ddr->dq_map_1 = ((dimm_params->dq_mapping[5] & 0x3F) << 26) |
|
||||
((dimm_params->dq_mapping[6] & 0x3F) << 20) |
|
||||
((dimm_params->dq_mapping[7] & 0x3F) << 14) |
|
||||
((dimm_params->dq_mapping[10] & 0x3F) << 8) |
|
||||
((dimm_params->dq_mapping[11] & 0x3F) << 2);
|
||||
ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
|
||||
((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
|
||||
((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
|
||||
((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
|
||||
((dimm_params[i].dq_mapping[4] & 0x3F) << 2);
|
||||
|
||||
ddr->dq_map_2 = ((dimm_params->dq_mapping[12] & 0x3F) << 26) |
|
||||
((dimm_params->dq_mapping[13] & 0x3F) << 20) |
|
||||
((dimm_params->dq_mapping[14] & 0x3F) << 14) |
|
||||
((dimm_params->dq_mapping[15] & 0x3F) << 8) |
|
||||
((dimm_params->dq_mapping[16] & 0x3F) << 2);
|
||||
ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
|
||||
((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
|
||||
((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
|
||||
((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
|
||||
((dimm_params[i].dq_mapping[11] & 0x3F) << 2);
|
||||
|
||||
ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
|
||||
((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
|
||||
((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
|
||||
((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
|
||||
((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
|
||||
|
||||
/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
|
||||
ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) |
|
||||
((dimm_params->dq_mapping[8] & 0x3F) << 20) |
|
||||
ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
|
||||
((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
|
||||
(acc_ecc_en ? 0 :
|
||||
(dimm_params->dq_mapping[9] & 0x3F) << 14) |
|
||||
dimm_params->dq_mapping_ors;
|
||||
(dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
|
||||
dimm_params[i].dq_mapping_ors;
|
||||
|
||||
debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
|
||||
debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
|
||||
|
@ -2357,7 +2386,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
|
|||
set_ddr_cdr1(ddr, popts);
|
||||
set_ddr_cdr2(ddr, popts);
|
||||
set_ddr_sdram_cfg(ddr, popts, common_dimm);
|
||||
ip_rev = fsl_ddr_get_version();
|
||||
ip_rev = fsl_ddr_get_version(ctrl_num);
|
||||
if (ip_rev > 0x40400)
|
||||
unq_mrs_en = 1;
|
||||
|
||||
|
|
|
@ -135,7 +135,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
|
|||
|
||||
if (spd->mem_type) {
|
||||
if (spd->mem_type != SPD_MEMTYPE_DDR4) {
|
||||
printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
|
||||
printf("Ctrl %u DIMM %u: is not a DDR4 SPD.\n",
|
||||
ctrl_num, dimm_number);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
@ -11,6 +11,22 @@
|
|||
#include <fsl_immap.h>
|
||||
#include <fsl_ddr.h>
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
|
||||
static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
|
||||
{
|
||||
int timeout = 1000;
|
||||
|
||||
ddr_out32(ptr, value);
|
||||
|
||||
while (ddr_in32(ptr) & bits) {
|
||||
udelay(100);
|
||||
timeout--;
|
||||
}
|
||||
if (timeout <= 0)
|
||||
puts("Error: A007865 wait for clear timeout.\n");
|
||||
}
|
||||
#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
|
||||
|
||||
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
|
||||
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
|
||||
#endif
|
||||
|
@ -36,6 +52,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
|
|||
defined(CONFIG_SYS_FSL_ERRATUM_A008514)
|
||||
u32 *eddrtqcr1;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
|
||||
u32 temp32, mr6;
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
u32 mtcr, err_detect, err_sbe;
|
||||
u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
char buffer[CONFIG_SYS_CBSIZE];
|
||||
#endif
|
||||
|
||||
switch (ctrl_num) {
|
||||
case 0:
|
||||
|
@ -214,6 +240,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
|
|||
ddr_setbits32(ddr->debug[28], 0x9 << 20);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
|
||||
/* Part 1 of 2 */
|
||||
/* This erraum only applies to verion 5.2.0 */
|
||||
if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
|
||||
/* Disable DRAM VRef training */
|
||||
ddr_out32(&ddr->ddr_cdr2,
|
||||
regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
|
||||
/* Disable deskew */
|
||||
ddr_out32(&ddr->debug[28], 0x400);
|
||||
/* Disable D_INIT */
|
||||
ddr_out32(&ddr->sdram_cfg_2,
|
||||
regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
|
||||
ddr_out32(&ddr->debug[25], 0x9000);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* For RDIMMs, JEDEC spec requires clocks to be stable before reset is
|
||||
* deasserted. Clocks start when any chip select is enabled and clock
|
||||
|
@ -261,6 +302,66 @@ step2:
|
|||
mb();
|
||||
isb();
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
|
||||
/* Part 2 of 2 */
|
||||
/* This erraum only applies to verion 5.2.0 */
|
||||
if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
|
||||
/* Wait for idle */
|
||||
timeout = 200;
|
||||
while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
|
||||
(timeout > 0)) {
|
||||
udelay(100);
|
||||
timeout--;
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
printf("Controler %d timeout, debug_2 = %x\n",
|
||||
ctrl_num, ddr_in32(&ddr->debug[1]));
|
||||
}
|
||||
/* Set VREF */
|
||||
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
|
||||
if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
|
||||
continue;
|
||||
|
||||
mr6 = (regs->ddr_sdram_mode_10 >> 16) |
|
||||
MD_CNTL_MD_EN |
|
||||
MD_CNTL_CS_SEL(i) |
|
||||
MD_CNTL_MD_SEL(6) |
|
||||
0x00200000;
|
||||
temp32 = mr6 | 0xc0;
|
||||
set_wait_for_bits_clear(&ddr->sdram_md_cntl,
|
||||
temp32, MD_CNTL_MD_EN);
|
||||
udelay(1);
|
||||
debug("MR6 = 0x%08x\n", temp32);
|
||||
temp32 = mr6 | 0xf0;
|
||||
set_wait_for_bits_clear(&ddr->sdram_md_cntl,
|
||||
temp32, MD_CNTL_MD_EN);
|
||||
udelay(1);
|
||||
debug("MR6 = 0x%08x\n", temp32);
|
||||
temp32 = mr6 | 0x70;
|
||||
set_wait_for_bits_clear(&ddr->sdram_md_cntl,
|
||||
temp32, MD_CNTL_MD_EN);
|
||||
udelay(1);
|
||||
debug("MR6 = 0x%08x\n", temp32);
|
||||
}
|
||||
ddr_out32(&ddr->sdram_md_cntl, 0);
|
||||
ddr_out32(&ddr->debug[28], 0); /* Enable deskew */
|
||||
ddr_out32(&ddr->debug[1], 0x400); /* restart deskew */
|
||||
/* wait for idle */
|
||||
timeout = 200;
|
||||
while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
|
||||
(timeout > 0)) {
|
||||
udelay(100);
|
||||
timeout--;
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
printf("Controler %d timeout, debug_2 = %x\n",
|
||||
ctrl_num, ddr_in32(&ddr->debug[1]));
|
||||
}
|
||||
/* Restore D_INIT */
|
||||
ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
|
||||
}
|
||||
#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
|
||||
|
||||
total_gb_size_per_controller = 0;
|
||||
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
|
||||
if (!(regs->cs[i].config & 0x80000000))
|
||||
|
@ -309,4 +410,70 @@ step2:
|
|||
ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
#define BIST_PATTERN1 0xFFFFFFFF
|
||||
#define BIST_PATTERN2 0x0
|
||||
#define BIST_CR 0x80010000
|
||||
#define BIST_CR_EN 0x80000000
|
||||
#define BIST_CR_STAT 0x00000001
|
||||
#define CTLR_INTLV_MASK 0x20000000
|
||||
/* Perform build-in test on memory. Three-way interleaving is not yet
|
||||
* supported by this code. */
|
||||
if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) {
|
||||
puts("Running BIST test. This will take a while...");
|
||||
cs0_config = ddr_in32(&ddr->cs0_config);
|
||||
if (cs0_config & CTLR_INTLV_MASK) {
|
||||
cs0_bnds = ddr_in32(&cs0_bnds);
|
||||
cs1_bnds = ddr_in32(&cs1_bnds);
|
||||
cs2_bnds = ddr_in32(&cs2_bnds);
|
||||
cs3_bnds = ddr_in32(&cs3_bnds);
|
||||
/* set bnds to non-interleaving */
|
||||
ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1);
|
||||
}
|
||||
ddr_out32(&ddr->mtp1, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp2, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp3, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp4, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp5, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp6, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp7, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp8, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp9, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp10, BIST_PATTERN2);
|
||||
mtcr = BIST_CR;
|
||||
ddr_out32(&ddr->mtcr, mtcr);
|
||||
timeout = 100;
|
||||
while (timeout > 0 && (mtcr & BIST_CR_EN)) {
|
||||
mdelay(1000);
|
||||
timeout--;
|
||||
mtcr = ddr_in32(&ddr->mtcr);
|
||||
}
|
||||
if (timeout <= 0)
|
||||
puts("Timeout\n");
|
||||
else
|
||||
puts("Done\n");
|
||||
err_detect = ddr_in32(&ddr->err_detect);
|
||||
err_sbe = ddr_in32(&ddr->err_sbe);
|
||||
if (mtcr & BIST_CR_STAT) {
|
||||
printf("BIST test failed on controller %d.\n",
|
||||
ctrl_num);
|
||||
}
|
||||
if (err_detect || (err_sbe & 0xffff)) {
|
||||
printf("ECC error detected on controller %d.\n",
|
||||
ctrl_num);
|
||||
}
|
||||
|
||||
if (cs0_config & CTLR_INTLV_MASK) {
|
||||
/* restore bnds registers */
|
||||
ddr_out32(&cs0_bnds, cs0_bnds);
|
||||
ddr_out32(&cs1_bnds, cs1_bnds);
|
||||
ddr_out32(&cs2_bnds, cs2_bnds);
|
||||
ddr_out32(&cs3_bnds, cs3_bnds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -205,6 +205,8 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
|
|||
|
||||
#define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \
|
||||
sizeof((dimm_params_t *)0)->x, 0}
|
||||
#define DIMM_PARM_HEX(x) {#x, offsetof(dimm_params_t, x), \
|
||||
sizeof((dimm_params_t *)0)->x, 1}
|
||||
|
||||
static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
|
||||
unsigned int ctrl_num,
|
||||
|
@ -220,6 +222,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
|
|||
DIMM_PARM(primary_sdram_width),
|
||||
DIMM_PARM(ec_sdram_width),
|
||||
DIMM_PARM(registered_dimm),
|
||||
DIMM_PARM(mirrored_dimm),
|
||||
DIMM_PARM(device_width),
|
||||
|
||||
DIMM_PARM(n_row_addr),
|
||||
|
@ -274,7 +277,27 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
|
|||
DIMM_PARM(tdqsq_max_ps),
|
||||
DIMM_PARM(tqhs_ps),
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_DDR4
|
||||
DIMM_PARM_HEX(dq_mapping[0]),
|
||||
DIMM_PARM_HEX(dq_mapping[1]),
|
||||
DIMM_PARM_HEX(dq_mapping[2]),
|
||||
DIMM_PARM_HEX(dq_mapping[3]),
|
||||
DIMM_PARM_HEX(dq_mapping[4]),
|
||||
DIMM_PARM_HEX(dq_mapping[5]),
|
||||
DIMM_PARM_HEX(dq_mapping[6]),
|
||||
DIMM_PARM_HEX(dq_mapping[7]),
|
||||
DIMM_PARM_HEX(dq_mapping[8]),
|
||||
DIMM_PARM_HEX(dq_mapping[9]),
|
||||
DIMM_PARM_HEX(dq_mapping[10]),
|
||||
DIMM_PARM_HEX(dq_mapping[11]),
|
||||
DIMM_PARM_HEX(dq_mapping[12]),
|
||||
DIMM_PARM_HEX(dq_mapping[13]),
|
||||
DIMM_PARM_HEX(dq_mapping[14]),
|
||||
DIMM_PARM_HEX(dq_mapping[15]),
|
||||
DIMM_PARM_HEX(dq_mapping[16]),
|
||||
DIMM_PARM_HEX(dq_mapping[17]),
|
||||
DIMM_PARM(dq_mapping_ors),
|
||||
#endif
|
||||
DIMM_PARM(rank_density),
|
||||
DIMM_PARM(capacity),
|
||||
DIMM_PARM(base_address),
|
||||
|
@ -296,6 +319,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
|
|||
DIMM_PARM(primary_sdram_width),
|
||||
DIMM_PARM(ec_sdram_width),
|
||||
DIMM_PARM(registered_dimm),
|
||||
DIMM_PARM(mirrored_dimm),
|
||||
DIMM_PARM(device_width),
|
||||
|
||||
DIMM_PARM(n_row_addr),
|
||||
|
@ -314,6 +338,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
|
|||
DIMM_PARM(tckmax_ps),
|
||||
|
||||
DIMM_PARM(caslat_x),
|
||||
DIMM_PARM_HEX(caslat_x),
|
||||
DIMM_PARM(taa_ps),
|
||||
DIMM_PARM(caslat_x_minus_1),
|
||||
DIMM_PARM(caslat_x_minus_2),
|
||||
|
@ -322,6 +347,9 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
|
|||
DIMM_PARM(trcd_ps),
|
||||
DIMM_PARM(trp_ps),
|
||||
DIMM_PARM(tras_ps),
|
||||
#if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
|
||||
DIMM_PARM(tfaw_ps),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_DDR4
|
||||
DIMM_PARM(trfc1_ps),
|
||||
DIMM_PARM(trfc2_ps),
|
||||
|
@ -346,6 +374,27 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
|
|||
DIMM_PARM(tdh_ps),
|
||||
DIMM_PARM(tdqsq_max_ps),
|
||||
DIMM_PARM(tqhs_ps),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_FSL_DDR4
|
||||
DIMM_PARM_HEX(dq_mapping[0]),
|
||||
DIMM_PARM_HEX(dq_mapping[1]),
|
||||
DIMM_PARM_HEX(dq_mapping[2]),
|
||||
DIMM_PARM_HEX(dq_mapping[3]),
|
||||
DIMM_PARM_HEX(dq_mapping[4]),
|
||||
DIMM_PARM_HEX(dq_mapping[5]),
|
||||
DIMM_PARM_HEX(dq_mapping[6]),
|
||||
DIMM_PARM_HEX(dq_mapping[7]),
|
||||
DIMM_PARM_HEX(dq_mapping[8]),
|
||||
DIMM_PARM_HEX(dq_mapping[9]),
|
||||
DIMM_PARM_HEX(dq_mapping[10]),
|
||||
DIMM_PARM_HEX(dq_mapping[11]),
|
||||
DIMM_PARM_HEX(dq_mapping[12]),
|
||||
DIMM_PARM_HEX(dq_mapping[13]),
|
||||
DIMM_PARM_HEX(dq_mapping[14]),
|
||||
DIMM_PARM_HEX(dq_mapping[15]),
|
||||
DIMM_PARM_HEX(dq_mapping[16]),
|
||||
DIMM_PARM_HEX(dq_mapping[17]),
|
||||
DIMM_PARM(dq_mapping_ors),
|
||||
#endif
|
||||
};
|
||||
static const unsigned int n_opts = ARRAY_SIZE(options);
|
||||
|
@ -463,7 +512,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
|
|||
CTRL_OPTIONS_CS(3, odt_rd_cfg),
|
||||
CTRL_OPTIONS_CS(3, odt_wr_cfg),
|
||||
#endif
|
||||
#if defined(CONFIG_SYS_FSL_DDR3)
|
||||
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
|
||||
CTRL_OPTIONS_CS(0, odt_rtt_norm),
|
||||
CTRL_OPTIONS_CS(0, odt_rtt_wr),
|
||||
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
|
||||
|
@ -753,7 +802,7 @@ static void print_memctl_options(const memctl_options_t *popts)
|
|||
CTRL_OPTIONS_CS(3, odt_rd_cfg),
|
||||
CTRL_OPTIONS_CS(3, odt_wr_cfg),
|
||||
#endif
|
||||
#if defined(CONFIG_SYS_FSL_DDR3)
|
||||
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
|
||||
CTRL_OPTIONS_CS(0, odt_rtt_norm),
|
||||
CTRL_OPTIONS_CS(0, odt_rtt_wr),
|
||||
#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
|
||||
|
@ -795,6 +844,7 @@ static void print_memctl_options(const memctl_options_t *popts)
|
|||
CTRL_OPTIONS(twot_en),
|
||||
CTRL_OPTIONS(threet_en),
|
||||
CTRL_OPTIONS(registered_dimm_en),
|
||||
CTRL_OPTIONS(mirrored_dimm),
|
||||
CTRL_OPTIONS(ap_en),
|
||||
CTRL_OPTIONS(x4_en),
|
||||
CTRL_OPTIONS(bstopre),
|
||||
|
|
|
@ -22,7 +22,7 @@ compute_cas_latency(const unsigned int ctrl_num,
|
|||
unsigned int common_caslat;
|
||||
unsigned int caslat_actual;
|
||||
unsigned int retry = 16;
|
||||
unsigned int tmp;
|
||||
unsigned int tmp = ~0;
|
||||
const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
|
||||
#ifdef CONFIG_SYS_FSL_DDR3
|
||||
const unsigned int taamax = 20000;
|
||||
|
@ -31,8 +31,7 @@ compute_cas_latency(const unsigned int ctrl_num,
|
|||
#endif
|
||||
|
||||
/* compute the common CAS latency supported between slots */
|
||||
tmp = dimm_params[0].caslat_x;
|
||||
for (i = 1; i < number_of_dimms; i++) {
|
||||
for (i = 0; i < number_of_dimms; i++) {
|
||||
if (dimm_params[i].n_ranks)
|
||||
tmp &= dimm_params[i].caslat_x;
|
||||
}
|
||||
|
|
|
@ -453,7 +453,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
|
|||
retval = compute_dimm_parameters(
|
||||
i, spd, pdimm, j);
|
||||
#ifdef CONFIG_SYS_DDR_RAW_TIMING
|
||||
if (!i && !j && retval) {
|
||||
if (!j && retval) {
|
||||
printf("SPD error on controller %d! "
|
||||
"Trying fallback to raw timing "
|
||||
"calculation\n", i);
|
||||
|
|
|
@ -728,7 +728,12 @@ unsigned int populate_memctl_options(int all_dimms_registered,
|
|||
|
||||
/* Choose ddr controller address mirror mode */
|
||||
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
|
||||
popts->mirrored_dimm = pdimm[0].mirrored_dimm;
|
||||
for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
|
||||
if (pdimm[i].n_ranks) {
|
||||
popts->mirrored_dimm = pdimm[i].mirrored_dimm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Global Timing Parameters. */
|
||||
|
|
|
@ -23,12 +23,34 @@
|
|||
|
||||
#define ULL_8FS 0xFFFFFFFFULL
|
||||
|
||||
u32 fsl_ddr_get_version(void)
|
||||
u32 fsl_ddr_get_version(unsigned int ctrl_num)
|
||||
{
|
||||
struct ccsr_ddr __iomem *ddr;
|
||||
u32 ver_major_minor_errata;
|
||||
|
||||
ddr = (void *)_DDR_ADDR;
|
||||
switch (ctrl_num) {
|
||||
case 0:
|
||||
ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
|
||||
break;
|
||||
#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
|
||||
case 1:
|
||||
ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
|
||||
case 2:
|
||||
ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
|
||||
case 3:
|
||||
ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
|
||||
return 0;
|
||||
}
|
||||
ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
|
||||
ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
|
||||
|
||||
|
@ -212,7 +234,7 @@ void print_ddr_info(unsigned int start_ctrl)
|
|||
|
||||
/* Calculate CAS latency based on timing cfg values */
|
||||
cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
|
||||
if (fsl_ddr_get_version() <= 0x40400)
|
||||
if (fsl_ddr_get_version(0) <= 0x40400)
|
||||
cas_lat += 1;
|
||||
else
|
||||
cas_lat += 2;
|
||||
|
|
|
@ -114,6 +114,9 @@ static u16 i2c_clk_div[50][2] = {
|
|||
#ifndef CONFIG_SYS_MXC_I2C3_SPEED
|
||||
#define CONFIG_SYS_MXC_I2C3_SPEED 100000
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_MXC_I2C4_SPEED
|
||||
#define CONFIG_SYS_MXC_I2C4_SPEED 100000
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_MXC_I2C1_SLAVE
|
||||
#define CONFIG_SYS_MXC_I2C1_SLAVE 0
|
||||
|
@ -124,6 +127,9 @@ static u16 i2c_clk_div[50][2] = {
|
|||
#ifndef CONFIG_SYS_MXC_I2C3_SLAVE
|
||||
#define CONFIG_SYS_MXC_I2C3_SLAVE 0
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_MXC_I2C4_SLAVE
|
||||
#define CONFIG_SYS_MXC_I2C4_SLAVE 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
@ -543,12 +549,17 @@ U_BOOT_I2C_ADAP_COMPLETE(mxc1, mxc_i2c_init, mxc_i2c_probe,
|
|||
mxc_i2c_set_bus_speed,
|
||||
CONFIG_SYS_MXC_I2C2_SPEED,
|
||||
CONFIG_SYS_MXC_I2C2_SLAVE, 1)
|
||||
#if defined(CONFIG_MX31) || defined(CONFIG_MX35) ||\
|
||||
defined(CONFIG_MX51) || defined(CONFIG_MX53) ||\
|
||||
defined(CONFIG_MX6) || defined(CONFIG_LS102XA)
|
||||
#ifdef CONFIG_SYS_I2C_MXC_I2C3
|
||||
U_BOOT_I2C_ADAP_COMPLETE(mxc2, mxc_i2c_init, mxc_i2c_probe,
|
||||
mxc_i2c_read, mxc_i2c_write,
|
||||
mxc_i2c_set_bus_speed,
|
||||
CONFIG_SYS_MXC_I2C3_SPEED,
|
||||
CONFIG_SYS_MXC_I2C3_SLAVE, 2)
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_MXC_I2C4
|
||||
U_BOOT_I2C_ADAP_COMPLETE(mxc3, mxc_i2c_init, mxc_i2c_probe,
|
||||
mxc_i2c_read, mxc_i2c_write,
|
||||
mxc_i2c_set_bus_speed,
|
||||
CONFIG_SYS_MXC_I2C4_SPEED,
|
||||
CONFIG_SYS_MXC_I2C4_SLAVE, 3)
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
|
|||
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
|
||||
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
|
||||
obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o
|
||||
obj-$(CONFIG_FSL_IIM) += fsl_iim.o
|
||||
obj-$(CONFIG_GPIO_LED) += gpio_led.o
|
||||
obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o
|
||||
|
|
246
drivers/misc/fsl_debug_server.c
Normal file
246
drivers/misc/fsl_debug_server.c
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
|
||||
|
||||
#include <fsl_debug_server.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
static int debug_server_ver_info_maj, debug_server_ver_info_min;
|
||||
|
||||
/**
|
||||
* Copying Debug Server firmware to DDR
|
||||
*/
|
||||
static int debug_server_copy_image(const char *title, u64 image_addr,
|
||||
u32 image_size, u64 debug_server_ram_addr)
|
||||
{
|
||||
debug("%s copied to address %p\n", title,
|
||||
(void *)debug_server_ram_addr);
|
||||
memcpy((void *)debug_server_ram_addr, (void *)image_addr, image_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug Server FIT image parser checks if the image is in FIT
|
||||
* format, verifies integrity of the image and calculates
|
||||
* raw image address and size values.
|
||||
*
|
||||
* Returns 0 if success and -1 if any of the above mentioned
|
||||
* task fail.
|
||||
**/
|
||||
int debug_server_parse_firmware_fit_image(const void **raw_image_addr,
|
||||
size_t *raw_image_size)
|
||||
{
|
||||
int format;
|
||||
void *fit_hdr;
|
||||
int node_offset;
|
||||
const void *data;
|
||||
size_t size;
|
||||
const char *uname = "firmware";
|
||||
char *desc;
|
||||
char *debug_server_ver_info;
|
||||
char *debug_server_ver_info_major, *debug_server_ver_info_minor;
|
||||
|
||||
/* Check if the image is in NOR flash */
|
||||
#ifdef CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR
|
||||
fit_hdr = (void *)CONFIG_SYS_DEBUG_SERVER_FW_ADDR;
|
||||
#else
|
||||
#error "CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR not defined"
|
||||
#endif
|
||||
|
||||
/* Check if Image is in FIT format */
|
||||
format = genimg_get_format(fit_hdr);
|
||||
if (format != IMAGE_FORMAT_FIT) {
|
||||
printf("Error! Not a FIT image\n");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (!fit_check_format(fit_hdr)) {
|
||||
printf("Error! Bad FIT image format\n");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
node_offset = fit_image_get_node(fit_hdr, uname);
|
||||
if (node_offset < 0) {
|
||||
printf("Error! Can not find %s subimage\n", uname);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* Verify Debug Server firmware image */
|
||||
if (!fit_image_verify(fit_hdr, node_offset)) {
|
||||
printf("Error! Bad Debug Server firmware hash");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (fit_get_desc(fit_hdr, node_offset, &desc) < 0) {
|
||||
printf("Error! Failed to get Debug Server fw description");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
debug_server_ver_info = strstr(desc, "Version");
|
||||
debug_server_ver_info_major = strtok(debug_server_ver_info, ".");
|
||||
debug_server_ver_info_minor = strtok(NULL, ".");
|
||||
|
||||
debug_server_ver_info_maj =
|
||||
simple_strtoul(debug_server_ver_info_major, NULL, 10);
|
||||
debug_server_ver_info_min =
|
||||
simple_strtoul(debug_server_ver_info_minor, NULL, 10);
|
||||
|
||||
/* Debug server version checking */
|
||||
if ((debug_server_ver_info_maj < DEBUG_SERVER_VER_MAJOR) ||
|
||||
(debug_server_ver_info_min < DEBUG_SERVER_VER_MINOR)) {
|
||||
printf("Debug server FW mismatches the min version required\n");
|
||||
printf("Expected:%d.%d, Got %d.%d\n",
|
||||
DEBUG_SERVER_VER_MAJOR, DEBUG_SERVER_VER_MINOR,
|
||||
debug_server_ver_info_maj,
|
||||
debug_server_ver_info_min);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* Get address and size of raw image */
|
||||
fit_image_get_data(fit_hdr, node_offset, &data, &size);
|
||||
|
||||
*raw_image_addr = data;
|
||||
*raw_image_size = size;
|
||||
|
||||
return 0;
|
||||
|
||||
out_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the actual size of the Debug Server private DRAM block.
|
||||
*
|
||||
* NOTE: For now this function always returns the minimum required size,
|
||||
* However, in the future, the actual size may be obtained from an environment
|
||||
* variable.
|
||||
*/
|
||||
unsigned long debug_server_get_dram_block_size(void)
|
||||
{
|
||||
return CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE;
|
||||
}
|
||||
|
||||
int debug_server_init(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
int error, timeout = CONFIG_SYS_DEBUG_SERVER_TIMEOUT;
|
||||
int debug_server_boot_status;
|
||||
u64 debug_server_ram_addr, debug_server_ram_size;
|
||||
const void *raw_image_addr;
|
||||
size_t raw_image_size = 0;
|
||||
|
||||
debug("debug_server_init called\n");
|
||||
/*
|
||||
* The Debug Server private DRAM block was already carved at the end of
|
||||
* DRAM by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE:
|
||||
*/
|
||||
debug_server_ram_size = debug_server_get_dram_block_size();
|
||||
if (gd->bd->bi_dram[1].start)
|
||||
debug_server_ram_addr =
|
||||
gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size;
|
||||
else
|
||||
debug_server_ram_addr =
|
||||
gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
|
||||
|
||||
error = debug_server_parse_firmware_fit_image(&raw_image_addr,
|
||||
&raw_image_size);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
debug("debug server (ram addr = 0x%llx, ram size = 0x%llx)\n",
|
||||
debug_server_ram_addr, debug_server_ram_size);
|
||||
/*
|
||||
* Load the Debug Server FW at the beginning of the Debug Server
|
||||
* private DRAM block:
|
||||
*/
|
||||
debug_server_copy_image("Debug Server Firmware",
|
||||
(u64)raw_image_addr, raw_image_size,
|
||||
debug_server_ram_addr);
|
||||
|
||||
/* flush dcache */
|
||||
flush_dcache_range((unsigned long)debug_server_ram_addr,
|
||||
(unsigned long)debug_server_ram_addr +
|
||||
(unsigned long)debug_server_ram_size);
|
||||
|
||||
/*
|
||||
* Tell SP that the Debug Server FW is about to be launched. Before that
|
||||
* populate the following:
|
||||
* 1. Write the size allocated to SP Memory region into Bits {31:16} of
|
||||
* SCRATCHRW5.
|
||||
* 2. Write the start address of the SP memory regions into
|
||||
* SCRATCHRW5 (Bits {15:0}, contain most significant bits, Bits
|
||||
* {47:32} of the SP Memory Region physical start address
|
||||
* (SoC address)) and SCRATCHRW6 (Bits {31:0}).
|
||||
* 3. To know the Debug Server FW boot status, set bit 0 of SCRATCHRW11
|
||||
* to 1. The Debug Server sets this to 0 to indicate a
|
||||
* successul boot.
|
||||
* 4. Wakeup SP by writing 0x1F to VSG GIC reg VIGR2.
|
||||
*/
|
||||
|
||||
/* 512 MB */
|
||||
out_le32(&gur->scratchrw[5 - 1],
|
||||
(u32)((u64)debug_server_ram_addr >> 32) | (0x000D << 16));
|
||||
out_le32(&gur->scratchrw[6 - 1],
|
||||
((u32)debug_server_ram_addr) & 0xFFFFFFFF);
|
||||
|
||||
out_le32(&gur->scratchrw[11 - 1], DEBUG_SERVER_INIT_STATUS);
|
||||
/* Allow the changes to reflect in GUR block */
|
||||
mb();
|
||||
|
||||
/*
|
||||
* Program VGIC to raise an interrupt to SP
|
||||
*/
|
||||
out_le32(CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2, 0x1F);
|
||||
/* Allow the changes to reflect in VIGR2 */
|
||||
mb();
|
||||
|
||||
dmb();
|
||||
debug("Polling for Debug server to launch ...\n");
|
||||
|
||||
while (1) {
|
||||
debug_server_boot_status = in_le32(&gur->scratchrw[11 - 1]);
|
||||
if (!(debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK))
|
||||
break;
|
||||
|
||||
udelay(1); /* throttle polling */
|
||||
if (timeout-- <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout <= 0) {
|
||||
printf("Debug Server FW timed out (boot status: 0x%x)\n",
|
||||
debug_server_boot_status);
|
||||
error = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK) {
|
||||
printf("Debug server FW error'ed out (boot status: 0x%x)\n",
|
||||
debug_server_boot_status);
|
||||
error = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Debug server booted\n");
|
||||
printf("Detected firmware %d.%d, (boot status: 0x0%x)\n",
|
||||
debug_server_ver_info_maj, debug_server_ver_info_min,
|
||||
debug_server_boot_status);
|
||||
|
||||
out:
|
||||
if (error != 0)
|
||||
debug_server_boot_status = -error;
|
||||
else
|
||||
debug_server_boot_status = 0;
|
||||
|
||||
return debug_server_boot_status;
|
||||
}
|
||||
|
|
@ -168,4 +168,25 @@ void init_final_memctl_regs(void)
|
|||
#ifdef CONFIG_SYS_CSPR0_FINAL
|
||||
set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0_FINAL);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_AMASK0_FINAL
|
||||
set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_CSPR1_FINAL
|
||||
set_ifc_cspr(IFC_CS1, CONFIG_SYS_CSPR1_FINAL);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_AMASK1_FINAL
|
||||
set_ifc_amask(IFC_CS1, CONFIG_SYS_AMASK1_FINAL);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_CSPR2_FINAL
|
||||
set_ifc_cspr(IFC_CS2, CONFIG_SYS_CSPR2_FINAL);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_AMASK2_FINAL
|
||||
set_ifc_amask(IFC_CS2, CONFIG_SYS_AMASK2);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_CSPR3_FINAL
|
||||
set_ifc_cspr(IFC_CS3, CONFIG_SYS_CSPR3_FINAL);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_AMASK3_FINAL
|
||||
set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -105,7 +105,8 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
|
|||
else if (cmd->resp_type & MMC_RSP_PRESENT)
|
||||
xfertyp |= XFERTYP_RSPTYP_48;
|
||||
|
||||
#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || defined(CONFIG_LS102XA)
|
||||
#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \
|
||||
defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A)
|
||||
if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
|
||||
xfertyp |= XFERTYP_CMDTYP_ABORT;
|
||||
#endif
|
||||
|
@ -183,7 +184,9 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
|||
int timeout;
|
||||
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||
|
||||
#ifdef CONFIG_LS2085A
|
||||
dma_addr_t addr;
|
||||
#endif
|
||||
uint wml_value;
|
||||
|
||||
wml_value = data->blocksize/4;
|
||||
|
@ -194,7 +197,15 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
|||
|
||||
esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value);
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
#ifdef CONFIG_LS2085A
|
||||
addr = virt_to_phys((void *)(data->dest));
|
||||
if (upper_32_bits(addr))
|
||||
printf("Error found for upper 32 bits\n");
|
||||
else
|
||||
esdhc_write32(®s->dsaddr, lower_32_bits(addr));
|
||||
#else
|
||||
esdhc_write32(®s->dsaddr, (u32)data->dest);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
|
@ -212,7 +223,15 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
|||
esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK,
|
||||
wml_value << 16);
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
#ifdef CONFIG_LS2085A
|
||||
addr = virt_to_phys((void *)(data->src));
|
||||
if (upper_32_bits(addr))
|
||||
printf("Error found for upper 32 bits\n");
|
||||
else
|
||||
esdhc_write32(®s->dsaddr, lower_32_bits(addr));
|
||||
#else
|
||||
esdhc_write32(®s->dsaddr, (u32)data->src);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -259,10 +278,23 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
|||
static void check_and_invalidate_dcache_range
|
||||
(struct mmc_cmd *cmd,
|
||||
struct mmc_data *data) {
|
||||
#ifdef CONFIG_LS2085A
|
||||
unsigned start = 0;
|
||||
#else
|
||||
unsigned start = (unsigned)data->dest ;
|
||||
#endif
|
||||
unsigned size = roundup(ARCH_DMA_MINALIGN,
|
||||
data->blocks*data->blocksize);
|
||||
unsigned end = start+size ;
|
||||
#ifdef CONFIG_LS2085A
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = virt_to_phys((void *)(data->dest));
|
||||
if (upper_32_bits(addr))
|
||||
printf("Error found for upper 32 bits\n");
|
||||
else
|
||||
start = lower_32_bits(addr);
|
||||
#endif
|
||||
invalidate_dcache_range(start, end);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,7 @@ struct fsl_ifc_ctrl {
|
|||
struct fsl_ifc_mtd *chips[MAX_BANKS];
|
||||
|
||||
/* device info */
|
||||
struct fsl_ifc *regs;
|
||||
struct fsl_ifc regs;
|
||||
uint8_t __iomem *addr; /* Address of assigned IFC buffer */
|
||||
unsigned int cs_nand; /* On which chipsel NAND is connected */
|
||||
unsigned int page; /* Last page written to / read from */
|
||||
|
@ -225,7 +225,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
|
|||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc *ifc = ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
|
||||
int buf_num;
|
||||
|
||||
ctrl->page = page_addr;
|
||||
|
@ -289,10 +289,10 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
|
|||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc *ifc = ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
|
||||
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
|
||||
u32 time_start;
|
||||
u32 eccstat[4] = {0};
|
||||
u32 eccstat[8] = {0};
|
||||
int i;
|
||||
|
||||
/* set the chip select for NAND Transaction */
|
||||
|
@ -325,8 +325,15 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
|
|||
int sector = bufnum * chip->ecc.steps;
|
||||
int sector_end = sector + chip->ecc.steps - 1;
|
||||
|
||||
for (i = sector / 4; i <= sector_end / 4; i++)
|
||||
for (i = sector / 4; i <= sector_end / 4; i++) {
|
||||
if (i >= ARRAY_SIZE(eccstat)) {
|
||||
printf("%s: eccstat too small for %d\n",
|
||||
__func__, i);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
|
||||
}
|
||||
|
||||
for (i = sector; i <= sector_end; i++) {
|
||||
errors = check_read_ecc(mtd, ctrl, eccstat, i);
|
||||
|
@ -362,7 +369,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
|
|||
{
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc *ifc = ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
|
||||
|
||||
/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
|
||||
if (mtd->writesize > 512) {
|
||||
|
@ -400,7 +407,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|||
struct nand_chip *chip = mtd->priv;
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc *ifc = ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
|
||||
|
||||
/* clear the read buffer */
|
||||
ctrl->read_bytes = 0;
|
||||
|
@ -690,7 +697,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|||
{
|
||||
struct fsl_ifc_mtd *priv = chip->priv;
|
||||
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
|
||||
struct fsl_ifc *ifc = ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
|
||||
u32 nand_fsr;
|
||||
|
||||
if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
|
||||
|
@ -747,24 +754,33 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
static void fsl_ifc_ctrl_init(void)
|
||||
{
|
||||
uint32_t ver = 0;
|
||||
ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
|
||||
if (!ifc_ctrl)
|
||||
return;
|
||||
|
||||
ifc_ctrl->regs = IFC_BASE_ADDR;
|
||||
ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
|
||||
|
||||
ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
|
||||
if (ver >= FSL_IFC_V2_0_0)
|
||||
ifc_ctrl->regs.rregs =
|
||||
(void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
|
||||
else
|
||||
ifc_ctrl->regs.rregs =
|
||||
(void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
|
||||
|
||||
/* clear event registers */
|
||||
ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
|
||||
ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
|
||||
ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
|
||||
ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
|
||||
|
||||
/* Enable error and event for any detected errors */
|
||||
ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
|
||||
ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
|
||||
IFC_NAND_EVTER_EN_OPC_EN |
|
||||
IFC_NAND_EVTER_EN_PGRDCMPL_EN |
|
||||
IFC_NAND_EVTER_EN_FTOER_EN |
|
||||
IFC_NAND_EVTER_EN_WPER_EN);
|
||||
|
||||
ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
|
||||
ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
|
||||
}
|
||||
|
||||
static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
|
||||
|
@ -773,7 +789,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
|
|||
|
||||
static int fsl_ifc_sram_init(uint32_t ver)
|
||||
{
|
||||
struct fsl_ifc *ifc = ifc_ctrl->regs;
|
||||
struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
|
||||
uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
|
||||
uint32_t ncfgr = 0;
|
||||
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
|
||||
|
@ -799,13 +815,13 @@ static int fsl_ifc_sram_init(uint32_t ver)
|
|||
cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
|
||||
|
||||
/* Save CSOR and CSOR_ext */
|
||||
csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor);
|
||||
csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
|
||||
csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
|
||||
csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
|
||||
|
||||
/* chage PageSize 8K and SpareSize 1K*/
|
||||
csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
|
||||
ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
|
||||
ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
|
||||
ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
|
||||
ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
|
||||
|
||||
/* READID */
|
||||
ifc_out32(&ifc->ifc_nand.nand_fir0,
|
||||
|
@ -845,8 +861,8 @@ static int fsl_ifc_sram_init(uint32_t ver)
|
|||
ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
|
||||
|
||||
/* Restore CSOR and CSOR_ext */
|
||||
ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
|
||||
ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
|
||||
ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
|
||||
ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -857,6 +873,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
|
|||
struct nand_chip *nand;
|
||||
struct fsl_ifc_mtd *priv;
|
||||
struct nand_ecclayout *layout;
|
||||
struct fsl_ifc_fcm *gregs = NULL;
|
||||
uint32_t cspr = 0, csor = 0, ver = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -872,14 +889,15 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
|
|||
|
||||
priv->ctrl = ifc_ctrl;
|
||||
priv->vbase = addr;
|
||||
gregs = ifc_ctrl->regs.gregs;
|
||||
|
||||
/* Find which chip select it is connected to.
|
||||
*/
|
||||
for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
|
||||
phys_addr_t phys_addr = virt_to_phys(addr);
|
||||
|
||||
cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
|
||||
csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
|
||||
cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
|
||||
csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
|
||||
|
||||
if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
|
||||
(cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
|
||||
|
@ -998,7 +1016,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
|
|||
nand->ecc.mode = NAND_ECC_SOFT;
|
||||
}
|
||||
|
||||
ver = ifc_in32(&ifc_ctrl->regs->ifc_rev);
|
||||
ver = ifc_in32(&gregs->ifc_rev);
|
||||
if (ver >= FSL_IFC_V1_1_0)
|
||||
ret = fsl_ifc_sram_init(ver);
|
||||
if (ret)
|
||||
|
|
|
@ -48,11 +48,25 @@ static inline int check_read_ecc(uchar *buf, u32 *eccstat,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline struct fsl_ifc_runtime *runtime_regs_address(void)
|
||||
{
|
||||
struct fsl_ifc regs = {(void *)CONFIG_SYS_IFC_ADDR, NULL};
|
||||
int ver = 0;
|
||||
|
||||
ver = ifc_in32(®s.gregs->ifc_rev);
|
||||
if (ver >= FSL_IFC_V2_0_0)
|
||||
regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
|
||||
else
|
||||
regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
|
||||
|
||||
return regs.rregs;
|
||||
}
|
||||
|
||||
static inline void nand_wait(uchar *buf, int bufnum, int page_size)
|
||||
{
|
||||
struct fsl_ifc *ifc = IFC_BASE_ADDR;
|
||||
struct fsl_ifc_runtime *ifc = runtime_regs_address();
|
||||
u32 status;
|
||||
u32 eccstat[4];
|
||||
u32 eccstat[8];
|
||||
int bufperpage = page_size / 512;
|
||||
int bufnum_end, i;
|
||||
|
||||
|
@ -90,7 +104,8 @@ static inline int bad_block(uchar *marker, int port_size)
|
|||
|
||||
int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
|
||||
{
|
||||
struct fsl_ifc *ifc = IFC_BASE_ADDR;
|
||||
struct fsl_ifc_fcm *gregs = (void *)CONFIG_SYS_IFC_ADDR;
|
||||
struct fsl_ifc_runtime *ifc = NULL;
|
||||
uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
|
||||
int page_size;
|
||||
int port_size;
|
||||
|
@ -107,6 +122,8 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
|
|||
int pg_no;
|
||||
uchar *dst = vdst;
|
||||
|
||||
ifc = runtime_regs_address();
|
||||
|
||||
/* Get NAND Flash configuration */
|
||||
csor = CONFIG_SYS_NAND_CSOR;
|
||||
cspr = CONFIG_SYS_NAND_CSPR;
|
||||
|
@ -130,7 +147,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
|
|||
bad_marker = 5;
|
||||
}
|
||||
|
||||
ver = ifc_in32(&ifc->ifc_rev);
|
||||
ver = ifc_in32(&gregs->ifc_rev);
|
||||
if (ver >= FSL_IFC_V2_0_0)
|
||||
bufnum_mask = (bufnum_mask * 2) + 1;
|
||||
|
||||
|
|
|
@ -69,4 +69,6 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
|
|||
xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
|
||||
obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
|
||||
obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
|
||||
obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
|
||||
obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
|
||||
obj-$(CONFIG_VSC9953) += vsc9953.o
|
||||
|
|
|
@ -2174,7 +2174,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
|
|||
DEBUGOUT("Error, did not detect valid phy.\n");
|
||||
return ret_val;
|
||||
}
|
||||
DEBUGOUT("Phy ID = %x \n", hw->phy_id);
|
||||
DEBUGOUT("Phy ID = %x\n", hw->phy_id);
|
||||
|
||||
/* Set PHY to class A mode (if necessary) */
|
||||
ret_val = e1000_set_phy_mode(hw);
|
||||
|
@ -3485,11 +3485,11 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
|
|||
* some "sticky" (latched) bits.
|
||||
*/
|
||||
if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
|
||||
DEBUGOUT("PHY Read Error \n");
|
||||
DEBUGOUT("PHY Read Error\n");
|
||||
return -E1000_ERR_PHY;
|
||||
}
|
||||
if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
|
||||
DEBUGOUT("PHY Read Error \n");
|
||||
DEBUGOUT("PHY Read Error\n");
|
||||
return -E1000_ERR_PHY;
|
||||
}
|
||||
|
||||
|
@ -5152,7 +5152,7 @@ e1000_poll(struct eth_device *nic)
|
|||
|
||||
if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD)
|
||||
return 0;
|
||||
/*DEBUGOUT("recv: packet len=%d \n", rd->length); */
|
||||
/* DEBUGOUT("recv: packet len=%d\n", rd->length); */
|
||||
/* Packet received, make sure the data are re-loaded from RAM. */
|
||||
len = le32_to_cpu(rd->length);
|
||||
invalidate_dcache_range((unsigned long)packet,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <phy.h>
|
||||
#include <asm/fsl_dtsec.h>
|
||||
#include <asm/fsl_tgec.h>
|
||||
#include <asm/fsl_memac.h>
|
||||
#include <fsl_memac.h>
|
||||
|
||||
#include "fm.h"
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <phy.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/fsl_memac.h>
|
||||
#include <fsl_memac.h>
|
||||
|
||||
#include "fm.h"
|
||||
|
||||
|
|
|
@ -10,9 +10,28 @@
|
|||
#include <miiphy.h>
|
||||
#include <phy.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/fsl_memac.h>
|
||||
#include <fsl_memac.h>
|
||||
#include <fm_eth.h>
|
||||
|
||||
#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
|
||||
#define memac_out_32(a, v) out_le32(a, v)
|
||||
#define memac_clrbits_32(a, v) clrbits_le32(a, v)
|
||||
#define memac_setbits_32(a, v) setbits_le32(a, v)
|
||||
#else
|
||||
#define memac_out_32(a, v) out_be32(a, v)
|
||||
#define memac_clrbits_32(a, v) clrbits_be32(a, v)
|
||||
#define memac_setbits_32(a, v) setbits_be32(a, v)
|
||||
#endif
|
||||
|
||||
static u32 memac_in_32(u32 *reg)
|
||||
{
|
||||
#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
|
||||
return in_le32(reg);
|
||||
#else
|
||||
return in_be32(reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Write value to the PHY for this device to the register at regnum, waiting
|
||||
* until the write is done before it returns. All PHY configuration has to be
|
||||
|
@ -28,31 +47,31 @@ int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
|
|||
if (dev_addr == MDIO_DEVAD_NONE) {
|
||||
c45 = 0; /* clause 22 */
|
||||
dev_addr = regnum & 0x1f;
|
||||
clrbits_be32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
} else
|
||||
setbits_be32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
|
||||
/* Wait till the bus is free */
|
||||
while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
;
|
||||
|
||||
/* Set the port and dev addr */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
out_be32(®s->mdio_ctl, mdio_ctl);
|
||||
memac_out_32(®s->mdio_ctl, mdio_ctl);
|
||||
|
||||
/* Set the register address */
|
||||
if (c45)
|
||||
out_be32(®s->mdio_addr, regnum & 0xffff);
|
||||
memac_out_32(®s->mdio_addr, regnum & 0xffff);
|
||||
|
||||
/* Wait till the bus is free */
|
||||
while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
;
|
||||
|
||||
/* Write the value to the register */
|
||||
out_be32(®s->mdio_data, MDIO_DATA(value));
|
||||
memac_out_32(®s->mdio_data, MDIO_DATA(value));
|
||||
|
||||
/* Wait till the MDIO write is complete */
|
||||
while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY)
|
||||
while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY)
|
||||
;
|
||||
|
||||
return 0;
|
||||
|
@ -75,39 +94,39 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
|
|||
return 0xffff;
|
||||
c45 = 0; /* clause 22 */
|
||||
dev_addr = regnum & 0x1f;
|
||||
clrbits_be32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
} else
|
||||
setbits_be32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
|
||||
|
||||
/* Wait till the bus is free */
|
||||
while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
;
|
||||
|
||||
/* Set the Port and Device Addrs */
|
||||
mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
|
||||
out_be32(®s->mdio_ctl, mdio_ctl);
|
||||
memac_out_32(®s->mdio_ctl, mdio_ctl);
|
||||
|
||||
/* Set the register address */
|
||||
if (c45)
|
||||
out_be32(®s->mdio_addr, regnum & 0xffff);
|
||||
memac_out_32(®s->mdio_addr, regnum & 0xffff);
|
||||
|
||||
/* Wait till the bus is free */
|
||||
while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
|
||||
;
|
||||
|
||||
/* Initiate the read */
|
||||
mdio_ctl |= MDIO_CTL_READ;
|
||||
out_be32(®s->mdio_ctl, mdio_ctl);
|
||||
memac_out_32(®s->mdio_ctl, mdio_ctl);
|
||||
|
||||
/* Wait till the MDIO write is complete */
|
||||
while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY)
|
||||
while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY)
|
||||
;
|
||||
|
||||
/* Return all Fs if nothing was there */
|
||||
if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER)
|
||||
if (memac_in_32(®s->mdio_stat) & MDIO_STAT_RD_ER)
|
||||
return 0xffff;
|
||||
|
||||
return in_be32(®s->mdio_data) & 0xffff;
|
||||
return memac_in_32(®s->mdio_data) & 0xffff;
|
||||
}
|
||||
|
||||
int memac_mdio_reset(struct mii_dev *bus)
|
||||
|
@ -143,8 +162,9 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
|
|||
* like T2080QDS, this bit default is '0', which leads to MDIO failure
|
||||
* on XAUI PHY, so set this bit definitely.
|
||||
*/
|
||||
setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat,
|
||||
MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
|
||||
memac_setbits_32(
|
||||
&((struct memac_mdio_controller *)info->regs)->mdio_stat,
|
||||
MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
|
||||
|
||||
return mdio_register(bus);
|
||||
}
|
||||
|
|
|
@ -7,4 +7,8 @@
|
|||
# Layerscape MC driver
|
||||
obj-y += mc.o \
|
||||
mc_sys.o \
|
||||
dpmng.o
|
||||
dpmng.o \
|
||||
dprc.o \
|
||||
dpbp.o \
|
||||
dpni.o
|
||||
obj-y += dpio/
|
||||
|
|
102
drivers/net/fsl-mc/dpbp.c
Normal file
102
drivers/net/fsl-mc/dpbp.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Freescale Layerscape MC I/O wrapper
|
||||
*
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
|
||||
* Author: German Rivera <German.Rivera@freescale.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <fsl-mc/fsl_mc_sys.h>
|
||||
#include <fsl-mc/fsl_mc_cmd.h>
|
||||
#include <fsl-mc/fsl_dpbp.h>
|
||||
|
||||
int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
|
||||
MC_CMD_PRI_LOW, 0);
|
||||
DPBP_CMD_OPEN(cmd, dpbp_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpbp_get_attributes(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpbp_attr *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPBP_RSP_GET_ATTRIBUTES(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
9
drivers/net/fsl-mc/dpio/Makefile
Normal file
9
drivers/net/fsl-mc/dpio/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Copyright 2014 Freescale Semiconductor, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
# Layerscape MC DPIO driver
|
||||
obj-y += dpio.o \
|
||||
qbman_portal.o
|
102
drivers/net/fsl-mc/dpio/dpio.c
Normal file
102
drivers/net/fsl-mc/dpio/dpio.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <fsl-mc/fsl_mc_sys.h>
|
||||
#include <fsl-mc/fsl_mc_cmd.h>
|
||||
#include <fsl-mc/fsl_dpio.h>
|
||||
|
||||
int dpio_open(struct fsl_mc_io *mc_io, int dpio_id, uint16_t *token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
|
||||
MC_CMD_PRI_LOW, 0);
|
||||
DPIO_CMD_OPEN(cmd, dpio_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpio_close(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
|
||||
MC_CMD_PRI_HIGH, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpio_enable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpio_disable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpio_reset(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpio_get_attributes(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpio_attr *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPIO_RSP_GET_ATTR(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
593
drivers/net/fsl-mc/dpio/qbman_portal.c
Normal file
593
drivers/net/fsl-mc/dpio/qbman_portal.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "qbman_portal.h"
|
||||
|
||||
/* QBMan portal management command codes */
|
||||
#define QBMAN_MC_ACQUIRE 0x30
|
||||
#define QBMAN_WQCHAN_CONFIGURE 0x46
|
||||
|
||||
/* CINH register offsets */
|
||||
#define QBMAN_CINH_SWP_EQAR 0x8c0
|
||||
#define QBMAN_CINH_SWP_DCAP 0xac0
|
||||
#define QBMAN_CINH_SWP_SDQCR 0xb00
|
||||
#define QBMAN_CINH_SWP_RAR 0xcc0
|
||||
|
||||
/* CENA register offsets */
|
||||
#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6))
|
||||
#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6))
|
||||
#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6))
|
||||
#define QBMAN_CENA_SWP_CR 0x600
|
||||
#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1))
|
||||
#define QBMAN_CENA_SWP_VDQCR 0x780
|
||||
|
||||
/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
|
||||
#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0xff) >> 6)
|
||||
|
||||
/*******************************/
|
||||
/* Pre-defined attribute codes */
|
||||
/*******************************/
|
||||
|
||||
struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7);
|
||||
struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8);
|
||||
|
||||
/*************************/
|
||||
/* SDQCR attribute codes */
|
||||
/*************************/
|
||||
|
||||
/* we put these here because at least some of them are required by
|
||||
* qbman_swp_init() */
|
||||
struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2);
|
||||
struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1);
|
||||
struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8);
|
||||
#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1)
|
||||
enum qbman_sdqcr_dct {
|
||||
qbman_sdqcr_dct_null = 0,
|
||||
qbman_sdqcr_dct_prio_ics,
|
||||
qbman_sdqcr_dct_active_ics,
|
||||
qbman_sdqcr_dct_active
|
||||
};
|
||||
enum qbman_sdqcr_fc {
|
||||
qbman_sdqcr_fc_one = 0,
|
||||
qbman_sdqcr_fc_up_to_3 = 1
|
||||
};
|
||||
|
||||
/*********************************/
|
||||
/* Portal constructor/destructor */
|
||||
/*********************************/
|
||||
|
||||
/* Software portals should always be in the power-on state when we initialise,
|
||||
* due to the CCSR-based portal reset functionality that MC has. */
|
||||
struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
|
||||
{
|
||||
int ret;
|
||||
struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->desc = d;
|
||||
#ifdef QBMAN_CHECKING
|
||||
p->mc.check = swp_mc_can_start;
|
||||
#endif
|
||||
p->mc.valid_bit = QB_VALID_BIT;
|
||||
p->sdq = 0;
|
||||
qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics);
|
||||
qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3);
|
||||
qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb);
|
||||
p->vdq.busy = 0; /* TODO: convert to atomic_t */
|
||||
p->vdq.valid_bit = QB_VALID_BIT;
|
||||
p->dqrr.next_idx = 0;
|
||||
p->dqrr.valid_bit = QB_VALID_BIT;
|
||||
ret = qbman_swp_sys_init(&p->sys, d);
|
||||
if (ret) {
|
||||
free(p);
|
||||
printf("qbman_swp_sys_init() failed %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, p->sdq);
|
||||
return p;
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* Management commands */
|
||||
/***********************/
|
||||
|
||||
/*
|
||||
* Internal code common to all types of management commands.
|
||||
*/
|
||||
|
||||
void *qbman_swp_mc_start(struct qbman_swp *p)
|
||||
{
|
||||
void *ret;
|
||||
#ifdef QBMAN_CHECKING
|
||||
BUG_ON(p->mc.check != swp_mc_can_start);
|
||||
#endif
|
||||
ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR);
|
||||
#ifdef QBMAN_CHECKING
|
||||
if (!ret)
|
||||
p->mc.check = swp_mc_can_submit;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb)
|
||||
{
|
||||
uint32_t *v = cmd;
|
||||
#ifdef QBMAN_CHECKING
|
||||
BUG_ON(!p->mc.check != swp_mc_can_submit);
|
||||
#endif
|
||||
lwsync();
|
||||
/* TBD: "|=" is going to hurt performance. Need to move as many fields
|
||||
* out of word zero, and for those that remain, the "OR" needs to occur
|
||||
* at the caller side. This debug check helps to catch cases where the
|
||||
* caller wants to OR but has forgotten to do so. */
|
||||
BUG_ON((*v & cmd_verb) != *v);
|
||||
*v = cmd_verb | p->mc.valid_bit;
|
||||
qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd);
|
||||
/* TODO: add prefetch support for GPP */
|
||||
#ifdef QBMAN_CHECKING
|
||||
p->mc.check = swp_mc_can_poll;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *qbman_swp_mc_result(struct qbman_swp *p)
|
||||
{
|
||||
uint32_t *ret, verb;
|
||||
#ifdef QBMAN_CHECKING
|
||||
BUG_ON(p->mc.check != swp_mc_can_poll);
|
||||
#endif
|
||||
ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
|
||||
/* Remove the valid-bit - command completed iff the rest is non-zero */
|
||||
verb = ret[0] & ~QB_VALID_BIT;
|
||||
if (!verb)
|
||||
return NULL;
|
||||
#ifdef QBMAN_CHECKING
|
||||
p->mc.check = swp_mc_can_start;
|
||||
#endif
|
||||
p->mc.valid_bit ^= QB_VALID_BIT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* Enqueue */
|
||||
/***********/
|
||||
|
||||
/* These should be const, eventually */
|
||||
static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2);
|
||||
static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1);
|
||||
static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24);
|
||||
/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */
|
||||
static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1);
|
||||
static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16);
|
||||
static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4);
|
||||
static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1);
|
||||
static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32);
|
||||
static struct qb_attr_code code_eq_rsp_hi = QB_CODE(7, 0, 32);
|
||||
|
||||
enum qbman_eq_cmd_e {
|
||||
/* No enqueue, primarily for plugging ORP gaps for dropped frames */
|
||||
qbman_eq_cmd_empty,
|
||||
/* DMA an enqueue response once complete */
|
||||
qbman_eq_cmd_respond,
|
||||
/* DMA an enqueue response only if the enqueue fails */
|
||||
qbman_eq_cmd_respond_reject
|
||||
};
|
||||
|
||||
void qbman_eq_desc_clear(struct qbman_eq_desc *d)
|
||||
{
|
||||
memset(d, 0, sizeof(*d));
|
||||
}
|
||||
|
||||
void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_eq_orp_en, cl, 0);
|
||||
qb_attr_code_encode(&code_eq_cmd, cl,
|
||||
respond_success ? qbman_eq_cmd_respond :
|
||||
qbman_eq_cmd_respond_reject);
|
||||
}
|
||||
|
||||
void qbman_eq_desc_set_response(struct qbman_eq_desc *d,
|
||||
dma_addr_t storage_phys,
|
||||
int stash)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_eq_rsp_lo, cl, lower32(storage_phys));
|
||||
qb_attr_code_encode(&code_eq_rsp_hi, cl, upper32(storage_phys));
|
||||
qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash);
|
||||
}
|
||||
|
||||
|
||||
void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid,
|
||||
uint32_t qd_bin, uint32_t qd_prio)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_eq_qd_en, cl, 1);
|
||||
qb_attr_code_encode(&code_eq_tgt_id, cl, qdid);
|
||||
qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin);
|
||||
qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio);
|
||||
}
|
||||
|
||||
#define EQAR_IDX(eqar) ((eqar) & 0x7)
|
||||
#define EQAR_VB(eqar) ((eqar) & 0x80)
|
||||
#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
|
||||
|
||||
int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
|
||||
const struct qbman_fd *fd)
|
||||
{
|
||||
uint32_t *p;
|
||||
const uint32_t *cl = qb_cl(d);
|
||||
uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR);
|
||||
debug("EQAR=%08x\n", eqar);
|
||||
if (!EQAR_SUCCESS(eqar))
|
||||
return -EBUSY;
|
||||
p = qbman_cena_write_start(&s->sys,
|
||||
QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
|
||||
word_copy(&p[1], &cl[1], 7);
|
||||
word_copy(&p[8], fd, sizeof(*fd) >> 2);
|
||||
lwsync();
|
||||
/* Set the verb byte, have to substitute in the valid-bit */
|
||||
p[0] = cl[0] | EQAR_VB(eqar);
|
||||
qbman_cena_write_complete(&s->sys,
|
||||
QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)),
|
||||
p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* Volatile (pull) dequeue */
|
||||
/***************************/
|
||||
|
||||
/* These should be const, eventually */
|
||||
static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2);
|
||||
static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2);
|
||||
static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1);
|
||||
static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1);
|
||||
static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4);
|
||||
static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8);
|
||||
static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24);
|
||||
static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32);
|
||||
static struct qb_attr_code code_pull_rsp_hi = QB_CODE(3, 0, 32);
|
||||
|
||||
enum qb_pull_dt_e {
|
||||
qb_pull_dt_channel,
|
||||
qb_pull_dt_workqueue,
|
||||
qb_pull_dt_framequeue
|
||||
};
|
||||
|
||||
void qbman_pull_desc_clear(struct qbman_pull_desc *d)
|
||||
{
|
||||
memset(d, 0, sizeof(*d));
|
||||
}
|
||||
|
||||
void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
|
||||
struct ldpaa_dq *storage,
|
||||
dma_addr_t storage_phys,
|
||||
int stash)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
/* Squiggle the pointer 'storage' into the extra 2 words of the
|
||||
* descriptor (which aren't copied to the hw command) */
|
||||
*(void **)&cl[4] = storage;
|
||||
if (!storage) {
|
||||
qb_attr_code_encode(&code_pull_rls, cl, 0);
|
||||
return;
|
||||
}
|
||||
qb_attr_code_encode(&code_pull_rls, cl, 1);
|
||||
qb_attr_code_encode(&code_pull_stash, cl, !!stash);
|
||||
qb_attr_code_encode(&code_pull_rsp_lo, cl, lower32(storage_phys));
|
||||
qb_attr_code_encode(&code_pull_rsp_hi, cl, upper32(storage_phys));
|
||||
}
|
||||
|
||||
void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
BUG_ON(!numframes || (numframes > 16));
|
||||
qb_attr_code_encode(&code_pull_numframes, cl,
|
||||
(uint32_t)(numframes - 1));
|
||||
}
|
||||
|
||||
void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_pull_token, cl, token);
|
||||
}
|
||||
|
||||
void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_pull_dct, cl, 1);
|
||||
qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue);
|
||||
qb_attr_code_encode(&code_pull_dqsource, cl, fqid);
|
||||
}
|
||||
|
||||
int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
|
||||
{
|
||||
uint32_t *p;
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
/* TODO: convert to atomic_t */
|
||||
if (s->vdq.busy)
|
||||
return -EBUSY;
|
||||
s->vdq.busy = 1;
|
||||
s->vdq.storage = *(void **)&cl[4];
|
||||
s->vdq.token = qb_attr_code_decode(&code_pull_token, cl);
|
||||
p = qbman_cena_write_start(&s->sys, QBMAN_CENA_SWP_VDQCR);
|
||||
word_copy(&p[1], &cl[1], 3);
|
||||
lwsync();
|
||||
/* Set the verb byte, have to substitute in the valid-bit */
|
||||
p[0] = cl[0] | s->vdq.valid_bit;
|
||||
s->vdq.valid_bit ^= QB_VALID_BIT;
|
||||
qbman_cena_write_complete(&s->sys, QBMAN_CENA_SWP_VDQCR, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* Polling DQRR */
|
||||
/****************/
|
||||
|
||||
static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8);
|
||||
static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7);
|
||||
static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8);
|
||||
|
||||
#define QBMAN_DQRR_RESPONSE_DQ 0x60
|
||||
#define QBMAN_DQRR_RESPONSE_FQRN 0x21
|
||||
#define QBMAN_DQRR_RESPONSE_FQRNI 0x22
|
||||
#define QBMAN_DQRR_RESPONSE_FQPN 0x24
|
||||
#define QBMAN_DQRR_RESPONSE_FQDAN 0x25
|
||||
#define QBMAN_DQRR_RESPONSE_CDAN 0x26
|
||||
#define QBMAN_DQRR_RESPONSE_CSCN_MEM 0x27
|
||||
#define QBMAN_DQRR_RESPONSE_CGCU 0x28
|
||||
#define QBMAN_DQRR_RESPONSE_BPSCN 0x29
|
||||
#define QBMAN_DQRR_RESPONSE_CSCN_WQ 0x2a
|
||||
|
||||
|
||||
/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry
|
||||
* only once, so repeated calls can return a sequence of DQRR entries, without
|
||||
* requiring they be consumed immediately or in any particular order. */
|
||||
const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
|
||||
{
|
||||
uint32_t verb;
|
||||
uint32_t response_verb;
|
||||
const struct ldpaa_dq *dq = qbman_cena_read(&s->sys,
|
||||
QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
|
||||
const uint32_t *p = qb_cl(dq);
|
||||
|
||||
verb = qb_attr_code_decode(&code_dqrr_verb, p);
|
||||
/* If the valid-bit isn't of the expected polarity, nothing there */
|
||||
if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
|
||||
qbman_cena_invalidate_prefetch(&s->sys,
|
||||
QBMAN_CENA_SWP_DQRR(
|
||||
s->dqrr.next_idx));
|
||||
return NULL;
|
||||
}
|
||||
/* There's something there. Move "next_idx" attention to the next ring
|
||||
* entry (and prefetch it) before returning what we found. */
|
||||
s->dqrr.next_idx++;
|
||||
s->dqrr.next_idx &= 3; /* Wrap around at 4 */
|
||||
/* TODO: it's possible to do all this without conditionals, optimise it
|
||||
* later. */
|
||||
if (!s->dqrr.next_idx)
|
||||
s->dqrr.valid_bit ^= QB_VALID_BIT;
|
||||
/* VDQCR "no longer busy" hook - if VDQCR shows "busy" and this is a
|
||||
* VDQCR result, mark it as non-busy. */
|
||||
if (s->vdq.busy) {
|
||||
uint32_t flags = ldpaa_dq_flags(dq);
|
||||
|
||||
response_verb = qb_attr_code_decode(&code_dqrr_response, &verb);
|
||||
if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) &&
|
||||
(flags & LDPAA_DQ_STAT_VOLATILE))
|
||||
s->vdq.busy = 0;
|
||||
}
|
||||
qbman_cena_invalidate_prefetch(&s->sys,
|
||||
QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
|
||||
return dq;
|
||||
}
|
||||
|
||||
/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */
|
||||
void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct ldpaa_dq *dq)
|
||||
{
|
||||
qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/* Polling user-provided storage */
|
||||
/*********************************/
|
||||
|
||||
void qbman_dq_entry_set_oldtoken(struct ldpaa_dq *dq,
|
||||
unsigned int num_entries,
|
||||
uint8_t oldtoken)
|
||||
{
|
||||
memset(dq, oldtoken, num_entries * sizeof(*dq));
|
||||
}
|
||||
|
||||
int qbman_dq_entry_has_newtoken(struct qbman_swp *s,
|
||||
const struct ldpaa_dq *dq,
|
||||
uint8_t newtoken)
|
||||
{
|
||||
/* To avoid converting the little-endian DQ entry to host-endian prior
|
||||
* to us knowing whether there is a valid entry or not (and run the
|
||||
* risk of corrupting the incoming hardware LE write), we detect in
|
||||
* hardware endianness rather than host. This means we need a different
|
||||
* "code" depending on whether we are BE or LE in software, which is
|
||||
* where DQRR_TOK_OFFSET comes in... */
|
||||
static struct qb_attr_code code_dqrr_tok_detect =
|
||||
QB_CODE(0, DQRR_TOK_OFFSET, 8);
|
||||
/* The user trying to poll for a result treats "dq" as const. It is
|
||||
* however the same address that was provided to us non-const in the
|
||||
* first place, for directing hardware DMA to. So we can cast away the
|
||||
* const because it is mutable from our perspective. */
|
||||
uint32_t *p = qb_cl((struct ldpaa_dq *)dq);
|
||||
uint32_t token;
|
||||
|
||||
token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]);
|
||||
if (token != newtoken)
|
||||
return 0;
|
||||
|
||||
/* Only now do we convert from hardware to host endianness. Also, as we
|
||||
* are returning success, the user has promised not to call us again, so
|
||||
* there's no risk of us converting the endianness twice... */
|
||||
make_le32_n(p, 16);
|
||||
|
||||
/* VDQCR "no longer busy" hook - not quite the same as DQRR, because the
|
||||
* fact "VDQCR" shows busy doesn't mean that the result we're looking at
|
||||
* is from the same command. Eg. we may be looking at our 10th dequeue
|
||||
* result from our first VDQCR command, yet the second dequeue command
|
||||
* could have been kicked off already, after seeing the 1st result. Ie.
|
||||
* the result we're looking at is not necessarily proof that we can
|
||||
* reset "busy". We instead base the decision on whether the current
|
||||
* result is sitting at the first 'storage' location of the busy
|
||||
* command. */
|
||||
if (s->vdq.busy && (s->vdq.storage == dq))
|
||||
s->vdq.busy = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
/* Categorising dequeue entries */
|
||||
/********************************/
|
||||
|
||||
static inline int __qbman_dq_entry_is_x(const struct ldpaa_dq *dq, uint32_t x)
|
||||
{
|
||||
const uint32_t *p = qb_cl(dq);
|
||||
uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p);
|
||||
|
||||
return response_verb == x;
|
||||
}
|
||||
|
||||
int qbman_dq_entry_is_DQ(const struct ldpaa_dq *dq)
|
||||
{
|
||||
return __qbman_dq_entry_is_x(dq, QBMAN_DQRR_RESPONSE_DQ);
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/* Parsing frame dequeue results */
|
||||
/*********************************/
|
||||
|
||||
/* These APIs assume qbman_dq_entry_is_DQ() is TRUE */
|
||||
|
||||
uint32_t ldpaa_dq_flags(const struct ldpaa_dq *dq)
|
||||
{
|
||||
const uint32_t *p = qb_cl(dq);
|
||||
|
||||
return qb_attr_code_decode(&code_dqrr_stat, p);
|
||||
}
|
||||
|
||||
const struct dpaa_fd *ldpaa_dq_fd(const struct ldpaa_dq *dq)
|
||||
{
|
||||
const uint32_t *p = qb_cl(dq);
|
||||
|
||||
return (const struct dpaa_fd *)&p[8];
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Buffer release */
|
||||
/******************/
|
||||
|
||||
/* These should be const, eventually */
|
||||
/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */
|
||||
static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1);
|
||||
static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16);
|
||||
|
||||
void qbman_release_desc_clear(struct qbman_release_desc *d)
|
||||
{
|
||||
uint32_t *cl;
|
||||
|
||||
memset(d, 0, sizeof(*d));
|
||||
cl = qb_cl(d);
|
||||
qb_attr_code_encode(&code_release_set_me, cl, 1);
|
||||
}
|
||||
|
||||
void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid)
|
||||
{
|
||||
uint32_t *cl = qb_cl(d);
|
||||
|
||||
qb_attr_code_encode(&code_release_bpid, cl, bpid);
|
||||
}
|
||||
|
||||
#define RAR_IDX(rar) ((rar) & 0x7)
|
||||
#define RAR_VB(rar) ((rar) & 0x80)
|
||||
#define RAR_SUCCESS(rar) ((rar) & 0x100)
|
||||
|
||||
int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
|
||||
const uint64_t *buffers, unsigned int num_buffers)
|
||||
{
|
||||
uint32_t *p;
|
||||
const uint32_t *cl = qb_cl(d);
|
||||
uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
|
||||
debug("RAR=%08x\n", rar);
|
||||
if (!RAR_SUCCESS(rar))
|
||||
return -EBUSY;
|
||||
BUG_ON(!num_buffers || (num_buffers > 7));
|
||||
/* Start the release command */
|
||||
p = qbman_cena_write_start(&s->sys,
|
||||
QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
|
||||
/* Copy the caller's buffer pointers to the command */
|
||||
u64_to_le32_copy(&p[2], buffers, num_buffers);
|
||||
lwsync();
|
||||
/* Set the verb byte, have to substitute in the valid-bit and the number
|
||||
* of buffers. */
|
||||
p[0] = cl[0] | RAR_VB(rar) | num_buffers;
|
||||
qbman_cena_write_complete(&s->sys,
|
||||
QBMAN_CENA_SWP_RCR(RAR_IDX(rar)),
|
||||
p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* Buffer acquires */
|
||||
/*******************/
|
||||
|
||||
/* These should be const, eventually */
|
||||
static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16);
|
||||
static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3);
|
||||
static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3);
|
||||
|
||||
int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers,
|
||||
unsigned int num_buffers)
|
||||
{
|
||||
uint32_t *p;
|
||||
uint32_t verb, rslt, num;
|
||||
|
||||
BUG_ON(!num_buffers || (num_buffers > 7));
|
||||
|
||||
/* Start the management command */
|
||||
p = qbman_swp_mc_start(s);
|
||||
|
||||
if (!p)
|
||||
return -EBUSY;
|
||||
|
||||
/* Encode the caller-provided attributes */
|
||||
qb_attr_code_encode(&code_acquire_bpid, p, bpid);
|
||||
qb_attr_code_encode(&code_acquire_num, p, num_buffers);
|
||||
|
||||
/* Complete the management command */
|
||||
p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE);
|
||||
|
||||
/* Decode the outcome */
|
||||
verb = qb_attr_code_decode(&code_generic_verb, p);
|
||||
rslt = qb_attr_code_decode(&code_generic_rslt, p);
|
||||
num = qb_attr_code_decode(&code_acquire_r_num, p);
|
||||
BUG_ON(verb != QBMAN_MC_ACQUIRE);
|
||||
|
||||
/* Determine success or failure */
|
||||
if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
|
||||
printf("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
|
||||
bpid, rslt);
|
||||
return -EIO;
|
||||
}
|
||||
BUG_ON(num > num_buffers);
|
||||
/* Copy the acquired buffers to the caller's array */
|
||||
u64_from_le32_copy(buffers, &p[2], num);
|
||||
return (int)num;
|
||||
}
|
157
drivers/net/fsl-mc/dpio/qbman_portal.h
Normal file
157
drivers/net/fsl-mc/dpio/qbman_portal.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "qbman_private.h"
|
||||
#include <fsl-mc/fsl_qbman_portal.h>
|
||||
#include <fsl-mc/fsl_dpaa_fd.h>
|
||||
|
||||
/* All QBMan command and result structures use this "valid bit" encoding */
|
||||
#define QB_VALID_BIT ((uint32_t)0x80)
|
||||
|
||||
/* Management command result codes */
|
||||
#define QBMAN_MC_RSLT_OK 0xf0
|
||||
|
||||
/* --------------------- */
|
||||
/* portal data structure */
|
||||
/* --------------------- */
|
||||
|
||||
struct qbman_swp {
|
||||
const struct qbman_swp_desc *desc;
|
||||
/* The qbman_sys (ie. arch/OS-specific) support code can put anything it
|
||||
* needs in here. */
|
||||
struct qbman_swp_sys sys;
|
||||
/* Management commands */
|
||||
struct {
|
||||
#ifdef QBMAN_CHECKING
|
||||
enum swp_mc_check {
|
||||
swp_mc_can_start, /* call __qbman_swp_mc_start() */
|
||||
swp_mc_can_submit, /* call __qbman_swp_mc_submit() */
|
||||
swp_mc_can_poll, /* call __qbman_swp_mc_result() */
|
||||
} check;
|
||||
#endif
|
||||
uint32_t valid_bit; /* 0x00 or 0x80 */
|
||||
} mc;
|
||||
/* Push dequeues */
|
||||
uint32_t sdq;
|
||||
/* Volatile dequeues */
|
||||
struct {
|
||||
/* VDQCR supports a "1 deep pipeline", meaning that if you know
|
||||
* the last-submitted command is already executing in the
|
||||
* hardware (as evidenced by at least 1 valid dequeue result),
|
||||
* you can write another dequeue command to the register, the
|
||||
* hardware will start executing it as soon as the
|
||||
* already-executing command terminates. (This minimises latency
|
||||
* and stalls.) With that in mind, this "busy" variable refers
|
||||
* to whether or not a command can be submitted, not whether or
|
||||
* not a previously-submitted command is still executing. In
|
||||
* other words, once proof is seen that the previously-submitted
|
||||
* command is executing, "vdq" is no longer "busy". TODO:
|
||||
* convert this to "atomic_t" so that it is thread-safe (without
|
||||
* locking). */
|
||||
int busy;
|
||||
uint32_t valid_bit; /* 0x00 or 0x80 */
|
||||
/* We need to determine when vdq is no longer busy. This depends
|
||||
* on whether the "busy" (last-submitted) dequeue command is
|
||||
* targetting DQRR or main-memory, and detected is based on the
|
||||
* presence of the dequeue command's "token" showing up in
|
||||
* dequeue entries in DQRR or main-memory (respectively). Debug
|
||||
* builds will, when submitting vdq commands, verify that the
|
||||
* dequeue result location is not already equal to the command's
|
||||
* token value. */
|
||||
struct ldpaa_dq *storage; /* NULL if DQRR */
|
||||
uint32_t token;
|
||||
} vdq;
|
||||
/* DQRR */
|
||||
struct {
|
||||
uint32_t next_idx;
|
||||
uint32_t valid_bit;
|
||||
} dqrr;
|
||||
};
|
||||
|
||||
/* -------------------------- */
|
||||
/* portal management commands */
|
||||
/* -------------------------- */
|
||||
|
||||
/* Different management commands all use this common base layer of code to issue
|
||||
* commands and poll for results. The first function returns a pointer to where
|
||||
* the caller should fill in their MC command (though they should ignore the
|
||||
* verb byte), the second function commits merges in the caller-supplied command
|
||||
* verb (which should not include the valid-bit) and submits the command to
|
||||
* hardware, and the third function checks for a completed response (returns
|
||||
* non-NULL if only if the response is complete). */
|
||||
void *qbman_swp_mc_start(struct qbman_swp *p);
|
||||
void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb);
|
||||
void *qbman_swp_mc_result(struct qbman_swp *p);
|
||||
|
||||
/* Wraps up submit + poll-for-result */
|
||||
static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
|
||||
uint32_t cmd_verb)
|
||||
{
|
||||
int loopvar;
|
||||
|
||||
qbman_swp_mc_submit(swp, cmd, cmd_verb);
|
||||
DBG_POLL_START(loopvar);
|
||||
do {
|
||||
DBG_POLL_CHECK(loopvar);
|
||||
cmd = qbman_swp_mc_result(swp);
|
||||
} while (!cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* ------------ */
|
||||
/* qb_attr_code */
|
||||
/* ------------ */
|
||||
|
||||
/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which
|
||||
* is either serving as a configuration command or a query result. The
|
||||
* representation is inherently little-endian, as the indexing of the words is
|
||||
* itself little-endian in nature and layerscape is little endian for anything
|
||||
* that crosses a word boundary too (64-bit fields are the obvious examples).
|
||||
*/
|
||||
struct qb_attr_code {
|
||||
unsigned int word; /* which uint32_t[] array member encodes the field */
|
||||
unsigned int lsoffset; /* encoding offset from ls-bit */
|
||||
unsigned int width; /* encoding width. (bool must be 1.) */
|
||||
};
|
||||
|
||||
/* Macros to define codes */
|
||||
#define QB_CODE(a, b, c) { a, b, c}
|
||||
|
||||
/* decode a field from a cacheline */
|
||||
static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code,
|
||||
const uint32_t *cacheline)
|
||||
{
|
||||
return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]);
|
||||
}
|
||||
|
||||
/* encode a field to a cacheline */
|
||||
static inline void qb_attr_code_encode(const struct qb_attr_code *code,
|
||||
uint32_t *cacheline, uint32_t val)
|
||||
{
|
||||
cacheline[code->word] =
|
||||
r32_uint32_t(code->lsoffset, code->width, cacheline[code->word])
|
||||
| e32_uint32_t(code->lsoffset, code->width, val);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
/* Descriptors/cachelines */
|
||||
/* ---------------------- */
|
||||
|
||||
/* To avoid needless dynamic allocation, the driver API often gives the caller
|
||||
* a "descriptor" type that the caller can instantiate however they like.
|
||||
* Ultimately though, it is just a cacheline of binary storage (or something
|
||||
* smaller when it is known that the descriptor doesn't need all 64 bytes) for
|
||||
* holding pre-formatted pieces of harware commands. The performance-critical
|
||||
* code can then copy these descriptors directly into hardware command
|
||||
* registers more efficiently than trying to construct/format commands
|
||||
* on-the-fly. The API user sees the descriptor as an array of 32-bit words in
|
||||
* order for the compiler to know its size, but the internal details are not
|
||||
* exposed. The following macro is used within the driver for converting *any*
|
||||
* descriptor pointer to a usable array pointer. The use of a macro (instead of
|
||||
* an inline) is necessary to work with different descriptor types and to work
|
||||
* correctly with const and non-const inputs (and similarly-qualified outputs).
|
||||
*/
|
||||
#define qb_cl(d) (&(d)->dont_manipulate_directly[0])
|
169
drivers/net/fsl-mc/dpio/qbman_private.h
Normal file
169
drivers/net/fsl-mc/dpio/qbman_private.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* Perform extra checking */
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/compat.h>
|
||||
#include <malloc.h>
|
||||
#include <fsl-mc/fsl_qbman_base.h>
|
||||
|
||||
#define QBMAN_CHECKING
|
||||
|
||||
/* Any time there is a register interface which we poll on, this provides a
|
||||
* "break after x iterations" scheme for it. It's handy for debugging, eg.
|
||||
* where you don't want millions of lines of log output from a polling loop
|
||||
* that won't, because such things tend to drown out the earlier log output
|
||||
* that might explain what caused the problem. (NB: put ";" after each macro!)
|
||||
* TODO: we should probably remove this once we're done sanitising the
|
||||
* simulator...
|
||||
*/
|
||||
#define DBG_POLL_START(loopvar) (loopvar = 10)
|
||||
#define DBG_POLL_CHECK(loopvar) \
|
||||
do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0)
|
||||
|
||||
/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets
|
||||
* and widths, these macro-generated encode/decode/isolate/remove inlines can
|
||||
* be used.
|
||||
*
|
||||
* Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type),
|
||||
* where the field is located 3 bits "up" from the least-significant bit of the
|
||||
* register (ie. the field location within the 32-bit register corresponds to a
|
||||
* mask of 0x0001fff8), you would do;
|
||||
* uint16_t field = d32_uint16_t(3, 14, reg_value);
|
||||
*
|
||||
* Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE,
|
||||
* non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!"
|
||||
* operator) into a register at bit location 0x00080000 (19 bits "in" from the
|
||||
* LS bit), do;
|
||||
* reg_value |= e32_int(19, 1, !!field);
|
||||
*
|
||||
* If you wish to read-modify-write a register, such that you leave the 14-bit
|
||||
* field as-is but have all other fields set to zero, then "i"solate the 14-bit
|
||||
* value using;
|
||||
* reg_value = i32_uint16_t(3, 14, reg_value);
|
||||
*
|
||||
* Alternatively, you could "r"emove the 1-bit boolean field (setting it to
|
||||
* zero) but leaving all other fields as-is;
|
||||
* reg_val = r32_int(19, 1, reg_value);
|
||||
*
|
||||
*/
|
||||
#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \
|
||||
(uint32_t)((1 << width) - 1))
|
||||
#define DECLARE_CODEC32(t) \
|
||||
static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \
|
||||
{ \
|
||||
BUG_ON(width > (sizeof(t) * 8)); \
|
||||
return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \
|
||||
} \
|
||||
static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \
|
||||
{ \
|
||||
BUG_ON(width > (sizeof(t) * 8)); \
|
||||
return (t)((val >> lsoffset) & MAKE_MASK32(width)); \
|
||||
} \
|
||||
static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \
|
||||
uint32_t val) \
|
||||
{ \
|
||||
BUG_ON(width > (sizeof(t) * 8)); \
|
||||
return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \
|
||||
} \
|
||||
static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \
|
||||
uint32_t val) \
|
||||
{ \
|
||||
BUG_ON(width > (sizeof(t) * 8)); \
|
||||
return ~(MAKE_MASK32(width) << lsoffset) & val; \
|
||||
}
|
||||
DECLARE_CODEC32(uint32_t)
|
||||
DECLARE_CODEC32(uint16_t)
|
||||
DECLARE_CODEC32(uint8_t)
|
||||
DECLARE_CODEC32(int)
|
||||
|
||||
/*********************/
|
||||
/* Debugging assists */
|
||||
/*********************/
|
||||
|
||||
static inline void __hexdump(unsigned long start, unsigned long end,
|
||||
unsigned long p, size_t sz, const unsigned char *c)
|
||||
{
|
||||
while (start < end) {
|
||||
unsigned int pos = 0;
|
||||
char buf[64];
|
||||
int nl = 0;
|
||||
|
||||
pos += sprintf(buf + pos, "%08lx: ", start);
|
||||
do {
|
||||
if ((start < p) || (start >= (p + sz)))
|
||||
pos += sprintf(buf + pos, "..");
|
||||
else
|
||||
pos += sprintf(buf + pos, "%02x", *(c++));
|
||||
if (!(++start & 15)) {
|
||||
buf[pos++] = '\n';
|
||||
nl = 1;
|
||||
} else {
|
||||
nl = 0;
|
||||
if (!(start & 1))
|
||||
buf[pos++] = ' ';
|
||||
if (!(start & 3))
|
||||
buf[pos++] = ' ';
|
||||
}
|
||||
} while (start & 15);
|
||||
if (!nl)
|
||||
buf[pos++] = '\n';
|
||||
buf[pos] = '\0';
|
||||
debug("%s", buf);
|
||||
}
|
||||
}
|
||||
static inline void hexdump(const void *ptr, size_t sz)
|
||||
{
|
||||
unsigned long p = (unsigned long)ptr;
|
||||
unsigned long start = p & ~(unsigned long)15;
|
||||
unsigned long end = (p + sz + 15) & ~(unsigned long)15;
|
||||
const unsigned char *c = ptr;
|
||||
|
||||
__hexdump(start, end, p, sz, c);
|
||||
}
|
||||
|
||||
#if defined(__BIG_ENDIAN)
|
||||
#define DQRR_TOK_OFFSET 0
|
||||
#else
|
||||
#define DQRR_TOK_OFFSET 24
|
||||
#endif
|
||||
|
||||
/* Similarly-named functions */
|
||||
#define upper32(a) upper_32_bits(a)
|
||||
#define lower32(a) lower_32_bits(a)
|
||||
|
||||
/****************/
|
||||
/* arch assists */
|
||||
/****************/
|
||||
|
||||
static inline void dcbz(void *ptr)
|
||||
{
|
||||
uint32_t *p = ptr;
|
||||
BUG_ON((unsigned long)ptr & 63);
|
||||
p[0] = 0;
|
||||
p[1] = 0;
|
||||
p[2] = 0;
|
||||
p[3] = 0;
|
||||
p[4] = 0;
|
||||
p[5] = 0;
|
||||
p[6] = 0;
|
||||
p[7] = 0;
|
||||
p[8] = 0;
|
||||
p[9] = 0;
|
||||
p[10] = 0;
|
||||
p[11] = 0;
|
||||
p[12] = 0;
|
||||
p[13] = 0;
|
||||
p[14] = 0;
|
||||
p[15] = 0;
|
||||
}
|
||||
|
||||
#define lwsync()
|
||||
|
||||
#include "qbman_sys.h"
|
290
drivers/net/fsl-mc/dpio/qbman_sys.h
Normal file
290
drivers/net/fsl-mc/dpio/qbman_sys.h
Normal file
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the
|
||||
* driver. They are only included via qbman_private.h, which is itself a
|
||||
* platform-independent file and is included by all the other driver source.
|
||||
*
|
||||
* qbman_sys_decl.h is included prior to all other declarations and logic, and
|
||||
* it exists to provide compatibility with any linux interfaces our
|
||||
* single-source driver code is dependent on (eg. kmalloc). Ie. this file
|
||||
* provides linux compatibility.
|
||||
*
|
||||
* This qbman_sys.h header, on the other hand, is included *after* any common
|
||||
* and platform-neutral declarations and logic in qbman_private.h, and exists to
|
||||
* implement any platform-specific logic of the qbman driver itself. Ie. it is
|
||||
* *not* to provide linux compatibility.
|
||||
*/
|
||||
|
||||
/* Trace the 3 different classes of read/write access to QBMan. #undef as
|
||||
* required. */
|
||||
#undef QBMAN_CCSR_TRACE
|
||||
#undef QBMAN_CINH_TRACE
|
||||
#undef QBMAN_CENA_TRACE
|
||||
|
||||
/* Temporarily define this to get around the fact that cache enabled mapping is
|
||||
* not working right now. Will remove this after uboot could map the cache
|
||||
* enabled portal memory.
|
||||
*/
|
||||
#define QBMAN_CINH_ONLY
|
||||
|
||||
static inline void word_copy(void *d, const void *s, unsigned int cnt)
|
||||
{
|
||||
uint32_t *dd = d;
|
||||
const uint32_t *ss = s;
|
||||
|
||||
while (cnt--)
|
||||
*(dd++) = *(ss++);
|
||||
}
|
||||
|
||||
/* Currently, the CENA support code expects each 32-bit word to be written in
|
||||
* host order, and these are converted to hardware (little-endian) order on
|
||||
* command submission. However, 64-bit quantities are must be written (and read)
|
||||
* as two 32-bit words with the least-significant word first, irrespective of
|
||||
* host endianness. */
|
||||
static inline void u64_to_le32_copy(void *d, const uint64_t *s,
|
||||
unsigned int cnt)
|
||||
{
|
||||
uint32_t *dd = d;
|
||||
const uint32_t *ss = (const uint32_t *)s;
|
||||
|
||||
while (cnt--) {
|
||||
/* TBD: the toolchain was choking on the use of 64-bit types up
|
||||
* until recently so this works entirely with 32-bit variables.
|
||||
* When 64-bit types become usable again, investigate better
|
||||
* ways of doing this. */
|
||||
#if defined(__BIG_ENDIAN)
|
||||
*(dd++) = ss[1];
|
||||
*(dd++) = ss[0];
|
||||
ss += 2;
|
||||
#else
|
||||
*(dd++) = *(ss++);
|
||||
*(dd++) = *(ss++);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
static inline void u64_from_le32_copy(uint64_t *d, const void *s,
|
||||
unsigned int cnt)
|
||||
{
|
||||
const uint32_t *ss = s;
|
||||
uint32_t *dd = (uint32_t *)d;
|
||||
|
||||
while (cnt--) {
|
||||
#if defined(__BIG_ENDIAN)
|
||||
dd[1] = *(ss++);
|
||||
dd[0] = *(ss++);
|
||||
dd += 2;
|
||||
#else
|
||||
*(dd++) = *(ss++);
|
||||
*(dd++) = *(ss++);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a host-native 32bit value into little endian */
|
||||
#if defined(__BIG_ENDIAN)
|
||||
static inline uint32_t make_le32(uint32_t val)
|
||||
{
|
||||
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
|
||||
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
|
||||
}
|
||||
#else
|
||||
#define make_le32(val) (val)
|
||||
#endif
|
||||
static inline void make_le32_n(uint32_t *val, unsigned int num)
|
||||
{
|
||||
while (num--) {
|
||||
*val = make_le32(*val);
|
||||
val++;
|
||||
}
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Portal access */
|
||||
/******************/
|
||||
struct qbman_swp_sys {
|
||||
/* On GPP, the sys support for qbman_swp is here. The CENA region isi
|
||||
* not an mmap() of the real portal registers, but an allocated
|
||||
* place-holder, because the actual writes/reads to/from the portal are
|
||||
* marshalled from these allocated areas using QBMan's "MC access
|
||||
* registers". CINH accesses are atomic so there's no need for a
|
||||
* place-holder. */
|
||||
void *cena;
|
||||
void __iomem *addr_cena;
|
||||
void __iomem *addr_cinh;
|
||||
};
|
||||
|
||||
/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal
|
||||
* C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH)
|
||||
* SWP_IDX is (ACCESS_CMD,16,10) - Software portal index
|
||||
* P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal)
|
||||
* T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE)
|
||||
* E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete)
|
||||
*/
|
||||
|
||||
static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset,
|
||||
uint32_t val)
|
||||
{
|
||||
__raw_writel(val, s->addr_cinh + offset);
|
||||
#ifdef QBMAN_CINH_TRACE
|
||||
pr_info("qbman_cinh_write(%p:0x%03x) 0x%08x\n",
|
||||
s->addr_cinh, offset, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset)
|
||||
{
|
||||
uint32_t reg = __raw_readl(s->addr_cinh + offset);
|
||||
|
||||
#ifdef QBMAN_CINH_TRACE
|
||||
pr_info("qbman_cinh_read(%p:0x%03x) 0x%08x\n",
|
||||
s->addr_cinh, offset, reg);
|
||||
#endif
|
||||
return reg;
|
||||
}
|
||||
|
||||
static inline void *qbman_cena_write_start(struct qbman_swp_sys *s,
|
||||
uint32_t offset)
|
||||
{
|
||||
void *shadow = s->cena + offset;
|
||||
|
||||
#ifdef QBMAN_CENA_TRACE
|
||||
pr_info("qbman_cena_write_start(%p:0x%03x) %p\n",
|
||||
s->addr_cena, offset, shadow);
|
||||
#endif
|
||||
BUG_ON(offset & 63);
|
||||
dcbz(shadow);
|
||||
return shadow;
|
||||
}
|
||||
|
||||
static inline void qbman_cena_write_complete(struct qbman_swp_sys *s,
|
||||
uint32_t offset, void *cmd)
|
||||
{
|
||||
const uint32_t *shadow = cmd;
|
||||
int loop;
|
||||
|
||||
#ifdef QBMAN_CENA_TRACE
|
||||
pr_info("qbman_cena_write_complete(%p:0x%03x) %p\n",
|
||||
s->addr_cena, offset, shadow);
|
||||
hexdump(cmd, 64);
|
||||
#endif
|
||||
for (loop = 15; loop >= 0; loop--)
|
||||
#ifdef QBMAN_CINH_ONLY
|
||||
__raw_writel(shadow[loop], s->addr_cinh +
|
||||
offset + loop * 4);
|
||||
#else
|
||||
__raw_writel(shadow[loop], s->addr_cena +
|
||||
offset + loop * 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset)
|
||||
{
|
||||
uint32_t *shadow = s->cena + offset;
|
||||
unsigned int loop;
|
||||
|
||||
#ifdef QBMAN_CENA_TRACE
|
||||
pr_info("qbman_cena_read(%p:0x%03x) %p\n",
|
||||
s->addr_cena, offset, shadow);
|
||||
#endif
|
||||
|
||||
for (loop = 0; loop < 16; loop++)
|
||||
#ifdef QBMAN_CINH_ONLY
|
||||
shadow[loop] = __raw_readl(s->addr_cinh + offset
|
||||
+ loop * 4);
|
||||
#else
|
||||
shadow[loop] = __raw_readl(s->addr_cena + offset
|
||||
+ loop * 4);
|
||||
#endif
|
||||
#ifdef QBMAN_CENA_TRACE
|
||||
hexdump(shadow, 64);
|
||||
#endif
|
||||
return shadow;
|
||||
}
|
||||
|
||||
static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s,
|
||||
uint32_t offset)
|
||||
{
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Portal support */
|
||||
/******************/
|
||||
|
||||
/* The SWP_CFG portal register is special, in that it is used by the
|
||||
* platform-specific code rather than the platform-independent code in
|
||||
* qbman_portal.c. So use of it is declared locally here. */
|
||||
#define QBMAN_CINH_SWP_CFG 0xd00
|
||||
|
||||
/* For MC portal use, we always configure with
|
||||
* DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4)
|
||||
* EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x0)
|
||||
* RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3)
|
||||
* DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2)
|
||||
* EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x3)
|
||||
* SD is (SWP_CFG,5,1) - memory stashing drop enable (<- FALSE)
|
||||
* SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE)
|
||||
* SE is (SWP_CFG,3,1) - memory stashing enable (<- 0x0)
|
||||
* DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE)
|
||||
* DE is (SWP_CFG,1,1) - dequeue stashing enable (<- 0x0)
|
||||
* EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- FALSE)
|
||||
*/
|
||||
static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn,
|
||||
uint8_t est, uint8_t rpm, uint8_t dcm,
|
||||
uint8_t epm, int sd, int sp, int se,
|
||||
int dp, int de, int ep)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = e32_uint8_t(20, 3, max_fill) | e32_uint8_t(16, 3, est) |
|
||||
e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) |
|
||||
e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) |
|
||||
e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) |
|
||||
e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn);
|
||||
return reg;
|
||||
}
|
||||
|
||||
static inline int qbman_swp_sys_init(struct qbman_swp_sys *s,
|
||||
const struct qbman_swp_desc *d)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
s->addr_cena = d->cena_bar;
|
||||
s->addr_cinh = d->cinh_bar;
|
||||
s->cena = (void *)valloc(CONFIG_SYS_PAGE_SIZE);
|
||||
memset((void *)s->cena, 0x00, CONFIG_SYS_PAGE_SIZE);
|
||||
if (!s->cena) {
|
||||
printf("Could not allocate page for cena shadow\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef QBMAN_CHECKING
|
||||
/* We should never be asked to initialise for a portal that isn't in
|
||||
* the power-on state. (Ie. don't forget to reset portals when they are
|
||||
* decommissioned!)
|
||||
*/
|
||||
reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
|
||||
BUG_ON(reg);
|
||||
#endif
|
||||
#ifdef QBMAN_CINH_ONLY
|
||||
reg = qbman_set_swp_cfg(4, 1, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
|
||||
#else
|
||||
reg = qbman_set_swp_cfg(4, 0, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
|
||||
#endif
|
||||
qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg);
|
||||
reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
|
||||
if (!reg) {
|
||||
printf("The portal is not enabled!\n");
|
||||
free(s->cena);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s)
|
||||
{
|
||||
free((void *)s->cena);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2014 Freescale Semiconductor Inc.
|
||||
/* Copyright 2013-2015 Freescale Semiconductor Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
@ -26,66 +26,3 @@ int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpmng_reset_aiop(struct fsl_mc_io *mc_io, int container_id,
|
||||
int aiop_tile_id)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_AIOP,
|
||||
MC_CMD_PRI_LOW, 0);
|
||||
DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpmng_load_aiop(struct fsl_mc_io *mc_io,
|
||||
int container_id,
|
||||
int aiop_tile_id,
|
||||
uint64_t img_iova,
|
||||
uint32_t img_size)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPMNG_CMDID_LOAD_AIOP,
|
||||
MC_CMD_PRI_LOW,
|
||||
0);
|
||||
DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size,
|
||||
img_iova);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpmng_run_aiop(struct fsl_mc_io *mc_io,
|
||||
int container_id,
|
||||
int aiop_tile_id,
|
||||
const struct dpmng_aiop_run_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RUN_AIOP,
|
||||
MC_CMD_PRI_LOW,
|
||||
0);
|
||||
DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpmng_reset_mc_portal(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_MC_PORTAL,
|
||||
MC_CMD_PRI_LOW,
|
||||
0);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
|
506
drivers/net/fsl-mc/dpni.c
Normal file
506
drivers/net/fsl-mc/dpni.c
Normal file
|
@ -0,0 +1,506 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <fsl-mc/fsl_mc_sys.h>
|
||||
#include <fsl-mc/fsl_mc_cmd.h>
|
||||
#include <fsl-mc/fsl_dpni.h>
|
||||
|
||||
int dpni_open(struct fsl_mc_io *mc_io, int dpni_id, uint16_t *token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
|
||||
MC_CMD_PRI_LOW, 0);
|
||||
DPNI_CMD_OPEN(cmd, dpni_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_close(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
|
||||
MC_CMD_PRI_HIGH, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_set_pools(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dpni_pools_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
DPNI_CMD_SET_POOLS(cmd, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_enable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_disable(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_reset(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_attributes(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_attr *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_ATTR(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dpni_buffer_layout *layout)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_qdid(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *qdid)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_QDID(cmd, *qdid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint16_t *data_offset)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_get_counter(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
enum dpni_counter counter,
|
||||
uint64_t *value)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_GET_COUNTER(cmd, counter);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_COUNTER(cmd, *value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_counter(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
enum dpni_counter counter,
|
||||
uint64_t value)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_COUNTER(cmd, counter, value);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_link_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_LINK_CFG(cmd, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_link_state(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dpni_link_state *state)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_LINK_STATE(cmd, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const uint8_t mac_addr[6])
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint8_t mac_addr[6])
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const uint8_t mac_addr[6])
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const uint8_t mac_addr[6])
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_set_tx_flow(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint16_t *flow_id,
|
||||
const struct dpni_tx_flow_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_SET_TX_FLOW(cmd, *flow_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_get_tx_flow(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint16_t flow_id,
|
||||
struct dpni_tx_flow_attr *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_GET_TX_FLOW(cmd, flow_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_TX_FLOW(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpni_set_rx_flow(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint8_t tc_id,
|
||||
uint16_t flow_id,
|
||||
const struct dpni_queue_cfg *cfg)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dpni_get_rx_flow(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
uint8_t tc_id,
|
||||
uint16_t flow_id,
|
||||
struct dpni_queue_attr *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPNI_RSP_GET_RX_FLOW(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
283
drivers/net/fsl-mc/dprc.c
Normal file
283
drivers/net/fsl-mc/dprc.c
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Freescale Layerscape MC I/O wrapper
|
||||
*
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
|
||||
* Author: German Rivera <German.Rivera@freescale.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <fsl-mc/fsl_mc_sys.h>
|
||||
#include <fsl-mc/fsl_mc_cmd.h>
|
||||
#include <fsl-mc/fsl_dprc.h>
|
||||
|
||||
int dprc_get_container_id(struct fsl_mc_io *mc_io, int *container_id)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
|
||||
MC_CMD_PRI_LOW, 0);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, MC_CMD_PRI_LOW,
|
||||
0);
|
||||
DPRC_CMD_OPEN(cmd, container_id);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_close(struct fsl_mc_io *mc_io, uint16_t token)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, MC_CMD_PRI_HIGH,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dprc_reset_container(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
int child_container_id)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPRC_CMD_RESET_CONTAINER(cmd, child_container_id);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dprc_get_attributes(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
struct dprc_attributes *attr)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_ATTRIBUTES(cmd, attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_get_obj(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
int obj_index,
|
||||
struct dprc_obj_desc *obj_desc)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
DPRC_CMD_GET_OBJ(cmd, obj_index);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_OBJ(cmd, obj_desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_get_res_count(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
char *type,
|
||||
int *res_count)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
*res_count = 0;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPRC_CMD_GET_RES_COUNT(cmd, type);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_RES_COUNT(cmd, *res_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_get_res_ids(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
char *type,
|
||||
struct dprc_res_ids_range_desc *range_desc)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPRC_CMD_GET_RES_IDS(cmd, range_desc, type);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_RES_IDS(cmd, range_desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_get_obj_region(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
char *obj_type,
|
||||
int obj_id,
|
||||
uint8_t region_index,
|
||||
struct dprc_region_desc *region_desc)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
|
||||
MC_CMD_PRI_LOW, token);
|
||||
DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_OBJ_REGION(cmd, region_desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_connect(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dprc_endpoint *endpoint1,
|
||||
const struct dprc_endpoint *endpoint2)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dprc_disconnect(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dprc_endpoint *endpoint)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
DPRC_CMD_DISCONNECT(cmd, endpoint);
|
||||
|
||||
/* send command to mc*/
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
int dprc_get_connection(struct fsl_mc_io *mc_io,
|
||||
uint16_t token,
|
||||
const struct dprc_endpoint *endpoint1,
|
||||
struct dprc_endpoint *endpoint2,
|
||||
int *state)
|
||||
{
|
||||
struct mc_command cmd = { 0 };
|
||||
int err;
|
||||
|
||||
/* prepare command */
|
||||
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
|
||||
MC_CMD_PRI_LOW,
|
||||
token);
|
||||
DPRC_CMD_GET_CONNECTION(cmd, endpoint1);
|
||||
|
||||
/* send command to mc*/
|
||||
err = mc_send_command(mc_io, &cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* retrieve response parameters */
|
||||
DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2014 Freescale Semiconductor Inc.
|
||||
/* Copyright 2013-2015 Freescale Semiconductor Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
@ -7,10 +7,6 @@
|
|||
|
||||
/* Command IDs */
|
||||
#define DPMNG_CMDID_GET_VERSION 0x831
|
||||
#define DPMNG_CMDID_RESET_AIOP 0x832
|
||||
#define DPMNG_CMDID_LOAD_AIOP 0x833
|
||||
#define DPMNG_CMDID_RUN_AIOP 0x834
|
||||
#define DPMNG_CMDID_RESET_MC_PORTAL 0x835
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \
|
||||
|
@ -20,30 +16,4 @@ do { \
|
|||
MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \
|
||||
} while (0)
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id) \
|
||||
do { \
|
||||
MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
|
||||
MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
|
||||
} while (0)
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, \
|
||||
img_iova) \
|
||||
do { \
|
||||
MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
|
||||
MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
|
||||
MC_CMD_OP(cmd, 1, 0, 32, uint32_t, img_size); \
|
||||
MC_CMD_OP(cmd, 2, 0, 64, uint64_t, img_iova); \
|
||||
} while (0)
|
||||
|
||||
/* cmd, param, offset, width, type, arg_name */
|
||||
#define DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg) \
|
||||
do { \
|
||||
MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \
|
||||
MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \
|
||||
MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cores_mask); \
|
||||
MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \
|
||||
} while (0)
|
||||
|
||||
#endif /* __FSL_DPMNG_CMD_H */
|
||||
|
|
|
@ -3,16 +3,75 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <fsl-mc/fsl_mc.h>
|
||||
#include <fsl-mc/fsl_mc_sys.h>
|
||||
#include <fsl-mc/fsl_mc_private.h>
|
||||
#include <fsl-mc/fsl_dpmng.h>
|
||||
#include <fsl_debug_server.h>
|
||||
#include <fsl-mc/fsl_dprc.h>
|
||||
#include <fsl-mc/fsl_dpio.h>
|
||||
#include <fsl-mc/fsl_qbman_portal.h>
|
||||
|
||||
#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024)
|
||||
#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
|
||||
#define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024)
|
||||
|
||||
#define MC_MEM_SIZE_ENV_VAR "mcmemsize"
|
||||
#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
static int mc_boot_status;
|
||||
struct fsl_mc_io *dflt_mc_io = NULL;
|
||||
uint16_t dflt_dprc_handle = 0;
|
||||
struct fsl_dpbp_obj *dflt_dpbp = NULL;
|
||||
struct fsl_dpio_obj *dflt_dpio = NULL;
|
||||
uint16_t dflt_dpio_handle = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump_ram_words(const char *title, void *addr)
|
||||
{
|
||||
int i;
|
||||
uint32_t *words = addr;
|
||||
|
||||
printf("Dumping beginning of %s (%p):\n", title, addr);
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%#x ", words[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs)
|
||||
{
|
||||
printf("MC CCSR registers:\n"
|
||||
"reg_gcr1 %#x\n"
|
||||
"reg_gsr %#x\n"
|
||||
"reg_sicbalr %#x\n"
|
||||
"reg_sicbahr %#x\n"
|
||||
"reg_sicapr %#x\n"
|
||||
"reg_mcfbalr %#x\n"
|
||||
"reg_mcfbahr %#x\n"
|
||||
"reg_mcfapr %#x\n"
|
||||
"reg_psr %#x\n",
|
||||
mc_ccsr_regs->reg_gcr1,
|
||||
mc_ccsr_regs->reg_gsr,
|
||||
mc_ccsr_regs->reg_sicbalr,
|
||||
mc_ccsr_regs->reg_sicbahr,
|
||||
mc_ccsr_regs->reg_sicapr,
|
||||
mc_ccsr_regs->reg_mcfbalr,
|
||||
mc_ccsr_regs->reg_mcfbahr,
|
||||
mc_ccsr_regs->reg_mcfapr,
|
||||
mc_ccsr_regs->reg_psr);
|
||||
}
|
||||
#else
|
||||
|
||||
#define dump_ram_words(title, addr)
|
||||
#define dump_mc_ccsr_regs(mc_ccsr_regs)
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
|
||||
/**
|
||||
* Copying MC firmware or DPL image to DDR
|
||||
*/
|
||||
|
@ -21,6 +80,7 @@ static int mc_copy_image(const char *title,
|
|||
{
|
||||
debug("%s copied to address %p\n", title, (void *)mc_ram_addr);
|
||||
memcpy((void *)mc_ram_addr, (void *)image_addr, image_size);
|
||||
flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -82,23 +142,254 @@ int parse_mc_firmware_fit_image(const void **raw_image_addr,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mc_init(bd_t *bis)
|
||||
/*
|
||||
* Calculates the values to be used to specify the address range
|
||||
* for the MC private DRAM block, in the MCFBALR/MCFBAHR registers.
|
||||
* It returns the highest 512MB-aligned address within the given
|
||||
* address range, in '*aligned_base_addr', and the number of 256 MiB
|
||||
* blocks in it, in 'num_256mb_blocks'.
|
||||
*/
|
||||
static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr,
|
||||
size_t mc_ram_size,
|
||||
u64 *aligned_base_addr,
|
||||
u8 *num_256mb_blocks)
|
||||
{
|
||||
u64 addr;
|
||||
u16 num_blocks;
|
||||
|
||||
if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) {
|
||||
printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
|
||||
mc_ram_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT;
|
||||
if (num_blocks < 1 || num_blocks > 0xff) {
|
||||
printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n",
|
||||
mc_ram_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = (mc_private_ram_start_addr + mc_ram_size - 1) &
|
||||
MC_RAM_BASE_ADDR_ALIGNMENT_MASK;
|
||||
|
||||
if (addr < mc_private_ram_start_addr) {
|
||||
printf("fsl-mc: ERROR: bad start address %#llx\n",
|
||||
mc_private_ram_start_addr);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*aligned_base_addr = addr;
|
||||
*num_256mb_blocks = num_blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size)
|
||||
{
|
||||
u64 mc_dpc_offset;
|
||||
#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR
|
||||
int error;
|
||||
void *dpc_fdt_hdr;
|
||||
int dpc_size;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET
|
||||
BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 ||
|
||||
CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff);
|
||||
|
||||
mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET;
|
||||
#else
|
||||
#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load the MC DPC blob in the MC private DRAM block:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR
|
||||
printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset);
|
||||
#else
|
||||
/*
|
||||
* Get address and size of the DPC blob stored in flash:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DPC_IN_NOR
|
||||
dpc_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPC_ADDR;
|
||||
#else
|
||||
#error "No CONFIG_SYS_LS_MC_DPC_IN_xxx defined"
|
||||
#endif
|
||||
|
||||
error = fdt_check_header(dpc_fdt_hdr);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* Don't return with error here, since the MC firmware can
|
||||
* still boot without a DPC
|
||||
*/
|
||||
printf("fsl-mc: WARNING: No DPC image found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dpc_size = fdt_totalsize(dpc_fdt_hdr);
|
||||
if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) {
|
||||
printf("fsl-mc: ERROR: Bad DPC image (too large: %d)\n",
|
||||
dpc_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mc_copy_image("MC DPC blob",
|
||||
(u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset);
|
||||
#endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */
|
||||
|
||||
dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size)
|
||||
{
|
||||
int error = 0;
|
||||
int timeout = 200000;
|
||||
struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
|
||||
u64 mc_ram_addr;
|
||||
u64 mc_dpl_offset;
|
||||
u32 reg_gsr;
|
||||
u32 mc_fw_boot_status;
|
||||
#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR
|
||||
int error;
|
||||
void *dpl_fdt_hdr;
|
||||
int dpl_size;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
|
||||
BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
|
||||
CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
|
||||
|
||||
mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
|
||||
#else
|
||||
#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load the MC DPL blob in the MC private DRAM block:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR
|
||||
printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset);
|
||||
#else
|
||||
/*
|
||||
* Get address and size of the DPL blob stored in flash:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
|
||||
dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
|
||||
#else
|
||||
#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
|
||||
#endif
|
||||
|
||||
error = fdt_check_header(dpl_fdt_hdr);
|
||||
if (error != 0) {
|
||||
printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
dpl_size = fdt_totalsize(dpl_fdt_hdr);
|
||||
if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
|
||||
printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
|
||||
dpl_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mc_copy_image("MC DPL blob",
|
||||
(u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
|
||||
#endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */
|
||||
|
||||
dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MC boot timeout value in milliseconds
|
||||
*/
|
||||
static unsigned long get_mc_boot_timeout_ms(void)
|
||||
{
|
||||
unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
|
||||
|
||||
char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR);
|
||||
|
||||
if (timeout_ms_env_var) {
|
||||
timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10);
|
||||
if (timeout_ms == 0) {
|
||||
printf("fsl-mc: WARNING: Invalid value for \'"
|
||||
MC_BOOT_TIMEOUT_ENV_VAR
|
||||
"\' environment variable: %lu\n",
|
||||
timeout_ms);
|
||||
|
||||
timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS;
|
||||
}
|
||||
}
|
||||
|
||||
return timeout_ms;
|
||||
}
|
||||
|
||||
static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr)
|
||||
{
|
||||
u32 reg_gsr;
|
||||
u32 mc_fw_boot_status;
|
||||
unsigned long timeout_ms = get_mc_boot_timeout_ms();
|
||||
struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
|
||||
|
||||
dmb();
|
||||
debug("Polling mc_ccsr_regs->reg_gsr ...\n");
|
||||
assert(timeout_ms > 0);
|
||||
for (;;) {
|
||||
udelay(1000); /* throttle polling */
|
||||
reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
|
||||
mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
|
||||
if (mc_fw_boot_status & 0x1)
|
||||
break;
|
||||
|
||||
timeout_ms--;
|
||||
if (timeout_ms == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout_ms == 0) {
|
||||
if (booting_mc)
|
||||
printf("fsl-mc: timeout booting management complex firmware\n");
|
||||
else
|
||||
printf("fsl-mc: timeout deploying data path layout\n");
|
||||
|
||||
/* TODO: Get an error status from an MC CCSR register */
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (mc_fw_boot_status != 0x1) {
|
||||
/*
|
||||
* TODO: Identify critical errors from the GSR register's FS
|
||||
* field and for those errors, set error to -ENODEV or other
|
||||
* appropriate errno, so that the status property is set to
|
||||
* failure in the fsl,dprc device tree node.
|
||||
*/
|
||||
if (booting_mc) {
|
||||
printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
|
||||
reg_gsr);
|
||||
} else {
|
||||
printf("fsl-mc: WARNING: Data path layout deployed with error (GSR: %#x)\n",
|
||||
reg_gsr);
|
||||
}
|
||||
}
|
||||
|
||||
*final_reg_gsr = reg_gsr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mc_init(void)
|
||||
{
|
||||
int error = 0;
|
||||
int portal_id = 0;
|
||||
struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR;
|
||||
u64 mc_ram_addr;
|
||||
u32 reg_gsr;
|
||||
u32 reg_mcfbalr;
|
||||
#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR
|
||||
const void *raw_image_addr;
|
||||
size_t raw_image_size = 0;
|
||||
struct fsl_mc_io mc_io;
|
||||
int portal_id;
|
||||
#endif
|
||||
struct mc_version mc_ver_info;
|
||||
u64 mc_ram_aligned_base_addr;
|
||||
u8 mc_ram_num_256mb_blocks;
|
||||
size_t mc_ram_size = mc_get_dram_block_size();
|
||||
|
||||
/*
|
||||
* The MC private DRAM block was already carved at the end of DRAM
|
||||
|
@ -112,6 +403,20 @@ int mc_init(bd_t *bis)
|
|||
gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_DEBUG_SERVER
|
||||
/*
|
||||
* FIXME: I don't think this is right. See get_dram_size_to_hide()
|
||||
*/
|
||||
mc_ram_addr -= debug_server_get_dram_block_size();
|
||||
#endif
|
||||
|
||||
error = calculate_mc_private_ram_params(mc_ram_addr,
|
||||
mc_ram_size,
|
||||
&mc_ram_aligned_base_addr,
|
||||
&mc_ram_num_256mb_blocks);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Management Complex cores should be held at reset out of POR.
|
||||
* U-boot should be the first software to touch MC. To be safe,
|
||||
|
@ -127,6 +432,9 @@ int mc_init(bd_t *bis)
|
|||
out_le32(&mc_ccsr_regs->reg_gcr1, 0);
|
||||
dmb();
|
||||
|
||||
#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR
|
||||
printf("MC firmware is preloaded to %#llx\n", mc_ram_addr);
|
||||
#else
|
||||
error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
@ -135,83 +443,34 @@ int mc_init(bd_t *bis)
|
|||
*/
|
||||
mc_copy_image("MC Firmware",
|
||||
(u64)raw_image_addr, raw_image_size, mc_ram_addr);
|
||||
|
||||
/*
|
||||
* Get address and size of the DPL blob stored in flash:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR
|
||||
dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR;
|
||||
#else
|
||||
#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined"
|
||||
#endif
|
||||
dump_ram_words("firmware", (void *)mc_ram_addr);
|
||||
|
||||
error = fdt_check_header(dpl_fdt_hdr);
|
||||
if (error != 0) {
|
||||
printf("fsl-mc: ERROR: Bad DPL image (bad header)\n");
|
||||
error = load_mc_dpc(mc_ram_addr, mc_ram_size);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dpl_size = fdt_totalsize(dpl_fdt_hdr);
|
||||
if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) {
|
||||
printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n",
|
||||
dpl_size);
|
||||
error = -EINVAL;
|
||||
error = load_mc_dpl(mc_ram_addr, mc_ram_size);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate offset in the MC private DRAM block at which the MC DPL
|
||||
* blob is to be placed:
|
||||
*/
|
||||
#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET
|
||||
BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 ||
|
||||
CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff);
|
||||
|
||||
mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET;
|
||||
#else
|
||||
mc_dpl_offset = mc_get_dram_block_size() -
|
||||
roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096);
|
||||
|
||||
if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) {
|
||||
printf("%s: Invalid MC DPL offset: %llu\n",
|
||||
__func__, mc_dpl_offset);
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load the MC DPL blob at the far end of the MC private DRAM block:
|
||||
*
|
||||
* TODO: Should we place the DPL at a different location to match
|
||||
* assumptions of MC firmware about its memory layout?
|
||||
*/
|
||||
mc_copy_image("MC DPL blob",
|
||||
(u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset);
|
||||
|
||||
debug("mc_ccsr_regs %p\n", mc_ccsr_regs);
|
||||
dump_mc_ccsr_regs(mc_ccsr_regs);
|
||||
|
||||
/*
|
||||
* Tell MC where the MC Firmware image was loaded in DDR:
|
||||
* Tell MC what is the address range of the DRAM block assigned to it:
|
||||
*/
|
||||
out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr);
|
||||
out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32));
|
||||
reg_mcfbalr = (u32)mc_ram_aligned_base_addr |
|
||||
(mc_ram_num_256mb_blocks - 1);
|
||||
out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr);
|
||||
out_le32(&mc_ccsr_regs->reg_mcfbahr,
|
||||
(u32)(mc_ram_aligned_base_addr >> 32));
|
||||
out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK);
|
||||
|
||||
/*
|
||||
* Tell MC where the DPL blob was loaded in DDR, by indicating
|
||||
* its offset relative to the beginning of the DDR block
|
||||
* allocated to the MC firmware. The MC firmware is responsible
|
||||
* for checking that there is no overlap between the DPL blob
|
||||
* and the runtime heap and stack of the MC firmware itself.
|
||||
*
|
||||
* NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of
|
||||
* the GSR MC CCSR register. So, this offset is assumed to be 4-byte
|
||||
* aligned.
|
||||
* Care must be taken not to write 1s into bits 31 and 30 of the GSR in
|
||||
* this case as the SoC COP or PIC will be signaled.
|
||||
* Tell the MC that we want delayed DPL deployment.
|
||||
*/
|
||||
out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2));
|
||||
out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00);
|
||||
|
||||
printf("\nfsl-mc: Booting Management Complex ...\n");
|
||||
|
||||
|
@ -219,38 +478,9 @@ int mc_init(bd_t *bis)
|
|||
* Deassert reset and release MC core 0 to run
|
||||
*/
|
||||
out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST);
|
||||
dmb();
|
||||
debug("Polling mc_ccsr_regs->reg_gsr ...\n");
|
||||
|
||||
for (;;) {
|
||||
reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr);
|
||||
mc_fw_boot_status = (reg_gsr & GSR_FS_MASK);
|
||||
if (mc_fw_boot_status & 0x1)
|
||||
break;
|
||||
|
||||
udelay(1000); /* throttle polling */
|
||||
if (timeout-- <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout <= 0) {
|
||||
printf("fsl-mc: timeout booting management complex firmware\n");
|
||||
|
||||
/* TODO: Get an error status from an MC CCSR register */
|
||||
error = -ETIMEDOUT;
|
||||
error = wait_for_mc(true, ®_gsr);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mc_fw_boot_status != 0x1) {
|
||||
/*
|
||||
* TODO: Identify critical errors from the GSR register's FS
|
||||
* field and for those errors, set error to -ENODEV or other
|
||||
* appropriate errno, so that the status property is set to
|
||||
* failure in the fsl,dprc device tree node.
|
||||
*/
|
||||
printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n",
|
||||
reg_gsr);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: need to obtain the portal_id for the root container from the
|
||||
|
@ -259,13 +489,20 @@ int mc_init(bd_t *bis)
|
|||
portal_id = 0;
|
||||
|
||||
/*
|
||||
* Check that the MC firmware is responding portal commands:
|
||||
* Initialize the global default MC portal
|
||||
* And check that the MC firmware is responding portal commands:
|
||||
*/
|
||||
mc_io.mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
|
||||
debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
|
||||
portal_id, mc_io.mmio_regs);
|
||||
dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io));
|
||||
if (!dflt_mc_io) {
|
||||
printf(" No memory: malloc() failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
error = mc_get_version(&mc_io, &mc_ver_info);
|
||||
dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id);
|
||||
debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n",
|
||||
portal_id, dflt_mc_io->mmio_regs);
|
||||
|
||||
error = mc_get_version(dflt_mc_io, &mc_ver_info);
|
||||
if (error != 0) {
|
||||
printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n",
|
||||
error);
|
||||
|
@ -282,7 +519,16 @@ int mc_init(bd_t *bis)
|
|||
|
||||
printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n",
|
||||
mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision,
|
||||
mc_fw_boot_status);
|
||||
reg_gsr & GSR_FS_MASK);
|
||||
|
||||
/*
|
||||
* Tell the MC to deploy the DPL:
|
||||
*/
|
||||
out_le32(&mc_ccsr_regs->reg_gsr, 0x0);
|
||||
printf("\nfsl-mc: Deploying data path layout ...\n");
|
||||
error = wait_for_mc(false, ®_gsr);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
out:
|
||||
if (error != 0)
|
||||
mc_boot_status = -error;
|
||||
|
@ -299,12 +545,242 @@ int get_mc_boot_status(void)
|
|||
|
||||
/**
|
||||
* Return the actual size of the MC private DRAM block.
|
||||
*
|
||||
* NOTE: For now this function always returns the minimum required size,
|
||||
* However, in the future, the actual size may be obtained from an environment
|
||||
* variable.
|
||||
*/
|
||||
unsigned long mc_get_dram_block_size(void)
|
||||
{
|
||||
return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
|
||||
unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
|
||||
|
||||
char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR);
|
||||
|
||||
if (dram_block_size_env_var) {
|
||||
dram_block_size = simple_strtoul(dram_block_size_env_var, NULL,
|
||||
10);
|
||||
|
||||
if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) {
|
||||
printf("fsl-mc: WARNING: Invalid value for \'"
|
||||
MC_MEM_SIZE_ENV_VAR
|
||||
"\' environment variable: %lu\n",
|
||||
dram_block_size);
|
||||
|
||||
dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return dram_block_size;
|
||||
}
|
||||
|
||||
int dpio_init(struct dprc_obj_desc obj_desc)
|
||||
{
|
||||
struct qbman_swp_desc p_des;
|
||||
struct dpio_attr attr;
|
||||
int err = 0;
|
||||
|
||||
dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj));
|
||||
if (!dflt_dpio) {
|
||||
printf(" No memory: malloc() failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dflt_dpio->dpio_id = obj_desc.id;
|
||||
|
||||
err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle);
|
||||
if (err) {
|
||||
printf("dpio_open() failed\n");
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr);
|
||||
if (err) {
|
||||
printf("dpio_get_attributes() failed %d\n", err);
|
||||
goto err_get_attr;
|
||||
}
|
||||
|
||||
err = dpio_enable(dflt_mc_io, dflt_dpio_handle);
|
||||
if (err) {
|
||||
printf("dpio_enable() failed %d\n", err);
|
||||
goto err_get_enable;
|
||||
}
|
||||
debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n",
|
||||
attr.qbman_portal_ce_paddr,
|
||||
attr.qbman_portal_ci_paddr,
|
||||
attr.qbman_portal_id,
|
||||
attr.num_priorities);
|
||||
|
||||
p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr;
|
||||
p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr;
|
||||
|
||||
dflt_dpio->sw_portal = qbman_swp_init(&p_des);
|
||||
if (dflt_dpio->sw_portal == NULL) {
|
||||
printf("qbman_swp_init() failed\n");
|
||||
goto err_get_swp_init;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_get_swp_init:
|
||||
err_get_enable:
|
||||
dpio_disable(dflt_mc_io, dflt_dpio_handle);
|
||||
err_get_attr:
|
||||
dpio_close(dflt_mc_io, dflt_dpio_handle);
|
||||
err_open:
|
||||
free(dflt_dpio);
|
||||
return err;
|
||||
}
|
||||
|
||||
int dpbp_init(struct dprc_obj_desc obj_desc)
|
||||
{
|
||||
dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj));
|
||||
if (!dflt_dpbp) {
|
||||
printf(" No memory: malloc() failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
dflt_dpbp->dpbp_attr.id = obj_desc.id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle)
|
||||
{
|
||||
int error = 0, state = 0;
|
||||
struct dprc_endpoint dpni_endpoint, dpmac_endpoint;
|
||||
if (!strcmp(obj_desc.type, "dpbp")) {
|
||||
if (!dflt_dpbp) {
|
||||
error = dpbp_init(obj_desc);
|
||||
if (error < 0)
|
||||
printf("dpbp_init failed\n");
|
||||
}
|
||||
} else if (!strcmp(obj_desc.type, "dpio")) {
|
||||
if (!dflt_dpio) {
|
||||
error = dpio_init(obj_desc);
|
||||
if (error < 0)
|
||||
printf("dpio_init failed\n");
|
||||
}
|
||||
} else if (!strcmp(obj_desc.type, "dpni")) {
|
||||
strcpy(dpni_endpoint.type, obj_desc.type);
|
||||
dpni_endpoint.id = obj_desc.id;
|
||||
error = dprc_get_connection(dflt_mc_io, dprc_handle,
|
||||
&dpni_endpoint, &dpmac_endpoint, &state);
|
||||
if (!strcmp(dpmac_endpoint.type, "dpmac"))
|
||||
error = ldpaa_eth_init(obj_desc);
|
||||
if (error < 0)
|
||||
printf("ldpaa_eth_init failed\n");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i)
|
||||
{
|
||||
int error = 0;
|
||||
struct dprc_obj_desc obj_desc;
|
||||
|
||||
memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc));
|
||||
|
||||
error = dprc_get_obj(dflt_mc_io, dprc_handle,
|
||||
i, &obj_desc);
|
||||
if (error < 0) {
|
||||
printf("dprc_get_obj(i=%d) failed: %d\n",
|
||||
i, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!strcmp(obj_desc.type, obj_type)) {
|
||||
debug("Discovered object: type %s, id %d, req %s\n",
|
||||
obj_desc.type, obj_desc.id, obj_type);
|
||||
|
||||
error = dprc_init_container_obj(obj_desc, dprc_handle);
|
||||
if (error < 0) {
|
||||
printf("dprc_init_container_obj(i=%d) failed: %d\n",
|
||||
i, error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int fsl_mc_ldpaa_init(bd_t *bis)
|
||||
{
|
||||
int i, error = 0;
|
||||
int dprc_opened = 0, container_id;
|
||||
int num_child_objects = 0;
|
||||
|
||||
error = mc_init();
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
||||
error = dprc_get_container_id(dflt_mc_io, &container_id);
|
||||
if (error < 0) {
|
||||
printf("dprc_get_container_id() failed: %d\n", error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
debug("fsl-mc: Container id=0x%x\n", container_id);
|
||||
|
||||
error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle);
|
||||
if (error < 0) {
|
||||
printf("dprc_open() failed: %d\n", error);
|
||||
goto error;
|
||||
}
|
||||
dprc_opened = true;
|
||||
|
||||
error = dprc_get_obj_count(dflt_mc_io,
|
||||
dflt_dprc_handle,
|
||||
&num_child_objects);
|
||||
if (error < 0) {
|
||||
printf("dprc_get_obj_count() failed: %d\n", error);
|
||||
goto error;
|
||||
}
|
||||
debug("Total child in container %d = %d\n", container_id,
|
||||
num_child_objects);
|
||||
|
||||
if (num_child_objects != 0) {
|
||||
/*
|
||||
* Discover objects currently in the DPRC container in the MC:
|
||||
*/
|
||||
for (i = 0; i < num_child_objects; i++)
|
||||
error = dprc_scan_container_obj(dflt_dprc_handle,
|
||||
"dpbp", i);
|
||||
|
||||
for (i = 0; i < num_child_objects; i++)
|
||||
error = dprc_scan_container_obj(dflt_dprc_handle,
|
||||
"dpio", i);
|
||||
|
||||
for (i = 0; i < num_child_objects; i++)
|
||||
error = dprc_scan_container_obj(dflt_dprc_handle,
|
||||
"dpni", i);
|
||||
}
|
||||
error:
|
||||
if (dprc_opened)
|
||||
dprc_close(dflt_mc_io, dflt_dprc_handle);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void fsl_mc_ldpaa_exit(bd_t *bis)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (get_mc_boot_status() == 0) {
|
||||
err = dpio_disable(dflt_mc_io, dflt_dpio_handle);
|
||||
if (err < 0) {
|
||||
printf("dpio_disable() failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
err = dpio_reset(dflt_mc_io, dflt_dpio_handle);
|
||||
if (err < 0) {
|
||||
printf("dpio_reset() failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
err = dpio_close(dflt_mc_io, dflt_dpio_handle);
|
||||
if (err < 0) {
|
||||
printf("dpio_close() failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
free(dflt_dpio);
|
||||
free(dflt_dpbp);
|
||||
}
|
||||
|
||||
if (dflt_mc_io)
|
||||
free(dflt_mc_io);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Freescale Layerscape MC I/O wrapper
|
||||
*
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
|
||||
* Author: German Rivera <German.Rivera@freescale.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
|
@ -32,7 +32,7 @@ int mc_send_command(struct fsl_mc_io *mc_io,
|
|||
struct mc_command *cmd)
|
||||
{
|
||||
enum mc_cmd_status status;
|
||||
int timeout = 2000;
|
||||
int timeout = 6000;
|
||||
|
||||
mc_write_command(mc_io->mmio_regs, cmd);
|
||||
|
||||
|
@ -52,7 +52,7 @@ int mc_send_command(struct fsl_mc_io *mc_io,
|
|||
if (status != MC_CMD_STATUS_OK) {
|
||||
printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
|
||||
mc_io->mmio_regs,
|
||||
(unsigned int)MC_CMD_HDR_READ_AUTHID(cmd->header),
|
||||
(unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
|
||||
(unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
|
||||
(unsigned int)status);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue