[PATCH] PPC4xx: Add 440SP(e) DDR2 SPD DIMM support

This patch adds support for the DDR2 controller used on the
440SP and 440SPe. It is tested on the Katmai (440SPe) eval
board and works fine with the following DIMM modules:

- Corsair CM2X512-5400C4 (512MByte per DIMM)
- Kingston ValueRAM KVR667D2N5/512 (512MByte per DIMM)
- Kingston ValueRAM KVR667D2N5K2/2G (1GByte per DIMM)

This patch also adds the nice functionality to dynamically
create the TLB entries for the SDRAM (tlb.c). So we should
never run into such problems with wrong (too short) TLB
initialization again on these platforms.

Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index 914f28b..b226825 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -335,41 +335,6 @@
  * instructions.
  */
 
-#define	TLB_LO          1
-#define	TLB_HI          0
-
-#define	TLB_DATA        TLB_LO
-#define	TLB_TAG         TLB_HI
-
-/* Tag portion */
-
-#define TLB_EPN_MASK    0xFFFFFC00      /* Effective Page Number */
-#define TLB_PAGESZ_MASK 0x00000380
-#define TLB_PAGESZ(x)   (((x) & 0x7) << 7)
-#define   PAGESZ_1K		0
-#define   PAGESZ_4K             1
-#define   PAGESZ_16K            2
-#define   PAGESZ_64K            3
-#define   PAGESZ_256K           4
-#define   PAGESZ_1M             5
-#define   PAGESZ_4M             6
-#define   PAGESZ_16M            7
-#define TLB_VALID       0x00000040      /* Entry is valid */
-
-/* Data portion */
-
-#define TLB_RPN_MASK    0xFFFFFC00      /* Real Page Number */
-#define TLB_PERM_MASK   0x00000300
-#define TLB_EX          0x00000200      /* Instruction execution allowed */
-#define TLB_WR          0x00000100      /* Writes permitted */
-#define TLB_ZSEL_MASK   0x000000F0
-#define TLB_ZSEL(x)     (((x) & 0xF) << 4)
-#define TLB_ATTR_MASK   0x0000000F
-#define TLB_W           0x00000008      /* Caching is write-through */
-#define TLB_I           0x00000004      /* Caching is inhibited */
-#define TLB_M           0x00000002      /* Memory is coherent */
-#define TLB_G           0x00000001      /* Memory is guarded from prefetch */
-
 /*
  * e500 support
  */
@@ -482,7 +447,162 @@
 #define LAWAR_SIZE_16G		(LAWAR_SIZE_BASE+23)
 #define LAWAR_SIZE_32G		(LAWAR_SIZE_BASE+24)
 
+#ifdef CONFIG_440
+/* General */
+#define TLB_VALID   0x00000200
+
-#ifdef CONFIG_440SPE
+/* Supported page sizes */
+
+#define SZ_1K	0x00000000
+#define SZ_4K	0x00000010
+#define SZ_16K	0x00000020
+#define SZ_64K	0x00000030
+#define SZ_256K	0x00000040
+#define SZ_1M	0x00000050
+#define SZ_16M	0x00000070
+#define SZ_256M	0x00000090
+
+/* Storage attributes */
+#define SA_W	0x00000800	/* Write-through */
+#define SA_I	0x00000400	/* Caching inhibited */
+#define SA_M	0x00000200	/* Memory coherence */
+#define SA_G	0x00000100	/* Guarded */
+#define SA_E	0x00000080	/* Endian */
+
+/* Access control */
+#define AC_X	0x00000024	/* Execute */
+#define AC_W	0x00000012	/* Write */
+#define AC_R	0x00000009	/* Read */
+
+/* Some handy macros */
+
+#define EPN(e)		((e) & 0xfffffc00)
+#define TLB0(epn,sz)	((EPN((epn)) | (sz) | TLB_VALID ))
+#define TLB1(rpn,erpn)	(((rpn) & 0xfffffc00) | (erpn))
+#define TLB2(a)		((a) & 0x00000fbf)
+
+#define tlbtab_start\
+	mflr	r1	;\
+	bl	0f	;
+
+#define tlbtab_end\
+	.long 0, 0, 0	;\
+0:	mflr	r0	;\
+	mtlr	r1	;\
+	blr		;
+
+#define tlbentry(epn,sz,rpn,erpn,attr)\
+	.long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
+
+/*----------------------------------------------------------------------------+
+| TLB specific defines.
++----------------------------------------------------------------------------*/
+#define TLB_256MB_ALIGN_MASK 0xF0000000
+#define TLB_16MB_ALIGN_MASK  0xFF000000
+#define TLB_1MB_ALIGN_MASK   0xFFF00000
+#define TLB_256KB_ALIGN_MASK 0xFFFC0000
+#define TLB_64KB_ALIGN_MASK  0xFFFF0000
+#define TLB_16KB_ALIGN_MASK  0xFFFFC000
+#define TLB_4KB_ALIGN_MASK   0xFFFFF000
+#define TLB_1KB_ALIGN_MASK   0xFFFFFC00
+#define TLB_256MB_SIZE       0x10000000
+#define TLB_16MB_SIZE        0x01000000
+#define TLB_1MB_SIZE         0x00100000
+#define TLB_256KB_SIZE       0x00040000
+#define TLB_64KB_SIZE        0x00010000
+#define TLB_16KB_SIZE        0x00004000
+#define TLB_4KB_SIZE         0x00001000
+#define TLB_1KB_SIZE         0x00000400
+
+#define TLB_WORD0_EPN_MASK   0xFFFFFC00
+#define TLB_WORD0_EPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_EPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_V_MASK     0x00000200
+#define TLB_WORD0_V_ENABLE   0x00000200
+#define TLB_WORD0_V_DISABLE  0x00000000
+#define TLB_WORD0_TS_MASK    0x00000100
+#define TLB_WORD0_TS_1       0x00000100
+#define TLB_WORD0_TS_0       0x00000000
+#define TLB_WORD0_SIZE_MASK  0x000000F0
+#define TLB_WORD0_SIZE_1KB   0x00000000
+#define TLB_WORD0_SIZE_4KB   0x00000010
+#define TLB_WORD0_SIZE_16KB  0x00000020
+#define TLB_WORD0_SIZE_64KB  0x00000030
+#define TLB_WORD0_SIZE_256KB 0x00000040
+#define TLB_WORD0_SIZE_1MB   0x00000050
+#define TLB_WORD0_SIZE_16MB  0x00000070
+#define TLB_WORD0_SIZE_256MB 0x00000090
+#define TLB_WORD0_TPAR_MASK  0x0000000F
+#define TLB_WORD0_TPAR_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD0_TPAR_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD1_RPN_MASK   0xFFFFFC00
+#define TLB_WORD1_RPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_RPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_PAR1_MASK  0x00000300
+#define TLB_WORD1_PAR1_ENCODE(n) ((((unsigned long)(n))&0x03)<<8)
+#define TLB_WORD1_PAR1_DECODE(n) ((((unsigned long)(n))>>8)&0x03)
+#define TLB_WORD1_PAR1_0     0x00000000
+#define TLB_WORD1_PAR1_1     0x00000100
+#define TLB_WORD1_PAR1_2     0x00000200
+#define TLB_WORD1_PAR1_3     0x00000300
+#define TLB_WORD1_ERPN_MASK  0x0000000F
+#define TLB_WORD1_ERPN_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD1_ERPN_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD2_PAR2_MASK  0xC0000000
+#define TLB_WORD2_PAR2_ENCODE(n) ((((unsigned long)(n))&0x03)<<30)
+#define TLB_WORD2_PAR2_DECODE(n) ((((unsigned long)(n))>>30)&0x03)
+#define TLB_WORD2_PAR2_0     0x00000000
+#define TLB_WORD2_PAR2_1     0x40000000
+#define TLB_WORD2_PAR2_2     0x80000000
+#define TLB_WORD2_PAR2_3     0xC0000000
+#define TLB_WORD2_U0_MASK    0x00008000
+#define TLB_WORD2_U0_ENABLE  0x00008000
+#define TLB_WORD2_U0_DISABLE 0x00000000
+#define TLB_WORD2_U1_MASK    0x00004000
+#define TLB_WORD2_U1_ENABLE  0x00004000
+#define TLB_WORD2_U1_DISABLE 0x00000000
+#define TLB_WORD2_U2_MASK    0x00002000
+#define TLB_WORD2_U2_ENABLE  0x00002000
+#define TLB_WORD2_U2_DISABLE 0x00000000
+#define TLB_WORD2_U3_MASK    0x00001000
+#define TLB_WORD2_U3_ENABLE  0x00001000
+#define TLB_WORD2_U3_DISABLE 0x00000000
+#define TLB_WORD2_W_MASK     0x00000800
+#define TLB_WORD2_W_ENABLE   0x00000800
+#define TLB_WORD2_W_DISABLE  0x00000000
+#define TLB_WORD2_I_MASK     0x00000400
+#define TLB_WORD2_I_ENABLE   0x00000400
+#define TLB_WORD2_I_DISABLE  0x00000000
+#define TLB_WORD2_M_MASK     0x00000200
+#define TLB_WORD2_M_ENABLE   0x00000200
+#define TLB_WORD2_M_DISABLE  0x00000000
+#define TLB_WORD2_G_MASK     0x00000100
+#define TLB_WORD2_G_ENABLE   0x00000100
+#define TLB_WORD2_G_DISABLE  0x00000000
+#define TLB_WORD2_E_MASK     0x00000080
+#define TLB_WORD2_E_ENABLE   0x00000080
+#define TLB_WORD2_E_DISABLE  0x00000000
+#define TLB_WORD2_UX_MASK    0x00000020
+#define TLB_WORD2_UX_ENABLE  0x00000020
+#define TLB_WORD2_UX_DISABLE 0x00000000
+#define TLB_WORD2_UW_MASK    0x00000010
+#define TLB_WORD2_UW_ENABLE  0x00000010
+#define TLB_WORD2_UW_DISABLE 0x00000000
+#define TLB_WORD2_UR_MASK    0x00000008
+#define TLB_WORD2_UR_ENABLE  0x00000008
+#define TLB_WORD2_UR_DISABLE 0x00000000
+#define TLB_WORD2_SX_MASK    0x00000004
+#define TLB_WORD2_SX_ENABLE  0x00000004
+#define TLB_WORD2_SX_DISABLE 0x00000000
+#define TLB_WORD2_SW_MASK    0x00000002
+#define TLB_WORD2_SW_ENABLE  0x00000002
+#define TLB_WORD2_SW_DISABLE 0x00000000
+#define TLB_WORD2_SR_MASK    0x00000001
+#define TLB_WORD2_SR_ENABLE  0x00000001
+#define TLB_WORD2_SR_DISABLE 0x00000000
+
 /*----------------------------------------------------------------------------+
 | Following instructions are not available in Book E mode of the GNU assembler.
 +----------------------------------------------------------------------------*/
@@ -516,11 +636,15 @@
 #define MBAR_INST 				.long 0x7c000000|\
 					(854<<1)
 
-/*----------------------------------------------------------------------------+
-| Following instruction is not available in PPC405 mode of the GNU assembler.
-+----------------------------------------------------------------------------*/
-#define TLBRE(rt,ra,ws)			.long 0x7c000000|\
-					(rt<<21)|(ra<<16)|(ws<<11)|(946<<1)
+#ifndef __ASSEMBLY__
+/* Prototypes */
+void mttlb1(unsigned long index, unsigned long value);
+void mttlb2(unsigned long index, unsigned long value);
+void mttlb3(unsigned long index, unsigned long value);
+unsigned long mftlb1(unsigned long index);
+unsigned long mftlb2(unsigned long index);
+unsigned long mftlb3(unsigned long index);
+#endif /* __ASSEMBLY__ */
 
-#endif
+#endif /* CONFIG_440 */
 #endif /* _PPC_MMU_H_ */