linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
To: Damien Le Moal <damien.lemoal@opensource.wdc.com>,
	Hans de Goede <hdegoede@redhat.com>, Jens Axboe <axboe@kernel.dk>,
	Serge Semin <fancer.lancer@gmail.com>
Cc: Serge Semin <Sergey.Semin@baikalelectronics.ru>,
	Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>,
	Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>,
	Rob Herring <robh+dt@kernel.org>, <linux-ide@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>
Subject: [PATCH 20/21] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support
Date: Thu, 24 Mar 2022 03:16:27 +0300	[thread overview]
Message-ID: <20220324001628.13028-21-Sergey.Semin@baikalelectronics.ru> (raw)
In-Reply-To: <20220324001628.13028-1-Sergey.Semin@baikalelectronics.ru>

It's almost fully compatible DWC AHCI SATA IP-core derivative except the
reference clocks source, which need to be very carefully selected. In
particular the DWC AHCI SATA PHY can be clocked either from the pads
ref_pad_clk_{m,p} or from the internal wires ref_alt_clk_{m,n}. In the
later case the clock signal is generated from the Baikal-T1 CCU SATA PLL.
The clocks source is selected by means of the ref_use_pad wire connected
to the CCU SATA reference clock CSR.

In normal situation it would be much more handy to use the internal
reference clock source, but alas we haven't managed to make the AHCI
controller working well with it so far. So it's preferable to have the
controller clocked from the external clock generator and fallback to the
internal clock source only as a last resort. Other than that the
controller is full compatible with the DWC AHCI SATA IP-core.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/ata/Kconfig    |  1 +
 drivers/ata/ahci_dwc.c | 86 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ab11bcf8510c..003f000a69a7 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -178,6 +178,7 @@ config AHCI_DWC
 	tristate "Synopsys DWC AHCI SATA support"
 	select SATA_HOST
 	default SATA_AHCI_PLATFORM
+	select MFD_SYSCON if (MIPS_BAIKAL_T1 || COMPILE_TEST)
 	help
 	  This option enables support for the Synopsys DWC AHCI SATA
 	  controller implementation.
diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
index 9e294f994ed3..efcd5f74c2d4 100644
--- a/drivers/ata/ahci_dwc.c
+++ b/drivers/ata/ahci_dwc.c
@@ -13,10 +13,12 @@
 #include <linux/kernel.h>
 #include <linux/libata.h>
 #include <linux/log2.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/regmap.h>
 
 #include "ahci.h"
 
@@ -90,6 +92,26 @@
 #define DWC_AHCI_PORT_PHYCR		0x74
 #define DWC_AHCI_PORT_PHYSR		0x78
 
+/* Baikal-T1 AHCI SATA specific registers */
+#define BT1_AHCI_HOST_PHYCR		DWC_AHCI_HOST_GPCR
+#define BT1_AHCI_HOST_MPLM_MASK		GENMASK(29, 23)
+#define BT1_AHCI_HOST_LOSDT_MASK	GENMASK(22, 20)
+#define BT1_AHCI_HOST_CRR		BIT(19)
+#define BT1_AHCI_HOST_CRW		BIT(18)
+#define BT1_AHCI_HOST_CRCD		BIT(17)
+#define BT1_AHCI_HOST_CRCA		BIT(16)
+#define BT1_AHCI_HOST_CRDI_MASK		GENMASK(15, 0)
+
+#define BT1_AHCI_HOST_PHYSR		DWC_AHCI_HOST_GPSR
+#define BT1_AHCI_HOST_CRA		BIT(16)
+#define BT1_AHCI_HOST_CRDO_MASK		GENMASK(15, 0)
+
+/* Baikal-T1 CCU registers concerning the AHCI SATA module */
+#define BT1_CCU_SYS_SATA_REF		0x60
+#define BT1_CCU_SYS_SATA_REF_EXT	BIT(28)
+#define BT1_CCU_SYS_SATA_REF_INV	BIT(29)
+#define BT1_CCU_SYS_SATA_REF_BUF	BIT(30)
+
 struct dwc_ahci_plat_data {
 	unsigned int pflags;
 	unsigned int hflags;
@@ -106,6 +128,64 @@ struct dwc_ahci_host_priv {
 	u32 dmacr[AHCI_MAX_PORTS];
 };
 
+static int bt1_ahci_init(struct ahci_host_priv *hpriv)
+{
+	struct dwc_ahci_host_priv *dpriv = hpriv->plat_data;
+	struct regmap *sys_regs;
+	u32 ref_ctl, mask;
+
+	/* APB and application clocks are required */
+	if (!ahci_platform_find_clk(hpriv, "pclk") ||
+	    !ahci_platform_find_clk(hpriv, "aclk")) {
+		dev_err(&dpriv->pdev->dev, "No system clocks specified\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * We need to select the PHY reference clock source. The signal
+	 * can be delivered either from the chip pads or from the internal
+	 * PLL. The source is selected by the PHY's ref_use_pad signal
+	 * tied up into one of the CCU SATA ref-ctl register field.
+	 */
+	sys_regs = syscon_regmap_lookup_by_phandle(dpriv->pdev->dev.of_node, "syscon");
+	if (IS_ERR(sys_regs)) {
+		dev_err(&dpriv->pdev->dev, "CCU syscon couldn't be found\n");
+		return PTR_ERR(sys_regs);
+	}
+
+	(void)regmap_read(sys_regs, BT1_CCU_SYS_SATA_REF, &ref_ctl);
+
+	/*
+	 * Prefer activating external reference clock if one is supplied.
+	 * If there is no external ref clock, then we have no choice but
+	 * to fall back to the internal signal coming from PLL. Alas
+	 * we haven't managed to make the interface working well when it's
+	 * used so far, but in no alternative let's at least try...
+	 */
+	if (ahci_platform_find_clk(hpriv, "ref_ext")) {
+		ref_ctl |= BT1_CCU_SYS_SATA_REF_EXT;
+		mask = BT1_CCU_SYS_SATA_REF_EXT;
+	} else if (ahci_platform_find_clk(hpriv, "ref_int")) {
+		ref_ctl &= ~BT1_CCU_SYS_SATA_REF_EXT;
+		ref_ctl |= BT1_CCU_SYS_SATA_REF_INV | BT1_CCU_SYS_SATA_REF_BUF;
+		mask = BT1_CCU_SYS_SATA_REF_EXT |
+		       BT1_CCU_SYS_SATA_REF_INV | BT1_CCU_SYS_SATA_REF_BUF;
+		dev_warn(&dpriv->pdev->dev, "Fallback to PLL-based ref clock!\n");
+	} else {
+		dev_err(&dpriv->pdev->dev, "No ref clock specified\n");
+		return -EINVAL;
+	}
+
+	regmap_update_bits(sys_regs, BT1_CCU_SYS_SATA_REF, mask, ref_ctl);
+
+	/*
+	 * Fully reset the SATA AXI and ref clocks domain so to ensure the
+	 * state machine is working from scratch.
+	 */
+	ahci_platform_assert_rsts(hpriv);
+	return ahci_platform_deassert_rsts(hpriv);
+}
+
 static struct ahci_host_priv *dwc_ahci_get_resources(struct platform_device *pdev)
 {
 	struct dwc_ahci_host_priv *dpriv;
@@ -415,9 +495,15 @@ struct dwc_ahci_plat_data dwc_ahci_plat = {
 	.pflags = AHCI_PLATFORM_GET_RESETS,
 };
 
+struct dwc_ahci_plat_data bt1_ahci_plat = {
+	.pflags = AHCI_PLATFORM_GET_RESETS | AHCI_PLATFORM_RST_TRIGGER,
+	.init = bt1_ahci_init,
+};
+
 static const struct of_device_id dwc_ahci_of_match[] = {
 	{ .compatible = "snps,dwc-ahci", &dwc_ahci_plat },
 	{ .compatible = "snps,spear-ahci", &dwc_ahci_plat },
+	{ .compatible = "baikal,bt1-ahci", &bt1_ahci_plat },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dwc_ahci_of_match);
-- 
2.35.1


  parent reply	other threads:[~2022-03-28 15:47 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-24  0:16 [PATCH 00/21] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
2022-03-24  0:16 ` [PATCH 01/21] dt-bindings: ata: sata: Extend number of SATA ports Serge Semin
2022-03-29  8:15   ` Damien Le Moal
2022-04-11 19:25     ` Serge Semin
2022-03-24  0:16 ` [PATCH 02/21] dt-bindings: ata: Convert AHCI-bindings to DT schema Serge Semin
2022-03-28 19:32   ` Rob Herring
2022-04-11 19:34     ` Serge Semin
2022-03-24  0:16 ` [PATCH 03/21] ata: libahci_platform: Explicitly set rc on devres_alloc failure Serge Semin
2022-03-24  0:58   ` Damien Le Moal
2022-03-24 21:37     ` Serge Semin
2022-03-25  1:56       ` Damien Le Moal
2022-04-06 20:03         ` Serge Semin
2022-03-29  8:20   ` Damien Le Moal
2022-03-24  0:16 ` [PATCH 04/21] ata: libahci_platform: Convert to using handy devm-ioremap methods Serge Semin
2022-03-24  1:11   ` Damien Le Moal
2022-04-06 20:42     ` Serge Semin
2022-03-24  0:16 ` [PATCH 05/21] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
2022-03-24  1:29   ` Damien Le Moal
2022-04-09  4:59     ` Serge Semin
2022-03-28 22:36   ` kernel test robot
2022-03-28 23:42   ` kernel test robot
2022-03-29  0:03   ` kernel test robot
2022-03-24  0:16 ` [PATCH 06/21] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
2022-03-24  1:36   ` Damien Le Moal
2022-04-11  6:02     ` Serge Semin
2022-03-24  0:16 ` [PATCH 07/21] ata: libahci_platform: Sanity check the DT child nodes number Serge Semin
2022-03-24  1:40   ` Damien Le Moal
2022-03-24  8:12     ` Sergey Shtylyov
2022-03-24  8:13       ` Damien Le Moal
2022-04-11 13:10         ` Serge Semin
2022-03-24  0:16 ` [PATCH 08/21] ata: libahci_platform: Parse ports-implemented property in resources getter Serge Semin
2022-03-24  0:16 ` [PATCH 09/21] ata: libahci_platform: Introduce reset assertion/deassertion methods Serge Semin
2022-03-24  1:52   ` Damien Le Moal
2022-04-11 10:57     ` Serge Semin
2022-03-24  0:16 ` [PATCH 10/21] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
2022-03-24  0:16 ` [PATCH 11/21] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
2022-03-24  0:16 ` [PATCH 12/21] ata: libahci: Discard redundant force_port_map parameter Serge Semin
2022-03-24  2:05   ` Damien Le Moal
2022-04-11 12:11     ` Serge Semin
2022-04-11 12:25       ` Damien Le Moal
2022-04-11 20:52         ` Serge Semin
2022-04-11 22:48           ` Damien Le Moal
2022-04-12 12:29             ` Serge Semin
2022-03-24  0:16 ` [PATCH 13/21] ata: libahci: Don't read AHCI version twice in the save-config method Serge Semin
2022-03-24  0:16 ` [PATCH 14/21] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
2022-03-24  0:16 ` [PATCH 15/21] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
2022-03-24  0:16 ` [PATCH 16/21] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
2022-04-01  0:06   ` Rob Herring
2022-04-11 20:00     ` Serge Semin
2022-03-24  0:16 ` [PATCH 17/21] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
2022-03-24  2:21   ` Damien Le Moal
2022-04-11 12:41     ` Serge Semin
2022-04-11 13:03       ` Damien Le Moal
2022-04-11 20:41         ` Serge Semin
2022-03-24  0:16 ` [PATCH 18/21] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
2022-03-24  0:16 ` [PATCH 19/21] ata: ahci-dwc: Add platform-specific quirks support Serge Semin
2022-03-24  0:16 ` Serge Semin [this message]
2022-03-24  0:16 ` [PATCH 21/21] MAINTAINERS: Add maintainers for DWC AHCI SATA driver Serge Semin
2022-03-24  2:17   ` Damien Le Moal
2022-04-11 12:16     ` Serge Semin
2022-03-28 20:06 ` [PATCH 00/21] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Damien Le Moal
2022-03-29  8:30   ` Damien Le Moal
2022-04-06 19:54     ` Serge Semin

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=20220324001628.13028-21-Sergey.Semin@baikalelectronics.ru \
    --to=sergey.semin@baikalelectronics.ru \
    --cc=Alexey.Malahov@baikalelectronics.ru \
    --cc=Pavel.Parkhomenko@baikalelectronics.ru \
    --cc=axboe@kernel.dk \
    --cc=damien.lemoal@opensource.wdc.com \
    --cc=devicetree@vger.kernel.org \
    --cc=fancer.lancer@gmail.com \
    --cc=hdegoede@redhat.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).