mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
nand: update config for mtd driver
PD#142470: update nand config for mtd
1. update dts of skt&s400
2. update clock reg
3. update regbase
4. update bchmode for infopage
5. mtd: support desctrete uboot layout for slc
change uboot layout for slc [3/3]
multi bootloaders were stored in mlc/slc/emmc.
For emmc/mlc, there's enough space at the begining.
bl2&fip can be stored together which we may call it
as compact mode.
|bl2|fip|bl2|fip|bl2|fip|rsv|normal|
But for slc, space is restricted by romboot. bl2 and
fip had to be stored discretely.
|bl2|bl2|bl2|bl2|rsv|fip|fip|fip|fip|normal|
If kernle want mtd driver use descrete mode.
1. bl_mode in dts should be set as 1.
2. fip_copies and fip_size should be the same as uboot which
was described by marco CONFIG_TPL_COPY_NUM&CONFIG_TPL_SIZE_PER_COPY.
3. And the tpl partition should be added in mtd partition table whose
offset and size are negligible.
when using, mtd0 is for bl2, mtd1 is for tpl(fip)
Change-Id: I0ed07168ba7497d674a7160f7966ebb484a123d5
Signed-off-by: Yonghui Yu <yonghui.yu@amlogic.com>
This commit is contained in:
@@ -13615,6 +13615,8 @@ F: include/linux/mmc/host.h
|
||||
AMLOGIC MTD DRIVER
|
||||
M: Liang Yang <liang.yang@amlogic.com>
|
||||
F: drivers/amlogic/mtd/
|
||||
M: Yonghui Yu <yonghui.yu@amlogic.com>
|
||||
F: drivers/amlogic/mtd/boot.c
|
||||
|
||||
AMLOGIC GPU DEVICETREE
|
||||
M: Jiyu Yang <jiyu.yang@amlogic.com>
|
||||
|
||||
@@ -56,7 +56,93 @@
|
||||
};
|
||||
};
|
||||
|
||||
mtd_nand {
|
||||
compatible = "amlogic, aml_mtd_nand";
|
||||
dev_name = "mtdnand";
|
||||
status = "okay";
|
||||
reg = <0x0 0xFFE07800 0x0 0x200>;
|
||||
interrupts = < 0 34 1 >;
|
||||
pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only";
|
||||
pinctrl-0 = <&all_nand_pins>;
|
||||
pinctrl-1 = <&all_nand_pins>;
|
||||
pinctrl-2 = <&nand_cs_pins>;
|
||||
device_id = <0>;
|
||||
|
||||
/*fip/tpl configurations, must be same
|
||||
* with uboot if bl_mode was set as 1
|
||||
* bl_mode: 0 compact mode; 1 descrete mode
|
||||
* if bl_mode was set as 1, fip configeration will work
|
||||
*/
|
||||
bl_mode = <1>;
|
||||
/*copy count of fip*/
|
||||
fip_copies = <4>;
|
||||
/*size of each fip copy */
|
||||
fip_size = <0x200000>;
|
||||
nand_clk_ctrl = <0xFFE07000>;
|
||||
plat-names = "bootloader","nandnormal";
|
||||
plat-num = <2>;
|
||||
plat-part-0 = <&bootloader>;
|
||||
plat-part-1 = <&nandnormal>;
|
||||
bootloader: bootloader{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <1>;
|
||||
part_num = <0>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nandnormal: nandnormal{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
plane_mode = "twoplane";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <2>;
|
||||
part_num = <3>;
|
||||
partition = <&nand_partitions>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nand_partitions:nand_partition{
|
||||
/*
|
||||
* if bl_mode is 1, tpl size was generate by
|
||||
* fip_copies * fip_size which
|
||||
* will not skip bad when calculating
|
||||
* the partition size;
|
||||
*
|
||||
* if bl_mode is 0,
|
||||
* tpl partition must be comment out.
|
||||
*/
|
||||
tpl{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
logo{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x200000>;
|
||||
};
|
||||
recovery{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x1000000>;
|
||||
};
|
||||
boot{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xC00000>;
|
||||
};
|
||||
system{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xDC40000>;
|
||||
};
|
||||
data{
|
||||
offset=<0xffffffff 0xffffffff>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dwc3: dwc3@ff500000 {
|
||||
compatible = "synopsys, dwc3";
|
||||
|
||||
@@ -55,6 +55,94 @@
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
mtd_nand {
|
||||
compatible = "amlogic, aml_mtd_nand";
|
||||
dev_name = "mtdnand";
|
||||
status = "okay";
|
||||
reg = <0x0 0xFFE07800 0x0 0x200>;
|
||||
interrupts = < 0 34 1 >;
|
||||
pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only";
|
||||
pinctrl-0 = <&all_nand_pins>;
|
||||
pinctrl-1 = <&all_nand_pins>;
|
||||
pinctrl-2 = <&nand_cs_pins>;
|
||||
device_id = <0>;
|
||||
|
||||
/*fip/tpl configurations, must be same
|
||||
* with uboot if bl_mode was set as 1
|
||||
* bl_mode: 0 compact mode; 1 descrete mode
|
||||
* if bl_mode was set as 1, fip configeration will work
|
||||
*/
|
||||
bl_mode = <1>;
|
||||
/*copy count of fip*/
|
||||
fip_copies = <4>;
|
||||
/*size of each fip copy */
|
||||
fip_size = <0x200000>;
|
||||
nand_clk_ctrl = <0xFFE07000>;
|
||||
plat-names = "bootloader","nandnormal";
|
||||
plat-num = <2>;
|
||||
plat-part-0 = <&bootloader>;
|
||||
plat-part-1 = <&nandnormal>;
|
||||
bootloader: bootloader{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <1>;
|
||||
part_num = <0>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nandnormal: nandnormal{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
plane_mode = "twoplane";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <2>;
|
||||
part_num = <3>;
|
||||
partition = <&nand_partitions>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nand_partitions:nand_partition{
|
||||
/*
|
||||
* if bl_mode is 1, tpl size was generate by
|
||||
* fip_copies * fip_size which
|
||||
* will not skip bad when calculating
|
||||
* the partition size;
|
||||
*
|
||||
* if bl_mode is 0,
|
||||
* tpl partition must be comment out.
|
||||
*/
|
||||
tpl{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
logo{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x200000>;
|
||||
};
|
||||
recovery{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x1000000>;
|
||||
};
|
||||
boot{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xC00000>;
|
||||
};
|
||||
system{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xDC40000>;
|
||||
};
|
||||
data{
|
||||
offset=<0xffffffff 0xffffffff>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
dwc3: dwc3@ff500000 {
|
||||
compatible = "synopsys, dwc3";
|
||||
|
||||
@@ -56,6 +56,94 @@
|
||||
};
|
||||
|
||||
};
|
||||
mtd_nand {
|
||||
compatible = "amlogic, aml_mtd_nand";
|
||||
dev_name = "mtdnand";
|
||||
status = "okay";
|
||||
reg = <0x0 0xFFE07800 0x0 0x200>;
|
||||
interrupts = < 0 34 1 >;
|
||||
pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only";
|
||||
pinctrl-0 = <&all_nand_pins>;
|
||||
pinctrl-1 = <&all_nand_pins>;
|
||||
pinctrl-2 = <&nand_cs_pins>;
|
||||
device_id = <0>;
|
||||
|
||||
/*fip/tpl configurations, must be same
|
||||
* with uboot if bl_mode was set as 1
|
||||
* bl_mode: 0 compact mode; 1 descrete mode
|
||||
* if bl_mode was set as 1, fip configeration will work
|
||||
*/
|
||||
bl_mode = <1>;
|
||||
/*copy count of fip*/
|
||||
fip_copies = <4>;
|
||||
/*size of each fip copy */
|
||||
fip_size = <0x200000>;
|
||||
nand_clk_ctrl = <0xFFE07000>;
|
||||
plat-names = "bootloader","nandnormal";
|
||||
plat-num = <2>;
|
||||
plat-part-0 = <&bootloader>;
|
||||
plat-part-1 = <&nandnormal>;
|
||||
bootloader: bootloader{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <1>;
|
||||
part_num = <0>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nandnormal: nandnormal{
|
||||
enable_pad ="ce0";
|
||||
busy_pad = "rb0";
|
||||
timming_mode = "mode5";
|
||||
bch_mode = "bch8_1k";
|
||||
plane_mode = "twoplane";
|
||||
t_rea = <20>;
|
||||
t_rhoh = <15>;
|
||||
chip_num = <2>;
|
||||
part_num = <3>;
|
||||
partition = <&nand_partitions>;
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nand_partitions:nand_partition{
|
||||
/*
|
||||
* if bl_mode is 1, tpl size was generate by
|
||||
* fip_copies * fip_size which
|
||||
* will not skip bad when calculating
|
||||
* the partition size;
|
||||
*
|
||||
* if bl_mode is 0,
|
||||
* tpl partition must be comment out.
|
||||
*/
|
||||
tpl{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
logo{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x200000>;
|
||||
};
|
||||
recovery{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x1000000>;
|
||||
};
|
||||
boot{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xC00000>;
|
||||
};
|
||||
system{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0xDC40000>;
|
||||
};
|
||||
data{
|
||||
offset=<0xffffffff 0xffffffff>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dwc3: dwc3@ff500000 {
|
||||
compatible = "synopsys, dwc3";
|
||||
status = "okay";
|
||||
|
||||
@@ -244,6 +244,18 @@
|
||||
pinctrl-1 = <&all_nand_pins>;
|
||||
pinctrl-2 = <&nand_cs_pins>;
|
||||
device_id = <0>;
|
||||
|
||||
/*fip/tpl configurations, must be same
|
||||
* with uboot if bl_mode was set as 1
|
||||
* bl_mode: 0 compact mode; 1 descrete mode
|
||||
* if bl_mode was set as 1, fip configeration will work
|
||||
*/
|
||||
bl_mode = <1>;
|
||||
/*copy count of fip*/
|
||||
fip_copies = <4>;
|
||||
/*size of each fip copy */
|
||||
fip_size = <0x200000>;
|
||||
nand_clk_ctrl = <0xd0074000>;
|
||||
plat-names = "bootloader","nandnormal";
|
||||
plat-num = <2>;
|
||||
plat-part-0 = <&bootloader>;
|
||||
@@ -273,6 +285,19 @@
|
||||
rb_detect = <1>;
|
||||
};
|
||||
nand_partitions:nand_partition{
|
||||
/*
|
||||
* if bl_mode is 1, tpl size was generate by
|
||||
* fip_copies * fip_size which
|
||||
* will not skip bad when calculating
|
||||
* the partition size;
|
||||
*
|
||||
* if bl_mode is 0,
|
||||
* tpl partition must be comment out.
|
||||
*/
|
||||
tpl{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x0>;
|
||||
};
|
||||
logo{
|
||||
offset=<0x0 0x0>;
|
||||
size=<0x0 0x200000>;
|
||||
|
||||
@@ -592,6 +592,57 @@
|
||||
function = "spi_b";
|
||||
};
|
||||
};
|
||||
nand_pulldown: nand_pulldown {
|
||||
mux {
|
||||
pins = "BOOT_0",
|
||||
"BOOT_1",
|
||||
"BOOT_2",
|
||||
"BOOT_3",
|
||||
"BOOT_4",
|
||||
"BOOT_5",
|
||||
"BOOT_6",
|
||||
"BOOT_7",
|
||||
"BOOT_13";
|
||||
function = "nandflash";
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
nand_pullup: nand_pullup {
|
||||
mux {
|
||||
pins = "BOOT_8";
|
||||
function = "nandflash";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
all_nand_pins: all_nand_pins {
|
||||
mux {
|
||||
pins = "BOOT_0",
|
||||
"BOOT_1",
|
||||
"BOOT_2",
|
||||
"BOOT_3",
|
||||
"BOOT_4",
|
||||
"BOOT_5",
|
||||
"BOOT_6",
|
||||
"BOOT_7",
|
||||
"BOOT_8",
|
||||
"BOOT_9",
|
||||
"BOOT_10",
|
||||
"BOOT_11",
|
||||
"BOOT_12",
|
||||
"BOOT_13";
|
||||
function = "nandflash";
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
|
||||
nand_cs_pins: nand_cs {
|
||||
mux {
|
||||
pins = "BOOT_8";
|
||||
function = "nandflash";
|
||||
};
|
||||
};
|
||||
|
||||
}; /* end of pinctrl_periphs */
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@ obj-$(CONFIG_AMLOGIC_NAND) += aml_nand.o \
|
||||
rsv_manage.o \
|
||||
nand_flash.o \
|
||||
mtd_driver.o \
|
||||
new_nand.o
|
||||
new_nand.o \
|
||||
boot.o
|
||||
|
||||
@@ -53,8 +53,8 @@ struct hw_controller {
|
||||
void __iomem *nand_clk_reg;
|
||||
u32 irq;
|
||||
#ifndef AML_NAND_UBOOT
|
||||
dma_addr_t data_dma_addr;
|
||||
dma_addr_t info_dma_addr;
|
||||
/*dma_addr_t data_dma_addr;*/
|
||||
/*dma_addr_t info_dma_addr;*/
|
||||
struct pinctrl *nand_pinctrl;
|
||||
struct pinctrl_state *nand_pinstate;
|
||||
struct pinctrl_state *nand_rbstate;
|
||||
@@ -92,7 +92,9 @@ struct hw_controller {
|
||||
#endif /* 0 */
|
||||
|
||||
/* gx, for pxp and ic. */
|
||||
#define SD_EMMC_BASE_C (0xd0074000)
|
||||
//#define SD_EMMC_BASE_C (0xd0074000)
|
||||
/* axg */
|
||||
#define SD_EMMC_BASE_C 0xFFE07000
|
||||
#define P_NAND_BASE (SD_EMMC_BASE_C | (1<<11))
|
||||
#define NAND_BASE_APB (P_NAND_BASE)
|
||||
#define NAND_CLK_CNTL (SD_EMMC_BASE_C)
|
||||
@@ -101,9 +103,10 @@ struct hw_controller {
|
||||
|
||||
#define A0_GP_CFG0 (0xc8100240)
|
||||
#define A0_GP_CFG2 (0xc8100248)
|
||||
#define NAND_CLK_CNTL (0xd0074000)
|
||||
#define SD_EMMC_BASE_C 0xFFE07000
|
||||
#define NAND_CLK_CNTL (SD_EMMC_BASE_C)
|
||||
#define PINMUX_BASE (0xc8834400 + (0x2c << 2))
|
||||
#define P_NAND_BASE (0xd0074000 | (1<<11))
|
||||
#define P_NAND_BASE (SD_EMMC_BASE_C | (1<<11))
|
||||
#define NAND_BASE_APB (P_NAND_BASE)
|
||||
|
||||
/* NAND Write Command And Read Status Register */
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
/*#include "partition_table.h"*/
|
||||
|
||||
#define CONFIG_MTD_PARTITIONS 1
|
||||
#define NAND_MAX_DEVICE 4
|
||||
extern struct mtd_info *nand_info[NAND_MAX_DEVICE];
|
||||
extern unsigned char pagelist_hynix256[128];
|
||||
#define CONFIG_ENV_SIZE (64*1024U)
|
||||
|
||||
/*
|
||||
@@ -117,10 +120,27 @@ struct _ext_info {
|
||||
uint32_t page_per_blk;
|
||||
uint32_t xlc;
|
||||
uint32_t ce_mask;
|
||||
/* copact mode: boot means whole uboot
|
||||
* it's easy to understood that copies of
|
||||
* bl2 and fip are the same.
|
||||
* discrete mode, boot means the fip only
|
||||
*/
|
||||
uint32_t boot_num;
|
||||
uint32_t each_boot_pages;
|
||||
uint32_t rsv[2];
|
||||
/* add new below, */
|
||||
/* for comptible reason */
|
||||
uint32_t bbt_occupy_pages;
|
||||
uint32_t bbt_start_block;
|
||||
};
|
||||
#define NAND_FIPMODE_COMPACT (0)
|
||||
#define NAND_FIPMODE_DISCRETE (1)
|
||||
|
||||
struct _fip_info {
|
||||
/* version */
|
||||
uint16_t version;
|
||||
/* compact or discrete */
|
||||
uint16_t mode;
|
||||
/* fip start, pages */
|
||||
uint32_t fip_start;
|
||||
};
|
||||
|
||||
/*max size is 384 bytes*/
|
||||
@@ -129,6 +149,8 @@ struct _nand_page0 {
|
||||
unsigned char page_list[16];
|
||||
struct _nand_cmd retry_usr[32];
|
||||
struct _ext_info ext_info;
|
||||
/* added for slc */
|
||||
struct _fip_info fip_info;
|
||||
};
|
||||
|
||||
|
||||
@@ -476,6 +498,8 @@ struct aml_nand_chip {
|
||||
unsigned int rbpin_mode;
|
||||
unsigned int rbpin_detect;
|
||||
unsigned int short_pgsz;
|
||||
/* bch for infopage on short mode */
|
||||
unsigned int bch_info;
|
||||
|
||||
unsigned int bch_mode;
|
||||
u8 user_byte_mode;
|
||||
@@ -497,6 +521,10 @@ struct aml_nand_chip {
|
||||
/*add property field for key private data*/
|
||||
int dtbsize;
|
||||
int keysize;
|
||||
int boot_copy_num; /*tell how many bootloader copies*/
|
||||
unsigned int bl_mode;
|
||||
unsigned int fip_copies;
|
||||
unsigned int fip_size;
|
||||
|
||||
u8 key_protect;
|
||||
unsigned char *rsv_data_buf;
|
||||
@@ -553,6 +581,8 @@ struct aml_nand_chip {
|
||||
int (*aml_nand_block_bad_scrub)(struct mtd_info *mtd);
|
||||
};
|
||||
|
||||
struct aml_nand_device;
|
||||
|
||||
struct aml_nand_platform {
|
||||
struct aml_nand_flash_dev *nand_flash_dev;
|
||||
char *name;
|
||||
@@ -567,8 +597,9 @@ struct aml_nand_platform {
|
||||
unsigned int rbpin_mode; /*may get from romboot*/
|
||||
unsigned int rbpin_detect;
|
||||
unsigned int short_pgsz; /*zero means no short*/
|
||||
|
||||
struct aml_nand_chip *aml_chip;
|
||||
/* back pointer to the device*/
|
||||
struct aml_nand_device *aml_nand_device;
|
||||
struct platform_nand_data platform_nand_data;
|
||||
};
|
||||
|
||||
@@ -577,6 +608,11 @@ struct aml_nand_device {
|
||||
u8 dev_num;
|
||||
#ifndef AML_NAND_UBOOT
|
||||
struct notifier_block nb;
|
||||
u32 bl_mode;
|
||||
u32 fip_copies;
|
||||
u32 fip_size;
|
||||
/* for mapping regsters */
|
||||
u32 nand_clk_ctrl;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -803,7 +839,20 @@ void aml_nand_command(struct mtd_info *mtd,
|
||||
int aml_nand_wait(struct mtd_info *mtd, struct nand_chip *chip);
|
||||
|
||||
int aml_nand_erase_cmd(struct mtd_info *mtd, int page);
|
||||
/* for boot operations */
|
||||
int m3_nand_boot_erase_cmd(struct mtd_info *mtd, int page);
|
||||
|
||||
int m3_nand_boot_read_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
|
||||
|
||||
int m3_nand_boot_write_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, const uint8_t *buf, int oob_required, int page);
|
||||
|
||||
int m3_nand_boot_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint32_t offset, int data_len, const uint8_t *buf,
|
||||
int oob_required, int page, int cached, int raw);
|
||||
|
||||
int boot_device_register(struct aml_nand_chip *aml_chip);
|
||||
int add_mtd_partitions(struct mtd_info *mtd,
|
||||
const struct mtd_partition *part, int num);
|
||||
|
||||
|
||||
@@ -234,6 +234,50 @@ static struct nand_ecclayout aml_nand_oob_1664 = {
|
||||
.length = 32} }
|
||||
};
|
||||
#endif
|
||||
int nand_get_device(struct mtd_info *mtd, int new_state)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
spinlock_t *lock = &chip->controller->lock;
|
||||
wait_queue_head_t *wq = &chip->controller->wq;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
retry:
|
||||
spin_lock(lock);
|
||||
|
||||
/* Hardware controller shared among independent devices */
|
||||
if (!chip->controller->active)
|
||||
chip->controller->active = chip;
|
||||
|
||||
if (chip->controller->active == chip && chip->state == FL_READY) {
|
||||
chip->state = new_state;
|
||||
spin_unlock(lock);
|
||||
return 0;
|
||||
}
|
||||
if (new_state == FL_PM_SUSPENDED) {
|
||||
if (chip->controller->active->state == FL_PM_SUSPENDED) {
|
||||
chip->state = FL_PM_SUSPENDED;
|
||||
spin_unlock(lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
add_wait_queue(wq, &wait);
|
||||
spin_unlock(lock);
|
||||
schedule();
|
||||
remove_wait_queue(wq, &wait);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void nand_release_device(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
/* Release the controller and the chip */
|
||||
spin_lock(&chip->controller->lock);
|
||||
chip->controller->active = NULL;
|
||||
chip->state = FL_READY;
|
||||
wake_up(&chip->controller->wq);
|
||||
spin_unlock(&chip->controller->lock);
|
||||
}
|
||||
|
||||
void aml_platform_get_user_byte(struct aml_nand_chip *aml_chip,
|
||||
unsigned char *oob_buf, int byte_num)
|
||||
@@ -303,6 +347,8 @@ static int aml_nand_add_partition(struct aml_nand_chip *aml_chip)
|
||||
uint64_t last_size = 0, start_blk = 0;
|
||||
uint64_t mini_part_size;
|
||||
int reserved_part_blk_num = RESERVED_BLOCK_NUM;
|
||||
uint8_t bl_mode, base_part = 0;
|
||||
uint32_t fip_copies, fip_size, fip_part_size = 0;
|
||||
unsigned int bad_blk_addr[128];
|
||||
|
||||
mini_part_size =
|
||||
@@ -329,20 +375,39 @@ static int aml_nand_add_partition(struct aml_nand_chip *aml_chip)
|
||||
(1024 * mtd->writesize / aml_chip->plane_num);
|
||||
part_num++;
|
||||
start_blk = 0;
|
||||
do {
|
||||
offset = adjust_offset + start_blk * mtd->erasesize;
|
||||
error = mtd->_block_isbad(mtd, offset);
|
||||
if (error == FACTORY_BAD_BLOCK_ERROR) {
|
||||
pr_info("%s:%d factory bad addr =%llx\n",
|
||||
bl_mode = aml_chip->bl_mode;
|
||||
if (bl_mode == NAND_FIPMODE_COMPACT) {
|
||||
/* compact bootloader mode */
|
||||
do {
|
||||
offset = adjust_offset +
|
||||
start_blk * mtd->erasesize;
|
||||
error = mtd->_block_isbad(mtd, offset);
|
||||
if (error == FACTORY_BAD_BLOCK_ERROR) {
|
||||
pr_info("%s:%d factory bad addr =%llx\n",
|
||||
__func__, __LINE__,
|
||||
(uint64_t)(offset >> phys_erase_shift));
|
||||
adjust_offset += mtd->erasesize;
|
||||
continue;
|
||||
}
|
||||
start_blk++;
|
||||
} while (start_blk < reserved_part_blk_num);
|
||||
adjust_offset += reserved_part_blk_num * mtd->erasesize;
|
||||
|
||||
adjust_offset += mtd->erasesize;
|
||||
continue;
|
||||
}
|
||||
start_blk++;
|
||||
} while (start_blk < reserved_part_blk_num);
|
||||
} else {
|
||||
/* descrete bootloader mode */
|
||||
/* calculate fip partition by dts config*/
|
||||
fip_copies = aml_chip->fip_copies;
|
||||
fip_size = aml_chip->fip_size;
|
||||
fip_part_size = fip_copies * fip_size;
|
||||
temp_parts = parts;
|
||||
/* TODO: do name check! */
|
||||
temp_parts->offset = adjust_offset
|
||||
+ reserved_part_blk_num * mtd->erasesize;
|
||||
temp_parts->size = fip_part_size;
|
||||
pr_info("%s: off %lld, size %lld\n", temp_parts->name,
|
||||
temp_parts->offset, temp_parts->size);
|
||||
base_part = 1;
|
||||
}
|
||||
adjust_offset += reserved_part_blk_num * mtd->erasesize
|
||||
+fip_part_size;
|
||||
/*normal mtd device divide part from here(adjust_offset)*/
|
||||
if (nr == 0) {
|
||||
part_save_in_env = 0;
|
||||
@@ -357,7 +422,7 @@ static int aml_nand_add_partition(struct aml_nand_chip *aml_chip)
|
||||
mini_part_size =
|
||||
(mtd->erasesize > MINI_PART_SIZE) ? mtd->erasesize : MINI_PART_SIZE;
|
||||
}
|
||||
for (i = 0; i < nr; i++) {
|
||||
for (i = base_part; i < nr; i++) {
|
||||
temp_parts = parts + i;
|
||||
bad_block_cnt = 0;
|
||||
memset((u8 *)bad_blk_addr, 0xff, 128 * sizeof(int));
|
||||
@@ -2311,6 +2376,7 @@ int aml_nand_init(struct aml_nand_chip *aml_chip)
|
||||
struct new_tech_nand_t *new_nand_info = &aml_chip->new_nand_info;
|
||||
struct aml_nand_read_retry *nand_read_retry;
|
||||
struct aml_nand_slc_program *slc_program_info;
|
||||
|
||||
/*#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 13)*/
|
||||
#if 0
|
||||
struct nand_oobfree *oobfree = NULL;
|
||||
@@ -2356,6 +2422,9 @@ int aml_nand_init(struct aml_nand_chip *aml_chip)
|
||||
|
||||
aml_chip->aml_nand_hw_init(aml_chip);
|
||||
aml_chip->toggle_mode = 0;
|
||||
aml_chip->bch_info = NAND_ECC_BCH60_1K;
|
||||
if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG)
|
||||
aml_chip->bch_info = NAND_ECC_BCH8_1K;
|
||||
if (nand_scan(mtd, controller->chip_num) == 0) {
|
||||
chip->options = 0;
|
||||
chip->options |= NAND_SKIP_BBTSCAN;
|
||||
|
||||
1043
drivers/amlogic/mtd/boot.c
Normal file
1043
drivers/amlogic/mtd/boot.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -25,15 +25,7 @@
|
||||
int nand_curr_device = -1;
|
||||
struct hw_controller *controller;
|
||||
|
||||
/* extern void nand_release_device(struct mtd_info *mtd); */
|
||||
|
||||
#define NAND_MAX_DEVICE 4
|
||||
struct mtd_info nand_info[NAND_MAX_DEVICE] = {
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0}
|
||||
};
|
||||
struct mtd_info *nand_info[NAND_MAX_DEVICE];
|
||||
|
||||
#ifdef CONFIG_MTD_DEVICE
|
||||
static __attribute__((unused)) char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
|
||||
@@ -271,39 +263,36 @@ static void m3_nand_select_chip(struct aml_nand_chip *aml_chip, int chipnr)
|
||||
void get_sys_clk_rate_mtd(struct hw_controller *controller, int *rate)
|
||||
{
|
||||
int clk_freq = *rate;
|
||||
unsigned int always_on = 0x1 << 24;
|
||||
unsigned int clk;
|
||||
#ifdef AML_NAND_UBOOT
|
||||
cpu_id_t cpu_id = get_cpu_id();
|
||||
|
||||
if ((cpu_id.family_id == MESON_CPU_MAJOR_ID_GXBB)
|
||||
|| (cpu_id.family_id == MESON_CPU_MAJOR_ID_GXL)) {
|
||||
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_AXG)
|
||||
#else
|
||||
if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB)
|
||||
|| (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL)) {
|
||||
if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG)
|
||||
always_on = 0x1 << 28;
|
||||
#endif
|
||||
/* basic debug code using 24Mhz, fixme. */
|
||||
if (clk_freq == 24) {
|
||||
/* 24Mhz/1 = 24Mhz */
|
||||
amlnf_write_reg32(controller->nand_clk_reg, 0x81000201);
|
||||
} else if (clk_freq == 200) {
|
||||
/* 1000Mhz/5 = 200Mhz */
|
||||
amlnf_write_reg32(controller->nand_clk_reg, 0x81000245);
|
||||
pr_info("%s() %d, clock setting 200!\n",
|
||||
__func__, __LINE__);
|
||||
} else if (clk_freq == 250) {
|
||||
/* 1000Mhz/4 = 250Mhz */
|
||||
amlnf_write_reg32(controller->nand_clk_reg, 0x81000244);
|
||||
pr_info("%s() %d, clock setting 250!\n",
|
||||
__func__, __LINE__);
|
||||
} else {
|
||||
/* 1000Mhz/5 = 200Mhz */
|
||||
amlnf_write_reg32(controller->nand_clk_reg, 0x81000245);
|
||||
pr_info("%s() %d, using default clock 200MHz !\n",
|
||||
__func__, __LINE__);
|
||||
if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB)
|
||||
|| (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL)
|
||||
|| (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG)) {
|
||||
switch (clk_freq) {
|
||||
case 24:
|
||||
clk = 0x80000201;
|
||||
break;
|
||||
case 200:
|
||||
clk = 0x80000245;
|
||||
break;
|
||||
case 250:
|
||||
clk = 0x80000244;
|
||||
break;
|
||||
default:
|
||||
clk = 0x80000245;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
*pr_info("clk_reg 0x%x\n",
|
||||
* AMLNF_READ_REG(controller->nand_clk_reg));
|
||||
**/
|
||||
clk |= always_on;
|
||||
amlnf_write_reg32(controller->nand_clk_reg, clk);
|
||||
return;
|
||||
} else
|
||||
pr_info("%s %d: not support cpu type!!!\n",
|
||||
__func__, __LINE__);
|
||||
@@ -662,7 +651,7 @@ static int m3_nand_dma_write(struct aml_nand_chip *aml_chip,
|
||||
NFC_SEND_CMD_M2N_RAW(controller, 0, len);
|
||||
else
|
||||
NFC_SEND_CMD_M2N(controller, aml_chip->ran_mode,
|
||||
((bch_mode == NAND_ECC_BCH_SHORT) ? NAND_ECC_BCH60_1K : bch_mode),
|
||||
((bch_mode == NAND_ECC_BCH_SHORT) ? aml_chip->bch_info : bch_mode),
|
||||
((bch_mode == NAND_ECC_BCH_SHORT) ? 1 : 0), dma_unit_size, count);
|
||||
|
||||
ret = aml_platform_dma_waiting(aml_chip);
|
||||
@@ -737,7 +726,7 @@ static int m3_nand_dma_read(struct aml_nand_chip *aml_chip,
|
||||
NFC_SEND_CMD_N2M_RAW(controller, 0, len);
|
||||
else
|
||||
NFC_SEND_CMD_N2M(controller, aml_chip->ran_mode,
|
||||
((bch_mode == NAND_ECC_BCH_SHORT)?NAND_ECC_BCH60_1K:bch_mode),
|
||||
((bch_mode == NAND_ECC_BCH_SHORT)?aml_chip->bch_info:bch_mode),
|
||||
((bch_mode == NAND_ECC_BCH_SHORT)?1:0), dma_unit_size, count);
|
||||
|
||||
ret = aml_platform_dma_waiting(aml_chip);
|
||||
@@ -799,474 +788,6 @@ static int m3_nand_hwecc_correct(struct aml_nand_chip *aml_chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m3_nand_boot_erase_cmd(struct mtd_info *mtd, int page)
|
||||
{
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
loff_t ofs;
|
||||
int i, page_addr;
|
||||
|
||||
if (page >= BOOT_PAGES_PER_COPY)
|
||||
return -EPERM;
|
||||
|
||||
if (aml_chip->valid_chip[0]) {
|
||||
for (i = 0; i < BOOT_COPY_NUM; i++) {
|
||||
page_addr = page + i*BOOT_PAGES_PER_COPY;
|
||||
ofs = (page_addr << chip->page_shift);
|
||||
|
||||
if (chip->block_bad(mtd, ofs))
|
||||
continue;
|
||||
|
||||
aml_chip->aml_nand_select_chip(aml_chip, 0);
|
||||
aml_chip->aml_nand_command(aml_chip,
|
||||
NAND_CMD_ERASE1, -1, page_addr, 0);
|
||||
aml_chip->aml_nand_command(aml_chip,
|
||||
NAND_CMD_ERASE2, -1, -1, 0);
|
||||
chip->waitfunc(mtd, chip);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m3_nand_boot_read_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
uint8_t *oob_buf = chip->oob_poi;
|
||||
unsigned int nand_page_size = chip->ecc.steps * chip->ecc.size;
|
||||
uint32_t pages_per_blk_shift = chip->phys_erase_shift-chip->page_shift;
|
||||
int user_byte_num = (chip->ecc.steps * aml_chip->user_byte_mode);
|
||||
int bch_mode = aml_chip->bch_mode, ran_mode = 0;
|
||||
int error = 0, i = 0, stat = 0;
|
||||
int ecc_size, configure_data_w, pages_per_blk_w, configure_data;
|
||||
int pages_per_blk, read_page;
|
||||
int en_slc = 0;
|
||||
/* using info page structure */
|
||||
struct _nand_page0 *p_nand_page0 = NULL;
|
||||
struct _ext_info *p_ext_info = NULL;
|
||||
struct nand_setup *p_nand_setup = NULL;
|
||||
u8 type = aml_chip->new_nand_info.type;
|
||||
|
||||
if (aml_chip->support_new_nand == 1)
|
||||
en_slc = ((type < 10) && type) ? 1:0;
|
||||
|
||||
if (page >= (BOOT_PAGES_PER_COPY*BOOT_COPY_NUM)) {
|
||||
memset(buf, 0, (1 << chip->page_shift));
|
||||
pr_info("nand boot read out of uboot failed, page:%d\n", page);
|
||||
goto exit;
|
||||
}
|
||||
/* nand page info */
|
||||
if ((page % BOOT_PAGES_PER_COPY) == 0) {
|
||||
if (aml_chip->bch_mode == NAND_ECC_BCH_SHORT)
|
||||
configure_data_w =
|
||||
NFC_CMD_N2M(aml_chip->ran_mode,
|
||||
NAND_ECC_BCH60_1K, 1, (chip->ecc.size >> 3), chip->ecc.steps);
|
||||
else
|
||||
configure_data_w =
|
||||
NFC_CMD_N2M(aml_chip->ran_mode,
|
||||
aml_chip->bch_mode, 0, (chip->ecc.size >> 3), chip->ecc.steps);
|
||||
|
||||
ecc_size = chip->ecc.size; /* backup ecc size */
|
||||
|
||||
if (aml_chip->bch_mode != NAND_ECC_BCH_SHORT) {
|
||||
nand_page_size =
|
||||
(mtd->writesize / 512) * NAND_ECC_UNIT_SHORT;
|
||||
bch_mode = NAND_ECC_BCH_SHORT;
|
||||
chip->ecc.size = NAND_ECC_UNIT_SHORT;
|
||||
} else
|
||||
bch_mode = aml_chip->bch_mode;
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
|
||||
memset(buf, 0xff, (1 << chip->page_shift));
|
||||
/* read back page0 and check it */
|
||||
if (aml_chip->valid_chip[0]) {
|
||||
if (!aml_chip->aml_nand_wait_devready(aml_chip, i)) {
|
||||
pr_info("don't found selected chip:%d ready\n",
|
||||
i);
|
||||
error = -EBUSY;
|
||||
}
|
||||
if (aml_chip->ops_mode & AML_CHIP_NONE_RB)
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_READ0 & 0xff,
|
||||
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
|
||||
if (en_slc == 0) {
|
||||
ran_mode = aml_chip->ran_mode;
|
||||
aml_chip->ran_mode = 1;
|
||||
}
|
||||
error = aml_chip->aml_nand_dma_read(aml_chip,
|
||||
buf, nand_page_size, bch_mode);
|
||||
if (en_slc == 0)
|
||||
aml_chip->ran_mode = ran_mode;
|
||||
if (error)
|
||||
pr_info(" page0 aml_nand_dma_read failed\n");
|
||||
|
||||
aml_chip->aml_nand_get_user_byte(aml_chip,
|
||||
oob_buf, user_byte_num);
|
||||
stat = aml_chip->aml_nand_hwecc_correct(aml_chip,
|
||||
buf, nand_page_size, oob_buf);
|
||||
if (stat < 0) {
|
||||
mtd->ecc_stats.failed++;
|
||||
pr_info("page0 read ecc fail at blk0 chip0\n");
|
||||
} else
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
} else {
|
||||
pr_info("nand boot page 0 no valid chip failed\n");
|
||||
error = -ENODEV;
|
||||
/* goto exit; */
|
||||
}
|
||||
|
||||
/* check page 0 info here */
|
||||
p_nand_page0 = (struct _nand_page0 *) buf;
|
||||
p_nand_setup = &p_nand_page0->nand_setup;
|
||||
p_ext_info = &p_nand_page0->ext_info;
|
||||
|
||||
configure_data = p_nand_setup->cfg.b.cmd;
|
||||
pages_per_blk = p_ext_info->page_per_blk;
|
||||
pages_per_blk_w =
|
||||
(1 << (chip->phys_erase_shift - chip->page_shift));
|
||||
|
||||
if ((pages_per_blk_w != pages_per_blk)
|
||||
|| (configure_data != configure_data_w)) {
|
||||
pr_info("page%d fail ", page);
|
||||
pr_info("configure:0x%x-0x%x pages_per_blk:0x%x-0x%x\n",
|
||||
configure_data_w, configure_data,
|
||||
pages_per_blk_w, pages_per_blk);
|
||||
}
|
||||
|
||||
bch_mode = aml_chip->bch_mode;
|
||||
chip->ecc.size = ecc_size;
|
||||
nand_page_size = chip->ecc.steps * chip->ecc.size;
|
||||
}
|
||||
|
||||
read_page = page;
|
||||
read_page++;
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
if (en_slc) {
|
||||
read_page = page % BOOT_PAGES_PER_COPY;
|
||||
if (type == HYNIX_1YNM_8GB)
|
||||
read_page =
|
||||
pagelist_1ynm_hynix256_mtd[read_page + 1] +
|
||||
(page / BOOT_PAGES_PER_COPY) * BOOT_PAGES_PER_COPY;
|
||||
else
|
||||
read_page =
|
||||
pagelist_hynix256[read_page + 1] +
|
||||
(page / BOOT_PAGES_PER_COPY)*BOOT_PAGES_PER_COPY;
|
||||
}
|
||||
}
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, read_page);
|
||||
|
||||
memset(buf, 0xff, (1 << chip->page_shift));
|
||||
if (aml_chip->valid_chip[0]) {
|
||||
if (!aml_chip->aml_nand_wait_devready(aml_chip, 0)) {
|
||||
pr_info("don't found selected chip0 ready, page: %d\n",
|
||||
page);
|
||||
error = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
if (aml_chip->ops_mode & AML_CHIP_NONE_RB)
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_READ0 & 0xff,
|
||||
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
|
||||
|
||||
error = aml_chip->aml_nand_dma_read(aml_chip,
|
||||
buf, nand_page_size, bch_mode);
|
||||
if (error) {
|
||||
error = -ENODEV;
|
||||
pr_info("aml_nand_dma_read failed: page:%d\n", page);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
aml_chip->aml_nand_get_user_byte(aml_chip,
|
||||
oob_buf, user_byte_num);
|
||||
stat = aml_chip->aml_nand_hwecc_correct(aml_chip,
|
||||
buf, nand_page_size, oob_buf);
|
||||
if (stat < 0) {
|
||||
error = -ENODEV;
|
||||
mtd->ecc_stats.failed++;
|
||||
pr_info("read data ecc failed at blk%d chip%d\n",
|
||||
(page >> pages_per_blk_shift), i);
|
||||
} else
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
} else
|
||||
error = -ENODEV;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* set nand info into page0_buf for romboot.
|
||||
*/
|
||||
void __attribute__((unused)) nand_info_page_prepare(
|
||||
struct aml_nand_chip *aml_chip,
|
||||
u8 *page0_buf)
|
||||
{
|
||||
struct nand_chip *chip = &aml_chip->chip;
|
||||
/* fixme,
|
||||
*devops_len = devops->len which means the total operation of uboot
|
||||
**/
|
||||
u32 devops_len = (BOOT_PAGES_PER_COPY-1) * aml_chip->page_size;
|
||||
/* struct hw_controller *controller = &(aml_chip->controller); */
|
||||
int i, nand_read_info;
|
||||
u32 en_slc, configure_data;
|
||||
u32 boot_num = 1, each_boot_pages;
|
||||
u32 valid_pages = BOOT_TOTAL_PAGES;
|
||||
|
||||
struct _nand_page0 *p_nand_page0 = NULL;
|
||||
struct _ext_info *p_ext_info = NULL;
|
||||
struct nand_setup *p_nand_setup = NULL;
|
||||
|
||||
p_nand_page0 = (struct _nand_page0 *) page0_buf;
|
||||
p_nand_setup = &p_nand_page0->nand_setup;
|
||||
p_ext_info = &p_nand_page0->ext_info;
|
||||
|
||||
|
||||
configure_data = NFC_CMD_N2M(aml_chip->ran_mode,
|
||||
aml_chip->bch_mode, 0, (chip->ecc.size >> 3),
|
||||
chip->ecc.steps);
|
||||
/* en_slc mode will not be used on slc */
|
||||
en_slc = 0;
|
||||
|
||||
memset(p_nand_page0, 0x0, sizeof(struct _nand_page0));
|
||||
/* info_cfg->ext = (configure_data | (1<<23) |(1<<22) | (2<<20)); */
|
||||
/*
|
||||
*p_nand_setup->cfg.d32 =
|
||||
*(configure_data|(1<<23) | (1<<22) | (2<<20) | (1<<19));
|
||||
**/
|
||||
/* randomizer mode depends on chip's cofig */
|
||||
p_nand_setup->cfg.d32 = (configure_data|(1<<23) | (1<<22) | (2<<20));
|
||||
pr_info("cfg.d32 0x%x\n", p_nand_setup->cfg.d32);
|
||||
/* need finish here for romboot retry */
|
||||
p_nand_setup->id = 0;
|
||||
p_nand_setup->max = 0;
|
||||
|
||||
memset(p_nand_page0->page_list,
|
||||
0,
|
||||
NAND_PAGELIST_CNT);
|
||||
/* chip_num occupy the lowest 2 bit */
|
||||
nand_read_info = controller->chip_num;
|
||||
|
||||
/*
|
||||
*make it
|
||||
*1)calu the number of boot saved and pages each boot needs.
|
||||
*2)the number is 2*n but less than 4.
|
||||
**/
|
||||
pr_info("valid_pages = %d en_slc = %d devops_len = 0x%x",
|
||||
valid_pages,
|
||||
en_slc, devops_len);
|
||||
valid_pages = (en_slc)?(valid_pages>>1):valid_pages;
|
||||
for (i = 1;
|
||||
i < ((valid_pages*aml_chip->page_size)/devops_len + 1); i++) {
|
||||
if (((valid_pages*aml_chip->page_size)/(2*i) >= devops_len)
|
||||
&& (boot_num < 4))
|
||||
boot_num <<= 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
each_boot_pages = valid_pages/boot_num;
|
||||
|
||||
p_ext_info->read_info = nand_read_info;
|
||||
p_ext_info->page_per_blk = aml_chip->block_size / aml_chip->page_size;
|
||||
/* fixme, only ce0 is enabled! */
|
||||
p_ext_info->ce_mask = 0x01;
|
||||
/* xlc is not in using for now */
|
||||
p_ext_info->xlc = 1;
|
||||
p_ext_info->boot_num = boot_num;
|
||||
p_ext_info->each_boot_pages = each_boot_pages;
|
||||
|
||||
/* pr_info("new_type = 0x%x\n", p_ext_info->new_type); */
|
||||
pr_info("page_per_blk = 0x%x\n", p_ext_info->page_per_blk);
|
||||
pr_info("boot_num = %d each_boot_pages = %d", boot_num,
|
||||
each_boot_pages);
|
||||
}
|
||||
|
||||
static int m3_nand_boot_write_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)
|
||||
{
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
uint8_t *oob_buf = chip->oob_poi;
|
||||
unsigned int nand_page_size = chip->ecc.steps * chip->ecc.size;
|
||||
int user_byte_num = (chip->ecc.steps * aml_chip->user_byte_mode);
|
||||
int error = 0, i = 0, bch_mode, ecc_size;
|
||||
|
||||
ecc_size = chip->ecc.size;
|
||||
if (((aml_chip->page_addr % BOOT_PAGES_PER_COPY) == 0)
|
||||
&& (aml_chip->bch_mode != NAND_ECC_BCH_SHORT)) {
|
||||
nand_page_size = (mtd->writesize / 512) * NAND_ECC_UNIT_SHORT;
|
||||
bch_mode = NAND_ECC_BCH_SHORT;
|
||||
chip->ecc.size = NAND_ECC_UNIT_SHORT;
|
||||
} else
|
||||
bch_mode = aml_chip->bch_mode;
|
||||
/* setting magic for romboot checks. */
|
||||
for (i = 0; i < mtd->oobavail; i += 2) {
|
||||
oob_buf[i] = 0x55;
|
||||
oob_buf[i+1] = 0xaa;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (aml_chip->valid_chip[i]) {
|
||||
aml_chip->aml_nand_select_chip(aml_chip, i);
|
||||
aml_chip->aml_nand_set_user_byte(aml_chip,
|
||||
oob_buf, user_byte_num);
|
||||
error = aml_chip->aml_nand_dma_write(aml_chip,
|
||||
(unsigned char *)buf, nand_page_size, bch_mode);
|
||||
if (error)
|
||||
goto exit;
|
||||
aml_chip->aml_nand_command(aml_chip,
|
||||
NAND_CMD_PAGEPROG, -1, -1, i);
|
||||
} else {
|
||||
error = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
if (((aml_chip->page_addr % BOOT_PAGES_PER_COPY) == 0)
|
||||
&& (aml_chip->bch_mode != NAND_ECC_BCH_SHORT))
|
||||
chip->ecc.size = ecc_size;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int m3_nand_boot_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
uint32_t offset, int data_len, const uint8_t *buf,
|
||||
int oob_required, int page, int cached, int raw)
|
||||
{
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
int status, i, write_page, ran_mode = 0;
|
||||
int new_nand_type = 0;
|
||||
int pages_per_blk;
|
||||
struct new_tech_nand_t *new_nand_info;
|
||||
struct aml_nand_slc_program *slc_program_info;
|
||||
int en_slc = 0;
|
||||
unsigned char *fill_buf = NULL;
|
||||
unsigned int priv_slc_page;
|
||||
u8 type = aml_chip->new_nand_info.type;
|
||||
|
||||
new_nand_info = &aml_chip->new_nand_info;
|
||||
slc_program_info = &new_nand_info->slc_program_info;
|
||||
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
new_nand_type = type;
|
||||
en_slc = ((type < 10) && type) ? 1 : 0;
|
||||
if (new_nand_type == HYNIX_1YNM_8GB) {
|
||||
fill_buf = kzalloc(mtd->writesize, GFP_KERNEL);
|
||||
if (fill_buf == NULL) {
|
||||
pr_info("malloc fill buf fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(fill_buf, 0xff, mtd->writesize);
|
||||
}
|
||||
|
||||
if (en_slc) {
|
||||
if (page >= (BOOT_PAGES_PER_COPY/2 - 1))
|
||||
return 0;
|
||||
if (slc_program_info->enter_enslc_mode)
|
||||
slc_program_info->enter_enslc_mode(mtd);
|
||||
} else {
|
||||
if (page >= (BOOT_PAGES_PER_COPY - 1))
|
||||
return 0;
|
||||
}
|
||||
pages_per_blk = (1<<(chip->phys_erase_shift-chip->page_shift));
|
||||
} else {
|
||||
if (page >= (BOOT_PAGES_PER_COPY - 1))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write all copies at 1 time */
|
||||
for (i = 0; i < BOOT_COPY_NUM; i++) {
|
||||
/* actual page to be written */
|
||||
write_page = page + i*BOOT_PAGES_PER_COPY;
|
||||
/* zero page of each copy */
|
||||
if ((write_page % BOOT_PAGES_PER_COPY) == 0) {
|
||||
nand_info_page_prepare(aml_chip,
|
||||
chip->buffers->databuf);
|
||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, write_page);
|
||||
/* must enable ran_mode for info page */
|
||||
if (en_slc == 0) {
|
||||
ran_mode = aml_chip->ran_mode;
|
||||
aml_chip->ran_mode = 1;
|
||||
}
|
||||
chip->ecc.write_page(mtd,
|
||||
chip, chip->buffers->databuf, 0, write_page);
|
||||
if (en_slc == 0)
|
||||
aml_chip->ran_mode = ran_mode;
|
||||
|
||||
status = chip->waitfunc(mtd, chip);
|
||||
|
||||
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
|
||||
status = chip->errstat(mtd,
|
||||
chip, FL_WRITING, status, write_page);
|
||||
|
||||
if (status & NAND_STATUS_FAIL) {
|
||||
pr_info("uboot wr 0 page=0x%x, status=0x%x\n",
|
||||
page, status);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
/* +1 for skipping nand info page */
|
||||
if (en_slc) {
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
if (type == HYNIX_1YNM_8GB)
|
||||
write_page =
|
||||
pagelist_1ynm_hynix256_mtd[page + 1] +
|
||||
i*BOOT_PAGES_PER_COPY;
|
||||
else
|
||||
write_page =
|
||||
pagelist_hynix256[page + 1] +
|
||||
i * BOOT_PAGES_PER_COPY;
|
||||
}
|
||||
} else
|
||||
write_page++;
|
||||
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
if (new_nand_type == HYNIX_1YNM_8GB) {
|
||||
if ((page + 1) > 1)
|
||||
priv_slc_page =
|
||||
pagelist_1ynm_hynix256_mtd[page] +
|
||||
i * BOOT_PAGES_PER_COPY;
|
||||
else
|
||||
priv_slc_page = page +
|
||||
i * BOOT_PAGES_PER_COPY;
|
||||
while ((priv_slc_page + 1) < write_page) {
|
||||
chip->cmdfunc(mtd,
|
||||
NAND_CMD_SEQIN,
|
||||
0x00, ++priv_slc_page);
|
||||
chip->ecc.write_page_raw(mtd,
|
||||
chip, fill_buf, 0, priv_slc_page);
|
||||
chip->waitfunc(mtd, chip);
|
||||
pr_info("%s, fill page:0x%x\n",
|
||||
__func__, priv_slc_page);
|
||||
}
|
||||
}
|
||||
}
|
||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, write_page);
|
||||
|
||||
if (unlikely(raw))
|
||||
chip->ecc.write_page_raw(mtd, chip, buf, 0, write_page);
|
||||
else
|
||||
chip->ecc.write_page(mtd, chip, buf, 0, write_page);
|
||||
|
||||
if (!cached || !(chip->options & NAND_CACHEPRG)) {
|
||||
status = chip->waitfunc(mtd, chip);
|
||||
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
|
||||
status = chip->errstat(mtd,
|
||||
chip, FL_WRITING, status, write_page);
|
||||
if (status & NAND_STATUS_FAIL) {
|
||||
pr_info("uboot wr page=0x%x, status=0x%x\n",
|
||||
page, status);
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
if (en_slc && slc_program_info->exit_enslc_mode)
|
||||
slc_program_info->exit_enslc_mode(mtd);
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
} else
|
||||
status = chip->waitfunc(mtd, chip);
|
||||
}
|
||||
if (aml_chip->support_new_nand == 1) {
|
||||
if (en_slc && slc_program_info->exit_enslc_mode)
|
||||
slc_program_info->exit_enslc_mode(mtd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef AML_NAND_UBOOT
|
||||
struct nand_hw_control upper_controller;
|
||||
@@ -1331,6 +852,7 @@ static int m3_nand_probe(struct aml_nand_platform *plat, unsigned int dev_num)
|
||||
struct mtd_info *mtd = NULL;
|
||||
int err = 0;
|
||||
unsigned int nand_type = 0;
|
||||
struct aml_nand_device *aml_nand_device = NULL;
|
||||
/*#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 13)*/
|
||||
#if 0
|
||||
int tmp_val, i;
|
||||
@@ -1349,6 +871,7 @@ static int m3_nand_probe(struct aml_nand_platform *plat, unsigned int dev_num)
|
||||
|
||||
/* initialize mtd info data struct */
|
||||
aml_chip->controller = controller;
|
||||
/* to it's own plat data */
|
||||
aml_chip->platform = plat;
|
||||
aml_chip->bch_desc = m3_bch_list;
|
||||
aml_chip->max_bch_mode = ARRAY_SIZE(m3_bch_list);
|
||||
@@ -1362,6 +885,15 @@ static int m3_nand_probe(struct aml_nand_platform *plat, unsigned int dev_num)
|
||||
#ifndef AML_NAND_UBOOT
|
||||
/*fixit ,hardware support all address*/
|
||||
/* dev->coherent_dma_mask = DMA_BIT_MASK(32); */
|
||||
aml_nand_device = plat->aml_nand_device;
|
||||
pr_info("%s() aml_nand_device %p\n", __func__, aml_nand_device);
|
||||
if (aml_nand_device) {
|
||||
aml_chip->bl_mode = aml_nand_device->bl_mode;
|
||||
aml_chip->fip_copies = aml_nand_device->fip_copies;
|
||||
aml_chip->fip_size = aml_nand_device->fip_size;
|
||||
}
|
||||
|
||||
|
||||
aml_chip->device = dev;
|
||||
mtd->dev.parent = dev->parent;
|
||||
mtd->owner = THIS_MODULE;
|
||||
@@ -1434,7 +966,7 @@ static int m3_nand_probe(struct aml_nand_platform *plat, unsigned int dev_num)
|
||||
/*need to set device_boot_flag here*/
|
||||
device_boot_flag = NAND_BOOT_FLAG;
|
||||
#endif
|
||||
nand_info[dev_num] = *mtd;
|
||||
nand_info[dev_num] = mtd;
|
||||
return 0;
|
||||
|
||||
exit_error:
|
||||
@@ -1477,7 +1009,6 @@ void nand_init(void)
|
||||
pr_info("error for not platform data\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = m3_nand_probe(plat, i);
|
||||
if (ret) {
|
||||
pr_info("nand init faile: %d\n", ret);
|
||||
@@ -1529,9 +1060,11 @@ int nand_init(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "ioremap Nand Flash IO fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pr_info("nand_clk_ctrl 0x%x\n",
|
||||
aml_nand_mid_device.nand_clk_ctrl);
|
||||
|
||||
controller->nand_clk_reg = devm_ioremap_nocache(&pdev->dev,
|
||||
NAND_CLK_CNTL,
|
||||
aml_nand_mid_device.nand_clk_ctrl,
|
||||
sizeof(int));
|
||||
if (controller->nand_clk_reg == NULL) {
|
||||
dev_err(&pdev->dev, "ioremap External Nand Clock IO fail\n");
|
||||
@@ -1590,6 +1123,9 @@ int nand_init(struct platform_device *pdev)
|
||||
continue;
|
||||
}
|
||||
#ifndef AML_NAND_UBOOT
|
||||
/* to get the glb fip infos */
|
||||
plat->aml_nand_device = &aml_nand_mid_device;
|
||||
pr_info("plat->aml_nand_device %p\n", plat->aml_nand_device);
|
||||
ret = m3_nand_probe(plat, i, &pdev->dev);
|
||||
#else
|
||||
ret = m3_nand_probe(plat, i);
|
||||
|
||||
@@ -194,6 +194,38 @@ static int prase_get_dtb_nand_parameter(struct aml_nand_device *aml_nand_dev,
|
||||
of_node_put(np_config);
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np,
|
||||
"bl_mode", (u32 *)&aml_nand_dev->bl_mode);
|
||||
if (ret) {
|
||||
pr_info("%s:%d,please config bl_mode item\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
pr_info("bl mode %s\n",
|
||||
aml_nand_dev->bl_mode?"descrete":"compact");
|
||||
|
||||
ret = of_property_read_u32(np,
|
||||
"fip_copies", (u32 *)&aml_nand_dev->fip_copies);
|
||||
if (ret) {
|
||||
pr_info("%s:%d,please config fip_copies item\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
pr_info("fip_copies %d\n", aml_nand_dev->fip_copies);
|
||||
ret = of_property_read_u32(np,
|
||||
"fip_size", (u32 *)&aml_nand_dev->fip_size);
|
||||
pr_info("fip_size 0x%x\n", aml_nand_dev->fip_size);
|
||||
if (ret) {
|
||||
pr_info("%s:%d,please config fip_size item\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
ret = of_property_read_u32(np,
|
||||
"nand_clk_ctrl", (u32 *)&aml_nand_dev->nand_clk_ctrl);
|
||||
pr_info("nand_clk_ctrl 0x%x\n", aml_nand_dev->nand_clk_ctrl);
|
||||
if (ret) {
|
||||
aml_nand_dev->nand_clk_ctrl = NAND_CLK_CNTL;
|
||||
pr_info("%s:%d, using default nand_clk_ctrl 0x%x\n",
|
||||
__func__, __LINE__, NAND_CLK_CNTL);
|
||||
}
|
||||
};
|
||||
pr_info("%s:%d,parse dts end\n", __func__, __LINE__);
|
||||
return 0;
|
||||
|
||||
@@ -1281,7 +1281,7 @@ static int aml_nand_scan_ident(struct mtd_info *mtd, int maxchips)
|
||||
|
||||
/* overide bootloader's size consdering info page */
|
||||
if (!strcmp(mtd->name, NAND_BOOT_NAME))
|
||||
mtd->size = BOOT_PAGES_PER_COPY * mtd->writesize;
|
||||
mtd->size = BOOT_TOTAL_PAGES * mtd->writesize;
|
||||
|
||||
chip->cmdfunc = aml_nand_command;
|
||||
chip->waitfunc = aml_nand_wait;
|
||||
|
||||
@@ -67,32 +67,40 @@ static const struct meson_desc_pin mesonaxg_periphs_pins[] = {
|
||||
MESON_FUNCTION(0x0, "gpio")),
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_0, EE_OFF), 0x0, 0,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc")), /*EMMC_D0*/
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_D0*/
|
||||
MESON_FUNCTION(0x1, "nandflash")), /*EMMC_D0*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_1, EE_OFF), 0x0, 4,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc")), /*EMMC_D1*/
|
||||
MESON_FUNCTION(0x1, "emmc"),
|
||||
MESON_FUNCTION(0x1, "nandflash")), /*EMMC_D1*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_2, EE_OFF), 0x0, 8,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc")), /*EMMC_D2*/
|
||||
MESON_FUNCTION(0x1, "emmc"),
|
||||
MESON_FUNCTION(0x1, "nandflash")), /*EMMC_D2*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_3, EE_OFF), 0x0, 12,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_D3*/
|
||||
MESON_FUNCTION(0x1, "nandflash"),
|
||||
MESON_FUNCTION(0x3, "norflash")), /*NOR_HOLD*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_4, EE_OFF), 0x0, 16,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_D4*/
|
||||
MESON_FUNCTION(0x1, "nandflash"),
|
||||
MESON_FUNCTION(0x3, "norflash")), /*NOR_D*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_5, EE_OFF), 0x0, 20,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_D5*/
|
||||
MESON_FUNCTION(0x1, "nandflash"),
|
||||
MESON_FUNCTION(0x3, "norflash")), /*NOR_Q*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_6, EE_OFF), 0x0, 24,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_D6*/
|
||||
MESON_FUNCTION(0x1, "nandflash"),
|
||||
MESON_FUNCTION(0x3, "norflash")), /*NOR_C*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_7, EE_OFF), 0x0, 28,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc")), /*EMMC_D7*/
|
||||
MESON_FUNCTION(0x1, "emmc"),
|
||||
MESON_FUNCTION(0x1, "nandflash")), /*EMMC_D7*/
|
||||
MESON_PINCTRL_PIN(MESON_PIN(BOOT_8, EE_OFF), 0x1, 0,
|
||||
MESON_FUNCTION(0x0, "gpio"),
|
||||
MESON_FUNCTION(0x1, "emmc"), /*EMMC_CLK*/
|
||||
|
||||
Reference in New Issue
Block a user