u-boot/drivers/mtd/nand/denali_dt.c
Masahiro Yamada 6c71b6f454 mtd: nand: denali: allow to override corrupted revision register
The Denali IP does not update the revision register properly.
Allow to override it with SoC data associated with compatible.

Linux had already finished big surgery of this driver, but I need
to prepare the NAND core before the full sync of the driver.
For now, I am fixing the most fatal problem on UniPhier platform.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-09-18 20:26:00 +09:00

98 lines
2.2 KiB
C

/*
* Copyright (C) 2017 Socionext Inc.
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include "denali.h"
struct denali_dt_data {
unsigned int revision;
unsigned int caps;
};
static const struct denali_dt_data denali_socfpga_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP,
};
static const struct denali_dt_data denali_uniphier_v5a_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT,
};
static const struct denali_dt_data denali_uniphier_v5b_data = {
.revision = 0x0501,
.caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT,
};
static const struct udevice_id denali_nand_dt_ids[] = {
{
.compatible = "altr,socfpga-denali-nand",
.data = (unsigned long)&denali_socfpga_data,
},
{
.compatible = "socionext,uniphier-denali-nand-v5a",
.data = (unsigned long)&denali_uniphier_v5a_data,
},
{
.compatible = "socionext,uniphier-denali-nand-v5b",
.data = (unsigned long)&denali_uniphier_v5b_data,
},
{ /* sentinel */ }
};
static int denali_dt_probe(struct udevice *dev)
{
struct denali_nand_info *denali = dev_get_priv(dev);
const struct denali_dt_data *data;
struct resource res;
int ret;
data = (void *)dev_get_driver_data(dev);
if (data) {
denali->revision = data->revision;
denali->caps = data->caps;
}
ret = dev_read_resource_byname(dev, "denali_reg", &res);
if (ret)
return ret;
denali->flash_reg = devm_ioremap(dev, res.start, resource_size(&res));
ret = dev_read_resource_byname(dev, "nand_data", &res);
if (ret)
return ret;
denali->flash_mem = devm_ioremap(dev, res.start, resource_size(&res));
return denali_init(denali);
}
U_BOOT_DRIVER(denali_nand_dt) = {
.name = "denali-nand-dt",
.id = UCLASS_MISC,
.of_match = denali_nand_dt_ids,
.probe = denali_dt_probe,
.priv_auto_alloc_size = sizeof(struct denali_nand_info),
};
void board_nand_init(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(denali_nand_dt),
&dev);
if (ret && ret != -ENODEV)
printf("Failed to initialize Denali NAND controller. (error %d)\n",
ret);
}