am43xx: Tune the system to avoid DSS underflows

* This is done by limiting the ARM's bandwidth and setting DSS priority in
  the EMIF controller to ensure underflows do not occur.
diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c
index bbe9d1a..fc66872 100644
--- a/arch/arm/cpu/armv7/am33xx/ddr.c
+++ b/arch/arm/cpu/armv7/am33xx/ddr.c
@@ -94,6 +94,18 @@
 	writel(regs->emif_rd_wr_exec_thresh,
 	       &emif_reg[nr]->emif_rd_wr_exec_thresh);
 
+	/*
+	 * for most SOCs these registers won't need to be changed so only
+	 * write to these registers if someone explicitly has set the
+	 * register's value.
+	 */
+	if(regs->emif_cos_config) {
+		writel(regs->emif_prio_class_serv_map, &emif_reg[nr]->emif_prio_class_serv_map);
+		writel(regs->emif_connect_id_serv_1_map, &emif_reg[nr]->emif_connect_id_serv_1_map);
+		writel(regs->emif_connect_id_serv_2_map, &emif_reg[nr]->emif_connect_id_serv_2_map);
+		writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config);
+	}
+
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
 	writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index aa10fab..8dd69b3 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -489,6 +489,12 @@
 #define OMAP_GPIO_SETDATAOUT		0x0194
 
 /* Control Device Register */
+
+ /* Control Device Register */
+#define MREQPRIO_0_SAB_INIT1_MASK	0xFFFFFF8F
+#define MREQPRIO_0_SAB_INIT0_MASK	0xFFFFFFF8
+#define MREQPRIO_1_DSS_MASK		0xFFFFFF8F
+
 struct ctrl_dev {
 	unsigned int deviceid;		/* offset 0x00 */
 	unsigned int resv1[7];
@@ -502,10 +508,25 @@
 	unsigned int macid1h;		/* offset 0x3c */
 	unsigned int resv4[4];
 	unsigned int miisel;		/* offset 0x50 */
-	unsigned int resv5[106];
+	unsigned int resv5[7];
+	unsigned int mreqprio_0;	/* offset 0x70 */
+	unsigned int mreqprio_1;	/* offset 0x74 */
+	unsigned int resv6[97];
 	unsigned int efuse_sma;		/* offset 0x1FC */
 };
 
+/* Bandwidth Limiter Portion of the L3Fast Configuration Register */
+#define BW_LIMITER_BW_FRAC_MASK         0xFFFFFFE0
+#define BW_LIMITER_BW_INT_MASK          0xFFFFFFF0
+#define BW_LIMITER_BW_WATERMARK_MASK    0xFFFFF800
+
+struct l3f_cfg_bwlimiter {
+	u32 padding0[2];
+	u32 modena_init0_bw_fractional;
+	u32 modena_init0_bw_integer;
+	u32 modena_init0_watermark_0;
+};
+
 /* gmii_sel register defines */
 #define GMII1_SEL_MII		0x0
 #define GMII1_SEL_RMII		0x1
diff --git a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
index 15399dc..b470319 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
@@ -13,6 +13,9 @@
 
 /* Module base addresses */
 
+/* L3 Fast Configuration Bandwidth Limiter Base Address */
+#define L3F_CFG_BWLIMITER		0x44005200
+
 /* UART Base Address */
 #define UART0_BASE			0x44E09000
 
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 45668ca..b8d6bdc 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -642,11 +642,16 @@
 	u32 emif_ddr_phy_ctrl_1;
 	u32 emif_ddr_phy_ctrl_1_shdw;
 	u32 emif_ddr_phy_ctrl_2;
-	u32 padding7[12];
+	u32 padding7[4];
+	u32 emif_prio_class_serv_map;
+	u32 emif_connect_id_serv_1_map;
+	u32 emif_connect_id_serv_2_map;
+	u32 padding8[5];
 	u32 emif_rd_wr_exec_thresh;
-	u32 padding8[7];
+	u32 emif_cos_config;
+	u32 padding9[6];
 	u32 emif_ddr_phy_status[21];
-	u32 padding9[27];
+	u32 padding10[27];
 	u32 emif_ddr_ext_phy_ctrl_1;
 	u32 emif_ddr_ext_phy_ctrl_1_shdw;
 	u32 emif_ddr_ext_phy_ctrl_2;
@@ -1137,6 +1142,10 @@
 	u32 emif_rd_wr_lvl_rmp_ctl;
 	u32 emif_rd_wr_lvl_ctl;
 	u32 emif_rd_wr_exec_thresh;
+	u32 emif_prio_class_serv_map;
+	u32 emif_connect_id_serv_1_map;
+	u32 emif_connect_id_serv_2_map;
+	u32 emif_cos_config;
 };
 
 struct lpddr2_mr_regs {
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 5eaa4a5..7e239f1 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -157,12 +157,16 @@
 	.emif_rd_wr_lvl_rmp_ctl		= 0x0,
 	.emif_rd_wr_lvl_ctl		= 0x0,
 	.emif_ddr_phy_ctlr_1		= 0x0E084006,
-	.emif_rd_wr_exec_thresh		= 0x00000405,
+	.emif_rd_wr_exec_thresh		= 0x80000405,
 	.emif_ddr_ext_phy_ctrl_1	= 0x04010040,
 	.emif_ddr_ext_phy_ctrl_2	= 0x00500050,
 	.emif_ddr_ext_phy_ctrl_3	= 0x00500050,
 	.emif_ddr_ext_phy_ctrl_4	= 0x00500050,
-	.emif_ddr_ext_phy_ctrl_5	= 0x00500050
+	.emif_ddr_ext_phy_ctrl_5	= 0x00500050,
+	.emif_prio_class_serv_map	= 0x80000001,
+	.emif_connect_id_serv_1_map	= 0x80000094,
+	.emif_connect_id_serv_2_map	= 0x00000000,
+	.emif_cos_config			= 0x000FFFFF
 };
 
 const u32 ext_phy_ctrl_const_base_lpddr2[] = {
@@ -217,7 +221,11 @@
 	.emif_rd_wr_lvl_rmp_win		= 0x0,
 	.emif_rd_wr_lvl_rmp_ctl		= 0x0,
 	.emif_rd_wr_lvl_ctl		= 0x0,
-	.emif_rd_wr_exec_thresh		= 0x00000405
+	.emif_rd_wr_exec_thresh		= 0x80000405,
+	.emif_prio_class_serv_map	= 0x80000001,
+	.emif_connect_id_serv_1_map	= 0x80000094,
+	.emif_connect_id_serv_2_map	= 0x00000000,
+	.emif_cos_config		= 0x000FFFFF
 };
 
 /* EMIF DDR3 Configurations are different for beta AM43X GP EVMs */
@@ -236,7 +244,11 @@
 	.emif_ddr_ext_phy_ctrl_3	= 0x00000091,
 	.emif_ddr_ext_phy_ctrl_4	= 0x000000B5,
 	.emif_ddr_ext_phy_ctrl_5	= 0x000000E5,
-	.emif_rd_wr_exec_thresh		= 0x00000405
+	.emif_rd_wr_exec_thresh		= 0x80000405,
+	.emif_prio_class_serv_map	= 0x80000001,
+	.emif_connect_id_serv_1_map	= 0x80000094,
+	.emif_connect_id_serv_2_map	= 0x00000000,
+	.emif_cos_config		= 0x000FFFFF
 };
 
 /* EMIF DDR3 Configurations are different for production AM43X GP EVMs */
@@ -255,7 +267,11 @@
 	.emif_ddr_ext_phy_ctrl_3	= 0x00000091,
 	.emif_ddr_ext_phy_ctrl_4	= 0x000000B9,
 	.emif_ddr_ext_phy_ctrl_5	= 0x000000E6,
-	.emif_rd_wr_exec_thresh		= 0x00000405
+	.emif_rd_wr_exec_thresh		= 0x80000405,
+	.emif_prio_class_serv_map	= 0x80000001,
+	.emif_connect_id_serv_1_map	= 0x80000094,
+	.emif_connect_id_serv_2_map	= 0x00000000,
+	.emif_cos_config		= 0x000FFFFF
 };
 
 static const struct emif_regs ddr3_sk_emif_regs_400Mhz = {
@@ -277,7 +293,11 @@
 	.emif_rd_wr_lvl_rmp_win		= 0x0,
 	.emif_rd_wr_lvl_rmp_ctl		= 0x00000000,
 	.emif_rd_wr_lvl_ctl		= 0x00000000,
-	.emif_rd_wr_exec_thresh		= 0x00000000,
+	.emif_rd_wr_exec_thresh		= 0x80000000,
+	.emif_prio_class_serv_map	= 0x80000001,
+	.emif_connect_id_serv_1_map	= 0x80000094,
+	.emif_connect_id_serv_2_map	= 0x00000000,
+	.emif_cos_config		= 0x000FFFFF
 };
 
 const u32 ext_phy_ctrl_const_base_ddr3[] = {
@@ -587,8 +607,44 @@
 
 int board_init(void)
 {
+	struct l3f_cfg_bwlimiter *bwlimiter = (struct l3f_cfg_bwlimiter *)L3F_CFG_BWLIMITER;
+	u32 mreqprio_0, mreqprio_1, modena_init0_bw_fractional,
+	    modena_init0_bw_integer, modena_init0_watermark_0;
+
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 
+	/* Clear all important bits for DSS errata that may need to be tweaked*/
+	mreqprio_0 = readl(&cdev->mreqprio_0) & MREQPRIO_0_SAB_INIT1_MASK &
+	                   MREQPRIO_0_SAB_INIT0_MASK;
+
+	mreqprio_1 = readl(&cdev->mreqprio_1) & MREQPRIO_1_DSS_MASK;
+
+	modena_init0_bw_fractional = readl(&bwlimiter->modena_init0_bw_fractional) &
+	                                   BW_LIMITER_BW_FRAC_MASK;
+
+	modena_init0_bw_integer = readl(&bwlimiter->modena_init0_bw_integer) &
+	                                BW_LIMITER_BW_INT_MASK;
+
+	modena_init0_watermark_0 = readl(&bwlimiter->modena_init0_watermark_0) &
+	                                 BW_LIMITER_BW_WATERMARK_MASK;
+
+	/* Setting MReq Priority of the DSS*/
+	mreqprio_0 |= 0x77;
+
+	/*
+	 * Set L3 Fast Configuration Register
+	 * Limiting bandwith for ARM core to 700 MBPS
+	 */
+	modena_init0_bw_fractional |= 0x10;
+	modena_init0_bw_integer |= 0x3;
+
+	writel(mreqprio_0, &cdev->mreqprio_0);
+	writel(mreqprio_1, &cdev->mreqprio_1);
+
+	writel(modena_init0_bw_fractional, &bwlimiter->modena_init0_bw_fractional);
+	writel(modena_init0_bw_integer, &bwlimiter->modena_init0_bw_integer);
+	writel(modena_init0_watermark_0, &bwlimiter->modena_init0_watermark_0);
+
 	return 0;
 }