Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
U
uboot-imx
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Eric Kuzmenko
uboot-imx
Commits
659ea493
Commit
659ea493
authored
Dec 28, 2018
by
Angus Ainslie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
imx8m_som/ddr : Add an option to use the M4 code to load the DDR training firmware
parent
f5f73bb2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
349 additions
and
1 deletion
+349
-1
board/emcraft/imx8m_som/Kconfig
board/emcraft/imx8m_som/Kconfig
+3
-0
board/emcraft/imx8m_som/ddr/lpddr4/helper.c
board/emcraft/imx8m_som/ddr/lpddr4/helper.c
+346
-1
No files found.
board/emcraft/imx8m_som/Kconfig
View file @
659ea493
...
...
@@ -6,3 +6,6 @@ config SYS_VENDOR
config SYS_CONFIG_NAME
default "imx8m_som"
config M4_LOAD_DDR_TRAINING
bool "Use the M4 to load the DDR training firmware"
board/emcraft/imx8m_som/ddr/lpddr4/helper.c
View file @
659ea493
...
...
@@ -6,26 +6,66 @@
#include <common.h>
#include <spl.h>
#include <mmc.h>
#include <blk.h>
#include <asm/io.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
#include <asm/arch/clock.h>
#include <asm/sections.h>
#include <asm/arch/sys_proto.h>
#include <fsl_wdog.h>
#include "ddr.h"
DECLARE_GLOBAL_DATA_PTR
;
#define OCRAM_BASE 0x900000
#define OCRAM_SIZE (128*1024)
#define TCML_BASE 0x7e0000
#define TCMU_BASE 0x800000
#define TCMU_SIZE 0x20000
#define TCMU_CMD_M4 (TCMU_BASE + TCMU_SIZE - 24)
/* command mailbox */
#define TCMU_ARG_M4 (TCMU_BASE + TCMU_SIZE - 20)
/* arg mailbox */
#define TCMU_ST_M4 (TCMU_BASE + TCMU_SIZE - 16)
/* status mailbox */
#define TCMU_CMD_A53 (TCMU_BASE + TCMU_SIZE - 12)
/* command mailbox */
#define TCMU_ARG_A53 (TCMU_BASE + TCMU_SIZE - 8)
/* arg mailbox */
#define TCMU_ST_A53 (TCMU_BASE + TCMU_SIZE - 4)
/* status mailbox */
#define CMD_NONE 0
#define CMD_READY 1
#define CMD_WRITE_FW 2
#define ST_NONE 0
#define ST_READY 1
#define ST_FAIL 2
#define ST_SUCCESS 3
#define ST_BUSY 4
#define ST_EXCEPT 5
#define IMEM_LEN 32768//23400 //byte
#define DMEM_LEN 16384//1720 //byte
#define IMEM_2D_OFFSET 49152
#define FIRMWARE_BASE (OCRAM_BASE + OCRAM_SIZE / 2)
#define IMEM_OFFSET_ADDR 0x00050000
#define DMEM_OFFSET_ADDR 0x00054000
#define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
struct
aipstz_regs
{
u32
mprot0
;
u32
mprot1
;
u32
rsvd
[
0xe
];
u32
opacr0
;
u32
opacr1
;
u32
opacr2
;
u32
opacr3
;
u32
opacr4
;
};
/* We need PHY iMEM PHY is 32KB padded */
void
ddr_load_train_code
(
enum
fw_type
type
)
void
old_
ddr_load_train_code
(
enum
fw_type
type
)
{
u32
tmp32
,
i
;
u32
error
=
0
;
...
...
@@ -58,6 +98,7 @@ void ddr_load_train_code(enum fw_type type)
i
+=
4
;
}
printf
(
"check ddr4_pmu_train_imem code
\n
"
);
pr_from32
=
imem_start
;
pr_to32
=
DDR_TRAIN_CODE_BASE_ADDR
+
4
*
IMEM_OFFSET_ADDR
;
for
(
i
=
0x0
;
i
<
IMEM_LEN
;){
...
...
@@ -75,8 +116,11 @@ void ddr_load_train_code(enum fw_type type)
}
if
(
error
){
printf
(
"check ddr4_pmu_train_imem code fail=%d
\n
"
,
error
);
}
else
{
printf
(
"check ddr4_pmu_train_imem code pass
\n
"
);
}
printf
(
"check ddr4_pmu_train_dmem code
\n
"
);
pr_from32
=
dmem_start
;
pr_to32
=
DDR_TRAIN_CODE_BASE_ADDR
+
4
*
DMEM_OFFSET_ADDR
;
for
(
i
=
0x0
;
i
<
DMEM_LEN
;){
...
...
@@ -94,5 +138,306 @@ void ddr_load_train_code(enum fw_type type)
if
(
error
){
printf
(
"check ddr4_pmu_train_dmem code fail=%d"
,
error
);
}
else
{
printf
(
"check ddr4_pmu_train_dmem code pass
\n
"
);
}
}
void
load_train_code_tcmu
(
enum
fw_type
type
)
{
u32
tmp32
,
i
;
unsigned
long
pr_to32
,
pr_from32
;
unsigned
long
fw_offset
=
type
?
IMEM_2D_OFFSET
:
0
;
unsigned
long
imem_start
=
(
unsigned
long
)
&
_end
+
fw_offset
;
unsigned
long
dmem_start
=
imem_start
+
IMEM_LEN
;
printf
(
"copying ddr4_pmu_train_imem code
\n
"
);
pr_from32
=
imem_start
;
pr_to32
=
FIRMWARE_BASE
;
for
(
i
=
0x0
;
i
<
IMEM_LEN
;
){
tmp32
=
readl
(
pr_from32
);
writel
(
tmp32
,
pr_to32
);
pr_to32
+=
4
;
pr_from32
+=
4
;
i
+=
4
;
}
printf
(
"copying ddr4_pmu_train_dmem code
\n
"
);
pr_from32
=
dmem_start
;
pr_to32
=
FIRMWARE_BASE
+
IMEM_LEN
;
for
(
i
=
0x0
;
i
<
DMEM_LEN
;){
tmp32
=
readl
(
pr_from32
);
writel
(
tmp32
,
pr_to32
);
pr_to32
+=
4
;
pr_from32
+=
4
;
i
+=
4
;
}
}
extern
int
spl_mmc_find_device
(
struct
mmc
**
mmcp
,
u32
boot_device
);
int
is_mx8
(
void
)
{
return
1
;
}
void
init_aips
(
void
)
{
struct
aipstz_regs
*
aips
[
4
];
int
num_aips
=
2
,
i
;
aips
[
0
]
=
(
struct
aipstz_regs
*
)
AIPS1_BASE_ADDR
;
aips
[
1
]
=
(
struct
aipstz_regs
*
)
AIPS2_BASE_ADDR
;
aips
[
2
]
=
(
struct
aipstz_regs
*
)
AIPS3_BASE_ADDR
;
aips
[
3
]
=
(
struct
aipstz_regs
*
)
AIPS4_BASE_ADDR
;
if
(
is_mx6ull
()
||
is_mx6sx
()
||
is_mx7
())
num_aips
=
3
;
if
(
is_mx8
())
num_aips
=
4
;
for
(
i
=
0
;
i
<
num_aips
;
i
++
)
{
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
* not forced to user-mode.
*/
writel
(
0x77770700
,
&
aips
[
i
]
->
mprot0
);
//writel(0x77777777, &aips[i]->mprot1);
/*
* Set all OPACRx to be non-bufferable, not require
* supervisor privilege level for access,allow for
* write access and untrusted master access.
*/
writel
(
0x00000000
,
&
aips
[
i
]
->
opacr0
);
writel
(
0x00000000
,
&
aips
[
i
]
->
opacr1
);
writel
(
0x00000000
,
&
aips
[
i
]
->
opacr2
);
writel
(
0x00000000
,
&
aips
[
i
]
->
opacr3
);
writel
(
0x00000000
,
&
aips
[
i
]
->
opacr4
);
}
}
#define SRC_M4RCR 0x3039000C
void
M4_load_firmware
(
enum
fw_type
type
)
{
#if defined(CONFIG_M4_LOAD_DDR_TRAINING)
uint32_t
status
;
printf
(
"Set A53 ready
\n
"
);
writel
(
CMD_READY
,
TCMU_CMD_A53
);
printf
(
"Wait for M4 cmd finished
\n
"
);
status
=
readl
(
TCMU_ST_M4
);
while
(
status
!=
ST_FAIL
&&
status
!=
ST_SUCCESS
)
{
status
=
readl
(
TCMU_ST_M4
);
/*if(status == ST_EXCEPT)
{
printf( "M4 Exception : %d\n", readl(TCMU_CMD_M4));
return;
}*/
}
printf
(
"Clear A53 command
\n
"
);
writel
(
0
,
TCMU_CMD_A53
);
while
(
status
!=
ST_READY
)
status
=
readl
(
TCMU_ST_M4
);
printf
(
"Cortex M4 synchronized
\n
"
);
load_train_code_tcmu
(
type
);
writel
(
type
,
TCMU_ARG_A53
);
writel
(
0
,
TCMU_ST_A53
);
printf
(
"Cmd write firmware
\n
"
);
writel
(
CMD_WRITE_FW
,
TCMU_CMD_A53
);
status
=
readl
(
TCMU_ST_M4
);
printf
(
"Wait for M4 to complete
\n
"
);
while
(
status
!=
ST_FAIL
&&
status
!=
ST_SUCCESS
)
{
status
=
readl
(
TCMU_ST_M4
);
/*if(status == ST_EXCEPT)
{
printf( "M4 Exception : %d\n", readl(TCMU_CMD_M4));
return;
}*/
}
/*
printf("ddr trainging code loaded - type 0x%x\n", type);
writel(0, TCMU_CMD_A53);
while(status != ST_READY)
status = readl(TCMU_ST_M4);
*/
#endif
}
void
start_M4
(
void
)
{
struct
mmc
*
mmc
;
struct
blk_desc
*
block_dev
;
void
*
vect_buffer
=
(
void
*
)
TCML_BASE
;
void
*
buffer
=
(
void
*
)
OCRAM_BASE
;
uint32_t
status
,
reg
,
stack
,
pc
;
int
err
,
count
;
int
boot_device
;
#if 0
/* use this wait to stop the code for the OpenOCD debugger */
volatile int i = 0;
printf("busy wait");
while( i==0 );
#endif
printf
(
"Setting up AIPS
\n
"
);
init_aips
();
printf
(
"Finding MMC device
\n
"
);
boot_device
=
spl_boot_device
();
if
(
0
==
(
err
=
spl_mmc_find_device
(
&
mmc
,
boot_device
)))
{
err
=
mmc_init
(
mmc
);
if
(
err
)
{
printf
(
"spl: mmc init failed with error: %d
\n
"
,
err
);
}
else
{
printf
(
"Disabling Cortex M4 clock
\n
"
);
clock_enable
(
CCGR_M4
,
0
);
printf
(
"Getting block device
\n
"
);
block_dev
=
mmc_get_blk_desc
(
mmc
);
printf
(
"Loading Cortex M4 firmware loader
\n
"
);
/* From 2k copy - blocks are 512 bytes each */
blk_dread
(
block_dev
,
4
,
64
,
buffer
);
printf
(
"Loading Cortex M4 exception vectors
\n
"
);
blk_dread
(
block_dev
,
4
,
1
,
vect_buffer
);
printf
(
"Starting Cortex M4 core
\n
"
);
stack
=
*
(
u32
*
)
buffer
;
pc
=
*
(
u32
*
)(
buffer
+
4
);
/* Set the stack and pc to M4 bootROM */
writel
(
stack
,
M4_BOOTROM_BASE_ADDR
);
writel
(
pc
,
M4_BOOTROM_BASE_ADDR
+
4
);
printf
(
"Enabling Cortex M4 clock
\n
"
);
clock_enable
(
CCGR_M4
,
1
);
printf
(
"reset M4 core
\n
"
);
reg
=
readl
(
SRC_M4RCR
);
writel
((
reg
&
~
0xF
)
|
0xa
,
SRC_M4RCR
);
status
=
readl
(
TCMU_ST_M4
);
for
(
count
=
0
;
count
<
50000
;
count
++
)
{
status
=
readl
(
TCMU_ST_M4
);
if
(
status
==
ST_READY
)
break
;
udelay
(
10
);
}
if
(
status
==
ST_READY
)
{
printf
(
"Cortex M4 ready
\n
"
);
}
else
{
printf
(
"Cortex M4 NOT ready
\n
"
);
}
}
}
else
{
printf
(
"spl: mmc find device failed with error: %d
\n
"
,
err
);
}
}
void
ddr_load_train_code
(
enum
fw_type
type
)
{
struct
mmc
*
mmc
;
struct
blk_desc
*
block_dev
;
void
*
vect_buffer
=
(
void
*
)
TCML_BASE
;
void
*
buffer
=
(
void
*
)
OCRAM_BASE
;
uint32_t
status
,
reg
,
stack
,
pc
;
int
err
,
count
;
int
boot_device
;
#if defined(CONFIG_M4_LOAD_DDR_TRAINING)
printf
(
"Finding MMC device
\n
"
);
boot_device
=
spl_boot_device
();
if
(
0
==
(
err
=
spl_mmc_find_device
(
&
mmc
,
boot_device
)))
{
err
=
mmc_init
(
mmc
);
if
(
err
)
{
printf
(
"spl: mmc init failed with error: %d
\n
"
,
err
);
}
else
{
printf
(
"Disabling Cortex M4 clock
\n
"
);
clock_enable
(
CCGR_M4
,
0
);
printf
(
"Getting block device
\n
"
);
block_dev
=
mmc_get_blk_desc
(
mmc
);
printf
(
"Loading Cortex M4 firmware loader
\n
"
);
/* From 2k copy - blocks are 512 bytes each */
blk_dread
(
block_dev
,
4
,
64
,
buffer
);
printf
(
"Loading Cortex M4 exception vectors
\n
"
);
blk_dread
(
block_dev
,
4
,
1
,
vect_buffer
);
printf
(
"Starting Cortex M4 core
\n
"
);
stack
=
*
(
u32
*
)
buffer
;
pc
=
*
(
u32
*
)(
buffer
+
4
);
/* Set the stack and pc to M4 bootROM */
writel
(
stack
,
M4_BOOTROM_BASE_ADDR
);
writel
(
pc
,
M4_BOOTROM_BASE_ADDR
+
4
);
printf
(
"Enabling Cortex M4 clock
\n
"
);
clock_enable
(
CCGR_M4
,
1
);
printf
(
"reset M4 core
\n
"
);
reg
=
readl
(
SRC_M4RCR
);
writel
((
reg
&
~
0xF
)
|
0xa
,
SRC_M4RCR
);
status
=
readl
(
TCMU_ST_M4
);
for
(
count
=
0
;
count
<
50000
;
count
++
)
{
status
=
readl
(
TCMU_ST_M4
);
if
(
status
==
ST_READY
)
break
;
udelay
(
10
);
}
if
(
status
==
ST_READY
)
{
printf
(
"Cortex M4 ready
\n
"
);
}
else
{
printf
(
"Cortex M4 NOT ready
\n
"
);
}
//if( boot_M4() == ST_READY )
M4_load_firmware
(
type
);
}
}
else
{
printf
(
"spl: mmc find device failed with error: %d
\n
"
,
err
);
}
#else
old_ddr_load_train_code
(
type
);
#endif
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment