summaryrefslogtreecommitdiff
path: root/src/soc/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/mediatek')
-rw-r--r--src/soc/mediatek/mt8173/flash_controller.c60
-rw-r--r--src/soc/mediatek/mt8173/include/soc/flash_controller.h15
2 files changed, 70 insertions, 5 deletions
diff --git a/src/soc/mediatek/mt8173/flash_controller.c b/src/soc/mediatek/mt8173/flash_controller.c
index 3cd81a226a..f66291661e 100644
--- a/src/soc/mediatek/mt8173/flash_controller.c
+++ b/src/soc/mediatek/mt8173/flash_controller.c
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <symbols.h>
#include <timer.h>
#include <soc/flash_controller.h>
@@ -111,21 +112,74 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
return min(65535, buf_len);
}
-static int nor_read(struct spi_flash *flash, u32 addr, size_t len, void *buf)
+static int dma_read(u32 addr, u8 *buf, u32 len)
{
- u8 *buffer = (u8 *)buf;
+ struct stopwatch sw;
+
+ assert(IS_ALIGNED((uintptr_t)buf, SFLASH_DMA_ALIGN) &&
+ IS_ALIGNED(len, SFLASH_DMA_ALIGN) &&
+ len <= _dma_coherent_size);
+
+ /* do dma reset */
+ write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_SW_RESET);
+ write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_WDLE_EN);
+ /* flash source address and dram dest address */
+ write32(&mt8173_nor->fdma_fadr, addr);
+ write32(&mt8173_nor->fdma_dadr, ((uintptr_t)_dma_coherent ));
+ write32(&mt8173_nor->fdma_end_dadr, ((uintptr_t)_dma_coherent + len));
+ /* start dma */
+ write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_TRIGGER | SFLASH_DMA_WDLE_EN);
+
+ stopwatch_init_usecs_expire(&sw, SFLASH_POLLINGREG_US);
+ while ((read32(&mt8173_nor->fdma_ctl) & SFLASH_DMA_TRIGGER) != 0) {
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_WARNING, "dma read timeout!\n");
+ return -1;
+ }
+ }
+
+ memcpy(buf, _dma_coherent, len);
+ return 0;
+}
+static int pio_read(u32 addr, u8 *buf, u32 len)
+{
set_sfpaddr(addr);
while (len) {
if (mt8173_nor_execute_cmd(SFLASH_RD_TRIGGER | SFLASH_AUTOINC))
return -1;
- *buffer++ = read8(&mt8173_nor->rdata);
+ *buf++ = read8(&mt8173_nor->rdata);
len--;
}
return 0;
}
+static int nor_read(struct spi_flash *flash, u32 addr, size_t len, void *buf)
+{
+ u32 next;
+
+ size_t done = 0;
+ if (!IS_ALIGNED((uintptr_t)buf, SFLASH_DMA_ALIGN)) {
+ next = MIN(ALIGN_UP((uintptr_t)buf, SFLASH_DMA_ALIGN) -
+ (uintptr_t)buf, len);
+ if (pio_read(addr, buf, next))
+ return -1;
+ done += next;
+ }
+ while (len - done >= SFLASH_DMA_ALIGN) {
+ next = MIN(_dma_coherent_size, ALIGN_DOWN(len - done,
+ SFLASH_DMA_ALIGN));
+ if (dma_read(addr + done, buf + done, next))
+ return -1;
+ done += next;
+ }
+ next = len - done;
+ if (next > 0 && pio_read(addr + done, buf + done, next))
+ return -1;
+ return 0;
+}
+
static int nor_write(struct spi_flash *flash, u32 addr, size_t len,
const void *buf)
{
diff --git a/src/soc/mediatek/mt8173/include/soc/flash_controller.h b/src/soc/mediatek/mt8173/include/soc/flash_controller.h
index 2527d6be6a..1d2ac32432 100644
--- a/src/soc/mediatek/mt8173/include/soc/flash_controller.h
+++ b/src/soc/mediatek/mt8173/include/soc/flash_controller.h
@@ -27,6 +27,7 @@ enum {
SFLASHNAME_LENGTH = 16,
SFLASH_WRITE_IN_PROGRESS = 1,
SFLASH_COMMAND_ENABLE = 0x30,
+ SFLASH_DMA_ALIGN = 0x10,
/* NOR flash controller commands */
SFLASH_RD_TRIGGER = 1 << 0,
@@ -38,7 +39,11 @@ enum {
/* NOR flash commands */
SFLASH_OP_WREN = 0x6,
SECTOR_ERASE_CMD = 0x20,
- SFLASH_UNPROTECTED = 0x0
+ SFLASH_UNPROTECTED = 0x0,
+ /* DMA commands */
+ SFLASH_DMA_TRIGGER = 1 << 0,
+ SFLASH_DMA_SW_RESET = 1 << 1,
+ SFLASH_DMA_WDLE_EN = 1 << 2
};
/* register Offset */
@@ -72,8 +77,14 @@ struct mt8173_nor_regs {
u32 radr3;
u32 read_dual;
u32 delsel[3];
+ u32 reserved[397];
+ u32 cfg1_bri[2];
+ u32 fdma_ctl;
+ u32 fdma_fadr;
+ u32 fdma_dadr;
+ u32 fdma_end_dadr;
};
-check_member(mt8173_nor_regs, delsel[2], 0xD8);
+check_member(mt8173_nor_regs, fdma_end_dadr, 0x724);
static struct mt8173_nor_regs * const mt8173_nor = (void *)SFLASH_REG_BASE;
struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi);