Commit 27698cd2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mtd/fixes-for-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull mtd fixes from Miquel Raynal:
 "MTD fixes:

   - dataflash: Add device-tree SPI IDs to avoid new warnings

  Raw NAND fixes:

   - Fix nand_choose_best_timings() on unsupported interface

   - Fix nand_erase_op delay (wrong unit)

   - fsmc:
      - Fix timing computation
      - Take instruction delay into account

   - denali:
      - Add the dependency on HAS_IOMEM to silence robots"

* tag 'mtd/fixes-for-5.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: dataflash: Add device-tree SPI IDs
  mtd: rawnand: fsmc: Fix timing computation
  mtd: rawnand: fsmc: Take instruction delay into account
  mtd: rawnand: Fix nand_choose_best_timings() on unsupported interface
  mtd: rawnand: Fix nand_erase_op delay
  mtd: rawnand: denali: Add the dependency on HAS_IOMEM
parents 03090cc7 27a030e8
...@@ -96,6 +96,13 @@ struct dataflash { ...@@ -96,6 +96,13 @@ struct dataflash {
struct mtd_info mtd; struct mtd_info mtd;
}; };
static const struct spi_device_id dataflash_dev_ids[] = {
{ "at45" },
{ "dataflash" },
{ },
};
MODULE_DEVICE_TABLE(spi, dataflash_dev_ids);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id dataflash_dt_ids[] = { static const struct of_device_id dataflash_dt_ids[] = {
{ .compatible = "atmel,at45", }, { .compatible = "atmel,at45", },
...@@ -927,6 +934,7 @@ static struct spi_driver dataflash_driver = { ...@@ -927,6 +934,7 @@ static struct spi_driver dataflash_driver = {
.name = "mtd_dataflash", .name = "mtd_dataflash",
.of_match_table = of_match_ptr(dataflash_dt_ids), .of_match_table = of_match_ptr(dataflash_dt_ids),
}, },
.id_table = dataflash_dev_ids,
.probe = dataflash_probe, .probe = dataflash_probe,
.remove = dataflash_remove, .remove = dataflash_remove,
......
...@@ -26,7 +26,7 @@ config MTD_NAND_DENALI_PCI ...@@ -26,7 +26,7 @@ config MTD_NAND_DENALI_PCI
config MTD_NAND_DENALI_DT config MTD_NAND_DENALI_DT
tristate "Denali NAND controller as a DT device" tristate "Denali NAND controller as a DT device"
select MTD_NAND_DENALI select MTD_NAND_DENALI
depends on HAS_DMA && HAVE_CLK && OF depends on HAS_DMA && HAVE_CLK && OF && HAS_IOMEM
help help
Enable the driver for NAND flash on platforms using a Denali NAND Enable the driver for NAND flash on platforms using a Denali NAND
controller as a DT device. controller as a DT device.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/delay.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -93,6 +94,14 @@ ...@@ -93,6 +94,14 @@
#define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
/*
* According to SPEAr300 Reference Manual (RM0082)
* TOUDEL = 7ns (Output delay from the flip-flops to the board)
* TINDEL = 5ns (Input delay from the board to the flipflop)
*/
#define TOUTDEL 7000
#define TINDEL 5000
struct fsmc_nand_timings { struct fsmc_nand_timings {
u8 tclr; u8 tclr;
u8 tar; u8 tar;
...@@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, ...@@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
{ {
unsigned long hclk = clk_get_rate(host->clk); unsigned long hclk = clk_get_rate(host->clk);
unsigned long hclkn = NSEC_PER_SEC / hclk; unsigned long hclkn = NSEC_PER_SEC / hclk;
u32 thiz, thold, twait, tset; u32 thiz, thold, twait, tset, twait_min;
if (sdrt->tRC_min < 30000) if (sdrt->tRC_min < 30000)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, ...@@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
else if (tims->thold > FSMC_THOLD_MASK) else if (tims->thold > FSMC_THOLD_MASK)
tims->thold = FSMC_THOLD_MASK; tims->thold = FSMC_THOLD_MASK;
twait = max(sdrt->tRP_min, sdrt->tWP_min);
tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
if (tims->twait == 0)
tims->twait = 1;
else if (tims->twait > FSMC_TWAIT_MASK)
tims->twait = FSMC_TWAIT_MASK;
tset = max(sdrt->tCS_min - sdrt->tWP_min, tset = max(sdrt->tCS_min - sdrt->tWP_min,
sdrt->tCEA_max - sdrt->tREA_max); sdrt->tCEA_max - sdrt->tREA_max);
tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1;
...@@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, ...@@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
else if (tims->tset > FSMC_TSET_MASK) else if (tims->tset > FSMC_TSET_MASK)
tims->tset = FSMC_TSET_MASK; tims->tset = FSMC_TSET_MASK;
/*
* According to SPEAr300 Reference Manual (RM0082) which gives more
* information related to FSMSC timings than the SPEAr600 one (RM0305),
* twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL
*/
twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000)
+ TOUTDEL + TINDEL;
twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min);
tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
if (tims->twait == 0)
tims->twait = 1;
else if (tims->twait > FSMC_TWAIT_MASK)
tims->twait = FSMC_TWAIT_MASK;
return 0; return 0;
} }
...@@ -664,6 +681,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, ...@@ -664,6 +681,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
instr->ctx.waitrdy.timeout_ms); instr->ctx.waitrdy.timeout_ms);
break; break;
} }
if (instr->delay_ns)
ndelay(instr->delay_ns);
} }
return ret; return ret;
......
...@@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, ...@@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
struct nand_sdr_timings *spec_timings) struct nand_sdr_timings *spec_timings)
{ {
const struct nand_controller_ops *ops = chip->controller->ops; const struct nand_controller_ops *ops = chip->controller->ops;
int best_mode = 0, mode, ret; int best_mode = 0, mode, ret = -EOPNOTSUPP;
iface->type = NAND_SDR_IFACE; iface->type = NAND_SDR_IFACE;
...@@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip, ...@@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip,
struct nand_nvddr_timings *spec_timings) struct nand_nvddr_timings *spec_timings)
{ {
const struct nand_controller_ops *ops = chip->controller->ops; const struct nand_controller_ops *ops = chip->controller->ops;
int best_mode = 0, mode, ret; int best_mode = 0, mode, ret = -EOPNOTSUPP;
iface->type = NAND_NVDDR_IFACE; iface->type = NAND_NVDDR_IFACE;
...@@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) ...@@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
NAND_OP_CMD(NAND_CMD_ERASE1, 0), NAND_OP_CMD(NAND_CMD_ERASE1, 0),
NAND_OP_ADDR(2, addrs, 0), NAND_OP_ADDR(2, addrs, 0),
NAND_OP_CMD(NAND_CMD_ERASE2, NAND_OP_CMD(NAND_CMD_ERASE2,
NAND_COMMON_TIMING_MS(conf, tWB_max)), NAND_COMMON_TIMING_NS(conf, tWB_max)),
NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max), NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max),
0), 0),
}; };
......
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