From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: dri-devel@lists.freedesktop.org
Cc: airlied@redhat.com, eich@suse.com
Subject: Re: [PATCH 1/9] drm/ast: Handle configuration without P2A bridge
Date: Fri, 17 Feb 2017 18:43:00 +1100 [thread overview]
Message-ID: <1487317380.23576.124.camel@kernel.crashing.org> (raw)
In-Reply-To: <20170217053212.4839-1-benh@kernel.crashing.org>
On Fri, 2017-02-17 at 16:32 +1100, Benjamin Herrenschmidt wrote:
Make this
From: Russell Currey <ruscur@russell.cc>
Git ate it when I amended (citool bug) and I forgot to fix it up.
> The ast driver configures a window to enable access into BMC
> memory space in order to read some configuration registers.
>
> If this window is disabled, which it can be from the BMC side,
> the ast driver can't function.
>
> Closing this window is a necessity for security if a machine's
> host side and BMC side are controlled by different parties;
> i.e. a cloud provider offering machines "bare metal".
>
> A recent patch went in to try to check if that window is open
> but it does so by trying to access the registers in question
> and testing if the result is 0xffffffff.
>
> This method will trigger a PCIe error when the window is closed
> which on some systems will be fatal (it will trigger an EEH
> for example on POWER which will take out the device).
>
> This patch improves this in two ways:
>
> - First, if the firmware has put properties in the device-tree
> containing the relevant configuration information, we use these.
>
> - Otherwise, a bit in one of the SCU scratch registers (which
> are readable via the VGA register space and writeable by the BMC)
> will indicate if the BMC has closed the window. This bit has been
> defined by Y.C Chen from Aspeed.
>
> If the window is closed and the configuration isn't available from
> the device-tree, some sane defaults are used. Those defaults are
> hopefully sufficient for standard video modes used on a server.
>
> Signed-off-by: Russell Currey <ruscur@russell.cc>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> --
>
> v2. [BenH]
> - Reworked on top of Aspeed P2A patch
> - Cleanup overall detection via a "config_mode" and log the
> selected mode for diagnostics purposes
> - Add a property for the SCU straps
>
> v3. [BenH]
> - Moved the config mode detection to a separate functionn
> - Add reading of SCU 0x40 D[12] to detect the window is
> closed as to not trigger a bus error by just "trying".
> (change provided by Y.C. Chen)
> ---
> drivers/gpu/drm/ast/ast_drv.h | 6 +-
> drivers/gpu/drm/ast/ast_main.c | 223 +++++++++++++++++++++++++----
> ------------
> drivers/gpu/drm/ast/ast_post.c | 7 +-
> 3 files changed, 141 insertions(+), 95 deletions(-)
>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> b/drivers/gpu/drm/ast/ast_drv.h
> index 7abda94..3bedcf7 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -113,7 +113,11 @@ struct ast_private {
> struct ttm_bo_kmap_obj cache_kmap;
> int next_cursor;
> bool support_wide_screen;
> - bool DisableP2A;
> + enum {
> + ast_use_p2a,
> + ast_use_dt,
> + ast_use_defaults
> + } config_mode;
>
> enum ast_tx_chip tx_chip_type;
> u8 dp501_maxclk;
> diff --git a/drivers/gpu/drm/ast/ast_main.c
> b/drivers/gpu/drm/ast/ast_main.c
> index 533e762..823c68f 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -62,13 +62,58 @@ uint8_t ast_get_index_reg_mask(struct ast_private
> *ast,
> 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, jreg;
> +
> + /* Check if we have device-tree properties */
> + if (np && !of_property_read_u32(np, "ast,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;
> + }
> +
> + /*
> + * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
> + * is disabled
> + */
> + jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1,
> 0xff);
> + if (!(jreg & 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;
> + }
> + }
> +
> + DRM_INFO("P2A bridge disabled, using default
> configuration\n");
> + ast->config_mode = ast_use_defaults;
> + *scu_rev = 0xffffffff;
> +}
>
> static int ast_detect_chip(struct drm_device *dev, bool *need_post)
> {
> struct ast_private *ast = dev->dev_private;
> - uint32_t data, jreg;
> + uint32_t jreg, scu_rev;
> +
> 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) {
> ast->chip = AST1100;
> DRM_INFO("AST 1180 detected\n");
> @@ -80,12 +125,7 @@ static int ast_detect_chip(struct drm_device
> *dev, bool *need_post)
> ast->chip = AST2300;
> DRM_INFO("AST 2300 detected\n");
> } 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:
> ast->chip = AST1100;
> DRM_INFO("AST 1100 detected\n");
> @@ -124,12 +164,6 @@ static int ast_detect_chip(struct drm_device
> *dev, bool *need_post)
> } 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 */
> switch (ast->chip) {
> case AST1180:
> @@ -146,17 +180,12 @@ static int ast_detect_chip(struct drm_device
> *dev, bool *need_post)
> ast->support_wide_screen = true;
> else {
> 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;
> }
> @@ -220,85 +249,101 @@ static int ast_detect_chip(struct drm_device
> *dev, bool *need_post)
>
> static int ast_get_dram_info(struct drm_device *dev)
> {
> + struct device_node *np = dev->pdev->dev.of_node;
> struct ast_private *ast = dev->dev_private;
> - uint32_t data, data2;
> - uint32_t denum, num, div, ref_pll;
> + 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, "ast,mcr-
> configuration", &mcr_cfg))
> + mcr_cfg = 0x00000577;
> + if (of_property_read_u32(np, "ast,ast,mcr-scu-mpll",
> + &mcr_scu_mpll))
> + mcr_scu_mpll = 0x000050C0;
> + if (of_property_read_u32(np, "ast,ast,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_type = AST_DRAM_1Gx16;
> 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;
> - case 2:
> + default:
> case 1:
> - div = 0x2;
> + ast->dram_type = AST_DRAM_1Gx16;
> break;
> - default:
> - div = 0x1;
> + case 2:
> + ast->dram_type = AST_DRAM_2Gx16;
> + break;
> + case 3:
> + ast->dram_type = AST_DRAM_4Gx16;
> break;
> }
> - ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div
> * 1000);
> + } 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;
> + }
> + }
> +
> + 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;
> }
>
> diff --git a/drivers/gpu/drm/ast/ast_post.c
> b/drivers/gpu/drm/ast/ast_post.c
> index 5331ee1..7197635 100644
> --- a/drivers/gpu/drm/ast/ast_post.c
> +++ b/drivers/gpu/drm/ast/ast_post.c
> @@ -379,17 +379,14 @@ void ast_post_gpu(struct drm_device *dev)
> ast_open_key(ast);
> ast_set_def_ext_reg(dev);
>
> - if (ast->DisableP2A == false)
> - {
> + if (ast->config_mode == ast_use_p2a) {
> if (ast->chip == AST2300 || ast->chip == AST2400)
> ast_init_dram_2300(dev);
> else
> ast_init_dram_reg(dev);
>
> ast_init_3rdtx(dev);
> - }
> - else
> - {
> + } else {
> if (ast->tx_chip_type != AST_TX_NONE)
> ast_set_index_reg_mask(ast,
> AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
> }
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2017-02-17 7:43 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-17 5:32 [PATCH 1/9] drm/ast: Handle configuration without P2A bridge Benjamin Herrenschmidt
2017-02-17 5:32 ` [PATCH 2/9] drm/ast: const'ify mode setting tables Benjamin Herrenschmidt
2017-02-18 14:59 ` Emil Velikov
2017-02-17 5:32 ` [PATCH 3/9] drm/ast: Remove spurrious include Benjamin Herrenschmidt
2017-02-18 15:04 ` Emil Velikov
2017-02-17 5:32 ` [PATCH 4/9] drm/ast: Fix calculation of MCLK Benjamin Herrenschmidt
2017-02-18 15:04 ` Emil Velikov
2017-02-17 5:32 ` [PATCH 5/9] drm/ast: Base support for AST2500 Benjamin Herrenschmidt
2017-02-17 5:32 ` [PATCH 6/9] drm/ast: Factor mmc_test code in POST code Benjamin Herrenschmidt
2017-02-18 15:28 ` Emil Velikov
2017-02-18 22:20 ` Benjamin Herrenschmidt
2017-02-17 5:32 ` [PATCH 7/9] drm/ast: Rename ast_init_dram_2300 to ast_post_chip_2300 Benjamin Herrenschmidt
2017-02-17 5:32 ` [PATCH 8/9] drm/ast: POST code for the new AST2500 Benjamin Herrenschmidt
2017-02-17 5:32 ` [PATCH 9/9] drm/ast: Fixed vram size incorrect issue on POWER Benjamin Herrenschmidt
2017-02-17 7:43 ` Benjamin Herrenschmidt [this message]
2017-02-17 10:42 ` [PATCH 1/9] drm/ast: Handle configuration without P2A bridge Benjamin Herrenschmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1487317380.23576.124.camel@kernel.crashing.org \
--to=benh@kernel.crashing.org \
--cc=airlied@redhat.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=eich@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.