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 <pgeorgi@chromium.org>
Original-Commit-Id: 6ea0407f7273bc88613bc23a6fc4c41f9cca1adb
Original-Change-Id: Ic422e7265fdd35c573d8cd44280a1f7dc163a6db
Original-Signed-off-by: Bayi Cheng <bayi.cheng@mediatek.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/323932
Original-Commit-Ready: Yidi Lin <yidi.lin@mediatek.com>
Original-Tested-by: Yidi Lin <yidi.lin@mediatek.com>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/13979
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Bayi Cheng 2016-01-21 21:48:37 +08:00 committed by Patrick Georgi
parent 5ffb6887c2
commit d8bb51eb4e
2 changed files with 70 additions and 5 deletions

View File

@ -23,6 +23,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <symbols.h>
#include <timer.h> #include <timer.h>
#include <soc/flash_controller.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); 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); set_sfpaddr(addr);
while (len) { while (len) {
if (mt8173_nor_execute_cmd(SFLASH_RD_TRIGGER | SFLASH_AUTOINC)) if (mt8173_nor_execute_cmd(SFLASH_RD_TRIGGER | SFLASH_AUTOINC))
return -1; return -1;
*buffer++ = read8(&mt8173_nor->rdata); *buf++ = read8(&mt8173_nor->rdata);
len--; len--;
} }
return 0; 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, static int nor_write(struct spi_flash *flash, u32 addr, size_t len,
const void *buf) const void *buf)
{ {

View File

@ -27,6 +27,7 @@ enum {
SFLASHNAME_LENGTH = 16, SFLASHNAME_LENGTH = 16,
SFLASH_WRITE_IN_PROGRESS = 1, SFLASH_WRITE_IN_PROGRESS = 1,
SFLASH_COMMAND_ENABLE = 0x30, SFLASH_COMMAND_ENABLE = 0x30,
SFLASH_DMA_ALIGN = 0x10,
/* NOR flash controller commands */ /* NOR flash controller commands */
SFLASH_RD_TRIGGER = 1 << 0, SFLASH_RD_TRIGGER = 1 << 0,
@ -38,7 +39,11 @@ enum {
/* NOR flash commands */ /* NOR flash commands */
SFLASH_OP_WREN = 0x6, SFLASH_OP_WREN = 0x6,
SECTOR_ERASE_CMD = 0x20, 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 */ /* register Offset */
@ -72,8 +77,14 @@ struct mt8173_nor_regs {
u32 radr3; u32 radr3;
u32 read_dual; u32 read_dual;
u32 delsel[3]; 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; static struct mt8173_nor_regs * const mt8173_nor = (void *)SFLASH_REG_BASE;
struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi); struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi);