Pull MTD updates from Miquel Raynal: "MTD core - block2mtd: page index should use pgoff_t - maps: physmap: minimal Runtime PM support - maps: pcmciamtd: avoid possible sleep-in-atomic-context bugs - concat: Fix a comment referring to an unknown symbol Raw NAND: - Macronix: Use match_string() helper - Atmel: switch to using devm_fwnode_gpiod_get() - Denali: rework the SKIP_BYTES feature and add reset controlling - Brcmnand: set appropriate DMA mask - Cadence: add unspecified HAS_IOMEM dependency - Various cleanup. Onenand: - Rename Samsung and Omap2 drivers to avoid possible build warnings - Enable compile testing - Various build issues - Kconfig cleanup SPI-NAND: - Support for Toshiba TC58CVG2S0HRAIJ SPI-NOR: - Add support for TB selection using SR bit 6, - Add support for few flashes" * tag 'mtd/for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (41 commits) mtd: concat: Fix a comment referring to an unknown symbol mtd: rawnand: add unspecified HAS_IOMEM dependency mtd: block2mtd: page index should use pgoff_t mtd: maps: physmap: Add minimal Runtime PM support mtd: maps: pcmciamtd: fix possible sleep-in-atomic-context bugs in pcmciamtd_set_vpp() mtd: onenand: Rename omap2 driver to avoid a build warning mtd: onenand: Use a better name for samsung driver mtd: rawnand: atmel: switch to using devm_fwnode_gpiod_get() mtd: spinand: add support for Toshiba TC58CVG2S0HRAIJ mtd: rawnand: macronix: Use match_string() helper to simplify the code mtd: sharpslpart: Fix unsigned comparison to zero mtd: onenand: Enable compile testing of OMAP and Samsung drivers mtd: onenand: samsung: Fix printing format for size_t on 64-bit mtd: onenand: samsung: Fix pointer cast -Wpointer-to-int-cast warnings on 64 bit mtd: rawnand: denali: remove hard-coded DENALI_DEFAULT_OOB_SKIP_BYTES mtd: rawnand: denali_dt: add reset controlling dt-bindings: mtd: denali_dt: document reset property mtd: rawnand: denali_dt: Add support for configuring SPARE_AREA_SKIP_BYTES mtd: rawnand: denali_dt: error out if platform has no associated data mtd: rawnand: brcmnand: Set appropriate DMA mask ...
Unified · Split
| @@ -14,6 +14,11 @@ Required properties: · 13 unmodified lines | ||
| 14 | 14 | interface clock, and the ECC circuit clock. |
| 15 | 15 | - clock-names: should contain "nand", "nand_x", "ecc" |
| 16 | 16 | |
| 17 | +Optional properties: | |
| 18 | + - resets: may contain phandles to the controller core reset, the register | |
| 19 | + reset | |
| 20 | + - reset-names: may contain "nand", "reg" | |
| 21 | + | |
| 17 | 22 | Sub-nodes: |
| 18 | 23 | Sub-nodes represent available NAND chips. |
| 19 | 24 | |
| @@ -46,6 +51,8 @@ nand: nand@ff900000 { · 26 unmodified lines | ||
| 46 | 51 | reg-names = "nand_data", "denali_reg"; |
| 47 | 52 | clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; |
| 48 | 53 | clock-names = "nand", "nand_x", "ecc"; |
| 54 | + resets = <&nand_rst>, <&nand_reg_rst>; | |
| 55 | + reset-names = "nand", "reg"; | |
| 49 | 56 | interrupts = <0 144 4>; |
| 50 | 57 | |
| 51 | 58 | nand@0 { |
| @@ -44,7 +44,7 @@ struct block2mtd_dev { · 43 unmodified lines | ||
| 44 | 44 | static LIST_HEAD(blkmtd_device_list); |
| 45 | 45 | |
| 46 | 46 | |
| 47 | −static struct page *page_read(struct address_space *mapping, int index) | |
| 47 | +static struct page *page_read(struct address_space *mapping, pgoff_t index) | |
| 48 | 48 | { |
| 49 | 49 | return read_mapping_page(mapping, index, NULL); |
| 50 | 50 | } |
| @@ -54,7 +54,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) · 3 unmodified lines | ||
| 54 | 54 | { |
| 55 | 55 | struct address_space *mapping = dev->blkdev->bd_inode->i_mapping; |
| 56 | 56 | struct page *page; |
| 57 | − int index = to >> PAGE_SHIFT; // page index | |
| 57 | + pgoff_t index = to >> PAGE_SHIFT; // page index | |
| 58 | 58 | int pages = len >> PAGE_SHIFT; |
| 59 | 59 | u_long *p; |
| 60 | 60 | u_long *max; |
| @@ -103,7 +103,7 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, · 42 unmodified lines | ||
| 103 | 103 | { |
| 104 | 104 | struct block2mtd_dev *dev = mtd->priv; |
| 105 | 105 | struct page *page; |
| 106 | − int index = from >> PAGE_SHIFT; | |
| 106 | + pgoff_t index = from >> PAGE_SHIFT; | |
| 107 | 107 | int offset = from & (PAGE_SIZE-1); |
| 108 | 108 | int cpylen; |
| 109 | 109 | |
| @@ -137,7 +137,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, · 27 unmodified lines | ||
| 137 | 137 | { |
| 138 | 138 | struct page *page; |
| 139 | 139 | struct address_space *mapping = dev->blkdev->bd_inode->i_mapping; |
| 140 | − int index = to >> PAGE_SHIFT; // page index | |
| 140 | + pgoff_t index = to >> PAGE_SHIFT; // page index | |
| 141 | 141 | int offset = to & ~PAGE_MASK; // page offset |
| 142 | 142 | int cpylen; |
| 143 | 143 | |
| @@ -294,16 +294,15 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f · 293 unmodified lines | ||
| 294 | 294 | } |
| 295 | 295 | |
| 296 | 296 | |
| 297 | −static DEFINE_SPINLOCK(pcmcia_vpp_lock); | |
| 297 | +static DEFINE_MUTEX(pcmcia_vpp_lock); | |
| 298 | 298 | static int pcmcia_vpp_refcnt; |
| 299 | 299 | static void pcmciamtd_set_vpp(struct map_info *map, int on) |
| 300 | 300 | { |
| 301 | 301 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
| 302 | 302 | struct pcmcia_device *link = dev->p_dev; |
| 303 | − unsigned long flags; | |
| 304 | 303 | |
| 305 | 304 | pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp); |
| 306 | − spin_lock_irqsave(&pcmcia_vpp_lock, flags); | |
| 305 | + mutex_lock(&pcmcia_vpp_lock); | |
| 307 | 306 | if (on) { |
| 308 | 307 | if (++pcmcia_vpp_refcnt == 1) /* first nested 'on' */ |
| 309 | 308 | pcmcia_fixup_vpp(link, dev->vpp); |
| @@ -311,7 +310,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) · 1 unmodified line | ||
| 311 | 310 | if (--pcmcia_vpp_refcnt == 0) /* last nested 'off' */ |
| 312 | 311 | pcmcia_fixup_vpp(link, 0); |
| 313 | 312 | } |
| 314 | − spin_unlock_irqrestore(&pcmcia_vpp_lock, flags); | |
| 313 | + mutex_unlock(&pcmcia_vpp_lock); | |
| 315 | 314 | } |
| 316 | 315 | |
| 317 | 316 | |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/mtd/cfi_endian.h> |
| 39 | 39 | #include <linux/io.h> |
| 40 | 40 | #include <linux/of_device.h> |
| 41 | +#include <linux/pm_runtime.h> | |
| 41 | 42 | #include <linux/gpio/consumer.h> |
| 42 | 43 | |
| 43 | 44 | #include "physmap-gemini.h" |
| @@ -64,16 +65,16 @@ static int physmap_flash_remove(struct platform_device *dev) · 20 unmodified lines | ||
| 64 | 65 | { |
| 65 | 66 | struct physmap_flash_info *info; |
| 66 | 67 | struct physmap_flash_data *physmap_data; |
| 67 | − int i, err; | |
| 68 | + int i, err = 0; | |
| 68 | 69 | |
| 69 | 70 | info = platform_get_drvdata(dev); |
| 70 | 71 | if (!info) |
| 71 | − return 0; | |
| 72 | + goto out; | |
| 72 | 73 | |
| 73 | 74 | if (info->cmtd) { |
| 74 | 75 | err = mtd_device_unregister(info->cmtd); |
| 75 | 76 | if (err) |
| 76 | − return err; | |
| 77 | + goto out; | |
| 77 | 78 | |
| 78 | 79 | if (info->cmtd != info->mtds[0]) |
| 79 | 80 | mtd_concat_destroy(info->cmtd); |
| @@ -88,7 +89,10 @@ static int physmap_flash_remove(struct platform_device *dev) · 8 unmodified lines | ||
| 88 | 89 | if (physmap_data && physmap_data->exit) |
| 89 | 90 | physmap_data->exit(dev); |
| 90 | 91 | |
| 91 | − return 0; | |
| 92 | +out: | |
| 93 | + pm_runtime_put(&dev->dev); | |
| 94 | + pm_runtime_disable(&dev->dev); | |
| 95 | + return err; | |
| 92 | 96 | } |
| 93 | 97 | |
| 94 | 98 | static void physmap_set_vpp(struct map_info *map, int state) |
| @@ -484,13 +488,19 @@ static int physmap_flash_probe(struct platform_device *dev) · 389 unmodified lines | ||
| 484 | 488 | return -EINVAL; |
| 485 | 489 | } |
| 486 | 490 | |
| 491 | + pm_runtime_enable(&dev->dev); | |
| 492 | + pm_runtime_get_sync(&dev->dev); | |
| 493 | + | |
| 487 | 494 | if (dev->dev.of_node) |
| 488 | 495 | err = physmap_flash_of_init(dev); |
| 489 | 496 | else |
| 490 | 497 | err = physmap_flash_pdata_init(dev); |
| 491 | 498 | |
| 492 | − if (err) | |
| 499 | + if (err) { | |
| 500 | + pm_runtime_put(&dev->dev); | |
| 501 | + pm_runtime_disable(&dev->dev); | |
| 493 | 502 | return err; |
| 503 | + } | |
| 494 | 504 | |
| 495 | 505 | for (i = 0; i < info->nmaps; i++) { |
| 496 | 506 | struct resource *res; |
| @@ -841,10 +841,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c · 840 unmodified lines | ||
| 841 | 841 | return &concat->mtd; |
| 842 | 842 | } |
| 843 | 843 | |
| 844 | −/* | |
| 845 | − * This function destroys an MTD object obtained from concat_mtd_devs() | |
| 846 | − */ | |
| 847 | − | |
| 844 | +/* Cleans the context obtained from mtd_concat_create() */ | |
| 848 | 845 | void mtd_concat_destroy(struct mtd_info *mtd) |
| 849 | 846 | { |
| 850 | 847 | struct mtd_concat *concat = CONCAT(mtd); |
| @@ -25,7 +25,7 @@ config MTD_ONENAND_GENERIC · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | config MTD_ONENAND_OMAP2 |
| 27 | 27 | tristate "OneNAND on OMAP2/OMAP3 support" |
| 28 | − depends on ARCH_OMAP2 || ARCH_OMAP3 | |
| 28 | + depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && ARM) | |
| 29 | 29 | depends on OF || COMPILE_TEST |
| 30 | 30 | help |
| 31 | 31 | Support for a OneNAND flash device connected to an OMAP2/OMAP3 SoC |
| @@ -33,12 +33,12 @@ config MTD_ONENAND_OMAP2 · 1 unmodified line | ||
| 33 | 33 | Enable dmaengine and gpiolib for better performance. |
| 34 | 34 | |
| 35 | 35 | config MTD_ONENAND_SAMSUNG |
| 36 | − tristate "OneNAND on Samsung SOC controller support" | |
| 37 | − depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 | |
| 38 | − help | |
| 39 | − Support for a OneNAND flash device connected to an Samsung SOC. | |
| 40 | − S3C64XX uses command mapping method. | |
| 41 | − S5PC110/S5PC210 use generic OneNAND method. | |
| 36 | + tristate "OneNAND on Samsung SOC controller support" | |
| 37 | + depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 || COMPILE_TEST | |
| 38 | + help | |
| 39 | + Support for a OneNAND flash device connected to an Samsung SOC. | |
| 40 | + S3C64XX uses command mapping method. | |
| 41 | + S5PC110/S5PC210 use generic OneNAND method. | |
| 42 | 42 | |
| 43 | 43 | config MTD_ONENAND_OTP |
| 44 | 44 | bool "OneNAND OTP Support" |
| @@ -8,7 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | # Board specific. |
| 10 | 10 | obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o |
| 11 | −obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o | |
| 12 | −obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += samsung_mtd.o | |
| 11 | +obj-$(CONFIG_MTD_ONENAND_OMAP2) += onenand_omap2.o | |
| 12 | +obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += onenand_samsung.o | |
| 13 | 13 | |
| 14 | 14 | onenand-objs = onenand_base.o onenand_bbt.o |
| @@ -1248,44 +1248,44 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, · 1247 unmodified lines | ||
| 1248 | 1248 | |
| 1249 | 1249 | stats = mtd->ecc_stats; |
| 1250 | 1250 | |
| 1251 | − /* Read-while-load method */ | |
| 1251 | + /* Read-while-load method */ | |
| 1252 | 1252 | |
| 1253 | − /* Do first load to bufferRAM */ | |
| 1254 | − if (read < len) { | |
| 1255 | − if (!onenand_check_bufferram(mtd, from)) { | |
| 1253 | + /* Do first load to bufferRAM */ | |
| 1254 | + if (read < len) { | |
| 1255 | + if (!onenand_check_bufferram(mtd, from)) { | |
| 1256 | 1256 | this->command(mtd, ONENAND_CMD_READ, from, writesize); |
| 1257 | − ret = this->wait(mtd, FL_READING); | |
| 1258 | − onenand_update_bufferram(mtd, from, !ret); | |
| 1257 | + ret = this->wait(mtd, FL_READING); | |
| 1258 | + onenand_update_bufferram(mtd, from, !ret); | |
| 1259 | 1259 | if (mtd_is_eccerr(ret)) |
| 1260 | 1260 | ret = 0; |
| 1261 | − } | |
| 1262 | − } | |
| 1261 | + } | |
| 1262 | + } | |
| 1263 | 1263 | |
| 1264 | 1264 | thislen = min_t(int, writesize, len - read); |
| 1265 | 1265 | column = from & (writesize - 1); |
| 1266 | 1266 | if (column + thislen > writesize) |
| 1267 | 1267 | thislen = writesize - column; |
| 1268 | 1268 | |
| 1269 | − while (!ret) { | |
| 1270 | − /* If there is more to load then start next load */ | |
| 1271 | − from += thislen; | |
| 1272 | − if (read + thislen < len) { | |
| 1269 | + while (!ret) { | |
| 1270 | + /* If there is more to load then start next load */ | |
| 1271 | + from += thislen; | |
| 1272 | + if (read + thislen < len) { | |
| 1273 | 1273 | this->command(mtd, ONENAND_CMD_READ, from, writesize); |
| 1274 | − /* | |
| 1275 | − * Chip boundary handling in DDP | |
| 1276 | − * Now we issued chip 1 read and pointed chip 1 | |
| 1274 | + /* | |
| 1275 | + * Chip boundary handling in DDP | |
| 1276 | + * Now we issued chip 1 read and pointed chip 1 | |
| 1277 | 1277 | * bufferram so we have to point chip 0 bufferram. |
| 1278 | − */ | |
| 1279 | − if (ONENAND_IS_DDP(this) && | |
| 1280 | − unlikely(from == (this->chipsize >> 1))) { | |
| 1281 | − this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2); | |
| 1282 | − boundary = 1; | |
| 1283 | − } else | |
| 1284 | − boundary = 0; | |
| 1285 | − ONENAND_SET_PREV_BUFFERRAM(this); | |
| 1286 | − } | |
| 1287 | − /* While load is going, read from last bufferRAM */ | |
| 1288 | − this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); | |
| 1278 | + */ | |
| 1279 | + if (ONENAND_IS_DDP(this) && | |
| 1280 | + unlikely(from == (this->chipsize >> 1))) { | |
| 1281 | + this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2); | |
| 1282 | + boundary = 1; | |
| 1283 | + } else | |
| 1284 | + boundary = 0; | |
| 1285 | + ONENAND_SET_PREV_BUFFERRAM(this); | |
| 1286 | + } | |
| 1287 | + /* While load is going, read from last bufferRAM */ | |
| 1288 | + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); | |
| 1289 | 1289 | |
| 1290 | 1290 | /* Read oob area if needed */ |
| 1291 | 1291 | if (oobbuf) { |
| @@ -1301,24 +1301,24 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, · 9 unmodified lines | ||
| 1301 | 1301 | oobcolumn = 0; |
| 1302 | 1302 | } |
| 1303 | 1303 | |
| 1304 | − /* See if we are done */ | |
| 1305 | − read += thislen; | |
| 1306 | − if (read == len) | |
| 1307 | − break; | |
| 1308 | − /* Set up for next read from bufferRAM */ | |
| 1309 | − if (unlikely(boundary)) | |
| 1310 | − this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2); | |
| 1311 | − ONENAND_SET_NEXT_BUFFERRAM(this); | |
| 1312 | − buf += thislen; | |
| 1304 | + /* See if we are done */ | |
| 1305 | + read += thislen; | |
| 1306 | + if (read == len) | |
| 1307 | + break; | |
| 1308 | + /* Set up for next read from bufferRAM */ | |
| 1309 | + if (unlikely(boundary)) | |
| 1310 | + this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2); | |
| 1311 | + ONENAND_SET_NEXT_BUFFERRAM(this); | |
| 1312 | + buf += thislen; | |
| 1313 | 1313 | thislen = min_t(int, writesize, len - read); |
| 1314 | − column = 0; | |
| 1315 | − cond_resched(); | |
| 1316 | − /* Now wait for load */ | |
| 1317 | − ret = this->wait(mtd, FL_READING); | |
| 1318 | − onenand_update_bufferram(mtd, from, !ret); | |
| 1314 | + column = 0; | |
| 1315 | + cond_resched(); | |
| 1316 | + /* Now wait for load */ | |
| 1317 | + ret = this->wait(mtd, FL_READING); | |
| 1318 | + onenand_update_bufferram(mtd, from, !ret); | |
| 1319 | 1319 | if (mtd_is_eccerr(ret)) |
| 1320 | 1320 | ret = 0; |
| 1321 | − } | |
| 1321 | + } | |
| 1322 | 1322 | |
| 1323 | 1323 | /* |
| 1324 | 1324 | * Return success, if no ECC failures, else -EBADMSG |
File renamed without changes.
| @@ -248,7 +248,7 @@ static unsigned short s3c_onenand_readw(void __iomem *addr) · 247 unmodified lines | ||
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | /* BootRAM access control */ |
| 251 | − if ((unsigned int) addr < ONENAND_DATARAM && onenand->bootram_command) { | |
| 251 | + if ((unsigned long)addr < ONENAND_DATARAM && onenand->bootram_command) { | |
| 252 | 252 | if (word_addr == 0) |
| 253 | 253 | return s3c_read_reg(MANUFACT_ID_OFFSET); |
| 254 | 254 | if (word_addr == 1) |
| @@ -289,7 +289,7 @@ static void s3c_onenand_writew(unsigned short value, void __iomem *addr) · 34 unmodified lines | ||
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | /* BootRAM access control */ |
| 292 | − if ((unsigned int)addr < ONENAND_DATARAM) { | |
| 292 | + if ((unsigned long)addr < ONENAND_DATARAM) { | |
| 293 | 293 | if (value == ONENAND_CMD_READID) { |
| 294 | 294 | onenand->bootram_command = 1; |
| 295 | 295 | return; |
| @@ -658,7 +658,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, · 362 unmodified lines | ||
| 658 | 658 | dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); |
| 659 | 659 | } |
| 660 | 660 | if (dma_mapping_error(dev, dma_dst)) { |
| 661 | − dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count); | |
| 661 | + dev_err(dev, "Couldn't map a %zu byte buffer for DMA\n", count); | |
| 662 | 662 | goto normal; |
| 663 | 663 | } |
| 664 | 664 | err = s5pc110_dma_ops(dma_dst, dma_src, |
| @@ -728,13 +728,12 @@ static void s3c_onenand_check_lock_status(struct mtd_info *mtd) · 63 unmodified lines | ||
| 728 | 728 | struct onenand_chip *this = mtd->priv; |
| 729 | 729 | struct device *dev = &onenand->pdev->dev; |
| 730 | 730 | unsigned int block, end; |
| 731 | − int tmp; | |
| 732 | 731 | |
| 733 | 732 | end = this->chipsize >> this->erase_shift; |
| 734 | 733 | |
| 735 | 734 | for (block = 0; block < end; block++) { |
| 736 | 735 | unsigned int mem_addr = onenand->mem_addr(block, 0, 0); |
| 737 | − tmp = s3c_read_cmd(CMD_MAP_01(onenand, mem_addr)); | |
| 736 | + s3c_read_cmd(CMD_MAP_01(onenand, mem_addr)); | |
| 738 | 737 | |
| 739 | 738 | if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) { |
| 740 | 739 | dev_err(dev, "block %d is write-protected!\n", block); |
| @@ -452,7 +452,7 @@ config MTD_NAND_PLATFORM · 451 unmodified lines | ||
| 452 | 452 | |
| 453 | 453 | config MTD_NAND_CADENCE |
| 454 | 454 | tristate "Support Cadence NAND (HPNFC) controller" |
| 455 | − depends on OF || COMPILE_TEST | |
| 455 | + depends on (OF || COMPILE_TEST) && HAS_IOMEM | |
| 456 | 456 | help |
| 457 | 457 | Enable the driver for NAND flash on platforms using a Cadence NAND |
| 458 | 458 | controller. |
| @@ -1578,9 +1578,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, · 1577 unmodified lines | ||
| 1578 | 1578 | |
| 1579 | 1579 | nand->numcs = numcs; |
| 1580 | 1580 | |
| 1581 | − gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "det", 0, | |
| 1582 | − &np->fwnode, GPIOD_IN, | |
| 1583 | − "nand-det"); | |
| 1581 | + gpio = devm_fwnode_gpiod_get(nc->dev, of_fwnode_handle(np), | |
| 1582 | + "det", GPIOD_IN, "nand-det"); | |
| 1584 | 1583 | if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { |
| 1585 | 1584 | dev_err(nc->dev, |
| 1586 | 1585 | "Failed to get detect gpio (err = %ld)\n", |
| @@ -1624,9 +1623,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, · 37 unmodified lines | ||
| 1624 | 1623 | nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB; |
| 1625 | 1624 | nand->cs[i].rb.id = val; |
| 1626 | 1625 | } else { |
| 1627 | − gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, | |
| 1628 | − "rb", i, &np->fwnode, | |
| 1629 | − GPIOD_IN, "nand-rb"); | |
| 1626 | + gpio = devm_fwnode_gpiod_get_index(nc->dev, | |
| 1627 | + of_fwnode_handle(np), | |
| 1628 | + "rb", i, GPIOD_IN, | |
| 1629 | + "nand-rb"); | |
| 1630 | 1630 | if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { |
| 1631 | 1631 | dev_err(nc->dev, |
| 1632 | 1632 | "Failed to get R/B gpio (err = %ld)\n", |
| @@ -1640,10 +1640,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, · 7 unmodified lines | ||
| 1640 | 1640 | } |
| 1641 | 1641 | } |
| 1642 | 1642 | |
| 1643 | − gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "cs", | |
| 1644 | − i, &np->fwnode, | |
| 1645 | − GPIOD_OUT_HIGH, | |
| 1646 | − "nand-cs"); | |
| 1643 | + gpio = devm_fwnode_gpiod_get_index(nc->dev, | |
| 1644 | + of_fwnode_handle(np), | |
| 1645 | + "cs", i, GPIOD_OUT_HIGH, | |
| 1646 | + "nand-cs"); | |
| 1647 | 1647 | if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { |
| 1648 | 1648 | dev_err(nc->dev, |
| 1649 | 1649 | "Failed to get CS gpio (err = %ld)\n", |
| @@ -2635,6 +2635,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) · 2634 unmodified lines | ||
| 2635 | 2635 | /* initialize the dma version */ |
| 2636 | 2636 | brcmnand_flash_dma_revision_init(ctrl); |
| 2637 | 2637 | |
| 2638 | + ret = -EIO; | |
| 2639 | + if (ctrl->nand_version >= 0x0700) | |
| 2640 | + ret = dma_set_mask_and_coherent(&pdev->dev, | |
| 2641 | + DMA_BIT_MASK(40)); | |
| 2642 | + if (ret) | |
| 2643 | + ret = dma_set_mask_and_coherent(&pdev->dev, | |
| 2644 | + DMA_BIT_MASK(32)); | |
| 2645 | + if (ret) | |
| 2646 | + goto err; | |
| 2647 | + | |
| 2638 | 2648 | /* linked-list and stop on error */ |
| 2639 | 2649 | flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK); |
| 2640 | 2650 | flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); |
| @@ -21,7 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "denali.h" |
| 22 | 22 | |
| 23 | 23 | #define DENALI_NAND_NAME "denali-nand" |
| 24 | −#define DENALI_DEFAULT_OOB_SKIP_BYTES 8 | |
| 25 | 24 | |
| 26 | 25 | /* for Indexed Addressing */ |
| 27 | 26 | #define DENALI_INDEXED_CTRL 0x00 |
| @@ -1302,15 +1301,16 @@ int denali_init(struct denali_controller *denali) · 1274 unmodified lines | ||
| 1302 | 1301 | |
| 1303 | 1302 | /* |
| 1304 | 1303 | * Set how many bytes should be skipped before writing data in OOB. |
| 1305 | − * If a non-zero value has already been set (by firmware or something), | |
| 1306 | − * just use it. Otherwise, set the driver's default. | |
| 1304 | + * If a platform requests a non-zero value, set it to the register. | |
| 1305 | + * Otherwise, read the value out, expecting it has already been set up | |
| 1306 | + * by firmware. | |
| 1307 | 1307 | */ |
| 1308 | − denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); | |
| 1309 | − if (!denali->oob_skip_bytes) { | |
| 1310 | − denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; | |
| 1308 | + if (denali->oob_skip_bytes) | |
| 1311 | 1309 | iowrite32(denali->oob_skip_bytes, |
| 1312 | 1310 | denali->reg + SPARE_AREA_SKIP_BYTES); |
| 1313 | − } | |
| 1311 | + else | |
| 1312 | + denali->oob_skip_bytes = ioread32(denali->reg + | |
| 1313 | + SPARE_AREA_SKIP_BYTES); | |
| 1314 | 1314 | |
| 1315 | 1315 | iowrite32(0, denali->reg + TRANSFER_SPARE_REG); |
| 1316 | 1316 | iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/clk.h> |
| 9 | +#include <linux/delay.h> | |
| 9 | 10 | #include <linux/err.h> |
| 10 | 11 | #include <linux/io.h> |
| 11 | 12 | #include <linux/ioport.h> |
| @@ -14,6 +15,7 @@ · 2 unmodified lines | ||
| 14 | 15 | #include <linux/of.h> |
| 15 | 16 | #include <linux/of_device.h> |
| 16 | 17 | #include <linux/platform_device.h> |
| 18 | +#include <linux/reset.h> | |
| 17 | 19 | |
| 18 | 20 | #include "denali.h" |
| 19 | 21 | |
| @@ -22,11 +24,14 @@ struct denali_dt { · 2 unmodified lines | ||
| 22 | 24 | struct clk *clk; /* core clock */ |
| 23 | 25 | struct clk *clk_x; /* bus interface clock */ |
| 24 | 26 | struct clk *clk_ecc; /* ECC circuit clock */ |
| 27 | + struct reset_control *rst; /* core reset */ | |
| 28 | + struct reset_control *rst_reg; /* register reset */ | |
| 25 | 29 | }; |
| 26 | 30 | |
| 27 | 31 | struct denali_dt_data { |
| 28 | 32 | unsigned int revision; |
| 29 | 33 | unsigned int caps; |
| 34 | + unsigned int oob_skip_bytes; | |
| 30 | 35 | const struct nand_ecc_caps *ecc_caps; |
| 31 | 36 | }; |
| 32 | 37 | |
| @@ -34,6 +39,7 @@ NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes, · 1 unmodified line | ||
| 34 | 39 | 512, 8, 15); |
| 35 | 40 | static const struct denali_dt_data denali_socfpga_data = { |
| 36 | 41 | .caps = DENALI_CAP_HW_ECC_FIXUP, |
| 42 | + .oob_skip_bytes = 2, | |
| 37 | 43 | .ecc_caps = &denali_socfpga_ecc_caps, |
| 38 | 44 | }; |
| 39 | 45 | |
| @@ -42,6 +48,7 @@ NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes, · 2 unmodified lines | ||
| 42 | 48 | static const struct denali_dt_data denali_uniphier_v5a_data = { |
| 43 | 49 | .caps = DENALI_CAP_HW_ECC_FIXUP | |
| 44 | 50 | DENALI_CAP_DMA_64BIT, |
| 51 | + .oob_skip_bytes = 8, | |
| 45 | 52 | .ecc_caps = &denali_uniphier_v5a_ecc_caps, |
| 46 | 53 | }; |
| 47 | 54 | |
| @@ -51,6 +58,7 @@ static const struct denali_dt_data denali_uniphier_v5b_data = { · 3 unmodified lines | ||
| 51 | 58 | .revision = 0x0501, |
| 52 | 59 | .caps = DENALI_CAP_HW_ECC_FIXUP | |
| 53 | 60 | DENALI_CAP_DMA_64BIT, |
| 61 | + .oob_skip_bytes = 8, | |
| 54 | 62 | .ecc_caps = &denali_uniphier_v5b_ecc_caps, |
| 55 | 63 | }; |
| 56 | 64 | |
| @@ -118,11 +126,13 @@ static int denali_dt_probe(struct platform_device *pdev) · 61 unmodified lines | ||
| 118 | 126 | denali = &dt->controller; |
| 119 | 127 | |
| 120 | 128 | data = of_device_get_match_data(dev); |
| 121 | − if (data) { | |
| 122 | − denali->revision = data->revision; | |
| 123 | − denali->caps = data->caps; | |
| 124 | − denali->ecc_caps = data->ecc_caps; | |
| 125 | − } | |
| 129 | + if (WARN_ON(!data)) | |
| 130 | + return -EINVAL; | |
| 131 | + | |
| 132 | + denali->revision = data->revision; | |
| 133 | + denali->caps = data->caps; | |
| 134 | + denali->oob_skip_bytes = data->oob_skip_bytes; | |
| 135 | + denali->ecc_caps = data->ecc_caps; | |
| 126 | 136 | |
| 127 | 137 | denali->dev = dev; |
| 128 | 138 | denali->irq = platform_get_irq(pdev, 0); |
| @@ -151,6 +161,14 @@ static int denali_dt_probe(struct platform_device *pdev) · 22 unmodified lines | ||
| 151 | 161 | if (IS_ERR(dt->clk_ecc)) |
| 152 | 162 | return PTR_ERR(dt->clk_ecc); |
| 153 | 163 | |
| 164 | + dt->rst = devm_reset_control_get_optional_shared(dev, "nand"); | |
| 165 | + if (IS_ERR(dt->rst)) | |
| 166 | + return PTR_ERR(dt->rst); | |
| 167 | + | |
| 168 | + dt->rst_reg = devm_reset_control_get_optional_shared(dev, "reg"); | |
| 169 | + if (IS_ERR(dt->rst_reg)) | |
| 170 | + return PTR_ERR(dt->rst_reg); | |
| 171 | + | |
| 154 | 172 | ret = clk_prepare_enable(dt->clk); |
| 155 | 173 | if (ret) |
| 156 | 174 | return ret; |
| @@ -166,10 +184,30 @@ static int denali_dt_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 166 | 184 | denali->clk_rate = clk_get_rate(dt->clk); |
| 167 | 185 | denali->clk_x_rate = clk_get_rate(dt->clk_x); |
| 168 | 186 | |
| 169 | − ret = denali_init(denali); | |
| 187 | + /* | |
| 188 | + * Deassert the register reset, and the core reset in this order. | |
| 189 | + * Deasserting the core reset while the register reset is asserted | |
| 190 | + * will cause unpredictable behavior in the controller. | |
| 191 | + */ | |
| 192 | + ret = reset_control_deassert(dt->rst_reg); | |
| 170 | 193 | if (ret) |
| 171 | 194 | goto out_disable_clk_ecc; |
| 172 | 195 | |
| 196 | + ret = reset_control_deassert(dt->rst); | |
| 197 | + if (ret) | |
| 198 | + goto out_assert_rst_reg; | |
| 199 | + | |
| 200 | + /* | |
| 201 | + * When the reset is deasserted, the initialization sequence is kicked | |
| 202 | + * (bootstrap process). The driver must wait until it finished. | |
| 203 | + * Otherwise, it will result in unpredictable behavior. | |
| 204 | + */ | |
| 205 | + usleep_range(200, 1000); | |
| 206 | + | |
| 207 | + ret = denali_init(denali); | |
| 208 | + if (ret) | |
| 209 | + goto out_assert_rst; | |
| 210 | + | |
| 173 | 211 | for_each_child_of_node(dev->of_node, np) { |
| 174 | 212 | ret = denali_dt_chip_init(denali, np); |
| 175 | 213 | if (ret) { |
| @@ -184,6 +222,10 @@ static int denali_dt_probe(struct platform_device *pdev) · 8 unmodified lines | ||
| 184 | 222 | |
| 185 | 223 | out_remove_denali: |
| 186 | 224 | denali_remove(denali); |
| 225 | +out_assert_rst: | |
| 226 | + reset_control_assert(dt->rst); | |
| 227 | +out_assert_rst_reg: | |
| 228 | + reset_control_assert(dt->rst_reg); | |
| 187 | 229 | out_disable_clk_ecc: |
| 188 | 230 | clk_disable_unprepare(dt->clk_ecc); |
| 189 | 231 | out_disable_clk_x: |
| @@ -199,6 +241,8 @@ static int denali_dt_remove(struct platform_device *pdev) · 9 unmodified lines | ||
| 199 | 241 | struct denali_dt *dt = platform_get_drvdata(pdev); |
| 200 | 242 | |
| 201 | 243 | denali_remove(&dt->controller); |
| 244 | + reset_control_assert(dt->rst); | |
| 245 | + reset_control_assert(dt->rst_reg); | |
| 202 | 246 | clk_disable_unprepare(dt->clk_ecc); |
| 203 | 247 | clk_disable_unprepare(dt->clk_x); |
| 204 | 248 | clk_disable_unprepare(dt->clk); |
| @@ -438,7 +438,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, · 437 unmodified lines | ||
| 438 | 438 | buffer += blksize; |
| 439 | 439 | offset += blksize; |
| 440 | 440 | size -= blksize; |
| 441 | − }; | |
| 441 | + } | |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | 444 | /* Copy data from/to NFC main and spare buffers */ |
| @@ -59,7 +59,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip) · 58 unmodified lines | ||
| 59 | 59 | */ |
| 60 | 60 | static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) |
| 61 | 61 | { |
| 62 | − unsigned int i; | |
| 62 | + int i; | |
| 63 | 63 | static const char * const broken_get_timings[] = { |
| 64 | 64 | "MX30LF1G18AC", |
| 65 | 65 | "MX30LF1G28AC", |
| @@ -80,12 +80,9 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) · 14 unmodified lines | ||
| 80 | 80 | if (!chip->parameters.supports_set_get_features) |
| 81 | 81 | return; |
| 82 | 82 | |
| 83 | − for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) { | |
| 84 | − if (!strcmp(broken_get_timings[i], chip->parameters.model)) | |
| 85 | − break; | |
| 86 | − } | |
| 87 | − | |
| 88 | − if (i == ARRAY_SIZE(broken_get_timings)) | |
| 83 | + i = match_string(broken_get_timings, ARRAY_SIZE(broken_get_timings), | |
| 84 | + chip->parameters.model); | |
| 85 | + if (i < 0) | |
| 89 | 86 | return; |
| 90 | 87 | |
| 91 | 88 | bitmap_clear(chip->parameters.get_feature_list, |
| @@ -124,6 +124,16 @@ static const struct spinand_info toshiba_spinand_table[] = { · 123 unmodified lines | ||
| 124 | 124 | 0, |
| 125 | 125 | SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, |
| 126 | 126 | tc58cxgxsx_ecc_get_status)), |
| 127 | + /* 3.3V 4Gb */ | |
| 128 | + SPINAND_INFO("TC58CVG2S0", 0xED, | |
| 129 | + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), | |
| 130 | + NAND_ECCREQ(8, 512), | |
| 131 | + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | |
| 132 | + &write_cache_variants, | |
| 133 | + &update_cache_variants), | |
| 134 | + 0, | |
| 135 | + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, | |
| 136 | + tc58cxgxsx_ecc_get_status)), | |
| 127 | 137 | /* 1.8V 1Gb */ |
| 128 | 138 | SPINAND_INFO("TC58CYG0S3", 0xB2, |
| 129 | 139 | NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), |
| @@ -165,10 +165,10 @@ static int sharpsl_nand_get_logical_num(u8 *oob) · 164 unmodified lines | ||
| 165 | 165 | |
| 166 | 166 | static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl) |
| 167 | 167 | { |
| 168 | − unsigned int block_num, log_num, phymax; | |
| 168 | + unsigned int block_num, phymax; | |
| 169 | + int i, ret, log_num; | |
| 169 | 170 | loff_t block_adr; |
| 170 | 171 | u8 *oob; |
| 171 | − int i, ret; | |
| 172 | 172 | |
| 173 | 173 | oob = kzalloc(mtd->oobsize, GFP_KERNEL); |
| 174 | 174 | if (!oob) |
| @@ -46,11 +46,11 @@ config SPI_CADENCE_QUADSPI · 45 unmodified lines | ||
| 46 | 46 | Flash as an MTD device. |
| 47 | 47 | |
| 48 | 48 | config SPI_HISI_SFC |
| 49 | − tristate "Hisilicon SPI-NOR Flash Controller(SFC)" | |
| 49 | + tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)" | |
| 50 | 50 | depends on ARCH_HISI || COMPILE_TEST |
| 51 | 51 | depends on HAS_IOMEM |
| 52 | 52 | help |
| 53 | − This enables support for hisilicon SPI-NOR flash controller. | |
| 53 | + This enables support for HiSilicon FMC SPI-NOR flash controller. | |
| 54 | 54 | |
| 55 | 55 | config SPI_MTK_QUADSPI |
| 56 | 56 | tristate "MediaTek Quad SPI controller" |
| @@ -305,7 +305,7 @@ static void aspeed_smc_stop_user(struct spi_nor *nor) · 304 unmodified lines | ||
| 305 | 305 | writel(ctl, chip->ctl); /* default to fread or read mode */ |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | −static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 308 | +static int aspeed_smc_prep(struct spi_nor *nor) | |
| 309 | 309 | { |
| 310 | 310 | struct aspeed_smc_chip *chip = nor->priv; |
| 311 | 311 | |
| @@ -313,7 +313,7 @@ static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) · 1 unmodified line | ||
| 313 | 313 | return 0; |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | −static void aspeed_smc_unprep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 316 | +static void aspeed_smc_unprep(struct spi_nor *nor) | |
| 317 | 317 | { |
| 318 | 318 | struct aspeed_smc_chip *chip = nor->priv; |
| 319 | 319 | |
| @@ -1062,7 +1062,7 @@ static int cqspi_erase(struct spi_nor *nor, loff_t offs) · 1061 unmodified lines | ||
| 1062 | 1062 | return 0; |
| 1063 | 1063 | } |
| 1064 | 1064 | |
| 1065 | −static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 1065 | +static int cqspi_prep(struct spi_nor *nor) | |
| 1066 | 1066 | { |
| 1067 | 1067 | struct cqspi_flash_pdata *f_pdata = nor->priv; |
| 1068 | 1068 | struct cqspi_st *cqspi = f_pdata->cqspi; |
| @@ -1072,7 +1072,7 @@ static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) · 3 unmodified lines | ||
| 1072 | 1072 | return 0; |
| 1073 | 1073 | } |
| 1074 | 1074 | |
| 1075 | −static void cqspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 1075 | +static void cqspi_unprep(struct spi_nor *nor) | |
| 1076 | 1076 | { |
| 1077 | 1077 | struct cqspi_flash_pdata *f_pdata = nor->priv; |
| 1078 | 1078 | struct cqspi_st *cqspi = f_pdata->cqspi; |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * HiSilicon SPI Nor Flash Controller Driver | |
| 3 | + * HiSilicon FMC SPI-NOR flash controller driver | |
| 4 | 4 | * |
| 5 | 5 | * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd. |
| 6 | 6 | */ |
| @@ -144,7 +144,7 @@ static void hisi_spi_nor_init(struct hifmc_host *host) · 137 unmodified lines | ||
| 144 | 144 | writel(reg, host->regbase + FMC_SPI_TIMING_CFG); |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | −static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 147 | +static int hisi_spi_nor_prep(struct spi_nor *nor) | |
| 148 | 148 | { |
| 149 | 149 | struct hifmc_priv *priv = nor->priv; |
| 150 | 150 | struct hifmc_host *host = priv->host; |
| @@ -167,7 +167,7 @@ out: · 16 unmodified lines | ||
| 167 | 167 | return ret; |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | −static void hisi_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 170 | +static void hisi_spi_nor_unprep(struct spi_nor *nor) | |
| 171 | 171 | { |
| 172 | 172 | struct hifmc_priv *priv = nor->priv; |
| 173 | 173 | struct hifmc_host *host = priv->host; |
| @@ -70,10 +70,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = { · 69 unmodified lines | ||
| 70 | 70 | { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, |
| 71 | 71 | { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, |
| 72 | 72 | { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, |
| 73 | + { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, | |
| 73 | 74 | { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info }, |
| 74 | 75 | { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, |
| 75 | 76 | { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info }, |
| 76 | 77 | { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, |
| 78 | + { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&bxt_info }, | |
| 77 | 79 | { }, |
| 78 | 80 | }; |
| 79 | 81 | MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); |
| @@ -85,7 +85,7 @@ struct sfdp_header { · 84 unmodified lines | ||
| 85 | 85 | #define BFPT_DWORD(i) ((i) - 1) |
| 86 | 86 | #define BFPT_DWORD_MAX 16 |
| 87 | 87 | |
| 88 | −/* The first version of JESB216 defined only 9 DWORDs. */ | |
| 88 | +/* The first version of JESD216 defined only 9 DWORDs. */ | |
| 89 | 89 | #define BFPT_DWORD_MAX_JESD216 9 |
| 90 | 90 | |
| 91 | 91 | /* 1st DWORD. */ |
| @@ -196,7 +196,7 @@ struct flash_info { · 104 unmodified lines | ||
| 196 | 196 | u16 page_size; |
| 197 | 197 | u16 addr_width; |
| 198 | 198 | |
| 199 | − u16 flags; | |
| 199 | + u32 flags; | |
| 200 | 200 | #define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ |
| 201 | 201 | #define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ |
| 202 | 202 | #define SST_WRITE BIT(2) /* use SST byte programming */ |
| @@ -233,6 +233,11 @@ struct flash_info { · 30 unmodified lines | ||
| 233 | 233 | #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ |
| 234 | 234 | #define USE_CLSR BIT(14) /* use CLSR command */ |
| 235 | 235 | #define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ |
| 236 | +#define SPI_NOR_TB_SR_BIT6 BIT(16) /* | |
| 237 | + * Top/Bottom (TB) is bit 6 of | |
| 238 | + * status register. Must be used with | |
| 239 | + * SPI_NOR_HAS_TB. | |
| 240 | + */ | |
| 236 | 241 | |
| 237 | 242 | /* Part specific fixup hooks. */ |
| 238 | 243 | const struct spi_nor_fixups *fixups; |
| @@ -1307,14 +1312,14 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) · 1068 unmodified lines | ||
| 1307 | 1312 | } |
| 1308 | 1313 | } |
| 1309 | 1314 | |
| 1310 | −static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 1315 | +static int spi_nor_lock_and_prep(struct spi_nor *nor) | |
| 1311 | 1316 | { |
| 1312 | 1317 | int ret = 0; |
| 1313 | 1318 | |
| 1314 | 1319 | mutex_lock(&nor->lock); |
| 1315 | 1320 | |
| 1316 | 1321 | if (nor->controller_ops && nor->controller_ops->prepare) { |
| 1317 | − ret = nor->controller_ops->prepare(nor, ops); | |
| 1322 | + ret = nor->controller_ops->prepare(nor); | |
| 1318 | 1323 | if (ret) { |
| 1319 | 1324 | mutex_unlock(&nor->lock); |
| 1320 | 1325 | return ret; |
| @@ -1323,10 +1328,10 @@ static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) · 2 unmodified lines | ||
| 1323 | 1328 | return ret; |
| 1324 | 1329 | } |
| 1325 | 1330 | |
| 1326 | −static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) | |
| 1331 | +static void spi_nor_unlock_and_unprep(struct spi_nor *nor) | |
| 1327 | 1332 | { |
| 1328 | 1333 | if (nor->controller_ops && nor->controller_ops->unprepare) |
| 1329 | − nor->controller_ops->unprepare(nor, ops); | |
| 1334 | + nor->controller_ops->unprepare(nor); | |
| 1330 | 1335 | mutex_unlock(&nor->lock); |
| 1331 | 1336 | } |
| 1332 | 1337 | |
| @@ -1688,7 +1693,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) · 355 unmodified lines | ||
| 1688 | 1693 | addr = instr->addr; |
| 1689 | 1694 | len = instr->len; |
| 1690 | 1695 | |
| 1691 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE); | |
| 1696 | + ret = spi_nor_lock_and_prep(nor); | |
| 1692 | 1697 | if (ret) |
| 1693 | 1698 | return ret; |
| 1694 | 1699 | |
| @@ -1751,7 +1756,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) · 56 unmodified lines | ||
| 1751 | 1756 | ret = spi_nor_write_disable(nor); |
| 1752 | 1757 | |
| 1753 | 1758 | erase_err: |
| 1754 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); | |
| 1759 | + spi_nor_unlock_and_unprep(nor); | |
| 1755 | 1760 | |
| 1756 | 1761 | return ret; |
| 1757 | 1762 | } |
| @@ -1761,9 +1766,13 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, · 3 unmodified lines | ||
| 1761 | 1766 | { |
| 1762 | 1767 | struct mtd_info *mtd = &nor->mtd; |
| 1763 | 1768 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 1769 | + u8 tb_mask = SR_TB_BIT5; | |
| 1764 | 1770 | int shift = ffs(mask) - 1; |
| 1765 | 1771 | int pow; |
| 1766 | 1772 | |
| 1773 | + if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) | |
| 1774 | + tb_mask = SR_TB_BIT6; | |
| 1775 | + | |
| 1767 | 1776 | if (!(sr & mask)) { |
| 1768 | 1777 | /* No protection */ |
| 1769 | 1778 | *ofs = 0; |
| @@ -1771,7 +1780,7 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, · 1 unmodified line | ||
| 1771 | 1780 | } else { |
| 1772 | 1781 | pow = ((sr & mask) ^ mask) >> shift; |
| 1773 | 1782 | *len = mtd->size >> pow; |
| 1774 | − if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) | |
| 1783 | + if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask) | |
| 1775 | 1784 | *ofs = 0; |
| 1776 | 1785 | else |
| 1777 | 1786 | *ofs = mtd->size - *len; |
| @@ -1850,6 +1859,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 72 unmodified lines | ||
| 1850 | 1859 | struct mtd_info *mtd = &nor->mtd; |
| 1851 | 1860 | int ret, status_old, status_new; |
| 1852 | 1861 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 1862 | + u8 tb_mask = SR_TB_BIT5; | |
| 1853 | 1863 | u8 shift = ffs(mask) - 1, pow, val; |
| 1854 | 1864 | loff_t lock_len; |
| 1855 | 1865 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; |
| @@ -1886,6 +1896,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 30 unmodified lines | ||
| 1886 | 1896 | else |
| 1887 | 1897 | lock_len = ofs + len; |
| 1888 | 1898 | |
| 1899 | + if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) | |
| 1900 | + tb_mask = SR_TB_BIT6; | |
| 1901 | + | |
| 1889 | 1902 | /* |
| 1890 | 1903 | * Need smallest pow such that: |
| 1891 | 1904 | * |
| @@ -1903,13 +1916,13 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 11 unmodified lines | ||
| 1903 | 1916 | if (!(val & mask)) |
| 1904 | 1917 | return -EINVAL; |
| 1905 | 1918 | |
| 1906 | − status_new = (status_old & ~mask & ~SR_TB) | val; | |
| 1919 | + status_new = (status_old & ~mask & ~tb_mask) | val; | |
| 1907 | 1920 | |
| 1908 | 1921 | /* Disallow further writes if WP pin is asserted */ |
| 1909 | 1922 | status_new |= SR_SRWD; |
| 1910 | 1923 | |
| 1911 | 1924 | if (!use_top) |
| 1912 | − status_new |= SR_TB; | |
| 1925 | + status_new |= tb_mask; | |
| 1913 | 1926 | |
| 1914 | 1927 | /* Don't bother if they're the same */ |
| 1915 | 1928 | if (status_new == status_old) |
| @@ -1932,6 +1945,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 16 unmodified lines | ||
| 1932 | 1945 | struct mtd_info *mtd = &nor->mtd; |
| 1933 | 1946 | int ret, status_old, status_new; |
| 1934 | 1947 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 1948 | + u8 tb_mask = SR_TB_BIT5; | |
| 1935 | 1949 | u8 shift = ffs(mask) - 1, pow, val; |
| 1936 | 1950 | loff_t lock_len; |
| 1937 | 1951 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; |
| @@ -1968,6 +1982,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 30 unmodified lines | ||
| 1968 | 1982 | else |
| 1969 | 1983 | lock_len = ofs; |
| 1970 | 1984 | |
| 1985 | + if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) | |
| 1986 | + tb_mask = SR_TB_BIT6; | |
| 1971 | 1987 | /* |
| 1972 | 1988 | * Need largest pow such that: |
| 1973 | 1989 | * |
| @@ -1987,14 +2003,14 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) · 13 unmodified lines | ||
| 1987 | 2003 | return -EINVAL; |
| 1988 | 2004 | } |
| 1989 | 2005 | |
| 1990 | − status_new = (status_old & ~mask & ~SR_TB) | val; | |
| 2006 | + status_new = (status_old & ~mask & ~tb_mask) | val; | |
| 1991 | 2007 | |
| 1992 | 2008 | /* Don't protect status register if we're fully unlocked */ |
| 1993 | 2009 | if (lock_len == 0) |
| 1994 | 2010 | status_new &= ~SR_SRWD; |
| 1995 | 2011 | |
| 1996 | 2012 | if (!use_top) |
| 1997 | − status_new |= SR_TB; | |
| 2013 | + status_new |= tb_mask; | |
| 1998 | 2014 | |
| 1999 | 2015 | /* Don't bother if they're the same */ |
| 2000 | 2016 | if (status_new == status_old) |
| @@ -2036,13 +2052,13 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 35 unmodified lines | ||
| 2036 | 2052 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 2037 | 2053 | int ret; |
| 2038 | 2054 | |
| 2039 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); | |
| 2055 | + ret = spi_nor_lock_and_prep(nor); | |
| 2040 | 2056 | if (ret) |
| 2041 | 2057 | return ret; |
| 2042 | 2058 | |
| 2043 | 2059 | ret = nor->params.locking_ops->lock(nor, ofs, len); |
| 2044 | 2060 | |
| 2045 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); | |
| 2061 | + spi_nor_unlock_and_unprep(nor); | |
| 2046 | 2062 | return ret; |
| 2047 | 2063 | } |
| 2048 | 2064 | |
| @@ -2051,13 +2067,13 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 2 unmodified lines | ||
| 2051 | 2067 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 2052 | 2068 | int ret; |
| 2053 | 2069 | |
| 2054 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); | |
| 2070 | + ret = spi_nor_lock_and_prep(nor); | |
| 2055 | 2071 | if (ret) |
| 2056 | 2072 | return ret; |
| 2057 | 2073 | |
| 2058 | 2074 | ret = nor->params.locking_ops->unlock(nor, ofs, len); |
| 2059 | 2075 | |
| 2060 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); | |
| 2076 | + spi_nor_unlock_and_unprep(nor); | |
| 2061 | 2077 | return ret; |
| 2062 | 2078 | } |
| 2063 | 2079 | |
| @@ -2066,13 +2082,13 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 2 unmodified lines | ||
| 2066 | 2082 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 2067 | 2083 | int ret; |
| 2068 | 2084 | |
| 2069 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); | |
| 2085 | + ret = spi_nor_lock_and_prep(nor); | |
| 2070 | 2086 | if (ret) |
| 2071 | 2087 | return ret; |
| 2072 | 2088 | |
| 2073 | 2089 | ret = nor->params.locking_ops->is_locked(nor, ofs, len); |
| 2074 | 2090 | |
| 2075 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); | |
| 2091 | + spi_nor_unlock_and_unprep(nor); | |
| 2076 | 2092 | return ret; |
| 2077 | 2093 | } |
| 2078 | 2094 | |
| @@ -2309,6 +2325,9 @@ static const struct flash_info spi_nor_ids[] = { · 230 unmodified lines | ||
| 2309 | 2325 | { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, |
| 2310 | 2326 | { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, |
| 2311 | 2327 | |
| 2328 | + { "at25sl321", INFO(0x1f4216, 0, 64 * 1024, 64, | |
| 2329 | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | |
| 2330 | + | |
| 2312 | 2331 | { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, |
| 2313 | 2332 | { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, |
| 2314 | 2333 | { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, |
| @@ -2373,6 +2392,11 @@ static const struct flash_info spi_nor_ids[] = { · 58 unmodified lines | ||
| 2373 | 2392 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 2374 | 2393 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 2375 | 2394 | }, |
| 2395 | + { | |
| 2396 | + "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256, | |
| 2397 | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | |
| 2398 | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | |
| 2399 | + }, | |
| 2376 | 2400 | { |
| 2377 | 2401 | "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, |
| 2378 | 2402 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| @@ -2381,7 +2405,8 @@ static const struct flash_info spi_nor_ids[] = { · 2 unmodified lines | ||
| 2381 | 2405 | { |
| 2382 | 2406 | "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512, |
| 2383 | 2407 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 2384 | − SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | |
| 2408 | + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | | |
| 2409 | + SPI_NOR_TB_SR_BIT6) | |
| 2385 | 2410 | .fixups = &gd25q256_fixups, |
| 2386 | 2411 | }, |
| 2387 | 2412 | |
| @@ -2436,6 +2461,8 @@ static const struct flash_info spi_nor_ids[] = { · 48 unmodified lines | ||
| 2436 | 2461 | { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, |
| 2437 | 2462 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, |
| 2438 | 2463 | { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, |
| 2464 | + { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, | |
| 2465 | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | |
| 2439 | 2466 | { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, |
| 2440 | 2467 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 2441 | 2468 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, |
| @@ -2456,20 +2483,35 @@ static const struct flash_info spi_nor_ids[] = { · 14 unmodified lines | ||
| 2456 | 2483 | { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, |
| 2457 | 2484 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 2458 | 2485 | { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 2459 | − { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, | |
| 2460 | − { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, | |
| 2461 | − { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | |
| 2462 | − { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, | |
| 2486 | + { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | | |
| 2487 | + USE_FSR | SPI_NOR_QUAD_READ) }, | |
| 2488 | + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | | |
| 2489 | + USE_FSR | SPI_NOR_QUAD_READ) }, | |
| 2490 | + { "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512, | |
| 2491 | + SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | | |
| 2492 | + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | |
| 2493 | + { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | | |
| 2494 | + USE_FSR | SPI_NOR_DUAL_READ | | |
| 2495 | + SPI_NOR_QUAD_READ) }, | |
| 2496 | + { "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512, | |
| 2497 | + SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | | |
| 2498 | + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | |
| 2499 | + { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | | |
| 2500 | + USE_FSR | SPI_NOR_QUAD_READ) }, | |
| 2501 | + { "mt25ql512a", INFO6(0x20ba20, 0x104400, 64 * 1024, 1024, | |
| 2502 | + SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | | |
| 2503 | + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | |
| 2463 | 2504 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 2505 | + { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024, | |
| 2506 | + SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | | |
| 2507 | + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | |
| 2508 | + { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | | |
| 2509 | + USE_FSR | SPI_NOR_QUAD_READ) }, | |
| 2464 | 2510 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 2465 | 2511 | { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 2466 | 2512 | { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096, |
| 2467 | 2513 | SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | |
| 2468 | 2514 | NO_CHIP_ERASE) }, |
| 2469 | − { "mt25qu512a (n25q512a)", INFO(0x20bb20, 0, 64 * 1024, 1024, | |
| 2470 | − SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | | |
| 2471 | − SPI_NOR_QUAD_READ | | |
| 2472 | − SPI_NOR_4B_OPCODES) }, | |
| 2473 | 2515 | { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 2474 | 2516 | |
| 2475 | 2517 | /* Micron */ |
| @@ -2540,6 +2582,8 @@ static const struct flash_info spi_nor_ids[] = { · 64 unmodified lines | ||
| 2540 | 2582 | { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, |
| 2541 | 2583 | { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K | |
| 2542 | 2584 | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 2585 | + { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32, SECT_4K | | |
| 2586 | + SPI_NOR_DUAL_READ) }, | |
| 2543 | 2587 | { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 2544 | 2588 | |
| 2545 | 2589 | /* ST Microelectronics -- newer production may have feature updates */ |
| @@ -2610,6 +2654,11 @@ static const struct flash_info spi_nor_ids[] = { · 64 unmodified lines | ||
| 2610 | 2654 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 2611 | 2655 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 2612 | 2656 | }, |
| 2657 | + { | |
| 2658 | + "w25q32jwm", INFO(0xef8016, 0, 64 * 1024, 64, | |
| 2659 | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | |
| 2660 | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | |
| 2661 | + }, | |
| 2613 | 2662 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
| 2614 | 2663 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
| 2615 | 2664 | { |
| @@ -2630,7 +2679,9 @@ static const struct flash_info spi_nor_ids[] = { · 14 unmodified lines | ||
| 2630 | 2679 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, |
| 2631 | 2680 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, |
| 2632 | 2681 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, |
| 2633 | − { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | |
| 2682 | + { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, | |
| 2683 | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | |
| 2684 | + SPI_NOR_4B_OPCODES) }, | |
| 2634 | 2685 | { "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512, |
| 2635 | 2686 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 2636 | 2687 | { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512, |
| @@ -2701,7 +2752,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, · 64 unmodified lines | ||
| 2701 | 2752 | |
| 2702 | 2753 | dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); |
| 2703 | 2754 | |
| 2704 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ); | |
| 2755 | + ret = spi_nor_lock_and_prep(nor); | |
| 2705 | 2756 | if (ret) |
| 2706 | 2757 | return ret; |
| 2707 | 2758 | |
| @@ -2728,7 +2779,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, · 20 unmodified lines | ||
| 2728 | 2779 | ret = 0; |
| 2729 | 2780 | |
| 2730 | 2781 | read_err: |
| 2731 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); | |
| 2782 | + spi_nor_unlock_and_unprep(nor); | |
| 2732 | 2783 | return ret; |
| 2733 | 2784 | } |
| 2734 | 2785 | |
| @@ -2741,7 +2792,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, · 6 unmodified lines | ||
| 2741 | 2792 | |
| 2742 | 2793 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); |
| 2743 | 2794 | |
| 2744 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); | |
| 2795 | + ret = spi_nor_lock_and_prep(nor); | |
| 2745 | 2796 | if (ret) |
| 2746 | 2797 | return ret; |
| 2747 | 2798 | |
| @@ -2814,7 +2865,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, · 66 unmodified lines | ||
| 2814 | 2865 | } |
| 2815 | 2866 | out: |
| 2816 | 2867 | *retlen += actual; |
| 2817 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); | |
| 2868 | + spi_nor_unlock_and_unprep(nor); | |
| 2818 | 2869 | return ret; |
| 2819 | 2870 | } |
| 2820 | 2871 | |
| @@ -2832,7 +2883,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, · 11 unmodified lines | ||
| 2832 | 2883 | |
| 2833 | 2884 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); |
| 2834 | 2885 | |
| 2835 | − ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); | |
| 2886 | + ret = spi_nor_lock_and_prep(nor); | |
| 2836 | 2887 | if (ret) |
| 2837 | 2888 | return ret; |
| 2838 | 2889 | |
| @@ -2878,7 +2929,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, · 39 unmodified lines | ||
| 2878 | 2929 | } |
| 2879 | 2930 | |
| 2880 | 2931 | write_err: |
| 2881 | − spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); | |
| 2932 | + spi_nor_unlock_and_unprep(nor); | |
| 2882 | 2933 | return ret; |
| 2883 | 2934 | } |
| 2884 | 2935 | |
| @@ -5143,8 +5194,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, · 2258 unmodified lines | ||
| 5143 | 5194 | |
| 5144 | 5195 | if (info->flags & USE_FSR) |
| 5145 | 5196 | nor->flags |= SNOR_F_USE_FSR; |
| 5146 | − if (info->flags & SPI_NOR_HAS_TB) | |
| 5197 | + if (info->flags & SPI_NOR_HAS_TB) { | |
| 5147 | 5198 | nor->flags |= SNOR_F_HAS_SR_TB; |
| 5199 | + if (info->flags & SPI_NOR_TB_SR_BIT6) | |
| 5200 | + nor->flags |= SNOR_F_HAS_SR_TB_BIT6; | |
| 5201 | + } | |
| 5202 | + | |
| 5148 | 5203 | if (info->flags & NO_CHIP_ERASE) |
| 5149 | 5204 | nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; |
| 5150 | 5205 | if (info->flags & USE_CLSR) |
| @@ -128,7 +128,8 @@ · 127 unmodified lines | ||
| 128 | 128 | #define SR_BP0 BIT(2) /* Block protect 0 */ |
| 129 | 129 | #define SR_BP1 BIT(3) /* Block protect 1 */ |
| 130 | 130 | #define SR_BP2 BIT(4) /* Block protect 2 */ |
| 131 | −#define SR_TB BIT(5) /* Top/Bottom protect */ | |
| 131 | +#define SR_TB_BIT5 BIT(5) /* Top/Bottom protect */ | |
| 132 | +#define SR_TB_BIT6 BIT(6) /* Top/Bottom protect */ | |
| 132 | 133 | #define SR_SRWD BIT(7) /* SR write protect */ |
| 133 | 134 | /* Spansion/Cypress specific status bits */ |
| 134 | 135 | #define SR_E_ERR BIT(5) |
| @@ -224,14 +225,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto) · 89 unmodified lines | ||
| 224 | 225 | return spi_nor_get_protocol_data_nbits(proto); |
| 225 | 226 | } |
| 226 | 227 | |
| 227 | −enum spi_nor_ops { | |
| 228 | − SPI_NOR_OPS_READ = 0, | |
| 229 | − SPI_NOR_OPS_WRITE, | |
| 230 | − SPI_NOR_OPS_ERASE, | |
| 231 | − SPI_NOR_OPS_LOCK, | |
| 232 | − SPI_NOR_OPS_UNLOCK, | |
| 233 | −}; | |
| 234 | − | |
| 235 | 228 | enum spi_nor_option_flags { |
| 236 | 229 | SNOR_F_USE_FSR = BIT(0), |
| 237 | 230 | SNOR_F_HAS_SR_TB = BIT(1), |
| @@ -244,6 +237,7 @@ enum spi_nor_option_flags { · 6 unmodified lines | ||
| 244 | 237 | SNOR_F_HAS_LOCK = BIT(8), |
| 245 | 238 | SNOR_F_HAS_16BIT_SR = BIT(9), |
| 246 | 239 | SNOR_F_NO_READ_CR = BIT(10), |
| 240 | + SNOR_F_HAS_SR_TB_BIT6 = BIT(11), | |
| 247 | 241 | |
| 248 | 242 | }; |
| 249 | 243 | |
| @@ -483,8 +477,8 @@ struct spi_nor; · 233 unmodified lines | ||
| 483 | 477 | * opcode via write_reg(). |
| 484 | 478 | */ |
| 485 | 479 | struct spi_nor_controller_ops { |
| 486 | − int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); | |
| 487 | − void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); | |
| 480 | + int (*prepare)(struct spi_nor *nor); | |
| 481 | + void (*unprepare)(struct spi_nor *nor); | |
| 488 | 482 | int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len); |
| 489 | 483 | int (*write_reg)(struct spi_nor *nor, u8 opcode, const u8 *buf, |
| 490 | 484 | size_t len); |