rockchip: sdram: extend to use sys_reg3 for capacity info

Since we have new DRAM type and to support different DRAM size in different
CS, we need more bits, so introduce sys_reg3 to record the info.
Note that the info in sys_reg3 is extension to sys_reg2 and the info in
sys_reg2 is the same as before. We define the DRAM_INFO with sys_reg3 as
VERSION2.
All the ENC macro are moved to sdram_common.h since the sdram.c only
need to do the info decode.

Signed-off-by: YouMin Chen <cym@rock-chips.com>
Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
index 01fc353..cf2a7b7 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram.h
@@ -16,79 +16,66 @@
 };
 
 /*
- * sys_reg bitfield struct
+ * sys_reg2 bitfield struct
  * [31]		row_3_4_ch1
  * [30]		row_3_4_ch0
  * [29:28]	chinfo
  * [27]		rank_ch1
  * [26:25]	col_ch1
  * [24]		bk_ch1
- * [23:22]	cs0_row_ch1
- * [21:20]	cs1_row_ch1
+ * [23:22]	low bits of cs0_row_ch1
+ * [21:20]	low bits of cs1_row_ch1
  * [19:18]	bw_ch1
  * [17:16]	dbw_ch1;
  * [15:13]	ddrtype
  * [12]		channelnum
  * [11]		rank_ch0
- * [10:9]	col_ch0
+ * [10:9]	col_ch0,
  * [8]		bk_ch0
- * [7:6]	cs0_row_ch0
- * [5:4]	cs1_row_ch0
+ * [7:6]	low bits of cs0_row_ch0
+ * [5:4]	low bits of cs1_row_ch0
  * [3:2]	bw_ch0
  * [1:0]	dbw_ch0
-*/
+ */
 #define SYS_REG_DDRTYPE_SHIFT		13
-#define DDR_SYS_REG_VERSION		2
 #define SYS_REG_DDRTYPE_MASK		7
 #define SYS_REG_NUM_CH_SHIFT		12
 #define SYS_REG_NUM_CH_MASK		1
 #define SYS_REG_ROW_3_4_SHIFT(ch)	(30 + (ch))
 #define SYS_REG_ROW_3_4_MASK		1
-#define SYS_REG_ENC_ROW_3_4(n, ch)	((n) << (30 + (ch)))
 #define SYS_REG_CHINFO_SHIFT(ch)	(28 + (ch))
-#define SYS_REG_ENC_CHINFO(ch)		(1 << SYS_REG_CHINFO_SHIFT(ch))
-#define SYS_REG_ENC_DDRTYPE(n)		((n) << SYS_REG_DDRTYPE_SHIFT)
-#define SYS_REG_ENC_NUM_CH(n)		(((n) - SYS_REG_NUM_CH_MASK) << \
-					SYS_REG_NUM_CH_SHIFT)
 #define SYS_REG_RANK_SHIFT(ch)		(11 + (ch) * 16)
 #define SYS_REG_RANK_MASK		1
-#define SYS_REG_ENC_RANK(n, ch)		(((n) - SYS_REG_RANK_MASK) << \
-					 SYS_REG_RANK_SHIFT(ch))
 #define SYS_REG_COL_SHIFT(ch)		(9 + (ch) * 16)
 #define SYS_REG_COL_MASK		3
-#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << SYS_REG_COL_SHIFT(ch))
 #define SYS_REG_BK_SHIFT(ch)		(8 + (ch) * 16)
 #define SYS_REG_BK_MASK			1
-#define SYS_REG_ENC_BK(n, ch)		(((n) == 3 ? 0 : 1) << \
-					SYS_REG_BK_SHIFT(ch))
 #define SYS_REG_CS0_ROW_SHIFT(ch)	(6 + (ch) * 16)
 #define SYS_REG_CS0_ROW_MASK		3
 #define SYS_REG_CS1_ROW_SHIFT(ch)	(4 + (ch) * 16)
 #define SYS_REG_CS1_ROW_MASK		3
 #define SYS_REG_BW_SHIFT(ch)		(2 + (ch) * 16)
 #define SYS_REG_BW_MASK			3
-#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << SYS_REG_BW_SHIFT(ch))
 #define SYS_REG_DBW_SHIFT(ch)		((ch) * 16)
 #define SYS_REG_DBW_MASK		3
-#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << SYS_REG_DBW_SHIFT(ch))
-
-#define SYS_REG_ENC_VERSION(n)		((n) << 28)
-#define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \
-			(os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \
-			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
-				     (5 + 2 * (ch)); \
-		} while (0)
-
-#define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \
-			(os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \
-			(os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \
-			(os_reg2) |= (((n) - 13) & 0x3) << (4 + 16 * (ch)); \
-			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
-				     (4 + 2 * (ch)); \
-		} while (0)
 
-#define SYS_REG_CS1_COL_SHIFT(ch)	(0 + 2 * (ch))
-#define SYS_REG_ENC_CS1_COL(n, ch)      (((n) - 9) << SYS_REG_CS1_COL_SHIFT(ch))
+/*
+ * sys_reg3 bitfield struct
+ * [7]		high bit of cs0_row_ch1
+ * [6]		high bit of cs1_row_ch1
+ * [5]		high bit of cs0_row_ch0
+ * [4]		high bit of cs1_row_ch0
+ * [3:2]	cs1_col_ch1
+ * [1:0]	cs1_col_ch0
+ */
+#define SYS_REG_VERSION_SHIFT			28
+#define SYS_REG_VERSION_MASK			0xf
+#define SYS_REG_EXTEND_CS0_ROW_SHIFT(ch)	(5 + (ch) * 2)
+#define SYS_REG_EXTEND_CS0_ROW_MASK		1
+#define SYS_REG_EXTEND_CS1_ROW_SHIFT(ch)	(4 + (ch) * 2)
+#define SYS_REG_EXTEND_CS1_ROW_MASK		1
+#define SYS_REG_CS1_COL_SHIFT(ch)		(0 + (ch) * 2)
+#define SYS_REG_CS1_COL_MASK			3
 
 /* Get sdram size decode from reg */
 size_t rockchip_sdram_size(phys_addr_t reg);
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_common.h b/arch/arm/include/asm/arch-rockchip/sdram_common.h
index 8d771ce..cd3d7f9 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_common.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_common.h
@@ -36,6 +36,75 @@
 	unsigned int odt;
 };
 
+#define DDR_SYS_REG_VERSION		(0x2)
+/*
+ * sys_reg2 bitfield struct
+ * [31]		row_3_4_ch1
+ * [30]		row_3_4_ch0
+ * [29:28]	chinfo
+ * [27]		rank_ch1
+ * [26:25]	col_ch1
+ * [24]		bk_ch1
+ * [23:22]	cs0_row_ch1
+ * [21:20]	cs1_row_ch1
+ * [19:18]	bw_ch1
+ * [17:16]	dbw_ch1;
+ * [15:13]	ddrtype
+ * [12]		channelnum
+ * [11]		rank_ch0
+ * [10:9]	col_ch0
+ * [8]		bk_ch0
+ * [7:6]	cs0_row_ch0
+ * [5:4]	cs1_row_ch0
+ * [3:2]	bw_ch0
+ * [1:0]	dbw_ch0
+ */
+#define SYS_REG_ENC_ROW_3_4(n, ch)	((n) << (30 + (ch)))
+#define SYS_REG_DEC_ROW_3_4(n, ch)	(((n) >> (30 + (ch))) & 0x1)
+#define SYS_REG_ENC_CHINFO(ch)		(1 << (28 + (ch)))
+#define SYS_REG_ENC_DDRTYPE(n)		((n) << 13)
+#define SYS_REG_DEC_DDRTYPE(n)		(((n) >> 13) & 0x7)
+#define SYS_REG_ENC_NUM_CH(n)		(((n) - 1) << 12)
+#define SYS_REG_DEC_NUM_CH(n)		(1 + (((n) >> 12) & 0x1))
+#define SYS_REG_ENC_RANK(n, ch)		(((n) - 1) << (11 + ((ch) * 16)))
+#define SYS_REG_DEC_RANK(n, ch)		(1 + (((n) >> (11 + 16 * (ch))) & 0x1))
+#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << (9 + ((ch) * 16)))
+#define SYS_REG_DEC_COL(n, ch)		(9 + (((n) >> (9 + 16 * (ch))) & 0x3))
+#define SYS_REG_ENC_BK(n, ch)		(((n) == 3 ? 0 : 1) << \
+						(8 + ((ch) * 16)))
+#define SYS_REG_DEC_BK(n, ch)		(3 - (((n) >> (8 + 16 * (ch))) & 0x1))
+#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << (2 + ((ch) * 16)))
+#define SYS_REG_DEC_BW(n, ch)		(2 >> (((n) >> (2 + 16 * (ch))) & 0x3))
+#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << (0 + ((ch) * 16)))
+#define SYS_REG_DEC_DBW(n, ch)		(2 >> (((n) >> (0 + 16 * (ch))) & 0x3))
+/* sys reg 3 */
+#define SYS_REG_ENC_VERSION(n)		((n) << 28)
+#define SYS_REG_DEC_VERSION(n)		(((n) >> 28) & 0xf)
+#define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \
+			(os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \
+			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
+				     (5 + 2 * (ch)); \
+		} while (0)
+
+#define SYS_REG_DEC_CS0_ROW(os_reg2, os_reg3, ch)	\
+		((((((os_reg2) >> (6 + 16 * (ch)) & 0x3) | \
+		 ((((os_reg3) >> (5 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12)
+
+#define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \
+			(os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \
+			(os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \
+			(os_reg2) |= (((n) - 13) & 0x3) << (4 + 16 * (ch)); \
+			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
+				     (4 + 2 * (ch)); \
+		} while (0)
+
+#define SYS_REG_DEC_CS1_ROW(os_reg2, os_reg3, ch) \
+		((((((os_reg2) >> (4 + 16 * (ch)) & 0x3) | \
+		 ((((os_reg3) >> (4 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12)
+
+#define SYS_REG_ENC_CS1_COL(n, ch)	(((n) - 9) << (0 + 2 * (ch)))
+#define SYS_REG_DEC_CS1_COL(n, ch)	(9 + (((n) >> (0 + 2 * (ch))) & 0x3))
+
 #if !defined(CONFIG_RAM_ROCKCHIP_DEBUG)
 inline void sdram_print_dram_type(unsigned char dramtype)
 {
diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c
index acb1af7..8e5a572 100644
--- a/arch/arm/mach-rockchip/sdram.c
+++ b/arch/arm/mach-rockchip/sdram.c
@@ -76,39 +76,88 @@
 
 size_t rockchip_sdram_size(phys_addr_t reg)
 {
-	u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
+	u32 rank, cs0_col, bk, cs0_row, cs1_row, bw, row_3_4;
 	size_t chipsize_mb = 0;
 	size_t size_mb = 0;
 	u32 ch;
-
+	u32 cs1_col = 0;
+	u32 bg = 0;
+	u32 dbw, dram_type;
 	u32 sys_reg = readl(reg);
+	u32 sys_reg3 = readl(reg + 4);
 	u32 ch_num = 1 + ((sys_reg >> SYS_REG_NUM_CH_SHIFT)
 		       & SYS_REG_NUM_CH_MASK);
 
+	dram_type = (sys_reg >> SYS_REG_DDRTYPE_SHIFT) & SYS_REG_DDRTYPE_MASK;
 	debug("%s %x %x\n", __func__, (u32)reg, sys_reg);
 	for (ch = 0; ch < ch_num; ch++) {
 		rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
 			SYS_REG_RANK_MASK);
-		col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
+		cs0_col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) &
+			  SYS_REG_COL_MASK);
+		cs1_col = cs0_col;
 		bk = 3 - ((sys_reg >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
-		cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
+		if ((sys_reg3 >> SYS_REG_VERSION_SHIFT &
+		     SYS_REG_VERSION_MASK) == 0x2) {
+			cs1_col = 9 + (sys_reg3 >> SYS_REG_CS1_COL_SHIFT(ch) &
+				  SYS_REG_CS1_COL_MASK);
+			if (((sys_reg3 >> SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
+			    SYS_REG_EXTEND_CS0_ROW_MASK) << 2) + (sys_reg >>
+			    SYS_REG_CS0_ROW_SHIFT(ch) &
+			    SYS_REG_CS0_ROW_MASK) == 7)
+				cs0_row = 12;
+			else
+				cs0_row = 13 + (sys_reg >>
+					  SYS_REG_CS0_ROW_SHIFT(ch) &
+					  SYS_REG_CS0_ROW_MASK) +
+					  ((sys_reg3 >>
+					  SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
+					  SYS_REG_EXTEND_CS0_ROW_MASK) << 2);
+			if (((sys_reg3 >> SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
+			    SYS_REG_EXTEND_CS1_ROW_MASK) << 2) + (sys_reg >>
+			    SYS_REG_CS1_ROW_SHIFT(ch) &
+			    SYS_REG_CS1_ROW_MASK) == 7)
+				cs1_row = 12;
+			else
+				cs1_row = 13 + (sys_reg >>
+					  SYS_REG_CS1_ROW_SHIFT(ch) &
+					  SYS_REG_CS1_ROW_MASK) +
+					  ((sys_reg3 >>
+					  SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
+					  SYS_REG_EXTEND_CS1_ROW_MASK) << 2);
+		} else {
+			cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
 				SYS_REG_CS0_ROW_MASK);
-		cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
+			cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
 				SYS_REG_CS1_ROW_MASK);
+		}
 		bw = (2 >> ((sys_reg >> SYS_REG_BW_SHIFT(ch)) &
 			SYS_REG_BW_MASK));
 		row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
 			SYS_REG_ROW_3_4_MASK;
-
-		chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
+		if (dram_type == DDR4) {
+			dbw = (sys_reg >> SYS_REG_DBW_SHIFT(ch)) &
+				SYS_REG_DBW_MASK;
+			bg = (dbw == 2) ? 2 : 1;
+		}
+		chipsize_mb = (1 << (cs0_row + cs0_col + bk + bg + bw - 20));
 
 		if (rank > 1)
-			chipsize_mb += chipsize_mb >> (cs0_row - cs1_row);
+			chipsize_mb += chipsize_mb >> ((cs0_row - cs1_row) +
+				       (cs0_col - cs1_col));
 		if (row_3_4)
 			chipsize_mb = chipsize_mb * 3 / 4;
 		size_mb += chipsize_mb;
-		debug("rank %d col %d bk %d cs0_row %d bw %d row_3_4 %d\n",
-		      rank, col, bk, cs0_row, bw, row_3_4);
+		if (rank > 1)
+			debug("rank %d cs0_col %d cs1_col %d bk %d cs0_row %d\
+			       cs1_row %d bw %d row_3_4 %d\n",
+			       rank, cs0_col, cs1_col, bk, cs0_row,
+			       cs1_row, bw, row_3_4);
+		else
+			debug("rank %d cs0_col %d bk %d cs0_row %d\
+			       bw %d row_3_4 %d\n",
+			       rank, cs0_col, bk, cs0_row,
+			       bw, row_3_4);
 	}
 
 	/*