1
0
Fork 0

mtd: rawnand: Move ->setup_data_interface() to nand_controller_ops

->setup_data_interface() is a controller specific method and should
thus be placed in nand_controller_ops.

In order to make that work with controllers that support keeping
pre-configured timings we need to add a new NAND_KEEP_TIMINGS flag to
inform the core it should skip the timings selection step.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Tested-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
hifive-unleashed-5.1
Boris Brezillon 2018-11-11 08:55:24 +01:00 committed by Miquel Raynal
parent f2abfeb207
commit 7a08dbaedd
15 changed files with 65 additions and 28 deletions

View File

@ -1479,8 +1479,8 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
chip->legacy.write_buf = atmel_nand_write_buf;
chip->legacy.select_chip = atmel_nand_select_chip;
if (nc->mck && nc->caps->ops->setup_data_interface)
chip->setup_data_interface = atmel_nand_setup_data_interface;
if (!nc->mck || !nc->caps->ops->setup_data_interface)
chip->options |= NAND_KEEP_TIMINGS;
/* Some NANDs require a longer delay than the default one (20us). */
chip->legacy.chip_delay = 40;
@ -1908,6 +1908,7 @@ static int atmel_nand_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops atmel_nand_controller_ops = {
.attach_chip = atmel_nand_attach_chip,
.setup_data_interface = atmel_nand_setup_data_interface,
};
static int atmel_nand_controller_init(struct atmel_nand_controller *nc,

View File

@ -1316,6 +1316,7 @@ static void denali_detach_chip(struct nand_chip *chip)
static const struct nand_controller_ops denali_controller_ops = {
.attach_chip = denali_attach_chip,
.detach_chip = denali_detach_chip,
.setup_data_interface = denali_setup_data_interface,
};
int denali_init(struct denali_nand_info *denali)
@ -1372,7 +1373,7 @@ int denali_init(struct denali_nand_info *denali)
/* clk rate info is needed for setup_data_interface */
if (denali->clk_rate && denali->clk_x_rate)
chip->setup_data_interface = denali_setup_data_interface;
chip->options |= NAND_KEEP_TIMINGS;
chip->dummy_controller.ops = &denali_controller_ops;
ret = nand_scan(chip, denali->max_banks);

View File

@ -996,6 +996,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
static const struct nand_controller_ops fsmc_nand_controller_ops = {
.attach_chip = fsmc_nand_attach_chip,
.exec_op = fsmc_exec_op,
.setup_data_interface = fsmc_setup_data_interface,
};
/*
@ -1108,10 +1109,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
}
}
if (host->dev_timings)
if (host->dev_timings) {
fsmc_nand_setup(host, host->dev_timings);
else
nand->setup_data_interface = fsmc_setup_data_interface;
nand->options |= NAND_KEEP_TIMINGS;
}
if (AMBA_REV_BITS(host->pid) >= 8) {
nand->ecc.read_page = fsmc_read_page_hwecc;

View File

@ -1889,6 +1889,7 @@ static int gpmi_nand_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops gpmi_nand_controller_ops = {
.attach_chip = gpmi_nand_attach_chip,
.setup_data_interface = gpmi_setup_data_interface,
};
static int gpmi_nand_init(struct gpmi_nand_data *this)
@ -1908,7 +1909,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
nand_set_controller_data(chip, this);
nand_set_flash_node(chip, this->pdev->dev.of_node);
chip->legacy.select_chip = gpmi_select_chip;
chip->setup_data_interface = gpmi_setup_data_interface;
chip->legacy.cmd_ctrl = gpmi_cmd_ctrl;
chip->legacy.dev_ready = gpmi_dev_ready;
chip->legacy.read_byte = gpmi_read_byte;

View File

@ -116,6 +116,18 @@ static inline int nand_exec_op(struct nand_chip *chip,
return chip->controller->ops->exec_op(chip, op, false);
}
static inline bool nand_has_setup_data_iface(struct nand_chip *chip)
{
if (!chip->controller || !chip->controller->ops ||
!chip->controller->ops->setup_data_interface)
return false;
if (chip->options & NAND_KEEP_TIMINGS)
return false;
return true;
}
/* BBT functions */
int nand_markbad_bbt(struct nand_chip *chip, loff_t offs);
int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs);

View File

@ -2506,6 +2506,7 @@ static int marvell_nand_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops marvell_nand_controller_ops = {
.attach_chip = marvell_nand_attach_chip,
.exec_op = marvell_nfc_exec_op,
.setup_data_interface = marvell_nfc_setup_data_interface,
};
static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
@ -2629,7 +2630,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
nand_set_flash_node(chip, np);
if (!of_property_read_bool(np, "marvell,nand-keep-config"))
chip->setup_data_interface = marvell_nfc_setup_data_interface;
chip->options |= NAND_KEEP_TIMINGS;
mtd = nand_to_mtd(chip);
mtd->dev.parent = dev;

View File

@ -1288,6 +1288,7 @@ static int mtk_nfc_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops mtk_nfc_controller_ops = {
.attach_chip = mtk_nfc_attach_chip,
.setup_data_interface = mtk_nfc_setup_data_interface,
};
static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
@ -1339,7 +1340,6 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
nand->legacy.read_byte = mtk_nfc_read_byte;
nand->legacy.read_buf = mtk_nfc_read_buf;
nand->legacy.cmd_ctrl = mtk_nfc_cmd_ctrl;
nand->setup_data_interface = mtk_nfc_setup_data_interface;
/* set default mode in case dt entry is missing */
nand->ecc.mode = NAND_ECC_HW;

View File

@ -1738,8 +1738,17 @@ static int mxcnd_attach_chip(struct nand_chip *chip)
return 0;
}
static int mxcnd_setup_data_interface(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf)
{
struct mxc_nand_host *host = nand_get_controller_data(chip);
return host->devtype_data->setup_data_interface(chip, chipnr, conf);
}
static const struct nand_controller_ops mxcnd_controller_ops = {
.attach_chip = mxcnd_attach_chip,
.setup_data_interface = mxcnd_setup_data_interface,
};
static int mxcnd_probe(struct platform_device *pdev)
@ -1800,7 +1809,8 @@ static int mxcnd_probe(struct platform_device *pdev)
if (err < 0)
return err;
this->setup_data_interface = host->devtype_data->setup_data_interface;
if (!host->devtype_data->setup_data_interface)
this->options |= NAND_KEEP_TIMINGS;
if (host->devtype_data->needs_ip) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View File

@ -807,7 +807,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
{
int ret;
if (!chip->setup_data_interface)
if (!nand_has_setup_data_iface(chip))
return 0;
/*
@ -825,7 +825,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
*/
onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface);
ret = chip->controller->ops->setup_data_interface(chip, chipnr,
&chip->data_interface);
if (ret)
pr_err("Failed to configure data interface to SDR timing mode 0\n");
@ -852,7 +853,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
};
int ret;
if (!chip->setup_data_interface)
if (!nand_has_setup_data_iface(chip))
return 0;
/* Change the mode on the chip side (if supported by the NAND chip) */
@ -866,7 +867,8 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
}
/* Change the mode on the controller side */
ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface);
ret = chip->controller->ops->setup_data_interface(chip, chipnr,
&chip->data_interface);
if (ret)
return ret;
@ -921,7 +923,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
{
int modes, mode, ret;
if (!chip->setup_data_interface)
if (!nand_has_setup_data_iface(chip))
return 0;
/*
@ -947,7 +949,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
* Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
* controller supports the requested timings.
*/
ret = chip->setup_data_interface(chip,
ret = chip->controller->ops->setup_data_interface(chip,
NAND_DATA_IFACE_CHECK_ONLY,
&chip->data_interface);
if (!ret) {

View File

@ -364,7 +364,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
* Wait tCCS_min if it is correctly defined, otherwise wait 500ns
* (which should be safe for all NANDs).
*/
if (chip->setup_data_interface)
if (nand_has_setup_data_iface(chip))
ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
else
ndelay(500);

View File

@ -876,8 +876,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
* let's keep behavior unchanged for legacy boards booting via pdata and
* auto-detect timings only when booting with a device tree.
*/
if (np)
chip->setup_data_interface = s3c2410_nand_setup_data_interface;
if (!np)
chip->options |= NAND_KEEP_TIMINGS;
switch (info->cpu_type) {
case TYPE_S3C2410:
@ -1011,6 +1011,7 @@ static int s3c2410_nand_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
.attach_chip = s3c2410_nand_attach_chip,
.setup_data_interface = s3c2410_nand_setup_data_interface,
};
static const struct of_device_id s3c24xx_nand_dt_ids[] = {

View File

@ -1847,6 +1847,7 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand)
static const struct nand_controller_ops sunxi_nand_controller_ops = {
.attach_chip = sunxi_nand_attach_chip,
.setup_data_interface = sunxi_nfc_setup_data_interface,
};
static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
@ -1927,7 +1928,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
nand->legacy.read_buf = sunxi_nfc_read_buf;
nand->legacy.write_buf = sunxi_nfc_write_buf;
nand->legacy.read_byte = sunxi_nfc_read_byte;
nand->setup_data_interface = sunxi_nfc_setup_data_interface;
mtd = nand_to_mtd(nand);
mtd->dev.parent = dev;

View File

@ -530,6 +530,7 @@ static int tango_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops tango_controller_ops = {
.attach_chip = tango_attach_chip,
.setup_data_interface = tango_set_timings,
};
static int chip_init(struct device *dev, struct device_node *np)
@ -570,7 +571,6 @@ static int chip_init(struct device *dev, struct device_node *np)
chip->legacy.select_chip = tango_select_chip;
chip->legacy.cmd_ctrl = tango_cmd_ctrl;
chip->legacy.dev_ready = tango_dev_ready;
chip->setup_data_interface = tango_set_timings;
chip->options = NAND_USE_BOUNCE_BUFFER |
NAND_NO_SUBPAGE_WRITE |
NAND_WAIT_TCCS;

View File

@ -1051,6 +1051,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip)
static const struct nand_controller_ops tegra_nand_controller_ops = {
.attach_chip = &tegra_nand_attach_chip,
.exec_op = tegra_nand_exec_op,
.setup_data_interface = tegra_nand_setup_data_interface,
};
static int tegra_nand_chips_init(struct device *dev,
@ -1113,7 +1114,6 @@ static int tegra_nand_chips_init(struct device *dev,
mtd->name = "tegra_nand";
chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER;
chip->setup_data_interface = tegra_nand_setup_data_interface;
ret = nand_scan(chip, 1);
if (ret)

View File

@ -203,6 +203,13 @@ enum nand_ecc_algo {
*/
#define NAND_IS_BOOT_MEDIUM 0x00400000
/*
* Do not try to tweak the timings at runtime. This is needed when the
* controller initializes the timings on itself or when it relies on
* configuration done by the bootloader.
*/
#define NAND_KEEP_TIMINGS 0x00800000
/* Cell info constants */
#define NAND_CI_CHIPNR_MSK 0x03
#define NAND_CI_CELLTYPE_MSK 0x0C
@ -871,6 +878,11 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
* This method replaces chip->legacy.cmdfunc(),
* chip->legacy.{read,write}_{buf,byte,word}(),
* chip->legacy.dev_ready() and chip->legacy.waifunc().
* @setup_data_interface: setup the data interface and timing. If
* chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this
* means the configuration should not be applied but
* only checked.
* This hook is optional.
*/
struct nand_controller_ops {
int (*attach_chip)(struct nand_chip *chip);
@ -878,6 +890,8 @@ struct nand_controller_ops {
int (*exec_op)(struct nand_chip *chip,
const struct nand_operation *op,
bool check_only);
int (*setup_data_interface)(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf);
};
/**
@ -1019,10 +1033,6 @@ struct nand_legacy {
* cur_cs < numchips. NAND Controller drivers should not
* modify this value, but they're allowed to read it.
* @read_retries: [INTERN] the number of read retry modes supported
* @setup_data_interface: [OPTIONAL] setup the data interface and timing. If
* chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this
* means the configuration should not be applied but
* only checked.
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
* lookup.
@ -1044,8 +1054,6 @@ struct nand_chip {
struct nand_legacy legacy;
int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
int (*setup_data_interface)(struct nand_chip *chip, int chipnr,
const struct nand_data_interface *conf);
unsigned int options;
unsigned int bbt_options;