summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/atmel_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/atmel_nand.c')
-rw-r--r--drivers/mtd/nand/atmel_nand.c253
1 files changed, 108 insertions, 145 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index f3875a5648..db13f5b7e4 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -33,6 +33,7 @@
#include <of_mtd.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand.h>
#include <linux/err.h>
@@ -102,10 +103,10 @@ struct atmel_nand_host {
int *pmecc_mu;
int *pmecc_dmu;
int *pmecc_delta;
+ struct nand_ecclayout *ecclayout;
+ void *ecc_code;
};
-static struct nand_ecclayout atmel_pmecc_oobinfo;
-
/*
* Enable NAND.
*/
@@ -127,9 +128,8 @@ static void atmel_nand_disable(struct atmel_nand_host *host)
/*
* Hardware specific access to control-lines
*/
-static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+static void atmel_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, unsigned int ctrl)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
if (ctrl & NAND_CTRL_CHANGE) {
@@ -150,9 +150,8 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
/*
* Read the Device Ready pin.
*/
-static int atmel_nand_device_ready(struct mtd_info *mtd)
+static int atmel_nand_device_ready(struct nand_chip *nand_chip)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
return gpio_get_value(host->board->rdy_pin);
@@ -161,32 +160,24 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
/*
* Minimal-overhead PIO for data access.
*/
-static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+static void atmel_read_buf(struct nand_chip *nand_chip, u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
-
- readsb(nand_chip->IO_ADDR_R, buf, len);
+ readsb(nand_chip->legacy.IO_ADDR_R, buf, len);
}
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+static void atmel_read_buf16(struct nand_chip *nand_chip, u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
-
- readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+ readsw(nand_chip->legacy.IO_ADDR_R, buf, len / 2);
}
-static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+static void atmel_write_buf(struct nand_chip *nand_chip, const u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
-
- writesb(nand_chip->IO_ADDR_W, buf, len);
+ writesb(nand_chip->legacy.IO_ADDR_W, buf, len);
}
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+static void atmel_write_buf16(struct nand_chip *nand_chip, const u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
-
- writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+ writesw(nand_chip->legacy.IO_ADDR_W, buf, len / 2);
}
/*
@@ -208,22 +199,6 @@ static int pmecc_get_ecc_bytes(int cap, int sector_size)
return (m * cap + 7) / 8;
}
-static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
- int oobsize, int ecc_len)
-{
- int i;
-
- layout->eccbytes = ecc_len;
-
- /* ECC will occupy the last ecc_len bytes continuously */
- for (i = 0; i < ecc_len; i++)
- layout->eccpos[i] = oobsize - ecc_len + i;
-
- layout->oobfree[0].offset = 2;
- layout->oobfree[0].length =
- oobsize - ecc_len - layout->oobfree[0].offset;
-}
-
static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
{
int table_size;
@@ -545,7 +520,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
int i = 0;
- int byte_pos, bit_pos, sector_size, pos;
+ int byte_pos, bit_pos, sector_size;
uint32_t tmp;
uint8_t err_byte;
@@ -562,20 +537,12 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
if (byte_pos < sector_size) {
err_byte = *(buf + byte_pos);
*(buf + byte_pos) ^= (1 << bit_pos);
-
- pos = sector_num * host->board->pmecc_sector_size + byte_pos;
- dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
- pos, bit_pos, err_byte, *(buf + byte_pos));
} else {
/* Bit flip in OOB area */
tmp = sector_num * host->pmecc_bytes_per_sector
+ (byte_pos - sector_size);
err_byte = ecc[tmp];
ecc[tmp] ^= (1 << bit_pos);
-
- pos = tmp + nand_chip->ecc.layout->eccpos[0];
- dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
- pos, bit_pos, err_byte, ecc[tmp]);
}
i++;
@@ -585,17 +552,21 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
return;
}
-static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
- u8 *ecc)
+static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
- int i, err_nbr, eccbytes;
+ int i, err_nbr, ret, max_bitflips = 0;
uint8_t *buf_pos;
+ uint8_t *ecc_code = host->ecc_code;
+
+ ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, nand_chip->oob_poi, 0,
+ nand_chip->ecc.total);
+ if (ret)
+ return ret;
- eccbytes = nand_chip->ecc.bytes;
- for (i = 0; i < eccbytes; i++)
- if (ecc[i] != 0xff)
+ for (i = 0; i < nand_chip->ecc.bytes * nand_chip->ecc.steps; i++)
+ if (ecc_code[i] != 0xff)
goto normal_check;
/* Erased page, return OK */
return 0;
@@ -614,26 +585,25 @@ normal_check:
if (err_nbr == -1) {
dev_err(host->dev, "PMECC: Too many errors\n");
mtd->ecc_stats.failed++;
- return -EIO;
+ return -EBADMSG;
} else {
- pmecc_correct_data(mtd, buf_pos, ecc, i,
+ pmecc_correct_data(mtd, buf_pos, ecc_code, i,
host->pmecc_bytes_per_sector, err_nbr);
mtd->ecc_stats.corrected += err_nbr;
+ max_bitflips = max(max_bitflips, err_nbr);
}
}
pmecc_stat >>= 1;
}
- return 0;
+ return max_bitflips;
}
-static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
+static int atmel_nand_pmecc_read_page(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
{
+ struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
- uint8_t *oob = chip->oob_poi;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
uint32_t stat;
int ret;
@@ -645,8 +615,10 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
- chip->read_buf(mtd, buf, eccsize);
- chip->read_buf(mtd, oob, 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);
ret = wait_on_timeout(PMECC_MAX_TIMEOUT_MS,
!(pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY));
@@ -657,20 +629,23 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
stat = pmecc_readl_relaxed(host->ecc, ISR);
if (stat != 0)
- if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
- return -EIO;
+ return pmecc_correction(mtd, stat, buf);
return 0;
}
-static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf,
- int oob_required)
+static int atmel_nand_pmecc_write_page(struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page)
{
+ struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand_host *host = chip->priv;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint8_t *ecc_calc = host->ecc_code;
int i, j, ret;
+ ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+ if (ret)
+ return ret;
+
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
@@ -680,7 +655,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
- chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+ chip->legacy.write_buf(chip, (u8 *)buf, mtd->writesize);
ret = wait_on_timeout(PMECC_MAX_TIMEOUT_MS,
!(pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY));
@@ -694,13 +669,22 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
int pos;
pos = i * host->pmecc_bytes_per_sector + j;
- chip->oob_poi[eccpos[pos]] =
- pmecc_readb_ecc_relaxed(host->ecc, i, j);
+ ecc_calc[pos] = pmecc_readb_ecc_relaxed(host->ecc, i, j);
}
}
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
- return 0;
+ ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc,
+ chip->oob_poi, 0, chip->ecc.total);
+ if (ret)
+ return ret;
+
+ chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
+
+ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false);
+ if (ret)
+ return ret;
+
+ return nand_prog_page_end_op(chip);
}
static void atmel_pmecc_core_init(struct mtd_info *mtd)
@@ -708,7 +692,7 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
uint32_t val = 0;
- struct nand_ecclayout *ecc_layout;
+ int eccbytes;
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
@@ -755,11 +739,10 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
| PMECC_CFG_AUTO_DISABLE);
pmecc_writel(host->ecc, CFG, val);
- ecc_layout = nand_chip->ecc.layout;
+ eccbytes = host->pmecc_sector_number * host->pmecc_bytes_per_sector;
pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
- pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]);
- pmecc_writel(host->ecc, EADDR,
- ecc_layout->eccpos[ecc_layout->eccbytes - 1]);
+ pmecc_writel(host->ecc, SADDR, mtd->oobsize - eccbytes);
+ pmecc_writel(host->ecc, EADDR, mtd->oobsize - 1);
/* See datasheet about PMECC Clock Control Register */
pmecc_writel(host->ecc, CLK, 2);
pmecc_writel(host->ecc, IDR, 0xff);
@@ -862,7 +845,7 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
{
struct resource *iores;
struct nand_chip *nand_chip = &host->nand_chip;
- struct mtd_info *mtd = &nand_chip->mtd;
+ struct mtd_info *mtd = nand_to_mtd(nand_chip);
int cap, sector_size, err_no;
int ret;
@@ -911,9 +894,6 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
host->board->pmecc_lookup_table_offset = 0;
}
- /* ECC is calculated for the whole page (1 step) */
- nand_chip->ecc.size = mtd->writesize;
-
/* set ECC page size and oob layout */
switch (mtd->writesize) {
case 2048:
@@ -929,17 +909,16 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
host->pmecc_index_of = host->pmecc_rom_base +
host->board->pmecc_lookup_table_offset;
- nand_chip->ecc.steps = 1;
- nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
- host->pmecc_sector_number;
+ nand_chip->ecc.steps = host->pmecc_sector_number;
+ nand_chip->ecc.bytes = host->pmecc_bytes_per_sector;
+ nand_chip->ecc.size = sector_size;
+ nand_chip->ecc.strength = cap;
+
if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
dev_err(host->dev, "No room for ECC bytes\n");
return -EINVAL;
}
- pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
- mtd->oobsize,
- nand_chip->ecc.bytes);
- nand_chip->ecc.layout = &atmel_pmecc_oobinfo;
+ mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
break;
case 512:
case 1024:
@@ -979,10 +958,9 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
* dat: raw data (unused)
* ecc_code: buffer for ECC
*/
-static int atmel_nand_calculate(struct mtd_info *mtd,
+static int atmel_nand_calculate(struct nand_chip *nand_chip,
const u_char *dat, unsigned char *ecc_code)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
unsigned int ecc_value;
@@ -1008,34 +986,22 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
* chip: nand chip info structure
* buf: buffer to store read data
*/
-static int atmel_nand_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
+static int atmel_nand_read_page(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
{
- int eccsize = chip->ecc.size;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct atmel_nand_host *host = chip->priv;
int eccbytes = chip->ecc.bytes;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint32_t *eccpos = host->ecclayout->eccpos;
uint8_t *p = buf;
uint8_t *oob = chip->oob_poi;
uint8_t *ecc_pos;
int stat;
- /*
- * Errata: ALE is incorrectly wired up to the ECC controller
- * on the AP7000, so it will include the address cycles in the
- * ECC calculation.
- *
- * Workaround: Reset the parity registers before reading the
- * actual data.
- */
-#if 0
- if (cpu_is_at32ap7000()) {
- struct atmel_nand_host *host = chip->priv;
- ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
- }
-#endif
+ nand_read_page_op(chip, page, 0, NULL, 0);
/* read the page */
- chip->read_buf(mtd, p, eccsize);
+ chip->legacy.read_buf(chip, p, mtd->writesize);
/* move to ECC position if needed */
if (eccpos[0] != 0) {
@@ -1045,16 +1011,16 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
* NAND_CMD_RNDOUT.
* anyway, for small pages, the eccpos[0] == 0
*/
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
+ chip->legacy.cmdfunc(chip, NAND_CMD_RNDOUT,
mtd->writesize + eccpos[0], -1);
}
/* the ECC controller needs to read the ECC just after the data */
ecc_pos = oob + eccpos[0];
- chip->read_buf(mtd, ecc_pos, eccbytes);
+ chip->legacy.read_buf(chip, ecc_pos, eccbytes);
/* check if there's an error */
- stat = chip->ecc.correct(mtd, p, oob, NULL);
+ stat = chip->ecc.correct(chip, p, oob, NULL);
if (stat < 0)
mtd->ecc_stats.failed++;
@@ -1062,10 +1028,10 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
mtd->ecc_stats.corrected += stat;
/* get back to oob start (end of page) */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+ chip->legacy.cmdfunc(chip, NAND_CMD_RNDOUT, mtd->writesize, -1);
/* read the oob */
- chip->read_buf(mtd, oob, mtd->oobsize);
+ chip->legacy.read_buf(chip, oob, mtd->oobsize);
return 0;
}
@@ -1082,10 +1048,9 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
*
* Detect and correct a 1 bit error for a page
*/
-static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
+static int atmel_nand_correct(struct nand_chip *nand_chip, u_char *dat,
u_char *read_ecc, u_char *isnull)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
unsigned int ecc_status;
unsigned int ecc_word, ecc_bit;
@@ -1149,15 +1114,8 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/*
* Enable HW ECC : unused on most chips
*/
-static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
+static void atmel_nand_hwctl(struct nand_chip *nand_chip, int mode)
{
-#if 0
- if (cpu_is_at32ap7000()) {
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
- struct atmel_nand_host *host = nand_chip->priv;
- ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
- }
-#endif
}
static int atmel_nand_of_init(struct atmel_nand_host *host, struct device_node *np)
@@ -1251,7 +1209,7 @@ static int atmel_hw_nand_init_params(struct device_d *dev,
{
struct resource *iores;
struct nand_chip *nand_chip = &host->nand_chip;
- struct mtd_info *mtd = &nand_chip->mtd;
+ struct mtd_info *mtd = nand_to_mtd(nand_chip);
iores = dev_request_mem_resource(dev, 1);
if (IS_ERR(iores))
@@ -1268,19 +1226,23 @@ static int atmel_hw_nand_init_params(struct device_d *dev,
/* set ECC page size and oob layout */
switch (mtd->writesize) {
case 512:
- nand_chip->ecc.layout = &atmel_oobinfo_small;
+ host->ecclayout = &atmel_oobinfo_small;
+ mtd_set_ecclayout(mtd, host->ecclayout);
ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
break;
case 1024:
- nand_chip->ecc.layout = &atmel_oobinfo_large;
+ host->ecclayout = &atmel_oobinfo_large;
+ mtd_set_ecclayout(mtd, host->ecclayout);
ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
break;
case 2048:
- nand_chip->ecc.layout = &atmel_oobinfo_large;
+ host->ecclayout = &atmel_oobinfo_large;
+ mtd_set_ecclayout(mtd, host->ecclayout);
ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
break;
case 4096:
- nand_chip->ecc.layout = &atmel_oobinfo_large;
+ host->ecclayout = &atmel_oobinfo_large;
+ mtd_set_ecclayout(mtd, host->ecclayout);
ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
break;
default:
@@ -1328,7 +1290,7 @@ static int __init atmel_nand_probe(struct device_d *dev)
host->io_base = IOMEM(iores->start);
nand_chip = &host->nand_chip;
- mtd = &nand_chip->mtd;
+ mtd = nand_to_mtd(nand_chip);
host->board = pdata;
host->dev = dev;
@@ -1341,12 +1303,12 @@ static int __init atmel_nand_probe(struct device_d *dev)
}
nand_chip->priv = host; /* link the private data structures */
- mtd->parent = dev;
+ mtd->dev.parent = dev;
/* Set address of NAND IO lines */
- nand_chip->IO_ADDR_R = host->io_base;
- nand_chip->IO_ADDR_W = host->io_base;
- nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
+ nand_chip->legacy.IO_ADDR_R = host->io_base;
+ nand_chip->legacy.IO_ADDR_W = host->io_base;
+ nand_chip->legacy.cmd_ctrl = atmel_nand_cmd_ctrl;
if (gpio_is_valid(host->board->rdy_pin)) {
res = gpio_request(host->board->rdy_pin, "nand_rdy");
@@ -1364,7 +1326,7 @@ static int __init atmel_nand_probe(struct device_d *dev)
goto err_no_card;
}
- nand_chip->dev_ready = atmel_nand_device_ready;
+ nand_chip->legacy.dev_ready = atmel_nand_device_ready;
}
if (gpio_is_valid(host->board->enable_pin)) {
@@ -1394,7 +1356,7 @@ static int __init atmel_nand_probe(struct device_d *dev)
nand_chip->ecc.mode = NAND_ECC_HW;
}
- nand_chip->chip_delay = 40; /* 40us command delay time */
+ nand_chip->legacy.chip_delay = 40; /* 40us command delay time */
if (IS_ENABLED(CONFIG_NAND_ECC_BCH) &&
pdata->ecc_mode == NAND_ECC_SOFT_BCH) {
@@ -1403,11 +1365,11 @@ static int __init atmel_nand_probe(struct device_d *dev)
if (host->board->bus_width_16) { /* 16-bit bus width */
nand_chip->options |= NAND_BUSWIDTH_16;
- nand_chip->read_buf = atmel_read_buf16;
- nand_chip->write_buf = atmel_write_buf16;
+ nand_chip->legacy.read_buf = atmel_read_buf16;
+ nand_chip->legacy.write_buf = atmel_write_buf16;
} else {
- nand_chip->read_buf = atmel_read_buf;
- nand_chip->write_buf = atmel_write_buf;
+ nand_chip->legacy.read_buf = atmel_read_buf;
+ nand_chip->legacy.write_buf = atmel_write_buf;
}
atmel_nand_enable(host);
@@ -1442,11 +1404,13 @@ static int __init atmel_nand_probe(struct device_d *dev)
/* first scan to find the device and get the page size */
- if (nand_scan_ident(mtd, 1, NULL)) {
+ if (nand_scan_ident(nand_chip, 1, NULL)) {
res = -ENXIO;
goto err_scan_ident;
}
+ host->ecc_code = xmalloc(mtd->oobsize);
+
if (IS_ENABLED(CONFIG_NAND_ECC_HW) &&
nand_chip->ecc.mode == NAND_ECC_HW) {
if (IS_ENABLED(CONFIG_NAND_ATMEL_PMECC) && pdata->has_pmecc)
@@ -1459,7 +1423,7 @@ static int __init atmel_nand_probe(struct device_d *dev)
}
/* second phase scan */
- if (nand_scan_tail(mtd)) {
+ if (nand_scan_tail(nand_chip)) {
res = -ENXIO;
goto err_scan_tail;
}
@@ -1469,7 +1433,6 @@ static int __init atmel_nand_probe(struct device_d *dev)
if (!res)
return res;
- nand_release(mtd);
err_scan_tail:
err_hw_ecc:
err_scan_ident: