From d8bb51eb4e00882259862129325aa7bf160f79c3 Mon Sep 17 00:00:00 2001 From: Bayi Cheng Date: Thu, 21 Jan 2016 21:48:37 +0800 Subject: [PATCH] mediatek/mt8173: add NOR DMA read BRANCH=none BUG=none TEST=boot oak to kernel on rev2 Change-Id: I368fcac1cf5e2261d00a34882a7341733ebd0732 Signed-off-by: Patrick Georgi Original-Commit-Id: 6ea0407f7273bc88613bc23a6fc4c41f9cca1adb Original-Change-Id: Ic422e7265fdd35c573d8cd44280a1f7dc163a6db Original-Signed-off-by: Bayi Cheng Original-Reviewed-on: https://chromium-review.googlesource.com/323932 Original-Commit-Ready: Yidi Lin Original-Tested-by: Yidi Lin Original-Reviewed-by: Julius Werner Reviewed-on: https://review.coreboot.org/13979 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/soc/mediatek/mt8173/flash_controller.c | 60 ++++++++++++++++++- .../mt8173/include/soc/flash_controller.h | 15 ++++- 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 #include #include +#include #include #include @@ -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);