stm32: Add SDRAM support for stm32f746 discovery board

This patch adds SDRAM support for stm32f746 discovery board.
This patch depends on previous patch.
This patch is based on STM32F4 and emcraft's[1].

[1]:  https://github.com/EmcraftSystems/u-boot

Signed-off-by: Toshifumi NISHINAGA <tnishinaga.dev@gmail.com>
diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk
index 4a53006..db4660e 100644
--- a/arch/arm/cpu/armv7m/config.mk
+++ b/arch/arm/cpu/armv7m/config.mk
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-PLATFORM_CPPFLAGS += -march=armv7-m -mthumb
+PLATFORM_CPPFLAGS += -march=armv7-m -mthumb -mno-unaligned-access
diff --git a/arch/arm/include/asm/arch-stm32f7/fmc.h b/arch/arm/include/asm/arch-stm32f7/fmc.h
new file mode 100644
index 0000000..7dd5077
--- /dev/null
+++ b/arch/arm/include/asm/arch-stm32f7/fmc.h
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2013
+ * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com
+ *
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _MACH_FMC_H_
+#define _MACH_FMC_H_
+
+struct stm32_fmc_regs {
+	u32 sdcr1;	/* Control register 1 */
+	u32 sdcr2;	/* Control register 2 */
+	u32 sdtr1;	/* Timing register 1 */
+	u32 sdtr2;	/* Timing register 2 */
+	u32 sdcmr;	/* Mode register */
+	u32 sdrtr;	/* Refresh timing register */
+	u32 sdsr;	/* Status register */
+};
+
+/*
+ * FMC registers base
+ */
+#define STM32_SDRAM_FMC_BASE	0xA0000140
+#define STM32_SDRAM_FMC		((struct stm32_fmc_regs *)STM32_SDRAM_FMC_BASE)
+
+/* Control register SDCR */
+#define FMC_SDCR_RPIPE_SHIFT	13	/* RPIPE bit shift */
+#define FMC_SDCR_RBURST_SHIFT	12	/* RBURST bit shift */
+#define FMC_SDCR_SDCLK_SHIFT	10	/* SDRAM clock divisor shift */
+#define FMC_SDCR_WP_SHIFT	9	/* Write protection shift */
+#define FMC_SDCR_CAS_SHIFT	7	/* CAS latency shift */
+#define FMC_SDCR_NB_SHIFT	6	/* Number of banks shift */
+#define FMC_SDCR_MWID_SHIFT	4	/* Memory width shift */
+#define FMC_SDCR_NR_SHIFT	2	/* Number of row address bits shift */
+#define FMC_SDCR_NC_SHIFT	0	/* Number of col address bits shift */
+
+/* Timings register SDTR */
+#define FMC_SDTR_TMRD_SHIFT	0	/* Load mode register to active */
+#define FMC_SDTR_TXSR_SHIFT	4	/* Exit self-refresh time */
+#define FMC_SDTR_TRAS_SHIFT	8	/* Self-refresh time */
+#define FMC_SDTR_TRC_SHIFT	12	/* Row cycle delay */
+#define FMC_SDTR_TWR_SHIFT	16	/* Recovery delay */
+#define FMC_SDTR_TRP_SHIFT	20	/* Row precharge delay */
+#define FMC_SDTR_TRCD_SHIFT	24	/* Row-to-column delay */
+
+
+#define FMC_SDCMR_NRFS_SHIFT	5
+
+#define FMC_SDCMR_MODE_NORMAL		0
+#define FMC_SDCMR_MODE_START_CLOCK	1
+#define FMC_SDCMR_MODE_PRECHARGE	2
+#define FMC_SDCMR_MODE_AUTOREFRESH	3
+#define FMC_SDCMR_MODE_WRITE_MODE	4
+#define FMC_SDCMR_MODE_SELFREFRESH	5
+#define FMC_SDCMR_MODE_POWERDOWN	6
+
+#define FMC_SDCMR_BANK_1		(1 << 4)
+#define FMC_SDCMR_BANK_2		(1 << 3)
+
+#define FMC_SDCMR_MODE_REGISTER_SHIFT	9
+
+#define FMC_SDSR_BUSY			(1 << 5)
+
+#define FMC_BUSY_WAIT()		do { \
+		__asm__ __volatile__ ("dsb" : : : "memory"); \
+		while (STM32_SDRAM_FMC->sdsr & FMC_SDSR_BUSY) \
+			; \
+	} while (0)
+
+
+#endif /* _MACH_FMC_H_ */
diff --git a/arch/arm/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h
index 200444d..54d8a2b 100644
--- a/arch/arm/include/asm/armv7m.h
+++ b/arch/arm/include/asm/armv7m.h
@@ -51,10 +51,21 @@
 #define V7M_MPU_CTRL_ENABLE		(1 << 0)
 #define V7M_MPU_CTRL_HFNMIENA		(1 << 1)
 
+#define V7M_MPU_CTRL_ENABLE		(1 << 0)
+#define V7M_MPU_CTRL_DISABLE		(0 << 0)
+#define V7M_MPU_CTRL_HFNMIENA		(1 << 1)
+
 #define V7M_MPU_RASR_EN			(1 << 0)
 #define V7M_MPU_RASR_SIZE_BITS		1
 #define V7M_MPU_RASR_SIZE_4GB		(31 << V7M_MPU_RASR_SIZE_BITS)
+#define V7M_MPU_RASR_SIZE_8MB		(24 << V7M_MPU_RASR_SIZE_BITS)
+#define V7M_MPU_RASR_TEX_SHIFT	19
+#define V7M_MPU_RASR_S_SHIFT		18
+#define V7M_MPU_RASR_C_SHIFT		17
+#define V7M_MPU_RASR_B_SHIFT		16
 #define V7M_MPU_RASR_AP_RW_RW		(3 << 24)
+#define V7M_MPU_RASR_XN_ENABLE	(0 << 28)
+#define V7M_MPU_RASR_XN_DISABLE (1 << 28)
 
 #endif /* !defined(__ASSEMBLY__) */
 #endif /* ARMV7M_H */
diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c
index 6a1e019..8baee99 100644
--- a/arch/arm/mach-stm32/stm32f7/soc.c
+++ b/arch/arm/mach-stm32/stm32f7/soc.c
@@ -19,6 +19,55 @@
 {
 	configure_clocks();
 
+	/*
+		* Configure the memory protection unit (MPU)
+		* 0x00000000 - 0xffffffff: Strong-order, Shareable
+		* 0xC0000000 - 0xC0800000: Normal, Outer and inner Non-cacheable
+	 */
+
+	 /* Disable MPU */
+	 writel(0, &V7M_MPU->ctrl);
+
+	 writel(
+		 0x00000000 /* address */
+		 | 1 << 4	/* VALID */
+		 | 0 << 0	/* REGION */
+		 , &V7M_MPU->rbar
+	 );
+
+	 /* Strong-order, Shareable */
+	 /* TEX=000, S=1, C=0, B=0*/
+	 writel(
+		 (V7M_MPU_RASR_XN_ENABLE
+			 | V7M_MPU_RASR_AP_RW_RW
+			 | 0x01 << V7M_MPU_RASR_S_SHIFT
+			 | 0x00 << V7M_MPU_RASR_TEX_SHIFT
+			 | V7M_MPU_RASR_SIZE_4GB
+			 | V7M_MPU_RASR_EN)
+		 , &V7M_MPU->rasr
+	 );
+
+	 writel(
+		 0xC0000000 /* address */
+		 | 1 << 4	/* VALID */
+		 | 1 << 0	/* REGION */
+		 , &V7M_MPU->rbar
+	 );
+
+	 /* Normal, Outer and inner Non-cacheable */
+	 /* TEX=001, S=0, C=0, B=0*/
+	 writel(
+		 (V7M_MPU_RASR_XN_ENABLE
+			 | V7M_MPU_RASR_AP_RW_RW
+			 | 0x01 << V7M_MPU_RASR_TEX_SHIFT
+			 | V7M_MPU_RASR_SIZE_8MB
+			 | V7M_MPU_RASR_EN)
+			 , &V7M_MPU->rasr
+	 );
+
+	 /* Enable MPU */
+	 writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl);
+
 	return 0;
 }