summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2018-12-04 20:28:28 +0100
committerJens Axboe <axboe@kernel.dk>2019-01-11 14:47:50 -0700
commit2f558bc3f33ca344489cec2218545741028b6a70 (patch)
tree524c3d3067653b83a4d3bb89d7e3e1e8b785e666
parent96dbcb40e4b1a387cdb9b21f43638c759aebb5a4 (diff)
downloadlinux-2f558bc3f33ca344489cec2218545741028b6a70.tar.gz
linux-2f558bc3f33ca344489cec2218545741028b6a70.tar.bz2
linux-2f558bc3f33ca344489cec2218545741028b6a70.zip
ata: ahci: mvebu: add Armada 3700 initialization needed for S2RAM
A3700 comphy initialization is done in the firmware (TF-A). Looking at the SATA PHY initialization routine, there is a comment about "vendor specific" registers. Two registers are mentioned. They are not initialized there in the firmware because they are AHCI related, while the firmware at this location does only PHY configuration. The solution to avoid doing such initialization is relying on U-Boot. While this work at boot time, U-Boot is definitely not going to run during a resume after suspending to RAM. Two possible solutions were considered: * Fixing the firmware. * Fixing the kernel driver. The first solution would take ages to propagate, while the second solution is easy to implement as the driver as been a little bit reworked to prepare for such platform configuration. Hence, this patch adds an Armada 3700 configuration function to set these two registers both at boot time (in the probe) and after a suspend (in the resume path). Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/ata/ahci_mvebu.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index 7839a5df1fd2..bbab688d3c34 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -82,6 +82,19 @@ static int ahci_mvebu_armada_380_config(struct ahci_host_priv *hpriv)
return rc;
}
+static int ahci_mvebu_armada_3700_config(struct ahci_host_priv *hpriv)
+{
+ u32 reg;
+
+ writel(0, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR);
+
+ reg = readl(hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+ reg |= BIT(6);
+ writel(reg, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+
+ return 0;
+}
+
/**
* ahci_mvebu_stop_engine
*
@@ -148,8 +161,7 @@ static int ahci_mvebu_resume(struct platform_device *pdev)
struct ahci_host_priv *hpriv = host->private_data;
const struct ahci_mvebu_plat_data *pdata = hpriv->plat_data;
- if (pdata->plat_config)
- pdata->plat_config(hpriv);
+ pdata->plat_config(hpriv);
return ahci_platform_resume_host(&pdev->dev);
}
@@ -191,12 +203,9 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
hpriv->stop_engine = ahci_mvebu_stop_engine;
- pdata = hpriv->plat_data;
- if (pdata->plat_config) {
- rc = pdata->plat_config(hpriv);
- if (rc)
- goto disable_resources;
- }
+ rc = pdata->plat_config(hpriv);
+ if (rc)
+ goto disable_resources;
rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
&ahci_platform_sht);
@@ -215,7 +224,7 @@ static const struct ahci_mvebu_plat_data ahci_mvebu_armada_380_plat_data = {
};
static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = {
- .plat_config = NULL,
+ .plat_config = ahci_mvebu_armada_3700_config,
};
static const struct of_device_id ahci_mvebu_of_match[] = {