Commit 90b276f6 authored by Taylor Hutt's avatar Taylor Hutt Committed by Tom Rini
Browse files

ahci: flush / invalidate dcache around SATA commands



Exynos5 automatically performs DMA when the SATA controller executes
commands.  This adds the necessary dcache-to-memory flush &
invalidation calls to allow the DMA to properly function.
Signed-off-by: default avatarTaylor Hutt <thutt@chromium.org>
Signed-off-by: default avatarSimon Glass <sjg@chromium.org>
parent 64738e8a
...@@ -70,6 +70,39 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base, ...@@ -70,6 +70,39 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
#define msleep(a) udelay(a * 1000) #define msleep(a) udelay(a * 1000)
static void ahci_dcache_flush_range(unsigned begin, unsigned len)
{
const unsigned long start = begin;
const unsigned long end = start + len;
debug("%s: flush dcache: [%#lx, %#lx)\n", __func__, start, end);
flush_dcache_range(start, end);
}
/*
* SATA controller DMAs to physical RAM. Ensure data from the
* controller is invalidated from dcache; next access comes from
* physical RAM.
*/
static void ahci_dcache_invalidate_range(unsigned begin, unsigned len)
{
const unsigned long start = begin;
const unsigned long end = start + len;
debug("%s: invalidate dcache: [%#lx, %#lx)\n", __func__, start, end);
invalidate_dcache_range(start, end);
}
/*
* Ensure data for SATA controller is flushed out of dcache and
* written to physical memory.
*/
static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp)
{
ahci_dcache_flush_range((unsigned long)pp->cmd_slot,
AHCI_PORT_PRIV_DMA_SZ);
}
static int waiting_for_cmd_completed(volatile u8 *offset, static int waiting_for_cmd_completed(volatile u8 *offset,
int timeout_msec, int timeout_msec,
u32 sign) u32 sign)
...@@ -392,6 +425,7 @@ static void ahci_set_feature(u8 port) ...@@ -392,6 +425,7 @@ static void ahci_set_feature(u8 port)
memcpy((unsigned char *)pp->cmd_tbl, fis, sizeof(fis)); memcpy((unsigned char *)pp->cmd_tbl, fis, sizeof(fis));
ahci_fill_cmd_slot(pp, cmd_fis_len); ahci_fill_cmd_slot(pp, cmd_fis_len);
ahci_dcache_flush_sata_cmd(pp);
writel(1, port_mmio + PORT_CMD_ISSUE); writel(1, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); readl(port_mmio + PORT_CMD_ISSUE);
...@@ -496,12 +530,17 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, ...@@ -496,12 +530,17 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6); opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6);
ahci_fill_cmd_slot(pp, opts); ahci_fill_cmd_slot(pp, opts);
ahci_dcache_flush_sata_cmd(pp);
ahci_dcache_flush_range((unsigned)buf, (unsigned)buf_len);
writel_with_flush(1, port_mmio + PORT_CMD_ISSUE); writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 150, 0x1)) { if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 150, 0x1)) {
printf("timeout exit!\n"); printf("timeout exit!\n");
return -1; return -1;
} }
ahci_dcache_invalidate_range((unsigned)buf, (unsigned)buf_len);
debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status); debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status);
return 0; return 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment