spi: rockchip_sfc add SPI Nand support

Change-Id: Ie31ccacd44d2a7b286db49fd5f18f1ecda663a6f
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin 2019-08-07 15:59:15 +08:00
parent c4d5fc6337
commit 39b850de47
1 changed files with 54 additions and 11 deletions

View File

@ -22,6 +22,12 @@
DECLARE_GLOBAL_DATA_PTR;
#ifdef SFC_DEBUG
#define SFC_DBG printf
#else
#define SFC_DBG(args...)
#endif
struct rockchip_sfc_reg {
u32 ctrl;
u32 imr;
@ -42,6 +48,7 @@ struct rockchip_sfc_reg {
u32 addr;
u32 data;
};
check_member(rockchip_sfc_reg, data, 0x108);
/*SFC_CTRL*/
@ -196,7 +203,9 @@ static int rockchip_sfc_wait_idle(struct rockchip_sfc *sfc,
while (1) {
sr = readl(&regs->sr);
fsr = readl(&regs->fsr);
if ((fsr & SFC_TX_EMPTY) && (fsr & SFC_RX_EMPTY) && !(sr & SFC_BUSY))
if ((fsr & SFC_TX_EMPTY) &&
(fsr & SFC_RX_EMPTY) &&
!(sr & SFC_BUSY))
break;
if (get_timer(tbase) > timeout_ms) {
printf("waite sfc idle timeout(sr:0x%08x fsr:0x%08x)\n",
@ -239,13 +248,39 @@ static void rockchip_sfc_setup_xfer(struct rockchip_sfc *sfc, u32 trb)
u32 val = 0x02;
u8 data_width = IF_TYPE_STD;
if (sfc->addr_bits & SFC_ADDR_XBITS)
switch (sfc->addr_bits) {
case 0:
sfc->addr_bits = SFC_ADDR_0BITS;
break;
case 8:
sfc->addr_bits = SFC_ADDR_XBITS;
writel(7, &regs->abit);
break;
case 16:
sfc->addr_bits = SFC_ADDR_XBITS;
writel(15, &regs->abit);
break;
case 24:
sfc->addr_bits = SFC_ADDR_24BITS;
break;
case 32:
sfc->addr_bits = SFC_ADDR_32BITS;
break;
default:
pr_err("%s addr-bits error %d\n", __func__, sfc->addr_bits);
return;
}
SFC_DBG("--- sfc.addr_bit %x\n", sfc->addr_bits);
if (sfc->addr_bits == SFC_ADDR_24BITS ||
sfc->addr_bits == SFC_ADDR_32BITS)
data_width = rockchip_sfc_get_if_type(sfc);
val |= (data_width << SFC_DATA_WIDTH_SHIFT);
rockchip_sfc_wait_idle(sfc, 10);
SFC_DBG("--- sfc.ctrl %x\n", val);
writel(val, &regs->ctrl);
val = sfc->cmd;
@ -254,11 +289,14 @@ static void rockchip_sfc_setup_xfer(struct rockchip_sfc *sfc, u32 trb)
val |= sfc->addr_bits << SFC_ADDR_BITS_SHIFT;
val |= sfc->dummy_bits << SFC_DUMMY_BITS_SHIFT;
SFC_DBG("--- sfc.cmd %x\n", val);
writel(val, &regs->cmd);
if (sfc->addr_bits & SFC_ADDR_XBITS)
if (sfc->addr_bits & SFC_ADDR_XBITS) {
SFC_DBG("--- sfc.addr %x\n", sfc->addr);
writel(sfc->addr, &regs->addr);
}
}
static int rockchip_sfc_dma_xfer(struct rockchip_sfc *sfc, void *buffer, size_t trb)
{
@ -441,7 +479,6 @@ static int rockchip_sfc_read(struct rockchip_sfc *sfc, u32 offset,
static int rockchip_sfc_write(struct rockchip_sfc *sfc, u32 offset,
void *buf, size_t len)
{
if (len > SFC_MAX_TRB) {
printf("out of the max sfc trb");
return -EINVAL;
@ -457,7 +494,6 @@ static int rockchip_sfc_write(struct rockchip_sfc *sfc, u32 offset,
static int rockchip_sfc_do_xfer(struct rockchip_sfc *sfc, void *buf, size_t len)
{
if (sfc->rw)
return rockchip_sfc_write(sfc, sfc->addr, buf, len);
else
@ -477,9 +513,17 @@ static int rockchip_sfc_xfer(struct udevice *dev, unsigned int bitlen,
if (flags & SPI_XFER_BEGIN) {
sfc->cmd = pcmd[0];
if (len >= 4) {
sfc->addr_bits = SFC_ADDR_24BITS;
sfc->addr_bits = 24;
sfc->dummy_bits = (len - 4) << 3;
sfc->addr = pcmd[3] | (pcmd[2] << 8) | (pcmd[1] << 16);
} else if (len == 3 && dout) {
sfc->addr_bits = 16;
sfc->dummy_bits = 0;
sfc->addr = pcmd[2] | pcmd[1] << 8;
} else if (len == 2 && dout) {
sfc->addr_bits = 8;
sfc->dummy_bits = 0;
sfc->addr = pcmd[1];
} else {
sfc->addr_bits = 0;
sfc->dummy_bits = 0;
@ -488,7 +532,6 @@ static int rockchip_sfc_xfer(struct udevice *dev, unsigned int bitlen,
}
if (flags & SPI_XFER_END) {
if (din) {
sfc->rw = SFC_RD;
data_buf = din;