Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
e94696c1
Commit
e94696c1
authored
Mar 05, 2016
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NAND OTP support
parent
527402be
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
2058 additions
and
0 deletions
+2058
-0
Kconfig
src/drivers/mtd/nand/Kconfig
+554
-0
Makefile
src/drivers/mtd/nand/Makefile
+58
-0
nand.h
src/drivers/mtd/nand/nand.h
+13
-0
nandchip-micron.c
src/drivers/mtd/nand/nandchip-micron.c
+213
-0
pl35x_nand.c
src/drivers/mtd/nand/pl35x_nand.c
+1220
-0
No files found.
src/drivers/mtd/nand/Kconfig
0 → 100644
View file @
e94696c1
This diff is collapsed.
Click to expand it.
src/drivers/mtd/nand/Makefile
0 → 100644
View file @
e94696c1
#
# linux/drivers/nand/Makefile
#
obj-$(CONFIG_MTD_NAND)
+=
nand.o
obj-$(CONFIG_MTD_NAND_ECC)
+=
nand_ecc.o
obj-$(CONFIG_MTD_NAND_BCH)
+=
nand_bch.o
obj-$(CONFIG_MTD_NAND_IDS)
+=
nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON)
+=
sm_common.o
obj-$(CONFIG_MTD_NAND_CAFE)
+=
cafe_nand.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA)
+=
ams-delta.o
obj-$(CONFIG_MTD_NAND_DENALI)
+=
denali.o
obj-$(CONFIG_MTD_NAND_DENALI_PCI)
+=
denali_pci.o
obj-$(CONFIG_MTD_NAND_DENALI_DT)
+=
denali_dt.o
obj-$(CONFIG_MTD_NAND_AU1550)
+=
au1550nd.o
obj-$(CONFIG_MTD_NAND_BF5XX)
+=
bf5xx_nand.o
obj-$(CONFIG_MTD_NAND_S3C2410)
+=
s3c2410.o
obj-$(CONFIG_MTD_NAND_DAVINCI)
+=
davinci_nand.o
obj-$(CONFIG_MTD_NAND_DISKONCHIP)
+=
diskonchip.o
obj-$(CONFIG_MTD_NAND_DOCG4)
+=
docg4.o
obj-$(CONFIG_MTD_NAND_FSMC)
+=
fsmc_nand.o
obj-$(CONFIG_MTD_NAND_SHARPSL)
+=
sharpsl.o
obj-$(CONFIG_MTD_NAND_NANDSIM)
+=
nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X)
+=
cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC)
+=
ndfc.o
obj-$(CONFIG_MTD_NAND_ATMEL)
+=
atmel_nand.o
obj-$(CONFIG_MTD_NAND_GPIO)
+=
gpio.o
obj-$(CONFIG_MTD_NAND_OMAP2)
+=
omap2.o
obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD)
+=
omap_elm.o
obj-$(CONFIG_MTD_NAND_CM_X270)
+=
cmx270_nand.o
obj-$(CONFIG_MTD_NAND_PXA3xx)
+=
pxa3xx_nand.o
obj-$(CONFIG_MTD_NAND_TMIO)
+=
tmio_nand.o
obj-$(CONFIG_MTD_NAND_PLATFORM)
+=
plat_nand.o
obj-$(CONFIG_MTD_NAND_PASEMI)
+=
pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION)
+=
orion_nand.o
obj-$(CONFIG_MTD_NAND_FSL_ELBC)
+=
fsl_elbc_nand.o
obj-$(CONFIG_MTD_NAND_FSL_IFC)
+=
fsl_ifc_nand.o
obj-$(CONFIG_MTD_NAND_FSL_UPM)
+=
fsl_upm.o
obj-$(CONFIG_MTD_NAND_SLC_LPC32XX)
+=
lpc32xx_slc.o
obj-$(CONFIG_MTD_NAND_MLC_LPC32XX)
+=
lpc32xx_mlc.o
obj-$(CONFIG_MTD_NAND_SH_FLCTL)
+=
sh_flctl.o
obj-$(CONFIG_MTD_NAND_MXC)
+=
mxc_nand.o
obj-$(CONFIG_MTD_NAND_SOCRATES)
+=
socrates_nand.o
obj-$(CONFIG_MTD_NAND_TXX9NDFMC)
+=
txx9ndfmc.o
obj-$(CONFIG_MTD_NAND_NUC900)
+=
nuc900_nand.o
obj-$(CONFIG_MTD_NAND_MPC5121_NFC)
+=
mpc5121_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH)
+=
r852.o
obj-$(CONFIG_MTD_NAND_JZ4740)
+=
jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND)
+=
gpmi-nand/
obj-$(CONFIG_MTD_NAND_XWAY)
+=
xway_nand.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)
+=
bcm47xxnflash/
obj-$(CONFIG_MTD_NAND_SUNXI)
+=
sunxi_nand.o
obj-$(CONFIG_MTD_NAND_PL35X)
+=
pl35x_nand.o
obj-$(CONFIG_MTD_NAND_ARASAN)
+=
arasan_nfc.o
obj-$(CONFIG_MTD_NAND_HISI504)
+=
hisi504_nand.o
nand-objs
:=
nand_base.o nand_bbt.o nand_timings.o nandchip-micron.o
src/drivers/mtd/nand/nand.h
0 → 100644
View file @
e94696c1
#include <linux/mtd/mtd.h>
#define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
int
nand_get_device
(
struct
mtd_info
*
mtd
,
int
new_state
);
void
nand_release_device
(
struct
mtd_info
*
mtd
);
int
nand_do_read_ops
(
struct
mtd_info
*
mtd
,
loff_t
from
,
struct
mtd_oob_ops
*
ops
);
int
nand_do_write_ops
(
struct
mtd_info
*
mtd
,
loff_t
to
,
struct
mtd_oob_ops
*
ops
);
void
nandchip_micron_init
(
struct
mtd_info
*
mtd
,
int
dev_id
);
src/drivers/mtd/nand/nandchip-micron.c
0 → 100644
View file @
e94696c1
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/flashchip.h>
#include <linux/io.h>
#include "nand.h"
#define MICRON_SETFEATURE_ARRAYOP 0x90
#define MICRON_SETFEATURE_ARRAYOP_NORMAL ((uint8_t[]){0,0,0,0})
#define MICRON_SETFEATURE_ARRAYOP_OTP ((uint8_t[]){1,0,0,0})
#define MICRON_SETFEATURE_ARRAYOP_OTPPROTECT ((uint8_t[]){3,0,0,0})
#define MICRON_NUM_OTP_FIRSTPAGE 2
#define MICRON_NUM_OTP_PAGES 30
static
int
mt29f_get_user_prot_info
(
struct
mtd_info
*
mtd
,
struct
otp_info
*
buf
,
size_t
len
)
{
int
i
;
if
(
len
<
MICRON_NUM_OTP_PAGES
*
sizeof
(
*
buf
))
return
-
ENOSPC
;
for
(
i
=
0
;
i
<
MICRON_NUM_OTP_PAGES
;
++
i
)
{
buf
->
start
=
i
*
mtd
->
writesize
;
buf
->
length
=
mtd
->
writesize
;
/*
* XXX: don't know how to find out, if a page is locked
*/
buf
->
locked
=
0
;
buf
++
;
}
return
MICRON_NUM_OTP_PAGES
*
sizeof
(
*
buf
);
}
static
int
mt29f_read_user_prot_reg
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
uint8_t
*
buf
)
{
struct
nand_chip
*
chip
=
mtd
->
priv
;
struct
mtd_oob_ops
ops
;
int
ret
;
u8
get_feature
,
i
;
/* Valid pages in otp are 02h-1Fh. */
if
(
from
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
return
-
EIO
;
if
(
from
+
len
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
len
=
(
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
-
from
;
from
+=
MICRON_NUM_OTP_FIRSTPAGE
<<
chip
->
page_shift
;
/* XXX: FL_READING? */
nand_get_device
(
mtd
,
FL_READING
);
chip
->
select_chip
(
mtd
,
0
);
ret
=
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_OTP
);
ndelay
(
1000
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_GET_FEATURES
,
MICRON_SETFEATURE_ARRAYOP
,
-
1
);
get_feature
=
readb
(
chip
->
IO_ADDR_R
);
pr_debug
(
"Feature on: 0x%02x
\n
"
,
get_feature
);
if
(
ret
)
goto
out
;
ops
.
len
=
len
;
ops
.
datbuf
=
buf
;
ops
.
oobbuf
=
NULL
;
ops
.
mode
=
0
;
/*
* XXX: some things in nand_do_read_ops might be wrong for OTP. e.g.
* chip->pagemask, chip->pagebuf handling, caching
*/
ret
=
nand_do_read_ops
(
mtd
,
from
,
&
ops
);
*
retlen
=
ops
.
retlen
;
/* nand_do_read_ops deselects the chip so reselect here */
chip
->
select_chip
(
mtd
,
0
);
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_NORMAL
);
ndelay
(
1000
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_GET_FEATURES
,
MICRON_SETFEATURE_ARRAYOP
,
-
1
);
get_feature
=
readb
(
chip
->
IO_ADDR_R
);
pr_debug
(
"Feature off: 0x%02x
\n
"
,
get_feature
);
out:
nand_release_device
(
mtd
);
return
ret
;
}
static
int
mt29f_write_user_prot_reg
(
struct
mtd_info
*
mtd
,
loff_t
to
,
size_t
len
,
size_t
*
retlen
,
uint8_t
*
buf
)
{
struct
nand_chip
*
chip
=
mtd
->
priv
;
struct
mtd_oob_ops
ops
;
int
ret
;
pr_debug
(
"mt29f_write_user_prot_reg start!!!"
);
/* Valid pages in otp are 02h-1Fh. */
if
(
to
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
return
-
EIO
;
if
(
to
+
len
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
len
=
(
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
-
to
;
to
+=
MICRON_NUM_OTP_FIRSTPAGE
<<
chip
->
page_shift
;
nand_get_device
(
mtd
,
FL_WRITING
);
chip
->
select_chip
(
mtd
,
0
);
ret
=
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_OTP
);
if
(
ret
)
goto
out
;
ops
.
len
=
len
;
ops
.
datbuf
=
buf
;
ops
.
oobbuf
=
NULL
;
ops
.
mode
=
0
;
/*
* some things in nand_do_write_ops might be wrong for OTP. e.g.
* chip->pagemask, chip->pagebuf handling
*/
ret
=
nand_do_write_ops
(
mtd
,
to
,
&
ops
);
*
retlen
=
ops
.
retlen
;
/* nand_do_write_ops deselects the chip so reselect here */
chip
->
select_chip
(
mtd
,
0
);
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_NORMAL
);
out:
nand_release_device
(
mtd
);
return
ret
;
}
static
int
mt29f_lock_user_prot_reg
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
)
{
struct
nand_chip
*
chip
=
mtd
->
priv
;
int
ret
;
int
i
;
/* assert from and len are aligned */
if
(
NOTALIGNED
(
from
)
||
NOTALIGNED
(
len
))
{
pr_notice
(
"%s: attempt to lock non page aligned data
\n
"
,
__func__
);
return
-
EINVAL
;
}
if
(
!
len
)
return
0
;
if
(
from
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
return
-
EINVAL
;
if
(
from
+
len
>
MICRON_NUM_OTP_PAGES
<<
chip
->
page_shift
)
return
-
EINVAL
;
from
+=
MICRON_NUM_OTP_FIRSTPAGE
<<
chip
->
page_shift
;
nand_get_device
(
mtd
,
FL_WRITING
);
chip
->
select_chip
(
mtd
,
0
);
ret
=
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_OTPPROTECT
);
if
(
ret
)
goto
out
;
for
(
i
=
0
;
i
<
len
<<
chip
->
page_shift
;
++
i
)
{
chip
->
cmdfunc
(
mtd
,
NAND_CMD_SEQIN
,
0
,
(
from
<<
chip
->
page_shift
)
+
i
);
chip
->
write_byte
(
mtd
,
0
);
chip
->
cmdfunc
(
mtd
,
NAND_CMD_PAGEPROG
,
-
1
,
-
1
);
}
chip
->
onfi_set_features
(
mtd
,
chip
,
MICRON_SETFEATURE_ARRAYOP
,
MICRON_SETFEATURE_ARRAYOP_NORMAL
);
out:
nand_release_device
(
mtd
);
return
ret
;
}
void
nandchip_micron_init
(
struct
mtd_info
*
mtd
,
int
dev_id
)
{
/*
* OTP is available on (at least) Micron's MT29F2G{08,16}AB[AB]EA,
* MT29F[48]G{08,16}AB[AB]DA, MT29F16G08AJADA having device IDs:
* 0xda, 0xca, 0xaa, 0xba;
* 0xdc, 0xcc, 0xac, 0xbc, 0xa3, 0xb3, 0xd3, 0xc3;
* 0xd3
*/
if
(
IS_ENABLED
(
CONFIG_MTD_NAND_OTP
)
&&
((
dev_id
+
0x20
)
&
0xc0
)
==
0xc0
&&
((
dev_id
&
0x09
)
==
8
||
(
dev_id
&
0x0f
)
==
3
))
{
mtd
->
_get_user_prot_info
=
mt29f_get_user_prot_info
;
mtd
->
_read_user_prot_reg
=
mt29f_read_user_prot_reg
;
mtd
->
_write_user_prot_reg
=
mt29f_write_user_prot_reg
;
mtd
->
_lock_user_prot_reg
=
mt29f_lock_user_prot_reg
;
}
}
src/drivers/mtd/nand/pl35x_nand.c
0 → 100644
View file @
e94696c1
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment