From: Sascha Hauer <s.hauer@pengutronix.de> To: linux-mtd@lists.infradead.org Cc: Boris Brezillon <boris.brezillon@free-electrons.com>, kernel@pengutronix.de, linux-arm-kernel@lists.infradead.org, Sascha Hauer <s.hauer@pengutronix.de> Subject: [PATCH 7/7] mtd: nand: mxc: Add timing setup for v2 controllers Date: Tue, 6 Sep 2016 12:39:15 +0200 [thread overview] Message-ID: <1473158355-22451-8-git-send-email-s.hauer@pengutronix.de> (raw) In-Reply-To: <1473158355-22451-1-git-send-email-s.hauer@pengutronix.de> So far we relied on reset default or the bootloader to configure a suitable clk rate for the Nand controller. This works but we can optimize the timing for better performance. This sets the clk rate for v2 controllers (i.MX25/35) based on the timing mode read from the ONFI parameter page. This may also enable the symmetric mode (aks EDO mode) if necessary which reads one word per clock cycle. Tested on an i.MX25 with a Micron MT29F4G08ABBDAHC attached. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mtd/nand/mxc_nand.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 1db8299..1fe3484 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -152,6 +152,9 @@ struct mxc_nand_devtype_data { void (*select_chip)(struct mtd_info *mtd, int chip); int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); + int (*setup_data_interface)(struct mtd_info *mtd, + const struct nand_data_interface *conf, + bool check_only); /* * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked @@ -1012,6 +1015,83 @@ static void preset_v1(struct mtd_info *mtd) writew(0x4, NFC_V1_V2_WRPROT); } +static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, + const struct nand_data_interface *conf, + bool check_only) +{ + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); + int tRC_min_ns, tRC_ps, ret; + unsigned long rate, rate_round; + const struct nand_sdr_timings *timings; + uint16_t config1; + + if (conf->type != NAND_SDR_IFACE) + return -ENOTSUPP; + + config1 = readw(NFC_V1_V2_CONFIG1); + + timings = &conf->timings.sdr; + + tRC_min_ns = timings->tRC_min / 1000; + rate = 1000000000 / tRC_min_ns; + + /* + * For tRC < 30ns we have to use EDO mode. In this case the controller + * does one access per clock cycle. Otherwise the controller does one + * access in two clock cycles, thus we have to double the rate to the + * controller. + */ + if (tRC_min_ns < 30) { + rate_round = clk_round_rate(host->clk, rate); + config1 |= NFC_V2_CONFIG1_ONE_CYCLE; + tRC_ps = 1000000000 / (rate_round / 1000); + } else { + rate *= 2; + rate_round = clk_round_rate(host->clk, rate); + config1 &= ~NFC_V2_CONFIG1_ONE_CYCLE; + tRC_ps = 1000000000 / (rate_round / 1000 / 2); + } + + /* + * The timing values compared against are from the i.MX25 Automotive + * datasheet, Table 50. NFC Timing Parameters + */ + if (timings->tCLS_min > tRC_ps - 1000 || + timings->tCLH_min > tRC_ps - 2000 || + timings->tCS_min > tRC_ps - 1000 || + timings->tCH_min > tRC_ps - 2000 || + timings->tWP_min > tRC_ps - 1500 || + timings->tALS_min > tRC_ps || + timings->tALH_min > tRC_ps - 3000 || + timings->tDS_min > tRC_ps || + timings->tDH_min > tRC_ps - 5000 || + timings->tWC_min > 2 * tRC_ps || + timings->tWH_min > tRC_ps - 2500 || + timings->tRR_min > 6 * tRC_ps || + timings->tRP_min > 3 * tRC_ps / 2 || + timings->tRC_min > 2 * tRC_ps || + timings->tREH_min > (tRC_ps / 2) - 2500) { + dev_dbg(host->dev, "Timing out of bounds\n"); + return -EINVAL; + } + + if (check_only) + return 0; + + ret = clk_set_rate(host->clk, rate); + if (ret) + return ret; + + writew(config1, NFC_V1_V2_CONFIG1); + + dev_dbg(host->dev, "Setting rate to %ldHz, %s mode\n", rate_round, + config1 & NFC_V2_CONFIG1_ONE_CYCLE ? "One cycle (EDO)" : + "normal"); + + return 0; +} + static void preset_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); @@ -1378,6 +1458,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { .ooblayout = &mxc_v2_ooblayout_ops, .select_chip = mxc_nand_select_chip_v2, .correct_data = mxc_nand_correct_data_v2_v3, + .setup_data_interface = mxc_nand_v2_setup_data_interface, .irqpending_quirk = 0, .needs_ip = 0, .regs_offset = 0x1e00, @@ -1586,6 +1667,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->needs_ip) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs_ip = devm_ioremap_resource(&pdev->dev, res); -- 2.8.1
WARNING: multiple messages have this Message-ID (diff)
From: s.hauer@pengutronix.de (Sascha Hauer) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 7/7] mtd: nand: mxc: Add timing setup for v2 controllers Date: Tue, 6 Sep 2016 12:39:15 +0200 [thread overview] Message-ID: <1473158355-22451-8-git-send-email-s.hauer@pengutronix.de> (raw) In-Reply-To: <1473158355-22451-1-git-send-email-s.hauer@pengutronix.de> So far we relied on reset default or the bootloader to configure a suitable clk rate for the Nand controller. This works but we can optimize the timing for better performance. This sets the clk rate for v2 controllers (i.MX25/35) based on the timing mode read from the ONFI parameter page. This may also enable the symmetric mode (aks EDO mode) if necessary which reads one word per clock cycle. Tested on an i.MX25 with a Micron MT29F4G08ABBDAHC attached. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mtd/nand/mxc_nand.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 1db8299..1fe3484 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -152,6 +152,9 @@ struct mxc_nand_devtype_data { void (*select_chip)(struct mtd_info *mtd, int chip); int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); + int (*setup_data_interface)(struct mtd_info *mtd, + const struct nand_data_interface *conf, + bool check_only); /* * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked @@ -1012,6 +1015,83 @@ static void preset_v1(struct mtd_info *mtd) writew(0x4, NFC_V1_V2_WRPROT); } +static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, + const struct nand_data_interface *conf, + bool check_only) +{ + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); + int tRC_min_ns, tRC_ps, ret; + unsigned long rate, rate_round; + const struct nand_sdr_timings *timings; + uint16_t config1; + + if (conf->type != NAND_SDR_IFACE) + return -ENOTSUPP; + + config1 = readw(NFC_V1_V2_CONFIG1); + + timings = &conf->timings.sdr; + + tRC_min_ns = timings->tRC_min / 1000; + rate = 1000000000 / tRC_min_ns; + + /* + * For tRC < 30ns we have to use EDO mode. In this case the controller + * does one access per clock cycle. Otherwise the controller does one + * access in two clock cycles, thus we have to double the rate to the + * controller. + */ + if (tRC_min_ns < 30) { + rate_round = clk_round_rate(host->clk, rate); + config1 |= NFC_V2_CONFIG1_ONE_CYCLE; + tRC_ps = 1000000000 / (rate_round / 1000); + } else { + rate *= 2; + rate_round = clk_round_rate(host->clk, rate); + config1 &= ~NFC_V2_CONFIG1_ONE_CYCLE; + tRC_ps = 1000000000 / (rate_round / 1000 / 2); + } + + /* + * The timing values compared against are from the i.MX25 Automotive + * datasheet, Table 50. NFC Timing Parameters + */ + if (timings->tCLS_min > tRC_ps - 1000 || + timings->tCLH_min > tRC_ps - 2000 || + timings->tCS_min > tRC_ps - 1000 || + timings->tCH_min > tRC_ps - 2000 || + timings->tWP_min > tRC_ps - 1500 || + timings->tALS_min > tRC_ps || + timings->tALH_min > tRC_ps - 3000 || + timings->tDS_min > tRC_ps || + timings->tDH_min > tRC_ps - 5000 || + timings->tWC_min > 2 * tRC_ps || + timings->tWH_min > tRC_ps - 2500 || + timings->tRR_min > 6 * tRC_ps || + timings->tRP_min > 3 * tRC_ps / 2 || + timings->tRC_min > 2 * tRC_ps || + timings->tREH_min > (tRC_ps / 2) - 2500) { + dev_dbg(host->dev, "Timing out of bounds\n"); + return -EINVAL; + } + + if (check_only) + return 0; + + ret = clk_set_rate(host->clk, rate); + if (ret) + return ret; + + writew(config1, NFC_V1_V2_CONFIG1); + + dev_dbg(host->dev, "Setting rate to %ldHz, %s mode\n", rate_round, + config1 & NFC_V2_CONFIG1_ONE_CYCLE ? "One cycle (EDO)" : + "normal"); + + return 0; +} + static void preset_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); @@ -1378,6 +1458,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { .ooblayout = &mxc_v2_ooblayout_ops, .select_chip = mxc_nand_select_chip_v2, .correct_data = mxc_nand_correct_data_v2_v3, + .setup_data_interface = mxc_nand_v2_setup_data_interface, .irqpending_quirk = 0, .needs_ip = 0, .regs_offset = 0x1e00, @@ -1586,6 +1667,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->needs_ip) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs_ip = devm_ioremap_resource(&pdev->dev, res); -- 2.8.1
next prev parent reply other threads:[~2016-09-06 10:39 UTC|newest] Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-09-06 10:39 [PATCH v2] mtd: nand: automate NAND timings selection Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 10:39 ` [PATCH 1/7] mtd: nand: Create a NAND reset function Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 11:18 ` Boris Brezillon 2016-09-06 11:18 ` Boris Brezillon 2016-09-06 13:02 ` Sascha Hauer 2016-09-06 13:02 ` Sascha Hauer 2016-09-06 13:06 ` Boris Brezillon 2016-09-06 13:06 ` Boris Brezillon 2016-09-06 10:39 ` [PATCH 2/7] mtd: nand: Introduce nand_data_interface Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 11:21 ` Boris Brezillon 2016-09-06 11:21 ` Boris Brezillon 2016-09-06 13:34 ` Sascha Hauer 2016-09-06 13:34 ` Sascha Hauer 2016-09-06 13:46 ` Boris Brezillon 2016-09-06 13:46 ` Boris Brezillon 2016-09-06 14:09 ` Sascha Hauer 2016-09-06 14:09 ` Sascha Hauer 2016-09-06 10:39 ` [PATCH 3/7] mtd: nand: convert ONFI mode into data interface Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 11:27 ` Boris Brezillon 2016-09-06 11:27 ` Boris Brezillon 2016-09-06 12:15 ` Boris Brezillon 2016-09-06 12:15 ` Boris Brezillon 2016-09-06 10:39 ` [PATCH 4/7] mtd: nand: automate NAND timings selection Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 11:58 ` Boris Brezillon 2016-09-06 11:58 ` Boris Brezillon 2016-09-06 14:08 ` Sascha Hauer 2016-09-06 14:08 ` Sascha Hauer 2016-09-06 14:50 ` Boris Brezillon 2016-09-06 14:50 ` Boris Brezillon 2016-09-06 15:04 ` Sascha Hauer 2016-09-06 15:04 ` Sascha Hauer 2016-09-06 15:15 ` Boris Brezillon 2016-09-06 15:15 ` Boris Brezillon 2016-09-06 10:39 ` [PATCH 5/7] mtd: nand: sunxi: switch from manual to automated timing config Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 12:01 ` Boris Brezillon 2016-09-06 12:01 ` Boris Brezillon 2016-09-06 10:39 ` [PATCH 6/7] mtd: nand: mxc: implement onfi get/set features Sascha Hauer 2016-09-06 10:39 ` Sascha Hauer 2016-09-06 12:05 ` Boris Brezillon 2016-09-06 12:05 ` Boris Brezillon 2016-09-06 12:47 ` Sascha Hauer 2016-09-06 12:47 ` Sascha Hauer 2016-09-06 12:52 ` Boris Brezillon 2016-09-06 12:52 ` Boris Brezillon 2016-09-06 10:39 ` Sascha Hauer [this message] 2016-09-06 10:39 ` [PATCH 7/7] mtd: nand: mxc: Add timing setup for v2 controllers Sascha Hauer
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1473158355-22451-8-git-send-email-s.hauer@pengutronix.de \ --to=s.hauer@pengutronix.de \ --cc=boris.brezillon@free-electrons.com \ --cc=kernel@pengutronix.de \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-mtd@lists.infradead.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.