diff options
Diffstat (limited to 'drivers/mtd/nand/nand_mrvl_nfc.c')
-rw-r--r-- | drivers/mtd/nand/nand_mrvl_nfc.c | 152 |
1 files changed, 90 insertions, 62 deletions
diff --git a/drivers/mtd/nand/nand_mrvl_nfc.c b/drivers/mtd/nand/nand_mrvl_nfc.c index 15d052b5a4..1f3e152375 100644 --- a/drivers/mtd/nand/nand_mrvl_nfc.c +++ b/drivers/mtd/nand/nand_mrvl_nfc.c @@ -20,6 +20,7 @@ #include <init.h> #include <io.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/rawnand.h> #include <linux/mtd/nand.h> #include <linux/types.h> #include <linux/clk.h> @@ -277,8 +278,10 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = { #define NDTR1_tWHR(c) (min((c), 15) << 4) #define NDTR1_tAR(c) (min((c), 15) << 0) -#define mtd_info_to_host(mtd) ((struct mrvl_nand_host *) \ - (((struct nand_chip *)((mtd)->priv))->priv)) +static inline struct mrvl_nand_host *nand_to_host(struct nand_chip *chip) +{ + return container_of(chip, struct mrvl_nand_host, chip); +} static const struct mrvl_nand_variant pxa3xx_variant = { .hwflags = 0, @@ -341,7 +344,7 @@ static struct mrvl_nand_timing timings[] = { static void mrvl_nand_set_timing(struct mrvl_nand_host *host, bool use_default) { - struct mtd_info *mtd = &host->chip.mtd; + struct nand_chip *chip = &host->chip; unsigned long nand_clk = clk_get_rate(host->core_clk); struct mrvl_nand_timing *t; uint32_t ndtr0, ndtr1; @@ -350,8 +353,8 @@ static void mrvl_nand_set_timing(struct mrvl_nand_host *host, bool use_default) if (use_default) { id = 0; } else { - host->chip.cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - host->chip.read_buf(mtd, (unsigned char *)&id, sizeof(id)); + chip->legacy.cmdfunc(chip, NAND_CMD_READID, 0x00, -1); + chip->legacy.read_buf(chip, (unsigned char *)&id, sizeof(id)); } for (t = &timings[0]; t->id; t++) if (t->id == id) @@ -370,9 +373,9 @@ static void mrvl_nand_set_timing(struct mrvl_nand_host *host, bool use_default) nand_writel(host, NDTR1CS0, ndtr1); } -static int mrvl_nand_ready(struct mtd_info *mtd) +static int mrvl_nand_ready(struct nand_chip *chip) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mrvl_nand_host *host = nand_to_host(chip); u32 ndcr; ndcr = nand_readl(host, NDSR); @@ -396,14 +399,14 @@ static int mrvl_nand_ready(struct mtd_info *mtd) * Thus, this function is only called when we want *all* blocks to look good, * so it *always* return success. */ -static int mrvl_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int mrvl_nand_block_bad(struct nand_chip *chip, loff_t ofs) { return 0; } -static void mrvl_nand_select_chip(struct mtd_info *mtd, int chipnr) +static void mrvl_nand_select_chip(struct nand_chip *chip, int chipnr) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mrvl_nand_host *host = nand_to_host(chip); if (chipnr <= 0 || chipnr >= 3 || chipnr == host->cs) return; @@ -417,9 +420,12 @@ static void mrvl_nand_select_chip(struct mtd_info *mtd, int chipnr) */ static unsigned int mrvl_datasize(struct mrvl_nand_host *host) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + unsigned int datasize; - datasize = host->chip.mtd.writesize; + datasize = mtd->writesize; if (host->use_spare) { datasize += host->spare_size; if (!host->use_ecc) @@ -470,7 +476,7 @@ static void mrvl_nand_start(struct mrvl_nand_host *host) nand_writel(host, NDSR, NDSR_MASK); nand_writel(host, NDCR, ndcr | NDCR_ND_RUN); - if (wait_on_timeout(host->chip.chip_delay * USECOND, + if (wait_on_timeout(host->chip.legacy.chip_delay * USECOND, nand_readl(host, NDSR) & NDSR_WRCMDREQ)) { dev_err(host->dev, "Waiting for command request failed\n"); } else { @@ -529,6 +535,9 @@ static void set_command_address(struct mrvl_nand_host *host, static void prepare_start_command(struct mrvl_nand_host *host, int command) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + /* reset data and oob column point to handle data */ host->buf_start = 0; host->buf_count = 0; @@ -571,7 +580,7 @@ static void prepare_start_command(struct mrvl_nand_host *host, int command) if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB || command == NAND_CMD_SEQIN) { - host->buf_count = host->chip.mtd.writesize + host->chip.mtd.oobsize; + host->buf_count = mtd->writesize + mtd->oobsize; memset(host->data_buff, 0xFF, host->buf_count); } @@ -588,10 +597,10 @@ static void prepare_start_command(struct mrvl_nand_host *host, int command) static int prepare_set_command(struct mrvl_nand_host *host, int command, int ext_cmd_type, uint16_t column, int page_addr) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); int addr_cycle, exec_cmd; - struct mtd_info *mtd; - mtd = &host->chip.mtd; exec_cmd = 1; if (host->cs != 0) @@ -717,7 +726,7 @@ static void mrvl_data_stage(struct mrvl_nand_host *host) if (!host->data_size) return; - wait_on_timeout(host->chip.chip_delay * USECOND, + wait_on_timeout(host->chip.legacy.chip_delay * USECOND, nand_readl(host, NDSR) & mask); if (!(nand_readl(host, NDSR) & mask)) { dev_err(host->dev, "Timeout waiting for data ndsr=0x%08x\n", @@ -750,7 +759,7 @@ static void mrvl_nand_wait_cmd_done(struct mrvl_nand_host *host, mask = NDSR_CS0_CMDD; else mask = NDSR_CS1_CMDD; - wait_on_timeout(host->chip.chip_delay * USECOND, + wait_on_timeout(host->chip.legacy.chip_delay * USECOND, (nand_readl(host, NDSR) & mask) == mask); if ((nand_readl(host, NDSR) & mask) != mask) { dev_err(host->dev, "Waiting end of command %dth %d timeout, ndsr=0x%08x ndcr=0x%08x\n", @@ -759,10 +768,10 @@ static void mrvl_nand_wait_cmd_done(struct mrvl_nand_host *host, } } -static void mrvl_nand_cmdfunc(struct mtd_info *mtd, unsigned command, +static void mrvl_nand_cmdfunc(struct nand_chip *chip, unsigned command, int column, int page_addr) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mrvl_nand_host *host = nand_to_host(chip); /* * if this is a x16 device ,then convert the input @@ -790,10 +799,13 @@ static void mrvl_nand_cmdfunc(struct mtd_info *mtd, unsigned command, * * Returns 0 */ -static int mrvl_nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required) +static int mrvl_nand_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mrvl_nand_host *host = nand_to_host(chip); + + nand_prog_page_begin_op(chip, page, 0, NULL, 0); memcpy(host->data_buff, buf, mtd->writesize); if (oob_required) @@ -803,19 +815,22 @@ static int mrvl_nand_write_page_hwecc(struct mtd_info *mtd, memset(host->data_buff + mtd->writesize, 0xff, mtd->oobsize); dev_dbg(host->dev, "%s(buf=%p, oob_required=%d) => 0\n", __func__, buf, oob_required); - return 0; + + return nand_prog_page_end_op(chip); } -static int mrvl_nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, - int page) +static int mrvl_nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mrvl_nand_host *host = nand_to_host(chip); u32 ndsr; int ret = 0; - chip->read_buf(mtd, buf, mtd->writesize); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_read_page_op(chip, page, 0, NULL, 0); + + chip->legacy.read_buf(chip, buf, mtd->writesize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); ndsr = nand_readl(host, NDSR); if (ndsr & NDSR_UNCORERR) { @@ -837,9 +852,9 @@ static int mrvl_nand_read_page_hwecc(struct mtd_info *mtd, return ret; } -static void mrvl_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void mrvl_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mrvl_nand_host *host = nand_to_host(chip); int xfer; xfer = min_t(int, len, host->buf_count); @@ -848,26 +863,26 @@ static void mrvl_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) host->buf_count -= xfer; } -static uint8_t mrvl_nand_read_byte(struct mtd_info *mtd) +static uint8_t mrvl_nand_read_byte(struct nand_chip *chip) { uint8_t ret; - mrvl_nand_read_buf(mtd, (uint8_t *)&ret, sizeof(ret)); + mrvl_nand_read_buf(chip, (uint8_t *)&ret, sizeof(ret)); return ret; } -static u16 mrvl_nand_read_word(struct mtd_info *mtd) +static u16 mrvl_nand_read_word(struct nand_chip *chip) { u16 ret; - mrvl_nand_read_buf(mtd, (uint8_t *)&ret, sizeof(ret)); + mrvl_nand_read_buf(chip, (uint8_t *)&ret, sizeof(ret)); return ret; } -static void mrvl_nand_write_buf(struct mtd_info *mtd, +static void mrvl_nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct mrvl_nand_host *host = mtd_info_to_host(mtd); + struct mrvl_nand_host *host = nand_to_host(chip); memcpy(host->data_buff + host->buf_start, buf, len); host->buf_start += len; @@ -877,7 +892,7 @@ static void mrvl_nand_write_buf(struct mtd_info *mtd, static void mrvl_nand_config_flash(struct mrvl_nand_host *host) { struct nand_chip *chip = &host->chip; - struct mtd_info *mtd = &host->chip.mtd; + struct mtd_info *mtd = nand_to_mtd(chip); uint32_t ndcr = host->reg_ndcr; /* calculate flash information */ @@ -911,6 +926,9 @@ static void mrvl_nand_config_flash(struct mrvl_nand_host *host) static int pxa_ecc_strength1(struct mrvl_nand_host *host, struct nand_ecc_ctrl *ecc, int ecc_stepsize, int page_size) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + if (ecc_stepsize == 512 && page_size == 2048) { host->chunk_size = 2048; host->spare_size = 40; @@ -919,7 +937,7 @@ static int pxa_ecc_strength1(struct mrvl_nand_host *host, ecc->mode = NAND_ECC_HW; ecc->size = 512; ecc->strength = 1; - ecc->layout = &ecc_layout_2KB_hwecc; + mtd_set_ecclayout(mtd, &ecc_layout_2KB_hwecc); return 0; } @@ -930,7 +948,7 @@ static int pxa_ecc_strength1(struct mrvl_nand_host *host, host->ecc_bch = 0; ecc->mode = NAND_ECC_HW; ecc->size = 512; - ecc->layout = &ecc_layout_512B_hwecc; + mtd_set_ecclayout(mtd, &ecc_layout_512B_hwecc); ecc->strength = 1; return 0; } @@ -941,6 +959,9 @@ static int pxa_ecc_strength1(struct mrvl_nand_host *host, static int pxa_ecc_strength4(struct mrvl_nand_host *host, struct nand_ecc_ctrl *ecc, int ecc_stepsize, int page_size) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + if (!(host->hwflags & HWFLAGS_ECC_BCH)) return -ENODEV; @@ -955,7 +976,7 @@ static int pxa_ecc_strength4(struct mrvl_nand_host *host, host->ecc_bch = 1; ecc->mode = NAND_ECC_HW; ecc->size = 2048; - ecc->layout = &ecc_layout_2KB_bch4bit; + mtd_set_ecclayout(mtd, &ecc_layout_2KB_bch4bit); ecc->strength = 16; return 0; } @@ -967,7 +988,7 @@ static int pxa_ecc_strength4(struct mrvl_nand_host *host, host->ecc_bch = 1; ecc->mode = NAND_ECC_HW; ecc->size = 2048; - ecc->layout = &ecc_layout_4KB_bch4bit; + mtd_set_ecclayout(mtd, &ecc_layout_4KB_bch4bit); ecc->strength = 16; return 0; } @@ -978,6 +999,9 @@ static int pxa_ecc_strength4(struct mrvl_nand_host *host, static int pxa_ecc_strength8(struct mrvl_nand_host *host, struct nand_ecc_ctrl *ecc, int ecc_stepsize, int page_size) { + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + if (!(host->hwflags & HWFLAGS_ECC_BCH)) return -ENODEV; @@ -992,7 +1016,7 @@ static int pxa_ecc_strength8(struct mrvl_nand_host *host, host->ecc_bch = 1; ecc->mode = NAND_ECC_HW; ecc->size = 1024; - ecc->layout = &ecc_layout_4KB_bch8bit; + mtd_set_ecclayout(mtd, &ecc_layout_4KB_bch8bit); ecc->strength = 16; return 0; } @@ -1033,9 +1057,9 @@ static int pxa_ecc_init(struct mrvl_nand_host *host, return 0; } -static int mrvl_nand_scan(struct mtd_info *mtd) +static int mrvl_nand_scan(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct mrvl_nand_host *host = chip->priv; int ret; unsigned int ndcr; @@ -1053,9 +1077,9 @@ static int mrvl_nand_scan(struct mtd_info *mtd) nand_readl(host, NDECCCTRL) & ~NDECCCTRL_BCH_EN); mrvl_nand_set_timing(host, true); - if (nand_scan_ident(mtd, 1, NULL)) { + if (nand_scan_ident(chip, 1, NULL)) { host->reg_ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C; - if (nand_scan_ident(mtd, 1, NULL)) + if (nand_scan_ident(chip, 1, NULL)) return -ENODEV; } mrvl_nand_config_flash(host); @@ -1099,7 +1123,7 @@ static int mrvl_nand_scan(struct mtd_info *mtd) host->buf_size = mtd->writesize + mtd->oobsize; host->data_buff = xmalloc(host->buf_size); - return nand_scan_tail(mtd); + return nand_scan_tail(chip); } static struct mrvl_nand_host *alloc_nand_resource(struct device_d *dev) @@ -1114,24 +1138,24 @@ static struct mrvl_nand_host *alloc_nand_resource(struct device_d *dev) host = xzalloc(sizeof(*host)); host->num_cs = 1; host->cs = 0; - mtd = &host->chip.mtd; - mtd->parent = dev; + mtd = nand_to_mtd(&host->chip); + mtd->dev.parent = dev; mtd->name = "mrvl_nand"; chip = &host->chip; - chip->read_byte = mrvl_nand_read_byte; - chip->read_word = mrvl_nand_read_word; + chip->legacy.read_byte = mrvl_nand_read_byte; + chip->legacy.read_word = mrvl_nand_read_word; chip->ecc.read_page = mrvl_nand_read_page_hwecc; chip->ecc.write_page = mrvl_nand_write_page_hwecc; - chip->dev_ready = mrvl_nand_ready; - chip->select_chip = mrvl_nand_select_chip; - chip->block_bad = mrvl_nand_block_bad; - chip->read_buf = mrvl_nand_read_buf; - chip->write_buf = mrvl_nand_write_buf; + chip->legacy.dev_ready = mrvl_nand_ready; + chip->legacy.select_chip = mrvl_nand_select_chip; + chip->legacy.block_bad = mrvl_nand_block_bad; + chip->legacy.read_buf = mrvl_nand_read_buf; + chip->legacy.write_buf = mrvl_nand_write_buf; chip->options |= NAND_NO_SUBPAGE_WRITE; - chip->cmdfunc = mrvl_nand_cmdfunc; + chip->legacy.cmdfunc = mrvl_nand_cmdfunc; chip->priv = host; - chip->chip_delay = CHIP_DELAY_TIMEOUT_US; + chip->legacy.chip_delay = CHIP_DELAY_TIMEOUT_US; host->dev = dev; iores = dev_request_mem_resource(dev, 0); @@ -1201,6 +1225,8 @@ static int mrvl_nand_probe_dt(struct mrvl_nand_host *host) static int mrvl_nand_probe(struct device_d *dev) { struct mrvl_nand_host *host; + struct nand_chip *chip; + struct mtd_info *mtd; int ret; host = alloc_nand_resource(dev); @@ -1213,15 +1239,17 @@ static int mrvl_nand_probe(struct device_d *dev) if (ret) return ret; - host->chip.controller = &host->chip.hwcontrol; - ret = mrvl_nand_scan(&host->chip.mtd); + chip = &host->chip; + mtd = nand_to_mtd(chip); + + ret = mrvl_nand_scan(chip); if (ret) { dev_warn(dev, "failed to scan nand at cs %d\n", host->cs); return -ENODEV; } - ret = add_mtd_nand_device(&host->chip.mtd, "nand"); + ret = add_mtd_nand_device(mtd, "nand"); return ret; } |