[PATCH] drm/ast: Fix NO EDID on DP501

2022-08-18 Thread KuoHsiang Chou
1. Corrected the definition of AST_DP501_PNP_CONNECTED.
2. Created the Base address for DP501 MCU.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_dp501.c | 10 --
 drivers/gpu/drm/ast/ast_drv.h   |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 4f75a9efb..4693d68ca 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -180,7 +180,10 @@ void ast_set_dp501_video_output(struct drm_device *dev, u8 
mode)

 static u32 get_fw_base(struct ast_private *ast)
 {
-   return ast_mindwm(ast, 0x1e6e2104) & 0x7fff;
+   if (ast->chip == AST2500)
+   return ast_mindwm(ast, 0x1e6e2104) & 0xfffe;
+   else
+   return ast_mindwm(ast, 0x1e6e2104) & 0x7fff;
 }

 bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
@@ -257,7 +260,10 @@ static bool ast_launch_m68k(struct drm_device *dev)
ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);

/* Launch FW */
-   ast_moutdwm(ast, 0x1e6e2104, 0x8000 + boot_address);
+   if (ast->chip == AST2500)
+   ast_moutdwm(ast, 0x1e6e2104, boot_address | 0x0001);
+   else
+   ast_moutdwm(ast, 0x1e6e2104, boot_address | 0x8000);
ast_moutdwm(ast, 0x1e6e2100, 1);

/* Update Scratch */
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 2e44b971c..81e1317d3 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -358,7 +358,7 @@ int ast_mode_config_init(struct ast_private *ast);

 #define AST_DP501_FW_VERSION_MASK  GENMASK(7, 4)
 #define AST_DP501_FW_VERSION_1 BIT(4)
-#define AST_DP501_PNP_CONNECTEDBIT(1)
+#define AST_DP501_PNP_CONNECTEDBIT(0)

 #define AST_DP501_DEFAULT_DCLK 65


base-commit: 8953e41fa70d4507c6f5508e030347f7eda3ba8a
--
2.27.0



[PATCH v1] drm/ast: Fixed the casting issue reported by sparse

2022-06-23 Thread KuoHsiang Chou
V1:
1.Fixed sparse:cast truncates bits form constant value ()cast
  truncates bits from constant value (ff00 becomes 0)

Reported-by: kernel test robot 
Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_dp.c  | 8 
 drivers/gpu/drm/ast/ast_drv.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
index f573d5824..2c71b8eef 100644
--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -34,7 +34,7 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
 */
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
-   (u8) ~ASTDP_EDID_READ_POINTER_MASK, 
(u8) i);
+   ASTDP_AND_CLEAR_MASK, (u8) i);
j = 0;

/*
@@ -274,8 +274,8 @@ void ast_dp_set_mode(struct drm_crtc *crtc, struct 
ast_vbios_mode_info *vbios_mo
 * CRE1[7:0]: MISC1 (default: 0x00)
 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
 */
-   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
~ASTDP_CLEAR_MASK,
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, 
ASTDP_AND_CLEAR_MASK,
ASTDP_MISC0_24bpp);
-   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
~ASTDP_CLEAR_MASK, ASTDP_MISC1);
-   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) 
~ASTDP_CLEAR_MASK, ModeIdx);
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, 
ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, 
ASTDP_AND_CLEAR_MASK, ModeIdx);
 }
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index a34db4380..2e44b971c 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -433,7 +433,7 @@ int ast_mode_config_init(struct ast_private *ast);
  */
 #define ASTDP_MISC0_24bpp  BIT(5)
 #define ASTDP_MISC10
-#define ASTDP_CLEAR_MASK   GENMASK(7, 0)
+#define ASTDP_AND_CLEAR_MASK   0x00

 /*
  * ASTDP resoultion table:

base-commit: ab3bfa333f25d26bb8bf414419f9a2e6a46a141f
--
2.27.0



[PATCH v5] drm/ast: Create the driver for ASPEED proprietory Display-Port

2022-06-07 Thread KuoHsiang Chou
V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP // ast_dp_launch()
2. Check if DP-MCU FW has loaded// 
ast_dp_launch()
3. Read EDID// ast_dp_read_edid()
4. Resolution switch// ast_dp_SetOutput()

V3:
1. Remove unneeded semicolon.
2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
   git://anongit.freedesktop.org/drm/drm-misc
3. Resolve auto build test WARNINGs on V1 patch.

V4:
1. Sync code-base with kernel 5.17_rc6
2. Remove the define of DPControlPower, because DP chips need to be
   powered on to be used.
3. Remove the switches of PHY and Display from EDID procedure.
4. Revise increaing delay to fixed delay, because this version kernel
   doesn't detect minitor consistenntly.
5. Create clean-up code used for reset of power state on errors with
   -EIO manner.
6. Revise the DP detection by TX type and its DP-FW status during
   booting and resume.
7. Correct the CamelCase Style.
8. Use register reading while needing, and remove to hold full
   register.
9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
10.Correct typo
11.Remove the duplicated copy of TX definition.
12.Use EDID_LENGTH as the constant of 128.

V5:
1.Fixed sparse:cast truncates bits form constant value ()cast
  truncates bits from constant value (ff00 becomes 0)

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 282 +
 drivers/gpu/drm/ast/ast_drv.h  | 115 ++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c | 124 ++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 524 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 0..1ae12c407
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou 
+
+#include 
+#include 
+#include 
+#include "ast_drv.h"
+
+int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+   struct ast_private *ast = to_ast_private(dev);
+   u8 i = 0, j = 0;
+
+   /*
+* CRD1[b5]: DP MCU FW is executing
+* CRDC[b0]: DP link success
+* CRDF[b0]: DP HPD
+* CRE5[b0]: Host reading EDID process is done
+*/
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
ASTDP_MCU_FW_EXECUTING) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
ASTDP_LINK_SUCCESS) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) 
&&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+   
ASTDP_HOST_EDID_READ_DONE_MASK))) {
+   goto err_astdp_edid_not_ready;
+   }
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
~ASTDP_HOST_EDID_READ_DONE_MASK,
+   0x00);
+
+   for (i = 0; i < 32; i++) {
+   /*
+* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
+*/
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+   ASTDP_AND_CLEAR_MASK, (u8) i);
+   j = 0;
+
+   /*
+* CRD7[b0]: valid flag for EDID
+* CRD6[b0]: mirror read pointer for EDID
+*/
+

[PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

2022-04-28 Thread KuoHsiang Chou
V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP // ast_dp_launch()
2. Check if DP-MCU FW has loaded// 
ast_dp_launch()
3. Read EDID// ast_dp_read_edid()
4. Resolution switch// ast_dp_SetOutput()

V3:
1. Remove unneeded semicolon.
2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
   git://anongit.freedesktop.org/drm/drm-misc
3. Resolve auto build test WARNINGs on V1 patch.

V4:
1. Sync code-base with kernel 5.17_rc6
2. Remove the define of DPControlPower, because DP chips need to be
   powered on to be used.
3. Remove the switches of PHY and Display from EDID procedure.
4. Revise increaing delay to fixed delay, because this version kernel
   doesn't detect minitor consistenntly.
5. Create clean-up code used for reset of power state on errors with
   -EIO manner.
6. Revise the DP detection by TX type and its DP-FW status during
   booting and resume.
7. Correct the CamelCase Style.
8. Use register reading while needing, and remove to hold full
   register.
9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
10.Correct typo
11.Remove the duplicated copy of TX definition.
12.Use EDID_LENGTH as the constant of 128.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 282 +
 drivers/gpu/drm/ast/ast_drv.h  | 115 ++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c | 124 ++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 524 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 0..4551bc8a3
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou 
+
+#include 
+#include 
+#include 
+#include "ast_drv.h"
+
+int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+   struct ast_private *ast = to_ast_private(dev);
+   u8 i = 0, j = 0;
+
+   /*
+* CRD1[b5]: DP MCU FW is executing
+* CRDC[b0]: DP link success
+* CRDF[b0]: DP HPD
+* CRE5[b0]: Host reading EDID process is done
+*/
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
ASTDP_MCU_FW_EXECUTING) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
ASTDP_LINK_SUCCESS) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) 
&&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+   
ASTDP_HOST_EDID_READ_DONE_MASK))) {
+   goto err_astdp_edid_not_ready;
+   }
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
~ASTDP_HOST_EDID_READ_DONE_MASK,
+   0x00);
+
+   for (i = 0; i < 32; i++) {
+   /*
+* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
+*/
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+   (u8) ~ASTDP_EDID_READ_POINTER_MASK, 
(u8) i);
+   j = 0;
+
+   /*
+* CRD7[b0]: valid flag for EDID
+* CRD6[b0]: mirror read pointer for EDID
+*/
+   while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+   ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+ 

[PATCH] drm/ast: Create threshold values for AST2600

2022-01-17 Thread KuoHsiang Chou
The threshold value is used for AST2600 only.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_mode.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 1c7a57a03..7f2e248a6 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -471,7 +471,10 @@ static void ast_set_color_reg(struct ast_private *ast,
 static void ast_set_crtthd_reg(struct ast_private *ast)
 {
/* Set Threshold */
-   if (ast->chip == AST2300 || ast->chip == AST2400 ||
+   if (ast->chip == AST2600) {
+   ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0);
+   ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0);
+   } else if (ast->chip == AST2300 || ast->chip == AST2400 ||
ast->chip == AST2500) {
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
--
2.27.0



[PATCH v3] drm/ast: Create the driver for ASPEED proprietory Display-Port

2022-01-04 Thread KuoHsiang Chou
V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP // ast_dp_launch()
2. Check if DP-MCU FW has loaded// 
ast_dp_launch()
3. Read EDID// ast_dp_read_edid()
4. Resolution switch// ast_dp_SetOutput()

V3:
1. Remove unneeded semicolon.
2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
   git://anongit.freedesktop.org/drm/drm-misc
3. Resolve auto build test WARNINGs on V1 patch.

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 292 +
 drivers/gpu/drm/ast/ast_drv.h  | 127 ++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c |  46 +-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 468 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 0..1daa25d92
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou 
+
+#include 
+#include 
+#include 
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+   struct ast_private *ast = to_ast_private(dev);
+   u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+   u8 bDPState_Change = false;
+
+   // Check DP power off or not.
+   if (ast->ASTDP_State & AST_DP_PHY_SLEEP) {
+   // DP power on
+   ast_dp_PowerOnOff(dev, AST_DP_POWER_ON);
+   bDPState_Change = true;
+   }
+#endif
+
+   /*
+* CRD1[b5]: DP MCU FW is executing
+* CRDC[b0]: DP link success
+* CRDF[b0]: DP HPD
+* CRE5[b0]: Host reading EDID process is done
+*/
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
ASTDP_MCU_FW_EXECUTING) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
ASTDP_LINK_SUCCESS) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) 
&&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+   
ASTDP_HOST_EDID_READ_DONE_MASK))) {
+#ifdef DPControlPower
+   // Set back power off
+   if (bDPState_Change)
+   ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+   return false;
+   }
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
~ASTDP_HOST_EDID_READ_DONE_MASK,
+   0x00);
+
+   for (i = 0; i < 32; i++) {
+   /*
+* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
+*/
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+   (u8) ~ASTDP_EDID_READ_POINTER_MASK, 
(u8) i);
+   j = 0;
+
+   /*
+* CRD7[b0]: valid flag for EDID
+* CRD6[b0]: mirror read pointer for EDID
+*/
+   while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+   ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
+   ASTDP_EDID_READ_POINTER_MASK) 
!= i)) {
+   mdelay(j+1);
+
+   if (!(ast_get

[PATCH] drm/ast: Enable the supporting of wide screen on AST2600

2021-12-29 Thread KuoHsiang Chou
Enable the supporting of wide sscreen on AST2600, so that the resolution
of 16:9 and 16:10 are able to be selected on Display Settings.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 9f25fa2c8..1113ee1cb 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -209,6 +209,8 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
if (ast->chip == AST2500 &&
scu_rev == 0x100)   /* ast2510 */
ast->support_wide_screen = true;
+   if (ast->chip == AST2600)   /* ast2600 */
+   ast->support_wide_screen = true;
}
break;
}
--
2.27.0



[PATCH v2] drm/ast: Create the driver for ASPEED proprietory Display-Port

2021-12-27 Thread KuoHsiang Chou
V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP // ast_dp_launch()
2. Check if DP-MCU FW has loaded// 
ast_dp_launch()
3. Read EDID// ast_dp_read_edid()
4. Resolution switch// ast_dp_SetOutput()

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 292 +
 drivers/gpu/drm/ast/ast_drv.h  | 127 ++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c |  46 +-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 468 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 0..4ac719ab0
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou 
+
+#include 
+#include 
+#include 
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+   struct ast_private *ast = to_ast_private(dev);
+   u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+   u8 bDPState_Change = false;
+
+   // Check DP power off or not.
+   if (ast->ASTDP_State & AST_DP_PHY_SLEEP) {
+   // DP power on
+   ast_dp_PowerOnOff(dev, AST_DP_POWER_ON);
+   bDPState_Change = true;
+   }
+#endif
+
+   /*
+* CRD1[b5]: DP MCU FW is executing
+* CRDC[b0]: DP link success
+* CRDF[b0]: DP HPD
+* CRE5[b0]: Host reading EDID process is done
+*/
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
ASTDP_MCU_FW_EXECUTING) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
ASTDP_LINK_SUCCESS) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) 
&&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+   
ASTDP_HOST_EDID_READ_DONE_MASK))) {
+#ifdef DPControlPower
+   // Set back power off
+   if (bDPState_Change)
+   ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+   return false;
+   }
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
~ASTDP_HOST_EDID_READ_DONE_MASK,
+   0x00);
+
+   for (i = 0; i < 32; i++) {
+   /*
+* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
+*/
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+   (u8) ~ASTDP_EDID_READ_POINTER_MASK, 
(u8) i);
+   j = 0;
+
+   /*
+* CRD7[b0]: valid flag for EDID
+* CRD6[b0]: mirror read pointer for EDID
+*/
+   while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+   ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
+   ASTDP_EDID_READ_POINTER_MASK) 
!= i)) {
+   mdelay(j+1);
+
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xD1,
+   ASTDP_MCU_FW_EXECUTING) 
&&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xDC,
+ 

[PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port

2021-11-22 Thread KuoHsiang Chou
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 286 +
 drivers/gpu/drm/ast/ast_drv.h  |  13 ++
 drivers/gpu/drm/ast/ast_main.c |   7 +-
 drivers/gpu/drm/ast/ast_mode.c |  50 +-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 353 insertions(+), 9 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 438a2d05b..9bd0756e0 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o 
ast_dp.o
 
 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 0..537eaf4fa
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: KuoHsiang Chou 
+ */
+
+#include 
+#include 
+#include 
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+   struct ast_private *ast = to_ast_private(dev);
+   u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+   u8 bDPState_Change = false;
+
+   // Check DP power off or not.
+   if (ast->ASTDP_State & 0x10) {
+   // DP power on
+   ast_dp_PowerOnOff(dev, 1);
+   bDPState_Change = true;
+   }
+#endif
+
+   /*
+* CRD1[b5]: DP MCU FW is executing
+* CRDC[b0]: DP link success
+* CRDF[b0]: DP HPD
+* CRE5[b0]: Host reading EDID process is done
+*/
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x01))) {
+#ifdef DPControlPower
+   // Set back power off
+   if (bDPState_Change)
+   ast_dp_PowerOnOff(dev, 0);
+#endif
+   return false;
+   }
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x00);
+
+   for (i = 0; i < 32; i++) {
+   /*
+* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
range: 0~64
+*/
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, 0x00, (u8) 
i);
+   j = 0;
+
+   /*
+* CRD7[b0]: valid flag for EDID
+* CRD6[b0]: mirror read pointer for EDID
+*/
+   while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, 
0x01) != 0x01) ||
+   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, 
0xFF) != i)) {
+   mdelay(j+1);
+
+   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xD1, 0x20) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xDC, 0x01) &&
+   ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xDF, 0x01))) {
+   ast_set_index_reg_mask(ast, AS

[PATCH] drm/ast: Atomic CR/SR reg R/W

2021-09-17 Thread KuoHsiang Chou
1. Avoid IO-index racing
2. IO-index racing happened on resolustion switching
   and mouse moving at the same time
3. System hung while IO-index racing occurred.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_main.c | 48 +-
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 79a361867..1d8fa70c5 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -41,28 +41,52 @@ void ast_set_index_reg_mask(struct ast_private *ast,
uint32_t base, uint8_t index,
uint8_t mask, uint8_t val)
 {
-   u8 tmp;
-   ast_io_write8(ast, base, index);
-   tmp = (ast_io_read8(ast, base + 1) & mask) | val;
-   ast_set_index_reg(ast, base, index, tmp);
+   uint16_t volatile usData;
+   uint8_t  volatile jData;
+
+   do {
+   ast_io_write8(ast, base, index);
+   usData = ast_io_read16(ast, base);
+   } while ((uint8_t)(usData) != index);
+
+   jData  = (uint8_t)(usData >> 8);
+   jData &= mask;
+   jData |= val;
+   usData = ((uint16_t) jData << 8) | (uint16_t) index;
+   ast_io_write16(ast, base, usData);
 }

 uint8_t ast_get_index_reg(struct ast_private *ast,
  uint32_t base, uint8_t index)
 {
-   uint8_t ret;
-   ast_io_write8(ast, base, index);
-   ret = ast_io_read8(ast, base + 1);
-   return ret;
+   uint16_t volatile usData;
+   uint8_t  volatile jData;
+
+   do {
+   ast_io_write8(ast, base, index);
+   usData = ast_io_read16(ast, base);
+   } while ((uint8_t)(usData) != index);
+
+   jData  = (uint8_t)(usData >> 8);
+
+   return jData;
 }

 uint8_t ast_get_index_reg_mask(struct ast_private *ast,
   uint32_t base, uint8_t index, uint8_t mask)
 {
-   uint8_t ret;
-   ast_io_write8(ast, base, index);
-   ret = ast_io_read8(ast, base + 1) & mask;
-   return ret;
+   uint16_t volatile usData;
+   uint8_t  volatile jData;
+
+   do {
+   ast_io_write8(ast, base, index);
+   usData = ast_io_read16(ast, base);
+   } while ((uint8_t)(usData) != index);
+
+   jData  = (uint8_t)(usData >> 8);
+   jData &= mask;
+
+   return jData;
 }

 static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
--
2.18.4



[PATCH v5] drm/ast: Disable fast reset after DRAM initial

2021-07-09 Thread KuoHsiang Chou
[Bug][AST2500]

V1:
When AST2500 acts as stand-alone VGA so that DRAM and DVO initialization
have to be achieved by VGA driver with P2A (PCI to AHB) enabling.
However, HW suggests disable Fast reset mode after DRAM initializaton,
because fast reset mode is mainly designed for ARM ICE debugger.
Once Fast reset is checked as enabling, WDT (Watch Dog Timer) should be
first enabled to avoid system deadlock before disable fast reset mode.

V2:
Use to_pci_dev() to get revision of PCI configuration.

V3:
If SCU00 is not unlocked, just enter its password again.
It is unnecessary to clear AHB lock condition and restore WDT default
setting again, before Fast-reset clearing.

V4:
repatch after "error : could not build fake ancestor" resolved.

V5:
Since CVE_2019_6260 item3, Most of AST2500 have disabled P2A(PCIe to AMBA).
However, for backward compatibility, some patches about P2A, such as items
of v5.2 and v5.3, are considered to be upstreamed with comments.
1. Add define macro to improve source readability.
ast_drv.h, ast_main.c, ast_post.c
2. Add comment about "Fast restet" is enabled for ARM-ICE debugger
ast_post.c
3. Add comment about Reset USB port to patch USB unknown device issue
ast_post.c

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  |  6 +++
 drivers/gpu/drm/ast/ast_main.c |  5 ++
 drivers/gpu/drm/ast/ast_post.c | 91 --
 3 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 911f9f414..39ca338eb 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -337,6 +337,11 @@ int ast_mode_config_init(struct ast_private *ast);
 #define AST_DP501_LINKRATE 0xf014
 #define AST_DP501_EDID_DATA0xf020

+/* Define for Soc scratched reg */
+#define AST_VRAM_INIT_STATUS_MASK  GENMASK(7, 6)
+//#define AST_VRAM_INIT_BY_BMC BIT(7)
+//#define AST_VRAM_INIT_READY  BIT(6)
+
 int ast_mm_init(struct ast_private *ast);

 /* ast post */
@@ -346,6 +351,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
 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 ast_patch_ahb_2500(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);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 2aff2e6cf..79a361867 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -97,6 +97,11 @@ static void ast_detect_config_mode(struct drm_device *dev, 
u32 *scu_rev)
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 (((pdev->revision & 0xF0) == 0x40)
+   && ((jregd0 & AST_VRAM_INIT_STATUS_MASK) == 0))
+   ast_patch_ahb_2500(ast);
+
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
if ((data != 0x) && (data != 0x00)) {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 0607658dd..b5d92f652 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2028,6 +2028,40 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
 }

+void ast_patch_ahb_2500(struct ast_private *ast)
+{
+   u32 data;
+
+   /* Clear bus lock condition */
+   ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
+   ast_moutdwm(ast, 0x1e600084, 0x0001);
+   ast_moutdwm(ast, 0x1e600088, 0x);
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2070);
+   if (data & 0x0800) {/* 
check fast reset */
+   /*
+* If "Fast restet" is enabled for ARM-ICE debugger,
+* then WDT needs to enable, that
+* WDT04 is WDT#1 Reload reg.
+* WDT08 is WDT#1 counter restart reg to avoid system deadlock
+* WDT0C is WDT#1 control reg
+*  [6:5]:= 01:Full chip
+*  [4]:= 1:1MHz clock source
+*  [1]:= 1:WDT will be cleeared and disabled after timeout 
occurs
+*  [0]:= 1:WDT enable
+*/
+   ast_moutdwm(ast, 0x1E785004, 0x0010);
+   ast_moutdwm(ast, 0x1E785008, 0x4755);
+   ast_moutdwm(ast, 0x1E78500c, 0x0033);
+   udelay(1000);
+   }
+   do {
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+  

[PATCH v4] drm/ast: Disable fast reset after DRAM initial

2021-05-07 Thread KuoHsiang Chou
[Bug][AST2500]

V1:
When AST2500 acts as stand-alone VGA so that DRAM and DVO initialization
have to be achieved by VGA driver with P2A (PCI to AHB) enabling.
However, HW suggests disable Fast reset mode after DRAM initializaton,
because fast reset mode is mainly designed for ARM ICE debugger.
Once Fast reset is checked as enabling, WDT (Watch Dog Timer) should be
first enabled to avoid system deadlock before disable fast reset mode.

V2:
Use to_pci_dev() to get revision of PCI configuration.

V3:
If SCU00 is not unlocked, just enter its password again.
It is unnecessary to clear AHB lock condition and restore WDT default
setting again, before Fast-reset clearing.

V4:
repatch after "error : could not build fake ancestor" resolved.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  |  1 +
 drivers/gpu/drm/ast/ast_main.c |  4 ++
 drivers/gpu/drm/ast/ast_post.c | 68 +-
 3 files changed, 47 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 911f9f414..5ebb5905d 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -346,6 +346,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
 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 ast_patch_ahb_2500(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);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 2aff2e6cf..cfb56ea3a 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -97,6 +97,10 @@ static void ast_detect_config_mode(struct drm_device *dev, 
u32 *scu_rev)
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 (((pdev->revision & 0xF0) == 0x40) && ((jregd0 & 0xC0) == 0))
+   ast_patch_ahb_2500(ast);
+
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
if ((data != 0x) && (data != 0x00)) {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 0607658dd..56428798a 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2028,6 +2028,30 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
 }

+void ast_patch_ahb_2500(struct ast_private *ast)
+{
+   u32 data;
+
+   /* Clear bus lock condition */
+   ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
+   ast_moutdwm(ast, 0x1e600084, 0x0001);
+   ast_moutdwm(ast, 0x1e600088, 0x);
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2070);
+   if (data & 0x0800) {/* 
check fast reset */
+
+   ast_moutdwm(ast, 0x1E785004, 0x0010);
+   ast_moutdwm(ast, 0x1E785008, 0x4755);
+   ast_moutdwm(ast, 0x1E78500c, 0x0033);
+   udelay(1000);
+   }
+   do {
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2000);
+   }   while (data != 1);
+   ast_moutdwm(ast, 0x1e6e207c, 0x0800);   /* clear fast reset */
+}
+
 void ast_post_chip_2500(struct drm_device *dev)
 {
struct ast_private *ast = to_ast_private(dev);
@@ -2035,39 +2059,31 @@ void ast_post_chip_2500(struct drm_device *dev)
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, 0x1e60, 0xAEED1A03);
-   ast_moutdwm(ast, 0x1e600084, 0x0001);
-   ast_moutdwm(ast, 0x1e600088, 0x);
-   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
-   ast_write32(ast, 0xf004, 0x1e6e);
-   ast_write32(ast, 0xf000, 0x1);
-   ast_write32(ast, 0x12000, 0x1688a8a8);
-   while (ast_read32(ast, 0x12000) != 0x1)
-   ;
-
-   ast_write32(ast, 0x1, 0xfc600309);
-   while (ast_read32(ast, 0x1) != 0x1)
-   ;
+   ast_patch_ahb_2500(ast);
+
+   /* Disable watchdog */
+   ast_moutdwm(ast, 0x1E78502C, 0x);
+   ast_moutdwm(ast, 0x1E78504C, 0x);
+   /* Reset USB port */
+   ast_moutdwm(ast, 0x1E6E2090, 0x2000)

[PATCH v5] drm/ast: Fixed CVE for DP501

2021-04-21 Thread KuoHsiang Chou
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/ast_dp501.c | 139 +++-
 drivers/gpu/drm/ast/ast_drv.h   |  12 +++
 drivers/gpu/drm/ast/ast_main.c  |  11 ++-
 3 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0..cd93c44f2 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+   u32 *plinkcap;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap  = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   } else {
+   if (!ast->dp501_fw_buf)
+   return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = readl(ast->dp501_fw_buf + offset);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = readl(ast->dp501_fw_buf + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap = readl(ast->dp501_fw_buf + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
 {
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;
+   u32 *pEDIDidx;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-  

[PATCH v4] drm/ast: Fixed CVE for DP501

2021-04-08 Thread KuoHsiang Chou
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/ast_dp501.c | 139 +++-
 drivers/gpu/drm/ast/ast_drv.h   |  12 +++
 drivers/gpu/drm/ast/ast_main.c  |   8 ++
 3 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0..cd93c44f2 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+   u32 *plinkcap;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap  = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   } else {
+   if (!ast->dp501_fw_buf)
+   return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = readl(ast->dp501_fw_buf + offset);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = readl(ast->dp501_fw_buf + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap = readl(ast->dp501_fw_buf + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
 {
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;
+   u32 *pEDIDidx;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-  

[PATCH V3] drm/ast: Disable fast reset after DRAM initial

2021-03-19 Thread KuoHsiang Chou
[Bug][AST2500]

V1:
When AST2500 acts as stand-alone VGA so that DRAM and DVO initialization
have to be achieved by VGA driver with P2A (PCI to AHB) enabling.
However, HW suggests disable Fast reset mode after DRAM initializaton,
because fast reset mode is mainly designed for ARM ICE debugger.
Once Fast reset is checked as enabling, WDT (Watch Dog Timer) should be
first enabled to avoid system deadlock before disable fast reset mode.

V2:
Use to_pci_dev() to get revision of PCI configuration.

V3:
If SCU00 is not unlocked, just enter its password again.
It is unnecessary to clear AHB lock condition and restore WDT default
setting again, before Fast-reset clearing.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  |  1 +
 drivers/gpu/drm/ast/ast_main.c |  5 +++
 drivers/gpu/drm/ast/ast_post.c | 68 +-
 3 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index da6dfb677540..a2cf5fef2399 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -320,6 +320,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
 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 ast_patch_ahb_2500(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);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 3775fe26f792..0e4dfcc25623 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -69,6 +69,7 @@ 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 = to_ast_private(dev);
+   struct pci_dev *pdev = to_pci_dev(dev->dev);
uint32_t data, jregd0, jregd1;

/* Defaults */
@@ -96,6 +97,10 @@ static void ast_detect_config_mode(struct drm_device *dev, 
u32 *scu_rev)
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 (((pdev->revision & 0xF0) == 0x40) && ((jregd0 & 0xC0) == 0))
+   ast_patch_ahb_2500(ast);
+
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
if (data != 0x) {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 8902c2f84bf9..4f194c5fd2c2 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2026,6 +2026,30 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
 }

+void ast_patch_ahb_2500(struct ast_private *ast)
+{
+   u32 data;
+
+   /* Clear bus lock condition */
+   ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
+   ast_moutdwm(ast, 0x1e600084, 0x0001);
+   ast_moutdwm(ast, 0x1e600088, 0x);
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2070);
+   if (data & 0x0800) {/* 
check fast reset */
+
+   ast_moutdwm(ast, 0x1E785004, 0x0010);
+   ast_moutdwm(ast, 0x1E785008, 0x4755);
+   ast_moutdwm(ast, 0x1E78500c, 0x0033);
+   udelay(1000);
+   }
+   do {
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2000);
+   }   while (data != 1);
+   ast_moutdwm(ast, 0x1e6e207c, 0x0800);   /* clear fast reset */
+}
+
 void ast_post_chip_2500(struct drm_device *dev)
 {
struct ast_private *ast = to_ast_private(dev);
@@ -2033,39 +2057,31 @@ void ast_post_chip_2500(struct drm_device *dev)
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, 0x1e60, 0xAEED1A03);
-   ast_moutdwm(ast, 0x1e600084, 0x0001);
-   ast_moutdwm(ast, 0x1e600088, 0x);
-   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
-   ast_write32(ast, 0xf004, 0x1e6e);
-   ast_write32(ast, 0xf000, 0x1);
-   ast_write32(ast, 0x12000, 0x1688a8a8);
-   while (ast_read32(ast, 0x12000) != 0x1)
-   ;
-
-   ast_write32(ast, 0x1, 0xfc600309);
-   while (ast_read32(ast, 0x1) != 0x1)
-   ;
+   ast_patch_ahb_2500(ast);
+
+   /* Dis

[PATCH] drm/ast: Update the sequence of Clearing Fast-reset

2021-01-18 Thread KuoHsiang Chou
[Bug][AST2500]
If SCU00 is not unlocked, just enter its password again.
It is unnecessary to clear AHB lock condition and restore WDT default
setting again, before Fast-reset clearing.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_post.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 1f0007daa005..4f194c5fd2c2 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2030,7 +2030,6 @@ void ast_patch_ahb_2500(struct ast_private *ast)
 {
u32 data;

-patch_ahb_lock:
/* Clear bus lock condition */
ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
ast_moutdwm(ast, 0x1e600084, 0x0001);
@@ -2044,11 +2043,9 @@ void ast_patch_ahb_2500(struct ast_private *ast)
ast_moutdwm(ast, 0x1E78500c, 0x0033);
udelay(1000);
}
-   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
do {
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
data = ast_mindwm(ast, 0x1e6e2000);
-   if (data == 0x)
-   goto patch_ahb_lock;
}   while (data != 1);
ast_moutdwm(ast, 0x1e6e207c, 0x0800);   /* clear fast reset */
 }
--
2.18.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2] drm/ast: Disable fast reset after DRAM initial

2021-01-11 Thread KuoHsiang Chou
[Bug][AST2500]

V1:
When AST2500 acts as stand-alone VGA so that DRAM and DVO initialization
have to be achieved by VGA driver with P2A (PCI to AHB) enabling.
However, HW suggests disable Fast reset mode after DRAM initializaton,
because fast reset mode is mainly designed for ARM ICE debugger.
Once Fast reset is checked as enabling, WDT (Watch Dog Timer) should be
first enabled to avoid system deadlock before disable fast reset mode.

V2:
Use to_pci_dev() to get revision of PCI configuration.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  |  1 +
 drivers/gpu/drm/ast/ast_main.c |  5 +++
 drivers/gpu/drm/ast/ast_post.c | 71 +-
 3 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index da6dfb677540..a2cf5fef2399 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -320,6 +320,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
 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 ast_patch_ahb_2500(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);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 3775fe26f792..0e4dfcc25623 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -69,6 +69,7 @@ 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 = to_ast_private(dev);
+   struct pci_dev *pdev = to_pci_dev(dev->dev);
uint32_t data, jregd0, jregd1;

/* Defaults */
@@ -96,6 +97,10 @@ static void ast_detect_config_mode(struct drm_device *dev, 
u32 *scu_rev)
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 (((pdev->revision & 0xF0) == 0x40) && ((jregd0 & 0xC0) == 0))
+   ast_patch_ahb_2500(ast);
+
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
if (data != 0x) {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 8902c2f84bf9..1f0007daa005 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2026,6 +2026,33 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
 }

+void ast_patch_ahb_2500(struct ast_private *ast)
+{
+   u32 data;
+
+patch_ahb_lock:
+   /* Clear bus lock condition */
+   ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
+   ast_moutdwm(ast, 0x1e600084, 0x0001);
+   ast_moutdwm(ast, 0x1e600088, 0x);
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2070);
+   if (data & 0x0800) {/* 
check fast reset */
+
+   ast_moutdwm(ast, 0x1E785004, 0x0010);
+   ast_moutdwm(ast, 0x1E785008, 0x4755);
+   ast_moutdwm(ast, 0x1E78500c, 0x0033);
+   udelay(1000);
+   }
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   do {
+   data = ast_mindwm(ast, 0x1e6e2000);
+   if (data == 0x)
+   goto patch_ahb_lock;
+   }   while (data != 1);
+   ast_moutdwm(ast, 0x1e6e207c, 0x0800);   /* clear fast reset */
+}
+
 void ast_post_chip_2500(struct drm_device *dev)
 {
struct ast_private *ast = to_ast_private(dev);
@@ -2033,39 +2060,31 @@ void ast_post_chip_2500(struct drm_device *dev)
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, 0x1e60, 0xAEED1A03);
-   ast_moutdwm(ast, 0x1e600084, 0x0001);
-   ast_moutdwm(ast, 0x1e600088, 0x);
-   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
-   ast_write32(ast, 0xf004, 0x1e6e);
-   ast_write32(ast, 0xf000, 0x1);
-   ast_write32(ast, 0x12000, 0x1688a8a8);
-   while (ast_read32(ast, 0x12000) != 0x1)
-   ;
-
-   ast_write32(ast, 0x1, 0xfc600309);
-   while (ast_read32(ast, 0x1) != 0x1)
-   ;
+   ast_patch_ahb_2500(ast);
+
+   /* Disable watchdog */
+   ast_moutdwm(ast, 0x1E78502C, 0x);
+  

[PATCH] drm/ast: Disable fast reset after DRAM initial

2021-01-10 Thread KuoHsiang Chou
[Bug][AST2500]
When AST2500 acts as stand-alone VGA so that DRAM and DVO initialization
have to be achieved by VGA driver with P2A (PCI to AHB) enabling.
However, HW suggests disable Fast reset mode after DRAM initializaton,
because fast reset mode is mainly designed for ARM ICE debugger.
Once Fast reset is checked as enabling, WDT (Watch Dog Timer) should be
first enabled to avoid system deadlock before disable fast reset mode.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  |  1 +
 drivers/gpu/drm/ast/ast_main.c |  4 ++
 drivers/gpu/drm/ast/ast_post.c | 72 ++
 3 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index da6dfb677540..8bdd1482370d 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -320,6 +320,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
 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);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 3775fe26f792..3c072c6589a2 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -96,6 +96,10 @@ static void ast_detect_config_mode(struct drm_device *dev, 
u32 *scu_rev)
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 */
data = ast_read32(ast, 0xf004);
if (data != 0x) {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 8902c2f84bf9..2d121c5b2233 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2026,6 +2026,33 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
 }

+void patch_ahb_ast2500(struct ast_private *ast)
+{
+   u32 data;
+
+patch_ahb_lock:
+   /* Clear bus lock condition */
+   ast_moutdwm(ast, 0x1e60, 0xAEED1A03);
+   ast_moutdwm(ast, 0x1e600084, 0x0001);
+   ast_moutdwm(ast, 0x1e600088, 0x);
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   data = ast_mindwm(ast, 0x1e6e2070);
+   if (data & 0x0800) {/* check fast 
reset */
+
+   ast_moutdwm(ast, 0x1E785004, 0x0010);
+   ast_moutdwm(ast, 0x1E785008, 0x4755);
+   ast_moutdwm(ast, 0x1E78500c, 0x0033);
+   udelay(1000);
+   }
+   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+   do {
+   data = ast_mindwm(ast, 0x1e6e2000);
+   if (data == 0x)
+   goto patch_ahb_lock;
+   }   while (data != 1);
+   ast_moutdwm(ast, 0x1e6e207c, 0x0800);   /* clear fast 
reset */
+}
+
 void ast_post_chip_2500(struct drm_device *dev)
 {
struct ast_private *ast = to_ast_private(dev);
@@ -2033,39 +2060,32 @@ void ast_post_chip_2500(struct drm_device *dev)
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, 0x1e60, 0xAEED1A03);
-   ast_moutdwm(ast, 0x1e600084, 0x0001);
-   ast_moutdwm(ast, 0x1e600088, 0x);
-   ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
-   ast_write32(ast, 0xf004, 0x1e6e);
-   ast_write32(ast, 0xf000, 0x1);
-   ast_write32(ast, 0x12000, 0x1688a8a8);
-   while (ast_read32(ast, 0x12000) != 0x1)
-   ;
-
-   ast_write32(ast, 0x1, 0xfc600309);
-   while (ast_read32(ast, 0x1) != 0x1)
-   ;
+   patch_ahb_ast2500(ast);
+
+   /* Disable watchdog */
+   ast_moutdwm(ast, 0x1E78502C, 0x);
+   ast_moutdwm(ast, 0x1E78504C, 0x);
+   /* Reset USB port */
+   ast_moutdwm(ast, 0x1E6E2090, 0x2000);   /* add 
at V1.2 */
+   ast_moutdwm(ast, 0x1E6E2094, 0x4000);   /* add 
at V1.2 */
+   if (ast_mindwm(ast, 0x1E6E2070) & 0x0080) { /* add 
at V1.2 */
+   ast_mout

[PATCH V3] drm/ast: Fixed CVE for DP501

2020-12-27 Thread KuoHsiang Chou
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
0In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/ast_dp501.c | 139 +++-
 drivers/gpu/drm/ast/ast_drv.h   |  12 +++
 drivers/gpu/drm/ast/ast_main.c  |   8 ++
 3 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0d05..cd93c44f2662 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+   u32 *plinkcap;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap  = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   } else {
+   if (!ast->dp501_fw_buf)
+   return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = readl(ast->dp501_fw_buf + offset);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = readl(ast->dp501_fw_buf + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap = readl(ast->dp501_fw_buf + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
 {
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;
+   u32 *pEDIDidx;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-  

[PATCH V3] drm/ast: Fixed CVE for DP501

2020-12-27 Thread KuoHsiang Chou
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
0In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.

Signed-off-by: KuoHsiang Chou 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/ast/ast_dp501.c | 139 +++-
 drivers/gpu/drm/ast/ast_drv.h   |  12 +++
 drivers/gpu/drm/ast/ast_main.c  |   8 ++
 3 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0d05..cd93c44f2662 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+   u32 *plinkcap;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap  = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   } else {
+   if (!ast->dp501_fw_buf)
+   return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = readl(ast->dp501_fw_buf + offset);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = readl(ast->dp501_fw_buf + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap = readl(ast->dp501_fw_buf + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
 {
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;
+   u32 *pEDIDidx;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-  

[PATCH v2] drm/ast: Fixed CVE for DP501

2020-12-11 Thread KuoHsiang Chou
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_dp501.c | 136 +++-
 drivers/gpu/drm/ast/ast_drv.h   |  12 +++
 drivers/gpu/drm/ast/ast_main.c  |   8 ++
 3 files changed, 120 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0d05..aef9bbace99f 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a)
+   return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+   u32 *plinkcap;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap  = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   } else {
+   if (!ast->dp501_fw_buf)
+   return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = readl(ast->dp501_fw_buf + offset);
+
+   /* validate FW version */
+   offset = AST_DP501_GBL_VERSION;
+   data = readl(ast->dp501_fw_buf + offset);
+   if ((data & AST_DP501_FW_VERSION_MASK) != 
AST_DP501_FW_VERSION_1) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset = AST_DP501_LINKRATE;
+   plinkcap = (u32 *)linkcap;
+   *plinkcap = readl(ast->dp501_fw_buf + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -299,25 +335,53 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10)
-   return fal

[PATCH] drm/ast: Fixed CVE for DP501

2020-11-25 Thread KuoHsiang Chou
[Bug][DP501]
1. For security concerning, P2A have to be disabled by CVE regulation.
2. FrameBuffer reverses last 2MB used for the image of DP501.
3. If P2A is disallowed, the default "ioremap()" behavior is non-cached
   and could be an alternative accessing on the image of DP501.
---
 drivers/gpu/drm/ast/ast_dp501.c | 131 +++-
 drivers/gpu/drm/ast/ast_drv.h   |   2 +
 drivers/gpu/drm/ast/ast_main.c  |  12 +++
 drivers/gpu/drm/ast/ast_mm.c|   1 +
 4 files changed, 110 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0d05..7640364ef2bc 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,8 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 
size)
u32 i, data;
u32 boot_address;

+   if (ast->config_mode != ast_use_p2a) return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +209,8 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;

+   if (ast->config_mode != ast_use_p2a) return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {

@@ -272,24 +276,51 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10) /* version: 1x */
-   return maxclk;
-
-   /* Read Link Capability */
-   offset  = 0xf014;
-   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-   if (linkcap[2] == 0) {
-   linkrate = linkcap[0];
-   linklanes = linkcap[1];
-   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-   if (data > 0xff)
-   data = 0xff;
-   maxclk = (u8)data;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);
+
+   /* validate FW version */
+   offset = 0xf000;
+   data = ast_mindwm(ast, boot_address + offset);
+   if ((data & 0xf0) != 0x10) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = 0xf014;
+   *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
+   }
+   else {
+   if (!ast->reservedbuffer) return 65;/* 1024x768 as default 
*/
+
+   /* dummy read */
+   offset = 0x;
+   data = *(u32 *) (ast->reservedbuffer + offset);
+
+   /* validate FW version */
+   offset = 0xf000;
+   data = *(u32 *) (ast->reservedbuffer + offset);
+   if ((data & 0xf0) != 0x10) /* version: 1x */
+   return maxclk;
+
+   /* Read Link Capability */
+   offset  = 0xf014;
+   *(u32 *)linkcap = *(u32 *) (ast->reservedbuffer + offset);
+   if (linkcap[2] == 0) {
+   linkrate = linkcap[0];
+   linklanes = linkcap[1];
+   data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * 
linklanes);
+   if (data > 0xff)
+   data = 0xff;
+   maxclk = (u8)data;
+   }
}
return maxclk;
 }
@@ -299,25 +330,53 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 
*ediddata)
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;

-   boot_address = get_fw_base(ast);
-
-   /* validate FW version */
-   offset = 0xf000;
-   data = ast_mindwm(ast, boot_address + offset);
-   if ((data & 0xf0) != 0x10)
-   return false;
-
-   /* validate PnP Monitor */
-   offset = 0xf010;
-   data = ast_mindwm(ast, boot_address + offset);
-   if (!(data & 0x01))
-   return false;
+   if (ast->config_mode == ast_use_p2a) {
+   boot_address = get_fw_base(ast);

-   /* Read EDID */
-   offset = 0xf020;
-   for (i = 0; i < 128; i += 4) {
-   data = ast_mindwm(ast, boot_address + offset + i);
-   *(u32 *)(ediddata + i) = data;
+   /* validate FW version */
+   

[PATCH] drm/ast: Create chip AST2600

2020-11-09 Thread KuoHsiang Chou
[New] Support AST2600

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_drv.h  | 1 +
 drivers/gpu/drm/ast/ast_main.c | 5 -
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 467049ca8430..6b9e3b94a712 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -63,6 +63,7 @@ enum ast_chip {
AST2300,
AST2400,
AST2500,
+   AST2600,
 };

 enum ast_tx_chip {
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 77066bca8793..4ec6884f6c65 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -143,7 +143,10 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
ast_detect_config_mode(dev, _rev);

/* Identify chipset */
-   if (dev->pdev->revision >= 0x40) {
+   if (dev->pdev->revision >= 0x50) {
+   ast->chip = AST2600;
+   drm_info(dev, "AST 2600 detected\n");
+   } else if (dev->pdev->revision >= 0x40) {
ast->chip = AST2500;
drm_info(dev, "AST 2500 detected\n");
} else if (dev->pdev->revision >= 0x30) {
--
2.18.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/ast: Fixed 1920x1080 sync. polarity issue

2020-11-05 Thread KuoHsiang Chou
[Bug] Change the vertical synchroous polary of 1920x1080 @60Hz
  from  Negtive to Positive

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_tables.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h
index 8414e543f260..51efc5b4a55c 100644
--- a/drivers/gpu/drm/ast/ast_tables.h
+++ b/drivers/gpu/drm/ast/ast_tables.h
@@ -295,10 +295,10 @@ static const struct ast_vbios_enhtable res_1600x900[] = {

 static const struct ast_vbios_enhtable res_1920x1080[] = {
{2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,   /* 60Hz */
-(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
  AST2500PreCatchCRT), 60, 1, 0x38 },
{2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,   /* 60Hz */
-(SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
  AST2500PreCatchCRT), 0xFF, 1, 0x38 },
 };

--
2.18.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/ast: Support 1600x900 with 108MHz PCLK

2020-10-30 Thread KuoHsiang Chou
[New] Create the setting for 1600x900 @60Hz refresh rate
  by 108MHz pixel-clock.

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/ast_tables.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h
index d665dd5af5dd..8414e543f260 100644
--- a/drivers/gpu/drm/ast/ast_tables.h
+++ b/drivers/gpu/drm/ast/ast_tables.h
@@ -282,6 +282,8 @@ static const struct ast_vbios_enhtable res_1360x768[] = {
 };

 static const struct ast_vbios_enhtable res_1600x900[] = {
+   {1800, 1600, 24, 80,1000,  900, 1, 3, VCLK108,  /* 60Hz */
+(SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 
60, 3, 0x3A },
{1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB 
*/
 (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
  AST2500PreCatchCRT), 60, 1, 0x3A },
--
2.18.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/ast: Avoid to access BMC addressing when P2A is disabled

2020-10-16 Thread KuoHsiang Chou
The patch is upstreamed
1. For RHEL7.x, because its native kernel is suggested to update
   from 3.10 to 4.9 on 2 ODM's platform.
2. For AST2600.
3. For ASTDP.
4. v1.11

Signed-off-by: KuoHsiang Chou 
---
 drivers/gpu/drm/ast/Makefile  |   2 +-
 drivers/gpu/drm/ast/ast_dp.c  | 233 ++
 drivers/gpu/drm/ast/ast_dram_tables.h |  59 
 drivers/gpu/drm/ast/ast_drv.c |   2 +-
 drivers/gpu/drm/ast/ast_drv.h |  31 +-
 drivers/gpu/drm/ast/ast_main.c| 138 +++--
 drivers/gpu/drm/ast/ast_mode.c| 146 +++--
 drivers/gpu/drm/ast/ast_post.c| 553 ++
 drivers/gpu/drm/ast/ast_tables.h  | 238 ++-
 9 files changed, 1214 insertions(+), 188 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 171aa06..a6974af 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -4,6 +4,6 @@

 ccflags-y := -Iinclude/drm

-ast-y := ast_drv.o ast_main.o ast_mode.o ast_fb.o ast_ttm.o ast_post.o 
ast_dp501.o
+ast-y := ast_drv.o ast_main.o ast_mode.o ast_fb.o ast_ttm.o ast_post.o 
ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index ..2231fe1
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,233 @@
+#include 
+#include 
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+struct ast_private *ast = dev->dev_private;
+
+u32 i;
+
+#ifdef DPControlPower
+u8 bDPState_Change = false;
+
+// Check DP power off or not.
+if (ast->ASTDP_State & 0x10) {
+   // DP power on
+   ast_dp_PowerOnOff(ast->dev, 1);
+   bDPState_Change = true;
+}
+#endif
+
+if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0xFF) == 0) {
+#ifdef DPControlPower
+   // Set back power off
+   if (bDPState_Change)
+   ast_dp_PowerOnOff(ast->dev, 0);
+#endif
+   return false;
+}
+
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x00);
// reading EDID is NOT done.
+
+   for (i = 0; i < 64; i++) {
+   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, 0x00, (u8) 
i);
+
+   while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, 
0xFF) != 0x01)
+   || (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, 
0xFF) != i)) {
+   msleep(1);
+   }
+
+   *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xD8, 0xFF);
+   *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xD9, 0xFF);
+   *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xDA, 0xFF);
+   *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
0xDB, 0xFF);
+
+   ediddata += 4;
+   }
+
+ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);   
// reading EDID is DONE.
+
+#ifdef DPControlPower
+// Set back power off
+   if (bDPState_Change)
+   ast_dp_PowerOnOff(ast->dev, 0);
+#endif
+
+   return true;
+
+} /* ReadEDID_AspeedDP */
+
+/*
+ * Launch Aspeed DP
+ */
+bool ast_dp_launch(struct drm_device *dev, u8 bPower)
+{
+   u32 i = 0, j = 0, WaitCount = 5;
+   u8 bDPTX = 0;
+   u8 bDPExecute = 1;
+
+   struct ast_private *ast = dev->dev_private;
+
+// S3 come back, need more time to wait BMC ready.
+   if (bPower)
+   WaitCount = 300;
+
+// Fill
+   ast->tx_chip_type = AST_TX_NONE;
+
+// Wait total count by different condition.
+// This is a temp solution for DP check
+   for (j = 0; j < WaitCount; j++) {
+   // Wait BMC ready 100ms
+   for (i = 0; i < 100; i++) {
+   // 1ms
+   msleep(1);
+   }
+
+   bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
0x0E);
+
+   if (bDPTX)
+   break;
+   }
+
+// 0xE : ASTDP with DPMCU FW handling
+   if (bDPTX == 0x0E) {
+   // Wait one second then timeout.
+   i = 0;
+
+   while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
0x20) != 0x20) {
+   i++;
+   // wait 1 ms
+   msleep(1);
+
+   if (i >= 1000) {
+   // DP would not be ready.
+   bDPExecute = 0;
+   break;
+   }
+   };
+
+   if (bDPExecute)
+   ast->tx_chip_type = AST_TX_ASTDP;
+
+   }
+
+   return true;
+} /* Launch Aspeed DP */
+
+#ifdef DPContro