Commit 104e442a authored by Boris Brezillon's avatar Boris Brezillon

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: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent ebb528d9
...@@ -388,9 +388,8 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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); ...@@ -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 { ...@@ -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 { ...@@ -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;
......
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