summaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_mv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r--drivers/ata/sata_mv.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 05ff8c77649..d52ce118832 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -76,6 +76,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
+#include <linux/mbus.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -370,6 +371,9 @@ enum {
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
+#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
+
enum {
/* DMA boundary 0xffff is required by the s/g splitting
* we need on /length/ in mv_fill-sg().
@@ -2769,6 +2773,27 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
return 0;
}
+static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
+ struct mbus_dram_target_info *dram)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ writel(0, hpriv->base + WINDOW_CTRL(i));
+ writel(0, hpriv->base + WINDOW_BASE(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ writel(((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ hpriv->base + WINDOW_CTRL(i));
+ writel(cs->base, hpriv->base + WINDOW_BASE(i));
+ }
+}
+
/**
* mv_platform_probe - handle a positive probe of an soc Marvell
* host
@@ -2823,6 +2848,12 @@ static int mv_platform_probe(struct platform_device *pdev)
res->end - res->start + 1);
hpriv->base -= MV_SATAHC0_REG_BASE;
+ /*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (mv_platform_data->dram != NULL)
+ mv_conf_mbus_windows(hpriv, mv_platform_data->dram);
+
rc = mv_create_dma_pools(hpriv, &pdev->dev);
if (rc)
return rc;