|
@@ -62,13 +62,84 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
|
|
|
|
+{
|
|
|
|
+ struct device_node *np = dev->pdev->dev.of_node;
|
|
|
|
+ struct ast_private *ast = dev->dev_private;
|
|
|
|
+ uint32_t data, jregd0, jregd1;
|
|
|
|
+
|
|
|
|
+ /* Defaults */
|
|
|
|
+ ast->config_mode = ast_use_defaults;
|
|
|
|
+ *scu_rev = 0xffffffff;
|
|
|
|
+
|
|
|
|
+ /* Check if we have device-tree properties */
|
|
|
|
+ if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
|
|
|
|
+ scu_rev)) {
|
|
|
|
+ /* We do, disable P2A access */
|
|
|
|
+ ast->config_mode = ast_use_dt;
|
|
|
|
+ DRM_INFO("Using device-tree for configuration\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Not all families have a P2A bridge */
|
|
|
|
+ if (dev->pdev->device != PCI_CHIP_AST2000)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
|
|
|
|
+ * is disabled. We force using P2A if VGA only mode bit
|
|
|
|
+ * is set D[7]
|
|
|
|
+ */
|
|
|
|
+ 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)) {
|
|
|
|
+ /* Double check it's actually working */
|
|
|
|
+ data = ast_read32(ast, 0xf004);
|
|
|
|
+ if (data != 0xFFFFFFFF) {
|
|
|
|
+ /* P2A works, grab silicon revision */
|
|
|
|
+ ast->config_mode = ast_use_p2a;
|
|
|
|
+
|
|
|
|
+ DRM_INFO("Using P2A bridge for configuration\n");
|
|
|
|
+
|
|
|
|
+ /* Read SCU7c (silicon revision register) */
|
|
|
|
+ ast_write32(ast, 0xf004, 0x1e6e0000);
|
|
|
|
+ ast_write32(ast, 0xf000, 0x1);
|
|
|
|
+ *scu_rev = ast_read32(ast, 0x1207c);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* We have a P2A bridge but it's disabled */
|
|
|
|
+ DRM_INFO("P2A bridge disabled, using default configuration\n");
|
|
|
|
+}
|
|
|
|
|
|
static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
{
|
|
{
|
|
struct ast_private *ast = dev->dev_private;
|
|
struct ast_private *ast = dev->dev_private;
|
|
- uint32_t data, jreg;
|
|
|
|
|
|
+ uint32_t jreg, scu_rev;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If VGA isn't enabled, we need to enable now or subsequent
|
|
|
|
+ * access to the scratch registers will fail. We also inform
|
|
|
|
+ * our caller that it needs to POST the chip
|
|
|
|
+ * (Assumption: VGA not enabled -> need to POST)
|
|
|
|
+ */
|
|
|
|
+ if (!ast_is_vga_enabled(dev)) {
|
|
|
|
+ ast_enable_vga(dev);
|
|
|
|
+ DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
|
|
|
|
+ *need_post = true;
|
|
|
|
+ } else
|
|
|
|
+ *need_post = false;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* Enable extended register access */
|
|
|
|
+ ast_enable_mmio(dev);
|
|
ast_open_key(ast);
|
|
ast_open_key(ast);
|
|
|
|
|
|
|
|
+ /* Find out whether P2A works or whether to use device-tree */
|
|
|
|
+ ast_detect_config_mode(dev, &scu_rev);
|
|
|
|
+
|
|
|
|
+ /* Identify chipset */
|
|
if (dev->pdev->device == PCI_CHIP_AST1180) {
|
|
if (dev->pdev->device == PCI_CHIP_AST1180) {
|
|
ast->chip = AST1100;
|
|
ast->chip = AST1100;
|
|
DRM_INFO("AST 1180 detected\n");
|
|
DRM_INFO("AST 1180 detected\n");
|
|
@@ -80,12 +151,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
ast->chip = AST2300;
|
|
ast->chip = AST2300;
|
|
DRM_INFO("AST 2300 detected\n");
|
|
DRM_INFO("AST 2300 detected\n");
|
|
} else if (dev->pdev->revision >= 0x10) {
|
|
} else if (dev->pdev->revision >= 0x10) {
|
|
- uint32_t data;
|
|
|
|
- ast_write32(ast, 0xf004, 0x1e6e0000);
|
|
|
|
- ast_write32(ast, 0xf000, 0x1);
|
|
|
|
-
|
|
|
|
- data = ast_read32(ast, 0x1207c);
|
|
|
|
- switch (data & 0x0300) {
|
|
|
|
|
|
+ switch (scu_rev & 0x0300) {
|
|
case 0x0200:
|
|
case 0x0200:
|
|
ast->chip = AST1100;
|
|
ast->chip = AST1100;
|
|
DRM_INFO("AST 1100 detected\n");
|
|
DRM_INFO("AST 1100 detected\n");
|
|
@@ -110,26 +176,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * If VGA isn't enabled, we need to enable now or subsequent
|
|
|
|
- * access to the scratch registers will fail. We also inform
|
|
|
|
- * our caller that it needs to POST the chip
|
|
|
|
- * (Assumption: VGA not enabled -> need to POST)
|
|
|
|
- */
|
|
|
|
- if (!ast_is_vga_enabled(dev)) {
|
|
|
|
- ast_enable_vga(dev);
|
|
|
|
- ast_enable_mmio(dev);
|
|
|
|
- DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
|
|
|
|
- *need_post = true;
|
|
|
|
- } else
|
|
|
|
- *need_post = false;
|
|
|
|
-
|
|
|
|
- /* Check P2A Access */
|
|
|
|
- ast->DisableP2A = true;
|
|
|
|
- data = ast_read32(ast, 0xf004);
|
|
|
|
- if (data != 0xFFFFFFFF)
|
|
|
|
- ast->DisableP2A = false;
|
|
|
|
-
|
|
|
|
/* Check if we support wide screen */
|
|
/* Check if we support wide screen */
|
|
switch (ast->chip) {
|
|
switch (ast->chip) {
|
|
case AST1180:
|
|
case AST1180:
|
|
@@ -146,17 +192,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
ast->support_wide_screen = true;
|
|
ast->support_wide_screen = true;
|
|
else {
|
|
else {
|
|
ast->support_wide_screen = false;
|
|
ast->support_wide_screen = false;
|
|
- if (ast->DisableP2A == false) {
|
|
|
|
- /* 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;
|
|
|
|
- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
|
|
|
|
- ast->support_wide_screen = true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (ast->chip == AST2300 &&
|
|
|
|
+ (scu_rev & 0x300) == 0x0) /* ast1300 */
|
|
|
|
+ ast->support_wide_screen = true;
|
|
|
|
+ if (ast->chip == AST2400 &&
|
|
|
|
+ (scu_rev & 0x300) == 0x100) /* ast1400 */
|
|
|
|
+ ast->support_wide_screen = true;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -220,85 +261,102 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
|
|
|
|
|
static int ast_get_dram_info(struct drm_device *dev)
|
|
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;
|
|
struct ast_private *ast = dev->dev_private;
|
|
- uint32_t data, data2;
|
|
|
|
- uint32_t denum, num, div, ref_pll;
|
|
|
|
|
|
+ uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
|
|
|
|
+ uint32_t denum, num, div, ref_pll, dsel;
|
|
|
|
|
|
- if (ast->DisableP2A)
|
|
|
|
- {
|
|
|
|
|
|
+ switch (ast->config_mode) {
|
|
|
|
+ case ast_use_dt:
|
|
|
|
+ /*
|
|
|
|
+ * If some properties are missing, use reasonable
|
|
|
|
+ * defaults for AST2400
|
|
|
|
+ */
|
|
|
|
+ if (of_property_read_u32(np, "aspeed,mcr-configuration",
|
|
|
|
+ &mcr_cfg))
|
|
|
|
+ mcr_cfg = 0x00000577;
|
|
|
|
+ if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
|
|
|
|
+ &mcr_scu_mpll))
|
|
|
|
+ mcr_scu_mpll = 0x000050C0;
|
|
|
|
+ if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
|
|
|
|
+ &mcr_scu_strap))
|
|
|
|
+ mcr_scu_strap = 0;
|
|
|
|
+ break;
|
|
|
|
+ case ast_use_p2a:
|
|
|
|
+ ast_write32(ast, 0xf004, 0x1e6e0000);
|
|
|
|
+ ast_write32(ast, 0xf000, 0x1);
|
|
|
|
+ mcr_cfg = ast_read32(ast, 0x10004);
|
|
|
|
+ mcr_scu_mpll = ast_read32(ast, 0x10120);
|
|
|
|
+ mcr_scu_strap = ast_read32(ast, 0x10170);
|
|
|
|
+ break;
|
|
|
|
+ case ast_use_defaults:
|
|
|
|
+ default:
|
|
ast->dram_bus_width = 16;
|
|
ast->dram_bus_width = 16;
|
|
ast->dram_type = AST_DRAM_1Gx16;
|
|
ast->dram_type = AST_DRAM_1Gx16;
|
|
ast->mclk = 396;
|
|
ast->mclk = 396;
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- ast_write32(ast, 0xf004, 0x1e6e0000);
|
|
|
|
- ast_write32(ast, 0xf000, 0x1);
|
|
|
|
- data = ast_read32(ast, 0x10004);
|
|
|
|
-
|
|
|
|
- if (data & 0x40)
|
|
|
|
- ast->dram_bus_width = 16;
|
|
|
|
- else
|
|
|
|
- ast->dram_bus_width = 32;
|
|
|
|
|
|
|
|
- if (ast->chip == AST2300 || ast->chip == AST2400) {
|
|
|
|
- switch (data & 0x03) {
|
|
|
|
- case 0:
|
|
|
|
- ast->dram_type = AST_DRAM_512Mx16;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- case 1:
|
|
|
|
- ast->dram_type = AST_DRAM_1Gx16;
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- ast->dram_type = AST_DRAM_2Gx16;
|
|
|
|
- break;
|
|
|
|
- case 3:
|
|
|
|
- ast->dram_type = AST_DRAM_4Gx16;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- switch (data & 0x0c) {
|
|
|
|
- case 0:
|
|
|
|
- case 4:
|
|
|
|
- ast->dram_type = AST_DRAM_512Mx16;
|
|
|
|
- break;
|
|
|
|
- case 8:
|
|
|
|
- if (data & 0x40)
|
|
|
|
- ast->dram_type = AST_DRAM_1Gx16;
|
|
|
|
- else
|
|
|
|
- ast->dram_type = AST_DRAM_512Mx32;
|
|
|
|
- break;
|
|
|
|
- case 0xc:
|
|
|
|
- ast->dram_type = AST_DRAM_1Gx32;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (mcr_cfg & 0x40)
|
|
|
|
+ ast->dram_bus_width = 16;
|
|
|
|
+ else
|
|
|
|
+ ast->dram_bus_width = 32;
|
|
|
|
|
|
- data = ast_read32(ast, 0x10120);
|
|
|
|
- data2 = ast_read32(ast, 0x10170);
|
|
|
|
- if (data2 & 0x2000)
|
|
|
|
- ref_pll = 14318;
|
|
|
|
- else
|
|
|
|
- ref_pll = 12000;
|
|
|
|
-
|
|
|
|
- denum = data & 0x1f;
|
|
|
|
- num = (data & 0x3fe0) >> 5;
|
|
|
|
- data = (data & 0xc000) >> 14;
|
|
|
|
- switch (data) {
|
|
|
|
- case 3:
|
|
|
|
- div = 0x4;
|
|
|
|
|
|
+ if (ast->chip == AST2300 || ast->chip == AST2400) {
|
|
|
|
+ switch (mcr_cfg & 0x03) {
|
|
|
|
+ case 0:
|
|
|
|
+ ast->dram_type = AST_DRAM_512Mx16;
|
|
break;
|
|
break;
|
|
- case 2:
|
|
|
|
|
|
+ default:
|
|
case 1:
|
|
case 1:
|
|
- div = 0x2;
|
|
|
|
|
|
+ ast->dram_type = AST_DRAM_1Gx16;
|
|
break;
|
|
break;
|
|
- default:
|
|
|
|
- div = 0x1;
|
|
|
|
|
|
+ case 2:
|
|
|
|
+ ast->dram_type = AST_DRAM_2Gx16;
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ ast->dram_type = AST_DRAM_4Gx16;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ switch (mcr_cfg & 0x0c) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 4:
|
|
|
|
+ ast->dram_type = AST_DRAM_512Mx16;
|
|
|
|
+ break;
|
|
|
|
+ case 8:
|
|
|
|
+ if (mcr_cfg & 0x40)
|
|
|
|
+ ast->dram_type = AST_DRAM_1Gx16;
|
|
|
|
+ else
|
|
|
|
+ ast->dram_type = AST_DRAM_512Mx32;
|
|
|
|
+ break;
|
|
|
|
+ case 0xc:
|
|
|
|
+ ast->dram_type = AST_DRAM_1Gx32;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (mcr_scu_strap & 0x2000)
|
|
|
|
+ ref_pll = 14318;
|
|
|
|
+ else
|
|
|
|
+ ref_pll = 12000;
|
|
|
|
+
|
|
|
|
+ denum = mcr_scu_mpll & 0x1f;
|
|
|
|
+ num = (mcr_scu_mpll & 0x3fe0) >> 5;
|
|
|
|
+ dsel = (mcr_scu_mpll & 0xc000) >> 14;
|
|
|
|
+ switch (dsel) {
|
|
|
|
+ case 3:
|
|
|
|
+ div = 0x4;
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ case 1:
|
|
|
|
+ div = 0x2;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ div = 0x1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|