forked from luck/tmp_suning_uos_patched
mtd: rawnand: cs553x: Implement exec_op()
So we can later get rid of the legacy hooks. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20200501090650.1138200-4-boris.brezillon@collabora.com
This commit is contained in:
parent
ba03e48339
commit
b4ed6328b9
|
@ -21,9 +21,9 @@
|
|||
#include <linux/mtd/rawnand.h>
|
||||
#include <linux/mtd/nand_ecc.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define NR_CS553X_CONTROLLERS 4
|
||||
|
||||
|
@ -165,6 +165,125 @@ static int cs553x_device_ready(struct nand_chip *this)
|
|||
return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
|
||||
}
|
||||
|
||||
static int cs553x_write_ctrl_byte(struct cs553x_nand_controller *cs553x,
|
||||
u32 ctl, u8 data)
|
||||
{
|
||||
u8 status;
|
||||
int ret;
|
||||
|
||||
writeb(ctl, cs553x->mmio + MM_NAND_CTL);
|
||||
writeb(data, cs553x->mmio + MM_NAND_IO);
|
||||
ret = readb_poll_timeout_atomic(cs553x->mmio + MM_NAND_STS, status,
|
||||
!(status & CS_NAND_CTLR_BUSY), 1,
|
||||
100000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs553x_data_in(struct cs553x_nand_controller *cs553x, void *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
writeb(0, cs553x->mmio + MM_NAND_CTL);
|
||||
while (unlikely(len > 0x800)) {
|
||||
memcpy_fromio(buf, cs553x->mmio, 0x800);
|
||||
buf += 0x800;
|
||||
len -= 0x800;
|
||||
}
|
||||
memcpy_fromio(buf, cs553x->mmio, len);
|
||||
}
|
||||
|
||||
static void cs553x_data_out(struct cs553x_nand_controller *cs553x,
|
||||
const void *buf, unsigned int len)
|
||||
{
|
||||
writeb(0, cs553x->mmio + MM_NAND_CTL);
|
||||
while (unlikely(len > 0x800)) {
|
||||
memcpy_toio(cs553x->mmio, buf, 0x800);
|
||||
buf += 0x800;
|
||||
len -= 0x800;
|
||||
}
|
||||
memcpy_toio(cs553x->mmio, buf, len);
|
||||
}
|
||||
|
||||
static int cs553x_wait_ready(struct cs553x_nand_controller *cs553x,
|
||||
unsigned int timeout_ms)
|
||||
{
|
||||
u8 mask = CS_NAND_CTLR_BUSY | CS_NAND_STS_FLASH_RDY;
|
||||
u8 status;
|
||||
|
||||
return readb_poll_timeout(cs553x->mmio + MM_NAND_STS, status,
|
||||
(status & mask) == CS_NAND_STS_FLASH_RDY, 100,
|
||||
timeout_ms * 1000);
|
||||
}
|
||||
|
||||
static int cs553x_exec_instr(struct cs553x_nand_controller *cs553x,
|
||||
const struct nand_op_instr *instr)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
|
||||
switch (instr->type) {
|
||||
case NAND_OP_CMD_INSTR:
|
||||
ret = cs553x_write_ctrl_byte(cs553x, CS_NAND_CTL_CLE,
|
||||
instr->ctx.cmd.opcode);
|
||||
break;
|
||||
|
||||
case NAND_OP_ADDR_INSTR:
|
||||
for (i = 0; i < instr->ctx.addr.naddrs; i++) {
|
||||
ret = cs553x_write_ctrl_byte(cs553x, CS_NAND_CTL_ALE,
|
||||
instr->ctx.addr.addrs[i]);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAND_OP_DATA_IN_INSTR:
|
||||
cs553x_data_in(cs553x, instr->ctx.data.buf.in,
|
||||
instr->ctx.data.len);
|
||||
break;
|
||||
|
||||
case NAND_OP_DATA_OUT_INSTR:
|
||||
cs553x_data_out(cs553x, instr->ctx.data.buf.out,
|
||||
instr->ctx.data.len);
|
||||
break;
|
||||
|
||||
case NAND_OP_WAITRDY_INSTR:
|
||||
ret = cs553x_wait_ready(cs553x, instr->ctx.waitrdy.timeout_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
if (instr->delay_ns)
|
||||
ndelay(instr->delay_ns);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs553x_exec_op(struct nand_chip *this,
|
||||
const struct nand_operation *op,
|
||||
bool check_only)
|
||||
{
|
||||
struct cs553x_nand_controller *cs553x = to_cs553x(this->controller);
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (check_only)
|
||||
return true;
|
||||
|
||||
/* De-assert the CE pin */
|
||||
writeb(0, cs553x->mmio + MM_NAND_CTL);
|
||||
for (i = 0; i < op->ninstrs; i++) {
|
||||
ret = cs553x_exec_instr(cs553x, &op->instrs[i]);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Re-assert the CE pin. */
|
||||
writeb(CS_NAND_CTL_CE, cs553x->mmio + MM_NAND_CTL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs_enable_hwecc(struct nand_chip *this, int mode)
|
||||
{
|
||||
struct cs553x_nand_controller *cs553x = to_cs553x(this->controller);
|
||||
|
@ -188,6 +307,10 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat,
|
|||
|
||||
static struct cs553x_nand_controller *controllers[4];
|
||||
|
||||
static const struct nand_controller_ops cs553x_nand_controller_ops = {
|
||||
.exec_op = cs553x_exec_op,
|
||||
};
|
||||
|
||||
static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
||||
{
|
||||
struct cs553x_nand_controller *controller;
|
||||
|
@ -212,6 +335,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
|||
|
||||
this = &controller->chip;
|
||||
nand_controller_init(&controller->base);
|
||||
controller->base.ops = &cs553x_nand_controller_ops;
|
||||
this->controller = &controller->base;
|
||||
new_mtd = nand_to_mtd(this);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user