[PATCH] drivers/gpu/drm/ast: Support reading configuration values from device tree

Russell Currey ruscur at russell.cc
Tue Dec 20 07:40:45 UTC 2016


The ast driver configures a window to enable access into BMC memory space
in order to read some configuration registers.  If this window is
disabled, which it can be from the BMC side, the ast driver can't
function.  Closing this window is a necessity for security if a machine's
host side and BMC side are controlled by different parties; i.e. a cloud
provider offering machines "bare metal".

To work around this, enable reading these configuration values from the
device tree instead of through the window into BMC memory.  This enables
the driver to work when the window is closed; if the window is open, the
driver functions as usual regardless of whether it uses the device tree
or register accesses.

Signed-off-by: Russell Currey <ruscur at russell.cc>
---
This patch applies on top of my other patch
	"drivers/gpu/drm/ast: Fix infinite loop if read fails"
which was recently applied to drm-misc-fixes.
---
 drivers/gpu/drm/ast/ast_main.c | 46 ++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index f75c6421db62..9e362b4d913a 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -65,6 +65,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,
 
 static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 {
+	struct device_node *np = dev->pdev->dev.of_node;
 	struct ast_private *ast = dev->dev_private;
 	uint32_t data, jreg;
 	ast_open_key(ast);
@@ -140,10 +141,16 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->support_wide_screen = true;
 		else {
 			ast->support_wide_screen = false;
-			/* Read SCU7c (silicon revision register) */
-			ast_write32(ast, 0xf004, 0x1e6e0000);
-			ast_write32(ast, 0xf000, 0x1);
-			data = ast_read32(ast, 0x1207c);
+
+			if (!np || of_property_read_u32(np,
+							"ast,scu-revision-id",
+							&data)) {
+				/* Read SCU7c (silicon revision register) */
+				ast_write32(ast, 0xf004, 0x1e6e0000);
+				ast_write32(ast, 0xf000, 0x1);
+				data = ast_read32(ast, 0x1207c);
+			}
+
 			data &= 0x300;
 			if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
 				ast->support_wide_screen = true;
@@ -212,21 +219,24 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 
 static int ast_get_dram_info(struct drm_device *dev)
 {
+	struct device_node *np = dev->pdev->dev.of_node;
 	struct ast_private *ast = dev->dev_private;
 	uint32_t data, data2;
 	uint32_t denum, num, div, ref_pll;
 
-	ast_write32(ast, 0xf004, 0x1e6e0000);
-	ast_write32(ast, 0xf000, 0x1);
+	if (!np || of_property_read_u32(np, "ast,mcr-configuration", &data)) {
+		ast_write32(ast, 0xf004, 0x1e6e0000);
+		ast_write32(ast, 0xf000, 0x1);
 
+		ast_write32(ast, 0x10000, 0xfc600309);
 
-	ast_write32(ast, 0x10000, 0xfc600309);
-
-	do {
-		if (pci_channel_offline(dev->pdev))
-			return -EIO;
-	} while (ast_read32(ast, 0x10000) != 0x01);
-	data = ast_read32(ast, 0x10004);
+		/* poll until unlocked */
+		do {
+			if (pci_channel_offline(dev->pdev))
+				return -EIO;
+		} while (ast_read32(ast, 0x10000) != 0x01);
+		data = ast_read32(ast, 0x10004);
+	}
 
 	if (data & 0x40)
 		ast->dram_bus_width = 16;
@@ -267,8 +277,14 @@ static int ast_get_dram_info(struct drm_device *dev)
 		}
 	}
 
-	data = ast_read32(ast, 0x10120);
-	data2 = ast_read32(ast, 0x10170);
+	if (!np || of_property_read_u32(np, "ast,mcr-scu-mpll", &data)) {
+		data = ast_read32(ast, 0x10120);
+		data2 = ast_read32(ast, 0x10170);
+	} else {
+		/* always 0 for AST2400 and AST2500 */
+		data2 = 0;
+	}
+
 	if (data2 & 0x2000)
 		ref_pll = 14318;
 	else
-- 
2.11.0



More information about the dri-devel mailing list