mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-07 05:13:21 +09:00
![Shyam Saini](/assets/img/avatar_default.png)
Writing/updating boot image in nand device is not straight forward in i.MX6 platform and it requires boot control block(BCB) to be configured. It becomes difficult to use uboot 'nand' command to write BCB since it requires platform specific attributes need to be taken care of. It is even difficult to use existing msx-nand.c driver by incorporating BCB attributes like mxs_dma_desc does because it requires change in mtd and nand command. So, cmd_nandbcb implemented in arch/arm/mach-imx BCB contains two data structures, Firmware Configuration Block(FCB) and Discovered Bad Block Table(DBBT). FCB has nand timings, DBBT search area, page address of firmware. On summary, nandbcb update will - erase the entire partition - create BCB by creating 2 FCB/DBBT block followed by 1 FW block based on partition size and erasesize. - fill FCB/DBBT structures - write FW/SPL on FW1 - write FCB/DBBT in first 2 blocks for nand boot, up on reset bootrom look for FCB structure in first block's if FCB found the nand timings are loaded for further reads. once FCB read done, DTTB will load and finally firmware will be loaded which is boot image. Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage information. Reviewed-by: Stefano Babic <sbabic@denx.de> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> Signed-off-by: Sergey Kubushyn <ksi@koi8.net> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
95 lines
2.0 KiB
C
95 lines
2.0 KiB
C
/*
|
|
* NXP GPMI NAND flash driver (DT initialization)
|
|
*
|
|
* Copyright (C) 2018 Toradex
|
|
* Authors:
|
|
* Stefan Agner <stefan.agner@toradex.com>
|
|
*
|
|
* Based on denali_dt.c
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <dm.h>
|
|
#include <linux/io.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/printk.h>
|
|
|
|
#include <mxs_nand.h>
|
|
|
|
struct mxs_nand_dt_data {
|
|
unsigned int max_ecc_strength_supported;
|
|
};
|
|
|
|
static const struct mxs_nand_dt_data mxs_nand_imx6q_data = {
|
|
.max_ecc_strength_supported = 40,
|
|
};
|
|
|
|
static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
|
|
.max_ecc_strength_supported = 62,
|
|
};
|
|
|
|
static const struct udevice_id mxs_nand_dt_ids[] = {
|
|
{
|
|
.compatible = "fsl,imx6q-gpmi-nand",
|
|
.data = (unsigned long)&mxs_nand_imx6q_data,
|
|
},
|
|
{
|
|
.compatible = "fsl,imx7d-gpmi-nand",
|
|
.data = (unsigned long)&mxs_nand_imx7d_data,
|
|
},
|
|
{ /* sentinel */ }
|
|
};
|
|
|
|
static int mxs_nand_dt_probe(struct udevice *dev)
|
|
{
|
|
struct mxs_nand_info *info = dev_get_priv(dev);
|
|
const struct mxs_nand_dt_data *data;
|
|
struct resource res;
|
|
int ret;
|
|
|
|
data = (void *)dev_get_driver_data(dev);
|
|
if (data)
|
|
info->max_ecc_strength_supported = data->max_ecc_strength_supported;
|
|
|
|
info->dev = dev;
|
|
|
|
ret = dev_read_resource_byname(dev, "gpmi-nand", &res);
|
|
if (ret)
|
|
return ret;
|
|
|
|
info->gpmi_regs = devm_ioremap(dev, res.start, resource_size(&res));
|
|
|
|
|
|
ret = dev_read_resource_byname(dev, "bch", &res);
|
|
if (ret)
|
|
return ret;
|
|
|
|
info->bch_regs = devm_ioremap(dev, res.start, resource_size(&res));
|
|
|
|
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
|
|
|
|
return mxs_nand_init_ctrl(info);
|
|
}
|
|
|
|
U_BOOT_DRIVER(mxs_nand_dt) = {
|
|
.name = "mxs-nand-dt",
|
|
.id = UCLASS_MTD,
|
|
.of_match = mxs_nand_dt_ids,
|
|
.probe = mxs_nand_dt_probe,
|
|
.priv_auto_alloc_size = sizeof(struct mxs_nand_info),
|
|
};
|
|
|
|
void board_nand_init(void)
|
|
{
|
|
struct udevice *dev;
|
|
int ret;
|
|
|
|
ret = uclass_get_device_by_driver(UCLASS_MTD,
|
|
DM_GET_DRIVER(mxs_nand_dt),
|
|
&dev);
|
|
if (ret && ret != -ENODEV)
|
|
pr_err("Failed to initialize MXS NAND controller. (error %d)\n",
|
|
ret);
|
|
}
|