Blob Blame History Raw
From c2cbdb9c9367388d72b50fae7a901f866350a92a Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 21 Apr 2021 13:12:48 +0200
Subject: [PATCH 07/11] drm/ast: AST2500 fixups
Patch-mainline: Never, temporary fixes until upstream resolution
References: bsc#1174416

A code snippet forward-ported from A-Speed downstream driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/ast/ast_drv.h  |    1 
 drivers/gpu/drm/ast/ast_main.c |    4 +
 drivers/gpu/drm/ast/ast_post.c |   84 +++++++++++++++++++++++++++--------------
 3 files changed, 61 insertions(+), 28 deletions(-)

--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -324,6 +324,7 @@ bool ast_is_vga_enabled(struct drm_devic
 void ast_post_gpu(struct drm_device *dev);
 u32 ast_mindwm(struct ast_private *ast, u32 r);
 void ast_moutdwm(struct ast_private *ast, u32 r, u32 v);
+void patch_ahb_ast2500(struct ast_private *ast);
 /* ast dp501 */
 void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
 bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -91,6 +91,10 @@ static void ast_detect_config_mode(struc
 	jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
 	jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
 	if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+		/* Patch AST2500 */
+		if ((dev->pdev->revision & 0xF0) == 0x40 && (jregd0 & 0xC0) == 0)
+			patch_ahb_ast2500(ast);
+
 		/* Double check it's actually working */
 		if ((dev->pdev->revision & 0xF0) >= 0x30) {
 			/* AST2400 and newer */
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -1842,13 +1842,20 @@ static void set_mpll_2500(struct ast_pri
 
 static void reset_mmc_2500(struct ast_private *ast)
 {
+	u32 data;
+
 	ast_moutdwm(ast, 0x1E78505C, 0x00000004);
 	ast_moutdwm(ast, 0x1E785044, 0x00000001);
 	ast_moutdwm(ast, 0x1E785048, 0x00004755);
 	ast_moutdwm(ast, 0x1E78504C, 0x00000013);
 	mdelay(100);
+	ast_moutdwm(ast, 0x1E78505c, 0x023FFFF3);
 	ast_moutdwm(ast, 0x1E785054, 0x00000077);
-	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
+	do {
+		ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
+		data = ast_mindwm(ast, 0x1E6E0000);
+	} while (data == 0);
+	ast_moutdwm(ast, 0x1E6E0034, 0x00020000);
 }
 
 static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table)
@@ -1913,7 +1920,7 @@ static void ddr4_init_2500(struct ast_pr
 
 	/* DDR PHY Setting */
 	ast_moutdwm(ast, 0x1E6E0200, 0x42492AAE);
-	ast_moutdwm(ast, 0x1E6E0204, 0x09002000);
+	ast_moutdwm(ast, 0x1E6E0204, 0x09002800);		/* modify at V1.3 */
 	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
 	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
 	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
@@ -2029,10 +2036,37 @@ static bool ast_dram_init_2500(struct as
 	/* Patch code */
 	data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
 	ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
+	/* Version Number */
+	data = ast_mindwm(ast, 0x1E6E0004);			/* add at V1.3 */
+	ast_moutdwm(ast, 0x1E6E0004, data | 0x08300000);	/* add at V1.3 */
+	ast_moutdwm(ast, 0x1E6E0088, 0x20161229);		/* add at V1.3 */
 
 	return true;
 }
 
+void patch_ahb_ast2500(struct ast_private *ast)
+{
+	u32	data;
+
+	/* Clear bus lock condition */
+	ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
+	ast_moutdwm(ast, 0x1e600084, 0x00010000);
+	ast_moutdwm(ast, 0x1e600088, 0x00000000);
+	ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+	data = ast_mindwm(ast, 0x1e6e2070);
+	if (data & 0x08000000) {			/* check fast reset */
+		ast_moutdwm(ast, 0x1E785004, 0x00000010);
+		ast_moutdwm(ast, 0x1E785008, 0x00004755);
+		ast_moutdwm(ast, 0x1E78500c, 0x00000033);
+		udelay(1000);
+	}
+	do {
+		ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+		data = ast_mindwm(ast, 0x1e6e2000);
+	}	while (data != 1);
+	ast_moutdwm(ast, 0x1e6e207c, 0x08000000);	/* clear fast reset */
+}
+
 void ast_post_chip_2500(struct drm_device *dev)
 {
 	struct ast_private *ast = dev->dev_private;
@@ -2040,39 +2074,33 @@ void ast_post_chip_2500(struct drm_devic
 	u8 reg;
 
 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-	if ((reg & 0x80) == 0) {/* vga only */
+	if ((reg & 0xC0) == 0) {/* vga only */
 		/* Clear bus lock condition */
-		ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
-		ast_moutdwm(ast, 0x1e600084, 0x00010000);
-		ast_moutdwm(ast, 0x1e600088, 0x00000000);
-		ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
-		ast_write32(ast, 0xf004, 0x1e6e0000);
-		ast_write32(ast, 0xf000, 0x1);
-		ast_write32(ast, 0x12000, 0x1688a8a8);
-		while (ast_read32(ast, 0x12000) != 0x1)
-			;
-
-		ast_write32(ast, 0x10000, 0xfc600309);
-		while (ast_read32(ast, 0x10000) != 0x1)
-			;
+		patch_ahb_ast2500(ast);
+
+		/* Disable watchdog */
+		ast_moutdwm(ast, 0x1E78502C, 0x00000000);
+		ast_moutdwm(ast, 0x1E78504C, 0x00000000);
+
+		/* Reset USB port */
+		ast_moutdwm(ast, 0x1E6E2090, 0x20000000);
+		ast_moutdwm(ast, 0x1E6E2094, 0x00004000);
+		if (ast_mindwm(ast, 0x1E6E2070) & 0x00800000) {
+			ast_moutdwm(ast, 0x1E6E207C, 0x00800000);
+			mdelay(100);
+			ast_moutdwm(ast, 0x1E6E2070, 0x00800000);
+		}
+
+		/* Modify eSPI reset pin */
+		temp = ast_mindwm(ast, 0x1E6E2070);
+		if (temp & 0x02000000)
+			ast_moutdwm(ast, 0x1E6E207C, 0x00004000);
 
 		/* Slow down CPU/AHB CLK in VGA only mode */
 		temp = ast_read32(ast, 0x12008);
 		temp |= 0x73;
 		ast_write32(ast, 0x12008, temp);
 
-		/* Reset USB port to patch USB unknown device issue */
-		ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
-		temp  = ast_mindwm(ast, 0x1e6e2094);
-		temp |= 0x00004000;
-		ast_moutdwm(ast, 0x1e6e2094, temp);
-		temp  = ast_mindwm(ast, 0x1e6e2070);
-		if (temp & 0x00800000) {
-			ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
-			mdelay(100);
-			ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
-		}
-
 		if (!ast_dram_init_2500(ast))
 			DRM_ERROR("DRAM init failed !\n");