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
b025beef
Commit
b025beef
authored
Nov 22, 2017
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated
parent
9159c877
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
165 additions
and
101 deletions
+165
-101
pl35x_nand.c
src/drivers/mtd/nand/pl35x_nand.c
+165
-101
No files found.
src/drivers/mtd/nand/pl35x_nand.c
View file @
b025beef
...
@@ -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
;
u
int32_t
*
eccpos
=
chip
->
ecc
.
layout
->
eccpos
;
u
32
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
;
u
int32_t
*
eccpos
=
chip
->
ecc
.
layout
->
eccpos
;
u
32
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
;
}
}
...
...
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