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:
parent
5ffb6887c2
commit
d8bb51eb4e
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue