Commit b025beef authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

updated

parent 9159c877
...@@ -83,8 +83,6 @@ struct pl35x_nand_command_format { ...@@ -83,8 +83,6 @@ struct pl35x_nand_command_format {
/** /**
* struct pl35x_nand_info - Defines the NAND flash driver instance * struct pl35x_nand_info - Defines the NAND flash driver instance
* @chip: NAND chip information structure * @chip: NAND chip information structure
* @mtd: MTD information structure
* @parts: Pointer to the mtd_partition structure
* @nand_base: Virtual address of the NAND flash device * @nand_base: Virtual address of the NAND flash device
* @end_cmd_pending: End command is pending * @end_cmd_pending: End command is pending
* @end_cmd: End command * @end_cmd: End command
...@@ -93,8 +91,6 @@ struct pl35x_nand_command_format { ...@@ -93,8 +91,6 @@ struct pl35x_nand_command_format {
*/ */
struct pl35x_nand_info { struct pl35x_nand_info {
struct nand_chip chip; struct nand_chip chip;
struct mtd_info mtd;
struct mtd_partition *parts;
void __iomem *nand_base; void __iomem *nand_base;
unsigned long end_cmd_pending; unsigned long end_cmd_pending;
unsigned long end_cmd; unsigned long end_cmd;
...@@ -133,43 +129,110 @@ static const struct pl35x_nand_command_format pl35x_nand_commands[] = { ...@@ -133,43 +129,110 @@ static const struct pl35x_nand_command_format pl35x_nand_commands[] = {
*/ */
}; };
/* Define default oob placement schemes for large and small page devices */ static int pl35x_ecc_ooblayout16_ecc(struct mtd_info *mtd, int section,
static struct nand_ecclayout nand_oob_16 = { struct mtd_oob_region *oobregion)
.eccbytes = 3, {
.eccpos = {0, 1, 2}, struct nand_chip *chip = mtd_to_nand(mtd);
.oobfree = {
{.offset = 8, if (section >= chip->ecc.steps)
. length = 8} } return -ERANGE;
oobregion->offset = (section * 16) + 0;
oobregion->length = chip->ecc.bytes;
return 0;
}
static int pl35x_ecc_ooblayout16_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >= chip->ecc.steps)
return -ERANGE;
oobregion->offset = (section * 16) + 8;
oobregion->length = 8;
return 0;
}
static const struct mtd_ooblayout_ops fsmc_ecc_ooblayout16_ops = {
.ecc = pl35x_ecc_ooblayout16_ecc,
.free = pl35x_ecc_ooblayout16_free,
}; };
static int pl35x_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >= chip->ecc.steps)
return -ERANGE;
oobregion->offset = (section * 16) + 52;
oobregion->length = chip->ecc.bytes;
return 0;
}
static int pl35x_ecc_ooblayout64_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >= chip->ecc.steps)
return -ERANGE;
oobregion->offset = (section * 16) + 2;
oobregion->length = 50;
return 0;
}
static struct nand_ecclayout nand_oob_64 = { static const struct mtd_ooblayout_ops fsmc_ecc_ooblayout64_ops = {
.eccbytes = 12, .ecc = pl35x_ecc_ooblayout64_ecc,
.eccpos = { .free = pl35x_ecc_ooblayout64_free,
52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63},
.oobfree = {
{.offset = 2,
.length = 50} }
}; };
static int pl35x_ecc_ooblayout_ondie64_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
static struct nand_ecclayout ondie_nand_oob_64 = { if (section >= chip->ecc.steps)
.eccbytes = 32, return -ERANGE;
.eccpos = { oobregion->offset = (section * 16) + 8;
8, 9, 10, 11, 12, 13, 14, 15, oobregion->length = chip->ecc.bytes;
24, 25, 26, 27, 28, 29, 30, 31,
40, 41, 42, 43, 44, 45, 46, 47,
56, 57, 58, 59, 60, 61, 62, 63
},
.oobfree = { return 0;
{ .offset = 4, .length = 4 }, }
{ .offset = 20, .length = 4 },
{ .offset = 36, .length = 4 }, static int pl35x_ecc_ooblayout_ondie64_free(struct mtd_info *mtd, int section,
{ .offset = 52, .length = 4 } struct mtd_oob_region *oobregion)
} {
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >= chip->ecc.steps)
return -ERANGE;
oobregion->length = 4;
if (!section)
oobregion->offset = 4;
else
oobregion->offset = (section * 16) + 4;
return 0;
}
static const struct mtd_ooblayout_ops fsmc_ecc_ooblayout_ondie64_ops = {
.ecc = pl35x_ecc_ooblayout_ondie64_ecc,
.free = pl35x_ecc_ooblayout_ondie64_free,
}; };
/* Generic flash bbt decriptors */ /* Generic flash bbt decriptors */
static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
...@@ -211,7 +274,6 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd, ...@@ -211,7 +274,6 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd,
u32 ecc_value, ecc_status; u32 ecc_value, ecc_status;
u8 ecc_reg, ecc_byte; u8 ecc_reg, ecc_byte;
unsigned long timeout = jiffies + PL35X_NAND_ECC_BUSY_TIMEOUT; unsigned long timeout = jiffies + PL35X_NAND_ECC_BUSY_TIMEOUT;
/* Wait till the ECC operation is complete or timeout */ /* Wait till the ECC operation is complete or timeout */
do { do {
if (pl35x_smc_ecc_is_busy()) if (pl35x_smc_ecc_is_busy())
...@@ -415,7 +477,8 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, ...@@ -415,7 +477,8 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
*/ */
static int pl35x_nand_write_page_raw(struct mtd_info *mtd, static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, struct nand_chip *chip,
const uint8_t *buf, int oob_required) const uint8_t *buf, int oob_required,
int page)
{ {
unsigned long data_phase_addr; unsigned long data_phase_addr;
uint8_t *p; uint8_t *p;
...@@ -450,15 +513,15 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, ...@@ -450,15 +513,15 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
*/ */
static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, struct nand_chip *chip, const uint8_t *buf,
int oob_required) int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf; const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
unsigned long data_phase_addr; unsigned long data_phase_addr;
uint8_t *oob_ptr; uint8_t *oob_ptr;
u32 ret;
for ( ; (eccsteps - 1); eccsteps--) { for ( ; (eccsteps - 1); eccsteps--) {
chip->write_buf(mtd, p, eccsize); chip->write_buf(mtd, p, eccsize);
...@@ -473,13 +536,14 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, ...@@ -473,13 +536,14 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr;
chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH);
/* Wait for ECC to be calculated and read the error values */
p = buf; p = buf;
chip->ecc.calculate(mtd, p, &ecc_calc[0]); chip->ecc.calculate(mtd, p, &ecc_calc[0]);
for (i = 0; i < chip->ecc.total; i++) /* Wait for ECC to be calculated and read the error values */
chip->oob_poi[eccpos[i]] = ~(ecc_calc[i]); ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi,
0, chip->ecc.total);
if (ret)
return ret;
/* Clear ECC last bit */ /* Clear ECC last bit */
data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr = (unsigned long __force)chip->IO_ADDR_W;
data_phase_addr &= ~PL35X_NAND_ECC_LAST; data_phase_addr &= ~PL35X_NAND_ECC_LAST;
...@@ -511,23 +575,23 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, ...@@ -511,23 +575,23 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
*/ */
static int pl35x_nand_write_page_swecc(struct mtd_info *mtd, static int pl35x_nand_write_page_swecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, struct nand_chip *chip, const uint8_t *buf,
int oob_required) int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps; int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf; const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos; u32 ret;
/* Software ecc calculation */
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[0]);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi,
chip->oob_poi[eccpos[i]] = ecc_calc[i]; 0, chip->ecc.total);
if (ret)
chip->ecc.write_page_raw(mtd, chip, buf, 1); return ret;
chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
return 0; return 0;
} }
...@@ -555,9 +619,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, ...@@ -555,9 +619,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
uint8_t *p = buf; uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode; uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
unsigned long data_phase_addr; unsigned long data_phase_addr;
uint8_t *oob_ptr; uint8_t *oob_ptr;
u32 ret;
for ( ; (eccsteps - 1); eccsteps--) { for ( ; (eccsteps - 1); eccsteps--) {
chip->read_buf(mtd, p, eccsize); chip->read_buf(mtd, p, eccsize);
...@@ -594,8 +658,10 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, ...@@ -594,8 +658,10 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH);
chip->read_buf(mtd, oob_ptr, PL35X_NAND_LAST_TRANSFER_LENGTH); chip->read_buf(mtd, oob_ptr, PL35X_NAND_LAST_TRANSFER_LENGTH);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
ecc_code[i] = ~(chip->oob_poi[eccpos[i]]); chip->ecc.total);
if (ret)
return ret;
eccsteps = chip->ecc.steps; eccsteps = chip->ecc.steps;
p = buf; p = buf;
...@@ -631,15 +697,15 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd, ...@@ -631,15 +697,15 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd,
uint8_t *p = buf; uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode; uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos; u32 ret;
chip->ecc.read_page_raw(mtd, chip, buf, page, 1); chip->ecc.read_page_raw(mtd, chip, buf, page, 1);
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[i]);
for (i = 0; i < chip->ecc.total; i++) ret = mtd_ooblayout_get_eccbytes(mtd, ecc_calc, chip->oob_poi,
ecc_code[i] = chip->oob_poi[eccpos[i]]; 0, chip->ecc.total);
eccsteps = chip->ecc.steps; eccsteps = chip->ecc.steps;
p = buf; p = buf;
...@@ -684,10 +750,10 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, ...@@ -684,10 +750,10 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
if (command == NAND_CMD_UNLOCK1) pr_debug("NAND UNLOCK1\n"); if (command == NAND_CMD_UNLOCK1) pr_debug("NAND UNLOCK1\n");
if (command == NAND_CMD_SET_FEATURES) pr_debug("NAND NAND_CMD_SET_FEATURES\n"); if (command == NAND_CMD_SET_FEATURES) pr_debug("NAND NAND_CMD_SET_FEATURES\n");
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd_to_nand(mtd);
const struct pl35x_nand_command_format *curr_cmd = NULL; const struct pl35x_nand_command_format *curr_cmd = NULL;
struct pl35x_nand_info *xnand = struct pl35x_nand_info *xnand =
container_of(mtd, struct pl35x_nand_info, mtd); container_of(chip, struct pl35x_nand_info, chip);
void __iomem *cmd_addr; void __iomem *cmd_addr;
unsigned long cmd_data = 0, end_cmd_valid = 0; unsigned long cmd_data = 0, end_cmd_valid = 0;
unsigned long cmd_phase_addr, data_phase_addr, end_cmd, i; unsigned long cmd_phase_addr, data_phase_addr, end_cmd, i;
...@@ -834,7 +900,7 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, ...@@ -834,7 +900,7 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
static void pl35x_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void pl35x_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{ {
int i; int i;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd_to_nand(mtd);
unsigned long *ptr = (unsigned long *)buf; unsigned long *ptr = (unsigned long *)buf;
len >>= 2; len >>= 2;
...@@ -852,18 +918,17 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, ...@@ -852,18 +918,17 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
int len) int len)
{ {
int i; int i;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd_to_nand(mtd);
unsigned long *ptr = (unsigned long *)buf; unsigned long *ptr = (unsigned long *)buf;
pr_debug("pl35x_nand_write_buf: datasize=%d len=%d len>>2=%d\n",sizeof(ptr[0]),len,len>>2); pr_debug("pl35x_nand_write_buf: datasize=%d len=%d len>>2=%d\n",sizeof(ptr[0]),len,len>>2);
len >>= 2; len >>= 2;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
writel(ptr[i], chip->IO_ADDR_W); writel(ptr[i], chip->IO_ADDR_W);
//writeb(byte, chip->IO_ADDR_W);
} }
/** /**
* pl35x_nand_device_ready - Check device ready/busy line * pl35x_nand_device_ready - Check device ready/busy line
* @mtd: Pointer to the mtd_info structure * @mtd: Pointer to the mtd_info structure
...@@ -879,6 +944,7 @@ static int pl35x_nand_device_ready(struct mtd_info *mtd) ...@@ -879,6 +944,7 @@ static int pl35x_nand_device_ready(struct mtd_info *mtd)
return 0; return 0;
} }
// Elphel: whole function
/** /**
* pl35x_nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand * pl35x_nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -916,6 +982,7 @@ static int pl35x_nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip * ...@@ -916,6 +982,7 @@ static int pl35x_nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *
return 0; return 0;
} }
// Elphel: whole function
/** /**
* nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -952,7 +1019,7 @@ static int pl35x_nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip * ...@@ -952,7 +1019,7 @@ static int pl35x_nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *
*/ */
static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd) static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd)
{ {
struct nand_chip *nand_chip = mtd->priv; struct nand_chip *nand_chip = mtd_to_nand(mtd);
u8 maf_id, dev_id, i, get_feature; u8 maf_id, dev_id, i, get_feature;
u8 set_feature[4] = { 0x08, 0x00, 0x00, 0x00 }; u8 set_feature[4] = { 0x08, 0x00, 0x00, 0x00 };
...@@ -1009,16 +1076,17 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd) ...@@ -1009,16 +1076,17 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd)
* This function initializes the ecc block and functional pointers as per the * This function initializes the ecc block and functional pointers as per the
* ecc mode * ecc mode
*/ */
static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state) static void pl35x_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
int ondie_ecc_state)
{ {
struct nand_chip *nand_chip = mtd->priv; struct nand_chip *nand_chip = mtd_to_nand(mtd);
nand_chip->ecc.mode = NAND_ECC_HW; ecc->mode = NAND_ECC_HW;
nand_chip->ecc.read_oob = pl35x_nand_read_oob; ecc->read_oob = pl35x_nand_read_oob;
nand_chip->ecc.read_page_raw = pl35x_nand_read_page_raw; ecc->read_page_raw = pl35x_nand_read_page_raw;
nand_chip->ecc.strength = 1; ecc->strength = 1;
nand_chip->ecc.write_oob = pl35x_nand_write_oob; ecc->write_oob = pl35x_nand_write_oob;
nand_chip->ecc.write_page_raw = pl35x_nand_write_page_raw; ecc->write_page_raw = pl35x_nand_write_page_raw;
if (ondie_ecc_state) { if (ondie_ecc_state) {
/* bypass the controller ECC block */ /* bypass the controller ECC block */
...@@ -1028,11 +1096,11 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state) ...@@ -1028,11 +1096,11 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state)
* The software ECC routines won't work with the * The software ECC routines won't work with the
* SMC controller * SMC controller
*/ */
nand_chip->ecc.bytes = 0; ecc->bytes = 0;
nand_chip->ecc.layout = &ondie_nand_oob_64; mtd_set_ooblayout(mtd, &fsmc_ecc_ooblayout_ondie64_ops);
nand_chip->ecc.read_page = pl35x_nand_read_page_raw; ecc->read_page = pl35x_nand_read_page_raw;
nand_chip->ecc.write_page = pl35x_nand_write_page_raw; ecc->write_page = pl35x_nand_write_page_raw;
nand_chip->ecc.size = mtd->writesize; ecc->size = mtd->writesize;
/* /*
* On-Die ECC spare bytes offset 8 is used for ECC codes * On-Die ECC spare bytes offset 8 is used for ECC codes
* Use the BBT pattern descriptors * Use the BBT pattern descriptors
...@@ -1041,13 +1109,13 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state) ...@@ -1041,13 +1109,13 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state)
nand_chip->bbt_md = &bbt_mirror_descr; nand_chip->bbt_md = &bbt_mirror_descr;
} else { } else {
/* Hardware ECC generates 3 bytes ECC code for each 512 bytes */ /* Hardware ECC generates 3 bytes ECC code for each 512 bytes */
nand_chip->ecc.bytes = 3; ecc->bytes = 3;
nand_chip->ecc.calculate = pl35x_nand_calculate_hwecc; ecc->calculate = pl35x_nand_calculate_hwecc;
nand_chip->ecc.correct = pl35x_nand_correct_data; ecc->correct = pl35x_nand_correct_data;
nand_chip->ecc.hwctl = NULL; ecc->hwctl = NULL;
nand_chip->ecc.read_page = pl35x_nand_read_page_hwecc; ecc->read_page = pl35x_nand_read_page_hwecc;
nand_chip->ecc.size = PL35X_NAND_ECC_SIZE; ecc->size = PL35X_NAND_ECC_SIZE;
nand_chip->ecc.write_page = pl35x_nand_write_page_hwecc; ecc->write_page = pl35x_nand_write_page_hwecc;
pl35x_smc_set_ecc_pg_size(mtd->writesize); pl35x_smc_set_ecc_pg_size(mtd->writesize);
switch (mtd->writesize) { switch (mtd->writesize) {
...@@ -1061,18 +1129,18 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state) ...@@ -1061,18 +1129,18 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state)
* The software ECC routines won't work with the * The software ECC routines won't work with the
* SMC controller * SMC controller
*/ */
nand_chip->ecc.calculate = nand_calculate_ecc; ecc->calculate = nand_calculate_ecc;
nand_chip->ecc.correct = nand_correct_data; ecc->correct = nand_correct_data;
nand_chip->ecc.read_page = pl35x_nand_read_page_swecc; ecc->read_page = pl35x_nand_read_page_swecc;
nand_chip->ecc.write_page = pl35x_nand_write_page_swecc; ecc->write_page = pl35x_nand_write_page_swecc;
nand_chip->ecc.size = 256; ecc->size = 256;
break; break;
} }
if (mtd->oobsize == 16) if (mtd->oobsize == 16)
nand_chip->ecc.layout = &nand_oob_16; mtd_set_ooblayout(mtd, &fsmc_ecc_ooblayout16_ops);
else if (mtd->oobsize == 64) else if (mtd->oobsize == 64)
nand_chip->ecc.layout = &nand_oob_64; mtd_set_ooblayout(mtd, &fsmc_ecc_ooblayout64_ops);
} }
} }
...@@ -1090,7 +1158,6 @@ static int pl35x_nand_probe(struct platform_device *pdev) ...@@ -1090,7 +1158,6 @@ static int pl35x_nand_probe(struct platform_device *pdev)
struct mtd_info *mtd; struct mtd_info *mtd;
struct nand_chip *nand_chip; struct nand_chip *nand_chip;
struct resource *res; struct resource *res;
struct mtd_part_parser_data ppdata;
int ondie_ecc_state; int ondie_ecc_state;
xnand = devm_kzalloc(&pdev->dev, sizeof(*xnand), GFP_KERNEL); xnand = devm_kzalloc(&pdev->dev, sizeof(*xnand), GFP_KERNEL);
...@@ -1103,14 +1170,14 @@ static int pl35x_nand_probe(struct platform_device *pdev) ...@@ -1103,14 +1170,14 @@ static int pl35x_nand_probe(struct platform_device *pdev)
if (IS_ERR(xnand->nand_base)) if (IS_ERR(xnand->nand_base))
return PTR_ERR(xnand->nand_base); return PTR_ERR(xnand->nand_base);
/* Link the private data with the MTD structure */
mtd = &xnand->mtd;
nand_chip = &xnand->chip; nand_chip = &xnand->chip;
mtd = nand_to_mtd(nand_chip);
nand_chip->priv = xnand; nand_set_controller_data(nand_chip, xnand);
mtd->priv = nand_chip; mtd->priv = nand_chip;
mtd->owner = THIS_MODULE; mtd->owner = THIS_MODULE;
mtd->name = PL35X_NAND_DRIVER_NAME; mtd->name = PL35X_NAND_DRIVER_NAME;
nand_set_flash_node(nand_chip, pdev->dev.of_node);
/* Set address of NAND IO lines */ /* Set address of NAND IO lines */
nand_chip->IO_ADDR_R = xnand->nand_base; nand_chip->IO_ADDR_R = xnand->nand_base;
...@@ -1149,7 +1216,7 @@ static int pl35x_nand_probe(struct platform_device *pdev) ...@@ -1149,7 +1216,7 @@ static int pl35x_nand_probe(struct platform_device *pdev)
xnand->col_addr_cycles = xnand->col_addr_cycles =
(nand_chip->onfi_params.addr_cycles >> 4) & 0xF; (nand_chip->onfi_params.addr_cycles >> 4) & 0xF;
pl35x_nand_ecc_init(mtd, ondie_ecc_state); pl35x_nand_ecc_init(mtd, &nand_chip->ecc, ondie_ecc_state);
if (nand_chip->options & NAND_BUSWIDTH_16) if (nand_chip->options & NAND_BUSWIDTH_16)
pl35x_smc_set_buswidth(PL35X_SMC_MEM_WIDTH_16); pl35x_smc_set_buswidth(PL35X_SMC_MEM_WIDTH_16);
...@@ -1164,10 +1231,8 @@ static int pl35x_nand_probe(struct platform_device *pdev) ...@@ -1164,10 +1231,8 @@ static int pl35x_nand_probe(struct platform_device *pdev)
//TODO: add Micron chip ID checking //TODO: add Micron chip ID checking
mtd->_unlock = nand_unlock; mtd->_unlock = nand_unlock;
mtd->_lock = nand_lock; mtd->_lock = nand_lock;
ppdata.of_node = pdev->dev.of_node;
mtd_device_parse_register(&xnand->mtd, NULL, &ppdata, NULL, 0); mtd_device_register(mtd, NULL, 0);
return 0; return 0;
} }
...@@ -1184,11 +1249,10 @@ static int pl35x_nand_probe(struct platform_device *pdev) ...@@ -1184,11 +1249,10 @@ static int pl35x_nand_probe(struct platform_device *pdev)
static int pl35x_nand_remove(struct platform_device *pdev) static int pl35x_nand_remove(struct platform_device *pdev)
{ {
struct pl35x_nand_info *xnand = platform_get_drvdata(pdev); struct pl35x_nand_info *xnand = platform_get_drvdata(pdev);
struct mtd_info *mtd = nand_to_mtd(&xnand->chip);
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release(&xnand->mtd); nand_release(mtd);
/* kfree(NULL) is safe */
kfree(xnand->parts);
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment