diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 95e0e022b5bb..249717cdc74f 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -180,6 +180,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 f987efa1ad59..d464db20f869 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 AHCI_DWC_PORT_PHYCR		0x74
 #define AHCI_DWC_PORT_PHYSR		0x78
 
+/* Baikal-T1 AHCI SATA specific registers */
+#define AHCI_BT1_HOST_PHYCR		AHCI_DWC_HOST_GPCR
+#define AHCI_BT1_HOST_MPLM_MASK		GENMASK(29, 23)
+#define AHCI_BT1_HOST_LOSDT_MASK	GENMASK(22, 20)
+#define AHCI_BT1_HOST_CRR		BIT(19)
+#define AHCI_BT1_HOST_CRW		BIT(18)
+#define AHCI_BT1_HOST_CRCD		BIT(17)
+#define AHCI_BT1_HOST_CRCA		BIT(16)
+#define AHCI_BT1_HOST_CRDI_MASK		GENMASK(15, 0)
+
+#define AHCI_BT1_HOST_PHYSR		AHCI_DWC_HOST_GPSR
+#define AHCI_BT1_HOST_CRA		BIT(16)
+#define AHCI_BT1_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 ahci_dwc_plat_data {
 	unsigned int pflags;
 	unsigned int hflags;
@@ -106,6 +128,65 @@ struct ahci_dwc_host_priv {
 	u32 dmacr[AHCI_MAX_PORTS];
 };
 
+static int ahci_bt1_init(struct ahci_host_priv *hpriv)
+{
+	struct ahci_dwc_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,
+						   "baikal,bt1-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 *ahci_dwc_get_resources(struct platform_device *pdev)
 {
 	struct ahci_dwc_host_priv *dpriv;
@@ -415,9 +496,15 @@ struct ahci_dwc_plat_data ahci_dwc_plat = {
 	.pflags = AHCI_PLATFORM_GET_RESETS,
 };
 
+struct ahci_dwc_plat_data ahci_bt1_plat = {
+	.pflags = AHCI_PLATFORM_GET_RESETS | AHCI_PLATFORM_RST_TRIGGER,
+	.init = ahci_bt1_init,
+};
+
 static const struct of_device_id ahci_dwc_of_match[] = {
 	{ .compatible = "snps,dwc-ahci", &ahci_dwc_plat },
 	{ .compatible = "snps,spear-ahci", &ahci_dwc_plat },
+	{ .compatible = "baikal,bt1-ahci", &ahci_bt1_plat },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
