diff options
-rw-r--r-- | drivers/mtd/nand/raw/loongson-nand-controller.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/mtd/nand/raw/loongson-nand-controller.c b/drivers/mtd/nand/raw/loongson-nand-controller.c index b5a7be0fcacc..97cd566420a8 100644 --- a/drivers/mtd/nand/raw/loongson-nand-controller.c +++ b/drivers/mtd/nand/raw/loongson-nand-controller.c @@ -50,6 +50,9 @@ #define LOONGSON_NAND_COL_ADDR_CYC 2U #define LOONGSON_NAND_MAX_ADDR_CYC 5U +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000 +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 + #define BITS_PER_WORD (4 * BITS_PER_BYTE) struct loongson_nand_host; @@ -73,6 +76,8 @@ struct loongson_nand_op { }; struct loongson_nand_data { + unsigned int max_id_cycle; + unsigned int id_cycle_field; unsigned int status_field; unsigned int op_scope_field; unsigned int hold_cycle; @@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct struct loongson_nand_op op = {}; int i, ret; union { - char ids[5]; + char ids[6]; struct { int idl; - char idh; + u16 idh; }; } nand_id; @@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct if (ret) return ret; - nand_id.idl = readl(host->reg_base + LOONGSON_NAND_IDL); - nand_id.idh = readb(host->reg_base + LOONGSON_NAND_IDH_STATUS); + ret = regmap_read_poll_timeout(host->regmap, LOONGSON_NAND_IDL, nand_id.idl, nand_id.idl, + LOONGSON_NAND_READ_ID_SLEEP_US, + LOONGSON_NAND_READ_ID_TIMEOUT_US); + if (ret) + return ret; - for (i = 0; i < min(sizeof(nand_id.ids), op.orig_len); i++) - op.buf[i] = nand_id.ids[sizeof(nand_id.ids) - 1 - i]; + nand_id.idh = readw(host->reg_base + LOONGSON_NAND_IDH_STATUS); + + for (i = 0; i < min(host->data->max_id_cycle, op.orig_len); i++) + op.buf[i] = nand_id.ids[host->data->max_id_cycle - 1 - i]; return ret; } @@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host) if (IS_ERR(host->regmap)) return dev_err_probe(dev, PTR_ERR(host->regmap), "failed to init regmap\n"); + if (host->data->id_cycle_field) + regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field, + host->data->max_id_cycle << __ffs(host->data->id_cycle_field)); + chan = dma_request_chan(dev, "rxtx"); if (IS_ERR(chan)) return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n"); @@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev) } static const struct loongson_nand_data ls1b_nand_data = { + .max_id_cycle = 5, .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, @@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = { }; static const struct loongson_nand_data ls1c_nand_data = { + .max_id_cycle = 6, + .id_cycle_field = GENMASK(14, 12), .status_field = GENMASK(23, 16), .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, |