Skip to contentSkip to conversation

arm: socfpga: fix issue with warm reset when CSEL is 0

PATCH Superseded Dalon Westergreen 2 participants 2 messages Feb 14, 2017

Subsystems (3)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 arm: socfpga: fix issue with warm reset when CSEL is 0

When CSEL=0x0 the socfpga bootrom does not touch the clock configuration for the device. This can lead to a boot failure on warm resets. To address this, the bootrom is configured to run a bit of code in the last 4KB of onchip ram on a warm reset. This code puts the PLLs in bypass, disables the bootrom configuration to run the code snippet, and issues a warm reset to run the bootrom.

---
 arch/arm/mach-socfpga/Makefile                     |  2 +-
 arch/arm/mach-socfpga/include/mach/clock_manager.h | 22 ++++++-
 arch/arm/mach-socfpga/include/mach/reset_manager.h |  4 ++
 .../arm/mach-socfpga/include/mach/system_manager.h |  7 ++-
 arch/arm/mach-socfpga/misc.c                       | 29 +++++++++
 arch/arm/mach-socfpga/reset_clock_manager.S        | 71 ++++++++++++++++++++++
 6 files changed, 132 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-socfpga/reset_clock_manager.S
arch/arm/mach-socfpga/Makefile +1 -1
index 809cd47..6876ccf 100644
@@ -8,7 +8,7 @@
 #
 
 obj-y	+= misc.o timer.o reset_manager.o system_manager.o clock_manager.o \
-	   fpga_manager.o board.o
+	   fpga_manager.o board.o reset_clock_manager.o
 
 obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o
 
arch/arm/mach-socfpga/include/mach/clock_manager.h +21 -1
index 803c926..dd58c20 100644
@@ -21,7 +21,6 @@ const unsigned int cm_get_f2s_sdr_ref_clk_hz(void);
 
 /* Clock configuration accessors */
 const struct cm_config * const cm_get_default_config(void);
-#endif
 
 struct cm_config {
 	/* main group */
@@ -127,6 +126,19 @@ struct socfpga_clock_manager {
 	struct socfpga_clock_manager_altera altera;
 	u32	_pad_0xe8_0x200[70];
 };
+#endif
+
+#define CLKMGR_CTRL_ADDRESS 0x0
+#define CLKMGR_BYPASS_ADDRESS 0x4
+#define CLKMGR_INTER_ADDRESS 0x8
+#define CLKMGR_INTREN_ADDRESS 0xc
+#define CLKMGR_DBCTRL_ADDRESS 0x10 
+#define CLKMGR_STAT_ADDRESS 0x14
+#define CLKMGR_MAINPLLGRP_MAINQSPICLK_ADDRESS 0x54                              
+#define CLKMGR_MAINPLLGRP_MAINNANDSDMMCCLK_ADDRESS 0x58                         
+#define CLKMGR_PERPLLGRP_PERQSPICLK_ADDRESS 0x90                                
+#define CLKMGR_PERPLLGRP_PERNANDSDMMCCLK_ADDRESS 0x94
+
 
 #define CLKMGR_CTRL_SAFEMODE				(1 << 0)
 #define CLKMGR_CTRL_SAFEMODE_OFFSET			0
@@ -314,4 +326,12 @@ struct socfpga_clock_manager {
 #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_OFFSET	9
 #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK		0x00000e00
 
+/* Bypass Main and Per PLL, bypass source per input mux */                      
+#define CLKMGR_BYPASS_MAIN_PER_PLL_MASK         0x19                            
+                                                                                
+#define CLKMGR_MAINQSPICLK_RESET_VALUE          0x3                             
+#define CLKMGR_MAINNANDSDMMCCLK_RESET_VALUE     0x3                             
+#define CLKMGR_PERQSPICLK_RESET_VALUE           0x1                             
+#define CLKMGR_PERNANDSDMMCCLK_RESET_VALUE      0x1  
+
 #endif /* _CLOCK_MANAGER_H_ */
arch/arm/mach-socfpga/include/mach/reset_manager.h +4 -0
index 2f070f2..58d77fb 100644
@@ -7,6 +7,7 @@
 #ifndef	_RESET_MANAGER_H_
 #define	_RESET_MANAGER_H_
 
+#ifndef __ASSEMBLY__
 void reset_cpu(ulong addr);
 void reset_deassert_peripherals_handoff(void);
 
@@ -28,6 +29,8 @@ struct socfpga_reset_manager {
 	u32	padding2[12];
 	u32	tstscratch;
 };
+#endif
+
 
 #if defined(CONFIG_SOCFPGA_VIRTUAL_TARGET)
 #define RSTMGR_CTRL_SWWARMRSTREQ_LSB 2
@@ -40,6 +43,7 @@ struct socfpga_reset_manager {
  * and reset ID can be extracted using the subsequent macros
  * RSTMGR_RESET() and RSTMGR_BANK().
  */
+#define RSTMGR_CTRL_OFFSET	4
 #define RSTMGR_BANK_OFFSET	8
 #define RSTMGR_BANK_MASK	0x7
 #define RSTMGR_RESET_OFFSET	0
arch/arm/mach-socfpga/include/mach/system_manager.h +6 -1
index c45edea..d04fa2f 100644
@@ -13,7 +13,6 @@ void sysmgr_pinmux_init(void);
 void sysmgr_config_warmrstcfgio(int enable);
 
 void sysmgr_get_pinmux_table(const u8 **table, unsigned int *table_len);
-#endif
 
 struct socfpga_system_manager {
 	/* System Manager Module */
@@ -115,6 +114,12 @@ struct socfpga_system_manager {
 	u32	_pad_0x734;
 	u32	spim0usefpga;			/* 0x738 */
 };
+#endif
+
+#define CONFIG_SYSMGR_WARMRAMGRP_ENABLE		(SOCFPGA_SYSMGR_ADDRESS + 0xe0)
+
+#define SYSMGR_BOOTINFO_CSEL_MASK	0x18
+#define SYSMGR_BOOTINFO_CSEL_LSB 	3
 
 #define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGPINMUX	(1 << 0)
 #define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGIO	(1 << 1)
arch/arm/mach-socfpga/misc.c +29 -0
index dd6b53b..4d41420 100644
@@ -22,6 +22,9 @@
 
 #include <dt-bindings/reset/altr,rst-mgr.h>
 
+void reset_clock_manager(void);                                                 
+extern unsigned reset_clock_manager_size;
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct pl310_regs *const pl310 =
@@ -356,6 +359,32 @@ static uint32_t iswgrp_handoff[8];
 int arch_early_init_r(void)
 {
 	int i;
+	unsigned csel, ramboot_addr;
+
+	/* Check the CSEL value */
+	csel = (readl(&sysmgr_regs->bootinfo) & SYSMGR_BOOTINFO_CSEL_MASK) >>
+		SYSMGR_BOOTINFO_CSEL_LSB;
+
+	/*
+	 * For CSEL = 0 the bootrom does not configure the clocks which can
+	 * result in a boot failure on warm resets.  To remedy this a small 
+	 * bit of code is placed at the end of the onchip ram and run on
+	 * a warm reset.  It puts the PLLs in bypass and issues another warm
+	 * reset to get back to the bootrom.
+	 */
+	if(!csel) {
+		/* Put the code snippet in the last 4KB of the onchip ram */
+		ramboot_addr = CONFIG_SYS_INIT_RAM_ADDR + 
+			CONFIG_SYS_INIT_RAM_SIZE - 0x1000;
+
+		/* Copy the code to the onchip ramlocation */
+		memcpy((void *)ramboot_addr, reset_clock_manager,
+			reset_clock_manager_size);
+		
+		/* Set the bootrom to run the code snippet on reset */
+		writel(ramboot_addr,
+			&sysmgr_regs->romcodegrp_warmramgrp_execution);
+	}
 
 	/*
 	 * Write magic value into magic register to unlock support for
arch/arm/mach-socfpga/reset_clock_manager.S new file +71 -0

71 lines not on this page · raw message

Signature · 1 line
2.7.4
maintainer
#1 lore raw

PATCH 1/1 arm: socfpga: fix issue with warm reset when CSEL is 0

arch/arm/mach-socfpga/Makefile

Quoted 23 lines · Dalon Westergreen

When CSEL=0x0 the socfpga bootrom does not touch the clock configuration for the device. This can lead to a boot failure on warm resets. To address this, the bootrom is configured to run a bit of code in the last 4KB of onchip ram on a warm reset. This code puts the PLLs in bypass, disables the bootrom configuration to run the code snippet, and issues a warm reset to run the bootrom.

---
 arch/arm/mach-socfpga/Makefile                     |  2 +-
 arch/arm/mach-socfpga/include/mach/clock_manager.h | 22 ++++++-
 arch/arm/mach-socfpga/include/mach/reset_manager.h |  4 ++
 .../arm/mach-socfpga/include/mach/system_manager.h |  7 ++-
 arch/arm/mach-socfpga/misc.c                       | 29 +++++++++
 arch/arm/mach-socfpga/reset_clock_manager.S        | 71 ++++++++++++++++++++++
 6 files changed, 132 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-socfpga/reset_clock_manager.S
arch/arm/mach-socfpga/Makefile +0 -0
index 809cd47..6876ccf 100644
@@ -8,7 +8,7 @@

Please fix up these checkpatch errors:
total: 17 errors, 4 warnings, 2 checks, 199 lines checked

Dinh