mtd: nand: Pass the CS line to ->setup_data_interface()
Some NAND controllers can assign different NAND timings to different CS lines. Pass the CS line information to ->setup_data_interface() so that the NAND controller driver knows which CS line is concerned by the setup_data_interface() request. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
This commit is contained in:
Родитель
ebb528d978
Коммит
104e442a67
|
@ -388,9 +388,8 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsmc_setup_data_interface(struct mtd_info *mtd,
|
static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf)
|
||||||
bool check_only)
|
|
||||||
{
|
{
|
||||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||||
struct fsmc_nand_data *host = nand_get_controller_data(nand);
|
struct fsmc_nand_data *host = nand_get_controller_data(nand);
|
||||||
|
@ -406,7 +405,7 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (check_only)
|
if (csline == NAND_DATA_IFACE_CHECK_ONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fsmc_nand_setup(host, &tims);
|
fsmc_nand_setup(host, &tims);
|
||||||
|
|
|
@ -152,9 +152,8 @@ struct mxc_nand_devtype_data {
|
||||||
void (*select_chip)(struct mtd_info *mtd, int chip);
|
void (*select_chip)(struct mtd_info *mtd, int chip);
|
||||||
int (*correct_data)(struct mtd_info *mtd, u_char *dat,
|
int (*correct_data)(struct mtd_info *mtd, u_char *dat,
|
||||||
u_char *read_ecc, u_char *calc_ecc);
|
u_char *read_ecc, u_char *calc_ecc);
|
||||||
int (*setup_data_interface)(struct mtd_info *mtd,
|
int (*setup_data_interface)(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf);
|
||||||
bool check_only);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
|
* On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
|
||||||
|
@ -1015,9 +1014,8 @@ static void preset_v1(struct mtd_info *mtd)
|
||||||
writew(0x4, NFC_V1_V2_WRPROT);
|
writew(0x4, NFC_V1_V2_WRPROT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
|
static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf)
|
||||||
bool check_only)
|
|
||||||
{
|
{
|
||||||
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
struct nand_chip *nand_chip = mtd_to_nand(mtd);
|
||||||
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
|
||||||
|
@ -1075,7 +1073,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_only)
|
if (csline == NAND_DATA_IFACE_CHECK_ONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = clk_set_rate(host->clk, rate);
|
ret = clk_set_rate(host->clk, rate);
|
||||||
|
|
|
@ -1042,12 +1042,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||||
/**
|
/**
|
||||||
* nand_reset_data_interface - Reset data interface and timings
|
* nand_reset_data_interface - Reset data interface and timings
|
||||||
* @chip: The NAND chip
|
* @chip: The NAND chip
|
||||||
|
* @chipnr: Internal die id
|
||||||
*
|
*
|
||||||
* Reset the Data interface and timings to ONFI mode 0.
|
* Reset the Data interface and timings to ONFI mode 0.
|
||||||
*
|
*
|
||||||
* Returns 0 for success or negative error code otherwise.
|
* Returns 0 for success or negative error code otherwise.
|
||||||
*/
|
*/
|
||||||
static int nand_reset_data_interface(struct nand_chip *chip)
|
static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
const struct nand_data_interface *conf;
|
const struct nand_data_interface *conf;
|
||||||
|
@ -1071,7 +1072,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conf = nand_get_default_data_interface();
|
conf = nand_get_default_data_interface();
|
||||||
ret = chip->setup_data_interface(mtd, conf, false);
|
ret = chip->setup_data_interface(mtd, chipnr, conf);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_err("Failed to configure data interface to SDR timing mode 0\n");
|
pr_err("Failed to configure data interface to SDR timing mode 0\n");
|
||||||
|
|
||||||
|
@ -1081,6 +1082,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
|
||||||
/**
|
/**
|
||||||
* nand_setup_data_interface - Setup the best data interface and timings
|
* nand_setup_data_interface - Setup the best data interface and timings
|
||||||
* @chip: The NAND chip
|
* @chip: The NAND chip
|
||||||
|
* @chipnr: Internal die id
|
||||||
*
|
*
|
||||||
* Find and configure the best data interface and NAND timings supported by
|
* Find and configure the best data interface and NAND timings supported by
|
||||||
* the chip and the driver.
|
* the chip and the driver.
|
||||||
|
@ -1090,7 +1092,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
|
||||||
*
|
*
|
||||||
* Returns 0 for success or negative error code otherwise.
|
* Returns 0 for success or negative error code otherwise.
|
||||||
*/
|
*/
|
||||||
static int nand_setup_data_interface(struct nand_chip *chip)
|
static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1114,7 +1116,7 @@ static int nand_setup_data_interface(struct nand_chip *chip)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = chip->setup_data_interface(mtd, chip->data_interface, false);
|
ret = chip->setup_data_interface(mtd, chipnr, chip->data_interface);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1165,8 +1167,10 @@ static int nand_init_data_interface(struct nand_chip *chip)
|
||||||
if (ret)
|
if (ret)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = chip->setup_data_interface(mtd, chip->data_interface,
|
/* Pass -1 to only */
|
||||||
true);
|
ret = chip->setup_data_interface(mtd,
|
||||||
|
NAND_DATA_IFACE_CHECK_ONLY,
|
||||||
|
chip->data_interface);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
chip->onfi_timing_mode_default = mode;
|
chip->onfi_timing_mode_default = mode;
|
||||||
break;
|
break;
|
||||||
|
@ -1193,7 +1197,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nand_reset_data_interface(chip);
|
ret = nand_reset_data_interface(chip, chipnr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1206,7 +1210,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
|
||||||
chip->select_chip(mtd, -1);
|
chip->select_chip(mtd, -1);
|
||||||
|
|
||||||
chip->select_chip(mtd, chipnr);
|
chip->select_chip(mtd, chipnr);
|
||||||
ret = nand_setup_data_interface(chip);
|
ret = nand_setup_data_interface(chip, chipnr);
|
||||||
chip->select_chip(mtd, -1);
|
chip->select_chip(mtd, -1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4396,7 +4400,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
||||||
* For the other dies, nand_reset() will automatically switch to the
|
* For the other dies, nand_reset() will automatically switch to the
|
||||||
* best mode for us.
|
* best mode for us.
|
||||||
*/
|
*/
|
||||||
ret = nand_setup_data_interface(chip);
|
ret = nand_setup_data_interface(chip, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -812,9 +812,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd,
|
static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf)
|
||||||
bool check_only)
|
|
||||||
{
|
{
|
||||||
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
||||||
struct s3c2410_platform_nand *pdata = info->platform;
|
struct s3c2410_platform_nand *pdata = info->platform;
|
||||||
|
|
|
@ -1592,9 +1592,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
|
||||||
#define sunxi_nand_lookup_timing(l, p, c) \
|
#define sunxi_nand_lookup_timing(l, p, c) \
|
||||||
_sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
|
_sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
|
||||||
|
|
||||||
static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
|
static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf)
|
||||||
bool check_only)
|
|
||||||
{
|
{
|
||||||
struct nand_chip *nand = mtd_to_nand(mtd);
|
struct nand_chip *nand = mtd_to_nand(mtd);
|
||||||
struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
|
struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
|
||||||
|
@ -1707,7 +1706,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
|
||||||
return tRHW;
|
return tRHW;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_only)
|
if (csline == NAND_DATA_IFACE_CHECK_ONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -476,9 +476,8 @@ static u32 to_ticks(int kHz, int ps)
|
||||||
return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC);
|
return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tango_set_timings(struct mtd_info *mtd,
|
static int tango_set_timings(struct mtd_info *mtd, int csline,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf)
|
||||||
bool check_only)
|
|
||||||
{
|
{
|
||||||
const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
|
const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
|
||||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||||
|
@ -490,7 +489,7 @@ static int tango_set_timings(struct mtd_info *mtd,
|
||||||
if (IS_ERR(sdr))
|
if (IS_ERR(sdr))
|
||||||
return PTR_ERR(sdr);
|
return PTR_ERR(sdr);
|
||||||
|
|
||||||
if (check_only)
|
if (csline == NAND_DATA_IFACE_CHECK_ONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Trdy = to_ticks(kHz, sdr->tCEA_max - sdr->tREA_max);
|
Trdy = to_ticks(kHz, sdr->tCEA_max - sdr->tREA_max);
|
||||||
|
|
|
@ -107,6 +107,8 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||||
#define NAND_STATUS_READY 0x40
|
#define NAND_STATUS_READY 0x40
|
||||||
#define NAND_STATUS_WP 0x80
|
#define NAND_STATUS_WP 0x80
|
||||||
|
|
||||||
|
#define NAND_DATA_IFACE_CHECK_ONLY -1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants for ECC_MODES
|
* Constants for ECC_MODES
|
||||||
*/
|
*/
|
||||||
|
@ -818,7 +820,10 @@ struct nand_manufacturer_ops {
|
||||||
* @read_retries: [INTERN] the number of read retry modes supported
|
* @read_retries: [INTERN] the number of read retry modes supported
|
||||||
* @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
|
* @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
|
||||||
* @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
|
* @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
|
||||||
* @setup_data_interface: [OPTIONAL] setup the data interface and timing
|
* @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: [INTERN] bad block table pointer
|
||||||
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
|
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
|
||||||
* lookup.
|
* lookup.
|
||||||
|
@ -862,9 +867,8 @@ struct nand_chip {
|
||||||
int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
|
int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int feature_addr, uint8_t *subfeature_para);
|
int feature_addr, uint8_t *subfeature_para);
|
||||||
int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
|
int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
|
||||||
int (*setup_data_interface)(struct mtd_info *mtd,
|
int (*setup_data_interface)(struct mtd_info *mtd, int chipnr,
|
||||||
const struct nand_data_interface *conf,
|
const struct nand_data_interface *conf);
|
||||||
bool check_only);
|
|
||||||
|
|
||||||
|
|
||||||
int chip_delay;
|
int chip_delay;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче