Commit 4bbaac41 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

nand spl support - tmp working with nand_base.c

parent e47e7650
......@@ -257,8 +257,6 @@ void zynq_slcr_devcfg_enable(void)
u32 zynq_slcr_get_boot_mode(void)
{
/* Get the bootmode register value */
printf("\nBOOTMODE CODE is %d\n",(u32)readl(&slcr_base->boot_mode));
udelay(5000);
return readl(&slcr_base->boot_mode);
}
......
......@@ -17,9 +17,12 @@ obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
obj-$(CONFIG_SPL_NAND_ELPHEL393) += elphel393_nand_spl.o
obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
obj-$(CONFIG_SPL_NAND_BBT) += nand_bbt.o
obj-$(CONFIG_SPL_NAND_IDS) += nand_ids.o
obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o
obj-$(CONFIG_SPL_NAND_INIT) += nand.o
obj-$(CONFIG_SPL_NAND_INIT) += ../mtdcore.o ../mtd_uboot.o
ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
obj-$(CONFIG_ENV_IS_IN_NAND) += nand_util.o
endif
......
/*
* Xilinx Zynq NAND Flash Controller Driver
* This driver is based on plat_nand.c and mxc_nand.c drivers
* Elphel393 NAND driver for SPL, not based on denali_spl.c
*
* Copyright (C) 2009 - 2013 Xilinx, Inc.
* Copyright (C) 2016 Elphel, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
......@@ -19,82 +18,118 @@
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
/* The NAND flash driver defines */
#define ZYNQ_NAND_CMD_PHASE 1 /* End command valid in command phase */
#define ZYNQ_NAND_DATA_PHASE 2 /* End command valid in data phase */
#define ZYNQ_NAND_ECC_SIZE 512 /* Size of data for ECC operation */
/* Flash memory controller operating parameters */
#define ZYNQ_NAND_CLR_CONFIG ((0x1 << 1) | /* Disable interrupt */ \
(0x1 << 4) | /* Clear interrupt */ \
(0x1 << 6)) /* Disable ECC interrupt */
/* Assuming 50MHz clock (20ns cycle time) and 3V operation */
#define ZYNQ_NAND_SET_CYCLES ((0x2 << 20) | /* t_rr from nand_cycles */ \
(0x2 << 17) | /* t_ar from nand_cycles */ \
(0x1 << 14) | /* t_clr from nand_cycles */ \
(0x3 << 11) | /* t_wp from nand_cycles */ \
(0x2 << 8) | /* t_rea from nand_cycles */ \
(0x5 << 4) | /* t_wc from nand_cycles */ \
(0x5 << 0)) /* t_rc from nand_cycles */
#define ZYNQ_NAND_SET_OPMODE 0x0
#define ZYNQ_NAND_DIRECT_CMD ((0x4 << 23) | /* Chip 0 from interface 1 */ \
(0x2 << 21)) /* UpdateRegs operation */
#define ZYNQ_NAND_ECC_CONFIG ((0x1 << 2) | /* ECC available on APB */ \
(0x1 << 4) | /* ECC read at end of page */ \
(0x0 << 5)) /* No Jumping */
#define ZYNQ_NAND_ECC_CMD1 ((0x80) | /* Write command */ \
(0x00 << 8) | /* Read command */ \
(0x30 << 16) | /* Read End command */ \
(0x1 << 24)) /* Read End command calid */
#define ZYNQ_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \
(0x05 << 8) | /* Read col change cmd */ \
(0xE0 << 16) | /* Read col change end cmd */ \
(0x1 << 24)) /* Read col change
end cmd valid */
/* AXI Address definitions */
#define START_CMD_SHIFT 3
#define END_CMD_SHIFT 11
#define END_CMD_VALID_SHIFT 20
#define ADDR_CYCLES_SHIFT 21
#define CLEAR_CS_SHIFT 21
#define ECC_LAST_SHIFT 10
#define COMMAND_PHASE (0 << 19)
#define DATA_PHASE (1 << 19)
#define ZYNQ_NAND_ECC_LAST (1 << ECC_LAST_SHIFT) /* Set ECC_Last */
#define ZYNQ_NAND_CLEAR_CS (1 << CLEAR_CS_SHIFT) /* Clear chip select */
/* ECC block registers bit position and bit mask */
#define ZYNQ_NAND_ECC_BUSY (1 << 6) /* ECC block is busy */
#define ZYNQ_NAND_ECC_MASK 0x00FFFFFF /* ECC value mask */
#define ZYNQ_NAND_ROW_ADDR_CYCL_MASK 0x0F
#define ZYNQ_NAND_COL_ADDR_CYCL_MASK 0xF0
/* NAND MIO buswidth count*/
#define ZYNQ_NAND_MIO_NUM_NAND_8BIT 13
#define ZYNQ_NAND_MIO_NUM_NAND_16BIT 8
/* Based on Fabian Gottlieb von Bellingshausen's work in Antarctica */
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
extern nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
static int is_badblock(struct mtd_info *mtd, loff_t offs, int allowbbt)
{
register struct nand_chip *chip = mtd->priv;
unsigned int block = offs >> chip->phys_erase_shift;
unsigned int page = offs >> chip->page_shift;
printf(" is_badblock(): offs=0x%08x block=%d page=%d\n",(int)offs, block,
page);
//chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
//memset(chip->oob_poi, 0, mtd->oobsize);
//chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
//return chip->oob_poi[0] != 0xff;
return 0;
}
/* nand_init() - initialize data to make nand usable by SPL */
void nand_init(void)
//dst or buf - destination in RAM
//offs - u-boot-dtb.img offset in NAND
//size - size of u-boot-dtb.img
int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
{
struct nand_chip *chip;
struct mtd_info *mtd;
unsigned int page;
unsigned int nand_page_per_block;
unsigned int sz = 0;
printf("\nnand_spl_load_image(): offs=0x%08x size=%d (0x%08x) buf_addr=0x%08x\n",offs,size,size,buf);
udelay(10000);
//if (mxs_nand_init()) return -ENODEV;
mtd = &nand_info[0];
//mtd.priv = &nand_chip;
chip = mtd->priv;
page = offs >> chip->page_shift;
nand_page_per_block = mtd->erasesize / mtd->writesize;
debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page);
printf(" nand_page_per_block= %d\n",nand_page_per_block);
printf(" mtd->writesize= %d\n",mtd->writesize);
printf(" u-boot-dtb.img size is: %d (0x%08x)\n",size,size);
size = roundup(size, mtd->writesize);
printf(" u-boot-dtb.img size after roundup is:%d\n",size);
//u32 testbuf[16];
while (sz < size) {
//if (mxs_read_page_ecc(&mtd, buf, page) < 0)
// return -1;
//printf(" Reading from NAND, offset:0x%08x page_index:%d to MEM address:0x%08x\n",offs, page, buf);
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
udelay(500);
//read min
chip->read_buf(mtd,buf,min(size-sz, mtd->writesize));
//chip->ecc.read_page(mtd, chip, buf, 0, page);
sz += mtd->writesize;
offs += mtd->writesize;
page++;
buf += mtd->writesize;
/*
* Check if we have crossed a block boundary, and if so
* check for bad block.
*/
//if (!(page % nand_page_per_block)) {
// /*
// * Yes, new block. See if this block is good. If not,
// * loop until we find a good block.
// */
// while (is_badblock(&mtd, offs, 1)) {
// page = page + nand_page_per_block;
// /* Check we've reached the end of flash. */
// if (page >= mtd->size >> chip->page_shift)
// return -ENOMEM;
// }
//}
}
return 0;
}
/* already defined in nand.c
// nand_init() - initialize data to make nand usable by SPL
void nand_init(void)
{
puts("nand_init()\n");
udelay(5000);
board_nand_init();
}
*/
void nand_init_custom(void)
{
puts("nand_init_custom()\n");
udelay(5000);
//board_nand_init();
}
/* secret */
void nand_deselect(void) {
puts("nand_deselect(): empty function\n");
udelay(10000);
}
void nand_deselect2(void) {
printf("nand_deselect2(): &nand_info[0]=0x%08x\n",(u32)&nand_info[0]);
puts("nand_deselect2(): empty function\n");
udelay(10000);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -55,8 +55,8 @@
#define ZYNQ_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \
(0x05 << 8) | /* Read col change cmd */ \
(0xE0 << 16) | /* Read col change end cmd */ \
(0x1 << 24)) /* Read col change
end cmd valid */
(0x1 << 24)) /* Read col change end cmd valid */
/* AXI Address definitions */
#define START_CMD_SHIFT 3
#define END_CMD_SHIFT 11
......@@ -773,6 +773,8 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
unsigned long end_cmd_valid = 0;
unsigned long i;
//printf(" zynq_nand(): Command=0x%02x Column=0x%02x PageAddr=0x%08x\n",command,column,page_addr);
xnand = (struct zynq_nand_info *)chip->priv;
if (xnand->end_cmd_pending) {
/* Check for end command if this command request is same as the
......@@ -905,6 +907,9 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
*/
static void zynq_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
//printf("zynq_nand_read_buf():start len=0x%08x buf=0x%08x\n",len,buf);
struct nand_chip *chip = mtd->priv;
const u32 *nand = chip->IO_ADDR_R;
......@@ -955,6 +960,9 @@ static void zynq_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
*/
static void zynq_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
printf("zynq_nand_write_buf(): len=%d buf=%d\n",len,buf);
struct nand_chip *chip = mtd->priv;
const u32 *nand = chip->IO_ADDR_W;
......@@ -1040,7 +1048,9 @@ static int zynq_nand_check_is_16bit_bw_flash(void)
(mio_num_16bit == ZYNQ_NAND_MIO_NUM_NAND_16BIT))
is_16bit_bw = NAND_BW_16BIT;
return is_16bit_bw;
//return is_16bit_bw;
//elphel force 8 bits width
return NAND_BW_8BIT;
}
static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
......@@ -1056,7 +1066,12 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
int ondie_ecc_enabled = 0;
int is_16bit_bw;
//printf("\n zynq_nand_init():start\n");
xnand = calloc(1, sizeof(struct zynq_nand_info));
//printf("ZYNQ_NAND_INIT: CALLOC @0x%08x size=%d\n",(u32)&xnand,sizeof(xnand));
if (!xnand) {
printf("%s: failed to allocate\n", __func__);
goto free;
......@@ -1072,6 +1087,11 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
nand_chip->IO_ADDR_R = xnand->nand_base;
nand_chip->IO_ADDR_W = xnand->nand_base;
//printf(" ZYNQ_NAND_BASEADDR:0x%08x\n",(unsigned int)ZYNQ_NAND_BASEADDR);
//printf(" xnand->nand_base:0x%08x\n",(unsigned int)xnand->nand_base);
//printf(" nand_chip->IO_ADDR_R:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_R);
//printf(" nand_chip->IO_ADDR_W:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_W);
/* Set the driver entry points for MTD */
nand_chip->cmdfunc = zynq_nand_cmd_function;
nand_chip->dev_ready = zynq_nand_device_ready;
......@@ -1087,6 +1107,9 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
/* Check the NAND buswidth */
/* FIXME this will be changed by using NAND_BUSWIDTH_AUTO */
is_16bit_bw = zynq_nand_check_is_16bit_bw_flash();
//printf(" is_16bit_bw: %d\n",is_16bit_bw);
if (is_16bit_bw == NAND_BW_UNKNOWN) {
printf("%s: Unable detect NAND based on MIO settings\n",
__func__);
......@@ -1116,6 +1139,10 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
maf_id = nand_chip->read_byte(mtd);
dev_id = nand_chip->read_byte(mtd);
//printf(" maf_id=0x%02x dev_id=0x%02x\n",maf_id,dev_id);
//printf(" nand_chip->IO_ADDR_R:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_R);
//printf(" nand_chip->IO_ADDR_W:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_W);
if ((maf_id == 0x2c) && ((dev_id == 0xf1) ||
(dev_id == 0xa1) || (dev_id == 0xb1) ||
(dev_id == 0xaa) || (dev_id == 0xba) ||
......@@ -1146,6 +1173,13 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
}
if (ondie_ecc_enabled) {
//puts(" Welcome to OnDie ECC flash\n");
//printf(" ZYNQ_NAND_BASEADDR:0x%08x\n",(unsigned int)ZYNQ_NAND_BASEADDR);
//printf(" xnand->nand_base:0x%08x\n",(unsigned int)xnand->nand_base);
//printf(" nand_chip->IO_ADDR_R:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_R);
//printf(" nand_chip->IO_ADDR_W:0x%08x\n",(unsigned int)nand_chip->IO_ADDR_W);
/* bypass the controller ECC block */
ecc_cfg = readl(&zynq_nand_smc_base->emcr);
ecc_cfg &= ~0xc;
......@@ -1206,6 +1240,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
&zynq_nand_smc_base->emcr);
break;
case 2048:
printf(" necc_page_size = 0x3\n");
ecc_page_size = 0x3;
/* Set the ECC memory config register */
writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size),
......@@ -1248,6 +1283,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
if (nand_register(devnum))
goto fail;
//printf(" zynq_nand_init(): end\n");
return 0;
fail:
free:
......@@ -1261,6 +1297,9 @@ void board_nand_init(void)
{
struct nand_chip *nand = &nand_chip[0];
printf("board_nand_init(): &nand_chip[0]=0x%08x\n",(u32)&nand_chip[0]);
if (zynq_nand_init(nand, 0))
puts("ZYNQ NAND init failed\n");
}
......@@ -32,7 +32,7 @@
#define CONFIG_NAND_ZYNQ
#ifdef CONFIG_NAND_ZYNQ
#define CONFIG_CMD_NAND
/*#define CONFIG_CMD_NAND*/
#define CONFIG_CMD_NAND_LOCK_UNLOCK
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_SELF_INIT
......@@ -40,15 +40,35 @@
#define CONFIG_MTD_DEVICE
#endif
#define CONFIG_SPL_NAND_ELPHEL393
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x40000
/*
#define CONFIG_SPL_NAND_LOAD
#define CONFIG_SYS_NAND_U_BOOT_SIZE 0x100000
#define CONFIG_SYS_NAND_U_BOOT_DST 0x0
#define CONFIG_SYS_NAND_U_BOOT_START 0x0
*/
#define CONFIG_SPL_NAND_SUPPORT
#define CONFIG_SPL_NAND_DRIVERS
*/
#define CONFIG_SPL_NAND_INIT
#define CONFIG_SPL_NAND_BASE
#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_NAND_BBT
#define CONFIG_SPL_NAND_IDS
/* Load U-Boot to this address */
#define CONFIG_SYS_NAND_U_BOOT_DST CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
#define CONFIG_MTD
/*#define CONFIG_DEFAULT_DEVICE_TREE elphel393*/
/*redefined in zynq-common.h*/
#undef CONFIG_CMD_NAND
/*#undef CONFIG_CMD_NAND*/
#include <configs/zynq-common.h>
#undef CONFIG_SYS_PROMPT
......@@ -57,22 +77,12 @@
/*skip u-boot falcon mode*/
#undef CONFIG_SPL_OS_BOOT
#undef CONFIG_DISPLAY_BOARDINFO
#include <configs/ezynq/ezynq_MT41K256M16HA107.h> /* should be before zed_ezynq.h as it overwrites DDR3L with DDR3 */
#include <configs/ezynq/ezynq_XC7Z030_1FBG484C.h>
#include <configs/ezynq/ezynq_elphel393.h>
/*#define CONFIG_SYS_MAX_NAND_DEVICE 1*/
/*#define CONFIG_SYS_NAND_BASE 0xE1000000*/
/*
#define CONFIG_SPL_NAND_DENALI
#define CONFIG_SYS_NAND_DATA_BASE 0xE1000000
#define CONFIG_SYS_NAND_REGS_BASE 0xE1000000
#define CONFIG_SYS_NAND_BAD_BLOCK_POS 0
*/
/*
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0xE1000000
*/
#define CONFIG_CMD_MEMTEST
#define CONFIG_BOOTDELAY 1 /* -1 to Disable autoboot */
......@@ -92,8 +102,8 @@
"loadbit_addr=0x100000\0" \
"loadbootenv_addr=0x2000000\0" \
"kernel_size=0x500000\0" \
"devicetree_size=0x20000\0" \
"ramdisk_size=0x5E0000\0" \
"devicetree_size=0x100000\0" \
"ramdisk_size=0x1E00000\0" \
"boot_size=0xF00000\0" \
"fdt_high=0x20000000\0" \
"initrd_high=0x20000000\0" \
......@@ -144,11 +154,11 @@
"bootm 0x3000000 0x2000000 0x2A00000; " \
"fi\0" \
"nandboot=echo Copying Linux from NAND flash to RAM... && " \
"nand read 0x3000000 0x100000 ${kernel_size} && " \
"nand read 0x2A00000 0x600000 ${devicetree_size} && " \
"nand read 0x3F00000 0x240000 ${kernel_size} && " \
"nand read 0x3E00000 0x140000 ${devicetree_size} && " \
"echo Copying ramdisk... && " \
"nand read 0x2000000 0x620000 ${ramdisk_size} && " \
"bootm 0x3000000 0x2000000 0x2A00000\0" \
"nand read 0x2000000 0x1240000 ${ramdisk_size} && " \
"bootm 0x3F00000 0x2000000 0x3E00000\0" \
"jtagboot=echo TFTPing Linux to RAM... && " \
"tftpboot 0x3000000 ${kernel_image} && " \
"tftpboot 0x2A00000 ${devicetree_image} && " \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment