Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Linux-御风守护者
linux
提交
0305c865
L
linux
项目概览
Linux-御风守护者
/
linux
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0305c865
编写于
5月 24, 2006
作者:
D
David Woodhouse
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.infradead.org/~gleixner/mtd-nand-2.6.git
上级
99988f7b
d470a97c
变更
32
展开全部
隐藏空白更改
内联
并排
Showing
32 changed file
with
666 addition
and
1515 deletion
+666
-1515
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2000.c
+0
-66
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001.c
+0
-2
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/doc2001plus.c
+0
-2
drivers/mtd/inftlcore.c
drivers/mtd/inftlcore.c
+32
-31
drivers/mtd/inftlmount.c
drivers/mtd/inftlmount.c
+6
-6
drivers/mtd/mtdconcat.c
drivers/mtd/mtdconcat.c
+2
-134
drivers/mtd/mtdpart.c
drivers/mtd/mtdpart.c
+6
-100
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Kconfig
+2
-2
drivers/mtd/nand/ams-delta.c
drivers/mtd/nand/ams-delta.c
+28
-29
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/au1550nd.c
+26
-30
drivers/mtd/nand/autcpu12.c
drivers/mtd/nand/autcpu12.c
+48
-29
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/cs553x_nand.c
+8
-25
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/diskonchip.c
+34
-52
drivers/mtd/nand/edb7312.c
drivers/mtd/nand/edb7312.c
+18
-24
drivers/mtd/nand/h1910.c
drivers/mtd/nand/h1910.c
+11
-29
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_base.c
+121
-359
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_bbt.c
+62
-42
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/nandsim.c
+13
-76
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/ndfc.c
+9
-14
drivers/mtd/nand/ppchameleonevb.c
drivers/mtd/nand/ppchameleonevb.c
+58
-44
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/rtc_from4.c
+10
-24
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/s3c2410.c
+20
-44
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/sharpsl.c
+18
-23
drivers/mtd/nand/spia.c
drivers/mtd/nand/spia.c
+17
-10
drivers/mtd/nand/toto.c
drivers/mtd/nand/toto.c
+33
-32
drivers/mtd/nand/ts7250.c
drivers/mtd/nand/ts7250.c
+21
-23
drivers/mtd/nftlcore.c
drivers/mtd/nftlcore.c
+8
-7
drivers/mtd/nftlmount.c
drivers/mtd/nftlmount.c
+8
-4
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_base.c
+17
-200
fs/jffs2/wbuf.c
fs/jffs2/wbuf.c
+8
-20
include/linux/mtd/mtd.h
include/linux/mtd/mtd.h
+1
-10
include/linux/mtd/nand.h
include/linux/mtd/nand.h
+21
-22
未找到文件。
drivers/mtd/devices/doc2000.c
浏览文件 @
0305c865
...
...
@@ -59,9 +59,6 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
size_t
*
retlen
,
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
static
int
doc_write_ecc
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
static
int
doc_writev_ecc
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
static
int
doc_read_oob
(
struct
mtd_info
*
mtd
,
loff_t
ofs
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
);
static
int
doc_write_oob
(
struct
mtd_info
*
mtd
,
loff_t
ofs
,
size_t
len
,
...
...
@@ -587,9 +584,6 @@ void DoC2k_init(struct mtd_info *mtd)
mtd
->
unpoint
=
NULL
;
mtd
->
read
=
doc_read
;
mtd
->
write
=
doc_write
;
mtd
->
read_ecc
=
doc_read_ecc
;
mtd
->
write_ecc
=
doc_write_ecc
;
mtd
->
writev_ecc
=
doc_writev_ecc
;
mtd
->
read_oob
=
doc_read_oob
;
mtd
->
write_oob
=
doc_write_oob
;
mtd
->
sync
=
NULL
;
...
...
@@ -965,66 +959,6 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
return
0
;
}
static
int
doc_writev_ecc
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
static
char
static_buf
[
512
];
static
DEFINE_MUTEX
(
writev_buf_mutex
);
size_t
totretlen
=
0
;
size_t
thisvecofs
=
0
;
int
ret
=
0
;
mutex_lock
(
&
writev_buf_mutex
);
while
(
count
)
{
size_t
thislen
,
thisretlen
;
unsigned
char
*
buf
;
buf
=
vecs
->
iov_base
+
thisvecofs
;
thislen
=
vecs
->
iov_len
-
thisvecofs
;
if
(
thislen
>=
512
)
{
thislen
=
thislen
&
~
(
512
-
1
);
thisvecofs
+=
thislen
;
}
else
{
/* Not enough to fill a page. Copy into buf */
memcpy
(
static_buf
,
buf
,
thislen
);
buf
=
&
static_buf
[
thislen
];
while
(
count
&&
thislen
<
512
)
{
vecs
++
;
count
--
;
thisvecofs
=
min
((
512
-
thislen
),
vecs
->
iov_len
);
memcpy
(
buf
,
vecs
->
iov_base
,
thisvecofs
);
thislen
+=
thisvecofs
;
buf
+=
thisvecofs
;
}
buf
=
static_buf
;
}
if
(
count
&&
thisvecofs
==
vecs
->
iov_len
)
{
thisvecofs
=
0
;
vecs
++
;
count
--
;
}
ret
=
doc_write_ecc
(
mtd
,
to
,
thislen
,
&
thisretlen
,
buf
,
eccbuf
,
oobsel
);
totretlen
+=
thisretlen
;
if
(
ret
||
thisretlen
!=
thislen
)
break
;
to
+=
thislen
;
}
mutex_unlock
(
&
writev_buf_mutex
);
*
retlen
=
totretlen
;
return
ret
;
}
static
int
doc_read_oob
(
struct
mtd_info
*
mtd
,
loff_t
ofs
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
)
{
...
...
drivers/mtd/devices/doc2001.c
浏览文件 @
0305c865
...
...
@@ -369,8 +369,6 @@ void DoCMil_init(struct mtd_info *mtd)
mtd
->
unpoint
=
NULL
;
mtd
->
read
=
doc_read
;
mtd
->
write
=
doc_write
;
mtd
->
read_ecc
=
doc_read_ecc
;
mtd
->
write_ecc
=
doc_write_ecc
;
mtd
->
read_oob
=
doc_read_oob
;
mtd
->
write_oob
=
doc_write_oob
;
mtd
->
sync
=
NULL
;
...
...
drivers/mtd/devices/doc2001plus.c
浏览文件 @
0305c865
...
...
@@ -491,8 +491,6 @@ void DoCMilPlus_init(struct mtd_info *mtd)
mtd
->
unpoint
=
NULL
;
mtd
->
read
=
doc_read
;
mtd
->
write
=
doc_write
;
mtd
->
read_ecc
=
doc_read_ecc
;
mtd
->
write_ecc
=
doc_write_ecc
;
mtd
->
read_oob
=
doc_read_oob
;
mtd
->
write_oob
=
doc_write_oob
;
mtd
->
sync
=
NULL
;
...
...
drivers/mtd/inftlcore.c
浏览文件 @
0305c865
...
...
@@ -36,6 +36,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nftl.h>
#include <linux/mtd/inftl.h>
#include <linux/mtd/nand.h>
#include <asm/uaccess.h>
#include <asm/errno.h>
#include <asm/io.h>
...
...
@@ -79,14 +80,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
inftl
->
mbd
.
devnum
=
-
1
;
inftl
->
mbd
.
blksize
=
512
;
inftl
->
mbd
.
tr
=
tr
;
memcpy
(
&
inftl
->
oobinfo
,
&
mtd
->
oobinfo
,
sizeof
(
struct
nand_oobinfo
));
inftl
->
oobinfo
.
useecc
=
MTD_NANDECC_PLACEONLY
;
if
(
INFTL_mount
(
inftl
)
<
0
)
{
if
(
INFTL_mount
(
inftl
)
<
0
)
{
printk
(
KERN_WARNING
"INFTL: could not mount device
\n
"
);
kfree
(
inftl
);
return
;
}
}
/* OK, it's a new one. Set up all the data structures. */
...
...
@@ -221,7 +220,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
* Scan to find the Erase Unit which holds the actual data for each
* 512-byte block within the Chain.
*/
silly
=
MAX_LOOPS
;
silly
=
MAX_LOOPS
;
while
(
thisEUN
<
inftl
->
nb_blocks
)
{
for
(
block
=
0
;
block
<
inftl
->
EraseSize
/
SECTORSIZE
;
block
++
)
{
if
((
BlockMap
[
block
]
!=
0xffff
)
||
BlockDeleted
[
block
])
...
...
@@ -232,7 +231,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
(
char
*
)
&
oob
)
<
0
)
status
=
SECTOR_IGNORE
;
else
status
=
oob
.
b
.
Status
|
oob
.
b
.
Status1
;
status
=
oob
.
b
.
Status
|
oob
.
b
.
Status1
;
switch
(
status
)
{
case
SECTOR_FREE
:
...
...
@@ -282,29 +281,30 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
continue
;
}
/*
/*
* Copy only in non free block (free blocks can only
* happen in case of media errors or deleted blocks).
*/
if
(
BlockMap
[
block
]
==
BLOCK_NIL
)
continue
;
if
(
BlockMap
[
block
]
==
BLOCK_NIL
)
continue
;
ret
=
MTD_READ
(
inftl
->
mbd
.
mtd
,
(
inftl
->
EraseSize
*
ret
=
MTD_READ
(
inftl
->
mbd
.
mtd
,
(
inftl
->
EraseSize
*
BlockMap
[
block
])
+
(
block
*
SECTORSIZE
),
SECTORSIZE
,
&
retlen
,
movebuf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ret
=
MTD_READ
(
inftl
->
mbd
.
mtd
,
(
inftl
->
EraseSize
*
BlockMap
[
block
])
+
(
block
*
SECTORSIZE
),
SECTORSIZE
,
&
retlen
,
movebuf
);
if
(
ret
!=
-
EIO
)
DEBUG
(
MTD_DEBUG_LEVEL1
,
"INFTL: error went "
"away on retry?
\n
"
);
}
memset
(
&
oob
,
0xff
,
sizeof
(
struct
inftl_oob
));
oob
.
b
.
Status
=
oob
.
b
.
Status1
=
SECTOR_USED
;
MTD_WRITEECC
(
inftl
->
mbd
.
mtd
,
(
inftl
->
EraseSize
*
targetEUN
)
+
(
block
*
SECTORSIZE
),
SECTORSIZE
,
&
retlen
,
movebuf
,
(
char
*
)
&
oob
,
&
inftl
->
oobinfo
);
DEBUG
(
MTD_DEBUG_LEVEL1
,
"INFTL: error went "
"away on retry?
\n
"
);
}
memset
(
&
oob
,
0xff
,
sizeof
(
struct
inftl_oob
));
oob
.
b
.
Status
=
oob
.
b
.
Status1
=
SECTOR_USED
;
nand_write_raw
(
inftl
->
mbd
.
mtd
,
(
inftl
->
EraseSize
*
targetEUN
)
+
(
block
*
SECTORSIZE
),
SECTORSIZE
,
&
retlen
,
movebuf
,
(
char
*
)
&
oob
);
}
/*
...
...
@@ -329,17 +329,17 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
if
(
thisEUN
==
targetEUN
)
break
;
if
(
INFTL_formatblock
(
inftl
,
thisEUN
)
<
0
)
{
if
(
INFTL_formatblock
(
inftl
,
thisEUN
)
<
0
)
{
/*
* Could not erase : mark block as reserved.
*/
inftl
->
PUtable
[
thisEUN
]
=
BLOCK_RESERVED
;
}
else
{
}
else
{
/* Correctly erased : mark it as free */
inftl
->
PUtable
[
thisEUN
]
=
BLOCK_FREE
;
inftl
->
PUtable
[
prevEUN
]
=
BLOCK_NIL
;
inftl
->
numfreeEUNs
++
;
}
}
}
return
targetEUN
;
...
...
@@ -437,7 +437,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
MTD_READOOB
(
inftl
->
mbd
.
mtd
,
(
thisEUN
*
inftl
->
EraseSize
)
+
blockofs
,
8
,
&
retlen
,
(
char
*
)
&
bci
);
status
=
bci
.
Status
|
bci
.
Status1
;
status
=
bci
.
Status
|
bci
.
Status1
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"INFTL: status of block %d in "
"EUN %d is %x
\n
"
,
block
,
writeEUN
,
status
);
...
...
@@ -670,12 +670,12 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
DEBUG
(
MTD_DEBUG_LEVEL3
,
"Deleting EUN %d from VUC %d
\n
"
,
thisEUN
,
thisVUC
);
if
(
INFTL_formatblock
(
inftl
,
thisEUN
)
<
0
)
{
if
(
INFTL_formatblock
(
inftl
,
thisEUN
)
<
0
)
{
/*
* Could not erase : mark block as reserved.
*/
inftl
->
PUtable
[
thisEUN
]
=
BLOCK_RESERVED
;
}
else
{
}
else
{
/* Correctly erased : mark it as free */
inftl
->
PUtable
[
thisEUN
]
=
BLOCK_FREE
;
inftl
->
numfreeEUNs
++
;
...
...
@@ -784,9 +784,10 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
memset
(
&
oob
,
0xff
,
sizeof
(
struct
inftl_oob
));
oob
.
b
.
Status
=
oob
.
b
.
Status1
=
SECTOR_USED
;
MTD_WRITEECC
(
inftl
->
mbd
.
mtd
,
(
writeEUN
*
inftl
->
EraseSize
)
+
blockofs
,
SECTORSIZE
,
&
retlen
,
(
char
*
)
buffer
,
(
char
*
)
&
oob
,
&
inftl
->
oobinfo
);
nand_write_raw
(
inftl
->
mbd
.
mtd
,
(
writeEUN
*
inftl
->
EraseSize
)
+
blockofs
,
SECTORSIZE
,
&
retlen
,
(
char
*
)
buffer
,
(
char
*
)
&
oob
);
/*
* need to write SECTOR_USED flags since they are not written
* in mtd_writeecc
...
...
@@ -804,9 +805,9 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
struct
INFTLrecord
*
inftl
=
(
void
*
)
mbd
;
unsigned
int
thisEUN
=
inftl
->
VUtable
[
block
/
(
inftl
->
EraseSize
/
SECTORSIZE
)];
unsigned
long
blockofs
=
(
block
*
SECTORSIZE
)
&
(
inftl
->
EraseSize
-
1
);
unsigned
int
status
;
unsigned
int
status
;
int
silly
=
MAX_LOOPS
;
struct
inftl_bci
bci
;
struct
inftl_bci
bci
;
size_t
retlen
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"INFTL: inftl_readblock(inftl=%p,block=%ld,"
...
...
@@ -850,7 +851,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
/* The requested block is not on the media, return all 0x00 */
memset
(
buffer
,
0
,
SECTORSIZE
);
}
else
{
size_t
retlen
;
size_t
retlen
;
loff_t
ptr
=
(
thisEUN
*
inftl
->
EraseSize
)
+
blockofs
;
if
(
MTD_READ
(
inftl
->
mbd
.
mtd
,
ptr
,
SECTORSIZE
,
&
retlen
,
buffer
))
...
...
drivers/mtd/inftlmount.c
浏览文件 @
0305c865
...
...
@@ -350,21 +350,21 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
int
len
,
int
check_oob
)
{
u8
buf
[
SECTORSIZE
+
inftl
->
mbd
.
mtd
->
oobsize
];
struct
mtd_info
*
mtd
=
inftl
->
mbd
.
mtd
;
size_t
retlen
;
int
i
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"INFTL: check_free_sectors(inftl=%p,"
"address=0x%x,len=%d,check_oob=%d)
\n
"
,
inftl
,
address
,
len
,
check_oob
);
for
(
i
=
0
;
i
<
len
;
i
+=
SECTORSIZE
)
{
if
(
MTD_READECC
(
inftl
->
mbd
.
mtd
,
address
,
SECTORSIZE
,
&
retlen
,
buf
,
&
buf
[
SECTORSIZE
],
&
inftl
->
oobinfo
)
<
0
)
if
(
mtd
->
read
(
mtd
,
address
,
SECTORSIZE
,
&
retlen
,
buf
)
)
return
-
1
;
if
(
memcmpb
(
buf
,
0xff
,
SECTORSIZE
)
!=
0
)
return
-
1
;
if
(
check_oob
)
{
if
(
memcmpb
(
buf
+
SECTORSIZE
,
0xff
,
inftl
->
mbd
.
mtd
->
oobsize
)
!=
0
)
if
(
mtd
->
read_oob
(
mtd
,
address
,
mtd
->
oobsize
,
&
retlen
,
&
buf
[
SECTORSIZE
])
<
0
)
return
-
1
;
if
(
memcmpb
(
buf
+
SECTORSIZE
,
0xff
,
mtd
->
oobsize
)
!=
0
)
return
-
1
;
}
address
+=
SECTORSIZE
;
...
...
drivers/mtd/mtdconcat.c
浏览文件 @
0305c865
...
...
@@ -143,119 +143,8 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
}
static
int
concat_read_ecc
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_concat
*
concat
=
CONCAT
(
mtd
);
int
err
=
-
EINVAL
;
int
i
;
*
retlen
=
0
;
for
(
i
=
0
;
i
<
concat
->
num_subdev
;
i
++
)
{
struct
mtd_info
*
subdev
=
concat
->
subdev
[
i
];
size_t
size
,
retsize
;
if
(
from
>=
subdev
->
size
)
{
/* Not destined for this subdev */
size
=
0
;
from
-=
subdev
->
size
;
continue
;
}
if
(
from
+
len
>
subdev
->
size
)
/* First part goes into this subdev */
size
=
subdev
->
size
-
from
;
else
/* Entire transaction goes into this subdev */
size
=
len
;
if
(
subdev
->
read_ecc
)
err
=
subdev
->
read_ecc
(
subdev
,
from
,
size
,
&
retsize
,
buf
,
eccbuf
,
oobsel
);
else
err
=
-
EINVAL
;
if
(
err
)
break
;
*
retlen
+=
retsize
;
len
-=
size
;
if
(
len
==
0
)
break
;
err
=
-
EINVAL
;
buf
+=
size
;
if
(
eccbuf
)
{
eccbuf
+=
subdev
->
oobsize
;
/* in nand.c at least, eccbufs are
tagged with 2 (int)eccstatus'; we
must account for these */
eccbuf
+=
2
*
(
sizeof
(
int
));
}
from
=
0
;
}
return
err
;
}
static
int
concat_write_ecc
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_concat
*
concat
=
CONCAT
(
mtd
);
int
err
=
-
EINVAL
;
int
i
;
if
(
!
(
mtd
->
flags
&
MTD_WRITEABLE
))
return
-
EROFS
;
*
retlen
=
0
;
for
(
i
=
0
;
i
<
concat
->
num_subdev
;
i
++
)
{
struct
mtd_info
*
subdev
=
concat
->
subdev
[
i
];
size_t
size
,
retsize
;
if
(
to
>=
subdev
->
size
)
{
size
=
0
;
to
-=
subdev
->
size
;
continue
;
}
if
(
to
+
len
>
subdev
->
size
)
size
=
subdev
->
size
-
to
;
else
size
=
len
;
if
(
!
(
subdev
->
flags
&
MTD_WRITEABLE
))
err
=
-
EROFS
;
else
if
(
subdev
->
write_ecc
)
err
=
subdev
->
write_ecc
(
subdev
,
to
,
size
,
&
retsize
,
buf
,
eccbuf
,
oobsel
);
else
err
=
-
EINVAL
;
if
(
err
)
break
;
*
retlen
+=
retsize
;
len
-=
size
;
if
(
len
==
0
)
break
;
err
=
-
EINVAL
;
buf
+=
size
;
if
(
eccbuf
)
eccbuf
+=
subdev
->
oobsize
;
to
=
0
;
}
return
err
;
}
static
int
concat_writev_ecc
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
concat_writev
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
)
{
struct
mtd_concat
*
concat
=
CONCAT
(
mtd
);
struct
kvec
*
vecs_copy
;
...
...
@@ -315,10 +204,6 @@ concat_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
if
(
!
(
subdev
->
flags
&
MTD_WRITEABLE
))
err
=
-
EROFS
;
else
if
(
eccbuf
)
err
=
subdev
->
writev_ecc
(
subdev
,
&
vecs_copy
[
entry_low
],
entry_high
-
entry_low
+
1
,
to
,
&
retsize
,
eccbuf
,
oobsel
);
else
err
=
subdev
->
writev
(
subdev
,
&
vecs_copy
[
entry_low
],
entry_high
-
entry_low
+
1
,
to
,
&
retsize
);
...
...
@@ -333,8 +218,6 @@ concat_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
*
retlen
+=
retsize
;
total_len
-=
wsize
;
if
(
concat
->
mtd
.
type
==
MTD_NANDFLASH
&&
eccbuf
)
eccbuf
+=
mtd
->
oobavail
*
(
wsize
/
mtd
->
writesize
);
if
(
total_len
==
0
)
break
;
...
...
@@ -347,13 +230,6 @@ concat_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
return
err
;
}
static
int
concat_writev
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
)
{
return
concat_writev_ecc
(
mtd
,
vecs
,
count
,
to
,
retlen
,
NULL
,
NULL
);
}
static
int
concat_read_oob
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
)
...
...
@@ -837,14 +713,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat
->
mtd
.
oobsize
=
subdev
[
0
]
->
oobsize
;
concat
->
mtd
.
ecctype
=
subdev
[
0
]
->
ecctype
;
concat
->
mtd
.
eccsize
=
subdev
[
0
]
->
eccsize
;
if
(
subdev
[
0
]
->
read_ecc
)
concat
->
mtd
.
read_ecc
=
concat_read_ecc
;
if
(
subdev
[
0
]
->
write_ecc
)
concat
->
mtd
.
write_ecc
=
concat_write_ecc
;
if
(
subdev
[
0
]
->
writev
)
concat
->
mtd
.
writev
=
concat_writev
;
if
(
subdev
[
0
]
->
writev_ecc
)
concat
->
mtd
.
writev_ecc
=
concat_writev_ecc
;
if
(
subdev
[
0
]
->
read_oob
)
concat
->
mtd
.
read_oob
=
concat_read_oob
;
if
(
subdev
[
0
]
->
write_oob
)
...
...
@@ -885,8 +755,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat
->
mtd
.
oobsize
!=
subdev
[
i
]
->
oobsize
||
concat
->
mtd
.
ecctype
!=
subdev
[
i
]
->
ecctype
||
concat
->
mtd
.
eccsize
!=
subdev
[
i
]
->
eccsize
||
!
concat
->
mtd
.
read_ecc
!=
!
subdev
[
i
]
->
read_ecc
||
!
concat
->
mtd
.
write_ecc
!=
!
subdev
[
i
]
->
write_ecc
||
!
concat
->
mtd
.
read_oob
!=
!
subdev
[
i
]
->
read_oob
||
!
concat
->
mtd
.
write_oob
!=
!
subdev
[
i
]
->
write_oob
)
{
kfree
(
concat
);
...
...
drivers/mtd/mtdpart.c
浏览文件 @
0305c865
...
...
@@ -55,12 +55,8 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
len
=
0
;
else
if
(
from
+
len
>
mtd
->
size
)
len
=
mtd
->
size
-
from
;
if
(
part
->
master
->
read_ecc
==
NULL
)
return
part
->
master
->
read
(
part
->
master
,
from
+
part
->
offset
,
len
,
retlen
,
buf
);
else
return
part
->
master
->
read_ecc
(
part
->
master
,
from
+
part
->
offset
,
len
,
retlen
,
buf
,
NULL
,
&
mtd
->
oobinfo
);
return
part
->
master
->
read
(
part
->
master
,
from
+
part
->
offset
,
len
,
retlen
,
buf
);
}
static
int
part_point
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
...
...
@@ -74,6 +70,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
return
part
->
master
->
point
(
part
->
master
,
from
+
part
->
offset
,
len
,
retlen
,
buf
);
}
static
void
part_unpoint
(
struct
mtd_info
*
mtd
,
u_char
*
addr
,
loff_t
from
,
size_t
len
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
...
...
@@ -81,21 +78,6 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_
part
->
master
->
unpoint
(
part
->
master
,
addr
,
from
+
part
->
offset
,
len
);
}
static
int
part_read_ecc
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
oobsel
==
NULL
)
oobsel
=
&
mtd
->
oobinfo
;
if
(
from
>=
mtd
->
size
)
len
=
0
;
else
if
(
from
+
len
>
mtd
->
size
)
len
=
mtd
->
size
-
from
;
return
part
->
master
->
read_ecc
(
part
->
master
,
from
+
part
->
offset
,
len
,
retlen
,
buf
,
eccbuf
,
oobsel
);
}
static
int
part_read_oob
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
)
{
...
...
@@ -148,30 +130,8 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
len
=
0
;
else
if
(
to
+
len
>
mtd
->
size
)
len
=
mtd
->
size
-
to
;
if
(
part
->
master
->
write_ecc
==
NULL
)
return
part
->
master
->
write
(
part
->
master
,
to
+
part
->
offset
,
len
,
retlen
,
buf
);
else
return
part
->
master
->
write_ecc
(
part
->
master
,
to
+
part
->
offset
,
len
,
retlen
,
buf
,
NULL
,
&
mtd
->
oobinfo
);
}
static
int
part_write_ecc
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
!
(
mtd
->
flags
&
MTD_WRITEABLE
))
return
-
EROFS
;
if
(
oobsel
==
NULL
)
oobsel
=
&
mtd
->
oobinfo
;
if
(
to
>=
mtd
->
size
)
len
=
0
;
else
if
(
to
+
len
>
mtd
->
size
)
len
=
mtd
->
size
-
to
;
return
part
->
master
->
write_ecc
(
part
->
master
,
to
+
part
->
offset
,
len
,
retlen
,
buf
,
eccbuf
,
oobsel
);
return
part
->
master
->
write
(
part
->
master
,
to
+
part
->
offset
,
len
,
retlen
,
buf
);
}
static
int
part_write_oob
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
...
...
@@ -208,52 +168,8 @@ static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
!
(
mtd
->
flags
&
MTD_WRITEABLE
))
return
-
EROFS
;
if
(
part
->
master
->
writev_ecc
==
NULL
)
return
part
->
master
->
writev
(
part
->
master
,
vecs
,
count
,
return
part
->
master
->
writev
(
part
->
master
,
vecs
,
count
,
to
+
part
->
offset
,
retlen
);
else
return
part
->
master
->
writev_ecc
(
part
->
master
,
vecs
,
count
,
to
+
part
->
offset
,
retlen
,
NULL
,
&
mtd
->
oobinfo
);
}
static
int
part_readv
(
struct
mtd_info
*
mtd
,
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
from
,
size_t
*
retlen
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
part
->
master
->
readv_ecc
==
NULL
)
return
part
->
master
->
readv
(
part
->
master
,
vecs
,
count
,
from
+
part
->
offset
,
retlen
);
else
return
part
->
master
->
readv_ecc
(
part
->
master
,
vecs
,
count
,
from
+
part
->
offset
,
retlen
,
NULL
,
&
mtd
->
oobinfo
);
}
static
int
part_writev_ecc
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
!
(
mtd
->
flags
&
MTD_WRITEABLE
))
return
-
EROFS
;
if
(
oobsel
==
NULL
)
oobsel
=
&
mtd
->
oobinfo
;
return
part
->
master
->
writev_ecc
(
part
->
master
,
vecs
,
count
,
to
+
part
->
offset
,
retlen
,
eccbuf
,
oobsel
);
}
static
int
part_readv_ecc
(
struct
mtd_info
*
mtd
,
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
from
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
mtd_part
*
part
=
PART
(
mtd
);
if
(
oobsel
==
NULL
)
oobsel
=
&
mtd
->
oobinfo
;
return
part
->
master
->
readv_ecc
(
part
->
master
,
vecs
,
count
,
from
+
part
->
offset
,
retlen
,
eccbuf
,
oobsel
);
}
static
int
part_erase
(
struct
mtd_info
*
mtd
,
struct
erase_info
*
instr
)
...
...
@@ -416,10 +332,6 @@ int add_mtd_partitions(struct mtd_info *master,
slave
->
mtd
.
unpoint
=
part_unpoint
;
}
if
(
master
->
read_ecc
)
slave
->
mtd
.
read_ecc
=
part_read_ecc
;
if
(
master
->
write_ecc
)
slave
->
mtd
.
write_ecc
=
part_write_ecc
;
if
(
master
->
read_oob
)
slave
->
mtd
.
read_oob
=
part_read_oob
;
if
(
master
->
write_oob
)
...
...
@@ -444,12 +356,6 @@ int add_mtd_partitions(struct mtd_info *master,
}
if
(
master
->
writev
)
slave
->
mtd
.
writev
=
part_writev
;
if
(
master
->
readv
)
slave
->
mtd
.
readv
=
part_readv
;
if
(
master
->
writev_ecc
)
slave
->
mtd
.
writev_ecc
=
part_writev_ecc
;
if
(
master
->
readv_ecc
)
slave
->
mtd
.
readv_ecc
=
part_readv_ecc
;
if
(
master
->
lock
)
slave
->
mtd
.
lock
=
part_lock
;
if
(
master
->
unlock
)
...
...
drivers/mtd/nand/Kconfig
浏览文件 @
0305c865
...
...
@@ -65,7 +65,7 @@ config MTD_NAND_AMS_DELTA
config MTD_NAND_TOTO
tristate "NAND Flash device on TOTO board"
depends on ARCH_OMAP && MTD_NAND
depends on ARCH_OMAP && MTD_NAND
&& BROKEN
help
Support for NAND flash on Texas Instruments Toto platform.
...
...
@@ -96,7 +96,7 @@ config MTD_NAND_RTC_FROM4
config MTD_NAND_PPCHAMELEONEVB
tristate "NAND Flash device on PPChameleonEVB board"
depends on PPCHAMELEONEVB && MTD_NAND
depends on PPCHAMELEONEVB && MTD_NAND
&& BROKEN
help
This enables the NAND flash driver on the PPChameleon EVB Board.
...
...
drivers/mtd/nand/ams-delta.c
浏览文件 @
0305c865
...
...
@@ -34,13 +34,6 @@ static struct mtd_info *ams_delta_mtd = NULL;
#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
#define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0)
#define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE)
#define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0)
#define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE)
#define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0)
#define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE)
/*
* Define partitions for flash devices
*/
...
...
@@ -66,25 +59,6 @@ static struct mtd_partition partition_info[] = {
.
size
=
3
*
SZ_256K
},
};
/*
* hardware specific access to control-lines
*/
static
void
ams_delta_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
{
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
T_NAND_CTL_SETCLE
(
cmd
);
break
;
case
NAND_CTL_CLRCLE
:
T_NAND_CTL_CLRCLE
(
cmd
);
break
;
case
NAND_CTL_SETALE
:
T_NAND_CTL_SETALE
(
cmd
);
break
;
case
NAND_CTL_CLRALE
:
T_NAND_CTL_CLRALE
(
cmd
);
break
;
case
NAND_CTL_SETNCE
:
T_NAND_CTL_SETNCE
(
cmd
);
break
;
case
NAND_CTL_CLRNCE
:
T_NAND_CTL_CLRNCE
(
cmd
);
break
;
}
}
static
void
ams_delta_write_byte
(
struct
mtd_info
*
mtd
,
u_char
byte
)
{
struct
nand_chip
*
this
=
mtd
->
priv
;
...
...
@@ -141,6 +115,32 @@ static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
return
0
;
}
/*
* Command control function
*
* ctrl:
* NAND_NCE: bit 0 -> bit 2
* NAND_CLE: bit 1 -> bit 7
* NAND_ALE: bit 2 -> bit 6
*/
static
void
ams_delta_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
long
bits
;
bits
=
(
~
ctrl
&
NAND_NCE
)
<<
2
;
bits
|=
(
ctrl
&
NAND_CLE
)
<<
7
;
bits
|=
(
ctrl
&
NAND_ALE
)
<<
6
;
ams_delta_latch2_write
(
0xC2
,
bits
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
ams_delta_write_byte
(
mtd
,
cmd
);
}
static
int
ams_delta_nand_ready
(
struct
mtd_info
*
mtd
)
{
return
omap_get_gpio_datain
(
AMS_DELTA_GPIO_PIN_NAND_RB
);
...
...
@@ -179,11 +179,10 @@ static int __init ams_delta_init(void)
this
->
IO_ADDR_R
=
(
OMAP_MPUIO_BASE
+
OMAP_MPUIO_INPUT_LATCH
);
this
->
IO_ADDR_W
=
(
OMAP_MPUIO_BASE
+
OMAP_MPUIO_OUTPUT
);
this
->
read_byte
=
ams_delta_read_byte
;
this
->
write_byte
=
ams_delta_write_byte
;
this
->
write_buf
=
ams_delta_write_buf
;
this
->
read_buf
=
ams_delta_read_buf
;
this
->
verify_buf
=
ams_delta_verify_buf
;
this
->
hwcontro
l
=
ams_delta_hwcontrol
;
this
->
cmd_ctr
l
=
ams_delta_hwcontrol
;
if
(
!
omap_request_gpio
(
AMS_DELTA_GPIO_PIN_NAND_RB
))
{
this
->
dev_ready
=
ams_delta_nand_ready
;
}
else
{
...
...
@@ -200,7 +199,7 @@ static int __init ams_delta_init(void)
AMS_DELTA_LATCH2_NAND_NCE
|
AMS_DELTA_LATCH2_NAND_NWP
);
/* Scan to find existance of the device */
/* Scan to find existance of the device */
if
(
nand_scan
(
ams_delta_mtd
,
1
))
{
err
=
-
ENXIO
;
goto
out_mtd
;
...
...
drivers/mtd/nand/au1550nd.c
浏览文件 @
0305c865
...
...
@@ -40,6 +40,7 @@
static
struct
mtd_info
*
au1550_mtd
=
NULL
;
static
void
__iomem
*
p_nand
;
static
int
nand_width
=
1
;
/* default x8 */
static
void
(
*
au1550_write_byte
)(
struct
mtd_info
*
,
u_char
);
/*
* Define partitions for flash device
...
...
@@ -128,21 +129,6 @@ static u16 au_read_word(struct mtd_info *mtd)
return
ret
;
}
/**
* au_write_word - write one word to the chip
* @mtd: MTD device structure
* @word: data word to write
*
* write function for 16bit buswith without
* endianess conversion
*/
static
void
au_write_word
(
struct
mtd_info
*
mtd
,
u16
word
)
{
struct
nand_chip
*
this
=
mtd
->
priv
;
writew
(
word
,
this
->
IO_ADDR_W
);
au_sync
();
}
/**
* au_write_buf - write buffer to chip
* @mtd: MTD device structure
...
...
@@ -269,6 +255,18 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
return
0
;
}
/* Select the chip by setting nCE to low */
#define NAND_CTL_SETNCE 1
/* Deselect the chip by setting nCE to high */
#define NAND_CTL_CLRNCE 2
/* Select the command latch by setting CLE to high */
#define NAND_CTL_SETCLE 3
/* Deselect the command latch by setting CLE to low */
#define NAND_CTL_CLRCLE 4
/* Select the address latch by setting ALE to high */
#define NAND_CTL_SETALE 5
/* Deselect the address latch by setting ALE to low */
#define NAND_CTL_CLRALE 6
static
void
au1550_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
{
...
...
@@ -349,7 +347,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
ulong
flags
;
/* Begin command latch cycle */
this
->
hwcontrol
(
mtd
,
NAND_CTL_SETCLE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_SETCLE
);
/*
* Write out the command to the device.
*/
...
...
@@ -367,25 +365,25 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
column
-=
256
;
readcmd
=
NAND_CMD_READ1
;
}
this
->
write_byte
(
mtd
,
readcmd
);
au1550_
write_byte
(
mtd
,
readcmd
);
}
this
->
write_byte
(
mtd
,
command
);
au1550_
write_byte
(
mtd
,
command
);
/* Set ALE and clear CLE to start address cycle */
this
->
hwcontrol
(
mtd
,
NAND_CTL_CLRCLE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_CLRCLE
);
if
(
column
!=
-
1
||
page_addr
!=
-
1
)
{
this
->
hwcontrol
(
mtd
,
NAND_CTL_SETALE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_SETALE
);
/* Serially input address */
if
(
column
!=
-
1
)
{
/* Adjust columns for 16 bit buswidth */
if
(
this
->
options
&
NAND_BUSWIDTH_16
)
column
>>=
1
;
this
->
write_byte
(
mtd
,
column
);
au1550_
write_byte
(
mtd
,
column
);
}
if
(
page_addr
!=
-
1
)
{
this
->
write_byte
(
mtd
,
(
u8
)(
page_addr
&
0xff
));
au1550_
write_byte
(
mtd
,
(
u8
)(
page_addr
&
0xff
));
if
(
command
==
NAND_CMD_READ0
||
command
==
NAND_CMD_READ1
||
...
...
@@ -400,17 +398,17 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
*/
ce_override
=
1
;
local_irq_save
(
flags
);
this
->
hwcontrol
(
mtd
,
NAND_CTL_SETNCE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_SETNCE
);
}
this
->
write_byte
(
mtd
,
(
u8
)(
page_addr
>>
8
));
au1550_
write_byte
(
mtd
,
(
u8
)(
page_addr
>>
8
));
/* One more address cycle for devices > 32MiB */
if
(
this
->
chipsize
>
(
32
<<
20
))
this
->
write_byte
(
mtd
,
(
u8
)((
page_addr
>>
16
)
&
0x0f
));
au1550_
write_byte
(
mtd
,
(
u8
)((
page_addr
>>
16
)
&
0x0f
));
}
/* Latch in address */
this
->
hwcontrol
(
mtd
,
NAND_CTL_CLRALE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_CLRALE
);
}
/*
...
...
@@ -443,7 +441,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
udelay
(
1
);
/* Release -CE and re-enable interrupts. */
this
->
hwcontrol
(
mtd
,
NAND_CTL_CLRNCE
);
au1550_
hwcontrol
(
mtd
,
NAND_CTL_CLRNCE
);
local_irq_restore
(
flags
);
return
;
}
...
...
@@ -571,7 +569,6 @@ static int __init au1xxx_nand_init(void)
nand_width
=
au_readl
(
MEM_STCFG3
)
&
(
1
<<
22
);
/* Set address of hardware control function */
this
->
hwcontrol
=
au1550_hwcontrol
;
this
->
dev_ready
=
au1550_device_ready
;
this
->
select_chip
=
au1550_select_chip
;
this
->
cmdfunc
=
au1550_command
;
...
...
@@ -586,8 +583,7 @@ static int __init au1xxx_nand_init(void)
this
->
options
|=
NAND_BUSWIDTH_16
;
this
->
read_byte
=
(
!
nand_width
)
?
au_read_byte16
:
au_read_byte
;
this
->
write_byte
=
(
!
nand_width
)
?
au_write_byte16
:
au_write_byte
;
this
->
write_word
=
au_write_word
;
au1550_write_byte
=
(
!
nand_width
)
?
au_write_byte16
:
au_write_byte
;
this
->
read_word
=
au_read_word
;
this
->
write_buf
=
(
!
nand_width
)
?
au_write_buf16
:
au_write_buf
;
this
->
read_buf
=
(
!
nand_width
)
?
au_read_buf16
:
au_read_buf
;
...
...
drivers/mtd/nand/autcpu12.c
浏览文件 @
0305c865
...
...
@@ -4,7 +4,7 @@
* Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
*
* Derived from drivers/mtd/spia.c
*
Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
* $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
*
...
...
@@ -42,11 +42,6 @@
* MTD structure for AUTCPU12 board
*/
static
struct
mtd_info
*
autcpu12_mtd
=
NULL
;
static
int
autcpu12_io_base
=
CS89712_VIRT_BASE
;
static
int
autcpu12_fio_pbase
=
AUTCPU12_PHYS_SMC
;
static
int
autcpu12_fio_ctrl
=
AUTCPU12_SMC_SELECT_OFFSET
;
static
int
autcpu12_pedr
=
AUTCPU12_SMC_PORT_OFFSET
;
static
void
__iomem
*
autcpu12_fio_base
;
/*
...
...
@@ -94,31 +89,42 @@ static struct mtd_partition partition_info128k[] = {
#define NUM_PARTITIONS128K 2
/*
* hardware specific access to control-lines
*/
static
void
autcpu12_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
*
* ALE bit 4 autcpu12_pedr
* CLE bit 5 autcpu12_pedr
* NCE bit 0 fio_ctrl
*
*/
static
void
autcpu12_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
s
witch
(
cmd
)
{
s
truct
nand_chip
*
chip
=
mtd
->
priv
;
case
NAND_CTL_SETCLE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_io_base
+
autcpu12_pedr
))
|=
AUTCPU12_SMC_CLE
;
break
;
case
NAND_CTL_CLRCLE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_io_base
+
autcpu12_pedr
))
&=
~
AUTCPU12_SMC_CLE
;
break
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
void
__iomem
*
addr
unsigned
char
bits
;
case
NAND_CTL_SETALE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_io_base
+
autcpu12_pedr
))
|=
AUTCPU12_SMC_ALE
;
break
;
case
NAND_CTL_CLRALE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_io_base
+
autcpu12_pedr
))
&=
~
AUTCPU12_SMC_ALE
;
break
;
addr
=
CS89712_VIRT_BASE
+
AUTCPU12_SMC_PORT_OFFSET
;
bits
=
(
ctrl
&
NAND_CLE
)
<<
4
;
bits
|=
(
ctrl
&
NAND_ALE
)
<<
2
;
writeb
((
readb
(
addr
)
&
~
0x30
)
|
bits
,
addr
);
case
NAND_CTL_SETNCE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_fio_base
+
autcpu12_fio_ctrl
))
=
0x01
;
break
;
case
NAND_CTL_CLRNCE
:
(
*
(
volatile
unsigned
char
*
)
(
autcpu12_fio_base
+
autcpu12_fio_ctrl
))
=
0x00
;
break
;
addr
=
autcpu12_fio_base
+
AUTCPU12_SMC_SELECT_OFFSET
;
writeb
((
readb
(
addr
)
&
~
0x1
)
|
(
ctrl
&
NAND_NCE
),
addr
)
;
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
/*
* read device ready pin
*/
* read device ready pin
*/
int
autcpu12_device_ready
(
struct
mtd_info
*
mtd
)
{
void
__iomem
*
addr
=
CS89712_VIRT_BASE
+
AUTCPU12_SMC_PORT_OFFSET
;
return
((
*
(
volatile
unsigned
char
*
)(
autcpu12_io_base
+
autcpu12_pedr
))
&
AUTCPU12_SMC_RDY
)
?
1
:
0
;
return
readb
(
addr
)
&
AUTCPU12_SMC_RDY
;
}
/*
...
...
@@ -130,7 +136,8 @@ static int __init autcpu12_init(void)
int
err
=
0
;
/* Allocate memory for MTD device structure and private data */
autcpu12_mtd
=
kmalloc
(
sizeof
(
struct
mtd_info
)
+
sizeof
(
struct
nand_chip
),
GFP_KERNEL
);
autcpu12_mtd
=
kmalloc
(
sizeof
(
struct
mtd_info
)
+
sizeof
(
struct
nand_chip
),
GFP_KERNEL
);
if
(
!
autcpu12_mtd
)
{
printk
(
"Unable to allocate AUTCPU12 NAND MTD device structure.
\n
"
);
err
=
-
ENOMEM
;
...
...
@@ -138,7 +145,7 @@ static int __init autcpu12_init(void)
}
/* map physical adress */
autcpu12_fio_base
=
ioremap
(
autcpu12_fio_pbase
,
SZ_1K
);
autcpu12_fio_base
=
ioremap
(
AUTCPU12_PHYS_SMC
,
SZ_1K
);
if
(
!
autcpu12_fio_base
)
{
printk
(
"Ioremap autcpu12 SmartMedia Card failed
\n
"
);
err
=
-
EIO
;
...
...
@@ -159,7 +166,7 @@ static int __init autcpu12_init(void)
/* Set address of NAND IO lines */
this
->
IO_ADDR_R
=
autcpu12_fio_base
;
this
->
IO_ADDR_W
=
autcpu12_fio_base
;
this
->
hwcontro
l
=
autcpu12_hwcontrol
;
this
->
cmd_ctr
l
=
autcpu12_hwcontrol
;
this
->
dev_ready
=
autcpu12_device_ready
;
/* 20 us command delay time */
this
->
chip_delay
=
20
;
...
...
@@ -179,10 +186,22 @@ static int __init autcpu12_init(void)
/* Register the partitions */
switch
(
autcpu12_mtd
->
size
)
{
case
SZ_16M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info16k
,
NUM_PARTITIONS16K
);
break
;
case
SZ_32M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info32k
,
NUM_PARTITIONS32K
);
break
;
case
SZ_64M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info64k
,
NUM_PARTITIONS64K
);
break
;
case
SZ_128M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info128k
,
NUM_PARTITIONS128K
);
break
;
case
SZ_16M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info16k
,
NUM_PARTITIONS16K
);
break
;
case
SZ_32M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info32k
,
NUM_PARTITIONS32K
);
break
;
case
SZ_64M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info64k
,
NUM_PARTITIONS64K
);
break
;
case
SZ_128M
:
add_mtd_partitions
(
autcpu12_mtd
,
partition_info128k
,
NUM_PARTITIONS128K
);
break
;
default:
printk
(
"Unsupported SmartMedia device
\n
"
);
err
=
-
ENXIO
;
...
...
@@ -191,7 +210,7 @@ static int __init autcpu12_init(void)
goto
out
;
out_ior:
iounmap
(
(
void
*
)
autcpu12_fio_base
);
iounmap
(
autcpu12_fio_base
);
out_mtd:
kfree
(
autcpu12_mtd
);
out:
...
...
@@ -209,7 +228,7 @@ static void __exit autcpu12_cleanup(void)
nand_release
(
autcpu12_mtd
);
/* unmap physical adress */
iounmap
(
(
void
*
)
autcpu12_fio_base
);
iounmap
(
autcpu12_fio_base
);
/* Free the MTD device structure */
kfree
(
autcpu12_mtd
);
...
...
drivers/mtd/nand/cs553x_nand.c
浏览文件 @
0305c865
...
...
@@ -131,33 +131,17 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
writeb
(
byte
,
this
->
IO_ADDR_W
+
0x801
);
}
static
void
cs553x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
cs553x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
nand_chip
*
this
=
mtd
->
priv
;
void
__iomem
*
mmio_base
=
this
->
IO_ADDR_R
;
unsigned
char
ctl
;
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
ctl
=
CS_NAND_CTL_CLE
;
break
;
case
NAND_CTL_CLRCLE
:
case
NAND_CTL_CLRALE
:
case
NAND_CTL_SETNCE
:
ctl
=
0
;
break
;
case
NAND_CTL_SETALE
:
ctl
=
CS_NAND_CTL_ALE
;
break
;
default:
case
NAND_CTL_CLRNCE
:
ctl
=
CS_NAND_CTL_CE
;
break
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
char
ctl
=
(
ctrl
&
~
NAND_CTRL_CHANGE
)
^
0x01
;
writeb
(
ctl
,
mmio_base
+
MM_NAND_CTL
);
}
writeb
(
ctl
,
mmio_base
+
MM_NAND_CTL
);
if
(
cmd
!=
NAND_CMD_NONE
)
cs553x_write_byte
(
mtd
,
cmd
);
}
static
int
cs553x_device_ready
(
struct
mtd_info
*
mtd
)
...
...
@@ -233,10 +217,9 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
goto
out_mtd
;
}
this
->
hwcontro
l
=
cs553x_hwcontrol
;
this
->
cmd_ctr
l
=
cs553x_hwcontrol
;
this
->
dev_ready
=
cs553x_device_ready
;
this
->
read_byte
=
cs553x_read_byte
;
this
->
write_byte
=
cs553x_write_byte
;
this
->
read_buf
=
cs553x_read_buf
;
this
->
write_buf
=
cs553x_write_buf
;
...
...
drivers/mtd/nand/diskonchip.c
浏览文件 @
0305c865
...
...
@@ -95,7 +95,8 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
static
void
doc200x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
);
static
void
doc200x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
bitmask
);
static
void
doc200x_select_chip
(
struct
mtd_info
*
mtd
,
int
chip
);
static
int
debug
=
0
;
...
...
@@ -402,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
uint16_t
ret
;
doc200x_select_chip
(
mtd
,
nr
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_SETCLE
);
this
->
write_byte
(
mtd
,
NAND_CMD_READID
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_CLRCLE
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_SETALE
);
this
->
write_byte
(
mtd
,
0
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_CLRALE
);
doc200x_hwcontrol
(
mtd
,
NAND_CMD_READID
,
NAND_CTRL_CLE
|
NAND_CTRL_CHANGE
);
doc200x_hwcontrol
(
mtd
,
0
,
NAND_CTRL_ALE
|
NAND_CTRL_CHANGE
);
doc200x_hwcontrol
(
mtd
,
NAND_CMD_NONE
,
NAND_NCE
|
NAND_CTRL_CHANGE
);
/* We cant' use dev_ready here, but at least we wait for the
* command to complete
...
...
@@ -425,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
}
ident
;
void
__iomem
*
docptr
=
doc
->
virtadr
;
doc200x_hwcontrol
(
mtd
,
NAND_CTL_SETCLE
);
doc2000_write_byte
(
mtd
,
NAND_CMD_READID
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_CLRCLE
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_SETALE
);
doc2000_write_byte
(
mtd
,
0
);
doc200x_hwcontrol
(
mtd
,
NAND_CTL_CLRALE
);
doc200x_hwcontrol
(
mtd
,
NAND_CMD_READID
,
NAND_CTRL_CLE
|
NAND_CTRL_CHANGE
);
doc200x_hwcontrol
(
mtd
,
0
,
NAND_CTRL_ALE
|
NAND_CTRL_CHANGE
);
doc200x_hwcontrol
(
mtd
,
NAND_CMD_NONE
,
NAND_NCE
|
NAND_CTRL_CHANGE
);
udelay
(
50
);
...
...
@@ -690,54 +688,41 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
chip
-=
(
floor
*
doc
->
chips_per_floor
);
/* 11.4.4 -- deassert CE before changing chip */
doc200x_hwcontrol
(
mtd
,
NAND_C
TL_CLRNC
E
);
doc200x_hwcontrol
(
mtd
,
NAND_C
MD_NONE
,
0
|
NAND_CTRL_CHANG
E
);
WriteDOC
(
floor
,
docptr
,
FloorSelect
);
WriteDOC
(
chip
,
docptr
,
CDSNDeviceSelect
);
doc200x_hwcontrol
(
mtd
,
NAND_C
TL_SETNC
E
);
doc200x_hwcontrol
(
mtd
,
NAND_C
MD_NONE
,
NAND_NCE
|
NAND_CTRL_CHANG
E
);
doc
->
curchip
=
chip
;
doc
->
curfloor
=
floor
;
}
static
void
doc200x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
static
void
doc200x_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
nand_chip
*
this
=
mtd
->
priv
;
struct
doc_priv
*
doc
=
this
->
priv
;
void
__iomem
*
docptr
=
doc
->
virtadr
;
switch
(
cmd
)
{
case
NAND_CTL_SETNCE
:
doc
->
CDSNControl
|=
CDSN_CTRL_CE
;
break
;
case
NAND_CTL_CLRNCE
:
doc
->
CDSNControl
&=
~
CDSN_CTRL_CE
;
break
;
case
NAND_CTL_SETCLE
:
doc
->
CDSNControl
|=
CDSN_CTRL_CLE
;
break
;
case
NAND_CTL_CLRCLE
:
doc
->
CDSNControl
&=
~
CDSN_CTRL_CLE
;
break
;
case
NAND_CTL_SETALE
:
doc
->
CDSNControl
|=
CDSN_CTRL_ALE
;
break
;
case
NAND_CTL_CLRALE
:
doc
->
CDSNControl
&=
~
CDSN_CTRL_ALE
;
break
;
case
NAND_CTL_SETWP
:
doc
->
CDSNControl
|=
CDSN_CTRL_WP
;
break
;
case
NAND_CTL_CLRWP
:
doc
->
CDSNControl
&=
~
CDSN_CTRL_WP
;
break
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
doc
->
CDSNControl
&=
~
CDSN_CTRL_MSK
;
doc
->
CDSNControl
|=
ctrl
&
CDSN_CTRL_MSK
;
if
(
debug
)
printk
(
"hwcontrol(%d): %02x
\n
"
,
cmd
,
doc
->
CDSNControl
);
WriteDOC
(
doc
->
CDSNControl
,
docptr
,
CDSNControl
);
/* 11.4.3 -- 4 NOPs after CSDNControl write */
DoC_Delay
(
doc
,
4
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
{
if
(
DoC_is_2000
(
doc
))
doc2000_write_byte
(
mtd
,
cmd
);
else
doc2001_write_byte
(
mtd
,
cmd
);
}
if
(
debug
)
printk
(
"hwcontrol(%d): %02x
\n
"
,
cmd
,
doc
->
CDSNControl
);
WriteDOC
(
doc
->
CDSNControl
,
docptr
,
CDSNControl
);
/* 11.4.3 -- 4 NOPs after CSDNControl write */
DoC_Delay
(
doc
,
4
);
}
static
void
doc2001plus_command
(
struct
mtd_info
*
mtd
,
unsigned
command
,
int
column
,
int
page_addr
)
...
...
@@ -1454,7 +1439,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
struct
nand_chip
*
this
=
mtd
->
priv
;
struct
doc_priv
*
doc
=
this
->
priv
;
this
->
write_byte
=
doc2000_write_byte
;
this
->
read_byte
=
doc2000_read_byte
;
this
->
write_buf
=
doc2000_writebuf
;
this
->
read_buf
=
doc2000_readbuf
;
...
...
@@ -1472,7 +1456,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
struct
nand_chip
*
this
=
mtd
->
priv
;
struct
doc_priv
*
doc
=
this
->
priv
;
this
->
write_byte
=
doc2001_write_byte
;
this
->
read_byte
=
doc2001_read_byte
;
this
->
write_buf
=
doc2001_writebuf
;
this
->
read_buf
=
doc2001_readbuf
;
...
...
@@ -1504,16 +1487,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
struct
nand_chip
*
this
=
mtd
->
priv
;
struct
doc_priv
*
doc
=
this
->
priv
;
this
->
write_byte
=
NULL
;
this
->
read_byte
=
doc2001plus_read_byte
;
this
->
write_buf
=
doc2001plus_writebuf
;
this
->
read_buf
=
doc2001plus_readbuf
;
this
->
verify_buf
=
doc2001plus_verifybuf
;
this
->
scan_bbt
=
inftl_scan_bbt
;
this
->
hwcontro
l
=
NULL
;
this
->
cmd_ctr
l
=
NULL
;
this
->
select_chip
=
doc2001plus_select_chip
;
this
->
cmdfunc
=
doc2001plus_command
;
this
->
e
nable_hwecc
=
doc2001plus_enable_hwecc
;
this
->
e
cc
.
hwctl
=
doc2001plus_enable_hwecc
;
doc
->
chips_per_floor
=
1
;
mtd
->
name
=
"DiskOnChip Millennium Plus"
;
...
...
@@ -1670,7 +1652,7 @@ static int __init doc_probe(unsigned long physadr)
nand
->
priv
=
doc
;
nand
->
select_chip
=
doc200x_select_chip
;
nand
->
hwcontro
l
=
doc200x_hwcontrol
;
nand
->
cmd_ctr
l
=
doc200x_hwcontrol
;
nand
->
dev_ready
=
doc200x_dev_ready
;
nand
->
waitfunc
=
doc200x_wait
;
nand
->
block_bad
=
doc200x_block_bad
;
...
...
drivers/mtd/nand/edb7312.c
浏览文件 @
0305c865
...
...
@@ -73,32 +73,26 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*
* NAND_NCE: bit 0 -> bit 7
* NAND_CLE: bit 1 -> bit 4
* NAND_ALE: bit 2 -> bit 5
*/
static
void
ep7312_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
ep7312_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
clps_writeb
(
clps_readb
(
ep7312_pxdr
)
|
0x10
,
ep7312_pxdr
);
break
;
case
NAND_CTL_CLRCLE
:
clps_writeb
(
clps_readb
(
ep7312_pxdr
)
&
~
0x10
,
ep7312_pxdr
);
break
;
case
NAND_CTL_SETALE
:
clps_writeb
(
clps_readb
(
ep7312_pxdr
)
|
0x20
,
ep7312_pxdr
);
break
;
case
NAND_CTL_CLRALE
:
clps_writeb
(
clps_readb
(
ep7312_pxdr
)
&
~
0x20
,
ep7312_pxdr
);
break
;
case
NAND_CTL_SETNCE
:
clps_writeb
((
clps_readb
(
ep7312_pxdr
)
|
0x80
)
&
~
0x40
,
ep7312_pxdr
);
break
;
case
NAND_CTL_CLRNCE
:
clps_writeb
((
clps_readb
(
ep7312_pxdr
)
|
0x80
)
|
0x40
,
ep7312_pxdr
);
break
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
char
bits
;
bits
=
(
ctrl
&
(
NAND_CLE
|
NAND_ALE
))
<<
3
;
bits
=
(
ctrl
&
NAND_NCE
)
<<
7
;
clps_writeb
((
clps_readb
(
ep7312_pxdr
)
&
0xB0
)
|
0x10
,
ep7312_pxdr
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
/*
...
...
@@ -159,7 +153,7 @@ static int __init ep7312_init(void)
/* insert callbacks */
this
->
IO_ADDR_R
=
ep7312_fio_base
;
this
->
IO_ADDR_W
=
ep7312_fio_base
;
this
->
hwcontro
l
=
ep7312_hwcontrol
;
this
->
cmd_ctr
l
=
ep7312_hwcontrol
;
this
->
dev_ready
=
ep7312_device_ready
;
/* 15 us command delay time */
this
->
chip_delay
=
15
;
...
...
drivers/mtd/nand/h1910.c
浏览文件 @
0305c865
...
...
@@ -56,36 +56,18 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*
* NAND_NCE: bit 0 - don't care
* NAND_CLE: bit 1 - address bit 2
* NAND_ALE: bit 2 - address bit 3
*/
static
void
h1910_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
h1910_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
nand_chip
*
this
=
(
struct
nand_chip
*
)(
mtd
->
priv
);
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
this
->
IO_ADDR_R
|=
(
1
<<
2
);
this
->
IO_ADDR_W
|=
(
1
<<
2
);
break
;
case
NAND_CTL_CLRCLE
:
this
->
IO_ADDR_R
&=
~
(
1
<<
2
);
this
->
IO_ADDR_W
&=
~
(
1
<<
2
);
break
;
case
NAND_CTL_SETALE
:
this
->
IO_ADDR_R
|=
(
1
<<
3
);
this
->
IO_ADDR_W
|=
(
1
<<
3
);
break
;
case
NAND_CTL_CLRALE
:
this
->
IO_ADDR_R
&=
~
(
1
<<
3
);
this
->
IO_ADDR_W
&=
~
(
1
<<
3
);
break
;
case
NAND_CTL_SETNCE
:
break
;
case
NAND_CTL_CLRNCE
:
break
;
}
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
|
((
ctrl
&
0x6
)
<<
1
));
}
/*
...
...
@@ -145,7 +127,7 @@ static int __init h1910_init(void)
/* insert callbacks */
this
->
IO_ADDR_R
=
nandaddr
;
this
->
IO_ADDR_W
=
nandaddr
;
this
->
hwcontro
l
=
h1910_hwcontrol
;
this
->
cmd_ctr
l
=
h1910_hwcontrol
;
this
->
dev_ready
=
NULL
;
/* unknown whether that was correct or not so we will just do it like this */
/* 15 us command delay time */
this
->
chip_delay
=
50
;
...
...
drivers/mtd/nand/nand_base.c
浏览文件 @
0305c865
此差异已折叠。
点击以展开。
drivers/mtd/nand/nand_bbt.c
浏览文件 @
0305c865
...
...
@@ -156,7 +156,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
while
(
totlen
)
{
len
=
min
(
totlen
,
(
size_t
)
(
1
<<
this
->
bbt_erase_shift
));
res
=
mtd
->
read
_ecc
(
mtd
,
from
,
len
,
&
retlen
,
buf
,
NULL
,
this
->
autooob
);
res
=
mtd
->
read
(
mtd
,
from
,
len
,
&
retlen
,
buf
);
if
(
res
<
0
)
{
if
(
retlen
!=
len
)
{
printk
(
KERN_INFO
"nand_bbt: Error reading bad block table
\n
"
);
...
...
@@ -471,17 +471,17 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
*
*/
static
int
write_bbt
(
struct
mtd_info
*
mtd
,
uint8_t
*
buf
,
struct
nand_bbt_descr
*
td
,
struct
nand_bbt_descr
*
md
,
int
chipsel
)
struct
nand_bbt_descr
*
td
,
struct
nand_bbt_descr
*
md
,
int
chipsel
)
{
struct
nand_chip
*
this
=
mtd
->
priv
;
struct
nand_oobinfo
oobinfo
;
struct
erase_info
einfo
;
int
i
,
j
,
res
,
chip
=
0
;
int
bits
,
startblock
,
dir
,
page
,
offs
,
numblocks
,
sft
,
sftmsk
;
int
nrchips
,
bbtoffs
,
pageoffs
;
int
nrchips
,
bbtoffs
,
pageoffs
,
ooboffs
;
uint8_t
msk
[
4
];
uint8_t
rcode
=
td
->
reserved_block_code
;
size_t
retlen
,
len
=
0
;
size_t
retlen
,
len
=
0
,
ooblen
;
loff_t
to
;
if
(
!
rcode
)
...
...
@@ -526,12 +526,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for
(
i
=
0
;
i
<
td
->
maxblocks
;
i
++
)
{
int
block
=
startblock
+
dir
*
i
;
/* Check, if the block is bad */
switch
((
this
->
bbt
[
block
>>
2
]
>>
(
2
*
(
block
&
0x03
)))
&
0x03
)
{
switch
((
this
->
bbt
[
block
>>
2
]
>>
(
2
*
(
block
&
0x03
)))
&
0x03
)
{
case
0x01
:
case
0x03
:
continue
;
}
page
=
block
<<
(
this
->
bbt_erase_shift
-
this
->
page_shift
);
page
=
block
<<
(
this
->
bbt_erase_shift
-
this
->
page_shift
);
/* Check, if the block is used by the mirror table */
if
(
!
md
||
md
->
pages
[
chip
]
!=
page
)
goto
write
;
...
...
@@ -542,11 +544,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
/* Set up shift count and masks for the flash table */
bits
=
td
->
options
&
NAND_BBT_NRBITS_MSK
;
msk
[
2
]
=
~
rcode
;
switch
(
bits
)
{
case
1
:
sft
=
3
;
sftmsk
=
0x07
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x01
;
msk
[
2
]
=
~
rcode
;
msk
[
3
]
=
0x01
;
break
;
case
2
:
sft
=
2
;
sftmsk
=
0x06
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x01
;
msk
[
2
]
=
~
rcode
;
msk
[
3
]
=
0x03
;
break
;
case
4
:
sft
=
1
;
sftmsk
=
0x04
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x0C
;
msk
[
2
]
=
~
rcode
;
msk
[
3
]
=
0x0f
;
break
;
case
8
:
sft
=
0
;
sftmsk
=
0x00
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x0F
;
msk
[
2
]
=
~
rcode
;
msk
[
3
]
=
0xff
;
break
;
case
1
:
sft
=
3
;
sftmsk
=
0x07
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x01
;
msk
[
3
]
=
0x01
;
break
;
case
2
:
sft
=
2
;
sftmsk
=
0x06
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x01
;
msk
[
3
]
=
0x03
;
break
;
case
4
:
sft
=
1
;
sftmsk
=
0x04
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x0C
;
msk
[
3
]
=
0x0f
;
break
;
case
8
:
sft
=
0
;
sftmsk
=
0x00
;
msk
[
0
]
=
0x00
;
msk
[
1
]
=
0x0F
;
msk
[
3
]
=
0xff
;
break
;
default:
return
-
EINVAL
;
}
...
...
@@ -554,49 +565,55 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
to
=
((
loff_t
)
page
)
<<
this
->
page_shift
;
memcpy
(
&
oobinfo
,
this
->
autooob
,
sizeof
(
oobinfo
));
oobinfo
.
useecc
=
MTD_NANDECC_PLACEONLY
;
/* Must we save the block contents ? */
if
(
td
->
options
&
NAND_BBT_SAVECONTENT
)
{
/* Make it block aligned */
to
&=
~
((
loff_t
)
((
1
<<
this
->
bbt_erase_shift
)
-
1
));
len
=
1
<<
this
->
bbt_erase_shift
;
res
=
mtd
->
read
_ecc
(
mtd
,
to
,
len
,
&
retlen
,
buf
,
&
buf
[
len
],
&
oobinfo
);
res
=
mtd
->
read
(
mtd
,
to
,
len
,
&
retlen
,
buf
);
if
(
res
<
0
)
{
if
(
retlen
!=
len
)
{
printk
(
KERN_INFO
"nand_bbt: Error reading block for writing the bad block table
\n
"
);
printk
(
KERN_INFO
"nand_bbt: Error "
"reading block for writing "
"the bad block table
\n
"
);
return
res
;
}
printk
(
KERN_WARNING
"nand_bbt: ECC error while reading block for writing bad block table
\n
"
);
printk
(
KERN_WARNING
"nand_bbt: ECC error "
"while reading block for writing "
"bad block table
\n
"
);
}
/* Read oob data */
ooblen
=
(
len
>>
this
->
page_shift
)
*
mtd
->
oobsize
;
res
=
mtd
->
read_oob
(
mtd
,
to
+
mtd
->
writesize
,
ooblen
,
&
retlen
,
&
buf
[
len
]);
if
(
res
<
0
||
retlen
!=
ooblen
)
goto
outerr
;
/* Calc the byte offset in the buffer */
pageoffs
=
page
-
(
int
)(
to
>>
this
->
page_shift
);
offs
=
pageoffs
<<
this
->
page_shift
;
/* Preset the bbt area with 0xff */
memset
(
&
buf
[
offs
],
0xff
,
(
size_t
)
(
numblocks
>>
sft
));
/* Preset the bbt's oob area with 0xff */
memset
(
&
buf
[
len
+
pageoffs
*
mtd
->
oobsize
],
0xff
,
((
len
>>
this
->
page_shift
)
-
pageoffs
)
*
mtd
->
oobsize
);
if
(
td
->
options
&
NAND_BBT_VERSION
)
{
buf
[
len
+
(
pageoffs
*
mtd
->
oobsize
)
+
td
->
veroffs
]
=
td
->
version
[
chip
];
}
ooboffs
=
len
+
(
pageoffs
*
mtd
->
oobsize
);
}
else
{
/* Calc length */
len
=
(
size_t
)
(
numblocks
>>
sft
);
/* Make it page aligned ! */
len
=
(
len
+
(
mtd
->
writesize
-
1
))
&
~
(
mtd
->
writesize
-
1
);
len
=
(
len
+
(
mtd
->
writesize
-
1
))
&
~
(
mtd
->
writesize
-
1
);
/* Preset the buffer with 0xff */
memset
(
buf
,
0xff
,
len
+
(
len
>>
this
->
page_shift
)
*
mtd
->
oobsize
);
memset
(
buf
,
0xff
,
len
+
(
len
>>
this
->
page_shift
)
*
mtd
->
oobsize
);
offs
=
0
;
ooboffs
=
len
;
/* Pattern is located in oob area of first page */
memcpy
(
&
buf
[
len
+
td
->
offs
],
td
->
pattern
,
td
->
len
);
if
(
td
->
options
&
NAND_BBT_VERSION
)
{
buf
[
len
+
td
->
veroffs
]
=
td
->
version
[
chip
];
}
memcpy
(
&
buf
[
ooboffs
+
td
->
offs
],
td
->
pattern
,
td
->
len
);
}
if
(
td
->
options
&
NAND_BBT_VERSION
)
buf
[
ooboffs
+
td
->
veroffs
]
=
td
->
version
[
chip
];
/* walk through the memory table */
for
(
i
=
0
;
i
<
numblocks
;)
{
uint8_t
dat
;
...
...
@@ -604,7 +621,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for
(
j
=
0
;
j
<
4
;
j
++
,
i
++
)
{
int
sftcnt
=
(
i
<<
(
3
-
sft
))
&
sftmsk
;
/* Do not store the reserved bbt blocks ! */
buf
[
offs
+
(
i
>>
sft
)]
&=
~
(
msk
[
dat
&
0x03
]
<<
sftcnt
);
buf
[
offs
+
(
i
>>
sft
)]
&=
~
(
msk
[
dat
&
0x03
]
<<
sftcnt
);
dat
>>=
2
;
}
}
...
...
@@ -614,23 +632,25 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
einfo
.
addr
=
(
unsigned
long
)
to
;
einfo
.
len
=
1
<<
this
->
bbt_erase_shift
;
res
=
nand_erase_nand
(
mtd
,
&
einfo
,
1
);
if
(
res
<
0
)
{
printk
(
KERN_WARNING
"nand_bbt: Error during block erase: %d
\n
"
,
res
);
return
res
;
}
if
(
res
<
0
)
goto
outerr
;
res
=
mtd
->
write_ecc
(
mtd
,
to
,
len
,
&
retlen
,
buf
,
&
buf
[
len
],
&
oobinfo
);
if
(
res
<
0
)
{
printk
(
KERN_WARNING
"nand_bbt: Error while writing bad block table %d
\n
"
,
res
);
return
res
;
}
printk
(
KERN_DEBUG
"Bad block table written to 0x%08x, version 0x%02X
\n
"
,
(
unsigned
int
)
to
,
td
->
version
[
chip
]);
res
=
nand_write_raw
(
mtd
,
to
,
len
,
&
retlen
,
buf
,
&
buf
[
len
]);
if
(
res
<
0
)
goto
outerr
;
printk
(
KERN_DEBUG
"Bad block table written to 0x%08x, version "
"0x%02X
\n
"
,
(
unsigned
int
)
to
,
td
->
version
[
chip
]);
/* Mark it as used */
td
->
pages
[
chip
]
=
page
;
}
return
0
;
outerr:
printk
(
KERN_WARNING
"nand_bbt: Error while writing bad block table %d
\n
"
,
res
);
return
res
;
}
/**
...
...
drivers/mtd/nand/nandsim.c
浏览文件 @
0305c865
...
...
@@ -1071,68 +1071,6 @@ switch_state(struct nandsim *ns)
}
}
static
void
ns_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
{
struct
nandsim
*
ns
=
(
struct
nandsim
*
)((
struct
nand_chip
*
)
mtd
->
priv
)
->
priv
;
switch
(
cmd
)
{
/* set CLE line high */
case
NAND_CTL_SETCLE
:
NS_DBG
(
"ns_hwcontrol: start command latch cycles
\n
"
);
ns
->
lines
.
cle
=
1
;
break
;
/* set CLE line low */
case
NAND_CTL_CLRCLE
:
NS_DBG
(
"ns_hwcontrol: stop command latch cycles
\n
"
);
ns
->
lines
.
cle
=
0
;
break
;
/* set ALE line high */
case
NAND_CTL_SETALE
:
NS_DBG
(
"ns_hwcontrol: start address latch cycles
\n
"
);
ns
->
lines
.
ale
=
1
;
break
;
/* set ALE line low */
case
NAND_CTL_CLRALE
:
NS_DBG
(
"ns_hwcontrol: stop address latch cycles
\n
"
);
ns
->
lines
.
ale
=
0
;
break
;
/* set WP line high */
case
NAND_CTL_SETWP
:
NS_DBG
(
"ns_hwcontrol: enable write protection
\n
"
);
ns
->
lines
.
wp
=
1
;
break
;
/* set WP line low */
case
NAND_CTL_CLRWP
:
NS_DBG
(
"ns_hwcontrol: disable write protection
\n
"
);
ns
->
lines
.
wp
=
0
;
break
;
/* set CE line low */
case
NAND_CTL_SETNCE
:
NS_DBG
(
"ns_hwcontrol: enable chip
\n
"
);
ns
->
lines
.
ce
=
1
;
break
;
/* set CE line high */
case
NAND_CTL_CLRNCE
:
NS_DBG
(
"ns_hwcontrol: disable chip
\n
"
);
ns
->
lines
.
ce
=
0
;
break
;
default:
NS_ERR
(
"hwcontrol: unknown command
\n
"
);
}
return
;
}
static
u_char
ns_nand_read_byte
(
struct
mtd_info
*
mtd
)
{
...
...
@@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
return
;
}
static
void
ns_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
bitmask
)
{
struct
nandsim
*
ns
=
((
struct
nand_chip
*
)
mtd
->
priv
)
->
priv
;
ns
->
lines
.
cle
=
bitmask
&
NAND_CLE
?
1
:
0
;
ns
->
lines
.
ale
=
bitmask
&
NAND_ALE
?
1
:
0
;
ns
->
lines
.
ce
=
bitmask
&
NAND_NCE
?
1
:
0
;
if
(
cmd
!=
NAND_CMD_NONE
)
ns_nand_write_byte
(
mtd
,
cmd
);
}
static
int
ns_device_ready
(
struct
mtd_info
*
mtd
)
{
...
...
@@ -1376,17 +1326,6 @@ ns_nand_read_word(struct mtd_info *mtd)
return
chip
->
read_byte
(
mtd
)
|
(
chip
->
read_byte
(
mtd
)
<<
8
);
}
static
void
ns_nand_write_word
(
struct
mtd_info
*
mtd
,
uint16_t
word
)
{
struct
nand_chip
*
chip
=
(
struct
nand_chip
*
)
mtd
->
priv
;
NS_DBG
(
"write_word
\n
"
);
chip
->
write_byte
(
mtd
,
word
&
0xFF
);
chip
->
write_byte
(
mtd
,
word
>>
8
);
}
static
void
ns_nand_write_buf
(
struct
mtd_info
*
mtd
,
const
u_char
*
buf
,
int
len
)
{
...
...
@@ -1514,14 +1453,12 @@ static int __init ns_init_module(void)
/*
* Register simulator's callbacks.
*/
chip
->
hwcontrol
=
ns_hwcontrol
;
chip
->
cmd_ctrl
=
ns_hwcontrol
;
chip
->
read_byte
=
ns_nand_read_byte
;
chip
->
dev_ready
=
ns_device_ready
;
chip
->
write_byte
=
ns_nand_write_byte
;
chip
->
write_buf
=
ns_nand_write_buf
;
chip
->
read_buf
=
ns_nand_read_buf
;
chip
->
verify_buf
=
ns_nand_verify_buf
;
chip
->
write_word
=
ns_nand_write_word
;
chip
->
read_word
=
ns_nand_read_word
;
chip
->
ecc
.
mode
=
NAND_ECC_SOFT
;
chip
->
options
|=
NAND_SKIP_BBTSCAN
;
...
...
drivers/mtd/nand/ndfc.c
浏览文件 @
0305c865
...
...
@@ -60,22 +60,17 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
writel
(
ccr
,
ndfc
->
ndfcbase
+
NDFC_CCR
);
}
static
void
ndfc_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
ndfc_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
ndfc_controller
*
ndfc
=
&
ndfc_ctrl
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
chip
->
IO_ADDR_W
=
ndfc
->
ndfcbase
+
NDFC_CMD
;
break
;
case
NAND_CTL_SETALE
:
chip
->
IO_ADDR_W
=
ndfc
->
ndfcbase
+
NDFC_ALE
;
break
;
default:
chip
->
IO_ADDR_W
=
ndfc
->
ndfcbase
+
NDFC_DATA
;
break
;
}
if
(
cmd
==
NAND_CMD_NONE
)
return
;
if
(
ctrl
&
NAND_CLE
)
writel
(
cmd
&
0xFF
,
chip
->
IO_ADDR_W
+
NDFC_CMD
);
else
writel
(
cmd
&
0xFF
,
chip
->
IO_ADDR_W
+
NDFC_ALE
);
}
static
int
ndfc_ready
(
struct
mtd_info
*
mtd
)
...
...
@@ -158,7 +153,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip
->
IO_ADDR_R
=
ndfc
->
ndfcbase
+
NDFC_DATA
;
chip
->
IO_ADDR_W
=
ndfc
->
ndfcbase
+
NDFC_DATA
;
chip
->
hwcontro
l
=
ndfc_hwcontrol
;
chip
->
cmd_ctr
l
=
ndfc_hwcontrol
;
chip
->
dev_ready
=
ndfc_ready
;
chip
->
select_chip
=
ndfc_select_chip
;
chip
->
chip_delay
=
50
;
...
...
drivers/mtd/nand/ppchameleonevb.c
浏览文件 @
0305c865
...
...
@@ -108,54 +108,68 @@ extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio
/*
* hardware specific access to control-lines
*/
static
void
ppchameleon_hwcontrol
(
struct
mtd_info
*
mtdinfo
,
int
cmd
)
static
void
ppchameleon_hwcontrol
(
struct
mtd_info
*
mtdinfo
,
int
cmd
,
unsigned
int
ctrl
)
{
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
MACRO_NAND_CTL_SETCLE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRCLE
:
MACRO_NAND_CTL_CLRCLE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_SETALE
:
MACRO_NAND_CTL_SETALE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRALE
:
MACRO_NAND_CTL_CLRALE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_SETNCE
:
MACRO_NAND_ENABLE_CE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRNCE
:
MACRO_NAND_DISABLE_CE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
#error Missing headerfiles. No way to fix this. -tglx
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
MACRO_NAND_CTL_SETCLE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRCLE
:
MACRO_NAND_CTL_CLRCLE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_SETALE
:
MACRO_NAND_CTL_SETALE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRALE
:
MACRO_NAND_CTL_CLRALE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_SETNCE
:
MACRO_NAND_ENABLE_CE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
case
NAND_CTL_CLRNCE
:
MACRO_NAND_DISABLE_CE
((
unsigned
long
)
CFG_NAND0_PADDR
);
break
;
}
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
static
void
ppchameleonevb_hwcontrol
(
struct
mtd_info
*
mtdinfo
,
int
cmd
)
static
void
ppchameleonevb_hwcontrol
(
struct
mtd_info
*
mtdinfo
,
int
cmd
,
unsigned
int
ctrl
)
{
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
MACRO_NAND_CTL_SETCLE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRCLE
:
MACRO_NAND_CTL_CLRCLE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_SETALE
:
MACRO_NAND_CTL_SETALE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRALE
:
MACRO_NAND_CTL_CLRALE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_SETNCE
:
MACRO_NAND_ENABLE_CE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRNCE
:
MACRO_NAND_DISABLE_CE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
#error Missing headerfiles. No way to fix this. -tglx
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
MACRO_NAND_CTL_SETCLE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRCLE
:
MACRO_NAND_CTL_CLRCLE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_SETALE
:
MACRO_NAND_CTL_SETALE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRALE
:
MACRO_NAND_CTL_CLRALE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_SETNCE
:
MACRO_NAND_ENABLE_CE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
case
NAND_CTL_CLRNCE
:
MACRO_NAND_DISABLE_CE
((
unsigned
long
)
CFG_NAND1_PADDR
);
break
;
}
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
#ifdef USE_READY_BUSY_PIN
...
...
@@ -251,7 +265,7 @@ static int __init ppchameleonevb_init(void)
/* insert callbacks */
this
->
IO_ADDR_R
=
ppchameleon_fio_base
;
this
->
IO_ADDR_W
=
ppchameleon_fio_base
;
this
->
hwcontro
l
=
ppchameleon_hwcontrol
;
this
->
cmd_ctr
l
=
ppchameleon_hwcontrol
;
#ifdef USE_READY_BUSY_PIN
this
->
dev_ready
=
ppchameleon_device_ready
;
#endif
...
...
@@ -351,7 +365,7 @@ static int __init ppchameleonevb_init(void)
/* insert callbacks */
this
->
IO_ADDR_R
=
ppchameleonevb_fio_base
;
this
->
IO_ADDR_W
=
ppchameleonevb_fio_base
;
this
->
hwcontro
l
=
ppchameleonevb_hwcontrol
;
this
->
cmd_ctr
l
=
ppchameleonevb_hwcontrol
;
#ifdef USE_READY_BUSY_PIN
this
->
dev_ready
=
ppchameleonevb_device_ready
;
#endif
...
...
drivers/mtd/nand/rtc_from4.c
浏览文件 @
0305c865
...
...
@@ -208,32 +208,18 @@ static uint8_t revbits[256] = {
* Address lines (A24-A22), so no action is required here.
*
*/
static
void
rtc_from4_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
rtc_from4_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
nand_chip
*
this
=
(
struct
nand_chip
*
)
(
mtd
->
priv
);
struct
nand_chip
*
chip
=
(
mtd
->
priv
);
switch
(
cmd
)
{
if
(
cmd
==
NAND_CMD_NONE
)
return
;
case
NAND_CTL_SETCLE
:
this
->
IO_ADDR_W
=
(
void
__iomem
*
)((
unsigned
long
)
this
->
IO_ADDR_W
|
RTC_FROM4_CLE
);
break
;
case
NAND_CTL_CLRCLE
:
this
->
IO_ADDR_W
=
(
void
__iomem
*
)((
unsigned
long
)
this
->
IO_ADDR_W
&
~
RTC_FROM4_CLE
);
break
;
case
NAND_CTL_SETALE
:
this
->
IO_ADDR_W
=
(
void
__iomem
*
)((
unsigned
long
)
this
->
IO_ADDR_W
|
RTC_FROM4_ALE
);
break
;
case
NAND_CTL_CLRALE
:
this
->
IO_ADDR_W
=
(
void
__iomem
*
)((
unsigned
long
)
this
->
IO_ADDR_W
&
~
RTC_FROM4_ALE
);
break
;
case
NAND_CTL_SETNCE
:
break
;
case
NAND_CTL_CLRNCE
:
break
;
}
if
(
ctrl
&
NAND_CLE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
|
RTC_FROM4_CLE
);
else
writeb
(
cmd
,
chip
->
IO_ADDR_W
|
RTC_FROM4_ALE
);
}
/*
...
...
@@ -559,7 +545,7 @@ static int __init rtc_from4_init(void)
this
->
IO_ADDR_R
=
rtc_from4_fio_base
;
this
->
IO_ADDR_W
=
rtc_from4_fio_base
;
/* Set address of hardware control function */
this
->
hwcontro
l
=
rtc_from4_hwcontrol
;
this
->
cmd_ctr
l
=
rtc_from4_hwcontrol
;
/* Set address of chip select function */
this
->
select_chip
=
rtc_from4_nand_select_chip
;
/* command delay time (in us) */
...
...
drivers/mtd/nand/s3c2410.c
浏览文件 @
0305c865
...
...
@@ -256,60 +256,36 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
*
*/
static
void
s3c2410_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
s3c2410_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigend
int
ctrl
)
{
struct
s3c2410_nand_info
*
info
=
s3c2410_nand_mtd_toinfo
(
mtd
);
struct
nand_chip
*
chip
=
mtd
->
priv
;
switch
(
cmd
)
{
case
NAND_CTL_SETNCE
:
case
NAND_CTL_CLRNCE
:
printk
(
KERN_ERR
"%s: called for NCE
\n
"
,
__FUNCTION__
);
break
;
case
NAND_CTL_SETCLE
:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2410_NFCMD
;
break
;
case
NAND_CTL_SETALE
:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2410_NFADDR
;
break
;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2410_NFDATA
;
break
;
}
if
(
cmd
==
NAND_CMD_NONE
)
return
;
if
(
cmd
&
NAND_CLE
)
writeb
(
cmd
,
info
->
regs
+
S3C2410_NFCMD
);
else
writeb
(
cmd
,
info
->
regs
+
S3C2410_NFADDR
);
}
/* command and control functions */
static
void
s3c2440_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
s3c2410_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigend
int
ctrl
)
{
struct
s3c2410_nand_info
*
info
=
s3c2410_nand_mtd_toinfo
(
mtd
);
struct
nand_chip
*
chip
=
mtd
->
priv
;
switch
(
cmd
)
{
case
NAND_CTL_SETNCE
:
case
NAND_CTL_CLRNCE
:
printk
(
KERN_ERR
"%s: called for NCE
\n
"
,
__FUNCTION__
);
break
;
case
NAND_CTL_SETCLE
:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2440_NFCMD
;
break
;
case
NAND_CTL_SETALE
:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2440_NFADDR
;
break
;
/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2440_NFDATA
;
break
;
}
if
(
cmd
==
NAND_CMD_NONE
)
return
;
if
(
cmd
&
NAND_CLE
)
writeb
(
cmd
,
info
->
regs
+
S3C2440_NFCMD
);
else
writeb
(
cmd
,
info
->
regs
+
S3C2440_NFADDR
);
}
/* s3c2410_nand_devready()
...
...
@@ -498,7 +474,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip
->
IO_ADDR_R
=
info
->
regs
+
S3C2410_NFDATA
;
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2410_NFDATA
;
chip
->
hwcontrol
=
s3c2410_nand_hwcontrol
;
chip
->
cmd_ctrl
=
s3c2410_nand_hwcontrol
;
chip
->
dev_ready
=
s3c2410_nand_devready
;
chip
->
write_buf
=
s3c2410_nand_write_buf
;
chip
->
read_buf
=
s3c2410_nand_read_buf
;
...
...
@@ -511,7 +487,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
if
(
info
->
is_s3c2440
)
{
chip
->
IO_ADDR_R
=
info
->
regs
+
S3C2440_NFDATA
;
chip
->
IO_ADDR_W
=
info
->
regs
+
S3C2440_NFDATA
;
chip
->
hwcontrol
=
s3c2440_nand_hwcontrol
;
chip
->
cmd_ctrl
=
s3c2440_nand_hwcontrol
;
}
nmtd
->
info
=
info
;
...
...
drivers/mtd/nand/sharpsl.c
浏览文件 @
0305c865
...
...
@@ -77,31 +77,26 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = {
/*
* hardware specific access to control-lines
* ctrl:
* NAND_CNE: bit 0 -> bit 0 & 4
* NAND_CLE: bit 1 -> bit 1
* NAND_ALE: bit 2 -> bit 2
*
*/
static
void
sharpsl_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
sharpsl_nand_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
writeb
(
readb
(
FLASHCTL
)
|
FLCLE
,
FLASHCTL
);
break
;
case
NAND_CTL_CLRCLE
:
writeb
(
readb
(
FLASHCTL
)
&
~
FLCLE
,
FLASHCTL
);
break
;
case
NAND_CTL_SETALE
:
writeb
(
readb
(
FLASHCTL
)
|
FLALE
,
FLASHCTL
);
break
;
case
NAND_CTL_CLRALE
:
writeb
(
readb
(
FLASHCTL
)
&
~
FLALE
,
FLASHCTL
);
break
;
case
NAND_CTL_SETNCE
:
writeb
(
readb
(
FLASHCTL
)
&
~
(
FLCE0
|
FLCE1
),
FLASHCTL
);
break
;
case
NAND_CTL_CLRNCE
:
writeb
(
readb
(
FLASHCTL
)
|
(
FLCE0
|
FLCE1
),
FLASHCTL
);
break
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
char
bits
=
ctrl
&
0x07
;
bits
|=
(
ctrl
&
0x01
)
<<
4
;
writeb
((
readb
(
FLASHCTL
)
&
0x17
)
|
bits
,
FLASHCTL
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
static
uint8_t
scan_ff_pattern
[]
=
{
0xff
,
0xff
};
...
...
@@ -196,7 +191,7 @@ static int __init sharpsl_nand_init(void)
this
->
IO_ADDR_R
=
FLASHIO
;
this
->
IO_ADDR_W
=
FLASHIO
;
/* Set address of hardware control function */
this
->
hwcontro
l
=
sharpsl_nand_hwcontrol
;
this
->
cmd_ctr
l
=
sharpsl_nand_hwcontrol
;
this
->
dev_ready
=
sharpsl_nand_dev_ready
;
/* 15 us command delay time */
this
->
chip_delay
=
15
;
...
...
drivers/mtd/nand/spia.c
浏览文件 @
0305c865
...
...
@@ -82,20 +82,27 @@ static const struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*/
*
* ctrl:
* NAND_CNE: bit 0 -> bit 2
* NAND_CLE: bit 1 -> bit 0
* NAND_ALE: bit 2 -> bit 1
*/
static
void
spia_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
{
s
witch
(
cmd
)
{
s
truct
nand_chip
*
chip
=
mtd
->
priv
;
case
NAND_CTL_SETCLE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
|=
0x01
;
break
;
case
NAND_CTL_CLRCLE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
&=
~
0x01
;
break
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
void
__iomem
*
addr
=
spia_io_base
+
spia_pedr
;
unsigned
char
bits
;
case
NAND_CTL_SETALE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
|=
0x02
;
break
;
case
NAND_CTL_CLRALE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
&=
~
0x02
;
break
;
case
NAND_CTL_SETNCE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
&=
~
0x04
;
break
;
case
NAND_CTL_CLRNCE
:
(
*
(
volatile
unsigned
char
*
)
(
spia_io_base
+
spia_pedr
))
|=
0x04
;
break
;
bits
=
(
ctrl
&
NAND_CNE
)
<<
2
;
bits
|=
(
ctrl
&
NAND_CLE
|
NAND_ALE
)
>>
1
;
writeb
((
readb
(
addr
)
&
~
0x7
)
|
bits
,
addr
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
/*
...
...
@@ -133,7 +140,7 @@ static int __init spia_init(void)
this
->
IO_ADDR_R
=
(
void
__iomem
*
)
spia_fio_base
;
this
->
IO_ADDR_W
=
(
void
__iomem
*
)
spia_fio_base
;
/* Set address of hardware control function */
this
->
hwcontro
l
=
spia_hwcontrol
;
this
->
cmd_ctr
l
=
spia_hwcontrol
;
/* 15 us command delay time */
this
->
chip_delay
=
15
;
...
...
drivers/mtd/nand/toto.c
浏览文件 @
0305c865
...
...
@@ -32,6 +32,8 @@
#include <asm/arch-omap1510/hardware.h>
#include <asm/arch/gpio.h>
#define CONFIG_NAND_WORKAROUND 1
/*
* MTD structure for TOTO board
*/
...
...
@@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL;
static
unsigned
long
toto_io_base
=
OMAP_FLASH_1_BASE
;
#define CONFIG_NAND_WORKAROUND 1
#define NAND_NCE 0x4000
#define NAND_CLE 0x1000
#define NAND_ALE 0x0002
#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
#ifdef CONFIG_NAND_WORKAROUND
/* "some" dev boards busted, blue wired to rts2 :( */
#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
#else
#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0)
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE)
#endif
#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0)
#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE)
/*
* Define partitions for flash devices
*/
...
...
@@ -91,25 +74,43 @@ static struct mtd_partition partition_info32M[] = {
#define NUM_PARTITIONS32M 3
#define NUM_PARTITIONS64M 4
/*
* hardware specific access to control-lines
*/
static
void
toto_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
*
* ctrl:
* NAND_NCE: bit 0 -> bit 14 (0x4000)
* NAND_CLE: bit 1 -> bit 12 (0x1000)
* NAND_ALE: bit 2 -> bit 1 (0x0002)
*/
static
void
toto_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
long
bits
;
udelay
(
1
);
/* hopefully enough time for tc make proceding write to clear */
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
T_NAND_CTL_SETCLE
(
cmd
);
break
;
case
NAND_CTL_CLRCLE
:
T_NAND_CTL_CLRCLE
(
cmd
);
break
;
/* hopefully enough time for tc make proceding write to clear */
udelay
(
1
);
case
NAND_CTL_SETALE
:
T_NAND_CTL_SETALE
(
cmd
);
break
;
case
NAND_CTL_CLRALE
:
T_NAND_CTL_CLRALE
(
cmd
);
break
;
bits
=
(
~
ctrl
&
NAND_NCE
)
<<
14
;
bits
|=
(
ctrl
&
NAND_CLE
)
<<
12
;
bits
|=
(
ctrl
&
NAND_ALE
)
>>
1
;
case
NAND_CTL_SETNCE
:
T_NAND_CTL_SETNCE
(
cmd
);
break
;
case
NAND_CTL_CLRNCE
:
T_NAND_CTL_CLRNCE
(
cmd
);
break
;
#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
gpiosetout
(
0x5002
,
bits
);
#ifdef CONFIG_NAND_WORKAROUND
/* "some" dev boards busted, blue wired to rts2 :( */
rts2setout
(
2
,
(
ctrl
&
NAND_CLE
)
<<
1
);
#endif
/* allow time to ensure gpio state to over take memory write */
udelay
(
1
);
}
udelay
(
1
);
/* allow time to ensure gpio state to over take memory write */
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
/*
...
...
@@ -142,7 +143,7 @@ static int __init toto_init(void)
/* Set address of NAND IO lines */
this
->
IO_ADDR_R
=
toto_io_base
;
this
->
IO_ADDR_W
=
toto_io_base
;
this
->
hwcontro
l
=
toto_hwcontrol
;
this
->
cmd_ctr
l
=
toto_hwcontrol
;
this
->
dev_ready
=
NULL
;
/* 25 us command delay time */
this
->
chip_delay
=
30
;
...
...
drivers/mtd/nand/ts7250.c
浏览文件 @
0305c865
...
...
@@ -83,31 +83,29 @@ static struct mtd_partition partition_info128[] = {
/*
* hardware specific access to control-lines
*
* ctrl:
* NAND_NCE: bit 0 -> bit 2
* NAND_CLE: bit 1 -> bit 1
* NAND_ALE: bit 2 -> bit 0
*/
static
void
ts7250_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
)
static
void
ts7250_hwcontrol
(
struct
mtd_info
*
mtd
,
int
cmd
,
unsigned
int
ctrl
)
{
unsigned
long
ctrl
=
TS72XX_NAND_CONTROL_VIRT_BASE
;
switch
(
cmd
)
{
case
NAND_CTL_SETCLE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
|
0x2
,
ctrl
);
break
;
case
NAND_CTL_CLRCLE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
&
~
0x2
,
ctrl
);
break
;
case
NAND_CTL_SETALE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
|
0x1
,
ctrl
);
break
;
case
NAND_CTL_CLRALE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
&
~
0x1
,
ctrl
);
break
;
case
NAND_CTL_SETNCE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
|
0x4
,
ctrl
);
break
;
case
NAND_CTL_CLRNCE
:
__raw_writeb
(
__raw_readb
(
ctrl
)
&
~
0x4
,
ctrl
);
break
;
struct
nand_chip
*
chip
=
mtd
->
priv
;
if
(
ctrl
&
NAND_CTRL_CHANGE
)
{
unsigned
long
addr
=
TS72XX_NAND_CONTROL_VIRT_BASE
;
unsigned
char
bits
;
bits
=
(
ctrl
&
NAND_CNE
)
<<
2
;
bits
|=
ctrl
&
NAND_CLE
;
bits
|=
(
ctrl
&
NAND_ALE
)
>>
2
;
__raw_writeb
((
__raw_readb
(
addr
)
&
~
0x7
)
|
bits
,
addr
);
}
if
(
cmd
!=
NAND_CMD_NONE
)
writeb
(
cmd
,
chip
->
IO_ADDR_W
);
}
/*
...
...
@@ -152,7 +150,7 @@ static int __init ts7250_init(void)
/* insert callbacks */
this
->
IO_ADDR_R
=
(
void
*
)
TS72XX_NAND_DATA_VIRT_BASE
;
this
->
IO_ADDR_W
=
(
void
*
)
TS72XX_NAND_DATA_VIRT_BASE
;
this
->
hwcontro
l
=
ts7250_hwcontrol
;
this
->
cmd_ctr
l
=
ts7250_hwcontrol
;
this
->
dev_ready
=
ts7250_device_ready
;
this
->
chip_delay
=
15
;
this
->
ecc
.
mode
=
NAND_ECC_SOFT
;
...
...
drivers/mtd/nftlcore.c
浏览文件 @
0305c865
...
...
@@ -70,8 +70,6 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
nftl
->
mbd
.
devnum
=
-
1
;
nftl
->
mbd
.
blksize
=
512
;
nftl
->
mbd
.
tr
=
tr
;
memcpy
(
&
nftl
->
oobinfo
,
&
mtd
->
oobinfo
,
sizeof
(
struct
nand_oobinfo
));
nftl
->
oobinfo
.
useecc
=
MTD_NANDECC_PLACEONLY
;
if
(
NFTL_mount
(
nftl
)
<
0
)
{
printk
(
KERN_WARNING
"NFTL: could not mount device
\n
"
);
...
...
@@ -369,8 +367,11 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
}
memset
(
&
oob
,
0xff
,
sizeof
(
struct
nftl_oob
));
oob
.
b
.
Status
=
oob
.
b
.
Status1
=
SECTOR_USED
;
MTD_WRITEECC
(
nftl
->
mbd
.
mtd
,
(
nftl
->
EraseSize
*
targetEUN
)
+
(
block
*
512
),
512
,
&
retlen
,
movebuf
,
(
char
*
)
&
oob
,
&
nftl
->
oobinfo
);
nand_write_raw
(
nftl
->
mbd
.
mtd
,
(
nftl
->
EraseSize
*
targetEUN
)
+
(
block
*
512
),
512
,
&
retlen
,
movebuf
,
(
char
*
)
&
oob
);
}
/* add the header so that it is now a valid chain */
...
...
@@ -639,10 +640,10 @@ static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
memset
(
&
oob
,
0xff
,
sizeof
(
struct
nftl_oob
));
oob
.
b
.
Status
=
oob
.
b
.
Status1
=
SECTOR_USED
;
MTD_WRITEECC
(
nftl
->
mbd
.
mtd
,
(
writeEUN
*
nftl
->
EraseSize
)
+
blockofs
,
512
,
&
retlen
,
(
char
*
)
buffer
,
(
char
*
)
&
oob
,
&
nftl
->
oobinfo
);
/* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
nand_write_raw
(
nftl
->
mbd
.
mtd
,
(
writeEUN
*
nftl
->
EraseSize
)
+
blockofs
,
512
,
&
retlen
,
(
char
*
)
buffer
,
(
char
*
)
&
oob
);
return
0
;
}
#endif
/* CONFIG_NFTL_RW */
...
...
drivers/mtd/nftlmount.c
浏览文件 @
0305c865
...
...
@@ -268,18 +268,22 @@ static int memcmpb(void *a, int c, int n)
static
int
check_free_sectors
(
struct
NFTLrecord
*
nftl
,
unsigned
int
address
,
int
len
,
int
check_oob
)
{
int
i
;
size_t
retlen
;
u8
buf
[
SECTORSIZE
+
nftl
->
mbd
.
mtd
->
oobsize
];
struct
mtd_info
*
mtd
=
nftl
->
mbd
.
mtd
;
size_t
retlen
;
int
i
;
for
(
i
=
0
;
i
<
len
;
i
+=
SECTORSIZE
)
{
if
(
MTD_READECC
(
nftl
->
mbd
.
mtd
,
address
,
SECTORSIZE
,
&
retlen
,
buf
,
&
buf
[
SECTORSIZE
],
&
nftl
->
oobinfo
)
<
0
)
if
(
mtd
->
read
(
mtd
,
address
,
SECTORSIZE
,
&
retlen
,
buf
)
)
return
-
1
;
if
(
memcmpb
(
buf
,
0xff
,
SECTORSIZE
)
!=
0
)
return
-
1
;
if
(
check_oob
)
{
if
(
memcmpb
(
buf
+
SECTORSIZE
,
0xff
,
nftl
->
mbd
.
mtd
->
oobsize
)
!=
0
)
if
(
mtd
->
read_oob
(
mtd
,
address
,
mtd
->
oobsize
,
&
retlen
,
&
buf
[
SECTORSIZE
])
<
0
)
return
-
1
;
if
(
memcmpb
(
buf
+
SECTORSIZE
,
0xff
,
mtd
->
oobsize
)
!=
0
)
return
-
1
;
}
address
+=
SECTORSIZE
;
...
...
drivers/mtd/onenand/onenand_base.c
浏览文件 @
0305c865
...
...
@@ -597,31 +597,28 @@ static void onenand_release_device(struct mtd_info *mtd)
}
/**
* onenand_read
_ecc - [MTD Interface] Read data with ECC
* onenand_read
- [MTD Interface] Read data from flash
* @param mtd MTD device structure
* @param from offset to read from
* @param len number of bytes to read
* @param retlen pointer to variable to store the number of read bytes
* @param buf the databuffer to put data
* @param oob_buf filesystem supplied oob data buffer
* @param oobsel oob selection structure
*
* OneNAND read with ECC
*/
static
int
onenand_read_ecc
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
,
u_char
*
oob_buf
,
struct
nand_oobinfo
*
oobsel
)
* Read with ecc
*/
static
int
onenand_read
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
)
{
struct
onenand_chip
*
this
=
mtd
->
priv
;
int
read
=
0
,
column
;
int
thislen
;
int
ret
=
0
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"onenand_read
_ecc
: from = 0x%08x, len = %i
\n
"
,
(
unsigned
int
)
from
,
(
int
)
len
);
DEBUG
(
MTD_DEBUG_LEVEL3
,
"onenand_read: from = 0x%08x, len = %i
\n
"
,
(
unsigned
int
)
from
,
(
int
)
len
);
/* Do not allow reads past end of device */
if
((
from
+
len
)
>
mtd
->
size
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_read
_ecc
: Attempt read beyond end of device
\n
"
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_read: Attempt read beyond end of device
\n
"
);
*
retlen
=
0
;
return
-
EINVAL
;
}
...
...
@@ -654,7 +651,7 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
break
;
if
(
ret
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_read
_ecc
: read failed = %d
\n
"
,
ret
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_read: read failed = %d
\n
"
,
ret
);
goto
out
;
}
...
...
@@ -675,22 +672,6 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
return
ret
;
}
/**
* onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
* @param mtd MTD device structure
* @param from offset to read from
* @param len number of bytes to read
* @param retlen pointer to variable to store the number of read bytes
* @param buf the databuffer to put data
*
* This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
*/
static
int
onenand_read
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
)
{
return
onenand_read_ecc
(
mtd
,
from
,
len
,
retlen
,
buf
,
NULL
,
NULL
);
}
/**
* onenand_read_oob - [MTD Interface] OneNAND read out-of-band
* @param mtd MTD device structure
...
...
@@ -834,39 +815,36 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
/**
* onenand_write
_ecc - [MTD Interface] OneNAND write with ECC
* onenand_write
- [MTD Interface] write buffer to FLASH
* @param mtd MTD device structure
* @param to offset to write to
* @param len number of bytes to write
* @param retlen pointer to variable to store the number of written bytes
* @param buf the data to write
* @param eccbuf filesystem supplied oob data buffer
* @param oobsel oob selection structure
*
*
OneNAND w
rite with ECC
*
W
rite with ECC
*/
static
int
onenand_write_ecc
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
static
int
onenand_write
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
)
{
struct
onenand_chip
*
this
=
mtd
->
priv
;
int
written
=
0
;
int
ret
=
0
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"onenand_write
_ecc
: to = 0x%08x, len = %i
\n
"
,
(
unsigned
int
)
to
,
(
int
)
len
);
DEBUG
(
MTD_DEBUG_LEVEL3
,
"onenand_write: to = 0x%08x, len = %i
\n
"
,
(
unsigned
int
)
to
,
(
int
)
len
);
/* Initialize retlen, in case of early exit */
*
retlen
=
0
;
/* Do not allow writes past end of device */
if
(
unlikely
((
to
+
len
)
>
mtd
->
size
))
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write
_ecc
: Attempt write to past end of device
\n
"
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write: Attempt write to past end of device
\n
"
);
return
-
EINVAL
;
}
/* Reject writes, which are not page aligned */
if
(
unlikely
(
NOTALIGNED
(
to
))
||
unlikely
(
NOTALIGNED
(
len
)))
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write
_ecc
: Attempt to write not page aligned data
\n
"
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write: Attempt to write not page aligned data
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -888,7 +866,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
ret
=
this
->
wait
(
mtd
,
FL_WRITING
);
if
(
ret
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write
_ecc
: write filaed %d
\n
"
,
ret
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write: write filaed %d
\n
"
,
ret
);
goto
out
;
}
...
...
@@ -897,7 +875,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
/* Only check verify write turn on */
ret
=
onenand_verify_page
(
mtd
,
(
u_char
*
)
buf
,
to
);
if
(
ret
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write
_ecc
: verify failed %d
\n
"
,
ret
);
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_write: verify failed %d
\n
"
,
ret
);
goto
out
;
}
...
...
@@ -917,23 +895,6 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
return
ret
;
}
/**
* onenand_write - [MTD Interface] compability function for onenand_write_ecc
* @param mtd MTD device structure
* @param to offset to write to
* @param len number of bytes to write
* @param retlen pointer to variable to store the number of written bytes
* @param buf the data to write
*
* This function simply calls onenand_write_ecc
* with oob buffer and oobsel = NULL
*/
static
int
onenand_write
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
)
{
return
onenand_write_ecc
(
mtd
,
to
,
len
,
retlen
,
buf
,
NULL
,
NULL
);
}
/**
* onenand_write_oob - [MTD Interface] OneNAND write out-of-band
* @param mtd MTD device structure
...
...
@@ -1013,144 +974,6 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
return
ret
;
}
/**
* onenand_writev_ecc - [MTD Interface] write with iovec with ecc
* @param mtd MTD device structure
* @param vecs the iovectors to write
* @param count number of vectors
* @param to offset to write to
* @param retlen pointer to variable to store the number of written bytes
* @param eccbuf filesystem supplied oob data buffer
* @param oobsel oob selection structure
*
* OneNAND write with iovec with ecc
*/
static
int
onenand_writev_ecc
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
)
{
struct
onenand_chip
*
this
=
mtd
->
priv
;
unsigned
char
*
pbuf
;
size_t
total_len
,
len
;
int
i
,
written
=
0
;
int
ret
=
0
;
/* Preset written len for early exit */
*
retlen
=
0
;
/* Calculate total length of data */
total_len
=
0
;
for
(
i
=
0
;
i
<
count
;
i
++
)
total_len
+=
vecs
[
i
].
iov_len
;
DEBUG
(
MTD_DEBUG_LEVEL3
,
"onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld
\n
"
,
(
unsigned
int
)
to
,
(
unsigned
int
)
total_len
,
count
);
/* Do not allow write past end of the device */
if
(
unlikely
((
to
+
total_len
)
>
mtd
->
size
))
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_writev_ecc: Attempted write past end of device
\n
"
);
return
-
EINVAL
;
}
/* Reject writes, which are not page aligned */
if
(
unlikely
(
NOTALIGNED
(
to
))
||
unlikely
(
NOTALIGNED
(
total_len
)))
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_writev_ecc: Attempt to write not page aligned data
\n
"
);
return
-
EINVAL
;
}
/* Grab the lock and see if the device is available */
onenand_get_device
(
mtd
,
FL_WRITING
);
/* TODO handling oob */
/* Loop until all keve's data has been written */
len
=
0
;
while
(
count
)
{
pbuf
=
this
->
page_buf
;
/*
* If the given tuple is >= pagesize then
* write it out from the iov
*/
if
((
vecs
->
iov_len
-
len
)
>=
mtd
->
writesize
)
{
pbuf
=
vecs
->
iov_base
+
len
;
len
+=
mtd
->
writesize
;
/* Check, if we have to switch to the next tuple */
if
(
len
>=
(
int
)
vecs
->
iov_len
)
{
vecs
++
;
len
=
0
;
count
--
;
}
}
else
{
int
cnt
=
0
,
thislen
;
while
(
cnt
<
mtd
->
writesize
)
{
thislen
=
min_t
(
int
,
mtd
->
writesize
-
cnt
,
vecs
->
iov_len
-
len
);
memcpy
(
this
->
page_buf
+
cnt
,
vecs
->
iov_base
+
len
,
thislen
);
cnt
+=
thislen
;
len
+=
thislen
;
/* Check, if we have to switch to the next tuple */
if
(
len
>=
(
int
)
vecs
->
iov_len
)
{
vecs
++
;
len
=
0
;
count
--
;
}
}
}
this
->
command
(
mtd
,
ONENAND_CMD_BUFFERRAM
,
to
,
mtd
->
writesize
);
this
->
write_bufferram
(
mtd
,
ONENAND_DATARAM
,
pbuf
,
0
,
mtd
->
writesize
);
this
->
write_bufferram
(
mtd
,
ONENAND_SPARERAM
,
ffchars
,
0
,
mtd
->
oobsize
);
this
->
command
(
mtd
,
ONENAND_CMD_PROG
,
to
,
mtd
->
writesize
);
onenand_update_bufferram
(
mtd
,
to
,
1
);
ret
=
this
->
wait
(
mtd
,
FL_WRITING
);
if
(
ret
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_writev_ecc: write failed %d
\n
"
,
ret
);
goto
out
;
}
/* Only check verify write turn on */
ret
=
onenand_verify_page
(
mtd
,
(
u_char
*
)
pbuf
,
to
);
if
(
ret
)
{
DEBUG
(
MTD_DEBUG_LEVEL0
,
"onenand_writev_ecc: verify failed %d
\n
"
,
ret
);
goto
out
;
}
written
+=
mtd
->
writesize
;
to
+=
mtd
->
writesize
;
}
out:
/* Deselect and wakt up anyone waiting on the device */
onenand_release_device
(
mtd
);
*
retlen
=
written
;
return
0
;
}
/**
* onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc
* @param mtd MTD device structure
* @param vecs the iovectors to write
* @param count number of vectors
* @param to offset to write to
* @param retlen pointer to variable to store the number of written bytes
*
* OneNAND write with kvec. This just calls the ecc function
*/
static
int
onenand_writev
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
)
{
return
onenand_writev_ecc
(
mtd
,
vecs
,
count
,
to
,
retlen
,
NULL
,
NULL
);
}
/**
* onenand_block_checkbad - [GENERIC] Check if a block is marked bad
* @param mtd MTD device structure
...
...
@@ -1950,8 +1773,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
mtd
->
unpoint
=
NULL
;
mtd
->
read
=
onenand_read
;
mtd
->
write
=
onenand_write
;
mtd
->
read_ecc
=
onenand_read_ecc
;
mtd
->
write_ecc
=
onenand_write_ecc
;
mtd
->
read_oob
=
onenand_read_oob
;
mtd
->
write_oob
=
onenand_write_oob
;
#ifdef CONFIG_MTD_ONENAND_OTP
...
...
@@ -1962,10 +1783,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
mtd
->
write_user_prot_reg
=
onenand_write_user_prot_reg
;
mtd
->
lock_user_prot_reg
=
onenand_lock_user_prot_reg
;
#endif
mtd
->
readv
=
NULL
;
mtd
->
readv_ecc
=
NULL
;
mtd
->
writev
=
onenand_writev
;
mtd
->
writev_ecc
=
onenand_writev_ecc
;
mtd
->
sync
=
onenand_sync
;
mtd
->
lock
=
NULL
;
mtd
->
unlock
=
onenand_unlock
;
...
...
fs/jffs2/wbuf.c
浏览文件 @
0305c865
...
...
@@ -236,10 +236,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
}
/* Do the read... */
if
(
jffs2_cleanmarker_oob
(
c
))
ret
=
c
->
mtd
->
read_ecc
(
c
->
mtd
,
start
,
c
->
wbuf_ofs
-
start
,
&
retlen
,
buf
,
NULL
,
c
->
oobinfo
);
else
ret
=
c
->
mtd
->
read
(
c
->
mtd
,
start
,
c
->
wbuf_ofs
-
start
,
&
retlen
,
buf
);
ret
=
c
->
mtd
->
read
(
c
->
mtd
,
start
,
c
->
wbuf_ofs
-
start
,
&
retlen
,
buf
);
if
(
ret
==
-
EBADMSG
&&
retlen
==
c
->
wbuf_ofs
-
start
)
{
/* ECC recovered */
...
...
@@ -293,16 +290,13 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
if
(
breakme
++
==
20
)
{
printk
(
KERN_NOTICE
"Faking write error at 0x%08x
\n
"
,
ofs
);
breakme
=
0
;
c
->
mtd
->
write
_ecc
(
c
->
mtd
,
ofs
,
towrite
,
&
retlen
,
brokenbuf
,
NULL
,
c
->
oobinfo
);
c
->
mtd
->
write
(
c
->
mtd
,
ofs
,
towrite
,
&
retlen
,
brokenbuf
);
ret
=
-
EIO
;
}
else
#endif
if
(
jffs2_cleanmarker_oob
(
c
))
ret
=
c
->
mtd
->
write_ecc
(
c
->
mtd
,
ofs
,
towrite
,
&
retlen
,
rewrite_buf
,
NULL
,
c
->
oobinfo
);
else
ret
=
c
->
mtd
->
write
(
c
->
mtd
,
ofs
,
towrite
,
&
retlen
,
rewrite_buf
);
ret
=
c
->
mtd
->
write
(
c
->
mtd
,
ofs
,
towrite
,
&
retlen
,
rewrite_buf
);
if
(
ret
||
retlen
!=
towrite
)
{
/* Argh. We tried. Really we did. */
...
...
@@ -455,15 +449,12 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
if
(
breakme
++
==
20
)
{
printk
(
KERN_NOTICE
"Faking write error at 0x%08x
\n
"
,
c
->
wbuf_ofs
);
breakme
=
0
;
c
->
mtd
->
write
_ecc
(
c
->
mtd
,
c
->
wbuf_ofs
,
c
->
wbuf_pagesize
,
&
retlen
,
brokenbuf
,
NULL
,
c
->
oobinfo
);
c
->
mtd
->
write
(
c
->
mtd
,
c
->
wbuf_ofs
,
c
->
wbuf_pagesize
,
&
retlen
,
brokenbuf
);
ret
=
-
EIO
;
}
else
#endif
if
(
jffs2_cleanmarker_oob
(
c
))
ret
=
c
->
mtd
->
write_ecc
(
c
->
mtd
,
c
->
wbuf_ofs
,
c
->
wbuf_pagesize
,
&
retlen
,
c
->
wbuf
,
NULL
,
c
->
oobinfo
);
else
ret
=
c
->
mtd
->
write
(
c
->
mtd
,
c
->
wbuf_ofs
,
c
->
wbuf_pagesize
,
&
retlen
,
c
->
wbuf
);
if
(
ret
||
retlen
!=
c
->
wbuf_pagesize
)
{
...
...
@@ -792,10 +783,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
/* Read flash */
down_read
(
&
c
->
wbuf_sem
);
if
(
jffs2_cleanmarker_oob
(
c
))
ret
=
c
->
mtd
->
read_ecc
(
c
->
mtd
,
ofs
,
len
,
retlen
,
buf
,
NULL
,
c
->
oobinfo
);
else
ret
=
c
->
mtd
->
read
(
c
->
mtd
,
ofs
,
len
,
retlen
,
buf
);
ret
=
c
->
mtd
->
read
(
c
->
mtd
,
ofs
,
len
,
retlen
,
buf
);
if
(
(
ret
==
-
EBADMSG
)
&&
(
*
retlen
==
len
)
)
{
printk
(
KERN_WARNING
"mtd->read(0x%zx bytes from 0x%llx) returned ECC error
\n
"
,
...
...
include/linux/mtd/mtd.h
浏览文件 @
0305c865
...
...
@@ -115,9 +115,6 @@ struct mtd_info {
int
(
*
read
)
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
);
int
(
*
write
)
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
);
int
(
*
read_ecc
)
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
int
(
*
write_ecc
)
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
int
(
*
read_oob
)
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
);
int
(
*
write_oob
)
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
const
u_char
*
buf
);
...
...
@@ -133,17 +130,11 @@ struct mtd_info {
int
(
*
write_user_prot_reg
)
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
u_char
*
buf
);
int
(
*
lock_user_prot_reg
)
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
);
/* kvec-based read/write methods. We need these especially for NAND flash,
with its limited number of write cycles per erase.
/* kvec-based read/write methods.
NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
int
(
*
readv
)
(
struct
mtd_info
*
mtd
,
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
from
,
size_t
*
retlen
);
int
(
*
readv_ecc
)
(
struct
mtd_info
*
mtd
,
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
from
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
int
(
*
writev
)
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
);
int
(
*
writev_ecc
)
(
struct
mtd_info
*
mtd
,
const
struct
kvec
*
vecs
,
unsigned
long
count
,
loff_t
to
,
size_t
*
retlen
,
u_char
*
eccbuf
,
struct
nand_oobinfo
*
oobsel
);
/* Sync */
void
(
*
sync
)
(
struct
mtd_info
*
mtd
);
...
...
include/linux/mtd/nand.h
浏览文件 @
0305c865
...
...
@@ -36,6 +36,9 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from,
size_t
len
,
size_t
ooblen
);
extern
int
nand_write_raw
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
uint8_t
*
buf
,
uint8_t
*
oob
);
/* The maximum number of NAND chips in an array */
#define NAND_MAX_CHIPS 8
...
...
@@ -47,23 +50,20 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from,
/*
* Constants for hardware specific CLE/ALE/NCE function
*/
*
* These are bits which can be or'ed to set/clear multiple
* bits in one go.
*/
/* Select the chip by setting nCE to low */
#define NAND_CTL_SETNCE 1
/* Deselect the chip by setting nCE to high */
#define NAND_CTL_CLRNCE 2
#define NAND_NCE 0x01
/* Select the command latch by setting CLE to high */
#define NAND_CTL_SETCLE 3
/* Deselect the command latch by setting CLE to low */
#define NAND_CTL_CLRCLE 4
#define NAND_CLE 0x02
/* Select the address latch by setting ALE to high */
#define NAND_CTL_SETALE 5
/* Deselect the address latch by setting ALE to low */
#define NAND_CTL_CLRALE 6
/* Set write protection by setting WP to high. Not used! */
#define NAND_CTL_SETWP 7
/* Clear write protection by setting WP to low. Not used! */
#define NAND_CTL_CLRWP 8
#define NAND_ALE 0x04
#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
#define NAND_CTRL_CHANGE 0x80
/*
* Standard NAND flash commands
...
...
@@ -103,6 +103,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from,
#define NAND_CMD_STATUS_RESET 0x7f
#define NAND_CMD_STATUS_CLEAR 0xff
#define NAND_CMD_NONE -1
/* Status bits */
#define NAND_STATUS_FAIL 0x01
#define NAND_STATUS_FAIL_N1 0x02
...
...
@@ -237,7 +239,7 @@ struct nand_ecc_ctrl {
int
steps
;
int
size
;
int
bytes
;
int
(
*
hwctl
)(
struct
mtd_info
*
mtd
,
int
mode
);
void
(
*
hwctl
)(
struct
mtd_info
*
mtd
,
int
mode
);
int
(
*
calculate
)(
struct
mtd_info
*
mtd
,
const
uint8_t
*
dat
,
uint8_t
*
ecc_code
);
...
...
@@ -251,16 +253,15 @@ struct nand_ecc_ctrl {
* @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
* @read_byte: [REPLACEABLE] read one byte from the chip
* @write_byte: [REPLACEABLE] write one byte to the chip
* @read_word: [REPLACEABLE] read one word from the chip
* @write_word: [REPLACEABLE] write one word to the chip
* @write_buf: [REPLACEABLE] write data from the buffer to the chip
* @read_buf: [REPLACEABLE] read data from the chip into the buffer
* @verify_buf: [REPLACEABLE] verify buffer contents against the chip data
* @select_chip: [REPLACEABLE] select chip nr
* @block_bad: [REPLACEABLE] check, if the block is bad
* @block_markbad: [REPLACEABLE] mark the block bad
* @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
* @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling
* ALE/CLE/nCE. Also used to write command and address
* @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
* If set to NULL no access to ready/busy is available and the ready/busy information
* is read from the chip status register
...
...
@@ -304,17 +305,15 @@ struct nand_chip {
void
__iomem
*
IO_ADDR_W
;
uint8_t
(
*
read_byte
)(
struct
mtd_info
*
mtd
);
void
(
*
write_byte
)(
struct
mtd_info
*
mtd
,
uint8_t
byte
);
u16
(
*
read_word
)(
struct
mtd_info
*
mtd
);
void
(
*
write_word
)(
struct
mtd_info
*
mtd
,
u16
word
);
void
(
*
write_buf
)(
struct
mtd_info
*
mtd
,
const
uint8_t
*
buf
,
int
len
);
void
(
*
read_buf
)(
struct
mtd_info
*
mtd
,
uint8_t
*
buf
,
int
len
);
int
(
*
verify_buf
)(
struct
mtd_info
*
mtd
,
const
uint8_t
*
buf
,
int
len
);
void
(
*
select_chip
)(
struct
mtd_info
*
mtd
,
int
chip
);
int
(
*
block_bad
)(
struct
mtd_info
*
mtd
,
loff_t
ofs
,
int
getchip
);
int
(
*
block_markbad
)(
struct
mtd_info
*
mtd
,
loff_t
ofs
);
void
(
*
hwcontrol
)(
struct
mtd_info
*
mtd
,
int
cmd
);
void
(
*
cmd_ctrl
)(
struct
mtd_info
*
mtd
,
int
dat
,
unsigned
int
ctrl
);
int
(
*
dev_ready
)(
struct
mtd_info
*
mtd
);
void
(
*
cmdfunc
)(
struct
mtd_info
*
mtd
,
unsigned
command
,
int
column
,
int
page_addr
);
int
(
*
waitfunc
)(
struct
mtd_info
*
mtd
,
struct
nand_chip
*
this
,
int
state
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录