Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
aba46df9
Commit
aba46df9
authored
Jul 23, 2019
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated to current version
parent
9f60cc05
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
202 additions
and
69 deletions
+202
-69
pl35x_nand.c
src/drivers/mtd/nand/pl35x_nand.c
+202
-69
No files found.
src/drivers/mtd/nand/pl35x_nand.c
View file @
aba46df9
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/moduleparam.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/
raw
nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/partitions.h>
#include <linux/of_address.h>
#include <linux/of_address.h>
...
@@ -171,7 +171,7 @@ static int pl35x_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section,
...
@@ -171,7 +171,7 @@ static int pl35x_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section,
if
(
section
>=
chip
->
ecc
.
steps
)
if
(
section
>=
chip
->
ecc
.
steps
)
return
-
ERANGE
;
return
-
ERANGE
;
oobregion
->
offset
=
(
section
*
16
)
+
52
;
oobregion
->
offset
=
(
section
*
chip
->
ecc
.
bytes
)
+
52
;
oobregion
->
length
=
chip
->
ecc
.
bytes
;
oobregion
->
length
=
chip
->
ecc
.
bytes
;
return
0
;
return
0
;
...
@@ -182,10 +182,12 @@ static int pl35x_ecc_ooblayout64_free(struct mtd_info *mtd, int section,
...
@@ -182,10 +182,12 @@ static int pl35x_ecc_ooblayout64_free(struct mtd_info *mtd, int section,
{
{
struct
nand_chip
*
chip
=
mtd_to_nand
(
mtd
);
struct
nand_chip
*
chip
=
mtd_to_nand
(
mtd
);
if
(
section
)
return
-
ERANGE
;
if
(
section
>=
chip
->
ecc
.
steps
)
if
(
section
>=
chip
->
ecc
.
steps
)
return
-
ERANGE
;
return
-
ERANGE
;
oobregion
->
offset
=
(
section
*
16
)
+
2
;
oobregion
->
offset
=
(
section
*
chip
->
ecc
.
bytes
)
+
2
;
oobregion
->
length
=
50
;
oobregion
->
length
=
50
;
...
@@ -296,7 +298,7 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd,
...
@@ -296,7 +298,7 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd,
if
(
ecc_status
&
0x40
)
{
if
(
ecc_status
&
0x40
)
{
for
(
ecc_byte
=
0
;
ecc_byte
<
3
;
ecc_byte
++
)
{
for
(
ecc_byte
=
0
;
ecc_byte
<
3
;
ecc_byte
++
)
{
/* Copy ECC bytes to MTD buffer */
/* Copy ECC bytes to MTD buffer */
*
ecc_code
=
ecc_value
&
0xFF
;
*
ecc_code
=
~
ecc_value
&
0xFF
;
ecc_value
=
ecc_value
>>
8
;
ecc_value
=
ecc_value
>>
8
;
ecc_code
++
;
ecc_code
++
;
}
}
...
@@ -386,6 +388,10 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
...
@@ -386,6 +388,10 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
uint8_t
*
p
;
uint8_t
*
p
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
chip
->
cmdfunc
(
mtd
,
NAND_CMD_READOOB
,
0
,
page
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_READOOB
,
0
,
page
);
p
=
chip
->
oob_poi
;
p
=
chip
->
oob_poi
;
...
@@ -394,7 +400,9 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
...
@@ -394,7 +400,9 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -415,6 +423,9 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
...
@@ -415,6 +423,9 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int
status
=
0
;
int
status
=
0
;
const
uint8_t
*
buf
=
chip
->
oob_poi
;
const
uint8_t
*
buf
=
chip
->
oob_poi
;
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
chip
->
cmdfunc
(
mtd
,
NAND_CMD_SEQIN
,
mtd
->
writesize
,
page
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_SEQIN
,
mtd
->
writesize
,
page
);
...
@@ -423,8 +434,10 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
...
@@ -423,8 +434,10 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
buf
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
buf
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
write_buf
(
mtd
,
buf
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
write_buf
(
mtd
,
buf
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -435,6 +448,79 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
...
@@ -435,6 +448,79 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
return
(
status
&
NAND_STATUS_FAIL
)
?
-
EIO
:
0
;
return
(
status
&
NAND_STATUS_FAIL
)
?
-
EIO
:
0
;
}
}
/**
* pl35x_nand_read_page_ondie - [Intern] read page data with ondie ecc
* @mtd: Pointer to the mtd info structure
* @chip: Pointer to the NAND chip info structure
* @buf: Pointer to the data buffer
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @page: Page number to read
*
* Return: Always return zero
*/
static
int
pl35x_nand_read_page_ondie
(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
chip
,
u8
*
buf
,
int
oob_required
,
int
page
)
{
unsigned
long
data_phase_addr
;
u8
*
p
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
int
status
;
chip
->
read_buf
(
mtd
,
buf
,
mtd
->
writesize
);
p
=
chip
->
oob_poi
;
chip
->
read_buf
(
mtd
,
p
,
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
));
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
/* Check ECC info */
chip
->
cmdfunc
(
mtd
,
NAND_CMD_STATUS
,
-
1
,
-
1
);
status
=
(
int
)
chip
->
read_byte
(
mtd
);
if
(
!
(
status
&
NAND_STATUS_READY
))
{
pr_err
(
"%s: page %d status=%#x - transfer not finished!
\n
"
,
__func__
,
page
,
status
);
ndelay
(
100
);
if
(
!
(
status
&
NAND_STATUS_READY
))
return
-
EIO
;
}
/* UnCorrectable Error bitflips. 5+ on our chip */
#define NAND_UCE_BITS 5
if
(
status
&
NAND_STATUS_FAIL
)
{
pr_warn
(
"%s: page %d status=%#x - ECC Uncorrectable Error
\n
"
,
__func__
,
page
,
status
);
/*
* Note: don't return -EIO which means no data and is fatal
* during a filesystem mount.
* Instead return NAND_UCE_BITS bitflips and increment
* the uncorrectable error count. This allows the layer above
* (such as UBI) to know data is present but corrupt and to
* be safely manage if its only a EC or VI page.
*/
mtd
->
ecc_stats
.
failed
++
;
return
NAND_UCE_BITS
;
}
#define NAND_STATUS_ECC_COR BIT(3)
/* Correctable error */
if
(
status
&
NAND_STATUS_ECC_COR
)
{
pr_info
(
"%s: page %d status=%#x - ECC Correctable error
\n
"
,
__func__
,
page
,
status
);
mtd
->
ecc_stats
.
corrected
++
;
return
1
;
}
return
0
;
}
/**
/**
* pl35x_nand_read_page_raw - [Intern] read raw page data without ecc
* pl35x_nand_read_page_raw - [Intern] read raw page data without ecc
* @mtd: Pointer to the mtd info structure
* @mtd: Pointer to the mtd info structure
...
@@ -451,6 +537,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
...
@@ -451,6 +537,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
{
{
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
uint8_t
*
p
;
uint8_t
*
p
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
chip
->
read_buf
(
mtd
,
buf
,
mtd
->
writesize
);
chip
->
read_buf
(
mtd
,
buf
,
mtd
->
writesize
);
...
@@ -460,7 +549,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
...
@@ -460,7 +549,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -473,6 +564,7 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
...
@@ -473,6 +564,7 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd,
* @chip: Pointer to the NAND chip info structure
* @chip: Pointer to the NAND chip info structure
* @buf: Pointer to the data buffer
* @buf: Pointer to the data buffer
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @page: Page number to write
*
*
* Return: Always return zero
* Return: Always return zero
*/
*/
...
@@ -483,6 +575,9 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
...
@@ -483,6 +575,9 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
{
{
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
uint8_t
*
p
;
uint8_t
*
p
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
chip
->
write_buf
(
mtd
,
buf
,
mtd
->
writesize
);
chip
->
write_buf
(
mtd
,
buf
,
mtd
->
writesize
);
...
@@ -492,8 +587,10 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
...
@@ -492,8 +587,10 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
p
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
+=
nand_offset
;
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
);
...
@@ -507,6 +604,7 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
...
@@ -507,6 +604,7 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd,
* @chip: Pointer to the NAND chip info structure
* @chip: Pointer to the NAND chip info structure
* @buf: Pointer to the data buffer
* @buf: Pointer to the data buffer
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @page: Page number to write
*
*
* This functions writes data and hardware generated ECC values in to the page.
* This functions writes data and hardware generated ECC values in to the page.
*
*
...
@@ -523,6 +621,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
...
@@ -523,6 +621,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
uint8_t
*
oob_ptr
;
uint8_t
*
oob_ptr
;
u32
ret
;
u32
ret
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
for
(
;
(
eccsteps
-
1
);
eccsteps
--
)
{
for
(
;
(
eccsteps
-
1
);
eccsteps
--
)
{
chip
->
write_buf
(
mtd
,
p
,
eccsize
);
chip
->
write_buf
(
mtd
,
p
,
eccsize
);
...
@@ -533,7 +634,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
...
@@ -533,7 +634,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
/* Set ECC Last bit to 1 */
/* Set ECC Last bit to 1 */
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_ECC_LAST
;
data_phase_addr
|=
PL35X_NAND_ECC_LAST
;
data_phase_addr
+=
nand_offset
;
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
);
...
@@ -547,7 +650,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
...
@@ -547,7 +650,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
return
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
-=
nand_offset
;
data_phase_addr
&=
~
PL35X_NAND_ECC_LAST
;
data_phase_addr
&=
~
PL35X_NAND_ECC_LAST
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
/* Write the spare area with ECC bytes */
/* Write the spare area with ECC bytes */
...
@@ -556,8 +661,10 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
...
@@ -556,8 +661,10 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
));
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
));
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_W
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
|=
(
1
<<
END_CMD_VALID_SHIFT
);
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_W
=
(
void
__iomem
*
__force
)
data_phase_addr
;
oob_ptr
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
oob_ptr
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
write_buf
(
mtd
,
oob_ptr
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
write_buf
(
mtd
,
oob_ptr
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -571,6 +678,7 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
...
@@ -571,6 +678,7 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd,
* @chip: Pointer to the NAND chip info structure
* @chip: Pointer to the NAND chip info structure
* @buf: Pointer to the data buffer
* @buf: Pointer to the data buffer
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @oob_required: Caller requires OOB data read to chip->oob_poi
* @page: Page number to write
*
*
* Return: Always return zero
* Return: Always return zero
*/
*/
...
@@ -623,6 +731,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
...
@@ -623,6 +731,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
unsigned
long
data_phase_addr
;
unsigned
long
data_phase_addr
;
uint8_t
*
oob_ptr
;
uint8_t
*
oob_ptr
;
u32
ret
;
u32
ret
;
struct
pl35x_nand_info
*
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
unsigned
long
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
for
(
;
(
eccsteps
-
1
);
eccsteps
--
)
{
for
(
;
(
eccsteps
-
1
);
eccsteps
--
)
{
chip
->
read_buf
(
mtd
,
p
,
eccsize
);
chip
->
read_buf
(
mtd
,
p
,
eccsize
);
...
@@ -633,7 +744,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
...
@@ -633,7 +744,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
/* Set ECC Last bit to 1 */
/* Set ECC Last bit to 1 */
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_ECC_LAST
;
data_phase_addr
|=
PL35X_NAND_ECC_LAST
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
chip
->
read_buf
(
mtd
,
p
,
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -643,7 +756,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
...
@@ -643,7 +756,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
/* Clear ECC last bit */
/* Clear ECC last bit */
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
&=
~
PL35X_NAND_ECC_LAST
;
data_phase_addr
&=
~
PL35X_NAND_ECC_LAST
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
/* Read the stored ECC value */
/* Read the stored ECC value */
...
@@ -653,7 +768,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
...
@@ -653,7 +768,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd,
/* de-assert chip select */
/* de-assert chip select */
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
oob_ptr
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
oob_ptr
+=
(
mtd
->
oobsize
-
PL35X_NAND_LAST_TRANSFER_LENGTH
);
...
@@ -707,6 +824,8 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd,
...
@@ -707,6 +824,8 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd,
ret
=
mtd_ooblayout_get_eccbytes
(
mtd
,
ecc_calc
,
chip
->
oob_poi
,
ret
=
mtd_ooblayout_get_eccbytes
(
mtd
,
ecc_calc
,
chip
->
oob_poi
,
0
,
chip
->
ecc
.
total
);
0
,
chip
->
ecc
.
total
);
if
(
ret
)
return
ret
;
eccsteps
=
chip
->
ecc
.
steps
;
eccsteps
=
chip
->
ecc
.
steps
;
p
=
buf
;
p
=
buf
;
...
@@ -726,14 +845,34 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd,
...
@@ -726,14 +845,34 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd,
/**
/**
* pl35x_nand_select_chip - Select the flash device
* pl35x_nand_select_chip - Select the flash device
* @mtd: Pointer to the mtd info structure
* @mtd: Pointer to the mtd info structure
* @chip
: Pointer to the NAND chip info structure
* @chip
nr: chipnumber to select, -1 for deselect
*
*
* This function is empty as the NAND controller handles chip select line
* This function is empty as the NAND controller handles chip select line
* internally based on the chip address passed in command and data phase.
* internally based on the chip address passed in command and data phase.
*/
*/
static
void
pl35x_nand_select_chip
(
struct
mtd_info
*
mtd
,
int
chip
)
static
void
pl35x_nand_select_chip
(
struct
mtd_info
*
mtd
,
int
chip
nr
)
{
{
unsigned
long
data_phase_addr
;
struct
pl35x_nand_info
*
xnand
;
unsigned
long
nand_offset
;
struct
nand_chip
*
chip
;
/*
* Chip selection will happen in command/data operation
*/
if
(
chipnr
>=
0
)
return
;
return
;
/* de-assert chip select */
chip
=
mtd_to_nand
(
mtd
);
data_phase_addr
=
(
unsigned
long
__force
)
chip
->
IO_ADDR_R
;
xnand
=
container_of
(
chip
,
struct
pl35x_nand_info
,
chip
);
nand_offset
=
(
unsigned
long
__force
)
xnand
->
nand_base
;
data_phase_addr
-=
nand_offset
;
data_phase_addr
|=
PL35X_NAND_CLEAR_CS
;
data_phase_addr
+=
nand_offset
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
read_byte
(
mtd
);
}
}
/**
/**
...
@@ -746,11 +885,6 @@ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip)
...
@@ -746,11 +885,6 @@ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip)
static
void
pl35x_nand_cmd_function
(
struct
mtd_info
*
mtd
,
unsigned
int
command
,
static
void
pl35x_nand_cmd_function
(
struct
mtd_info
*
mtd
,
unsigned
int
command
,
int
column
,
int
page_addr
)
int
column
,
int
page_addr
)
{
{
if
(
command
==
NAND_CMD_READ0
)
pr_debug
(
"NAND READ
\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
"
);
struct
nand_chip
*
chip
=
mtd_to_nand
(
mtd
);
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
=
...
@@ -808,24 +942,24 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
...
@@ -808,24 +942,24 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
else
else
addrcycles
=
curr_cmd
->
addr_cycles
;
addrcycles
=
curr_cmd
->
addr_cycles
;
cmd_phase_addr
=
(
unsigned
long
__force
)
xnand
->
nand_base
|
cmd_phase_addr
=
(
unsigned
long
__force
)
xnand
->
nand_base
+
(
(
addrcycles
<<
ADDR_CYCLES_SHIFT
)
|
(
addrcycles
<<
ADDR_CYCLES_SHIFT
)
|
(
end_cmd_valid
<<
END_CMD_VALID_SHIFT
)
|
(
end_cmd_valid
<<
END_CMD_VALID_SHIFT
)
|
(
COMMAND_PHASE
)
|
(
COMMAND_PHASE
)
|
(
end_cmd
<<
END_CMD_SHIFT
)
|
(
end_cmd
<<
END_CMD_SHIFT
)
|
(
curr_cmd
->
start_cmd
<<
START_CMD_SHIFT
);
(
curr_cmd
->
start_cmd
<<
START_CMD_SHIFT
)
)
;
cmd_addr
=
(
void
__iomem
*
__force
)
cmd_phase_addr
;
cmd_addr
=
(
void
__iomem
*
__force
)
cmd_phase_addr
;
/* Get the data phase address */
/* Get the data phase address */
end_cmd_valid
=
0
;
end_cmd_valid
=
0
;
data_phase_addr
=
(
unsigned
long
__force
)
xnand
->
nand_base
|
data_phase_addr
=
(
unsigned
long
__force
)
xnand
->
nand_base
+
(
(
0x0
<<
CLEAR_CS_SHIFT
)
|
(
0x0
<<
CLEAR_CS_SHIFT
)
|
(
end_cmd_valid
<<
END_CMD_VALID_SHIFT
)
|
(
end_cmd_valid
<<
END_CMD_VALID_SHIFT
)
|
(
DATA_PHASE
)
|
(
DATA_PHASE
)
|
(
end_cmd
<<
END_CMD_SHIFT
)
|
(
end_cmd
<<
END_CMD_SHIFT
)
|
(
0x0
<<
ECC_LAST_SHIFT
);
(
0x0
<<
ECC_LAST_SHIFT
)
)
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_R
=
(
void
__iomem
*
__force
)
data_phase_addr
;
chip
->
IO_ADDR_W
=
chip
->
IO_ADDR_R
;
chip
->
IO_ADDR_W
=
chip
->
IO_ADDR_R
;
...
@@ -922,8 +1056,6 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
...
@@ -922,8 +1056,6 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
struct
nand_chip
*
chip
=
mtd_to_nand
(
mtd
);
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
);
len
>>=
2
;
len
>>=
2
;
for
(
i
=
0
;
i
<
len
;
i
++
)
for
(
i
=
0
;
i
<
len
;
i
++
)
...
@@ -1072,6 +1204,7 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd)
...
@@ -1072,6 +1204,7 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd)
/**
/**
* pl35x_nand_ecc_init - Initialize the ecc information as per the ecc mode
* pl35x_nand_ecc_init - Initialize the ecc information as per the ecc mode
* @mtd: Pointer to the mtd_info structure
* @mtd: Pointer to the mtd_info structure
* @ecc: Pointer to ECC control structure
* @ondie_ecc_state: ondie ecc status
* @ondie_ecc_state: ondie ecc status
*
*
* This function initializes the ecc block and functional pointers as per the
* This function initializes the ecc block and functional pointers as per the
...
@@ -1099,7 +1232,7 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
...
@@ -1099,7 +1232,7 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
*/
*/
ecc
->
bytes
=
0
;
ecc
->
bytes
=
0
;
mtd_set_ooblayout
(
mtd
,
&
fsmc_ecc_ooblayout_ondie64_ops
);
mtd_set_ooblayout
(
mtd
,
&
fsmc_ecc_ooblayout_ondie64_ops
);
ecc
->
read_page
=
pl35x_nand_read_page_
raw
;
ecc
->
read_page
=
pl35x_nand_read_page_
ondie
;
ecc
->
write_page
=
pl35x_nand_write_page_raw
;
ecc
->
write_page
=
pl35x_nand_write_page_raw
;
ecc
->
size
=
mtd
->
writesize
;
ecc
->
size
=
mtd
->
writesize
;
/*
/*
...
@@ -1188,9 +1321,10 @@ static int pl35x_nand_probe(struct platform_device *pdev)
...
@@ -1188,9 +1321,10 @@ static int pl35x_nand_probe(struct platform_device *pdev)
nand_chip
->
cmdfunc
=
pl35x_nand_cmd_function
;
nand_chip
->
cmdfunc
=
pl35x_nand_cmd_function
;
nand_chip
->
dev_ready
=
pl35x_nand_device_ready
;
nand_chip
->
dev_ready
=
pl35x_nand_device_ready
;
nand_chip
->
select_chip
=
pl35x_nand_select_chip
;
nand_chip
->
select_chip
=
pl35x_nand_select_chip
;
nand_chip
->
onfi_set_features
=
pl35x_nand_onfi_set_features
;
nand_chip
->
onfi_set_features
=
pl35x_nand_onfi_set_features
;
nand_chip
->
onfi_get_features
=
pl35x_nand_onfi_get_features
;
nand_chip
->
onfi_get_features
=
pl35x_nand_onfi_get_features
;
//nand_chip->onfi_set_features = nand_onfi_get_set_features_notsupp;
//nand_chip->onfi_get_features = nand_onfi_get_set_features_notsupp;
/* If we don't set this delay driver sets 20us by default */
/* If we don't set this delay driver sets 20us by default */
nand_chip
->
chip_delay
=
30
;
nand_chip
->
chip_delay
=
30
;
...
@@ -1273,7 +1407,6 @@ static struct platform_driver pl35x_nand_driver = {
...
@@ -1273,7 +1407,6 @@ static struct platform_driver pl35x_nand_driver = {
.
remove
=
pl35x_nand_remove
,
.
remove
=
pl35x_nand_remove
,
.
driver
=
{
.
driver
=
{
.
name
=
PL35X_NAND_DRIVER_NAME
,
.
name
=
PL35X_NAND_DRIVER_NAME
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
pl35x_nand_of_match
,
.
of_match_table
=
pl35x_nand_of_match
,
},
},
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment