diff options
| -rw-r--r-- | drivers/mtd/spi-nor/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/cadence-quadspi.c | 96 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/fsl-quadspi.c | 15 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/hisi-sfc.c | 12 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/intel-spi.c | 80 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 33 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/stm32-quadspi.c | 2 | ||||
| -rw-r--r-- | include/linux/mtd/spi-nor.h | 2 |
8 files changed, 220 insertions, 24 deletions
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index c493b8230a38..6cc9c929ff57 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig | |||
| @@ -90,7 +90,7 @@ config SPI_INTEL_SPI | |||
| 90 | tristate | 90 | tristate |
| 91 | 91 | ||
| 92 | config SPI_INTEL_SPI_PCI | 92 | config SPI_INTEL_SPI_PCI |
| 93 | tristate "Intel PCH/PCU SPI flash PCI driver" | 93 | tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)" |
| 94 | depends on X86 && PCI | 94 | depends on X86 && PCI |
| 95 | select SPI_INTEL_SPI | 95 | select SPI_INTEL_SPI |
| 96 | help | 96 | help |
| @@ -106,7 +106,7 @@ config SPI_INTEL_SPI_PCI | |||
| 106 | will be called intel-spi-pci. | 106 | will be called intel-spi-pci. |
| 107 | 107 | ||
| 108 | config SPI_INTEL_SPI_PLATFORM | 108 | config SPI_INTEL_SPI_PLATFORM |
| 109 | tristate "Intel PCH/PCU SPI flash platform driver" | 109 | tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)" |
| 110 | depends on X86 | 110 | depends on X86 |
| 111 | select SPI_INTEL_SPI | 111 | select SPI_INTEL_SPI |
| 112 | help | 112 | help |
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 4b8e9183489a..2f3a4d4232b3 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| 19 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/dma-mapping.h> | ||
| 22 | #include <linux/dmaengine.h> | ||
| 21 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 22 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 23 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| @@ -73,6 +75,10 @@ struct cqspi_st { | |||
| 73 | struct completion transfer_complete; | 75 | struct completion transfer_complete; |
| 74 | struct mutex bus_mutex; | 76 | struct mutex bus_mutex; |
| 75 | 77 | ||
| 78 | struct dma_chan *rx_chan; | ||
| 79 | struct completion rx_dma_complete; | ||
| 80 | dma_addr_t mmap_phys_base; | ||
| 81 | |||
| 76 | int current_cs; | 82 | int current_cs; |
| 77 | int current_page_size; | 83 | int current_page_size; |
| 78 | int current_erase_size; | 84 | int current_erase_size; |
| @@ -915,11 +921,75 @@ static ssize_t cqspi_write(struct spi_nor *nor, loff_t to, | |||
| 915 | return len; | 921 | return len; |
| 916 | } | 922 | } |
| 917 | 923 | ||
| 924 | static void cqspi_rx_dma_callback(void *param) | ||
| 925 | { | ||
| 926 | struct cqspi_st *cqspi = param; | ||
| 927 | |||
| 928 | complete(&cqspi->rx_dma_complete); | ||
| 929 | } | ||
| 930 | |||
| 931 | static int cqspi_direct_read_execute(struct spi_nor *nor, u_char *buf, | ||
| 932 | loff_t from, size_t len) | ||
| 933 | { | ||
| 934 | struct cqspi_flash_pdata *f_pdata = nor->priv; | ||
| 935 | struct cqspi_st *cqspi = f_pdata->cqspi; | ||
| 936 | enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; | ||
| 937 | dma_addr_t dma_src = (dma_addr_t)cqspi->mmap_phys_base + from; | ||
| 938 | int ret = 0; | ||
| 939 | struct dma_async_tx_descriptor *tx; | ||
| 940 | dma_cookie_t cookie; | ||
| 941 | dma_addr_t dma_dst; | ||
| 942 | |||
| 943 | if (!cqspi->rx_chan || !virt_addr_valid(buf)) { | ||
| 944 | memcpy_fromio(buf, cqspi->ahb_base + from, len); | ||
| 945 | return 0; | ||
| 946 | } | ||
| 947 | |||
| 948 | dma_dst = dma_map_single(nor->dev, buf, len, DMA_DEV_TO_MEM); | ||
| 949 | if (dma_mapping_error(nor->dev, dma_dst)) { | ||
| 950 | dev_err(nor->dev, "dma mapping failed\n"); | ||
| 951 | return -ENOMEM; | ||
| 952 | } | ||
| 953 | tx = dmaengine_prep_dma_memcpy(cqspi->rx_chan, dma_dst, dma_src, | ||
| 954 | len, flags); | ||
| 955 | if (!tx) { | ||
| 956 | dev_err(nor->dev, "device_prep_dma_memcpy error\n"); | ||
| 957 | ret = -EIO; | ||
| 958 | goto err_unmap; | ||
| 959 | } | ||
| 960 | |||
| 961 | tx->callback = cqspi_rx_dma_callback; | ||
| 962 | tx->callback_param = cqspi; | ||
| 963 | cookie = tx->tx_submit(tx); | ||
| 964 | reinit_completion(&cqspi->rx_dma_complete); | ||
| 965 | |||
| 966 | ret = dma_submit_error(cookie); | ||
| 967 | if (ret) { | ||
| 968 | dev_err(nor->dev, "dma_submit_error %d\n", cookie); | ||
| 969 | ret = -EIO; | ||
| 970 | goto err_unmap; | ||
| 971 | } | ||
| 972 | |||
| 973 | dma_async_issue_pending(cqspi->rx_chan); | ||
| 974 | ret = wait_for_completion_timeout(&cqspi->rx_dma_complete, | ||
| 975 | msecs_to_jiffies(len)); | ||
| 976 | if (ret <= 0) { | ||
| 977 | dmaengine_terminate_sync(cqspi->rx_chan); | ||
| 978 | dev_err(nor->dev, "DMA wait_for_completion_timeout\n"); | ||
| 979 | ret = -ETIMEDOUT; | ||
| 980 | goto err_unmap; | ||
| 981 | } | ||
| 982 | |||
| 983 | err_unmap: | ||
| 984 | dma_unmap_single(nor->dev, dma_dst, len, DMA_DEV_TO_MEM); | ||
| 985 | |||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 918 | static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, | 989 | static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, |
| 919 | size_t len, u_char *buf) | 990 | size_t len, u_char *buf) |
| 920 | { | 991 | { |
| 921 | struct cqspi_flash_pdata *f_pdata = nor->priv; | 992 | struct cqspi_flash_pdata *f_pdata = nor->priv; |
| 922 | struct cqspi_st *cqspi = f_pdata->cqspi; | ||
| 923 | int ret; | 993 | int ret; |
| 924 | 994 | ||
| 925 | ret = cqspi_set_protocol(nor, 1); | 995 | ret = cqspi_set_protocol(nor, 1); |
| @@ -931,7 +1001,7 @@ static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, | |||
| 931 | return ret; | 1001 | return ret; |
| 932 | 1002 | ||
| 933 | if (f_pdata->use_direct_mode) | 1003 | if (f_pdata->use_direct_mode) |
| 934 | memcpy_fromio(buf, cqspi->ahb_base + from, len); | 1004 | ret = cqspi_direct_read_execute(nor, buf, from, len); |
| 935 | else | 1005 | else |
| 936 | ret = cqspi_indirect_read_execute(nor, buf, from, len); | 1006 | ret = cqspi_indirect_read_execute(nor, buf, from, len); |
| 937 | if (ret) | 1007 | if (ret) |
| @@ -1100,6 +1170,21 @@ static void cqspi_controller_init(struct cqspi_st *cqspi) | |||
| 1100 | cqspi_controller_enable(cqspi, 1); | 1170 | cqspi_controller_enable(cqspi, 1); |
| 1101 | } | 1171 | } |
| 1102 | 1172 | ||
| 1173 | static void cqspi_request_mmap_dma(struct cqspi_st *cqspi) | ||
| 1174 | { | ||
| 1175 | dma_cap_mask_t mask; | ||
| 1176 | |||
| 1177 | dma_cap_zero(mask); | ||
| 1178 | dma_cap_set(DMA_MEMCPY, mask); | ||
| 1179 | |||
| 1180 | cqspi->rx_chan = dma_request_chan_by_mask(&mask); | ||
| 1181 | if (IS_ERR(cqspi->rx_chan)) { | ||
| 1182 | dev_err(&cqspi->pdev->dev, "No Rx DMA available\n"); | ||
| 1183 | cqspi->rx_chan = NULL; | ||
| 1184 | } | ||
| 1185 | init_completion(&cqspi->rx_dma_complete); | ||
| 1186 | } | ||
| 1187 | |||
| 1103 | static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np) | 1188 | static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np) |
| 1104 | { | 1189 | { |
| 1105 | const struct spi_nor_hwcaps hwcaps = { | 1190 | const struct spi_nor_hwcaps hwcaps = { |
| @@ -1177,6 +1262,9 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np) | |||
| 1177 | f_pdata->use_direct_mode = true; | 1262 | f_pdata->use_direct_mode = true; |
| 1178 | dev_dbg(nor->dev, "using direct mode for %s\n", | 1263 | dev_dbg(nor->dev, "using direct mode for %s\n", |
| 1179 | mtd->name); | 1264 | mtd->name); |
| 1265 | |||
| 1266 | if (!cqspi->rx_chan) | ||
| 1267 | cqspi_request_mmap_dma(cqspi); | ||
| 1180 | } | 1268 | } |
| 1181 | } | 1269 | } |
| 1182 | 1270 | ||
| @@ -1237,6 +1325,7 @@ static int cqspi_probe(struct platform_device *pdev) | |||
| 1237 | dev_err(dev, "Cannot remap AHB address.\n"); | 1325 | dev_err(dev, "Cannot remap AHB address.\n"); |
| 1238 | return PTR_ERR(cqspi->ahb_base); | 1326 | return PTR_ERR(cqspi->ahb_base); |
| 1239 | } | 1327 | } |
| 1328 | cqspi->mmap_phys_base = (dma_addr_t)res_ahb->start; | ||
| 1240 | cqspi->ahb_size = resource_size(res_ahb); | 1329 | cqspi->ahb_size = resource_size(res_ahb); |
| 1241 | 1330 | ||
| 1242 | init_completion(&cqspi->transfer_complete); | 1331 | init_completion(&cqspi->transfer_complete); |
| @@ -1307,6 +1396,9 @@ static int cqspi_remove(struct platform_device *pdev) | |||
| 1307 | 1396 | ||
| 1308 | cqspi_controller_enable(cqspi, 0); | 1397 | cqspi_controller_enable(cqspi, 0); |
| 1309 | 1398 | ||
| 1399 | if (cqspi->rx_chan) | ||
| 1400 | dma_release_channel(cqspi->rx_chan); | ||
| 1401 | |||
| 1310 | clk_disable_unprepare(cqspi->clk); | 1402 | clk_disable_unprepare(cqspi->clk); |
| 1311 | 1403 | ||
| 1312 | pm_runtime_put_sync(&pdev->dev); | 1404 | pm_runtime_put_sync(&pdev->dev); |
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 3e3c0bbc45c0..7d9620c7ff6c 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
| @@ -214,6 +214,7 @@ enum fsl_qspi_devtype { | |||
| 214 | FSL_QUADSPI_IMX7D, | 214 | FSL_QUADSPI_IMX7D, |
| 215 | FSL_QUADSPI_IMX6UL, | 215 | FSL_QUADSPI_IMX6UL, |
| 216 | FSL_QUADSPI_LS1021A, | 216 | FSL_QUADSPI_LS1021A, |
| 217 | FSL_QUADSPI_LS2080A, | ||
| 217 | }; | 218 | }; |
| 218 | 219 | ||
| 219 | struct fsl_qspi_devtype_data { | 220 | struct fsl_qspi_devtype_data { |
| @@ -267,6 +268,15 @@ static struct fsl_qspi_devtype_data ls1021a_data = { | |||
| 267 | .driver_data = 0, | 268 | .driver_data = 0, |
| 268 | }; | 269 | }; |
| 269 | 270 | ||
| 271 | static const struct fsl_qspi_devtype_data ls2080a_data = { | ||
| 272 | .devtype = FSL_QUADSPI_LS2080A, | ||
| 273 | .rxfifo = 128, | ||
| 274 | .txfifo = 64, | ||
| 275 | .ahb_buf_size = 1024, | ||
| 276 | .driver_data = QUADSPI_QUIRK_TKT253890, | ||
| 277 | }; | ||
| 278 | |||
| 279 | |||
| 270 | #define FSL_QSPI_MAX_CHIP 4 | 280 | #define FSL_QSPI_MAX_CHIP 4 |
| 271 | struct fsl_qspi { | 281 | struct fsl_qspi { |
| 272 | struct spi_nor nor[FSL_QSPI_MAX_CHIP]; | 282 | struct spi_nor nor[FSL_QSPI_MAX_CHIP]; |
| @@ -661,7 +671,7 @@ static void fsl_qspi_set_map_addr(struct fsl_qspi *q) | |||
| 661 | * causes the controller to clear the buffer, and use the sequence pointed | 671 | * causes the controller to clear the buffer, and use the sequence pointed |
| 662 | * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. | 672 | * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. |
| 663 | */ | 673 | */ |
| 664 | static void fsl_qspi_init_abh_read(struct fsl_qspi *q) | 674 | static void fsl_qspi_init_ahb_read(struct fsl_qspi *q) |
| 665 | { | 675 | { |
| 666 | void __iomem *base = q->iobase; | 676 | void __iomem *base = q->iobase; |
| 667 | int seqid; | 677 | int seqid; |
| @@ -795,7 +805,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) | |||
| 795 | fsl_qspi_init_lut(q); | 805 | fsl_qspi_init_lut(q); |
| 796 | 806 | ||
| 797 | /* Init for AHB read */ | 807 | /* Init for AHB read */ |
| 798 | fsl_qspi_init_abh_read(q); | 808 | fsl_qspi_init_ahb_read(q); |
| 799 | 809 | ||
| 800 | return 0; | 810 | return 0; |
| 801 | } | 811 | } |
| @@ -806,6 +816,7 @@ static const struct of_device_id fsl_qspi_dt_ids[] = { | |||
| 806 | { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, }, | 816 | { .compatible = "fsl,imx7d-qspi", .data = &imx7d_data, }, |
| 807 | { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, | 817 | { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, |
| 808 | { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, | 818 | { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, |
| 819 | { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, }, | ||
| 809 | { /* sentinel */ } | 820 | { /* sentinel */ } |
| 810 | }; | 821 | }; |
| 811 | MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); | 822 | MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); |
diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/hisi-sfc.c index 04f9fb5cd9b6..dea7b0c4b339 100644 --- a/drivers/mtd/spi-nor/hisi-sfc.c +++ b/drivers/mtd/spi-nor/hisi-sfc.c | |||
| @@ -112,7 +112,7 @@ struct hifmc_host { | |||
| 112 | u32 num_chip; | 112 | u32 num_chip; |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | static inline int wait_op_finish(struct hifmc_host *host) | 115 | static inline int hisi_spi_nor_wait_op_finish(struct hifmc_host *host) |
| 116 | { | 116 | { |
| 117 | u32 reg; | 117 | u32 reg; |
| 118 | 118 | ||
| @@ -120,7 +120,7 @@ static inline int wait_op_finish(struct hifmc_host *host) | |||
| 120 | (reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT); | 120 | (reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static int get_if_type(enum spi_nor_protocol proto) | 123 | static int hisi_spi_nor_get_if_type(enum spi_nor_protocol proto) |
| 124 | { | 124 | { |
| 125 | enum hifmc_iftype if_type; | 125 | enum hifmc_iftype if_type; |
| 126 | 126 | ||
| @@ -208,7 +208,7 @@ static int hisi_spi_nor_op_reg(struct spi_nor *nor, | |||
| 208 | reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype; | 208 | reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype; |
| 209 | writel(reg, host->regbase + FMC_OP); | 209 | writel(reg, host->regbase + FMC_OP); |
| 210 | 210 | ||
| 211 | return wait_op_finish(host); | 211 | return hisi_spi_nor_wait_op_finish(host); |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, | 214 | static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, |
| @@ -259,9 +259,9 @@ static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, | |||
| 259 | 259 | ||
| 260 | reg = OP_CFG_FM_CS(priv->chipselect); | 260 | reg = OP_CFG_FM_CS(priv->chipselect); |
| 261 | if (op_type == FMC_OP_READ) | 261 | if (op_type == FMC_OP_READ) |
| 262 | if_type = get_if_type(nor->read_proto); | 262 | if_type = hisi_spi_nor_get_if_type(nor->read_proto); |
| 263 | else | 263 | else |
| 264 | if_type = get_if_type(nor->write_proto); | 264 | if_type = hisi_spi_nor_get_if_type(nor->write_proto); |
| 265 | reg |= OP_CFG_MEM_IF_TYPE(if_type); | 265 | reg |= OP_CFG_MEM_IF_TYPE(if_type); |
| 266 | if (op_type == FMC_OP_READ) | 266 | if (op_type == FMC_OP_READ) |
| 267 | reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3); | 267 | reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3); |
| @@ -274,7 +274,7 @@ static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, | |||
| 274 | : OP_CTRL_WR_OPCODE(nor->program_opcode); | 274 | : OP_CTRL_WR_OPCODE(nor->program_opcode); |
| 275 | writel(reg, host->regbase + FMC_OP_DMA); | 275 | writel(reg, host->regbase + FMC_OP_DMA); |
| 276 | 276 | ||
| 277 | return wait_op_finish(host); | 277 | return hisi_spi_nor_wait_op_finish(host); |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static ssize_t hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len, | 280 | static ssize_t hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len, |
diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 699951523179..d2cbfc27826e 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c | |||
| @@ -136,6 +136,7 @@ | |||
| 136 | * @swseq_reg: Use SW sequencer in register reads/writes | 136 | * @swseq_reg: Use SW sequencer in register reads/writes |
| 137 | * @swseq_erase: Use SW sequencer in erase operation | 137 | * @swseq_erase: Use SW sequencer in erase operation |
| 138 | * @erase_64k: 64k erase supported | 138 | * @erase_64k: 64k erase supported |
| 139 | * @atomic_preopcode: Holds preopcode when atomic sequence is requested | ||
| 139 | * @opcodes: Opcodes which are supported. This are programmed by BIOS | 140 | * @opcodes: Opcodes which are supported. This are programmed by BIOS |
| 140 | * before it locks down the controller. | 141 | * before it locks down the controller. |
| 141 | */ | 142 | */ |
| @@ -153,6 +154,7 @@ struct intel_spi { | |||
| 153 | bool swseq_reg; | 154 | bool swseq_reg; |
| 154 | bool swseq_erase; | 155 | bool swseq_erase; |
| 155 | bool erase_64k; | 156 | bool erase_64k; |
| 157 | u8 atomic_preopcode; | ||
| 156 | u8 opcodes[8]; | 158 | u8 opcodes[8]; |
| 157 | }; | 159 | }; |
| 158 | 160 | ||
| @@ -285,7 +287,7 @@ static int intel_spi_wait_hw_busy(struct intel_spi *ispi) | |||
| 285 | u32 val; | 287 | u32 val; |
| 286 | 288 | ||
| 287 | return readl_poll_timeout(ispi->base + HSFSTS_CTL, val, | 289 | return readl_poll_timeout(ispi->base + HSFSTS_CTL, val, |
| 288 | !(val & HSFSTS_CTL_SCIP), 0, | 290 | !(val & HSFSTS_CTL_SCIP), 40, |
| 289 | INTEL_SPI_TIMEOUT * 1000); | 291 | INTEL_SPI_TIMEOUT * 1000); |
| 290 | } | 292 | } |
| 291 | 293 | ||
| @@ -294,7 +296,7 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi) | |||
| 294 | u32 val; | 296 | u32 val; |
| 295 | 297 | ||
| 296 | return readl_poll_timeout(ispi->sregs + SSFSTS_CTL, val, | 298 | return readl_poll_timeout(ispi->sregs + SSFSTS_CTL, val, |
| 297 | !(val & SSFSTS_CTL_SCIP), 0, | 299 | !(val & SSFSTS_CTL_SCIP), 40, |
| 298 | INTEL_SPI_TIMEOUT * 1000); | 300 | INTEL_SPI_TIMEOUT * 1000); |
| 299 | } | 301 | } |
| 300 | 302 | ||
| @@ -474,7 +476,7 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len, | |||
| 474 | int optype) | 476 | int optype) |
| 475 | { | 477 | { |
| 476 | u32 val = 0, status; | 478 | u32 val = 0, status; |
| 477 | u16 preop; | 479 | u8 atomic_preopcode; |
| 478 | int ret; | 480 | int ret; |
| 479 | 481 | ||
| 480 | ret = intel_spi_opcode_index(ispi, opcode, optype); | 482 | ret = intel_spi_opcode_index(ispi, opcode, optype); |
| @@ -484,17 +486,42 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len, | |||
| 484 | if (len > INTEL_SPI_FIFO_SZ) | 486 | if (len > INTEL_SPI_FIFO_SZ) |
| 485 | return -EINVAL; | 487 | return -EINVAL; |
| 486 | 488 | ||
| 489 | /* | ||
| 490 | * Always clear it after each SW sequencer operation regardless | ||
| 491 | * of whether it is successful or not. | ||
| 492 | */ | ||
| 493 | atomic_preopcode = ispi->atomic_preopcode; | ||
| 494 | ispi->atomic_preopcode = 0; | ||
| 495 | |||
| 487 | /* Only mark 'Data Cycle' bit when there is data to be transferred */ | 496 | /* Only mark 'Data Cycle' bit when there is data to be transferred */ |
| 488 | if (len > 0) | 497 | if (len > 0) |
| 489 | val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; | 498 | val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; |
| 490 | val |= ret << SSFSTS_CTL_COP_SHIFT; | 499 | val |= ret << SSFSTS_CTL_COP_SHIFT; |
| 491 | val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE; | 500 | val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE; |
| 492 | val |= SSFSTS_CTL_SCGO; | 501 | val |= SSFSTS_CTL_SCGO; |
| 493 | preop = readw(ispi->sregs + PREOP_OPTYPE); | 502 | if (atomic_preopcode) { |
| 494 | if (preop) { | 503 | u16 preop; |
| 495 | val |= SSFSTS_CTL_ACS; | 504 | |
| 496 | if (preop >> 8) | 505 | switch (optype) { |
| 497 | val |= SSFSTS_CTL_SPOP; | 506 | case OPTYPE_WRITE_NO_ADDR: |
| 507 | case OPTYPE_WRITE_WITH_ADDR: | ||
| 508 | /* Pick matching preopcode for the atomic sequence */ | ||
| 509 | preop = readw(ispi->sregs + PREOP_OPTYPE); | ||
| 510 | if ((preop & 0xff) == atomic_preopcode) | ||
| 511 | ; /* Do nothing */ | ||
| 512 | else if ((preop >> 8) == atomic_preopcode) | ||
| 513 | val |= SSFSTS_CTL_SPOP; | ||
| 514 | else | ||
| 515 | return -EINVAL; | ||
| 516 | |||
| 517 | /* Enable atomic sequence */ | ||
| 518 | val |= SSFSTS_CTL_ACS; | ||
| 519 | break; | ||
| 520 | |||
| 521 | default: | ||
| 522 | return -EINVAL; | ||
| 523 | } | ||
| 524 | |||
| 498 | } | 525 | } |
| 499 | writel(val, ispi->sregs + SSFSTS_CTL); | 526 | writel(val, ispi->sregs + SSFSTS_CTL); |
| 500 | 527 | ||
| @@ -538,13 +565,31 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) | |||
| 538 | 565 | ||
| 539 | /* | 566 | /* |
| 540 | * This is handled with atomic operation and preop code in Intel | 567 | * This is handled with atomic operation and preop code in Intel |
| 541 | * controller so skip it here now. If the controller is not locked, | 568 | * controller so we only verify that it is available. If the |
| 542 | * program the opcode to the PREOP register for later use. | 569 | * controller is not locked, program the opcode to the PREOP |
| 570 | * register for later use. | ||
| 571 | * | ||
| 572 | * When hardware sequencer is used there is no need to program | ||
| 573 | * any opcodes (it handles them automatically as part of a command). | ||
| 543 | */ | 574 | */ |
| 544 | if (opcode == SPINOR_OP_WREN) { | 575 | if (opcode == SPINOR_OP_WREN) { |
| 545 | if (!ispi->locked) | 576 | u16 preop; |
| 577 | |||
| 578 | if (!ispi->swseq_reg) | ||
| 579 | return 0; | ||
| 580 | |||
| 581 | preop = readw(ispi->sregs + PREOP_OPTYPE); | ||
| 582 | if ((preop & 0xff) != opcode && (preop >> 8) != opcode) { | ||
| 583 | if (ispi->locked) | ||
| 584 | return -EINVAL; | ||
| 546 | writel(opcode, ispi->sregs + PREOP_OPTYPE); | 585 | writel(opcode, ispi->sregs + PREOP_OPTYPE); |
| 586 | } | ||
| 547 | 587 | ||
| 588 | /* | ||
| 589 | * This enables atomic sequence on next SW sycle. Will | ||
| 590 | * be cleared after next operation. | ||
| 591 | */ | ||
| 592 | ispi->atomic_preopcode = opcode; | ||
| 548 | return 0; | 593 | return 0; |
| 549 | } | 594 | } |
| 550 | 595 | ||
| @@ -569,6 +614,13 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, | |||
| 569 | u32 val, status; | 614 | u32 val, status; |
| 570 | ssize_t ret; | 615 | ssize_t ret; |
| 571 | 616 | ||
| 617 | /* | ||
| 618 | * Atomic sequence is not expected with HW sequencer reads. Make | ||
| 619 | * sure it is cleared regardless. | ||
| 620 | */ | ||
| 621 | if (WARN_ON_ONCE(ispi->atomic_preopcode)) | ||
| 622 | ispi->atomic_preopcode = 0; | ||
| 623 | |||
| 572 | switch (nor->read_opcode) { | 624 | switch (nor->read_opcode) { |
| 573 | case SPINOR_OP_READ: | 625 | case SPINOR_OP_READ: |
| 574 | case SPINOR_OP_READ_FAST: | 626 | case SPINOR_OP_READ_FAST: |
| @@ -627,6 +679,9 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, | |||
| 627 | u32 val, status; | 679 | u32 val, status; |
| 628 | ssize_t ret; | 680 | ssize_t ret; |
| 629 | 681 | ||
| 682 | /* Not needed with HW sequencer write, make sure it is cleared */ | ||
| 683 | ispi->atomic_preopcode = 0; | ||
| 684 | |||
| 630 | while (len > 0) { | 685 | while (len > 0) { |
| 631 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); | 686 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); |
| 632 | 687 | ||
| @@ -707,6 +762,9 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs) | |||
| 707 | return 0; | 762 | return 0; |
| 708 | } | 763 | } |
| 709 | 764 | ||
| 765 | /* Not needed with HW sequencer erase, make sure it is cleared */ | ||
| 766 | ispi->atomic_preopcode = 0; | ||
| 767 | |||
| 710 | while (len > 0) { | 768 | while (len > 0) { |
| 711 | writel(offs, ispi->base + FADDR); | 769 | writel(offs, ispi->base + FADDR); |
| 712 | 770 | ||
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 5bfa36e95f35..d9c368c44194 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
| @@ -284,6 +284,20 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, | |||
| 284 | if (need_wren) | 284 | if (need_wren) |
| 285 | write_disable(nor); | 285 | write_disable(nor); |
| 286 | 286 | ||
| 287 | if (!status && !enable && | ||
| 288 | JEDEC_MFR(info) == SNOR_MFR_WINBOND) { | ||
| 289 | /* | ||
| 290 | * On Winbond W25Q256FV, leaving 4byte mode causes | ||
| 291 | * the Extended Address Register to be set to 1, so all | ||
| 292 | * 3-byte-address reads come from the second 16M. | ||
| 293 | * We must clear the register to enable normal behavior. | ||
| 294 | */ | ||
| 295 | write_enable(nor); | ||
| 296 | nor->cmd_buf[0] = 0; | ||
| 297 | nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); | ||
| 298 | write_disable(nor); | ||
| 299 | } | ||
| 300 | |||
| 287 | return status; | 301 | return status; |
| 288 | default: | 302 | default: |
| 289 | /* Spansion style */ | 303 | /* Spansion style */ |
| @@ -980,6 +994,7 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 980 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | 994 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, |
| 981 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | 995 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, |
| 982 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, | 996 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, |
| 997 | { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) }, | ||
| 983 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, | 998 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, |
| 984 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, | 999 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, |
| 985 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, | 1000 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, |
| @@ -1049,6 +1064,14 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 1049 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1064 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1050 | { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, | 1065 | { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, |
| 1051 | SECT_4K | SPI_NOR_DUAL_READ) }, | 1066 | SECT_4K | SPI_NOR_DUAL_READ) }, |
| 1067 | { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512, | ||
| 1068 | SECT_4K | SPI_NOR_DUAL_READ) }, | ||
| 1069 | { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64, | ||
| 1070 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 1071 | { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128, | ||
| 1072 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 1073 | { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256, | ||
| 1074 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 1052 | 1075 | ||
| 1053 | /* Macronix */ | 1076 | /* Macronix */ |
| 1054 | { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, | 1077 | { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, |
| @@ -1087,6 +1110,7 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 1087 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, | 1110 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 1088 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | 1111 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 1089 | { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | 1112 | { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 1113 | { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | ||
| 1090 | 1114 | ||
| 1091 | /* PMC */ | 1115 | /* PMC */ |
| 1092 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, | 1116 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, |
| @@ -1198,6 +1222,11 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 1198 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1222 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1199 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1223 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1200 | }, | 1224 | }, |
| 1225 | { | ||
| 1226 | "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64, | ||
| 1227 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | ||
| 1228 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | ||
| 1229 | }, | ||
| 1201 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 1230 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1202 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 1231 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1203 | { | 1232 | { |
| @@ -1230,6 +1259,10 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 1230 | { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, | 1259 | { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, |
| 1231 | { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, | 1260 | { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, |
| 1232 | { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, | 1261 | { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, |
| 1262 | |||
| 1263 | /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ | ||
| 1264 | { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 1265 | { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||
| 1233 | { }, | 1266 | { }, |
| 1234 | }; | 1267 | }; |
| 1235 | 1268 | ||
diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c index b3c7f6addba7..72553506a00b 100644 --- a/drivers/mtd/spi-nor/stm32-quadspi.c +++ b/drivers/mtd/spi-nor/stm32-quadspi.c | |||
| @@ -656,7 +656,7 @@ static int stm32_qspi_probe(struct platform_device *pdev) | |||
| 656 | return ret; | 656 | return ret; |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | rstc = devm_reset_control_get(dev, NULL); | 659 | rstc = devm_reset_control_get_exclusive(dev, NULL); |
| 660 | if (!IS_ERR(rstc)) { | 660 | if (!IS_ERR(rstc)) { |
| 661 | reset_control_assert(rstc); | 661 | reset_control_assert(rstc); |
| 662 | udelay(2); | 662 | udelay(2); |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index de36969eb359..e60da0d34cc1 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
| @@ -62,6 +62,8 @@ | |||
| 62 | #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ | 62 | #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ |
| 63 | #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ | 63 | #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ |
| 64 | #define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */ | 64 | #define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */ |
| 65 | #define SPINOR_OP_RDEAR 0xc8 /* Read Extended Address Register */ | ||
| 66 | #define SPINOR_OP_WREAR 0xc5 /* Write Extended Address Register */ | ||
| 65 | 67 | ||
| 66 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ | 68 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ |
| 67 | #define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ | 69 | #define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ |
