Commit c4e8862308d420e85c227498797c32410d9e47a8
mtd: spi: Switch to new SPI NOR framework
Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD layer. Fix up sf_dataflash to work in legacy way. And update sandbox to use new interfaces/definitions Signed-off-by: Vignesh R <vigneshr@ti.com> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> Tested-by: Stefan Roese <sr@denx.de> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> Reviewed-by: Jagan Teki <jagan@openedev.com> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed
Showing 9 changed files with 113 additions and 365 deletions Inline Diff
| 1 | menu "SPI Flash Support" | 1 | menu "SPI Flash Support" |
| 2 | 2 | ||
| 3 | config DM_SPI_FLASH | 3 | config DM_SPI_FLASH |
| 4 | bool "Enable Driver Model for SPI flash" | 4 | bool "Enable Driver Model for SPI flash" |
| 5 | depends on DM && DM_SPI | 5 | depends on DM && DM_SPI |
| 6 | help | 6 | help |
| 7 | Enable driver model for SPI flash. This SPI flash interface | 7 | Enable driver model for SPI flash. This SPI flash interface |
| 8 | (spi_flash_probe(), spi_flash_write(), etc.) is then | 8 | (spi_flash_probe(), spi_flash_write(), etc.) is then |
| 9 | implemented by the SPI flash uclass. There is one standard | 9 | implemented by the SPI flash uclass. There is one standard |
| 10 | SPI flash driver which knows how to probe most chips | 10 | SPI flash driver which knows how to probe most chips |
| 11 | supported by U-Boot. The uclass interface is defined in | 11 | supported by U-Boot. The uclass interface is defined in |
| 12 | include/spi_flash.h, but is currently fully compatible | 12 | include/spi_flash.h, but is currently fully compatible |
| 13 | with the old interface to avoid confusion and duplication | 13 | with the old interface to avoid confusion and duplication |
| 14 | during the transition parent. SPI and SPI flash must be | 14 | during the transition parent. SPI and SPI flash must be |
| 15 | enabled together (it is not possible to use driver model | 15 | enabled together (it is not possible to use driver model |
| 16 | for one and not the other). | 16 | for one and not the other). |
| 17 | 17 | ||
| 18 | config SPI_FLASH_SANDBOX | 18 | config SPI_FLASH_SANDBOX |
| 19 | bool "Support sandbox SPI flash device" | 19 | bool "Support sandbox SPI flash device" |
| 20 | depends on SANDBOX && DM_SPI_FLASH | 20 | depends on SANDBOX && DM_SPI_FLASH |
| 21 | help | 21 | help |
| 22 | Since sandbox cannot access real devices, an emulation mechanism is | 22 | Since sandbox cannot access real devices, an emulation mechanism is |
| 23 | provided instead. Drivers can be connected up to the sandbox SPI | 23 | provided instead. Drivers can be connected up to the sandbox SPI |
| 24 | bus (see CONFIG_SANDBOX_SPI) and SPI traffic will be routed to this | 24 | bus (see CONFIG_SANDBOX_SPI) and SPI traffic will be routed to this |
| 25 | device. Typically the contents of the emulated SPI flash device is | 25 | device. Typically the contents of the emulated SPI flash device is |
| 26 | stored in a file on the host filesystem. | 26 | stored in a file on the host filesystem. |
| 27 | 27 | ||
| 28 | config SPI_FLASH | 28 | config SPI_FLASH |
| 29 | bool "Legacy SPI Flash Interface support" | 29 | bool "Legacy SPI Flash Interface support" |
| 30 | depends on SPI | ||
| 31 | select SPI_MEM | ||
| 30 | help | 32 | help |
| 31 | Enable the legacy SPI flash support. This will include basic | 33 | Enable the legacy SPI flash support. This will include basic |
| 32 | standard support for things like probing, read / write, and | 34 | standard support for things like probing, read / write, and |
| 33 | erasing through cmd_sf interface. | 35 | erasing through cmd_sf interface. |
| 34 | 36 | ||
| 35 | If unsure, say N | 37 | If unsure, say N |
| 36 | 38 | ||
| 37 | if SPI_FLASH | 39 | if SPI_FLASH |
| 38 | 40 | ||
| 39 | config SPI_FLASH_SFDP_SUPPORT | 41 | config SPI_FLASH_SFDP_SUPPORT |
| 40 | bool "SFDP table parsing support for SPI NOR flashes" | 42 | bool "SFDP table parsing support for SPI NOR flashes" |
| 41 | depends on !SPI_FLASH_BAR | 43 | depends on !SPI_FLASH_BAR |
| 42 | help | 44 | help |
| 43 | Enable support for parsing and auto discovery of parameters for | 45 | Enable support for parsing and auto discovery of parameters for |
| 44 | SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) | 46 | SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) |
| 45 | tables as per JESD216 standard. | 47 | tables as per JESD216 standard. |
| 46 | 48 | ||
| 47 | config SPI_FLASH_BAR | 49 | config SPI_FLASH_BAR |
| 48 | bool "SPI flash Bank/Extended address register support" | 50 | bool "SPI flash Bank/Extended address register support" |
| 49 | help | 51 | help |
| 50 | Enable the SPI flash Bank/Extended address register support. | 52 | Enable the SPI flash Bank/Extended address register support. |
| 51 | Bank/Extended address registers are used to access the flash | 53 | Bank/Extended address registers are used to access the flash |
| 52 | which has size > 16MiB in 3-byte addressing. | 54 | which has size > 16MiB in 3-byte addressing. |
| 53 | 55 | ||
| 54 | config SF_DUAL_FLASH | 56 | config SF_DUAL_FLASH |
| 55 | bool "SPI DUAL flash memory support" | 57 | bool "SPI DUAL flash memory support" |
| 56 | help | 58 | help |
| 57 | Enable this option to support two flash memories connected to a single | 59 | Enable this option to support two flash memories connected to a single |
| 58 | controller. Currently Xilinx Zynq qspi supports this. | 60 | controller. Currently Xilinx Zynq qspi supports this. |
| 59 | 61 | ||
| 60 | config SPI_FLASH_ATMEL | 62 | config SPI_FLASH_ATMEL |
| 61 | bool "Atmel SPI flash support" | 63 | bool "Atmel SPI flash support" |
| 62 | help | 64 | help |
| 63 | Add support for various Atmel SPI flash chips (AT45xxx and AT25xxx) | 65 | Add support for various Atmel SPI flash chips (AT45xxx and AT25xxx) |
| 64 | 66 | ||
| 65 | config SPI_FLASH_EON | 67 | config SPI_FLASH_EON |
| 66 | bool "EON SPI flash support" | 68 | bool "EON SPI flash support" |
| 67 | help | 69 | help |
| 68 | Add support for various EON SPI flash chips (EN25xxx) | 70 | Add support for various EON SPI flash chips (EN25xxx) |
| 69 | 71 | ||
| 70 | config SPI_FLASH_GIGADEVICE | 72 | config SPI_FLASH_GIGADEVICE |
| 71 | bool "GigaDevice SPI flash support" | 73 | bool "GigaDevice SPI flash support" |
| 72 | help | 74 | help |
| 73 | Add support for various GigaDevice SPI flash chips (GD25xxx) | 75 | Add support for various GigaDevice SPI flash chips (GD25xxx) |
| 74 | 76 | ||
| 75 | config SPI_FLASH_ISSI | 77 | config SPI_FLASH_ISSI |
| 76 | bool "ISSI SPI flash support" | 78 | bool "ISSI SPI flash support" |
| 77 | help | 79 | help |
| 78 | Add support for various ISSI SPI flash chips (ISxxx) | 80 | Add support for various ISSI SPI flash chips (ISxxx) |
| 79 | 81 | ||
| 80 | config SPI_FLASH_MACRONIX | 82 | config SPI_FLASH_MACRONIX |
| 81 | bool "Macronix SPI flash support" | 83 | bool "Macronix SPI flash support" |
| 82 | help | 84 | help |
| 83 | Add support for various Macronix SPI flash chips (MX25Lxxx) | 85 | Add support for various Macronix SPI flash chips (MX25Lxxx) |
| 84 | 86 | ||
| 85 | config SPI_FLASH_SPANSION | 87 | config SPI_FLASH_SPANSION |
| 86 | bool "Spansion SPI flash support" | 88 | bool "Spansion SPI flash support" |
| 87 | help | 89 | help |
| 88 | Add support for various Spansion SPI flash chips (S25FLxxx) | 90 | Add support for various Spansion SPI flash chips (S25FLxxx) |
| 89 | 91 | ||
| 90 | config SPI_FLASH_STMICRO | 92 | config SPI_FLASH_STMICRO |
| 91 | bool "STMicro SPI flash support" | 93 | bool "STMicro SPI flash support" |
| 92 | help | 94 | help |
| 93 | Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx) | 95 | Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx) |
| 94 | 96 | ||
| 95 | config SPI_FLASH_SST | 97 | config SPI_FLASH_SST |
| 96 | bool "SST SPI flash support" | 98 | bool "SST SPI flash support" |
| 97 | help | 99 | help |
| 98 | Add support for various SST SPI flash chips (SST25xxx) | 100 | Add support for various SST SPI flash chips (SST25xxx) |
| 99 | 101 | ||
| 100 | config SPI_FLASH_WINBOND | 102 | config SPI_FLASH_WINBOND |
| 101 | bool "Winbond SPI flash support" | 103 | bool "Winbond SPI flash support" |
| 102 | help | 104 | help |
| 103 | Add support for various Winbond SPI flash chips (W25xxx) | 105 | Add support for various Winbond SPI flash chips (W25xxx) |
| 104 | 106 | ||
| 105 | config SPI_FLASH_XMC | 107 | config SPI_FLASH_XMC |
| 106 | bool "XMC SPI flash support" | 108 | bool "XMC SPI flash support" |
| 107 | help | 109 | help |
| 108 | Add support for various XMC (Wuhan Xinxin Semiconductor | 110 | Add support for various XMC (Wuhan Xinxin Semiconductor |
| 109 | Manufacturing Corp.) SPI flash chips (XM25xxx) | 111 | Manufacturing Corp.) SPI flash chips (XM25xxx) |
| 110 | 112 | ||
| 111 | endif | 113 | endif |
| 112 | 114 | ||
| 113 | config SPI_FLASH_USE_4K_SECTORS | 115 | config SPI_FLASH_USE_4K_SECTORS |
| 114 | bool "Use small 4096 B erase sectors" | 116 | bool "Use small 4096 B erase sectors" |
| 115 | depends on SPI_FLASH | 117 | depends on SPI_FLASH |
| 116 | default y | 118 | default y |
| 117 | help | 119 | help |
| 118 | Many flash memories support erasing small (4096 B) sectors. Depending | 120 | Many flash memories support erasing small (4096 B) sectors. Depending |
| 119 | on the usage this feature may provide performance gain in comparison | 121 | on the usage this feature may provide performance gain in comparison |
| 120 | to erasing whole blocks (32/64 KiB). | 122 | to erasing whole blocks (32/64 KiB). |
| 121 | Changing a small part of the flash's contents is usually faster with | 123 | Changing a small part of the flash's contents is usually faster with |
| 122 | small sectors. On the other hand erasing should be faster when using | 124 | small sectors. On the other hand erasing should be faster when using |
| 123 | 64 KiB block instead of 16 × 4 KiB sectors. | 125 | 64 KiB block instead of 16 × 4 KiB sectors. |
| 124 | 126 | ||
| 125 | Please note that some tools/drivers/filesystems may not work with | 127 | Please note that some tools/drivers/filesystems may not work with |
| 126 | 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). | 128 | 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). |
| 127 | 129 | ||
| 128 | config SPI_FLASH_DATAFLASH | 130 | config SPI_FLASH_DATAFLASH |
| 129 | bool "AT45xxx DataFlash support" | 131 | bool "AT45xxx DataFlash support" |
| 130 | depends on SPI_FLASH && DM_SPI_FLASH | 132 | depends on SPI_FLASH && DM_SPI_FLASH |
| 131 | help | 133 | help |
| 132 | Enable the access for SPI-flash-based AT45xxx DataFlash chips. | 134 | Enable the access for SPI-flash-based AT45xxx DataFlash chips. |
| 133 | DataFlash is a kind of SPI flash. Most AT45 chips have two buffers | 135 | DataFlash is a kind of SPI flash. Most AT45 chips have two buffers |
| 134 | in each chip, which may be used for double buffered I/O; but this | 136 | in each chip, which may be used for double buffered I/O; but this |
| 135 | driver doesn't (yet) use these for any kind of i/o overlap or prefetching. | 137 | driver doesn't (yet) use these for any kind of i/o overlap or prefetching. |
| 136 | 138 | ||
| 137 | Sometimes DataFlash is packaged in MMC-format cards, although the | 139 | Sometimes DataFlash is packaged in MMC-format cards, although the |
| 138 | MMC stack can't (yet?) distinguish between MMC and DataFlash | 140 | MMC stack can't (yet?) distinguish between MMC and DataFlash |
| 139 | protocols during enumeration. | 141 | protocols during enumeration. |
| 140 | 142 | ||
| 141 | If unsure, say N | 143 | If unsure, say N |
| 142 | 144 | ||
| 143 | config SPI_FLASH_MTD | 145 | config SPI_FLASH_MTD |
| 144 | bool "SPI Flash MTD support" | 146 | bool "SPI Flash MTD support" |
| 145 | depends on SPI_FLASH | 147 | depends on SPI_FLASH |
| 146 | help | 148 | help |
| 147 | Enable the MTD support for spi flash layer, this adapter is for | 149 | Enable the MTD support for spi flash layer, this adapter is for |
| 148 | translating mtd_read/mtd_write commands into spi_flash_read/write | 150 | translating mtd_read/mtd_write commands into spi_flash_read/write |
| 149 | commands. It is not intended to use it within sf_cmd or the SPI | 151 | commands. It is not intended to use it within sf_cmd or the SPI |
| 150 | flash subsystem. Such an adapter is needed for subsystems like | 152 | flash subsystem. Such an adapter is needed for subsystems like |
| 151 | UBI which can only operate on top of the MTD layer. | 153 | UBI which can only operate on top of the MTD layer. |
| 152 | 154 | ||
| 153 | If unsure, say N | 155 | If unsure, say N |
| 154 | 156 | ||
| 155 | endmenu # menu "SPI Flash Support" | 157 | endmenu # menu "SPI Flash Support" |
| 156 | 158 |
| 1 | # SPDX-License-Identifier: GPL-2.0+ | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | # | 2 | # |
| 3 | # (C) Copyright 2006 | 3 | # (C) Copyright 2006 |
| 4 | # Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 4 | # Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o | 6 | obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o |
| 7 | 7 | ||
| 8 | ifdef CONFIG_SPL_BUILD | 8 | ifdef CONFIG_SPL_BUILD |
| 9 | obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o | 9 | obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o |
| 10 | endif | 10 | endif |
| 11 | 11 | ||
| 12 | obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o | 12 | obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi-nor-core.o |
| 13 | obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o | 13 | obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o sf.o |
| 14 | obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o | 14 | obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o |
| 15 | obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o | 15 | obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o |
| 16 | 16 |
| 1 | /* | 1 | /* |
| 2 | * Simulate a SPI flash | 2 | * Simulate a SPI flash |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2011-2013 The Chromium OS Authors. | 4 | * Copyright (c) 2011-2013 The Chromium OS Authors. |
| 5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
| 6 | * project. | 6 | * project. |
| 7 | * | 7 | * |
| 8 | * Licensed under the GPL-2 or later. | 8 | * Licensed under the GPL-2 or later. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #define LOG_CATEGORY UCLASS_SPI_FLASH | 11 | #define LOG_CATEGORY UCLASS_SPI_FLASH |
| 12 | 12 | ||
| 13 | #include <common.h> | 13 | #include <common.h> |
| 14 | #include <dm.h> | 14 | #include <dm.h> |
| 15 | #include <malloc.h> | 15 | #include <malloc.h> |
| 16 | #include <spi.h> | 16 | #include <spi.h> |
| 17 | #include <os.h> | 17 | #include <os.h> |
| 18 | 18 | ||
| 19 | #include <spi_flash.h> | 19 | #include <spi_flash.h> |
| 20 | #include "sf_internal.h" | 20 | #include "sf_internal.h" |
| 21 | 21 | ||
| 22 | #include <asm/getopt.h> | 22 | #include <asm/getopt.h> |
| 23 | #include <asm/spi.h> | 23 | #include <asm/spi.h> |
| 24 | #include <asm/state.h> | 24 | #include <asm/state.h> |
| 25 | #include <dm/device-internal.h> | 25 | #include <dm/device-internal.h> |
| 26 | #include <dm/lists.h> | 26 | #include <dm/lists.h> |
| 27 | #include <dm/uclass-internal.h> | 27 | #include <dm/uclass-internal.h> |
| 28 | 28 | ||
| 29 | /* | 29 | /* |
| 30 | * The different states that our SPI flash transitions between. | 30 | * The different states that our SPI flash transitions between. |
| 31 | * We need to keep track of this across multiple xfer calls since | 31 | * We need to keep track of this across multiple xfer calls since |
| 32 | * the SPI bus could possibly call down into us multiple times. | 32 | * the SPI bus could possibly call down into us multiple times. |
| 33 | */ | 33 | */ |
| 34 | enum sandbox_sf_state { | 34 | enum sandbox_sf_state { |
| 35 | SF_CMD, /* default state -- we're awaiting a command */ | 35 | SF_CMD, /* default state -- we're awaiting a command */ |
| 36 | SF_ID, /* read the flash's (jedec) ID code */ | 36 | SF_ID, /* read the flash's (jedec) ID code */ |
| 37 | SF_ADDR, /* processing the offset in the flash to read/etc... */ | 37 | SF_ADDR, /* processing the offset in the flash to read/etc... */ |
| 38 | SF_READ, /* reading data from the flash */ | 38 | SF_READ, /* reading data from the flash */ |
| 39 | SF_WRITE, /* writing data to the flash, i.e. page programming */ | 39 | SF_WRITE, /* writing data to the flash, i.e. page programming */ |
| 40 | SF_ERASE, /* erase the flash */ | 40 | SF_ERASE, /* erase the flash */ |
| 41 | SF_READ_STATUS, /* read the flash's status register */ | 41 | SF_READ_STATUS, /* read the flash's status register */ |
| 42 | SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/ | 42 | SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/ |
| 43 | SF_WRITE_STATUS, /* write the flash's status register */ | 43 | SF_WRITE_STATUS, /* write the flash's status register */ |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | #if CONFIG_IS_ENABLED(LOG) | 46 | #if CONFIG_IS_ENABLED(LOG) |
| 47 | static const char *sandbox_sf_state_name(enum sandbox_sf_state state) | 47 | static const char *sandbox_sf_state_name(enum sandbox_sf_state state) |
| 48 | { | 48 | { |
| 49 | static const char * const states[] = { | 49 | static const char * const states[] = { |
| 50 | "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS", | 50 | "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS", |
| 51 | "READ_STATUS1", "WRITE_STATUS", | 51 | "READ_STATUS1", "WRITE_STATUS", |
| 52 | }; | 52 | }; |
| 53 | return states[state]; | 53 | return states[state]; |
| 54 | } | 54 | } |
| 55 | #endif /* LOG */ | 55 | #endif /* LOG */ |
| 56 | 56 | ||
| 57 | /* Bits for the status register */ | 57 | /* Bits for the status register */ |
| 58 | #define STAT_WIP (1 << 0) | 58 | #define STAT_WIP (1 << 0) |
| 59 | #define STAT_WEL (1 << 1) | 59 | #define STAT_WEL (1 << 1) |
| 60 | #define STAT_BP_SHIFT 2 | 60 | #define STAT_BP_SHIFT 2 |
| 61 | #define STAT_BP_MASK (7 << STAT_BP_SHIFT) | 61 | #define STAT_BP_MASK (7 << STAT_BP_SHIFT) |
| 62 | 62 | ||
| 63 | /* Assume all SPI flashes have 3 byte addresses since they do atm */ | 63 | /* Assume all SPI flashes have 3 byte addresses since they do atm */ |
| 64 | #define SF_ADDR_LEN 3 | 64 | #define SF_ADDR_LEN 3 |
| 65 | 65 | ||
| 66 | #define IDCODE_LEN 3 | 66 | #define IDCODE_LEN 3 |
| 67 | 67 | ||
| 68 | /* Used to quickly bulk erase backing store */ | 68 | /* Used to quickly bulk erase backing store */ |
| 69 | static u8 sandbox_sf_0xff[0x1000]; | 69 | static u8 sandbox_sf_0xff[0x1000]; |
| 70 | 70 | ||
| 71 | /* Internal state data for each SPI flash */ | 71 | /* Internal state data for each SPI flash */ |
| 72 | struct sandbox_spi_flash { | 72 | struct sandbox_spi_flash { |
| 73 | unsigned int cs; /* Chip select we are attached to */ | 73 | unsigned int cs; /* Chip select we are attached to */ |
| 74 | /* | 74 | /* |
| 75 | * As we receive data over the SPI bus, our flash transitions | 75 | * As we receive data over the SPI bus, our flash transitions |
| 76 | * between states. For example, we start off in the SF_CMD | 76 | * between states. For example, we start off in the SF_CMD |
| 77 | * state where the first byte tells us what operation to perform | 77 | * state where the first byte tells us what operation to perform |
| 78 | * (such as read or write the flash). But the operation itself | 78 | * (such as read or write the flash). But the operation itself |
| 79 | * can go through a few states such as first reading in the | 79 | * can go through a few states such as first reading in the |
| 80 | * offset in the flash to perform the requested operation. | 80 | * offset in the flash to perform the requested operation. |
| 81 | * Thus "state" stores the exact state that our machine is in | 81 | * Thus "state" stores the exact state that our machine is in |
| 82 | * while "cmd" stores the overall command we're processing. | 82 | * while "cmd" stores the overall command we're processing. |
| 83 | */ | 83 | */ |
| 84 | enum sandbox_sf_state state; | 84 | enum sandbox_sf_state state; |
| 85 | uint cmd; | 85 | uint cmd; |
| 86 | /* Erase size of current erase command */ | 86 | /* Erase size of current erase command */ |
| 87 | uint erase_size; | 87 | uint erase_size; |
| 88 | /* Current position in the flash; used when reading/writing/etc... */ | 88 | /* Current position in the flash; used when reading/writing/etc... */ |
| 89 | uint off; | 89 | uint off; |
| 90 | /* How many address bytes we've consumed */ | 90 | /* How many address bytes we've consumed */ |
| 91 | uint addr_bytes, pad_addr_bytes; | 91 | uint addr_bytes, pad_addr_bytes; |
| 92 | /* The current flash status (see STAT_XXX defines above) */ | 92 | /* The current flash status (see STAT_XXX defines above) */ |
| 93 | u16 status; | 93 | u16 status; |
| 94 | /* Data describing the flash we're emulating */ | 94 | /* Data describing the flash we're emulating */ |
| 95 | const struct spi_flash_info *data; | 95 | const struct flash_info *data; |
| 96 | /* The file on disk to serv up data from */ | 96 | /* The file on disk to serv up data from */ |
| 97 | int fd; | 97 | int fd; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | struct sandbox_spi_flash_plat_data { | 100 | struct sandbox_spi_flash_plat_data { |
| 101 | const char *filename; | 101 | const char *filename; |
| 102 | const char *device_name; | 102 | const char *device_name; |
| 103 | int bus; | 103 | int bus; |
| 104 | int cs; | 104 | int cs; |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask) | 107 | void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask) |
| 108 | { | 108 | { |
| 109 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | 109 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); |
| 110 | 110 | ||
| 111 | sbsf->status &= ~STAT_BP_MASK; | 111 | sbsf->status &= ~STAT_BP_MASK; |
| 112 | sbsf->status |= bp_mask << STAT_BP_SHIFT; | 112 | sbsf->status |= bp_mask << STAT_BP_SHIFT; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | /** | 115 | /** |
| 116 | * This is a very strange probe function. If it has platform data (which may | 116 | * This is a very strange probe function. If it has platform data (which may |
| 117 | * have come from the device tree) then this function gets the filename and | 117 | * have come from the device tree) then this function gets the filename and |
| 118 | * device type from there. | 118 | * device type from there. |
| 119 | */ | 119 | */ |
| 120 | static int sandbox_sf_probe(struct udevice *dev) | 120 | static int sandbox_sf_probe(struct udevice *dev) |
| 121 | { | 121 | { |
| 122 | /* spec = idcode:file */ | 122 | /* spec = idcode:file */ |
| 123 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | 123 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); |
| 124 | size_t len, idname_len; | 124 | size_t len, idname_len; |
| 125 | const struct spi_flash_info *data; | 125 | const struct flash_info *data; |
| 126 | struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); | 126 | struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); |
| 127 | struct sandbox_state *state = state_get_current(); | 127 | struct sandbox_state *state = state_get_current(); |
| 128 | struct dm_spi_slave_platdata *slave_plat; | 128 | struct dm_spi_slave_platdata *slave_plat; |
| 129 | struct udevice *bus = dev->parent; | 129 | struct udevice *bus = dev->parent; |
| 130 | const char *spec = NULL; | 130 | const char *spec = NULL; |
| 131 | struct udevice *emul; | 131 | struct udevice *emul; |
| 132 | int ret = 0; | 132 | int ret = 0; |
| 133 | int cs = -1; | 133 | int cs = -1; |
| 134 | 134 | ||
| 135 | debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); | 135 | debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); |
| 136 | ret = sandbox_spi_get_emul(state, bus, dev, &emul); | 136 | ret = sandbox_spi_get_emul(state, bus, dev, &emul); |
| 137 | if (ret) { | 137 | if (ret) { |
| 138 | printf("Error: Unknown chip select for device '%s'\n", | 138 | printf("Error: Unknown chip select for device '%s'\n", |
| 139 | dev->name); | 139 | dev->name); |
| 140 | return ret; | 140 | return ret; |
| 141 | } | 141 | } |
| 142 | slave_plat = dev_get_parent_platdata(dev); | 142 | slave_plat = dev_get_parent_platdata(dev); |
| 143 | cs = slave_plat->cs; | 143 | cs = slave_plat->cs; |
| 144 | debug("found at cs %d\n", cs); | 144 | debug("found at cs %d\n", cs); |
| 145 | 145 | ||
| 146 | if (!pdata->filename) { | 146 | if (!pdata->filename) { |
| 147 | printf("Error: No filename available\n"); | 147 | printf("Error: No filename available\n"); |
| 148 | return -EINVAL; | 148 | return -EINVAL; |
| 149 | } | 149 | } |
| 150 | spec = strchr(pdata->device_name, ','); | 150 | spec = strchr(pdata->device_name, ','); |
| 151 | if (spec) | 151 | if (spec) |
| 152 | spec++; | 152 | spec++; |
| 153 | else | 153 | else |
| 154 | spec = pdata->device_name; | 154 | spec = pdata->device_name; |
| 155 | idname_len = strlen(spec); | 155 | idname_len = strlen(spec); |
| 156 | debug("%s: device='%s'\n", __func__, spec); | 156 | debug("%s: device='%s'\n", __func__, spec); |
| 157 | 157 | ||
| 158 | for (data = spi_flash_ids; data->name; data++) { | 158 | for (data = spi_nor_ids; data->name; data++) { |
| 159 | len = strlen(data->name); | 159 | len = strlen(data->name); |
| 160 | if (idname_len != len) | 160 | if (idname_len != len) |
| 161 | continue; | 161 | continue; |
| 162 | if (!strncasecmp(spec, data->name, len)) | 162 | if (!strncasecmp(spec, data->name, len)) |
| 163 | break; | 163 | break; |
| 164 | } | 164 | } |
| 165 | if (!data->name) { | 165 | if (!data->name) { |
| 166 | printf("%s: unknown flash '%*s'\n", __func__, (int)idname_len, | 166 | printf("%s: unknown flash '%*s'\n", __func__, (int)idname_len, |
| 167 | spec); | 167 | spec); |
| 168 | ret = -EINVAL; | 168 | ret = -EINVAL; |
| 169 | goto error; | 169 | goto error; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | if (sandbox_sf_0xff[0] == 0x00) | 172 | if (sandbox_sf_0xff[0] == 0x00) |
| 173 | memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); | 173 | memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); |
| 174 | 174 | ||
| 175 | sbsf->fd = os_open(pdata->filename, 02); | 175 | sbsf->fd = os_open(pdata->filename, 02); |
| 176 | if (sbsf->fd == -1) { | 176 | if (sbsf->fd == -1) { |
| 177 | printf("%s: unable to open file '%s'\n", __func__, | 177 | printf("%s: unable to open file '%s'\n", __func__, |
| 178 | pdata->filename); | 178 | pdata->filename); |
| 179 | ret = -EIO; | 179 | ret = -EIO; |
| 180 | goto error; | 180 | goto error; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | sbsf->data = data; | 183 | sbsf->data = data; |
| 184 | sbsf->cs = cs; | 184 | sbsf->cs = cs; |
| 185 | 185 | ||
| 186 | return 0; | 186 | return 0; |
| 187 | 187 | ||
| 188 | error: | 188 | error: |
| 189 | debug("%s: Got error %d\n", __func__, ret); | 189 | debug("%s: Got error %d\n", __func__, ret); |
| 190 | return ret; | 190 | return ret; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static int sandbox_sf_remove(struct udevice *dev) | 193 | static int sandbox_sf_remove(struct udevice *dev) |
| 194 | { | 194 | { |
| 195 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | 195 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); |
| 196 | 196 | ||
| 197 | os_close(sbsf->fd); | 197 | os_close(sbsf->fd); |
| 198 | 198 | ||
| 199 | return 0; | 199 | return 0; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | static void sandbox_sf_cs_activate(struct udevice *dev) | 202 | static void sandbox_sf_cs_activate(struct udevice *dev) |
| 203 | { | 203 | { |
| 204 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | 204 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); |
| 205 | 205 | ||
| 206 | log_content("sandbox_sf: CS activated; state is fresh!\n"); | 206 | log_content("sandbox_sf: CS activated; state is fresh!\n"); |
| 207 | 207 | ||
| 208 | /* CS is asserted, so reset state */ | 208 | /* CS is asserted, so reset state */ |
| 209 | sbsf->off = 0; | 209 | sbsf->off = 0; |
| 210 | sbsf->addr_bytes = 0; | 210 | sbsf->addr_bytes = 0; |
| 211 | sbsf->pad_addr_bytes = 0; | 211 | sbsf->pad_addr_bytes = 0; |
| 212 | sbsf->state = SF_CMD; | 212 | sbsf->state = SF_CMD; |
| 213 | sbsf->cmd = SF_CMD; | 213 | sbsf->cmd = SF_CMD; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | static void sandbox_sf_cs_deactivate(struct udevice *dev) | 216 | static void sandbox_sf_cs_deactivate(struct udevice *dev) |
| 217 | { | 217 | { |
| 218 | log_content("sandbox_sf: CS deactivated; cmd done processing!\n"); | 218 | log_content("sandbox_sf: CS deactivated; cmd done processing!\n"); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* | 221 | /* |
| 222 | * There are times when the data lines are allowed to tristate. What | 222 | * There are times when the data lines are allowed to tristate. What |
| 223 | * is actually sensed on the line depends on the hardware. It could | 223 | * is actually sensed on the line depends on the hardware. It could |
| 224 | * always be 0xFF/0x00 (if there are pull ups/downs), or things could | 224 | * always be 0xFF/0x00 (if there are pull ups/downs), or things could |
| 225 | * float and so we'd get garbage back. This func encapsulates that | 225 | * float and so we'd get garbage back. This func encapsulates that |
| 226 | * scenario so we can worry about the details here. | 226 | * scenario so we can worry about the details here. |
| 227 | */ | 227 | */ |
| 228 | static void sandbox_spi_tristate(u8 *buf, uint len) | 228 | static void sandbox_spi_tristate(u8 *buf, uint len) |
| 229 | { | 229 | { |
| 230 | /* XXX: make this into a user config option ? */ | 230 | /* XXX: make this into a user config option ? */ |
| 231 | memset(buf, 0xff, len); | 231 | memset(buf, 0xff, len); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | /* Figure out what command this stream is telling us to do */ | 234 | /* Figure out what command this stream is telling us to do */ |
| 235 | static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, | 235 | static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, |
| 236 | u8 *tx) | 236 | u8 *tx) |
| 237 | { | 237 | { |
| 238 | enum sandbox_sf_state oldstate = sbsf->state; | 238 | enum sandbox_sf_state oldstate = sbsf->state; |
| 239 | 239 | ||
| 240 | /* We need to output a byte for the cmd byte we just ate */ | 240 | /* We need to output a byte for the cmd byte we just ate */ |
| 241 | if (tx) | 241 | if (tx) |
| 242 | sandbox_spi_tristate(tx, 1); | 242 | sandbox_spi_tristate(tx, 1); |
| 243 | 243 | ||
| 244 | sbsf->cmd = rx[0]; | 244 | sbsf->cmd = rx[0]; |
| 245 | switch (sbsf->cmd) { | 245 | switch (sbsf->cmd) { |
| 246 | case CMD_READ_ID: | 246 | case SPINOR_OP_RDID: |
| 247 | sbsf->state = SF_ID; | 247 | sbsf->state = SF_ID; |
| 248 | sbsf->cmd = SF_ID; | 248 | sbsf->cmd = SF_ID; |
| 249 | break; | 249 | break; |
| 250 | case CMD_READ_ARRAY_FAST: | 250 | case SPINOR_OP_READ_FAST: |
| 251 | sbsf->pad_addr_bytes = 1; | 251 | sbsf->pad_addr_bytes = 1; |
| 252 | case CMD_READ_ARRAY_SLOW: | 252 | case SPINOR_OP_READ: |
| 253 | case CMD_PAGE_PROGRAM: | 253 | case SPINOR_OP_PP: |
| 254 | sbsf->state = SF_ADDR; | 254 | sbsf->state = SF_ADDR; |
| 255 | break; | 255 | break; |
| 256 | case CMD_WRITE_DISABLE: | 256 | case SPINOR_OP_WRDI: |
| 257 | debug(" write disabled\n"); | 257 | debug(" write disabled\n"); |
| 258 | sbsf->status &= ~STAT_WEL; | 258 | sbsf->status &= ~STAT_WEL; |
| 259 | break; | 259 | break; |
| 260 | case CMD_READ_STATUS: | 260 | case SPINOR_OP_RDSR: |
| 261 | sbsf->state = SF_READ_STATUS; | 261 | sbsf->state = SF_READ_STATUS; |
| 262 | break; | 262 | break; |
| 263 | case CMD_READ_STATUS1: | 263 | case SPINOR_OP_RDSR2: |
| 264 | sbsf->state = SF_READ_STATUS1; | 264 | sbsf->state = SF_READ_STATUS1; |
| 265 | break; | 265 | break; |
| 266 | case CMD_WRITE_ENABLE: | 266 | case SPINOR_OP_WREN: |
| 267 | debug(" write enabled\n"); | 267 | debug(" write enabled\n"); |
| 268 | sbsf->status |= STAT_WEL; | 268 | sbsf->status |= STAT_WEL; |
| 269 | break; | 269 | break; |
| 270 | case CMD_WRITE_STATUS: | 270 | case SPINOR_OP_WRSR: |
| 271 | sbsf->state = SF_WRITE_STATUS; | 271 | sbsf->state = SF_WRITE_STATUS; |
| 272 | break; | 272 | break; |
| 273 | default: { | 273 | default: { |
| 274 | int flags = sbsf->data->flags; | 274 | int flags = sbsf->data->flags; |
| 275 | 275 | ||
| 276 | /* we only support erase here */ | 276 | /* we only support erase here */ |
| 277 | if (sbsf->cmd == CMD_ERASE_CHIP) { | 277 | if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { |
| 278 | sbsf->erase_size = sbsf->data->sector_size * | 278 | sbsf->erase_size = sbsf->data->sector_size * |
| 279 | sbsf->data->n_sectors; | 279 | sbsf->data->n_sectors; |
| 280 | } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { | 280 | } else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { |
| 281 | sbsf->erase_size = 4 << 10; | 281 | sbsf->erase_size = 4 << 10; |
| 282 | } else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { | 282 | } else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { |
| 283 | sbsf->erase_size = 64 << 10; | 283 | sbsf->erase_size = 64 << 10; |
| 284 | } else { | 284 | } else { |
| 285 | debug(" cmd unknown: %#x\n", sbsf->cmd); | 285 | debug(" cmd unknown: %#x\n", sbsf->cmd); |
| 286 | return -EIO; | 286 | return -EIO; |
| 287 | } | 287 | } |
| 288 | sbsf->state = SF_ADDR; | 288 | sbsf->state = SF_ADDR; |
| 289 | break; | 289 | break; |
| 290 | } | 290 | } |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | if (oldstate != sbsf->state) | 293 | if (oldstate != sbsf->state) |
| 294 | log_content(" cmd: transition to %s state\n", | 294 | log_content(" cmd: transition to %s state\n", |
| 295 | sandbox_sf_state_name(sbsf->state)); | 295 | sandbox_sf_state_name(sbsf->state)); |
| 296 | 296 | ||
| 297 | return 0; | 297 | return 0; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) | 300 | int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) |
| 301 | { | 301 | { |
| 302 | int todo; | 302 | int todo; |
| 303 | int ret; | 303 | int ret; |
| 304 | 304 | ||
| 305 | while (size > 0) { | 305 | while (size > 0) { |
| 306 | todo = min(size, (int)sizeof(sandbox_sf_0xff)); | 306 | todo = min(size, (int)sizeof(sandbox_sf_0xff)); |
| 307 | ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); | 307 | ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); |
| 308 | if (ret != todo) | 308 | if (ret != todo) |
| 309 | return ret; | 309 | return ret; |
| 310 | size -= todo; | 310 | size -= todo; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | return 0; | 313 | return 0; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, | 316 | static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, |
| 317 | const void *rxp, void *txp, unsigned long flags) | 317 | const void *rxp, void *txp, unsigned long flags) |
| 318 | { | 318 | { |
| 319 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | 319 | struct sandbox_spi_flash *sbsf = dev_get_priv(dev); |
| 320 | const uint8_t *rx = rxp; | 320 | const uint8_t *rx = rxp; |
| 321 | uint8_t *tx = txp; | 321 | uint8_t *tx = txp; |
| 322 | uint cnt, pos = 0; | 322 | uint cnt, pos = 0; |
| 323 | int bytes = bitlen / 8; | 323 | int bytes = bitlen / 8; |
| 324 | int ret; | 324 | int ret; |
| 325 | 325 | ||
| 326 | log_content("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, | 326 | log_content("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, |
| 327 | sandbox_sf_state_name(sbsf->state), bytes); | 327 | sandbox_sf_state_name(sbsf->state), bytes); |
| 328 | 328 | ||
| 329 | if ((flags & SPI_XFER_BEGIN)) | 329 | if ((flags & SPI_XFER_BEGIN)) |
| 330 | sandbox_sf_cs_activate(dev); | 330 | sandbox_sf_cs_activate(dev); |
| 331 | 331 | ||
| 332 | if (sbsf->state == SF_CMD) { | 332 | if (sbsf->state == SF_CMD) { |
| 333 | /* Figure out the initial state */ | 333 | /* Figure out the initial state */ |
| 334 | ret = sandbox_sf_process_cmd(sbsf, rx, tx); | 334 | ret = sandbox_sf_process_cmd(sbsf, rx, tx); |
| 335 | if (ret) | 335 | if (ret) |
| 336 | return ret; | 336 | return ret; |
| 337 | ++pos; | 337 | ++pos; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | /* Process the remaining data */ | 340 | /* Process the remaining data */ |
| 341 | while (pos < bytes) { | 341 | while (pos < bytes) { |
| 342 | switch (sbsf->state) { | 342 | switch (sbsf->state) { |
| 343 | case SF_ID: { | 343 | case SF_ID: { |
| 344 | u8 id; | 344 | u8 id; |
| 345 | 345 | ||
| 346 | log_content(" id: off:%u tx:", sbsf->off); | 346 | log_content(" id: off:%u tx:", sbsf->off); |
| 347 | if (sbsf->off < IDCODE_LEN) { | 347 | if (sbsf->off < IDCODE_LEN) { |
| 348 | /* Extract correct byte from ID 0x00aabbcc */ | 348 | /* Extract correct byte from ID 0x00aabbcc */ |
| 349 | id = ((JEDEC_MFR(sbsf->data) << 16) | | 349 | id = ((JEDEC_MFR(sbsf->data) << 16) | |
| 350 | JEDEC_ID(sbsf->data)) >> | 350 | JEDEC_ID(sbsf->data)) >> |
| 351 | (8 * (IDCODE_LEN - 1 - sbsf->off)); | 351 | (8 * (IDCODE_LEN - 1 - sbsf->off)); |
| 352 | } else { | 352 | } else { |
| 353 | id = 0; | 353 | id = 0; |
| 354 | } | 354 | } |
| 355 | log_content("%d %02x\n", sbsf->off, id); | 355 | log_content("%d %02x\n", sbsf->off, id); |
| 356 | tx[pos++] = id; | 356 | tx[pos++] = id; |
| 357 | ++sbsf->off; | 357 | ++sbsf->off; |
| 358 | break; | 358 | break; |
| 359 | } | 359 | } |
| 360 | case SF_ADDR: | 360 | case SF_ADDR: |
| 361 | log_content(" addr: bytes:%u rx:%02x ", | 361 | log_content(" addr: bytes:%u rx:%02x ", |
| 362 | sbsf->addr_bytes, rx[pos]); | 362 | sbsf->addr_bytes, rx[pos]); |
| 363 | 363 | ||
| 364 | if (sbsf->addr_bytes++ < SF_ADDR_LEN) | 364 | if (sbsf->addr_bytes++ < SF_ADDR_LEN) |
| 365 | sbsf->off = (sbsf->off << 8) | rx[pos]; | 365 | sbsf->off = (sbsf->off << 8) | rx[pos]; |
| 366 | log_content("addr:%06x\n", sbsf->off); | 366 | log_content("addr:%06x\n", sbsf->off); |
| 367 | 367 | ||
| 368 | if (tx) | 368 | if (tx) |
| 369 | sandbox_spi_tristate(&tx[pos], 1); | 369 | sandbox_spi_tristate(&tx[pos], 1); |
| 370 | pos++; | 370 | pos++; |
| 371 | 371 | ||
| 372 | /* See if we're done processing */ | 372 | /* See if we're done processing */ |
| 373 | if (sbsf->addr_bytes < | 373 | if (sbsf->addr_bytes < |
| 374 | SF_ADDR_LEN + sbsf->pad_addr_bytes) | 374 | SF_ADDR_LEN + sbsf->pad_addr_bytes) |
| 375 | break; | 375 | break; |
| 376 | 376 | ||
| 377 | /* Next state! */ | 377 | /* Next state! */ |
| 378 | if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { | 378 | if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { |
| 379 | puts("sandbox_sf: os_lseek() failed"); | 379 | puts("sandbox_sf: os_lseek() failed"); |
| 380 | return -EIO; | 380 | return -EIO; |
| 381 | } | 381 | } |
| 382 | switch (sbsf->cmd) { | 382 | switch (sbsf->cmd) { |
| 383 | case CMD_READ_ARRAY_FAST: | 383 | case SPINOR_OP_READ_FAST: |
| 384 | case CMD_READ_ARRAY_SLOW: | 384 | case SPINOR_OP_READ: |
| 385 | sbsf->state = SF_READ; | 385 | sbsf->state = SF_READ; |
| 386 | break; | 386 | break; |
| 387 | case CMD_PAGE_PROGRAM: | 387 | case SPINOR_OP_PP: |
| 388 | sbsf->state = SF_WRITE; | 388 | sbsf->state = SF_WRITE; |
| 389 | break; | 389 | break; |
| 390 | default: | 390 | default: |
| 391 | /* assume erase state ... */ | 391 | /* assume erase state ... */ |
| 392 | sbsf->state = SF_ERASE; | 392 | sbsf->state = SF_ERASE; |
| 393 | goto case_sf_erase; | 393 | goto case_sf_erase; |
| 394 | } | 394 | } |
| 395 | log_content(" cmd: transition to %s state\n", | 395 | log_content(" cmd: transition to %s state\n", |
| 396 | sandbox_sf_state_name(sbsf->state)); | 396 | sandbox_sf_state_name(sbsf->state)); |
| 397 | break; | 397 | break; |
| 398 | case SF_READ: | 398 | case SF_READ: |
| 399 | /* | 399 | /* |
| 400 | * XXX: need to handle exotic behavior: | 400 | * XXX: need to handle exotic behavior: |
| 401 | * - reading past end of device | 401 | * - reading past end of device |
| 402 | */ | 402 | */ |
| 403 | 403 | ||
| 404 | cnt = bytes - pos; | 404 | cnt = bytes - pos; |
| 405 | log_content(" tx: read(%u)\n", cnt); | 405 | log_content(" tx: read(%u)\n", cnt); |
| 406 | assert(tx); | 406 | assert(tx); |
| 407 | ret = os_read(sbsf->fd, tx + pos, cnt); | 407 | ret = os_read(sbsf->fd, tx + pos, cnt); |
| 408 | if (ret < 0) { | 408 | if (ret < 0) { |
| 409 | puts("sandbox_sf: os_read() failed\n"); | 409 | puts("sandbox_sf: os_read() failed\n"); |
| 410 | return -EIO; | 410 | return -EIO; |
| 411 | } | 411 | } |
| 412 | pos += ret; | 412 | pos += ret; |
| 413 | break; | 413 | break; |
| 414 | case SF_READ_STATUS: | 414 | case SF_READ_STATUS: |
| 415 | log_content(" read status: %#x\n", sbsf->status); | 415 | log_content(" read status: %#x\n", sbsf->status); |
| 416 | cnt = bytes - pos; | 416 | cnt = bytes - pos; |
| 417 | memset(tx + pos, sbsf->status, cnt); | 417 | memset(tx + pos, sbsf->status, cnt); |
| 418 | pos += cnt; | 418 | pos += cnt; |
| 419 | break; | 419 | break; |
| 420 | case SF_READ_STATUS1: | 420 | case SF_READ_STATUS1: |
| 421 | log_content(" read status: %#x\n", sbsf->status); | 421 | log_content(" read status: %#x\n", sbsf->status); |
| 422 | cnt = bytes - pos; | 422 | cnt = bytes - pos; |
| 423 | memset(tx + pos, sbsf->status >> 8, cnt); | 423 | memset(tx + pos, sbsf->status >> 8, cnt); |
| 424 | pos += cnt; | 424 | pos += cnt; |
| 425 | break; | 425 | break; |
| 426 | case SF_WRITE_STATUS: | 426 | case SF_WRITE_STATUS: |
| 427 | log_content(" write status: %#x (ignored)\n", rx[pos]); | 427 | log_content(" write status: %#x (ignored)\n", rx[pos]); |
| 428 | pos = bytes; | 428 | pos = bytes; |
| 429 | break; | 429 | break; |
| 430 | case SF_WRITE: | 430 | case SF_WRITE: |
| 431 | /* | 431 | /* |
| 432 | * XXX: need to handle exotic behavior: | 432 | * XXX: need to handle exotic behavior: |
| 433 | * - unaligned addresses | 433 | * - unaligned addresses |
| 434 | * - more than a page (256) worth of data | 434 | * - more than a page (256) worth of data |
| 435 | * - reading past end of device | 435 | * - reading past end of device |
| 436 | */ | 436 | */ |
| 437 | if (!(sbsf->status & STAT_WEL)) { | 437 | if (!(sbsf->status & STAT_WEL)) { |
| 438 | puts("sandbox_sf: write enable not set before write\n"); | 438 | puts("sandbox_sf: write enable not set before write\n"); |
| 439 | goto done; | 439 | goto done; |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | cnt = bytes - pos; | 442 | cnt = bytes - pos; |
| 443 | log_content(" rx: write(%u)\n", cnt); | 443 | log_content(" rx: write(%u)\n", cnt); |
| 444 | if (tx) | 444 | if (tx) |
| 445 | sandbox_spi_tristate(&tx[pos], cnt); | 445 | sandbox_spi_tristate(&tx[pos], cnt); |
| 446 | ret = os_write(sbsf->fd, rx + pos, cnt); | 446 | ret = os_write(sbsf->fd, rx + pos, cnt); |
| 447 | if (ret < 0) { | 447 | if (ret < 0) { |
| 448 | puts("sandbox_spi: os_write() failed\n"); | 448 | puts("sandbox_spi: os_write() failed\n"); |
| 449 | return -EIO; | 449 | return -EIO; |
| 450 | } | 450 | } |
| 451 | pos += ret; | 451 | pos += ret; |
| 452 | sbsf->status &= ~STAT_WEL; | 452 | sbsf->status &= ~STAT_WEL; |
| 453 | break; | 453 | break; |
| 454 | case SF_ERASE: | 454 | case SF_ERASE: |
| 455 | case_sf_erase: { | 455 | case_sf_erase: { |
| 456 | if (!(sbsf->status & STAT_WEL)) { | 456 | if (!(sbsf->status & STAT_WEL)) { |
| 457 | puts("sandbox_sf: write enable not set before erase\n"); | 457 | puts("sandbox_sf: write enable not set before erase\n"); |
| 458 | goto done; | 458 | goto done; |
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | /* verify address is aligned */ | 461 | /* verify address is aligned */ |
| 462 | if (sbsf->off & (sbsf->erase_size - 1)) { | 462 | if (sbsf->off & (sbsf->erase_size - 1)) { |
| 463 | log_content(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", | 463 | log_content(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", |
| 464 | sbsf->cmd, sbsf->erase_size, | 464 | sbsf->cmd, sbsf->erase_size, |
| 465 | sbsf->off); | 465 | sbsf->off); |
| 466 | sbsf->status &= ~STAT_WEL; | 466 | sbsf->status &= ~STAT_WEL; |
| 467 | goto done; | 467 | goto done; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | log_content(" sector erase addr: %u, size: %u\n", | 470 | log_content(" sector erase addr: %u, size: %u\n", |
| 471 | sbsf->off, sbsf->erase_size); | 471 | sbsf->off, sbsf->erase_size); |
| 472 | 472 | ||
| 473 | cnt = bytes - pos; | 473 | cnt = bytes - pos; |
| 474 | if (tx) | 474 | if (tx) |
| 475 | sandbox_spi_tristate(&tx[pos], cnt); | 475 | sandbox_spi_tristate(&tx[pos], cnt); |
| 476 | pos += cnt; | 476 | pos += cnt; |
| 477 | 477 | ||
| 478 | /* | 478 | /* |
| 479 | * TODO(vapier@gentoo.org): latch WIP in status, and | 479 | * TODO(vapier@gentoo.org): latch WIP in status, and |
| 480 | * delay before clearing it ? | 480 | * delay before clearing it ? |
| 481 | */ | 481 | */ |
| 482 | ret = sandbox_erase_part(sbsf, sbsf->erase_size); | 482 | ret = sandbox_erase_part(sbsf, sbsf->erase_size); |
| 483 | sbsf->status &= ~STAT_WEL; | 483 | sbsf->status &= ~STAT_WEL; |
| 484 | if (ret) { | 484 | if (ret) { |
| 485 | log_content("sandbox_sf: Erase failed\n"); | 485 | log_content("sandbox_sf: Erase failed\n"); |
| 486 | goto done; | 486 | goto done; |
| 487 | } | 487 | } |
| 488 | goto done; | 488 | goto done; |
| 489 | } | 489 | } |
| 490 | default: | 490 | default: |
| 491 | log_content(" ??? no idea what to do ???\n"); | 491 | log_content(" ??? no idea what to do ???\n"); |
| 492 | goto done; | 492 | goto done; |
| 493 | } | 493 | } |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | done: | 496 | done: |
| 497 | if (flags & SPI_XFER_END) | 497 | if (flags & SPI_XFER_END) |
| 498 | sandbox_sf_cs_deactivate(dev); | 498 | sandbox_sf_cs_deactivate(dev); |
| 499 | return pos == bytes ? 0 : -EIO; | 499 | return pos == bytes ? 0 : -EIO; |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | int sandbox_sf_ofdata_to_platdata(struct udevice *dev) | 502 | int sandbox_sf_ofdata_to_platdata(struct udevice *dev) |
| 503 | { | 503 | { |
| 504 | struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); | 504 | struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); |
| 505 | 505 | ||
| 506 | pdata->filename = dev_read_string(dev, "sandbox,filename"); | 506 | pdata->filename = dev_read_string(dev, "sandbox,filename"); |
| 507 | pdata->device_name = dev_read_string(dev, "compatible"); | 507 | pdata->device_name = dev_read_string(dev, "compatible"); |
| 508 | if (!pdata->filename || !pdata->device_name) { | 508 | if (!pdata->filename || !pdata->device_name) { |
| 509 | debug("%s: Missing properties, filename=%s, device_name=%s\n", | 509 | debug("%s: Missing properties, filename=%s, device_name=%s\n", |
| 510 | __func__, pdata->filename, pdata->device_name); | 510 | __func__, pdata->filename, pdata->device_name); |
| 511 | return -EINVAL; | 511 | return -EINVAL; |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | return 0; | 514 | return 0; |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { | 517 | static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { |
| 518 | .xfer = sandbox_sf_xfer, | 518 | .xfer = sandbox_sf_xfer, |
| 519 | }; | 519 | }; |
| 520 | 520 | ||
| 521 | #ifdef CONFIG_SPI_FLASH | 521 | #ifdef CONFIG_SPI_FLASH |
| 522 | int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, | 522 | int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, |
| 523 | struct udevice *bus, ofnode node, const char *spec) | 523 | struct udevice *bus, ofnode node, const char *spec) |
| 524 | { | 524 | { |
| 525 | struct udevice *emul; | 525 | struct udevice *emul; |
| 526 | char name[20], *str; | 526 | char name[20], *str; |
| 527 | struct driver *drv; | 527 | struct driver *drv; |
| 528 | int ret; | 528 | int ret; |
| 529 | 529 | ||
| 530 | /* now the emulator */ | 530 | /* now the emulator */ |
| 531 | strncpy(name, spec, sizeof(name) - 6); | 531 | strncpy(name, spec, sizeof(name) - 6); |
| 532 | name[sizeof(name) - 6] = '\0'; | 532 | name[sizeof(name) - 6] = '\0'; |
| 533 | strcat(name, "-emul"); | 533 | strcat(name, "-emul"); |
| 534 | drv = lists_driver_lookup_name("sandbox_sf_emul"); | 534 | drv = lists_driver_lookup_name("sandbox_sf_emul"); |
| 535 | if (!drv) { | 535 | if (!drv) { |
| 536 | puts("Cannot find sandbox_sf_emul driver\n"); | 536 | puts("Cannot find sandbox_sf_emul driver\n"); |
| 537 | return -ENOENT; | 537 | return -ENOENT; |
| 538 | } | 538 | } |
| 539 | str = strdup(name); | 539 | str = strdup(name); |
| 540 | if (!str) | 540 | if (!str) |
| 541 | return -ENOMEM; | 541 | return -ENOMEM; |
| 542 | ret = device_bind_ofnode(bus, drv, str, NULL, node, &emul); | 542 | ret = device_bind_ofnode(bus, drv, str, NULL, node, &emul); |
| 543 | if (ret) { | 543 | if (ret) { |
| 544 | free(str); | 544 | free(str); |
| 545 | printf("Cannot create emul device for spec '%s' (err=%d)\n", | 545 | printf("Cannot create emul device for spec '%s' (err=%d)\n", |
| 546 | spec, ret); | 546 | spec, ret); |
| 547 | return ret; | 547 | return ret; |
| 548 | } | 548 | } |
| 549 | state->spi[busnum][cs].emul = emul; | 549 | state->spi[busnum][cs].emul = emul; |
| 550 | 550 | ||
| 551 | return 0; | 551 | return 0; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) | 554 | void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) |
| 555 | { | 555 | { |
| 556 | struct udevice *dev; | 556 | struct udevice *dev; |
| 557 | 557 | ||
| 558 | dev = state->spi[busnum][cs].emul; | 558 | dev = state->spi[busnum][cs].emul; |
| 559 | device_remove(dev, DM_REMOVE_NORMAL); | 559 | device_remove(dev, DM_REMOVE_NORMAL); |
| 560 | device_unbind(dev); | 560 | device_unbind(dev); |
| 561 | state->spi[busnum][cs].emul = NULL; | 561 | state->spi[busnum][cs].emul = NULL; |
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | int sandbox_spi_get_emul(struct sandbox_state *state, | 564 | int sandbox_spi_get_emul(struct sandbox_state *state, |
| 565 | struct udevice *bus, struct udevice *slave, | 565 | struct udevice *bus, struct udevice *slave, |
| 566 | struct udevice **emulp) | 566 | struct udevice **emulp) |
| 567 | { | 567 | { |
| 568 | struct sandbox_spi_info *info; | 568 | struct sandbox_spi_info *info; |
| 569 | int busnum = bus->seq; | 569 | int busnum = bus->seq; |
| 570 | int cs = spi_chip_select(slave); | 570 | int cs = spi_chip_select(slave); |
| 571 | int ret; | 571 | int ret; |
| 572 | 572 | ||
| 573 | info = &state->spi[busnum][cs]; | 573 | info = &state->spi[busnum][cs]; |
| 574 | if (!info->emul) { | 574 | if (!info->emul) { |
| 575 | /* Use the same device tree node as the SPI flash device */ | 575 | /* Use the same device tree node as the SPI flash device */ |
| 576 | debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ", | 576 | debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ", |
| 577 | __func__, busnum, cs); | 577 | __func__, busnum, cs); |
| 578 | ret = sandbox_sf_bind_emul(state, busnum, cs, bus, | 578 | ret = sandbox_sf_bind_emul(state, busnum, cs, bus, |
| 579 | dev_ofnode(slave), slave->name); | 579 | dev_ofnode(slave), slave->name); |
| 580 | if (ret) { | 580 | if (ret) { |
| 581 | debug("failed (err=%d)\n", ret); | 581 | debug("failed (err=%d)\n", ret); |
| 582 | return ret; | 582 | return ret; |
| 583 | } | 583 | } |
| 584 | debug("OK\n"); | 584 | debug("OK\n"); |
| 585 | } | 585 | } |
| 586 | *emulp = info->emul; | 586 | *emulp = info->emul; |
| 587 | 587 | ||
| 588 | return 0; | 588 | return 0; |
| 589 | } | 589 | } |
| 590 | #endif | 590 | #endif |
| 591 | 591 | ||
| 592 | static const struct udevice_id sandbox_sf_ids[] = { | 592 | static const struct udevice_id sandbox_sf_ids[] = { |
| 593 | { .compatible = "sandbox,spi-flash" }, | 593 | { .compatible = "sandbox,spi-flash" }, |
| 594 | { } | 594 | { } |
| 595 | }; | 595 | }; |
| 596 | 596 | ||
| 597 | U_BOOT_DRIVER(sandbox_sf_emul) = { | 597 | U_BOOT_DRIVER(sandbox_sf_emul) = { |
| 598 | .name = "sandbox_sf_emul", | 598 | .name = "sandbox_sf_emul", |
| 599 | .id = UCLASS_SPI_EMUL, | 599 | .id = UCLASS_SPI_EMUL, |
| 600 | .of_match = sandbox_sf_ids, | 600 | .of_match = sandbox_sf_ids, |
| 601 | .ofdata_to_platdata = sandbox_sf_ofdata_to_platdata, | 601 | .ofdata_to_platdata = sandbox_sf_ofdata_to_platdata, |
| 602 | .probe = sandbox_sf_probe, | 602 | .probe = sandbox_sf_probe, |
| 603 | .remove = sandbox_sf_remove, | 603 | .remove = sandbox_sf_remove, |
| 604 | .priv_auto_alloc_size = sizeof(struct sandbox_spi_flash), | 604 | .priv_auto_alloc_size = sizeof(struct sandbox_spi_flash), |
| 605 | .platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data), | 605 | .platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data), |
| 606 | .ops = &sandbox_sf_emul_ops, | 606 | .ops = &sandbox_sf_emul_ops, |
| 607 | }; | 607 | }; |
| 608 | 608 |
| 1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* | 2 | /* |
| 3 | * Atmel DataFlash probing | 3 | * Atmel DataFlash probing |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. | 5 | * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. |
| 6 | * Haikun Wang (haikun.wang@freescale.com) | 6 | * Haikun Wang (haikun.wang@freescale.com) |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <common.h> | 9 | #include <common.h> |
| 10 | #include <dm.h> | 10 | #include <dm.h> |
| 11 | #include <errno.h> | 11 | #include <errno.h> |
| 12 | #include <fdtdec.h> | 12 | #include <fdtdec.h> |
| 13 | #include <spi.h> | 13 | #include <spi.h> |
| 14 | #include <spi_flash.h> | 14 | #include <spi_flash.h> |
| 15 | #include <div64.h> | 15 | #include <div64.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/math64.h> | 17 | #include <linux/math64.h> |
| 18 | 18 | ||
| 19 | #include "sf_internal.h" | 19 | #include "sf_internal.h" |
| 20 | 20 | ||
| 21 | #define CMD_READ_ID 0x9f | ||
| 21 | /* reads can bypass the buffers */ | 22 | /* reads can bypass the buffers */ |
| 22 | #define OP_READ_CONTINUOUS 0xE8 | 23 | #define OP_READ_CONTINUOUS 0xE8 |
| 23 | #define OP_READ_PAGE 0xD2 | 24 | #define OP_READ_PAGE 0xD2 |
| 24 | 25 | ||
| 25 | /* group B requests can run even while status reports "busy" */ | 26 | /* group B requests can run even while status reports "busy" */ |
| 26 | #define OP_READ_STATUS 0xD7 /* group B */ | 27 | #define OP_READ_STATUS 0xD7 /* group B */ |
| 27 | 28 | ||
| 28 | /* move data between host and buffer */ | 29 | /* move data between host and buffer */ |
| 29 | #define OP_READ_BUFFER1 0xD4 /* group B */ | 30 | #define OP_READ_BUFFER1 0xD4 /* group B */ |
| 30 | #define OP_READ_BUFFER2 0xD6 /* group B */ | 31 | #define OP_READ_BUFFER2 0xD6 /* group B */ |
| 31 | #define OP_WRITE_BUFFER1 0x84 /* group B */ | 32 | #define OP_WRITE_BUFFER1 0x84 /* group B */ |
| 32 | #define OP_WRITE_BUFFER2 0x87 /* group B */ | 33 | #define OP_WRITE_BUFFER2 0x87 /* group B */ |
| 33 | 34 | ||
| 34 | /* erasing flash */ | 35 | /* erasing flash */ |
| 35 | #define OP_ERASE_PAGE 0x81 | 36 | #define OP_ERASE_PAGE 0x81 |
| 36 | #define OP_ERASE_BLOCK 0x50 | 37 | #define OP_ERASE_BLOCK 0x50 |
| 37 | 38 | ||
| 38 | /* move data between buffer and flash */ | 39 | /* move data between buffer and flash */ |
| 39 | #define OP_TRANSFER_BUF1 0x53 | 40 | #define OP_TRANSFER_BUF1 0x53 |
| 40 | #define OP_TRANSFER_BUF2 0x55 | 41 | #define OP_TRANSFER_BUF2 0x55 |
| 41 | #define OP_MREAD_BUFFER1 0xD4 | 42 | #define OP_MREAD_BUFFER1 0xD4 |
| 42 | #define OP_MREAD_BUFFER2 0xD6 | 43 | #define OP_MREAD_BUFFER2 0xD6 |
| 43 | #define OP_MWERASE_BUFFER1 0x83 | 44 | #define OP_MWERASE_BUFFER1 0x83 |
| 44 | #define OP_MWERASE_BUFFER2 0x86 | 45 | #define OP_MWERASE_BUFFER2 0x86 |
| 45 | #define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ | 46 | #define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ |
| 46 | #define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ | 47 | #define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ |
| 47 | 48 | ||
| 48 | /* write to buffer, then write-erase to flash */ | 49 | /* write to buffer, then write-erase to flash */ |
| 49 | #define OP_PROGRAM_VIA_BUF1 0x82 | 50 | #define OP_PROGRAM_VIA_BUF1 0x82 |
| 50 | #define OP_PROGRAM_VIA_BUF2 0x85 | 51 | #define OP_PROGRAM_VIA_BUF2 0x85 |
| 51 | 52 | ||
| 52 | /* compare buffer to flash */ | 53 | /* compare buffer to flash */ |
| 53 | #define OP_COMPARE_BUF1 0x60 | 54 | #define OP_COMPARE_BUF1 0x60 |
| 54 | #define OP_COMPARE_BUF2 0x61 | 55 | #define OP_COMPARE_BUF2 0x61 |
| 55 | 56 | ||
| 56 | /* read flash to buffer, then write-erase to flash */ | 57 | /* read flash to buffer, then write-erase to flash */ |
| 57 | #define OP_REWRITE_VIA_BUF1 0x58 | 58 | #define OP_REWRITE_VIA_BUF1 0x58 |
| 58 | #define OP_REWRITE_VIA_BUF2 0x59 | 59 | #define OP_REWRITE_VIA_BUF2 0x59 |
| 59 | 60 | ||
| 60 | /* | 61 | /* |
| 61 | * newer chips report JEDEC manufacturer and device IDs; chip | 62 | * newer chips report JEDEC manufacturer and device IDs; chip |
| 62 | * serial number and OTP bits; and per-sector writeprotect. | 63 | * serial number and OTP bits; and per-sector writeprotect. |
| 63 | */ | 64 | */ |
| 64 | #define OP_READ_ID 0x9F | 65 | #define OP_READ_ID 0x9F |
| 65 | #define OP_READ_SECURITY 0x77 | 66 | #define OP_READ_SECURITY 0x77 |
| 66 | #define OP_WRITE_SECURITY_REVC 0x9A | 67 | #define OP_WRITE_SECURITY_REVC 0x9A |
| 67 | #define OP_WRITE_SECURITY 0x9B /* revision D */ | 68 | #define OP_WRITE_SECURITY 0x9B /* revision D */ |
| 68 | 69 | ||
| 69 | struct dataflash { | 70 | struct dataflash { |
| 70 | uint8_t command[16]; | 71 | uint8_t command[16]; |
| 71 | unsigned short page_offset; /* offset in flash address */ | 72 | unsigned short page_offset; /* offset in flash address */ |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | /* Return the status of the DataFlash device */ | 75 | /* Return the status of the DataFlash device */ |
| 75 | static inline int dataflash_status(struct spi_slave *spi) | 76 | static inline int dataflash_status(struct spi_slave *spi) |
| 76 | { | 77 | { |
| 77 | int ret; | 78 | int ret; |
| 78 | u8 status; | 79 | u8 status; |
| 79 | /* | 80 | /* |
| 80 | * NOTE: at45db321c over 25 MHz wants to write | 81 | * NOTE: at45db321c over 25 MHz wants to write |
| 81 | * a dummy byte after the opcode... | 82 | * a dummy byte after the opcode... |
| 82 | */ | 83 | */ |
| 83 | ret = spi_flash_cmd(spi, OP_READ_STATUS, &status, 1); | 84 | ret = spi_flash_cmd(spi, OP_READ_STATUS, &status, 1); |
| 84 | return ret ? -EIO : status; | 85 | return ret ? -EIO : status; |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | /* | 88 | /* |
| 88 | * Poll the DataFlash device until it is READY. | 89 | * Poll the DataFlash device until it is READY. |
| 89 | * This usually takes 5-20 msec or so; more for sector erase. | 90 | * This usually takes 5-20 msec or so; more for sector erase. |
| 90 | * ready: return > 0 | 91 | * ready: return > 0 |
| 91 | */ | 92 | */ |
| 92 | static int dataflash_waitready(struct spi_slave *spi) | 93 | static int dataflash_waitready(struct spi_slave *spi) |
| 93 | { | 94 | { |
| 94 | int status; | 95 | int status; |
| 95 | int timeout = 2 * CONFIG_SYS_HZ; | 96 | int timeout = 2 * CONFIG_SYS_HZ; |
| 96 | int timebase; | 97 | int timebase; |
| 97 | 98 | ||
| 98 | timebase = get_timer(0); | 99 | timebase = get_timer(0); |
| 99 | do { | 100 | do { |
| 100 | status = dataflash_status(spi); | 101 | status = dataflash_status(spi); |
| 101 | if (status < 0) | 102 | if (status < 0) |
| 102 | status = 0; | 103 | status = 0; |
| 103 | 104 | ||
| 104 | if (status & (1 << 7)) /* RDY/nBSY */ | 105 | if (status & (1 << 7)) /* RDY/nBSY */ |
| 105 | return status; | 106 | return status; |
| 106 | 107 | ||
| 107 | mdelay(3); | 108 | mdelay(3); |
| 108 | } while (get_timer(timebase) < timeout); | 109 | } while (get_timer(timebase) < timeout); |
| 109 | 110 | ||
| 110 | return -ETIME; | 111 | return -ETIME; |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | /* Erase pages of flash */ | 114 | /* Erase pages of flash */ |
| 114 | static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) | 115 | static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) |
| 115 | { | 116 | { |
| 116 | struct dataflash *dataflash; | 117 | struct dataflash *dataflash; |
| 117 | struct spi_flash *spi_flash; | 118 | struct spi_flash *spi_flash; |
| 118 | struct spi_slave *spi; | 119 | struct spi_slave *spi; |
| 119 | unsigned blocksize; | 120 | unsigned blocksize; |
| 120 | uint8_t *command; | 121 | uint8_t *command; |
| 121 | uint32_t rem; | 122 | uint32_t rem; |
| 122 | int status; | 123 | int status; |
| 123 | 124 | ||
| 124 | dataflash = dev_get_priv(dev); | 125 | dataflash = dev_get_priv(dev); |
| 125 | spi_flash = dev_get_uclass_priv(dev); | 126 | spi_flash = dev_get_uclass_priv(dev); |
| 126 | spi = spi_flash->spi; | 127 | spi = spi_flash->spi; |
| 127 | 128 | ||
| 128 | blocksize = spi_flash->page_size << 3; | 129 | blocksize = spi_flash->page_size << 3; |
| 129 | 130 | ||
| 130 | memset(dataflash->command, 0 , sizeof(dataflash->command)); | 131 | memset(dataflash->command, 0 , sizeof(dataflash->command)); |
| 131 | command = dataflash->command; | 132 | command = dataflash->command; |
| 132 | 133 | ||
| 133 | debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); | 134 | debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); |
| 134 | 135 | ||
| 135 | div_u64_rem(len, spi_flash->page_size, &rem); | 136 | div_u64_rem(len, spi_flash->page_size, &rem); |
| 136 | if (rem) { | 137 | if (rem) { |
| 137 | printf("%s: len(0x%x) isn't the multiple of page size(0x%x)\n", | 138 | printf("%s: len(0x%x) isn't the multiple of page size(0x%x)\n", |
| 138 | dev->name, len, spi_flash->page_size); | 139 | dev->name, len, spi_flash->page_size); |
| 139 | return -EINVAL; | 140 | return -EINVAL; |
| 140 | } | 141 | } |
| 141 | div_u64_rem(offset, spi_flash->page_size, &rem); | 142 | div_u64_rem(offset, spi_flash->page_size, &rem); |
| 142 | if (rem) { | 143 | if (rem) { |
| 143 | printf("%s: offset(0x%x) isn't the multiple of page size(0x%x)\n", | 144 | printf("%s: offset(0x%x) isn't the multiple of page size(0x%x)\n", |
| 144 | dev->name, offset, spi_flash->page_size); | 145 | dev->name, offset, spi_flash->page_size); |
| 145 | return -EINVAL; | 146 | return -EINVAL; |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | status = spi_claim_bus(spi); | 149 | status = spi_claim_bus(spi); |
| 149 | if (status) { | 150 | if (status) { |
| 150 | debug("dataflash: unable to claim SPI bus\n"); | 151 | debug("dataflash: unable to claim SPI bus\n"); |
| 151 | return status; | 152 | return status; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | while (len > 0) { | 155 | while (len > 0) { |
| 155 | unsigned int pageaddr; | 156 | unsigned int pageaddr; |
| 156 | int do_block; | 157 | int do_block; |
| 157 | /* | 158 | /* |
| 158 | * Calculate flash page address; use block erase (for speed) if | 159 | * Calculate flash page address; use block erase (for speed) if |
| 159 | * we're at a block boundary and need to erase the whole block. | 160 | * we're at a block boundary and need to erase the whole block. |
| 160 | */ | 161 | */ |
| 161 | pageaddr = div_u64(offset, spi_flash->page_size); | 162 | pageaddr = div_u64(offset, spi_flash->page_size); |
| 162 | do_block = (pageaddr & 0x7) == 0 && len >= blocksize; | 163 | do_block = (pageaddr & 0x7) == 0 && len >= blocksize; |
| 163 | pageaddr = pageaddr << dataflash->page_offset; | 164 | pageaddr = pageaddr << dataflash->page_offset; |
| 164 | 165 | ||
| 165 | command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; | 166 | command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; |
| 166 | command[1] = (uint8_t)(pageaddr >> 16); | 167 | command[1] = (uint8_t)(pageaddr >> 16); |
| 167 | command[2] = (uint8_t)(pageaddr >> 8); | 168 | command[2] = (uint8_t)(pageaddr >> 8); |
| 168 | command[3] = 0; | 169 | command[3] = 0; |
| 169 | 170 | ||
| 170 | debug("%s ERASE %s: (%x) %x %x %x [%d]\n", | 171 | debug("%s ERASE %s: (%x) %x %x %x [%d]\n", |
| 171 | dev->name, do_block ? "block" : "page", | 172 | dev->name, do_block ? "block" : "page", |
| 172 | command[0], command[1], command[2], command[3], | 173 | command[0], command[1], command[2], command[3], |
| 173 | pageaddr); | 174 | pageaddr); |
| 174 | 175 | ||
| 175 | status = spi_flash_cmd_write(spi, command, 4, NULL, 0); | 176 | status = spi_flash_cmd_write(spi, command, 4, NULL, 0); |
| 176 | if (status < 0) { | 177 | if (status < 0) { |
| 177 | debug("%s: erase send command error!\n", dev->name); | 178 | debug("%s: erase send command error!\n", dev->name); |
| 178 | return -EIO; | 179 | return -EIO; |
| 179 | } | 180 | } |
| 180 | 181 | ||
| 181 | status = dataflash_waitready(spi); | 182 | status = dataflash_waitready(spi); |
| 182 | if (status < 0) { | 183 | if (status < 0) { |
| 183 | debug("%s: erase waitready error!\n", dev->name); | 184 | debug("%s: erase waitready error!\n", dev->name); |
| 184 | return status; | 185 | return status; |
| 185 | } | 186 | } |
| 186 | 187 | ||
| 187 | if (do_block) { | 188 | if (do_block) { |
| 188 | offset += blocksize; | 189 | offset += blocksize; |
| 189 | len -= blocksize; | 190 | len -= blocksize; |
| 190 | } else { | 191 | } else { |
| 191 | offset += spi_flash->page_size; | 192 | offset += spi_flash->page_size; |
| 192 | len -= spi_flash->page_size; | 193 | len -= spi_flash->page_size; |
| 193 | } | 194 | } |
| 194 | } | 195 | } |
| 195 | 196 | ||
| 196 | spi_release_bus(spi); | 197 | spi_release_bus(spi); |
| 197 | 198 | ||
| 198 | return 0; | 199 | return 0; |
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | /* | 202 | /* |
| 202 | * Read from the DataFlash device. | 203 | * Read from the DataFlash device. |
| 203 | * offset : Start offset in flash device | 204 | * offset : Start offset in flash device |
| 204 | * len : Amount to read | 205 | * len : Amount to read |
| 205 | * buf : Buffer containing the data | 206 | * buf : Buffer containing the data |
| 206 | */ | 207 | */ |
| 207 | static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, | 208 | static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, |
| 208 | void *buf) | 209 | void *buf) |
| 209 | { | 210 | { |
| 210 | struct dataflash *dataflash; | 211 | struct dataflash *dataflash; |
| 211 | struct spi_flash *spi_flash; | 212 | struct spi_flash *spi_flash; |
| 212 | struct spi_slave *spi; | 213 | struct spi_slave *spi; |
| 213 | unsigned int addr; | 214 | unsigned int addr; |
| 214 | uint8_t *command; | 215 | uint8_t *command; |
| 215 | int status; | 216 | int status; |
| 216 | 217 | ||
| 217 | dataflash = dev_get_priv(dev); | 218 | dataflash = dev_get_priv(dev); |
| 218 | spi_flash = dev_get_uclass_priv(dev); | 219 | spi_flash = dev_get_uclass_priv(dev); |
| 219 | spi = spi_flash->spi; | 220 | spi = spi_flash->spi; |
| 220 | 221 | ||
| 221 | memset(dataflash->command, 0 , sizeof(dataflash->command)); | 222 | memset(dataflash->command, 0 , sizeof(dataflash->command)); |
| 222 | command = dataflash->command; | 223 | command = dataflash->command; |
| 223 | 224 | ||
| 224 | debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); | 225 | debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); |
| 225 | debug("READ: (%x) %x %x %x\n", | 226 | debug("READ: (%x) %x %x %x\n", |
| 226 | command[0], command[1], command[2], command[3]); | 227 | command[0], command[1], command[2], command[3]); |
| 227 | 228 | ||
| 228 | /* Calculate flash page/byte address */ | 229 | /* Calculate flash page/byte address */ |
| 229 | addr = (((unsigned)offset / spi_flash->page_size) | 230 | addr = (((unsigned)offset / spi_flash->page_size) |
| 230 | << dataflash->page_offset) | 231 | << dataflash->page_offset) |
| 231 | + ((unsigned)offset % spi_flash->page_size); | 232 | + ((unsigned)offset % spi_flash->page_size); |
| 232 | 233 | ||
| 233 | status = spi_claim_bus(spi); | 234 | status = spi_claim_bus(spi); |
| 234 | if (status) { | 235 | if (status) { |
| 235 | debug("dataflash: unable to claim SPI bus\n"); | 236 | debug("dataflash: unable to claim SPI bus\n"); |
| 236 | return status; | 237 | return status; |
| 237 | } | 238 | } |
| 238 | 239 | ||
| 239 | /* | 240 | /* |
| 240 | * Continuous read, max clock = f(car) which may be less than | 241 | * Continuous read, max clock = f(car) which may be less than |
| 241 | * the peak rate available. Some chips support commands with | 242 | * the peak rate available. Some chips support commands with |
| 242 | * fewer "don't care" bytes. Both buffers stay unchanged. | 243 | * fewer "don't care" bytes. Both buffers stay unchanged. |
| 243 | */ | 244 | */ |
| 244 | command[0] = OP_READ_CONTINUOUS; | 245 | command[0] = OP_READ_CONTINUOUS; |
| 245 | command[1] = (uint8_t)(addr >> 16); | 246 | command[1] = (uint8_t)(addr >> 16); |
| 246 | command[2] = (uint8_t)(addr >> 8); | 247 | command[2] = (uint8_t)(addr >> 8); |
| 247 | command[3] = (uint8_t)(addr >> 0); | 248 | command[3] = (uint8_t)(addr >> 0); |
| 248 | 249 | ||
| 249 | /* plus 4 "don't care" bytes, command len: 4 + 4 "don't care" bytes */ | 250 | /* plus 4 "don't care" bytes, command len: 4 + 4 "don't care" bytes */ |
| 250 | status = spi_flash_cmd_read(spi, command, 8, buf, len); | 251 | status = spi_flash_cmd_read(spi, command, 8, buf, len); |
| 251 | 252 | ||
| 252 | spi_release_bus(spi); | 253 | spi_release_bus(spi); |
| 253 | 254 | ||
| 254 | return status; | 255 | return status; |
| 255 | } | 256 | } |
| 256 | 257 | ||
| 257 | /* | 258 | /* |
| 258 | * Write to the DataFlash device. | 259 | * Write to the DataFlash device. |
| 259 | * offset : Start offset in flash device | 260 | * offset : Start offset in flash device |
| 260 | * len : Amount to write | 261 | * len : Amount to write |
| 261 | * buf : Buffer containing the data | 262 | * buf : Buffer containing the data |
| 262 | */ | 263 | */ |
| 263 | int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, | 264 | int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, |
| 264 | const void *buf) | 265 | const void *buf) |
| 265 | { | 266 | { |
| 266 | struct dataflash *dataflash; | 267 | struct dataflash *dataflash; |
| 267 | struct spi_flash *spi_flash; | 268 | struct spi_flash *spi_flash; |
| 268 | struct spi_slave *spi; | 269 | struct spi_slave *spi; |
| 269 | uint8_t *command; | 270 | uint8_t *command; |
| 270 | unsigned int pageaddr, addr, to, writelen; | 271 | unsigned int pageaddr, addr, to, writelen; |
| 271 | size_t remaining = len; | 272 | size_t remaining = len; |
| 272 | u_char *writebuf = (u_char *)buf; | 273 | u_char *writebuf = (u_char *)buf; |
| 273 | int status = -EINVAL; | 274 | int status = -EINVAL; |
| 274 | 275 | ||
| 275 | dataflash = dev_get_priv(dev); | 276 | dataflash = dev_get_priv(dev); |
| 276 | spi_flash = dev_get_uclass_priv(dev); | 277 | spi_flash = dev_get_uclass_priv(dev); |
| 277 | spi = spi_flash->spi; | 278 | spi = spi_flash->spi; |
| 278 | 279 | ||
| 279 | memset(dataflash->command, 0 , sizeof(dataflash->command)); | 280 | memset(dataflash->command, 0 , sizeof(dataflash->command)); |
| 280 | command = dataflash->command; | 281 | command = dataflash->command; |
| 281 | 282 | ||
| 282 | debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); | 283 | debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); |
| 283 | 284 | ||
| 284 | pageaddr = ((unsigned)offset / spi_flash->page_size); | 285 | pageaddr = ((unsigned)offset / spi_flash->page_size); |
| 285 | to = ((unsigned)offset % spi_flash->page_size); | 286 | to = ((unsigned)offset % spi_flash->page_size); |
| 286 | if (to + len > spi_flash->page_size) | 287 | if (to + len > spi_flash->page_size) |
| 287 | writelen = spi_flash->page_size - to; | 288 | writelen = spi_flash->page_size - to; |
| 288 | else | 289 | else |
| 289 | writelen = len; | 290 | writelen = len; |
| 290 | 291 | ||
| 291 | status = spi_claim_bus(spi); | 292 | status = spi_claim_bus(spi); |
| 292 | if (status) { | 293 | if (status) { |
| 293 | debug("dataflash: unable to claim SPI bus\n"); | 294 | debug("dataflash: unable to claim SPI bus\n"); |
| 294 | return status; | 295 | return status; |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 297 | while (remaining > 0) { | 298 | while (remaining > 0) { |
| 298 | debug("write @ %d:%d len=%d\n", pageaddr, to, writelen); | 299 | debug("write @ %d:%d len=%d\n", pageaddr, to, writelen); |
| 299 | 300 | ||
| 300 | /* | 301 | /* |
| 301 | * REVISIT: | 302 | * REVISIT: |
| 302 | * (a) each page in a sector must be rewritten at least | 303 | * (a) each page in a sector must be rewritten at least |
| 303 | * once every 10K sibling erase/program operations. | 304 | * once every 10K sibling erase/program operations. |
| 304 | * (b) for pages that are already erased, we could | 305 | * (b) for pages that are already erased, we could |
| 305 | * use WRITE+MWRITE not PROGRAM for ~30% speedup. | 306 | * use WRITE+MWRITE not PROGRAM for ~30% speedup. |
| 306 | * (c) WRITE to buffer could be done while waiting for | 307 | * (c) WRITE to buffer could be done while waiting for |
| 307 | * a previous MWRITE/MWERASE to complete ... | 308 | * a previous MWRITE/MWERASE to complete ... |
| 308 | * (d) error handling here seems to be mostly missing. | 309 | * (d) error handling here seems to be mostly missing. |
| 309 | * | 310 | * |
| 310 | * Two persistent bits per page, plus a per-sector counter, | 311 | * Two persistent bits per page, plus a per-sector counter, |
| 311 | * could support (a) and (b) ... we might consider using | 312 | * could support (a) and (b) ... we might consider using |
| 312 | * the second half of sector zero, which is just one block, | 313 | * the second half of sector zero, which is just one block, |
| 313 | * to track that state. (On AT91, that sector should also | 314 | * to track that state. (On AT91, that sector should also |
| 314 | * support boot-from-DataFlash.) | 315 | * support boot-from-DataFlash.) |
| 315 | */ | 316 | */ |
| 316 | 317 | ||
| 317 | addr = pageaddr << dataflash->page_offset; | 318 | addr = pageaddr << dataflash->page_offset; |
| 318 | 319 | ||
| 319 | /* (1) Maybe transfer partial page to Buffer1 */ | 320 | /* (1) Maybe transfer partial page to Buffer1 */ |
| 320 | if (writelen != spi_flash->page_size) { | 321 | if (writelen != spi_flash->page_size) { |
| 321 | command[0] = OP_TRANSFER_BUF1; | 322 | command[0] = OP_TRANSFER_BUF1; |
| 322 | command[1] = (addr & 0x00FF0000) >> 16; | 323 | command[1] = (addr & 0x00FF0000) >> 16; |
| 323 | command[2] = (addr & 0x0000FF00) >> 8; | 324 | command[2] = (addr & 0x0000FF00) >> 8; |
| 324 | command[3] = 0; | 325 | command[3] = 0; |
| 325 | 326 | ||
| 326 | debug("TRANSFER: (%x) %x %x %x\n", | 327 | debug("TRANSFER: (%x) %x %x %x\n", |
| 327 | command[0], command[1], command[2], command[3]); | 328 | command[0], command[1], command[2], command[3]); |
| 328 | 329 | ||
| 329 | status = spi_flash_cmd_write(spi, command, 4, NULL, 0); | 330 | status = spi_flash_cmd_write(spi, command, 4, NULL, 0); |
| 330 | if (status < 0) { | 331 | if (status < 0) { |
| 331 | debug("%s: write(<pagesize) command error!\n", | 332 | debug("%s: write(<pagesize) command error!\n", |
| 332 | dev->name); | 333 | dev->name); |
| 333 | return -EIO; | 334 | return -EIO; |
| 334 | } | 335 | } |
| 335 | 336 | ||
| 336 | status = dataflash_waitready(spi); | 337 | status = dataflash_waitready(spi); |
| 337 | if (status < 0) { | 338 | if (status < 0) { |
| 338 | debug("%s: write(<pagesize) waitready error!\n", | 339 | debug("%s: write(<pagesize) waitready error!\n", |
| 339 | dev->name); | 340 | dev->name); |
| 340 | return status; | 341 | return status; |
| 341 | } | 342 | } |
| 342 | } | 343 | } |
| 343 | 344 | ||
| 344 | /* (2) Program full page via Buffer1 */ | 345 | /* (2) Program full page via Buffer1 */ |
| 345 | addr += to; | 346 | addr += to; |
| 346 | command[0] = OP_PROGRAM_VIA_BUF1; | 347 | command[0] = OP_PROGRAM_VIA_BUF1; |
| 347 | command[1] = (addr & 0x00FF0000) >> 16; | 348 | command[1] = (addr & 0x00FF0000) >> 16; |
| 348 | command[2] = (addr & 0x0000FF00) >> 8; | 349 | command[2] = (addr & 0x0000FF00) >> 8; |
| 349 | command[3] = (addr & 0x000000FF); | 350 | command[3] = (addr & 0x000000FF); |
| 350 | 351 | ||
| 351 | debug("PROGRAM: (%x) %x %x %x\n", | 352 | debug("PROGRAM: (%x) %x %x %x\n", |
| 352 | command[0], command[1], command[2], command[3]); | 353 | command[0], command[1], command[2], command[3]); |
| 353 | 354 | ||
| 354 | status = spi_flash_cmd_write(spi, command, | 355 | status = spi_flash_cmd_write(spi, command, |
| 355 | 4, writebuf, writelen); | 356 | 4, writebuf, writelen); |
| 356 | if (status < 0) { | 357 | if (status < 0) { |
| 357 | debug("%s: write send command error!\n", dev->name); | 358 | debug("%s: write send command error!\n", dev->name); |
| 358 | return -EIO; | 359 | return -EIO; |
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | status = dataflash_waitready(spi); | 362 | status = dataflash_waitready(spi); |
| 362 | if (status < 0) { | 363 | if (status < 0) { |
| 363 | debug("%s: write waitready error!\n", dev->name); | 364 | debug("%s: write waitready error!\n", dev->name); |
| 364 | return status; | 365 | return status; |
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | #ifdef CONFIG_SPI_DATAFLASH_WRITE_VERIFY | 368 | #ifdef CONFIG_SPI_DATAFLASH_WRITE_VERIFY |
| 368 | /* (3) Compare to Buffer1 */ | 369 | /* (3) Compare to Buffer1 */ |
| 369 | addr = pageaddr << dataflash->page_offset; | 370 | addr = pageaddr << dataflash->page_offset; |
| 370 | command[0] = OP_COMPARE_BUF1; | 371 | command[0] = OP_COMPARE_BUF1; |
| 371 | command[1] = (addr & 0x00FF0000) >> 16; | 372 | command[1] = (addr & 0x00FF0000) >> 16; |
| 372 | command[2] = (addr & 0x0000FF00) >> 8; | 373 | command[2] = (addr & 0x0000FF00) >> 8; |
| 373 | command[3] = 0; | 374 | command[3] = 0; |
| 374 | 375 | ||
| 375 | debug("COMPARE: (%x) %x %x %x\n", | 376 | debug("COMPARE: (%x) %x %x %x\n", |
| 376 | command[0], command[1], command[2], command[3]); | 377 | command[0], command[1], command[2], command[3]); |
| 377 | 378 | ||
| 378 | status = spi_flash_cmd_write(spi, command, | 379 | status = spi_flash_cmd_write(spi, command, |
| 379 | 4, writebuf, writelen); | 380 | 4, writebuf, writelen); |
| 380 | if (status < 0) { | 381 | if (status < 0) { |
| 381 | debug("%s: write(compare) send command error!\n", | 382 | debug("%s: write(compare) send command error!\n", |
| 382 | dev->name); | 383 | dev->name); |
| 383 | return -EIO; | 384 | return -EIO; |
| 384 | } | 385 | } |
| 385 | 386 | ||
| 386 | status = dataflash_waitready(spi); | 387 | status = dataflash_waitready(spi); |
| 387 | 388 | ||
| 388 | /* Check result of the compare operation */ | 389 | /* Check result of the compare operation */ |
| 389 | if (status & (1 << 6)) { | 390 | if (status & (1 << 6)) { |
| 390 | printf("dataflash: write compare page %u, err %d\n", | 391 | printf("dataflash: write compare page %u, err %d\n", |
| 391 | pageaddr, status); | 392 | pageaddr, status); |
| 392 | remaining = 0; | 393 | remaining = 0; |
| 393 | status = -EIO; | 394 | status = -EIO; |
| 394 | break; | 395 | break; |
| 395 | } else { | 396 | } else { |
| 396 | status = 0; | 397 | status = 0; |
| 397 | } | 398 | } |
| 398 | 399 | ||
| 399 | #endif /* CONFIG_SPI_DATAFLASH_WRITE_VERIFY */ | 400 | #endif /* CONFIG_SPI_DATAFLASH_WRITE_VERIFY */ |
| 400 | remaining = remaining - writelen; | 401 | remaining = remaining - writelen; |
| 401 | pageaddr++; | 402 | pageaddr++; |
| 402 | to = 0; | 403 | to = 0; |
| 403 | writebuf += writelen; | 404 | writebuf += writelen; |
| 404 | 405 | ||
| 405 | if (remaining > spi_flash->page_size) | 406 | if (remaining > spi_flash->page_size) |
| 406 | writelen = spi_flash->page_size; | 407 | writelen = spi_flash->page_size; |
| 407 | else | 408 | else |
| 408 | writelen = remaining; | 409 | writelen = remaining; |
| 409 | } | 410 | } |
| 410 | 411 | ||
| 411 | spi_release_bus(spi); | 412 | spi_release_bus(spi); |
| 412 | 413 | ||
| 413 | return 0; | 414 | return 0; |
| 414 | } | 415 | } |
| 415 | 416 | ||
| 416 | static int add_dataflash(struct udevice *dev, char *name, int nr_pages, | 417 | static int add_dataflash(struct udevice *dev, char *name, int nr_pages, |
| 417 | int pagesize, int pageoffset, char revision) | 418 | int pagesize, int pageoffset, char revision) |
| 418 | { | 419 | { |
| 419 | struct spi_flash *spi_flash; | 420 | struct spi_flash *spi_flash; |
| 420 | struct dataflash *dataflash; | 421 | struct dataflash *dataflash; |
| 421 | 422 | ||
| 422 | dataflash = dev_get_priv(dev); | 423 | dataflash = dev_get_priv(dev); |
| 423 | spi_flash = dev_get_uclass_priv(dev); | 424 | spi_flash = dev_get_uclass_priv(dev); |
| 424 | 425 | ||
| 425 | dataflash->page_offset = pageoffset; | 426 | dataflash->page_offset = pageoffset; |
| 426 | 427 | ||
| 427 | spi_flash->name = name; | 428 | spi_flash->name = name; |
| 428 | spi_flash->page_size = pagesize; | 429 | spi_flash->page_size = pagesize; |
| 429 | spi_flash->size = nr_pages * pagesize; | 430 | spi_flash->size = nr_pages * pagesize; |
| 430 | spi_flash->erase_size = pagesize; | 431 | spi_flash->erase_size = pagesize; |
| 431 | 432 | ||
| 432 | #ifndef CONFIG_SPL_BUILD | 433 | #ifndef CONFIG_SPL_BUILD |
| 433 | printf("SPI DataFlash: Detected %s with page size ", spi_flash->name); | 434 | printf("SPI DataFlash: Detected %s with page size ", spi_flash->name); |
| 434 | print_size(spi_flash->page_size, ", erase size "); | 435 | print_size(spi_flash->page_size, ", erase size "); |
| 435 | print_size(spi_flash->erase_size, ", total "); | 436 | print_size(spi_flash->erase_size, ", total "); |
| 436 | print_size(spi_flash->size, ""); | 437 | print_size(spi_flash->size, ""); |
| 437 | printf(", revision %c", revision); | 438 | printf(", revision %c", revision); |
| 438 | puts("\n"); | 439 | puts("\n"); |
| 439 | #endif | 440 | #endif |
| 440 | 441 | ||
| 441 | return 0; | 442 | return 0; |
| 442 | } | 443 | } |
| 443 | 444 | ||
| 444 | struct flash_info { | 445 | struct data_flash_info { |
| 445 | char *name; | 446 | char *name; |
| 446 | 447 | ||
| 447 | /* | 448 | /* |
| 448 | * JEDEC id has a high byte of zero plus three data bytes: | 449 | * JEDEC id has a high byte of zero plus three data bytes: |
| 449 | * the manufacturer id, then a two byte device id. | 450 | * the manufacturer id, then a two byte device id. |
| 450 | */ | 451 | */ |
| 451 | uint32_t jedec_id; | 452 | uint32_t jedec_id; |
| 452 | 453 | ||
| 453 | /* The size listed here is what works with OP_ERASE_PAGE. */ | 454 | /* The size listed here is what works with OP_ERASE_PAGE. */ |
| 454 | unsigned nr_pages; | 455 | unsigned nr_pages; |
| 455 | uint16_t pagesize; | 456 | uint16_t pagesize; |
| 456 | uint16_t pageoffset; | 457 | uint16_t pageoffset; |
| 457 | 458 | ||
| 458 | uint16_t flags; | 459 | uint16_t flags; |
| 459 | #define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ | 460 | #define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ |
| 460 | #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ | 461 | #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ |
| 461 | }; | 462 | }; |
| 462 | 463 | ||
| 463 | static struct flash_info dataflash_data[] = { | 464 | static struct data_flash_info dataflash_data[] = { |
| 464 | /* | 465 | /* |
| 465 | * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, | 466 | * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, |
| 466 | * one with IS_POW2PS and the other without. The entry with the | 467 | * one with IS_POW2PS and the other without. The entry with the |
| 467 | * non-2^N byte page size can't name exact chip revisions without | 468 | * non-2^N byte page size can't name exact chip revisions without |
| 468 | * losing backwards compatibility for cmdlinepart. | 469 | * losing backwards compatibility for cmdlinepart. |
| 469 | * | 470 | * |
| 470 | * Those two entries have different name spelling format in order to | 471 | * Those two entries have different name spelling format in order to |
| 471 | * show their difference obviously. | 472 | * show their difference obviously. |
| 472 | * The upper case refer to the chip isn't in normal 2^N bytes page-size | 473 | * The upper case refer to the chip isn't in normal 2^N bytes page-size |
| 473 | * mode. | 474 | * mode. |
| 474 | * The lower case refer to the chip is in normal 2^N bytes page-size | 475 | * The lower case refer to the chip is in normal 2^N bytes page-size |
| 475 | * mode. | 476 | * mode. |
| 476 | * | 477 | * |
| 477 | * These newer chips also support 128-byte security registers (with | 478 | * These newer chips also support 128-byte security registers (with |
| 478 | * 64 bytes one-time-programmable) and software write-protection. | 479 | * 64 bytes one-time-programmable) and software write-protection. |
| 479 | */ | 480 | */ |
| 480 | { "AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS}, | 481 | { "AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS}, |
| 481 | { "at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS}, | 482 | { "at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS}, |
| 482 | 483 | ||
| 483 | { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, | 484 | { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, |
| 484 | { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, | 485 | { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, |
| 485 | 486 | ||
| 486 | { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, | 487 | { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, |
| 487 | { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, | 488 | { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, |
| 488 | 489 | ||
| 489 | { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, | 490 | { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, |
| 490 | { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, | 491 | { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, |
| 491 | 492 | ||
| 492 | { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, | 493 | { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, |
| 493 | { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, | 494 | { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, |
| 494 | 495 | ||
| 495 | { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ | 496 | { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ |
| 496 | 497 | ||
| 497 | { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, | 498 | { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, |
| 498 | { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, | 499 | { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, |
| 499 | 500 | ||
| 500 | { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, | 501 | { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, |
| 501 | { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, | 502 | { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, |
| 502 | }; | 503 | }; |
| 503 | 504 | ||
| 504 | static struct flash_info *jedec_probe(struct spi_slave *spi) | 505 | static struct data_flash_info *jedec_probe(struct spi_slave *spi) |
| 505 | { | 506 | { |
| 506 | int tmp; | 507 | int tmp; |
| 507 | uint8_t id[5]; | 508 | uint8_t id[5]; |
| 508 | uint32_t jedec; | 509 | uint32_t jedec; |
| 509 | struct flash_info *info; | 510 | struct data_flash_info *info; |
| 510 | int status; | 511 | int status; |
| 511 | 512 | ||
| 512 | /* | 513 | /* |
| 513 | * JEDEC also defines an optional "extended device information" | 514 | * JEDEC also defines an optional "extended device information" |
| 514 | * string for after vendor-specific data, after the three bytes | 515 | * string for after vendor-specific data, after the three bytes |
| 515 | * we use here. Supporting some chips might require using it. | 516 | * we use here. Supporting some chips might require using it. |
| 516 | * | 517 | * |
| 517 | * If the vendor ID isn't Atmel's (0x1f), assume this call failed. | 518 | * If the vendor ID isn't Atmel's (0x1f), assume this call failed. |
| 518 | * That's not an error; only rev C and newer chips handle it, and | 519 | * That's not an error; only rev C and newer chips handle it, and |
| 519 | * only Atmel sells these chips. | 520 | * only Atmel sells these chips. |
| 520 | */ | 521 | */ |
| 521 | tmp = spi_flash_cmd(spi, CMD_READ_ID, id, sizeof(id)); | 522 | tmp = spi_flash_cmd(spi, CMD_READ_ID, id, sizeof(id)); |
| 522 | if (tmp < 0) { | 523 | if (tmp < 0) { |
| 523 | printf("dataflash: error %d reading JEDEC ID\n", tmp); | 524 | printf("dataflash: error %d reading JEDEC ID\n", tmp); |
| 524 | return ERR_PTR(tmp); | 525 | return ERR_PTR(tmp); |
| 525 | } | 526 | } |
| 526 | if (id[0] != 0x1f) | 527 | if (id[0] != 0x1f) |
| 527 | return NULL; | 528 | return NULL; |
| 528 | 529 | ||
| 529 | jedec = id[0]; | 530 | jedec = id[0]; |
| 530 | jedec = jedec << 8; | 531 | jedec = jedec << 8; |
| 531 | jedec |= id[1]; | 532 | jedec |= id[1]; |
| 532 | jedec = jedec << 8; | 533 | jedec = jedec << 8; |
| 533 | jedec |= id[2]; | 534 | jedec |= id[2]; |
| 534 | 535 | ||
| 535 | for (tmp = 0, info = dataflash_data; | 536 | for (tmp = 0, info = dataflash_data; |
| 536 | tmp < ARRAY_SIZE(dataflash_data); | 537 | tmp < ARRAY_SIZE(dataflash_data); |
| 537 | tmp++, info++) { | 538 | tmp++, info++) { |
| 538 | if (info->jedec_id == jedec) { | 539 | if (info->jedec_id == jedec) { |
| 539 | if (info->flags & SUP_POW2PS) { | 540 | if (info->flags & SUP_POW2PS) { |
| 540 | status = dataflash_status(spi); | 541 | status = dataflash_status(spi); |
| 541 | if (status < 0) { | 542 | if (status < 0) { |
| 542 | debug("dataflash: status error %d\n", | 543 | debug("dataflash: status error %d\n", |
| 543 | status); | 544 | status); |
| 544 | return NULL; | 545 | return NULL; |
| 545 | } | 546 | } |
| 546 | if (status & 0x1) { | 547 | if (status & 0x1) { |
| 547 | if (info->flags & IS_POW2PS) | 548 | if (info->flags & IS_POW2PS) |
| 548 | return info; | 549 | return info; |
| 549 | } else { | 550 | } else { |
| 550 | if (!(info->flags & IS_POW2PS)) | 551 | if (!(info->flags & IS_POW2PS)) |
| 551 | return info; | 552 | return info; |
| 552 | } | 553 | } |
| 553 | } else { | 554 | } else { |
| 554 | return info; | 555 | return info; |
| 555 | } | 556 | } |
| 556 | } | 557 | } |
| 557 | } | 558 | } |
| 558 | 559 | ||
| 559 | /* | 560 | /* |
| 560 | * Treat other chips as errors ... we won't know the right page | 561 | * Treat other chips as errors ... we won't know the right page |
| 561 | * size (it might be binary) even when we can tell which density | 562 | * size (it might be binary) even when we can tell which density |
| 562 | * class is involved (legacy chip id scheme). | 563 | * class is involved (legacy chip id scheme). |
| 563 | */ | 564 | */ |
| 564 | printf("dataflash: JEDEC id %06x not handled\n", jedec); | 565 | printf("dataflash: JEDEC id %06x not handled\n", jedec); |
| 565 | return ERR_PTR(-ENODEV); | 566 | return ERR_PTR(-ENODEV); |
| 566 | } | 567 | } |
| 567 | 568 | ||
| 568 | /* | 569 | /* |
| 569 | * Detect and initialize DataFlash device, using JEDEC IDs on newer chips | 570 | * Detect and initialize DataFlash device, using JEDEC IDs on newer chips |
| 570 | * or else the ID code embedded in the status bits: | 571 | * or else the ID code embedded in the status bits: |
| 571 | * | 572 | * |
| 572 | * Device Density ID code #Pages PageSize Offset | 573 | * Device Density ID code #Pages PageSize Offset |
| 573 | * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 | 574 | * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 |
| 574 | * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 | 575 | * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 |
| 575 | * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 | 576 | * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 |
| 576 | * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 | 577 | * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 |
| 577 | * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 | 578 | * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 |
| 578 | * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 | 579 | * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 |
| 579 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 | 580 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 |
| 580 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 | 581 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 |
| 581 | */ | 582 | */ |
| 582 | static int spi_dataflash_probe(struct udevice *dev) | 583 | static int spi_dataflash_probe(struct udevice *dev) |
| 583 | { | 584 | { |
| 584 | struct spi_slave *spi = dev_get_parent_priv(dev); | 585 | struct spi_slave *spi = dev_get_parent_priv(dev); |
| 585 | struct spi_flash *spi_flash; | 586 | struct spi_flash *spi_flash; |
| 586 | struct flash_info *info; | 587 | struct data_flash_info *info; |
| 587 | int status; | 588 | int status; |
| 588 | 589 | ||
| 589 | spi_flash = dev_get_uclass_priv(dev); | 590 | spi_flash = dev_get_uclass_priv(dev); |
| 590 | spi_flash->spi = spi; | 591 | spi_flash->spi = spi; |
| 591 | spi_flash->dev = dev; | 592 | spi_flash->dev = dev; |
| 592 | 593 | ||
| 593 | status = spi_claim_bus(spi); | 594 | status = spi_claim_bus(spi); |
| 594 | if (status) | 595 | if (status) |
| 595 | return status; | 596 | return status; |
| 596 | 597 | ||
| 597 | /* | 598 | /* |
| 598 | * Try to detect dataflash by JEDEC ID. | 599 | * Try to detect dataflash by JEDEC ID. |
| 599 | * If it succeeds we know we have either a C or D part. | 600 | * If it succeeds we know we have either a C or D part. |
| 600 | * D will support power of 2 pagesize option. | 601 | * D will support power of 2 pagesize option. |
| 601 | * Both support the security register, though with different | 602 | * Both support the security register, though with different |
| 602 | * write procedures. | 603 | * write procedures. |
| 603 | */ | 604 | */ |
| 604 | info = jedec_probe(spi); | 605 | info = jedec_probe(spi); |
| 605 | if (IS_ERR(info)) | 606 | if (IS_ERR(info)) |
| 606 | goto err_jedec_probe; | 607 | goto err_jedec_probe; |
| 607 | if (info != NULL) { | 608 | if (info != NULL) { |
| 608 | status = add_dataflash(dev, info->name, info->nr_pages, | 609 | status = add_dataflash(dev, info->name, info->nr_pages, |
| 609 | info->pagesize, info->pageoffset, | 610 | info->pagesize, info->pageoffset, |
| 610 | (info->flags & SUP_POW2PS) ? 'd' : 'c'); | 611 | (info->flags & SUP_POW2PS) ? 'd' : 'c'); |
| 611 | if (status < 0) | 612 | if (status < 0) |
| 612 | goto err_status; | 613 | goto err_status; |
| 613 | } | 614 | } |
| 614 | 615 | ||
| 615 | /* | 616 | /* |
| 616 | * Older chips support only legacy commands, identifing | 617 | * Older chips support only legacy commands, identifing |
| 617 | * capacity using bits in the status byte. | 618 | * capacity using bits in the status byte. |
| 618 | */ | 619 | */ |
| 619 | status = dataflash_status(spi); | 620 | status = dataflash_status(spi); |
| 620 | if (status <= 0 || status == 0xff) { | 621 | if (status <= 0 || status == 0xff) { |
| 621 | printf("dataflash: read status error %d\n", status); | 622 | printf("dataflash: read status error %d\n", status); |
| 622 | if (status == 0 || status == 0xff) | 623 | if (status == 0 || status == 0xff) |
| 623 | status = -ENODEV; | 624 | status = -ENODEV; |
| 624 | goto err_jedec_probe; | 625 | goto err_jedec_probe; |
| 625 | } | 626 | } |
| 626 | 627 | ||
| 627 | /* | 628 | /* |
| 628 | * if there's a device there, assume it's dataflash. | 629 | * if there's a device there, assume it's dataflash. |
| 629 | * board setup should have set spi->max_speed_max to | 630 | * board setup should have set spi->max_speed_max to |
| 630 | * match f(car) for continuous reads, mode 0 or 3. | 631 | * match f(car) for continuous reads, mode 0 or 3. |
| 631 | */ | 632 | */ |
| 632 | switch (status & 0x3c) { | 633 | switch (status & 0x3c) { |
| 633 | case 0x0c: /* 0 0 1 1 x x */ | 634 | case 0x0c: /* 0 0 1 1 x x */ |
| 634 | status = add_dataflash(dev, "AT45DB011B", 512, 264, 9, 0); | 635 | status = add_dataflash(dev, "AT45DB011B", 512, 264, 9, 0); |
| 635 | break; | 636 | break; |
| 636 | case 0x14: /* 0 1 0 1 x x */ | 637 | case 0x14: /* 0 1 0 1 x x */ |
| 637 | status = add_dataflash(dev, "AT45DB021B", 1024, 264, 9, 0); | 638 | status = add_dataflash(dev, "AT45DB021B", 1024, 264, 9, 0); |
| 638 | break; | 639 | break; |
| 639 | case 0x1c: /* 0 1 1 1 x x */ | 640 | case 0x1c: /* 0 1 1 1 x x */ |
| 640 | status = add_dataflash(dev, "AT45DB041x", 2048, 264, 9, 0); | 641 | status = add_dataflash(dev, "AT45DB041x", 2048, 264, 9, 0); |
| 641 | break; | 642 | break; |
| 642 | case 0x24: /* 1 0 0 1 x x */ | 643 | case 0x24: /* 1 0 0 1 x x */ |
| 643 | status = add_dataflash(dev, "AT45DB081B", 4096, 264, 9, 0); | 644 | status = add_dataflash(dev, "AT45DB081B", 4096, 264, 9, 0); |
| 644 | break; | 645 | break; |
| 645 | case 0x2c: /* 1 0 1 1 x x */ | 646 | case 0x2c: /* 1 0 1 1 x x */ |
| 646 | status = add_dataflash(dev, "AT45DB161x", 4096, 528, 10, 0); | 647 | status = add_dataflash(dev, "AT45DB161x", 4096, 528, 10, 0); |
| 647 | break; | 648 | break; |
| 648 | case 0x34: /* 1 1 0 1 x x */ | 649 | case 0x34: /* 1 1 0 1 x x */ |
| 649 | status = add_dataflash(dev, "AT45DB321x", 8192, 528, 10, 0); | 650 | status = add_dataflash(dev, "AT45DB321x", 8192, 528, 10, 0); |
| 650 | break; | 651 | break; |
| 651 | case 0x38: /* 1 1 1 x x x */ | 652 | case 0x38: /* 1 1 1 x x x */ |
| 652 | case 0x3c: | 653 | case 0x3c: |
| 653 | status = add_dataflash(dev, "AT45DB642x", 8192, 1056, 11, 0); | 654 | status = add_dataflash(dev, "AT45DB642x", 8192, 1056, 11, 0); |
| 654 | break; | 655 | break; |
| 655 | /* obsolete AT45DB1282 not (yet?) supported */ | 656 | /* obsolete AT45DB1282 not (yet?) supported */ |
| 656 | default: | 657 | default: |
| 657 | printf("dataflash: unsupported device (%x)\n", status & 0x3c); | 658 | printf("dataflash: unsupported device (%x)\n", status & 0x3c); |
| 658 | status = -ENODEV; | 659 | status = -ENODEV; |
| 659 | goto err_status; | 660 | goto err_status; |
| 660 | } | 661 | } |
| 661 | 662 | ||
| 662 | return status; | 663 | return status; |
| 663 | 664 | ||
| 664 | err_status: | 665 | err_status: |
| 665 | spi_free_slave(spi); | 666 | spi_free_slave(spi); |
| 666 | err_jedec_probe: | 667 | err_jedec_probe: |
| 667 | spi_release_bus(spi); | 668 | spi_release_bus(spi); |
| 668 | return status; | 669 | return status; |
| 669 | } | 670 | } |
| 670 | 671 | ||
| 671 | static const struct dm_spi_flash_ops spi_dataflash_ops = { | 672 | static const struct dm_spi_flash_ops spi_dataflash_ops = { |
| 672 | .read = spi_dataflash_read, | 673 | .read = spi_dataflash_read, |
| 673 | .write = spi_dataflash_write, | 674 | .write = spi_dataflash_write, |
| 674 | .erase = spi_dataflash_erase, | 675 | .erase = spi_dataflash_erase, |
| 675 | }; | 676 | }; |
| 676 | 677 | ||
| 677 | static const struct udevice_id spi_dataflash_ids[] = { | 678 | static const struct udevice_id spi_dataflash_ids[] = { |
| 678 | { .compatible = "atmel,at45", }, | 679 | { .compatible = "atmel,at45", }, |
| 679 | { .compatible = "atmel,dataflash", }, | 680 | { .compatible = "atmel,dataflash", }, |
| 680 | { } | 681 | { } |
| 681 | }; | 682 | }; |
| 682 | 683 | ||
| 683 | U_BOOT_DRIVER(spi_dataflash) = { | 684 | U_BOOT_DRIVER(spi_dataflash) = { |
| 684 | .name = "spi_dataflash", | 685 | .name = "spi_dataflash", |
| 685 | .id = UCLASS_SPI_FLASH, | 686 | .id = UCLASS_SPI_FLASH, |
| 686 | .of_match = spi_dataflash_ids, | 687 | .of_match = spi_dataflash_ids, |
| 687 | .probe = spi_dataflash_probe, | 688 | .probe = spi_dataflash_probe, |
| 688 | .priv_auto_alloc_size = sizeof(struct dataflash), | 689 | .priv_auto_alloc_size = sizeof(struct dataflash), |
| 689 | .ops = &spi_dataflash_ops, | 690 | .ops = &spi_dataflash_ops, |
| 690 | }; | 691 | }; |
| 691 | 692 |
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | /* | 2 | /* |
| 3 | * SPI flash internal definitions | 3 | * SPI flash internal definitions |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2008 Atmel Corporation | 5 | * Copyright (C) 2008 Atmel Corporation |
| 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #ifndef _SF_INTERNAL_H_ | 9 | #ifndef _SF_INTERNAL_H_ |
| 10 | #define _SF_INTERNAL_H_ | 10 | #define _SF_INTERNAL_H_ |
| 11 | 11 | ||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
| 14 | 14 | ||
| 15 | /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ | 15 | #define SPI_NOR_MAX_ID_LEN 6 |
| 16 | enum spi_dual_flash { | 16 | #define SPI_NOR_MAX_ADDR_WIDTH 4 |
| 17 | SF_SINGLE_FLASH = 0, | ||
| 18 | SF_DUAL_STACKED_FLASH = BIT(0), | ||
| 19 | SF_DUAL_PARALLEL_FLASH = BIT(1), | ||
| 20 | }; | ||
| 21 | 17 | ||
| 22 | enum spi_nor_option_flags { | 18 | struct flash_info { |
| 23 | SNOR_F_SST_WR = BIT(0), | 19 | char *name; |
| 24 | SNOR_F_USE_FSR = BIT(1), | ||
| 25 | SNOR_F_USE_UPAGE = BIT(3), | ||
| 26 | }; | ||
| 27 | 20 | ||
| 28 | #define SPI_FLASH_3B_ADDR_LEN 3 | ||
| 29 | #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) | ||
| 30 | #define SPI_FLASH_16MB_BOUN 0x1000000 | ||
| 31 | |||
| 32 | /* CFI Manufacture ID's */ | ||
| 33 | #define SPI_FLASH_CFI_MFR_SPANSION 0x01 | ||
| 34 | #define SPI_FLASH_CFI_MFR_STMICRO 0x20 | ||
| 35 | #define SPI_FLASH_CFI_MFR_MICRON 0x2C | ||
| 36 | #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 | ||
| 37 | #define SPI_FLASH_CFI_MFR_SST 0xbf | ||
| 38 | #define SPI_FLASH_CFI_MFR_WINBOND 0xef | ||
| 39 | #define SPI_FLASH_CFI_MFR_ATMEL 0x1f | ||
| 40 | |||
| 41 | /* Erase commands */ | ||
| 42 | #define CMD_ERASE_4K 0x20 | ||
| 43 | #define CMD_ERASE_CHIP 0xc7 | ||
| 44 | #define CMD_ERASE_64K 0xd8 | ||
| 45 | |||
| 46 | /* Write commands */ | ||
| 47 | #define CMD_WRITE_STATUS 0x01 | ||
| 48 | #define CMD_PAGE_PROGRAM 0x02 | ||
| 49 | #define CMD_WRITE_DISABLE 0x04 | ||
| 50 | #define CMD_WRITE_ENABLE 0x06 | ||
| 51 | #define CMD_QUAD_PAGE_PROGRAM 0x32 | ||
| 52 | |||
| 53 | /* Read commands */ | ||
| 54 | #define CMD_READ_ARRAY_SLOW 0x03 | ||
| 55 | #define CMD_READ_ARRAY_FAST 0x0b | ||
| 56 | #define CMD_READ_DUAL_OUTPUT_FAST 0x3b | ||
| 57 | #define CMD_READ_DUAL_IO_FAST 0xbb | ||
| 58 | #define CMD_READ_QUAD_OUTPUT_FAST 0x6b | ||
| 59 | #define CMD_READ_QUAD_IO_FAST 0xeb | ||
| 60 | #define CMD_READ_ID 0x9f | ||
| 61 | #define CMD_READ_STATUS 0x05 | ||
| 62 | #define CMD_READ_STATUS1 0x35 | ||
| 63 | #define CMD_READ_CONFIG 0x35 | ||
| 64 | #define CMD_FLAG_STATUS 0x70 | ||
| 65 | |||
| 66 | /* Bank addr access commands */ | ||
| 67 | #ifdef CONFIG_SPI_FLASH_BAR | ||
| 68 | # define CMD_BANKADDR_BRWR 0x17 | ||
| 69 | # define CMD_BANKADDR_BRRD 0x16 | ||
| 70 | # define CMD_EXTNADDR_WREAR 0xC5 | ||
| 71 | # define CMD_EXTNADDR_RDEAR 0xC8 | ||
| 72 | #endif | ||
| 73 | |||
| 74 | /* Common status */ | ||
| 75 | #define STATUS_WIP BIT(0) | ||
| 76 | #define STATUS_QEB_WINSPAN BIT(1) | ||
| 77 | #define STATUS_QEB_MXIC BIT(6) | ||
| 78 | #define STATUS_PEC BIT(7) | ||
| 79 | #define SR_BP0 BIT(2) /* Block protect 0 */ | ||
| 80 | #define SR_BP1 BIT(3) /* Block protect 1 */ | ||
| 81 | #define SR_BP2 BIT(4) /* Block protect 2 */ | ||
| 82 | |||
| 83 | /* Flash timeout values */ | ||
| 84 | #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) | ||
| 85 | #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) | ||
| 86 | #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) | ||
| 87 | |||
| 88 | /* SST specific */ | ||
| 89 | #ifdef CONFIG_SPI_FLASH_SST | ||
| 90 | #define SST26_CMD_READ_BPR 0x72 | ||
| 91 | #define SST26_CMD_WRITE_BPR 0x42 | ||
| 92 | |||
| 93 | #define SST26_BPR_8K_NUM 4 | ||
| 94 | #define SST26_MAX_BPR_REG_LEN (18 + 1) | ||
| 95 | #define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) | ||
| 96 | |||
| 97 | enum lock_ctl { | ||
| 98 | SST26_CTL_LOCK, | ||
| 99 | SST26_CTL_UNLOCK, | ||
| 100 | SST26_CTL_CHECK | ||
| 101 | }; | ||
| 102 | |||
| 103 | # define CMD_SST_BP 0x02 /* Byte Program */ | ||
| 104 | # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ | ||
| 105 | |||
| 106 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | ||
| 107 | const void *buf); | ||
| 108 | int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, | ||
| 109 | const void *buf); | ||
| 110 | #endif | ||
| 111 | |||
| 112 | #define JEDEC_MFR(info) ((info)->id[0]) | ||
| 113 | #define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) | ||
| 114 | #define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) | ||
| 115 | #define SPI_FLASH_MAX_ID_LEN 6 | ||
| 116 | |||
| 117 | struct spi_flash_info { | ||
| 118 | /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ | ||
| 119 | const char *name; | ||
| 120 | |||
| 121 | /* | 21 | /* |
| 122 | * This array stores the ID bytes. | 22 | * This array stores the ID bytes. |
| 123 | * The first three bytes are the JEDIC ID. | 23 | * The first three bytes are the JEDIC ID. |
| 124 | * JEDEC ID zero means "no ID" (mostly older chips). | 24 | * JEDEC ID zero means "no ID" (mostly older chips). |
| 125 | */ | 25 | */ |
| 126 | u8 id[SPI_FLASH_MAX_ID_LEN]; | 26 | u8 id[SPI_NOR_MAX_ID_LEN]; |
| 127 | u8 id_len; | 27 | u8 id_len; |
| 128 | 28 | ||
| 129 | /* | 29 | /* The size listed here is what works with SPINOR_OP_SE, which isn't |
| 130 | * The size listed here is what works with SPINOR_OP_SE, which isn't | ||
| 131 | * necessarily called a "sector" by the vendor. | 30 | * necessarily called a "sector" by the vendor. |
| 132 | */ | 31 | */ |
| 133 | u32 sector_size; | 32 | unsigned int sector_size; |
| 134 | u32 n_sectors; | 33 | u16 n_sectors; |
| 135 | 34 | ||
| 136 | u16 page_size; | 35 | u16 page_size; |
| 36 | u16 addr_width; | ||
| 137 | 37 | ||
| 138 | u16 flags; | 38 | u16 flags; |
| 139 | #define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */ | 39 | #define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ |
| 140 | #define E_FSR BIT(1) /* use flag status register for */ | 40 | #define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ |
| 141 | #define SST_WR BIT(2) /* use SST byte/word programming */ | 41 | #define SST_WRITE BIT(2) /* use SST byte programming */ |
| 142 | #define WR_QPP BIT(3) /* use Quad Page Program */ | 42 | #define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ |
| 143 | #define RD_QUAD BIT(4) /* use Quad Read */ | 43 | #define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ |
| 144 | #define RD_DUAL BIT(5) /* use Dual Read */ | 44 | #define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ |
| 145 | #define RD_QUADIO BIT(6) /* use Quad IO Read */ | 45 | #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ |
| 146 | #define RD_DUALIO BIT(7) /* use Dual IO Read */ | 46 | #define USE_FSR BIT(7) /* use flag status register */ |
| 147 | #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) | 47 | #define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ |
| 48 | #define SPI_NOR_HAS_TB BIT(9) /* | ||
| 49 | * Flash SR has Top/Bottom (TB) protect | ||
| 50 | * bit. Must be used with | ||
| 51 | * SPI_NOR_HAS_LOCK. | ||
| 52 | */ | ||
| 53 | #define SPI_S3AN BIT(10) /* | ||
| 54 | * Xilinx Spartan 3AN In-System Flash | ||
| 55 | * (MFR cannot be used for probing | ||
| 56 | * because it has the same value as | ||
| 57 | * ATMEL flashes) | ||
| 58 | */ | ||
| 59 | #define SPI_NOR_4B_OPCODES BIT(11) /* | ||
| 60 | * Use dedicated 4byte address op codes | ||
| 61 | * to support memory size above 128Mib. | ||
| 62 | */ | ||
| 63 | #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ | ||
| 64 | #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ | ||
| 65 | #define USE_CLSR BIT(14) /* use CLSR command */ | ||
| 148 | }; | 66 | }; |
| 149 | 67 | ||
| 150 | extern const struct spi_flash_info spi_flash_ids[]; | 68 | extern const struct flash_info spi_nor_ids[]; |
| 151 | 69 | ||
| 70 | #define JEDEC_MFR(info) ((info)->id[0]) | ||
| 71 | #define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) | ||
| 72 | |||
| 152 | /* Send a single-byte command to the device and read the response */ | 73 | /* Send a single-byte command to the device and read the response */ |
| 153 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); | 74 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); |
| 154 | 75 | ||
| 155 | /* | 76 | /* |
| 156 | * Send a multi-byte command to the device and read the response. Used | 77 | * Send a multi-byte command to the device and read the response. Used |
| 157 | * for flash array reads, etc. | 78 | * for flash array reads, etc. |
| 158 | */ | 79 | */ |
| 159 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, | 80 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, |
| 160 | size_t cmd_len, void *data, size_t data_len); | 81 | size_t cmd_len, void *data, size_t data_len); |
| 161 | 82 | ||
| 162 | /* | 83 | /* |
| 163 | * Send a multi-byte command to the device followed by (optional) | 84 | * Send a multi-byte command to the device followed by (optional) |
| 164 | * data. Used for programming the flash array, etc. | 85 | * data. Used for programming the flash array, etc. |
| 165 | */ | 86 | */ |
| 166 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, | 87 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, |
| 167 | const void *data, size_t data_len); | 88 | const void *data, size_t data_len); |
| 168 | 89 | ||
| 169 | 90 | ||
| 170 | /* Flash erase(sectors) operation, support all possible erase commands */ | ||
| 171 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); | ||
| 172 | |||
| 173 | /* Get software write-protect value (BP bits) */ | 91 | /* Get software write-protect value (BP bits) */ |
| 174 | int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); | 92 | int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); |
| 175 | 93 | ||
| 176 | /* Lock stmicro spi flash region */ | ||
| 177 | int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 178 | 94 | ||
| 179 | /* Unlock stmicro spi flash region */ | ||
| 180 | int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 181 | |||
| 182 | /* Check if a stmicro spi flash region is completely locked */ | ||
| 183 | int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 184 | |||
| 185 | /* Enable writing on the SPI flash */ | ||
| 186 | static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) | ||
| 187 | { | ||
| 188 | return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); | ||
| 189 | } | ||
| 190 | |||
| 191 | /* Disable writing on the SPI flash */ | ||
| 192 | static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) | ||
| 193 | { | ||
| 194 | return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* | ||
| 198 | * Used for spi_flash write operation | ||
| 199 | * - SPI claim | ||
| 200 | * - spi_flash_cmd_write_enable | ||
| 201 | * - spi_flash_cmd_write | ||
| 202 | * - spi_flash_wait_till_ready | ||
| 203 | * - SPI release | ||
| 204 | */ | ||
| 205 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | ||
| 206 | size_t cmd_len, const void *buf, size_t buf_len); | ||
| 207 | |||
| 208 | /* | ||
| 209 | * Flash write operation, support all possible write commands. | ||
| 210 | * Write the requested data out breaking it up into multiple write | ||
| 211 | * commands as needed per the write size. | ||
| 212 | */ | ||
| 213 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | ||
| 214 | size_t len, const void *buf); | ||
| 215 | |||
| 216 | /* | ||
| 217 | * Same as spi_flash_cmd_read() except it also claims/releases the SPI | ||
| 218 | * bus. Used as common part of the ->read() operation. | ||
| 219 | */ | ||
| 220 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | ||
| 221 | size_t cmd_len, void *data, size_t data_len); | ||
| 222 | |||
| 223 | /* Flash read operation, support all possible read commands */ |
| 1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* | 2 | /* |
| 3 | * SPI flash probing | 3 | * SPI flash probing |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2008 Atmel Corporation | 5 | * Copyright (C) 2008 Atmel Corporation |
| 6 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik | 6 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik |
| 7 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 7 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <common.h> | 10 | #include <common.h> |
| 11 | #include <dm.h> | 11 | #include <dm.h> |
| 12 | #include <errno.h> | 12 | #include <errno.h> |
| 13 | #include <malloc.h> | 13 | #include <malloc.h> |
| 14 | #include <spi.h> | 14 | #include <spi.h> |
| 15 | #include <spi_flash.h> | 15 | #include <spi_flash.h> |
| 16 | 16 | ||
| 17 | #include "sf_internal.h" | 17 | #include "sf_internal.h" |
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | * spi_flash_probe_slave() - Probe for a SPI flash device on a bus | 20 | * spi_flash_probe_slave() - Probe for a SPI flash device on a bus |
| 21 | * | 21 | * |
| 22 | * @flashp: Pointer to place to put flash info, which may be NULL if the | 22 | * @flashp: Pointer to place to put flash info, which may be NULL if the |
| 23 | * space should be allocated | 23 | * space should be allocated |
| 24 | */ | 24 | */ |
| 25 | static int spi_flash_probe_slave(struct spi_flash *flash) | 25 | static int spi_flash_probe_slave(struct spi_flash *flash) |
| 26 | { | 26 | { |
| 27 | struct spi_slave *spi = flash->spi; | 27 | struct spi_slave *spi = flash->spi; |
| 28 | int ret; | 28 | int ret; |
| 29 | 29 | ||
| 30 | /* Setup spi_slave */ | 30 | /* Setup spi_slave */ |
| 31 | if (!spi) { | 31 | if (!spi) { |
| 32 | printf("SF: Failed to set up slave\n"); | 32 | printf("SF: Failed to set up slave\n"); |
| 33 | return -ENODEV; | 33 | return -ENODEV; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | /* Claim spi bus */ | 36 | /* Claim spi bus */ |
| 37 | ret = spi_claim_bus(spi); | 37 | ret = spi_claim_bus(spi); |
| 38 | if (ret) { | 38 | if (ret) { |
| 39 | debug("SF: Failed to claim SPI bus: %d\n", ret); | 39 | debug("SF: Failed to claim SPI bus: %d\n", ret); |
| 40 | return ret; | 40 | return ret; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | ret = spi_flash_scan(flash); | 43 | ret = spi_nor_scan(flash); |
| 44 | if (ret) | 44 | if (ret) |
| 45 | goto err_read_id; | 45 | goto err_read_id; |
| 46 | 46 | ||
| 47 | #ifdef CONFIG_SPI_FLASH_MTD | 47 | #ifdef CONFIG_SPI_FLASH_MTD |
| 48 | ret = spi_flash_mtd_register(flash); | 48 | ret = spi_flash_mtd_register(flash); |
| 49 | #endif | 49 | #endif |
| 50 | 50 | ||
| 51 | err_read_id: | 51 | err_read_id: |
| 52 | spi_release_bus(spi); | 52 | spi_release_bus(spi); |
| 53 | return ret; | 53 | return ret; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | #ifndef CONFIG_DM_SPI_FLASH | 56 | #ifndef CONFIG_DM_SPI_FLASH |
| 57 | struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, | 57 | struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, |
| 58 | unsigned int max_hz, unsigned int spi_mode) | 58 | unsigned int max_hz, unsigned int spi_mode) |
| 59 | { | 59 | { |
| 60 | struct spi_slave *bus; | 60 | struct spi_slave *bus; |
| 61 | struct spi_flash *flash; | 61 | struct spi_flash *flash; |
| 62 | 62 | ||
| 63 | bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); | 63 | bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); |
| 64 | if (!bus) | 64 | if (!bus) |
| 65 | return NULL; | 65 | return NULL; |
| 66 | 66 | ||
| 67 | /* Allocate space if needed (not used by sf-uclass */ | 67 | /* Allocate space if needed (not used by sf-uclass */ |
| 68 | flash = calloc(1, sizeof(*flash)); | 68 | flash = calloc(1, sizeof(*flash)); |
| 69 | if (!flash) { | 69 | if (!flash) { |
| 70 | debug("SF: Failed to allocate spi_flash\n"); | 70 | debug("SF: Failed to allocate spi_flash\n"); |
| 71 | return NULL; | 71 | return NULL; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | flash->spi = bus; | 74 | flash->spi = bus; |
| 75 | if (spi_flash_probe_slave(flash)) { | 75 | if (spi_flash_probe_slave(flash)) { |
| 76 | spi_free_slave(bus); | 76 | spi_free_slave(bus); |
| 77 | free(flash); | 77 | free(flash); |
| 78 | return NULL; | 78 | return NULL; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | return flash; | 81 | return flash; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | void spi_flash_free(struct spi_flash *flash) | 84 | void spi_flash_free(struct spi_flash *flash) |
| 85 | { | 85 | { |
| 86 | #ifdef CONFIG_SPI_FLASH_MTD | 86 | #ifdef CONFIG_SPI_FLASH_MTD |
| 87 | spi_flash_mtd_unregister(); | 87 | spi_flash_mtd_unregister(); |
| 88 | #endif | 88 | #endif |
| 89 | spi_free_slave(flash->spi); | 89 | spi_free_slave(flash->spi); |
| 90 | free(flash); | 90 | free(flash); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | #else /* defined CONFIG_DM_SPI_FLASH */ | 93 | #else /* defined CONFIG_DM_SPI_FLASH */ |
| 94 | 94 | ||
| 95 | static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, | 95 | static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, |
| 96 | void *buf) | 96 | void *buf) |
| 97 | { | 97 | { |
| 98 | struct spi_flash *flash = dev_get_uclass_priv(dev); | 98 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
| 99 | struct mtd_info *mtd = &flash->mtd; | ||
| 100 | size_t retlen; | ||
| 99 | 101 | ||
| 100 | return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); | 102 | return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, | 105 | static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, |
| 104 | const void *buf) | 106 | const void *buf) |
| 105 | { | 107 | { |
| 106 | struct spi_flash *flash = dev_get_uclass_priv(dev); | 108 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
| 109 | struct mtd_info *mtd = &flash->mtd; | ||
| 110 | size_t retlen; | ||
| 107 | 111 | ||
| 108 | #if defined(CONFIG_SPI_FLASH_SST) | 112 | return mtd->_write(mtd, offset, len, &retlen, buf); |
| 109 | if (flash->flags & SNOR_F_SST_WR) { | ||
| 110 | if (flash->spi->mode & SPI_TX_BYTE) | ||
| 111 | return sst_write_bp(flash, offset, len, buf); | ||
| 112 | else | ||
| 113 | return sst_write_wp(flash, offset, len, buf); | ||
| 114 | } | ||
| 115 | #endif | ||
| 116 | |||
| 117 | return spi_flash_cmd_write_ops(flash, offset, len, buf); | ||
| 118 | } | 113 | } |
| 119 | 114 | ||
| 120 | static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) | 115 | static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) |
| 121 | { | 116 | { |
| 122 | struct spi_flash *flash = dev_get_uclass_priv(dev); | 117 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
| 118 | struct mtd_info *mtd = &flash->mtd; | ||
| 119 | struct erase_info instr; | ||
| 123 | 120 | ||
| 124 | return spi_flash_cmd_erase_ops(flash, offset, len); | 121 | if (offset % mtd->erasesize || len % mtd->erasesize) { |
| 122 | printf("SF: Erase offset/length not multiple of erase size\n"); | ||
| 123 | return -EINVAL; | ||
| 124 | } | ||
| 125 | |||
| 126 | memset(&instr, 0, sizeof(instr)); | ||
| 127 | instr.addr = offset; | ||
| 128 | instr.len = len; | ||
| 129 | |||
| 130 | return mtd->_erase(mtd, &instr); | ||
| 125 | } | 131 | } |
| 126 | 132 | ||
| 127 | static int spi_flash_std_get_sw_write_prot(struct udevice *dev) | 133 | static int spi_flash_std_get_sw_write_prot(struct udevice *dev) |
| 128 | { | 134 | { |
| 129 | struct spi_flash *flash = dev_get_uclass_priv(dev); | 135 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
| 130 | 136 | ||
| 131 | return spi_flash_cmd_get_sw_write_prot(flash); | 137 | return spi_flash_cmd_get_sw_write_prot(flash); |
| 132 | } | 138 | } |
| 133 | 139 | ||
| 134 | static int spi_flash_std_probe(struct udevice *dev) | 140 | static int spi_flash_std_probe(struct udevice *dev) |
| 135 | { | 141 | { |
| 136 | struct spi_slave *slave = dev_get_parent_priv(dev); | 142 | struct spi_slave *slave = dev_get_parent_priv(dev); |
| 137 | struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); | 143 | struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); |
| 138 | struct spi_flash *flash; | 144 | struct spi_flash *flash; |
| 139 | 145 | ||
| 140 | flash = dev_get_uclass_priv(dev); | 146 | flash = dev_get_uclass_priv(dev); |
| 141 | flash->dev = dev; | 147 | flash->dev = dev; |
| 142 | flash->spi = slave; | 148 | flash->spi = slave; |
| 143 | debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); | 149 | debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); |
| 144 | return spi_flash_probe_slave(flash); | 150 | return spi_flash_probe_slave(flash); |
| 145 | } | 151 | } |
| 146 | 152 | ||
| 147 | static int spi_flash_std_remove(struct udevice *dev) | 153 | static int spi_flash_std_remove(struct udevice *dev) |
| 148 | { | 154 | { |
| 149 | #ifdef CONFIG_SPI_FLASH_MTD | 155 | #ifdef CONFIG_SPI_FLASH_MTD |
| 150 | spi_flash_mtd_unregister(); | 156 | spi_flash_mtd_unregister(); |
| 151 | #endif | 157 | #endif |
| 152 | return 0; | 158 | return 0; |
| 153 | } | 159 | } |
| 154 | 160 | ||
| 155 | static const struct dm_spi_flash_ops spi_flash_std_ops = { | 161 | static const struct dm_spi_flash_ops spi_flash_std_ops = { |
| 156 | .read = spi_flash_std_read, | 162 | .read = spi_flash_std_read, |
| 157 | .write = spi_flash_std_write, | 163 | .write = spi_flash_std_write, |
| 158 | .erase = spi_flash_std_erase, | 164 | .erase = spi_flash_std_erase, |
| 159 | .get_sw_write_prot = spi_flash_std_get_sw_write_prot, | 165 | .get_sw_write_prot = spi_flash_std_get_sw_write_prot, |
| 160 | }; | 166 | }; |
| 161 | 167 | ||
| 162 | static const struct udevice_id spi_flash_std_ids[] = { | 168 | static const struct udevice_id spi_flash_std_ids[] = { |
| 163 | { .compatible = "spi-flash" }, | 169 | { .compatible = "spi-flash" }, |
| 164 | { .compatible = "jedec,spi-nor" }, | 170 | { .compatible = "jedec,spi-nor" }, |
| 165 | { } | 171 | { } |
| 166 | }; | 172 | }; |
| 167 | 173 | ||
| 168 | U_BOOT_DRIVER(spi_flash_std) = { | 174 | U_BOOT_DRIVER(spi_flash_std) = { |
| 169 | .name = "spi_flash_std", | 175 | .name = "spi_flash_std", |
| 170 | .id = UCLASS_SPI_FLASH, | 176 | .id = UCLASS_SPI_FLASH, |
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* | 2 | /* |
| 3 | * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with | 3 | * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with |
| 4 | * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c | 4 | * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2005, Intec Automation Inc. | 6 | * Copyright (C) 2005, Intec Automation Inc. |
| 7 | * Copyright (C) 2014, Freescale Semiconductor, Inc. | 7 | * Copyright (C) 2014, Freescale Semiconductor, Inc. |
| 8 | * | 8 | * |
| 9 | * Synced from Linux v4.19 | 9 | * Synced from Linux v4.19 |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <common.h> | 12 | #include <common.h> |
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
| 16 | #include <linux/math64.h> | 16 | #include <linux/math64.h> |
| 17 | #include <linux/sizes.h> | 17 | #include <linux/sizes.h> |
| 18 | 18 | ||
| 19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
| 20 | #include <linux/mtd/spi-nor.h> | 20 | #include <linux/mtd/spi-nor.h> |
| 21 | #include <spi-mem.h> | 21 | #include <spi-mem.h> |
| 22 | #include <spi.h> | 22 | #include <spi.h> |
| 23 | 23 | ||
| 24 | #include "sf_internal.h" | ||
| 25 | |||
| 24 | /* Define max times to check status register before we give up. */ | 26 | /* Define max times to check status register before we give up. */ |
| 25 | 27 | ||
| 26 | /* | 28 | /* |
| 27 | * For everything but full-chip erase; probably could be much smaller, but kept | 29 | * For everything but full-chip erase; probably could be much smaller, but kept |
| 28 | * around for safety for now | 30 | * around for safety for now |
| 29 | */ | 31 | */ |
| 30 | 32 | ||
| 31 | #define HZ CONFIG_SYS_HZ | 33 | #define HZ CONFIG_SYS_HZ |
| 32 | 34 | ||
| 33 | #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) | 35 | #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) |
| 34 | |||
| 35 | #define SPI_NOR_MAX_ID_LEN 6 | ||
| 36 | #define SPI_NOR_MAX_ADDR_WIDTH 4 | ||
| 37 | |||
| 38 | struct flash_info { | ||
| 39 | char *name; | ||
| 40 | |||
| 41 | /* | ||
| 42 | * This array stores the ID bytes. | ||
| 43 | * The first three bytes are the JEDIC ID. | ||
| 44 | * JEDEC ID zero means "no ID" (mostly older chips). | ||
| 45 | */ | ||
| 46 | u8 id[SPI_NOR_MAX_ID_LEN]; | ||
| 47 | u8 id_len; | ||
| 48 | |||
| 49 | /* The size listed here is what works with SPINOR_OP_SE, which isn't | ||
| 50 | * necessarily called a "sector" by the vendor. | ||
| 51 | */ | ||
| 52 | unsigned int sector_size; | ||
| 53 | u16 n_sectors; | ||
| 54 | |||
| 55 | u16 page_size; | ||
| 56 | u16 addr_width; | ||
| 57 | |||
| 58 | u16 flags; | ||
| 59 | #define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ | ||
| 60 | #define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ | ||
| 61 | #define SST_WRITE BIT(2) /* use SST byte programming */ | ||
| 62 | #define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ | ||
| 63 | #define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ | ||
| 64 | #define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ | ||
| 65 | #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ | ||
| 66 | #define USE_FSR BIT(7) /* use flag status register */ | ||
| 67 | #define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ | ||
| 68 | #define SPI_NOR_HAS_TB BIT(9) /* | ||
| 69 | * Flash SR has Top/Bottom (TB) protect | ||
| 70 | * bit. Must be used with | ||
| 71 | * SPI_NOR_HAS_LOCK. | ||
| 72 | */ | ||
| 73 | #define SPI_S3AN BIT(10) /* | ||
| 74 | * Xilinx Spartan 3AN In-System Flash | ||
| 75 | * (MFR cannot be used for probing | ||
| 76 | * because it has the same value as | ||
| 77 | * ATMEL flashes) | ||
| 78 | */ | ||
| 79 | #define SPI_NOR_4B_OPCODES BIT(11) /* | ||
| 80 | * Use dedicated 4byte address op codes | ||
| 81 | * to support memory size above 128Mib. | ||
| 82 | */ | ||
| 83 | #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ | ||
| 84 | #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ | ||
| 85 | #define USE_CLSR BIT(14) /* use CLSR command */ | ||
| 86 | |||
| 87 | int (*quad_enable)(struct spi_nor *nor); | ||
| 88 | }; | ||
| 89 | |||
| 90 | #define JEDEC_MFR(info) ((info)->id[0]) | ||
| 91 | 36 | ||
| 92 | static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op | 37 | static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op |
| 93 | *op, void *buf) | 38 | *op, void *buf) |
| 94 | { | 39 | { |
| 95 | if (op->data.dir == SPI_MEM_DATA_IN) | 40 | if (op->data.dir == SPI_MEM_DATA_IN) |
| 96 | op->data.buf.in = buf; | 41 | op->data.buf.in = buf; |
| 97 | else | 42 | else |
| 98 | op->data.buf.out = buf; | 43 | op->data.buf.out = buf; |
| 99 | return spi_mem_exec_op(nor->spi, op); | 44 | return spi_mem_exec_op(nor->spi, op); |
| 100 | } | 45 | } |
| 101 | 46 | ||
| 102 | static int spi_nor_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) | 47 | static int spi_nor_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) |
| 103 | { | 48 | { |
| 104 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), | 49 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), |
| 105 | SPI_MEM_OP_NO_ADDR, | 50 | SPI_MEM_OP_NO_ADDR, |
| 106 | SPI_MEM_OP_NO_DUMMY, | 51 | SPI_MEM_OP_NO_DUMMY, |
| 107 | SPI_MEM_OP_DATA_IN(len, NULL, 1)); | 52 | SPI_MEM_OP_DATA_IN(len, NULL, 1)); |
| 108 | int ret; | 53 | int ret; |
| 109 | 54 | ||
| 110 | ret = spi_nor_read_write_reg(nor, &op, val); | 55 | ret = spi_nor_read_write_reg(nor, &op, val); |
| 111 | if (ret < 0) | 56 | if (ret < 0) |
| 112 | dev_dbg(&flash->spimem->spi->dev, "error %d reading %x\n", ret, | 57 | dev_dbg(&flash->spimem->spi->dev, "error %d reading %x\n", ret, |
| 113 | code); | 58 | code); |
| 114 | 59 | ||
| 115 | return ret; | 60 | return ret; |
| 116 | } | 61 | } |
| 117 | 62 | ||
| 118 | static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) | 63 | static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) |
| 119 | { | 64 | { |
| 120 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), | 65 | struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), |
| 121 | SPI_MEM_OP_NO_ADDR, | 66 | SPI_MEM_OP_NO_ADDR, |
| 122 | SPI_MEM_OP_NO_DUMMY, | 67 | SPI_MEM_OP_NO_DUMMY, |
| 123 | SPI_MEM_OP_DATA_OUT(len, NULL, 1)); | 68 | SPI_MEM_OP_DATA_OUT(len, NULL, 1)); |
| 124 | 69 | ||
| 125 | return spi_nor_read_write_reg(nor, &op, buf); | 70 | return spi_nor_read_write_reg(nor, &op, buf); |
| 126 | } | 71 | } |
| 127 | 72 | ||
| 128 | static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, | 73 | static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, |
| 129 | u_char *buf) | 74 | u_char *buf) |
| 130 | { | 75 | { |
| 131 | struct spi_mem_op op = | 76 | struct spi_mem_op op = |
| 132 | SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), | 77 | SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), |
| 133 | SPI_MEM_OP_ADDR(nor->addr_width, from, 1), | 78 | SPI_MEM_OP_ADDR(nor->addr_width, from, 1), |
| 134 | SPI_MEM_OP_DUMMY(nor->read_dummy, 1), | 79 | SPI_MEM_OP_DUMMY(nor->read_dummy, 1), |
| 135 | SPI_MEM_OP_DATA_IN(len, buf, 1)); | 80 | SPI_MEM_OP_DATA_IN(len, buf, 1)); |
| 136 | size_t remaining = len; | 81 | size_t remaining = len; |
| 137 | int ret; | 82 | int ret; |
| 138 | 83 | ||
| 139 | /* get transfer protocols. */ | 84 | /* get transfer protocols. */ |
| 140 | op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); | 85 | op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); |
| 141 | op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); | 86 | op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); |
| 142 | op.dummy.buswidth = op.addr.buswidth; | 87 | op.dummy.buswidth = op.addr.buswidth; |
| 143 | op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); | 88 | op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); |
| 144 | 89 | ||
| 145 | /* convert the dummy cycles to the number of bytes */ | 90 | /* convert the dummy cycles to the number of bytes */ |
| 146 | op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; | 91 | op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; |
| 147 | 92 | ||
| 148 | while (remaining) { | 93 | while (remaining) { |
| 149 | op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; | 94 | op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; |
| 150 | ret = spi_mem_adjust_op_size(nor->spi, &op); | 95 | ret = spi_mem_adjust_op_size(nor->spi, &op); |
| 151 | if (ret) | 96 | if (ret) |
| 152 | return ret; | 97 | return ret; |
| 153 | 98 | ||
| 154 | ret = spi_mem_exec_op(nor->spi, &op); | 99 | ret = spi_mem_exec_op(nor->spi, &op); |
| 155 | if (ret) | 100 | if (ret) |
| 156 | return ret; | 101 | return ret; |
| 157 | 102 | ||
| 158 | op.addr.val += op.data.nbytes; | 103 | op.addr.val += op.data.nbytes; |
| 159 | remaining -= op.data.nbytes; | 104 | remaining -= op.data.nbytes; |
| 160 | op.data.buf.in += op.data.nbytes; | 105 | op.data.buf.in += op.data.nbytes; |
| 161 | } | 106 | } |
| 162 | 107 | ||
| 163 | return len; | 108 | return len; |
| 164 | } | 109 | } |
| 165 | 110 | ||
| 166 | static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, | 111 | static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, |
| 167 | const u_char *buf) | 112 | const u_char *buf) |
| 168 | { | 113 | { |
| 169 | struct spi_mem_op op = | 114 | struct spi_mem_op op = |
| 170 | SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), | 115 | SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), |
| 171 | SPI_MEM_OP_ADDR(nor->addr_width, to, 1), | 116 | SPI_MEM_OP_ADDR(nor->addr_width, to, 1), |
| 172 | SPI_MEM_OP_NO_DUMMY, | 117 | SPI_MEM_OP_NO_DUMMY, |
| 173 | SPI_MEM_OP_DATA_OUT(len, buf, 1)); | 118 | SPI_MEM_OP_DATA_OUT(len, buf, 1)); |
| 174 | size_t remaining = len; | 119 | size_t remaining = len; |
| 175 | int ret; | 120 | int ret; |
| 176 | 121 | ||
| 177 | /* get transfer protocols. */ | 122 | /* get transfer protocols. */ |
| 178 | op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); | 123 | op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); |
| 179 | op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); | 124 | op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); |
| 180 | op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); | 125 | op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); |
| 181 | 126 | ||
| 182 | if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) | 127 | if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) |
| 183 | op.addr.nbytes = 0; | 128 | op.addr.nbytes = 0; |
| 184 | 129 | ||
| 185 | while (remaining) { | 130 | while (remaining) { |
| 186 | op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; | 131 | op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; |
| 187 | ret = spi_mem_adjust_op_size(nor->spi, &op); | 132 | ret = spi_mem_adjust_op_size(nor->spi, &op); |
| 188 | if (ret) | 133 | if (ret) |
| 189 | return ret; | 134 | return ret; |
| 190 | 135 | ||
| 191 | ret = spi_mem_exec_op(nor->spi, &op); | 136 | ret = spi_mem_exec_op(nor->spi, &op); |
| 192 | if (ret) | 137 | if (ret) |
| 193 | return ret; | 138 | return ret; |
| 194 | 139 | ||
| 195 | op.addr.val += op.data.nbytes; | 140 | op.addr.val += op.data.nbytes; |
| 196 | remaining -= op.data.nbytes; | 141 | remaining -= op.data.nbytes; |
| 197 | op.data.buf.out += op.data.nbytes; | 142 | op.data.buf.out += op.data.nbytes; |
| 198 | } | 143 | } |
| 199 | 144 | ||
| 200 | return len; | 145 | return len; |
| 201 | } | 146 | } |
| 202 | 147 | ||
| 203 | /* | 148 | /* |
| 204 | * Read the status register, returning its value in the location | 149 | * Read the status register, returning its value in the location |
| 205 | * Return the status register value. | 150 | * Return the status register value. |
| 206 | * Returns negative if error occurred. | 151 | * Returns negative if error occurred. |
| 207 | */ | 152 | */ |
| 208 | static int read_sr(struct spi_nor *nor) | 153 | static int read_sr(struct spi_nor *nor) |
| 209 | { | 154 | { |
| 210 | int ret; | 155 | int ret; |
| 211 | u8 val; | 156 | u8 val; |
| 212 | 157 | ||
| 213 | ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); | 158 | ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); |
| 214 | if (ret < 0) { | 159 | if (ret < 0) { |
| 215 | pr_debug("error %d reading SR\n", (int)ret); | 160 | pr_debug("error %d reading SR\n", (int)ret); |
| 216 | return ret; | 161 | return ret; |
| 217 | } | 162 | } |
| 218 | 163 | ||
| 219 | return val; | 164 | return val; |
| 220 | } | 165 | } |
| 221 | 166 | ||
| 222 | /* | 167 | /* |
| 223 | * Read the flag status register, returning its value in the location | 168 | * Read the flag status register, returning its value in the location |
| 224 | * Return the status register value. | 169 | * Return the status register value. |
| 225 | * Returns negative if error occurred. | 170 | * Returns negative if error occurred. |
| 226 | */ | 171 | */ |
| 227 | static int read_fsr(struct spi_nor *nor) | 172 | static int read_fsr(struct spi_nor *nor) |
| 228 | { | 173 | { |
| 229 | int ret; | 174 | int ret; |
| 230 | u8 val; | 175 | u8 val; |
| 231 | 176 | ||
| 232 | ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); | 177 | ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); |
| 233 | if (ret < 0) { | 178 | if (ret < 0) { |
| 234 | pr_debug("error %d reading FSR\n", ret); | 179 | pr_debug("error %d reading FSR\n", ret); |
| 235 | return ret; | 180 | return ret; |
| 236 | } | 181 | } |
| 237 | 182 | ||
| 238 | return val; | 183 | return val; |
| 239 | } | 184 | } |
| 240 | 185 | ||
| 241 | /* | 186 | /* |
| 242 | * Read configuration register, returning its value in the | 187 | * Read configuration register, returning its value in the |
| 243 | * location. Return the configuration register value. | 188 | * location. Return the configuration register value. |
| 244 | * Returns negative if error occurred. | 189 | * Returns negative if error occurred. |
| 245 | */ | 190 | */ |
| 246 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 191 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
| 247 | static int read_cr(struct spi_nor *nor) | 192 | static int read_cr(struct spi_nor *nor) |
| 248 | { | 193 | { |
| 249 | int ret; | 194 | int ret; |
| 250 | u8 val; | 195 | u8 val; |
| 251 | 196 | ||
| 252 | ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); | 197 | ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); |
| 253 | if (ret < 0) { | 198 | if (ret < 0) { |
| 254 | dev_dbg(nor->dev, "error %d reading CR\n", ret); | 199 | dev_dbg(nor->dev, "error %d reading CR\n", ret); |
| 255 | return ret; | 200 | return ret; |
| 256 | } | 201 | } |
| 257 | 202 | ||
| 258 | return val; | 203 | return val; |
| 259 | } | 204 | } |
| 260 | #endif | 205 | #endif |
| 261 | 206 | ||
| 262 | /* | 207 | /* |
| 263 | * Write status register 1 byte | 208 | * Write status register 1 byte |
| 264 | * Returns negative if error occurred. | 209 | * Returns negative if error occurred. |
| 265 | */ | 210 | */ |
| 266 | static int write_sr(struct spi_nor *nor, u8 val) | 211 | static int write_sr(struct spi_nor *nor, u8 val) |
| 267 | { | 212 | { |
| 268 | nor->cmd_buf[0] = val; | 213 | nor->cmd_buf[0] = val; |
| 269 | return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); | 214 | return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); |
| 270 | } | 215 | } |
| 271 | 216 | ||
| 272 | /* | 217 | /* |
| 273 | * Set write enable latch with Write Enable command. | 218 | * Set write enable latch with Write Enable command. |
| 274 | * Returns negative if error occurred. | 219 | * Returns negative if error occurred. |
| 275 | */ | 220 | */ |
| 276 | static int write_enable(struct spi_nor *nor) | 221 | static int write_enable(struct spi_nor *nor) |
| 277 | { | 222 | { |
| 278 | return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); | 223 | return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); |
| 279 | } | 224 | } |
| 280 | 225 | ||
| 281 | /* | 226 | /* |
| 282 | * Send write disable instruction to the chip. | 227 | * Send write disable instruction to the chip. |
| 283 | */ | 228 | */ |
| 284 | static int write_disable(struct spi_nor *nor) | 229 | static int write_disable(struct spi_nor *nor) |
| 285 | { | 230 | { |
| 286 | return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); | 231 | return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); |
| 287 | } | 232 | } |
| 288 | 233 | ||
| 289 | static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) | 234 | static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) |
| 290 | { | 235 | { |
| 291 | return mtd->priv; | 236 | return mtd->priv; |
| 292 | } | 237 | } |
| 293 | 238 | ||
| 294 | #ifndef CONFIG_SPI_FLASH_BAR | 239 | #ifndef CONFIG_SPI_FLASH_BAR |
| 295 | static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) | 240 | static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) |
| 296 | { | 241 | { |
| 297 | size_t i; | 242 | size_t i; |
| 298 | 243 | ||
| 299 | for (i = 0; i < size; i++) | 244 | for (i = 0; i < size; i++) |
| 300 | if (table[i][0] == opcode) | 245 | if (table[i][0] == opcode) |
| 301 | return table[i][1]; | 246 | return table[i][1]; |
| 302 | 247 | ||
| 303 | /* No conversion found, keep input op code. */ | 248 | /* No conversion found, keep input op code. */ |
| 304 | return opcode; | 249 | return opcode; |
| 305 | } | 250 | } |
| 306 | 251 | ||
| 307 | static u8 spi_nor_convert_3to4_read(u8 opcode) | 252 | static u8 spi_nor_convert_3to4_read(u8 opcode) |
| 308 | { | 253 | { |
| 309 | static const u8 spi_nor_3to4_read[][2] = { | 254 | static const u8 spi_nor_3to4_read[][2] = { |
| 310 | { SPINOR_OP_READ, SPINOR_OP_READ_4B }, | 255 | { SPINOR_OP_READ, SPINOR_OP_READ_4B }, |
| 311 | { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, | 256 | { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, |
| 312 | { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, | 257 | { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, |
| 313 | { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, | 258 | { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, |
| 314 | { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, | 259 | { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, |
| 315 | { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, | 260 | { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, |
| 316 | 261 | ||
| 317 | { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, | 262 | { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, |
| 318 | { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, | 263 | { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, |
| 319 | { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B }, | 264 | { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B }, |
| 320 | }; | 265 | }; |
| 321 | 266 | ||
| 322 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, | 267 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, |
| 323 | ARRAY_SIZE(spi_nor_3to4_read)); | 268 | ARRAY_SIZE(spi_nor_3to4_read)); |
| 324 | } | 269 | } |
| 325 | 270 | ||
| 326 | static u8 spi_nor_convert_3to4_program(u8 opcode) | 271 | static u8 spi_nor_convert_3to4_program(u8 opcode) |
| 327 | { | 272 | { |
| 328 | static const u8 spi_nor_3to4_program[][2] = { | 273 | static const u8 spi_nor_3to4_program[][2] = { |
| 329 | { SPINOR_OP_PP, SPINOR_OP_PP_4B }, | 274 | { SPINOR_OP_PP, SPINOR_OP_PP_4B }, |
| 330 | { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, | 275 | { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, |
| 331 | { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, | 276 | { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, |
| 332 | }; | 277 | }; |
| 333 | 278 | ||
| 334 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, | 279 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, |
| 335 | ARRAY_SIZE(spi_nor_3to4_program)); | 280 | ARRAY_SIZE(spi_nor_3to4_program)); |
| 336 | } | 281 | } |
| 337 | 282 | ||
| 338 | static u8 spi_nor_convert_3to4_erase(u8 opcode) | 283 | static u8 spi_nor_convert_3to4_erase(u8 opcode) |
| 339 | { | 284 | { |
| 340 | static const u8 spi_nor_3to4_erase[][2] = { | 285 | static const u8 spi_nor_3to4_erase[][2] = { |
| 341 | { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B }, | 286 | { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B }, |
| 342 | { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B }, | 287 | { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B }, |
| 343 | { SPINOR_OP_SE, SPINOR_OP_SE_4B }, | 288 | { SPINOR_OP_SE, SPINOR_OP_SE_4B }, |
| 344 | }; | 289 | }; |
| 345 | 290 | ||
| 346 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase, | 291 | return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase, |
| 347 | ARRAY_SIZE(spi_nor_3to4_erase)); | 292 | ARRAY_SIZE(spi_nor_3to4_erase)); |
| 348 | } | 293 | } |
| 349 | 294 | ||
| 350 | static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, | 295 | static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, |
| 351 | const struct flash_info *info) | 296 | const struct flash_info *info) |
| 352 | { | 297 | { |
| 353 | /* Do some manufacturer fixups first */ | 298 | /* Do some manufacturer fixups first */ |
| 354 | switch (JEDEC_MFR(info)) { | 299 | switch (JEDEC_MFR(info)) { |
| 355 | case SNOR_MFR_SPANSION: | 300 | case SNOR_MFR_SPANSION: |
| 356 | /* No small sector erase for 4-byte command set */ | 301 | /* No small sector erase for 4-byte command set */ |
| 357 | nor->erase_opcode = SPINOR_OP_SE; | 302 | nor->erase_opcode = SPINOR_OP_SE; |
| 358 | nor->mtd.erasesize = info->sector_size; | 303 | nor->mtd.erasesize = info->sector_size; |
| 359 | break; | 304 | break; |
| 360 | 305 | ||
| 361 | default: | 306 | default: |
| 362 | break; | 307 | break; |
| 363 | } | 308 | } |
| 364 | 309 | ||
| 365 | nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); | 310 | nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); |
| 366 | nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode); | 311 | nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode); |
| 367 | nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); | 312 | nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); |
| 368 | } | 313 | } |
| 369 | #endif /* !CONFIG_SPI_FLASH_BAR */ | 314 | #endif /* !CONFIG_SPI_FLASH_BAR */ |
| 370 | 315 | ||
| 371 | /* Enable/disable 4-byte addressing mode. */ | 316 | /* Enable/disable 4-byte addressing mode. */ |
| 372 | static int set_4byte(struct spi_nor *nor, const struct flash_info *info, | 317 | static int set_4byte(struct spi_nor *nor, const struct flash_info *info, |
| 373 | int enable) | 318 | int enable) |
| 374 | { | 319 | { |
| 375 | int status; | 320 | int status; |
| 376 | bool need_wren = false; | 321 | bool need_wren = false; |
| 377 | u8 cmd; | 322 | u8 cmd; |
| 378 | 323 | ||
| 379 | switch (JEDEC_MFR(info)) { | 324 | switch (JEDEC_MFR(info)) { |
| 380 | case SNOR_MFR_ST: | 325 | case SNOR_MFR_ST: |
| 381 | case SNOR_MFR_MICRON: | 326 | case SNOR_MFR_MICRON: |
| 382 | /* Some Micron need WREN command; all will accept it */ | 327 | /* Some Micron need WREN command; all will accept it */ |
| 383 | need_wren = true; | 328 | need_wren = true; |
| 384 | case SNOR_MFR_MACRONIX: | 329 | case SNOR_MFR_MACRONIX: |
| 385 | case SNOR_MFR_WINBOND: | 330 | case SNOR_MFR_WINBOND: |
| 386 | if (need_wren) | 331 | if (need_wren) |
| 387 | write_enable(nor); | 332 | write_enable(nor); |
| 388 | 333 | ||
| 389 | cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; | 334 | cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; |
| 390 | status = nor->write_reg(nor, cmd, NULL, 0); | 335 | status = nor->write_reg(nor, cmd, NULL, 0); |
| 391 | if (need_wren) | 336 | if (need_wren) |
| 392 | write_disable(nor); | 337 | write_disable(nor); |
| 393 | 338 | ||
| 394 | if (!status && !enable && | 339 | if (!status && !enable && |
| 395 | JEDEC_MFR(info) == SNOR_MFR_WINBOND) { | 340 | JEDEC_MFR(info) == SNOR_MFR_WINBOND) { |
| 396 | /* | 341 | /* |
| 397 | * On Winbond W25Q256FV, leaving 4byte mode causes | 342 | * On Winbond W25Q256FV, leaving 4byte mode causes |
| 398 | * the Extended Address Register to be set to 1, so all | 343 | * the Extended Address Register to be set to 1, so all |
| 399 | * 3-byte-address reads come from the second 16M. | 344 | * 3-byte-address reads come from the second 16M. |
| 400 | * We must clear the register to enable normal behavior. | 345 | * We must clear the register to enable normal behavior. |
| 401 | */ | 346 | */ |
| 402 | write_enable(nor); | 347 | write_enable(nor); |
| 403 | nor->cmd_buf[0] = 0; | 348 | nor->cmd_buf[0] = 0; |
| 404 | nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); | 349 | nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); |
| 405 | write_disable(nor); | 350 | write_disable(nor); |
| 406 | } | 351 | } |
| 407 | 352 | ||
| 408 | return status; | 353 | return status; |
| 409 | default: | 354 | default: |
| 410 | /* Spansion style */ | 355 | /* Spansion style */ |
| 411 | nor->cmd_buf[0] = enable << 7; | 356 | nor->cmd_buf[0] = enable << 7; |
| 412 | return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); | 357 | return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); |
| 413 | } | 358 | } |
| 414 | } | 359 | } |
| 415 | 360 | ||
| 416 | static int spi_nor_sr_ready(struct spi_nor *nor) | 361 | static int spi_nor_sr_ready(struct spi_nor *nor) |
| 417 | { | 362 | { |
| 418 | int sr = read_sr(nor); | 363 | int sr = read_sr(nor); |
| 419 | 364 | ||
| 420 | if (sr < 0) | 365 | if (sr < 0) |
| 421 | return sr; | 366 | return sr; |
| 422 | 367 | ||
| 423 | if (nor->flags & SNOR_F_USE_CLSR && sr & (SR_E_ERR | SR_P_ERR)) { | 368 | if (nor->flags & SNOR_F_USE_CLSR && sr & (SR_E_ERR | SR_P_ERR)) { |
| 424 | if (sr & SR_E_ERR) | 369 | if (sr & SR_E_ERR) |
| 425 | dev_dbg(nor->dev, "Erase Error occurred\n"); | 370 | dev_dbg(nor->dev, "Erase Error occurred\n"); |
| 426 | else | 371 | else |
| 427 | dev_dbg(nor->dev, "Programming Error occurred\n"); | 372 | dev_dbg(nor->dev, "Programming Error occurred\n"); |
| 428 | 373 | ||
| 429 | nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); | 374 | nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); |
| 430 | return -EIO; | 375 | return -EIO; |
| 431 | } | 376 | } |
| 432 | 377 | ||
| 433 | return !(sr & SR_WIP); | 378 | return !(sr & SR_WIP); |
| 434 | } | 379 | } |
| 435 | 380 | ||
| 436 | static int spi_nor_fsr_ready(struct spi_nor *nor) | 381 | static int spi_nor_fsr_ready(struct spi_nor *nor) |
| 437 | { | 382 | { |
| 438 | int fsr = read_fsr(nor); | 383 | int fsr = read_fsr(nor); |
| 439 | 384 | ||
| 440 | if (fsr < 0) | 385 | if (fsr < 0) |
| 441 | return fsr; | 386 | return fsr; |
| 442 | 387 | ||
| 443 | if (fsr & (FSR_E_ERR | FSR_P_ERR)) { | 388 | if (fsr & (FSR_E_ERR | FSR_P_ERR)) { |
| 444 | if (fsr & FSR_E_ERR) | 389 | if (fsr & FSR_E_ERR) |
| 445 | dev_dbg(nor->dev, "Erase operation failed.\n"); | 390 | dev_dbg(nor->dev, "Erase operation failed.\n"); |
| 446 | else | 391 | else |
| 447 | dev_dbg(nor->dev, "Program operation failed.\n"); | 392 | dev_dbg(nor->dev, "Program operation failed.\n"); |
| 448 | 393 | ||
| 449 | if (fsr & FSR_PT_ERR) | 394 | if (fsr & FSR_PT_ERR) |
| 450 | dev_dbg(nor->dev, | 395 | dev_dbg(nor->dev, |
| 451 | "Attempted to modify a protected sector.\n"); | 396 | "Attempted to modify a protected sector.\n"); |
| 452 | 397 | ||
| 453 | nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); | 398 | nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); |
| 454 | return -EIO; | 399 | return -EIO; |
| 455 | } | 400 | } |
| 456 | 401 | ||
| 457 | return fsr & FSR_READY; | 402 | return fsr & FSR_READY; |
| 458 | } | 403 | } |
| 459 | 404 | ||
| 460 | static int spi_nor_ready(struct spi_nor *nor) | 405 | static int spi_nor_ready(struct spi_nor *nor) |
| 461 | { | 406 | { |
| 462 | int sr, fsr; | 407 | int sr, fsr; |
| 463 | 408 | ||
| 464 | sr = spi_nor_sr_ready(nor); | 409 | sr = spi_nor_sr_ready(nor); |
| 465 | if (sr < 0) | 410 | if (sr < 0) |
| 466 | return sr; | 411 | return sr; |
| 467 | fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; | 412 | fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; |
| 468 | if (fsr < 0) | 413 | if (fsr < 0) |
| 469 | return fsr; | 414 | return fsr; |
| 470 | return sr && fsr; | 415 | return sr && fsr; |
| 471 | } | 416 | } |
| 472 | 417 | ||
| 473 | /* | 418 | /* |
| 474 | * Service routine to read status register until ready, or timeout occurs. | 419 | * Service routine to read status register until ready, or timeout occurs. |
| 475 | * Returns non-zero if error. | 420 | * Returns non-zero if error. |
| 476 | */ | 421 | */ |
| 477 | static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, | 422 | static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, |
| 478 | unsigned long timeout) | 423 | unsigned long timeout) |
| 479 | { | 424 | { |
| 480 | unsigned long timebase; | 425 | unsigned long timebase; |
| 481 | int ret; | 426 | int ret; |
| 482 | 427 | ||
| 483 | timebase = get_timer(0); | 428 | timebase = get_timer(0); |
| 484 | 429 | ||
| 485 | while (get_timer(timebase) < timeout) { | 430 | while (get_timer(timebase) < timeout) { |
| 486 | ret = spi_nor_ready(nor); | 431 | ret = spi_nor_ready(nor); |
| 487 | if (ret < 0) | 432 | if (ret < 0) |
| 488 | return ret; | 433 | return ret; |
| 489 | if (ret) | 434 | if (ret) |
| 490 | return 0; | 435 | return 0; |
| 491 | } | 436 | } |
| 492 | 437 | ||
| 493 | dev_err(nor->dev, "flash operation timed out\n"); | 438 | dev_err(nor->dev, "flash operation timed out\n"); |
| 494 | 439 | ||
| 495 | return -ETIMEDOUT; | 440 | return -ETIMEDOUT; |
| 496 | } | 441 | } |
| 497 | 442 | ||
| 498 | static int spi_nor_wait_till_ready(struct spi_nor *nor) | 443 | static int spi_nor_wait_till_ready(struct spi_nor *nor) |
| 499 | { | 444 | { |
| 500 | return spi_nor_wait_till_ready_with_timeout(nor, | 445 | return spi_nor_wait_till_ready_with_timeout(nor, |
| 501 | DEFAULT_READY_WAIT_JIFFIES); | 446 | DEFAULT_READY_WAIT_JIFFIES); |
| 502 | } | 447 | } |
| 503 | 448 | ||
| 504 | #ifdef CONFIG_SPI_FLASH_BAR | 449 | #ifdef CONFIG_SPI_FLASH_BAR |
| 505 | /* | 450 | /* |
| 506 | * This "clean_bar" is necessary in a situation when one was accessing | 451 | * This "clean_bar" is necessary in a situation when one was accessing |
| 507 | * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. | 452 | * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. |
| 508 | * | 453 | * |
| 509 | * After it the BA24 bit shall be cleared to allow access to correct | 454 | * After it the BA24 bit shall be cleared to allow access to correct |
| 510 | * memory region after SW reset (by calling "reset" command). | 455 | * memory region after SW reset (by calling "reset" command). |
| 511 | * | 456 | * |
| 512 | * Otherwise, the BA24 bit may be left set and then after reset, the | 457 | * Otherwise, the BA24 bit may be left set and then after reset, the |
| 513 | * ROM would read/write/erase SPL from 16 MiB * bank_sel address. | 458 | * ROM would read/write/erase SPL from 16 MiB * bank_sel address. |
| 514 | */ | 459 | */ |
| 515 | static int clean_bar(struct spi_nor *nor) | 460 | static int clean_bar(struct spi_nor *nor) |
| 516 | { | 461 | { |
| 517 | u8 cmd, bank_sel = 0; | 462 | u8 cmd, bank_sel = 0; |
| 518 | 463 | ||
| 519 | if (nor->bank_curr == 0) | 464 | if (nor->bank_curr == 0) |
| 520 | return 0; | 465 | return 0; |
| 521 | cmd = nor->bank_write_cmd; | 466 | cmd = nor->bank_write_cmd; |
| 522 | nor->bank_curr = 0; | 467 | nor->bank_curr = 0; |
| 523 | write_enable(nor); | 468 | write_enable(nor); |
| 524 | 469 | ||
| 525 | return nor->write_reg(nor, cmd, &bank_sel, 1); | 470 | return nor->write_reg(nor, cmd, &bank_sel, 1); |
| 526 | } | 471 | } |
| 527 | 472 | ||
| 528 | static int write_bar(struct spi_nor *nor, u32 offset) | 473 | static int write_bar(struct spi_nor *nor, u32 offset) |
| 529 | { | 474 | { |
| 530 | u8 cmd, bank_sel; | 475 | u8 cmd, bank_sel; |
| 531 | int ret; | 476 | int ret; |
| 532 | 477 | ||
| 533 | bank_sel = offset / SZ_16M; | 478 | bank_sel = offset / SZ_16M; |
| 534 | if (bank_sel == nor->bank_curr) | 479 | if (bank_sel == nor->bank_curr) |
| 535 | goto bar_end; | 480 | goto bar_end; |
| 536 | 481 | ||
| 537 | cmd = nor->bank_write_cmd; | 482 | cmd = nor->bank_write_cmd; |
| 538 | write_enable(nor); | 483 | write_enable(nor); |
| 539 | ret = nor->write_reg(nor, cmd, &bank_sel, 1); | 484 | ret = nor->write_reg(nor, cmd, &bank_sel, 1); |
| 540 | if (ret < 0) { | 485 | if (ret < 0) { |
| 541 | debug("SF: fail to write bank register\n"); | 486 | debug("SF: fail to write bank register\n"); |
| 542 | return ret; | 487 | return ret; |
| 543 | } | 488 | } |
| 544 | 489 | ||
| 545 | bar_end: | 490 | bar_end: |
| 546 | nor->bank_curr = bank_sel; | 491 | nor->bank_curr = bank_sel; |
| 547 | return nor->bank_curr; | 492 | return nor->bank_curr; |
| 548 | } | 493 | } |
| 549 | 494 | ||
| 550 | static int read_bar(struct spi_nor *nor, const struct flash_info *info) | 495 | static int read_bar(struct spi_nor *nor, const struct flash_info *info) |
| 551 | { | 496 | { |
| 552 | u8 curr_bank = 0; | 497 | u8 curr_bank = 0; |
| 553 | int ret; | 498 | int ret; |
| 554 | 499 | ||
| 555 | switch (JEDEC_MFR(info)) { | 500 | switch (JEDEC_MFR(info)) { |
| 556 | case SNOR_MFR_SPANSION: | 501 | case SNOR_MFR_SPANSION: |
| 557 | nor->bank_read_cmd = SPINOR_OP_BRRD; | 502 | nor->bank_read_cmd = SPINOR_OP_BRRD; |
| 558 | nor->bank_write_cmd = SPINOR_OP_BRWR; | 503 | nor->bank_write_cmd = SPINOR_OP_BRWR; |
| 559 | break; | 504 | break; |
| 560 | default: | 505 | default: |
| 561 | nor->bank_read_cmd = SPINOR_OP_RDEAR; | 506 | nor->bank_read_cmd = SPINOR_OP_RDEAR; |
| 562 | nor->bank_write_cmd = SPINOR_OP_WREAR; | 507 | nor->bank_write_cmd = SPINOR_OP_WREAR; |
| 563 | } | 508 | } |
| 564 | 509 | ||
| 565 | ret = nor->read_reg(nor, nor->bank_read_cmd, | 510 | ret = nor->read_reg(nor, nor->bank_read_cmd, |
| 566 | &curr_bank, 1); | 511 | &curr_bank, 1); |
| 567 | if (ret) { | 512 | if (ret) { |
| 568 | debug("SF: fail to read bank addr register\n"); | 513 | debug("SF: fail to read bank addr register\n"); |
| 569 | return ret; | 514 | return ret; |
| 570 | } | 515 | } |
| 571 | nor->bank_curr = curr_bank; | 516 | nor->bank_curr = curr_bank; |
| 572 | 517 | ||
| 573 | return 0; | 518 | return 0; |
| 574 | } | 519 | } |
| 575 | #endif | 520 | #endif |
| 576 | 521 | ||
| 577 | /* | 522 | /* |
| 578 | * Initiate the erasure of a single sector | 523 | * Initiate the erasure of a single sector |
| 579 | */ | 524 | */ |
| 580 | static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) | 525 | static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) |
| 581 | { | 526 | { |
| 582 | u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; | 527 | u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; |
| 583 | int i; | 528 | int i; |
| 584 | 529 | ||
| 585 | if (nor->erase) | 530 | if (nor->erase) |
| 586 | return nor->erase(nor, addr); | 531 | return nor->erase(nor, addr); |
| 587 | 532 | ||
| 588 | /* | 533 | /* |
| 589 | * Default implementation, if driver doesn't have a specialized HW | 534 | * Default implementation, if driver doesn't have a specialized HW |
| 590 | * control | 535 | * control |
| 591 | */ | 536 | */ |
| 592 | for (i = nor->addr_width - 1; i >= 0; i--) { | 537 | for (i = nor->addr_width - 1; i >= 0; i--) { |
| 593 | buf[i] = addr & 0xff; | 538 | buf[i] = addr & 0xff; |
| 594 | addr >>= 8; | 539 | addr >>= 8; |
| 595 | } | 540 | } |
| 596 | 541 | ||
| 597 | return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); | 542 | return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); |
| 598 | } | 543 | } |
| 599 | 544 | ||
| 600 | /* | 545 | /* |
| 601 | * Erase an address range on the nor chip. The address range may extend | 546 | * Erase an address range on the nor chip. The address range may extend |
| 602 | * one or more erase sectors. Return an error is there is a problem erasing. | 547 | * one or more erase sectors. Return an error is there is a problem erasing. |
| 603 | */ | 548 | */ |
| 604 | static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) | 549 | static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) |
| 605 | { | 550 | { |
| 606 | struct spi_nor *nor = mtd_to_spi_nor(mtd); | 551 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 607 | u32 addr, len, rem; | 552 | u32 addr, len, rem; |
| 608 | int ret; | 553 | int ret; |
| 609 | 554 | ||
| 610 | dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, | 555 | dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, |
| 611 | (long long)instr->len); | 556 | (long long)instr->len); |
| 612 | 557 | ||
| 613 | div_u64_rem(instr->len, mtd->erasesize, &rem); | 558 | div_u64_rem(instr->len, mtd->erasesize, &rem); |
| 614 | if (rem) | 559 | if (rem) |
| 615 | return -EINVAL; | 560 | return -EINVAL; |
| 616 | 561 | ||
| 617 | addr = instr->addr; | 562 | addr = instr->addr; |
| 618 | len = instr->len; | 563 | len = instr->len; |
| 619 | 564 | ||
| 620 | while (len) { | 565 | while (len) { |
| 621 | #ifdef CONFIG_SPI_FLASH_BAR | 566 | #ifdef CONFIG_SPI_FLASH_BAR |
| 622 | ret = write_bar(nor, addr); | 567 | ret = write_bar(nor, addr); |
| 623 | if (ret < 0) | 568 | if (ret < 0) |
| 624 | return ret; | 569 | return ret; |
| 625 | #endif | 570 | #endif |
| 626 | write_enable(nor); | 571 | write_enable(nor); |
| 627 | 572 | ||
| 628 | ret = spi_nor_erase_sector(nor, addr); | 573 | ret = spi_nor_erase_sector(nor, addr); |
| 629 | if (ret) | 574 | if (ret) |
| 630 | goto erase_err; | 575 | goto erase_err; |
| 631 | 576 | ||
| 632 | addr += mtd->erasesize; | 577 | addr += mtd->erasesize; |
| 633 | len -= mtd->erasesize; | 578 | len -= mtd->erasesize; |
| 634 | 579 | ||
| 635 | ret = spi_nor_wait_till_ready(nor); | 580 | ret = spi_nor_wait_till_ready(nor); |
| 636 | if (ret) | 581 | if (ret) |
| 637 | goto erase_err; | 582 | goto erase_err; |
| 638 | } | 583 | } |
| 639 | 584 | ||
| 640 | erase_err: | 585 | erase_err: |
| 641 | #ifdef CONFIG_SPI_FLASH_BAR | 586 | #ifdef CONFIG_SPI_FLASH_BAR |
| 642 | ret = clean_bar(nor); | 587 | ret = clean_bar(nor); |
| 643 | #endif | 588 | #endif |
| 644 | write_disable(nor); | 589 | write_disable(nor); |
| 645 | 590 | ||
| 646 | return ret; | 591 | return ret; |
| 647 | } | 592 | } |
| 648 | 593 | ||
| 649 | #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) | 594 | #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) |
| 650 | /* Write status register and ensure bits in mask match written values */ | 595 | /* Write status register and ensure bits in mask match written values */ |
| 651 | static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) | 596 | static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) |
| 652 | { | 597 | { |
| 653 | int ret; | 598 | int ret; |
| 654 | 599 | ||
| 655 | write_enable(nor); | 600 | write_enable(nor); |
| 656 | ret = write_sr(nor, status_new); | 601 | ret = write_sr(nor, status_new); |
| 657 | if (ret) | 602 | if (ret) |
| 658 | return ret; | 603 | return ret; |
| 659 | 604 | ||
| 660 | ret = spi_nor_wait_till_ready(nor); | 605 | ret = spi_nor_wait_till_ready(nor); |
| 661 | if (ret) | 606 | if (ret) |
| 662 | return ret; | 607 | return ret; |
| 663 | 608 | ||
| 664 | ret = read_sr(nor); | 609 | ret = read_sr(nor); |
| 665 | if (ret < 0) | 610 | if (ret < 0) |
| 666 | return ret; | 611 | return ret; |
| 667 | 612 | ||
| 668 | return ((ret & mask) != (status_new & mask)) ? -EIO : 0; | 613 | return ((ret & mask) != (status_new & mask)) ? -EIO : 0; |
| 669 | } | 614 | } |
| 670 | 615 | ||
| 671 | static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, | 616 | static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, |
| 672 | uint64_t *len) | 617 | uint64_t *len) |
| 673 | { | 618 | { |
| 674 | struct mtd_info *mtd = &nor->mtd; | 619 | struct mtd_info *mtd = &nor->mtd; |
| 675 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; | 620 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 676 | int shift = ffs(mask) - 1; | 621 | int shift = ffs(mask) - 1; |
| 677 | int pow; | 622 | int pow; |
| 678 | 623 | ||
| 679 | if (!(sr & mask)) { | 624 | if (!(sr & mask)) { |
| 680 | /* No protection */ | 625 | /* No protection */ |
| 681 | *ofs = 0; | 626 | *ofs = 0; |
| 682 | *len = 0; | 627 | *len = 0; |
| 683 | } else { | 628 | } else { |
| 684 | pow = ((sr & mask) ^ mask) >> shift; | 629 | pow = ((sr & mask) ^ mask) >> shift; |
| 685 | *len = mtd->size >> pow; | 630 | *len = mtd->size >> pow; |
| 686 | if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) | 631 | if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) |
| 687 | *ofs = 0; | 632 | *ofs = 0; |
| 688 | else | 633 | else |
| 689 | *ofs = mtd->size - *len; | 634 | *ofs = mtd->size - *len; |
| 690 | } | 635 | } |
| 691 | } | 636 | } |
| 692 | 637 | ||
| 693 | /* | 638 | /* |
| 694 | * Return 1 if the entire region is locked (if @locked is true) or unlocked (if | 639 | * Return 1 if the entire region is locked (if @locked is true) or unlocked (if |
| 695 | * @locked is false); 0 otherwise | 640 | * @locked is false); 0 otherwise |
| 696 | */ | 641 | */ |
| 697 | static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, u64 len, | 642 | static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, u64 len, |
| 698 | u8 sr, bool locked) | 643 | u8 sr, bool locked) |
| 699 | { | 644 | { |
| 700 | loff_t lock_offs; | 645 | loff_t lock_offs; |
| 701 | uint64_t lock_len; | 646 | uint64_t lock_len; |
| 702 | 647 | ||
| 703 | if (!len) | 648 | if (!len) |
| 704 | return 1; | 649 | return 1; |
| 705 | 650 | ||
| 706 | stm_get_locked_range(nor, sr, &lock_offs, &lock_len); | 651 | stm_get_locked_range(nor, sr, &lock_offs, &lock_len); |
| 707 | 652 | ||
| 708 | if (locked) | 653 | if (locked) |
| 709 | /* Requested range is a sub-range of locked range */ | 654 | /* Requested range is a sub-range of locked range */ |
| 710 | return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); | 655 | return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); |
| 711 | else | 656 | else |
| 712 | /* Requested range does not overlap with locked range */ | 657 | /* Requested range does not overlap with locked range */ |
| 713 | return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); | 658 | return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); |
| 714 | } | 659 | } |
| 715 | 660 | ||
| 716 | static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, | 661 | static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, |
| 717 | u8 sr) | 662 | u8 sr) |
| 718 | { | 663 | { |
| 719 | return stm_check_lock_status_sr(nor, ofs, len, sr, true); | 664 | return stm_check_lock_status_sr(nor, ofs, len, sr, true); |
| 720 | } | 665 | } |
| 721 | 666 | ||
| 722 | static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, | 667 | static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, |
| 723 | u8 sr) | 668 | u8 sr) |
| 724 | { | 669 | { |
| 725 | return stm_check_lock_status_sr(nor, ofs, len, sr, false); | 670 | return stm_check_lock_status_sr(nor, ofs, len, sr, false); |
| 726 | } | 671 | } |
| 727 | 672 | ||
| 728 | /* | 673 | /* |
| 729 | * Lock a region of the flash. Compatible with ST Micro and similar flash. | 674 | * Lock a region of the flash. Compatible with ST Micro and similar flash. |
| 730 | * Supports the block protection bits BP{0,1,2} in the status register | 675 | * Supports the block protection bits BP{0,1,2} in the status register |
| 731 | * (SR). Does not support these features found in newer SR bitfields: | 676 | * (SR). Does not support these features found in newer SR bitfields: |
| 732 | * - SEC: sector/block protect - only handle SEC=0 (block protect) | 677 | * - SEC: sector/block protect - only handle SEC=0 (block protect) |
| 733 | * - CMP: complement protect - only support CMP=0 (range is not complemented) | 678 | * - CMP: complement protect - only support CMP=0 (range is not complemented) |
| 734 | * | 679 | * |
| 735 | * Support for the following is provided conditionally for some flash: | 680 | * Support for the following is provided conditionally for some flash: |
| 736 | * - TB: top/bottom protect | 681 | * - TB: top/bottom protect |
| 737 | * | 682 | * |
| 738 | * Sample table portion for 8MB flash (Winbond w25q64fw): | 683 | * Sample table portion for 8MB flash (Winbond w25q64fw): |
| 739 | * | 684 | * |
| 740 | * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion | 685 | * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion |
| 741 | * -------------------------------------------------------------------------- | 686 | * -------------------------------------------------------------------------- |
| 742 | * X | X | 0 | 0 | 0 | NONE | NONE | 687 | * X | X | 0 | 0 | 0 | NONE | NONE |
| 743 | * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 | 688 | * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 |
| 744 | * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 | 689 | * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 |
| 745 | * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 | 690 | * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 |
| 746 | * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 | 691 | * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 |
| 747 | * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 | 692 | * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 |
| 748 | * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 | 693 | * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 |
| 749 | * X | X | 1 | 1 | 1 | 8 MB | ALL | 694 | * X | X | 1 | 1 | 1 | 8 MB | ALL |
| 750 | * ------|-------|-------|-------|-------|---------------|------------------- | 695 | * ------|-------|-------|-------|-------|---------------|------------------- |
| 751 | * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 | 696 | * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 |
| 752 | * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 | 697 | * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 |
| 753 | * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 | 698 | * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 |
| 754 | * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 | 699 | * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 |
| 755 | * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 | 700 | * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 |
| 756 | * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 | 701 | * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 |
| 757 | * | 702 | * |
| 758 | * Returns negative on errors, 0 on success. | 703 | * Returns negative on errors, 0 on success. |
| 759 | */ | 704 | */ |
| 760 | static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) | 705 | static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) |
| 761 | { | 706 | { |
| 762 | struct mtd_info *mtd = &nor->mtd; | 707 | struct mtd_info *mtd = &nor->mtd; |
| 763 | int status_old, status_new; | 708 | int status_old, status_new; |
| 764 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; | 709 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 765 | u8 shift = ffs(mask) - 1, pow, val; | 710 | u8 shift = ffs(mask) - 1, pow, val; |
| 766 | loff_t lock_len; | 711 | loff_t lock_len; |
| 767 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; | 712 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; |
| 768 | bool use_top; | 713 | bool use_top; |
| 769 | 714 | ||
| 770 | status_old = read_sr(nor); | 715 | status_old = read_sr(nor); |
| 771 | if (status_old < 0) | 716 | if (status_old < 0) |
| 772 | return status_old; | 717 | return status_old; |
| 773 | 718 | ||
| 774 | /* If nothing in our range is unlocked, we don't need to do anything */ | 719 | /* If nothing in our range is unlocked, we don't need to do anything */ |
| 775 | if (stm_is_locked_sr(nor, ofs, len, status_old)) | 720 | if (stm_is_locked_sr(nor, ofs, len, status_old)) |
| 776 | return 0; | 721 | return 0; |
| 777 | 722 | ||
| 778 | /* If anything below us is unlocked, we can't use 'bottom' protection */ | 723 | /* If anything below us is unlocked, we can't use 'bottom' protection */ |
| 779 | if (!stm_is_locked_sr(nor, 0, ofs, status_old)) | 724 | if (!stm_is_locked_sr(nor, 0, ofs, status_old)) |
| 780 | can_be_bottom = false; | 725 | can_be_bottom = false; |
| 781 | 726 | ||
| 782 | /* If anything above us is unlocked, we can't use 'top' protection */ | 727 | /* If anything above us is unlocked, we can't use 'top' protection */ |
| 783 | if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), | 728 | if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), |
| 784 | status_old)) | 729 | status_old)) |
| 785 | can_be_top = false; | 730 | can_be_top = false; |
| 786 | 731 | ||
| 787 | if (!can_be_bottom && !can_be_top) | 732 | if (!can_be_bottom && !can_be_top) |
| 788 | return -EINVAL; | 733 | return -EINVAL; |
| 789 | 734 | ||
| 790 | /* Prefer top, if both are valid */ | 735 | /* Prefer top, if both are valid */ |
| 791 | use_top = can_be_top; | 736 | use_top = can_be_top; |
| 792 | 737 | ||
| 793 | /* lock_len: length of region that should end up locked */ | 738 | /* lock_len: length of region that should end up locked */ |
| 794 | if (use_top) | 739 | if (use_top) |
| 795 | lock_len = mtd->size - ofs; | 740 | lock_len = mtd->size - ofs; |
| 796 | else | 741 | else |
| 797 | lock_len = ofs + len; | 742 | lock_len = ofs + len; |
| 798 | 743 | ||
| 799 | /* | 744 | /* |
| 800 | * Need smallest pow such that: | 745 | * Need smallest pow such that: |
| 801 | * | 746 | * |
| 802 | * 1 / (2^pow) <= (len / size) | 747 | * 1 / (2^pow) <= (len / size) |
| 803 | * | 748 | * |
| 804 | * so (assuming power-of-2 size) we do: | 749 | * so (assuming power-of-2 size) we do: |
| 805 | * | 750 | * |
| 806 | * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) | 751 | * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) |
| 807 | */ | 752 | */ |
| 808 | pow = ilog2(mtd->size) - ilog2(lock_len); | 753 | pow = ilog2(mtd->size) - ilog2(lock_len); |
| 809 | val = mask - (pow << shift); | 754 | val = mask - (pow << shift); |
| 810 | if (val & ~mask) | 755 | if (val & ~mask) |
| 811 | return -EINVAL; | 756 | return -EINVAL; |
| 812 | /* Don't "lock" with no region! */ | 757 | /* Don't "lock" with no region! */ |
| 813 | if (!(val & mask)) | 758 | if (!(val & mask)) |
| 814 | return -EINVAL; | 759 | return -EINVAL; |
| 815 | 760 | ||
| 816 | status_new = (status_old & ~mask & ~SR_TB) | val; | 761 | status_new = (status_old & ~mask & ~SR_TB) | val; |
| 817 | 762 | ||
| 818 | /* Disallow further writes if WP pin is asserted */ | 763 | /* Disallow further writes if WP pin is asserted */ |
| 819 | status_new |= SR_SRWD; | 764 | status_new |= SR_SRWD; |
| 820 | 765 | ||
| 821 | if (!use_top) | 766 | if (!use_top) |
| 822 | status_new |= SR_TB; | 767 | status_new |= SR_TB; |
| 823 | 768 | ||
| 824 | /* Don't bother if they're the same */ | 769 | /* Don't bother if they're the same */ |
| 825 | if (status_new == status_old) | 770 | if (status_new == status_old) |
| 826 | return 0; | 771 | return 0; |
| 827 | 772 | ||
| 828 | /* Only modify protection if it will not unlock other areas */ | 773 | /* Only modify protection if it will not unlock other areas */ |
| 829 | if ((status_new & mask) < (status_old & mask)) | 774 | if ((status_new & mask) < (status_old & mask)) |
| 830 | return -EINVAL; | 775 | return -EINVAL; |
| 831 | 776 | ||
| 832 | return write_sr_and_check(nor, status_new, mask); | 777 | return write_sr_and_check(nor, status_new, mask); |
| 833 | } | 778 | } |
| 834 | 779 | ||
| 835 | /* | 780 | /* |
| 836 | * Unlock a region of the flash. See stm_lock() for more info | 781 | * Unlock a region of the flash. See stm_lock() for more info |
| 837 | * | 782 | * |
| 838 | * Returns negative on errors, 0 on success. | 783 | * Returns negative on errors, 0 on success. |
| 839 | */ | 784 | */ |
| 840 | static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) | 785 | static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) |
| 841 | { | 786 | { |
| 842 | struct mtd_info *mtd = &nor->mtd; | 787 | struct mtd_info *mtd = &nor->mtd; |
| 843 | int status_old, status_new; | 788 | int status_old, status_new; |
| 844 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; | 789 | u8 mask = SR_BP2 | SR_BP1 | SR_BP0; |
| 845 | u8 shift = ffs(mask) - 1, pow, val; | 790 | u8 shift = ffs(mask) - 1, pow, val; |
| 846 | loff_t lock_len; | 791 | loff_t lock_len; |
| 847 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; | 792 | bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; |
| 848 | bool use_top; | 793 | bool use_top; |
| 849 | 794 | ||
| 850 | status_old = read_sr(nor); | 795 | status_old = read_sr(nor); |
| 851 | if (status_old < 0) | 796 | if (status_old < 0) |
| 852 | return status_old; | 797 | return status_old; |
| 853 | 798 | ||
| 854 | /* If nothing in our range is locked, we don't need to do anything */ | 799 | /* If nothing in our range is locked, we don't need to do anything */ |
| 855 | if (stm_is_unlocked_sr(nor, ofs, len, status_old)) | 800 | if (stm_is_unlocked_sr(nor, ofs, len, status_old)) |
| 856 | return 0; | 801 | return 0; |
| 857 | 802 | ||
| 858 | /* If anything below us is locked, we can't use 'top' protection */ | 803 | /* If anything below us is locked, we can't use 'top' protection */ |
| 859 | if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) | 804 | if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) |
| 860 | can_be_top = false; | 805 | can_be_top = false; |
| 861 | 806 | ||
| 862 | /* If anything above us is locked, we can't use 'bottom' protection */ | 807 | /* If anything above us is locked, we can't use 'bottom' protection */ |
| 863 | if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), | 808 | if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), |
| 864 | status_old)) | 809 | status_old)) |
| 865 | can_be_bottom = false; | 810 | can_be_bottom = false; |
| 866 | 811 | ||
| 867 | if (!can_be_bottom && !can_be_top) | 812 | if (!can_be_bottom && !can_be_top) |
| 868 | return -EINVAL; | 813 | return -EINVAL; |
| 869 | 814 | ||
| 870 | /* Prefer top, if both are valid */ | 815 | /* Prefer top, if both are valid */ |
| 871 | use_top = can_be_top; | 816 | use_top = can_be_top; |
| 872 | 817 | ||
| 873 | /* lock_len: length of region that should remain locked */ | 818 | /* lock_len: length of region that should remain locked */ |
| 874 | if (use_top) | 819 | if (use_top) |
| 875 | lock_len = mtd->size - (ofs + len); | 820 | lock_len = mtd->size - (ofs + len); |
| 876 | else | 821 | else |
| 877 | lock_len = ofs; | 822 | lock_len = ofs; |
| 878 | 823 | ||
| 879 | /* | 824 | /* |
| 880 | * Need largest pow such that: | 825 | * Need largest pow such that: |
| 881 | * | 826 | * |
| 882 | * 1 / (2^pow) >= (len / size) | 827 | * 1 / (2^pow) >= (len / size) |
| 883 | * | 828 | * |
| 884 | * so (assuming power-of-2 size) we do: | 829 | * so (assuming power-of-2 size) we do: |
| 885 | * | 830 | * |
| 886 | * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) | 831 | * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) |
| 887 | */ | 832 | */ |
| 888 | pow = ilog2(mtd->size) - order_base_2(lock_len); | 833 | pow = ilog2(mtd->size) - order_base_2(lock_len); |
| 889 | if (lock_len == 0) { | 834 | if (lock_len == 0) { |
| 890 | val = 0; /* fully unlocked */ | 835 | val = 0; /* fully unlocked */ |
| 891 | } else { | 836 | } else { |
| 892 | val = mask - (pow << shift); | 837 | val = mask - (pow << shift); |
| 893 | /* Some power-of-two sizes are not supported */ | 838 | /* Some power-of-two sizes are not supported */ |
| 894 | if (val & ~mask) | 839 | if (val & ~mask) |
| 895 | return -EINVAL; | 840 | return -EINVAL; |
| 896 | } | 841 | } |
| 897 | 842 | ||
| 898 | status_new = (status_old & ~mask & ~SR_TB) | val; | 843 | status_new = (status_old & ~mask & ~SR_TB) | val; |
| 899 | 844 | ||
| 900 | /* Don't protect status register if we're fully unlocked */ | 845 | /* Don't protect status register if we're fully unlocked */ |
| 901 | if (lock_len == 0) | 846 | if (lock_len == 0) |
| 902 | status_new &= ~SR_SRWD; | 847 | status_new &= ~SR_SRWD; |
| 903 | 848 | ||
| 904 | if (!use_top) | 849 | if (!use_top) |
| 905 | status_new |= SR_TB; | 850 | status_new |= SR_TB; |
| 906 | 851 | ||
| 907 | /* Don't bother if they're the same */ | 852 | /* Don't bother if they're the same */ |
| 908 | if (status_new == status_old) | 853 | if (status_new == status_old) |
| 909 | return 0; | 854 | return 0; |
| 910 | 855 | ||
| 911 | /* Only modify protection if it will not lock other areas */ | 856 | /* Only modify protection if it will not lock other areas */ |
| 912 | if ((status_new & mask) > (status_old & mask)) | 857 | if ((status_new & mask) > (status_old & mask)) |
| 913 | return -EINVAL; | 858 | return -EINVAL; |
| 914 | 859 | ||
| 915 | return write_sr_and_check(nor, status_new, mask); | 860 | return write_sr_and_check(nor, status_new, mask); |
| 916 | } | 861 | } |
| 917 | 862 | ||
| 918 | /* | 863 | /* |
| 919 | * Check if a region of the flash is (completely) locked. See stm_lock() for | 864 | * Check if a region of the flash is (completely) locked. See stm_lock() for |
| 920 | * more info. | 865 | * more info. |
| 921 | * | 866 | * |
| 922 | * Returns 1 if entire region is locked, 0 if any portion is unlocked, and | 867 | * Returns 1 if entire region is locked, 0 if any portion is unlocked, and |
| 923 | * negative on errors. | 868 | * negative on errors. |
| 924 | */ | 869 | */ |
| 925 | static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) | 870 | static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) |
| 926 | { | 871 | { |
| 927 | int status; | 872 | int status; |
| 928 | 873 | ||
| 929 | status = read_sr(nor); | 874 | status = read_sr(nor); |
| 930 | if (status < 0) | 875 | if (status < 0) |
| 931 | return status; | 876 | return status; |
| 932 | 877 | ||
| 933 | return stm_is_locked_sr(nor, ofs, len, status); | 878 | return stm_is_locked_sr(nor, ofs, len, status); |
| 934 | } | 879 | } |
| 935 | #endif /* CONFIG_SPI_FLASH_STMICRO */ | 880 | #endif /* CONFIG_SPI_FLASH_STMICRO */ |
| 936 | 881 | ||
| 937 | /* Used when the "_ext_id" is two bytes at most */ | 882 | /* Used when the "_ext_id" is two bytes at most */ |
| 938 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 883 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
| 939 | .id = { \ | 884 | .id = { \ |
| 940 | ((_jedec_id) >> 16) & 0xff, \ | 885 | ((_jedec_id) >> 16) & 0xff, \ |
| 941 | ((_jedec_id) >> 8) & 0xff, \ | 886 | ((_jedec_id) >> 8) & 0xff, \ |
| 942 | (_jedec_id) & 0xff, \ | 887 | (_jedec_id) & 0xff, \ |
| 943 | ((_ext_id) >> 8) & 0xff, \ | 888 | ((_ext_id) >> 8) & 0xff, \ |
| 944 | (_ext_id) & 0xff, \ | 889 | (_ext_id) & 0xff, \ |
| 945 | }, \ | 890 | }, \ |
| 946 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ | 891 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ |
| 947 | .sector_size = (_sector_size), \ | 892 | .sector_size = (_sector_size), \ |
| 948 | .n_sectors = (_n_sectors), \ | 893 | .n_sectors = (_n_sectors), \ |
| 949 | .page_size = 256, \ | 894 | .page_size = 256, \ |
| 950 | .flags = (_flags), | 895 | .flags = (_flags), |
| 951 | 896 | ||
| 952 | #define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 897 | #define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
| 953 | .id = { \ | 898 | .id = { \ |
| 954 | ((_jedec_id) >> 16) & 0xff, \ | 899 | ((_jedec_id) >> 16) & 0xff, \ |
| 955 | ((_jedec_id) >> 8) & 0xff, \ | 900 | ((_jedec_id) >> 8) & 0xff, \ |
| 956 | (_jedec_id) & 0xff, \ | 901 | (_jedec_id) & 0xff, \ |
| 957 | ((_ext_id) >> 16) & 0xff, \ | 902 | ((_ext_id) >> 16) & 0xff, \ |
| 958 | ((_ext_id) >> 8) & 0xff, \ | 903 | ((_ext_id) >> 8) & 0xff, \ |
| 959 | (_ext_id) & 0xff, \ | 904 | (_ext_id) & 0xff, \ |
| 960 | }, \ | 905 | }, \ |
| 961 | .id_len = 6, \ | 906 | .id_len = 6, \ |
| 962 | .sector_size = (_sector_size), \ | 907 | .sector_size = (_sector_size), \ |
| 963 | .n_sectors = (_n_sectors), \ | 908 | .n_sectors = (_n_sectors), \ |
| 964 | .page_size = 256, \ | 909 | .page_size = 256, \ |
| 965 | .flags = (_flags), | 910 | .flags = (_flags), |
| 966 | 911 | ||
| 967 | /* NOTE: double check command sets and memory organization when you add | 912 | /* NOTE: double check command sets and memory organization when you add |
| 968 | * more nor chips. This current list focusses on newer chips, which | 913 | * more nor chips. This current list focusses on newer chips, which |
| 969 | * have been converging on command sets which including JEDEC ID. | 914 | * have been converging on command sets which including JEDEC ID. |
| 970 | * | 915 | * |
| 971 | * All newly added entries should describe *hardware* and should use SECT_4K | 916 | * All newly added entries should describe *hardware* and should use SECT_4K |
| 972 | * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage | 917 | * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage |
| 973 | * scenarios excluding small sectors there is config option that can be | 918 | * scenarios excluding small sectors there is config option that can be |
| 974 | * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. | 919 | * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. |
| 975 | * For historical (and compatibility) reasons (before we got above config) some | 920 | * For historical (and compatibility) reasons (before we got above config) some |
| 976 | * old entries may be missing 4K flag. | 921 | * old entries may be missing 4K flag. |
| 977 | */ | 922 | */ |
| 978 | const struct flash_info spi_nor_ids[] = { | 923 | const struct flash_info spi_nor_ids[] = { |
| 979 | #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ | 924 | #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ |
| 980 | /* Atmel -- some are (confusingly) marketed as "DataFlash" */ | 925 | /* Atmel -- some are (confusingly) marketed as "DataFlash" */ |
| 981 | { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, | 926 | { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, |
| 982 | { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, | 927 | { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, |
| 983 | 928 | ||
| 984 | { "at45db011d", INFO(0x1f2200, 0, 64 * 1024, 4, SECT_4K) }, | 929 | { "at45db011d", INFO(0x1f2200, 0, 64 * 1024, 4, SECT_4K) }, |
| 985 | { "at45db021d", INFO(0x1f2300, 0, 64 * 1024, 8, SECT_4K) }, | 930 | { "at45db021d", INFO(0x1f2300, 0, 64 * 1024, 8, SECT_4K) }, |
| 986 | { "at45db041d", INFO(0x1f2400, 0, 64 * 1024, 8, SECT_4K) }, | 931 | { "at45db041d", INFO(0x1f2400, 0, 64 * 1024, 8, SECT_4K) }, |
| 987 | { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, | 932 | { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, |
| 988 | { "at45db161d", INFO(0x1f2600, 0, 64 * 1024, 32, SECT_4K) }, | 933 | { "at45db161d", INFO(0x1f2600, 0, 64 * 1024, 32, SECT_4K) }, |
| 989 | { "at45db321d", INFO(0x1f2700, 0, 64 * 1024, 64, SECT_4K) }, | 934 | { "at45db321d", INFO(0x1f2700, 0, 64 * 1024, 64, SECT_4K) }, |
| 990 | { "at45db641d", INFO(0x1f2800, 0, 64 * 1024, 128, SECT_4K) }, | 935 | { "at45db641d", INFO(0x1f2800, 0, 64 * 1024, 128, SECT_4K) }, |
| 991 | { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, | 936 | { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, |
| 992 | #endif | 937 | #endif |
| 993 | #ifdef CONFIG_SPI_FLASH_EON /* EON */ | 938 | #ifdef CONFIG_SPI_FLASH_EON /* EON */ |
| 994 | /* EON -- en25xxx */ | 939 | /* EON -- en25xxx */ |
| 995 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | 940 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, |
| 996 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, | 941 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, |
| 997 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, | 942 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, |
| 998 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, | 943 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, |
| 999 | #endif | 944 | #endif |
| 1000 | #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ | 945 | #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ |
| 1001 | /* GigaDevice */ | 946 | /* GigaDevice */ |
| 1002 | { | 947 | { |
| 1003 | "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, | 948 | "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, |
| 1004 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 949 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1005 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 950 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1006 | }, | 951 | }, |
| 1007 | { | 952 | { |
| 1008 | "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, | 953 | "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, |
| 1009 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 954 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1010 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 955 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1011 | }, | 956 | }, |
| 1012 | { | 957 | { |
| 1013 | "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64, | 958 | "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64, |
| 1014 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 959 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1015 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 960 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1016 | }, | 961 | }, |
| 1017 | { | 962 | { |
| 1018 | "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, | 963 | "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, |
| 1019 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 964 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1020 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 965 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1021 | }, | 966 | }, |
| 1022 | #endif | 967 | #endif |
| 1023 | #ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ | 968 | #ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ |
| 1024 | /* ISSI */ | 969 | /* ISSI */ |
| 1025 | { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, | 970 | { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, |
| 1026 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 971 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1027 | { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64, 0) }, | 972 | { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64, 0) }, |
| 1028 | { "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128, 0) }, | 973 | { "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128, 0) }, |
| 1029 | { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, | 974 | { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, |
| 1030 | SECT_4K | SPI_NOR_DUAL_READ) }, | 975 | SECT_4K | SPI_NOR_DUAL_READ) }, |
| 1031 | { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512, | 976 | { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512, |
| 1032 | SECT_4K | SPI_NOR_DUAL_READ) }, | 977 | SECT_4K | SPI_NOR_DUAL_READ) }, |
| 1033 | { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64, | 978 | { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64, |
| 1034 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 979 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1035 | { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128, | 980 | { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128, |
| 1036 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 981 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1037 | { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256, | 982 | { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256, |
| 1038 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 983 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1039 | #endif | 984 | #endif |
| 1040 | #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ | 985 | #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ |
| 1041 | /* Macronix */ | 986 | /* Macronix */ |
| 1042 | { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, | 987 | { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, |
| 1043 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 988 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
| 1044 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | 989 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, |
| 1045 | { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, | 990 | { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, |
| 1046 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, | 991 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, |
| 1047 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, | 992 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1048 | { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, | 993 | { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, |
| 1049 | { "mx25u1635e", INFO(0xc22535, 0, 64 * 1024, 32, SECT_4K) }, | 994 | { "mx25u1635e", INFO(0xc22535, 0, 64 * 1024, 32, SECT_4K) }, |
| 1050 | { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, | 995 | { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, |
| 1051 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, | 996 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, |
| 1052 | { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, | 997 | { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, |
| 1053 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 998 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1054 | { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, | 999 | { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, |
| 1055 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, | 1000 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, |
| 1056 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | 1001 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, |
| 1057 | { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | 1002 | { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, |
| 1058 | { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1003 | { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1059 | { "mx25l1633e", INFO(0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, | 1004 | { "mx25l1633e", INFO(0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, |
| 1060 | #endif | 1005 | #endif |
| 1061 | 1006 | ||
| 1062 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ | 1007 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ |
| 1063 | /* Micron */ | 1008 | /* Micron */ |
| 1064 | { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) }, | 1009 | { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1065 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, | 1010 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, |
| 1066 | { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, | 1011 | { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, |
| 1067 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, | 1012 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1068 | { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, | 1013 | { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1069 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, | 1014 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1070 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, | 1015 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1071 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1016 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1072 | { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, | 1017 | { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 1073 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, | 1018 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 1074 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, | 1019 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 1075 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | 1020 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 1076 | { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | 1021 | { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 1077 | { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, | 1022 | { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, |
| 1078 | #endif | 1023 | #endif |
| 1079 | #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ | 1024 | #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ |
| 1080 | /* Spansion/Cypress -- single (large) sector size only, at least | 1025 | /* Spansion/Cypress -- single (large) sector size only, at least |
| 1081 | * for the chips listed here (without boot sectors). | 1026 | * for the chips listed here (without boot sectors). |
| 1082 | */ | 1027 | */ |
| 1083 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1028 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1084 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1029 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1085 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, | 1030 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, |
| 1086 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1031 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1087 | { "s25fl512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1032 | { "s25fl512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1088 | { "s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1033 | { "s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1089 | { "s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1034 | { "s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1090 | { "s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1035 | { "s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1091 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 1036 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
| 1092 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 1037 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
| 1093 | { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1038 | { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1094 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1039 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1095 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1040 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1096 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, | 1041 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, |
| 1097 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, | 1042 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, |
| 1098 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, | 1043 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, |
| 1099 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, | 1044 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, |
| 1100 | { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1045 | { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1101 | { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, | 1046 | { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1102 | { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) }, | 1047 | { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) }, |
| 1103 | { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, | 1048 | { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, |
| 1104 | #endif | 1049 | #endif |
| 1105 | #ifdef CONFIG_SPI_FLASH_SST /* SST */ | 1050 | #ifdef CONFIG_SPI_FLASH_SST /* SST */ |
| 1106 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ | 1051 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ |
| 1107 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, | 1052 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, |
| 1108 | { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, | 1053 | { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, |
| 1109 | { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, | 1054 | { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, |
| 1110 | { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, | 1055 | { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, |
| 1111 | { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, | 1056 | { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, |
| 1112 | { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, | 1057 | { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, |
| 1113 | { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, | 1058 | { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, |
| 1114 | { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, | 1059 | { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, |
| 1115 | { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, | 1060 | { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, |
| 1116 | { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) }, | 1061 | { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) }, |
| 1117 | { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, | 1062 | { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, |
| 1118 | { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, | 1063 | { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, |
| 1119 | { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1064 | { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1120 | { "sst26wf016", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K) }, | 1065 | { "sst26wf016", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K) }, |
| 1121 | { "sst26wf032", INFO(0xbf2622, 0, 64 * 1024, 64, SECT_4K) }, | 1066 | { "sst26wf032", INFO(0xbf2622, 0, 64 * 1024, 64, SECT_4K) }, |
| 1122 | { "sst26wf064", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K) }, | 1067 | { "sst26wf064", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K) }, |
| 1123 | #endif | 1068 | #endif |
| 1124 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ | 1069 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ |
| 1125 | /* ST Microelectronics -- newer production may have feature updates */ | 1070 | /* ST Microelectronics -- newer production may have feature updates */ |
| 1126 | { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, | 1071 | { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, |
| 1127 | { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, | 1072 | { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, |
| 1128 | { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, | 1073 | { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, |
| 1129 | { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, | 1074 | { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, |
| 1130 | { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, | 1075 | { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, |
| 1131 | { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, | 1076 | { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, |
| 1132 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, | 1077 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, |
| 1133 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, | 1078 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, |
| 1134 | { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, | 1079 | { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, |
| 1135 | { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1080 | { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1136 | { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, | 1081 | { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, |
| 1137 | #endif | 1082 | #endif |
| 1138 | #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ | 1083 | #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ |
| 1139 | /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ | 1084 | /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ |
| 1140 | { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, | 1085 | { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, |
| 1141 | { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, | 1086 | { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, |
| 1142 | { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, | 1087 | { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, |
| 1143 | { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, | 1088 | { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, |
| 1144 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, | 1089 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, |
| 1145 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, | 1090 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, |
| 1146 | { | 1091 | { |
| 1147 | "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, | 1092 | "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, |
| 1148 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1093 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1149 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1094 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1150 | }, | 1095 | }, |
| 1151 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, | 1096 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, |
| 1152 | { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, | 1097 | { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, |
| 1153 | { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, | 1098 | { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, |
| 1154 | { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) }, | 1099 | { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) }, |
| 1155 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | 1100 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, |
| 1156 | { | 1101 | { |
| 1157 | "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, | 1102 | "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, |
| 1158 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1103 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1159 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1104 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1160 | }, | 1105 | }, |
| 1161 | { | 1106 | { |
| 1162 | "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64, | 1107 | "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64, |
| 1163 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1108 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1164 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1109 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1165 | }, | 1110 | }, |
| 1166 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 1111 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1167 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 1112 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
| 1168 | { | 1113 | { |
| 1169 | "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, | 1114 | "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, |
| 1170 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1115 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1171 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1116 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1172 | }, | 1117 | }, |
| 1173 | { | 1118 | { |
| 1174 | "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, | 1119 | "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, |
| 1175 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | 1120 | SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | |
| 1176 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) | 1121 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) |
| 1177 | }, | 1122 | }, |
| 1178 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, | 1123 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, |
| 1179 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | 1124 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, |
| 1180 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, | 1125 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, |
| 1181 | { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1126 | { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1182 | { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, | 1127 | { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, |
| 1183 | SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, | 1128 | SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, |
| 1184 | #endif | 1129 | #endif |
| 1185 | #ifdef CONFIG_SPI_FLASH_XMC | 1130 | #ifdef CONFIG_SPI_FLASH_XMC |
| 1186 | /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ | 1131 | /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ |
| 1187 | { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1132 | { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1188 | { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 1133 | { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
| 1189 | #endif | 1134 | #endif |
| 1190 | { }, | 1135 | { }, |
| 1191 | }; | 1136 | }; |
| 1192 | 1137 | ||
| 1193 | static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) | 1138 | static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) |
| 1194 | { | 1139 | { |
| 1195 | int tmp; | 1140 | int tmp; |
| 1196 | u8 id[SPI_NOR_MAX_ID_LEN]; | 1141 | u8 id[SPI_NOR_MAX_ID_LEN]; |
| 1197 | const struct flash_info *info; | 1142 | const struct flash_info *info; |
| 1198 | 1143 | ||
| 1199 | if (!ARRAY_SIZE(spi_nor_ids)) | 1144 | if (!ARRAY_SIZE(spi_nor_ids)) |
| 1200 | return ERR_PTR(-ENODEV); | 1145 | return ERR_PTR(-ENODEV); |
| 1201 | 1146 | ||
| 1202 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); | 1147 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); |
| 1203 | if (tmp < 0) { | 1148 | if (tmp < 0) { |
| 1204 | dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); | 1149 | dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); |
| 1205 | return ERR_PTR(tmp); | 1150 | return ERR_PTR(tmp); |
| 1206 | } | 1151 | } |
| 1207 | 1152 | ||
| 1208 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { | 1153 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { |
| 1209 | info = &spi_nor_ids[tmp]; | 1154 | info = &spi_nor_ids[tmp]; |
| 1210 | if (info->id_len) { | 1155 | if (info->id_len) { |
| 1211 | if (!memcmp(info->id, id, info->id_len)) | 1156 | if (!memcmp(info->id, id, info->id_len)) |
| 1212 | return &spi_nor_ids[tmp]; | 1157 | return &spi_nor_ids[tmp]; |
| 1213 | } | 1158 | } |
| 1214 | } | 1159 | } |
| 1215 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", | 1160 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", |
| 1216 | id[0], id[1], id[2]); | 1161 | id[0], id[1], id[2]); |
| 1217 | return ERR_PTR(-ENODEV); | 1162 | return ERR_PTR(-ENODEV); |
| 1218 | } | 1163 | } |
| 1219 | 1164 | ||
| 1220 | static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, | 1165 | static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, |
| 1221 | size_t *retlen, u_char *buf) | 1166 | size_t *retlen, u_char *buf) |
| 1222 | { | 1167 | { |
| 1223 | struct spi_nor *nor = mtd_to_spi_nor(mtd); | 1168 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 1224 | int ret; | 1169 | int ret; |
| 1225 | 1170 | ||
| 1226 | dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); | 1171 | dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); |
| 1227 | 1172 | ||
| 1228 | while (len) { | 1173 | while (len) { |
| 1229 | loff_t addr = from; | 1174 | loff_t addr = from; |
| 1230 | size_t read_len = len; | 1175 | size_t read_len = len; |
| 1231 | 1176 | ||
| 1232 | #ifdef CONFIG_SPI_FLASH_BAR | 1177 | #ifdef CONFIG_SPI_FLASH_BAR |
| 1233 | u32 remain_len; | 1178 | u32 remain_len; |
| 1234 | 1179 | ||
| 1235 | ret = write_bar(nor, addr); | 1180 | ret = write_bar(nor, addr); |
| 1236 | if (ret < 0) | 1181 | if (ret < 0) |
| 1237 | return log_ret(ret); | 1182 | return log_ret(ret); |
| 1238 | remain_len = (SZ_16M * (nor->bank_curr + 1)) - addr; | 1183 | remain_len = (SZ_16M * (nor->bank_curr + 1)) - addr; |
| 1239 | 1184 | ||
| 1240 | if (len < remain_len) | 1185 | if (len < remain_len) |
| 1241 | read_len = len; | 1186 | read_len = len; |
| 1242 | else | 1187 | else |
| 1243 | read_len = remain_len; | 1188 | read_len = remain_len; |
| 1244 | #endif | 1189 | #endif |
| 1245 | 1190 | ||
| 1246 | ret = nor->read(nor, addr, read_len, buf); | 1191 | ret = nor->read(nor, addr, read_len, buf); |
| 1247 | if (ret == 0) { | 1192 | if (ret == 0) { |
| 1248 | /* We shouldn't see 0-length reads */ | 1193 | /* We shouldn't see 0-length reads */ |
| 1249 | ret = -EIO; | 1194 | ret = -EIO; |
| 1250 | goto read_err; | 1195 | goto read_err; |
| 1251 | } | 1196 | } |
| 1252 | if (ret < 0) | 1197 | if (ret < 0) |
| 1253 | goto read_err; | 1198 | goto read_err; |
| 1254 | 1199 | ||
| 1255 | *retlen += ret; | 1200 | *retlen += ret; |
| 1256 | buf += ret; | 1201 | buf += ret; |
| 1257 | from += ret; | 1202 | from += ret; |
| 1258 | len -= ret; | 1203 | len -= ret; |
| 1259 | } | 1204 | } |
| 1260 | ret = 0; | 1205 | ret = 0; |
| 1261 | 1206 | ||
| 1262 | read_err: | 1207 | read_err: |
| 1263 | #ifdef CONFIG_SPI_FLASH_BAR | 1208 | #ifdef CONFIG_SPI_FLASH_BAR |
| 1264 | ret = clean_bar(nor); | 1209 | ret = clean_bar(nor); |
| 1265 | #endif | 1210 | #endif |
| 1266 | return ret; | 1211 | return ret; |
| 1267 | } | 1212 | } |
| 1268 | 1213 | ||
| 1269 | #ifdef CONFIG_SPI_FLASH_SST | 1214 | #ifdef CONFIG_SPI_FLASH_SST |
| 1270 | static int sst_write_byteprogram(struct spi_nor *nor, loff_t to, size_t len, | 1215 | static int sst_write_byteprogram(struct spi_nor *nor, loff_t to, size_t len, |
| 1271 | size_t *retlen, const u_char *buf) | 1216 | size_t *retlen, const u_char *buf) |
| 1272 | { | 1217 | { |
| 1273 | size_t actual; | 1218 | size_t actual; |
| 1274 | int ret = 0; | 1219 | int ret = 0; |
| 1275 | 1220 | ||
| 1276 | for (actual = 0; actual < len; actual++) { | 1221 | for (actual = 0; actual < len; actual++) { |
| 1277 | nor->program_opcode = SPINOR_OP_BP; | 1222 | nor->program_opcode = SPINOR_OP_BP; |
| 1278 | 1223 | ||
| 1279 | write_enable(nor); | 1224 | write_enable(nor); |
| 1280 | /* write one byte. */ | 1225 | /* write one byte. */ |
| 1281 | ret = nor->write(nor, to, 1, buf + actual); | 1226 | ret = nor->write(nor, to, 1, buf + actual); |
| 1282 | if (ret < 0) | 1227 | if (ret < 0) |
| 1283 | goto sst_write_err; | 1228 | goto sst_write_err; |
| 1284 | ret = spi_nor_wait_till_ready(nor); | 1229 | ret = spi_nor_wait_till_ready(nor); |
| 1285 | if (ret) | 1230 | if (ret) |
| 1286 | goto sst_write_err; | 1231 | goto sst_write_err; |
| 1287 | to++; | 1232 | to++; |
| 1288 | } | 1233 | } |
| 1289 | 1234 | ||
| 1290 | sst_write_err: | 1235 | sst_write_err: |
| 1291 | write_disable(nor); | 1236 | write_disable(nor); |
| 1292 | return ret; | 1237 | return ret; |
| 1293 | } | 1238 | } |
| 1294 | 1239 | ||
| 1295 | static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | 1240 | static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, |
| 1296 | size_t *retlen, const u_char *buf) | 1241 | size_t *retlen, const u_char *buf) |
| 1297 | { | 1242 | { |
| 1298 | struct spi_nor *nor = mtd_to_spi_nor(mtd); | 1243 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 1299 | struct spi_slave *spi = nor->spi; | 1244 | struct spi_slave *spi = nor->spi; |
| 1300 | size_t actual; | 1245 | size_t actual; |
| 1301 | int ret; | 1246 | int ret; |
| 1302 | 1247 | ||
| 1303 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); | 1248 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); |
| 1304 | if (spi->mode & SPI_TX_BYTE) | 1249 | if (spi->mode & SPI_TX_BYTE) |
| 1305 | return sst_write_byteprogram(nor, to, len, retlen, buf); | 1250 | return sst_write_byteprogram(nor, to, len, retlen, buf); |
| 1306 | 1251 | ||
| 1307 | write_enable(nor); | 1252 | write_enable(nor); |
| 1308 | 1253 | ||
| 1309 | nor->sst_write_second = false; | 1254 | nor->sst_write_second = false; |
| 1310 | 1255 | ||
| 1311 | actual = to % 2; | 1256 | actual = to % 2; |
| 1312 | /* Start write from odd address. */ | 1257 | /* Start write from odd address. */ |
| 1313 | if (actual) { | 1258 | if (actual) { |
| 1314 | nor->program_opcode = SPINOR_OP_BP; | 1259 | nor->program_opcode = SPINOR_OP_BP; |
| 1315 | 1260 | ||
| 1316 | /* write one byte. */ | 1261 | /* write one byte. */ |
| 1317 | ret = nor->write(nor, to, 1, buf); | 1262 | ret = nor->write(nor, to, 1, buf); |
| 1318 | if (ret < 0) | 1263 | if (ret < 0) |
| 1319 | goto sst_write_err; | 1264 | goto sst_write_err; |
| 1320 | ret = spi_nor_wait_till_ready(nor); | 1265 | ret = spi_nor_wait_till_ready(nor); |
| 1321 | if (ret) | 1266 | if (ret) |
| 1322 | goto sst_write_err; | 1267 | goto sst_write_err; |
| 1323 | } | 1268 | } |
| 1324 | to += actual; | 1269 | to += actual; |
| 1325 | 1270 | ||
| 1326 | /* Write out most of the data here. */ | 1271 | /* Write out most of the data here. */ |
| 1327 | for (; actual < len - 1; actual += 2) { | 1272 | for (; actual < len - 1; actual += 2) { |
| 1328 | nor->program_opcode = SPINOR_OP_AAI_WP; | 1273 | nor->program_opcode = SPINOR_OP_AAI_WP; |
| 1329 | 1274 | ||
| 1330 | /* write two bytes. */ | 1275 | /* write two bytes. */ |
| 1331 | ret = nor->write(nor, to, 2, buf + actual); | 1276 | ret = nor->write(nor, to, 2, buf + actual); |
| 1332 | if (ret < 0) | 1277 | if (ret < 0) |
| 1333 | goto sst_write_err; | 1278 | goto sst_write_err; |
| 1334 | ret = spi_nor_wait_till_ready(nor); | 1279 | ret = spi_nor_wait_till_ready(nor); |
| 1335 | if (ret) | 1280 | if (ret) |
| 1336 | goto sst_write_err; | 1281 | goto sst_write_err; |
| 1337 | to += 2; | 1282 | to += 2; |
| 1338 | nor->sst_write_second = true; | 1283 | nor->sst_write_second = true; |
| 1339 | } | 1284 | } |
| 1340 | nor->sst_write_second = false; | 1285 | nor->sst_write_second = false; |
| 1341 | 1286 | ||
| 1342 | write_disable(nor); | 1287 | write_disable(nor); |
| 1343 | ret = spi_nor_wait_till_ready(nor); | 1288 | ret = spi_nor_wait_till_ready(nor); |
| 1344 | if (ret) | 1289 | if (ret) |
| 1345 | goto sst_write_err; | 1290 | goto sst_write_err; |
| 1346 | 1291 | ||
| 1347 | /* Write out trailing byte if it exists. */ | 1292 | /* Write out trailing byte if it exists. */ |
| 1348 | if (actual != len) { | 1293 | if (actual != len) { |
| 1349 | write_enable(nor); | 1294 | write_enable(nor); |
| 1350 | 1295 | ||
| 1351 | nor->program_opcode = SPINOR_OP_BP; | 1296 | nor->program_opcode = SPINOR_OP_BP; |
| 1352 | ret = nor->write(nor, to, 1, buf + actual); | 1297 | ret = nor->write(nor, to, 1, buf + actual); |
| 1353 | if (ret < 0) | 1298 | if (ret < 0) |
| 1354 | goto sst_write_err; | 1299 | goto sst_write_err; |
| 1355 | ret = spi_nor_wait_till_ready(nor); | 1300 | ret = spi_nor_wait_till_ready(nor); |
| 1356 | if (ret) | 1301 | if (ret) |
| 1357 | goto sst_write_err; | 1302 | goto sst_write_err; |
| 1358 | write_disable(nor); | 1303 | write_disable(nor); |
| 1359 | actual += 1; | 1304 | actual += 1; |
| 1360 | } | 1305 | } |
| 1361 | sst_write_err: | 1306 | sst_write_err: |
| 1362 | *retlen += actual; | 1307 | *retlen += actual; |
| 1363 | return ret; | 1308 | return ret; |
| 1364 | } | 1309 | } |
| 1365 | #endif | 1310 | #endif |
| 1366 | /* | 1311 | /* |
| 1367 | * Write an address range to the nor chip. Data must be written in | 1312 | * Write an address range to the nor chip. Data must be written in |
| 1368 | * FLASH_PAGESIZE chunks. The address range may be any size provided | 1313 | * FLASH_PAGESIZE chunks. The address range may be any size provided |
| 1369 | * it is within the physical boundaries. | 1314 | * it is within the physical boundaries. |
| 1370 | */ | 1315 | */ |
| 1371 | static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, | 1316 | static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, |
| 1372 | size_t *retlen, const u_char *buf) | 1317 | size_t *retlen, const u_char *buf) |
| 1373 | { | 1318 | { |
| 1374 | struct spi_nor *nor = mtd_to_spi_nor(mtd); | 1319 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| 1375 | size_t page_offset, page_remain, i; | 1320 | size_t page_offset, page_remain, i; |
| 1376 | ssize_t ret; | 1321 | ssize_t ret; |
| 1377 | 1322 | ||
| 1378 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); | 1323 | dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); |
| 1379 | 1324 | ||
| 1380 | for (i = 0; i < len; ) { | 1325 | for (i = 0; i < len; ) { |
| 1381 | ssize_t written; | 1326 | ssize_t written; |
| 1382 | loff_t addr = to + i; | 1327 | loff_t addr = to + i; |
| 1383 | 1328 | ||
| 1384 | /* | 1329 | /* |
| 1385 | * If page_size is a power of two, the offset can be quickly | 1330 | * If page_size is a power of two, the offset can be quickly |
| 1386 | * calculated with an AND operation. On the other cases we | 1331 | * calculated with an AND operation. On the other cases we |
| 1387 | * need to do a modulus operation (more expensive). | 1332 | * need to do a modulus operation (more expensive). |
| 1388 | * Power of two numbers have only one bit set and we can use | 1333 | * Power of two numbers have only one bit set and we can use |
| 1389 | * the instruction hweight32 to detect if we need to do a | 1334 | * the instruction hweight32 to detect if we need to do a |
| 1390 | * modulus (do_div()) or not. | 1335 | * modulus (do_div()) or not. |
| 1391 | */ | 1336 | */ |
| 1392 | if (hweight32(nor->page_size) == 1) { | 1337 | if (hweight32(nor->page_size) == 1) { |
| 1393 | page_offset = addr & (nor->page_size - 1); | 1338 | page_offset = addr & (nor->page_size - 1); |
| 1394 | } else { | 1339 | } else { |
| 1395 | u64 aux = addr; | 1340 | u64 aux = addr; |
| 1396 | 1341 | ||
| 1397 | page_offset = do_div(aux, nor->page_size); | 1342 | page_offset = do_div(aux, nor->page_size); |
| 1398 | } | 1343 | } |
| 1399 | /* the size of data remaining on the first page */ | 1344 | /* the size of data remaining on the first page */ |
| 1400 | page_remain = min_t(size_t, | 1345 | page_remain = min_t(size_t, |
| 1401 | nor->page_size - page_offset, len - i); | 1346 | nor->page_size - page_offset, len - i); |
| 1402 | 1347 | ||
| 1403 | #ifdef CONFIG_SPI_FLASH_BAR | 1348 | #ifdef CONFIG_SPI_FLASH_BAR |
| 1404 | ret = write_bar(nor, addr); | 1349 | ret = write_bar(nor, addr); |
| 1405 | if (ret < 0) | 1350 | if (ret < 0) |
| 1406 | return ret; | 1351 | return ret; |
| 1407 | #endif | 1352 | #endif |
| 1408 | write_enable(nor); | 1353 | write_enable(nor); |
| 1409 | ret = nor->write(nor, addr, page_remain, buf + i); | 1354 | ret = nor->write(nor, addr, page_remain, buf + i); |
| 1410 | if (ret < 0) | 1355 | if (ret < 0) |
| 1411 | goto write_err; | 1356 | goto write_err; |
| 1412 | written = ret; | 1357 | written = ret; |
| 1413 | 1358 | ||
| 1414 | ret = spi_nor_wait_till_ready(nor); | 1359 | ret = spi_nor_wait_till_ready(nor); |
| 1415 | if (ret) | 1360 | if (ret) |
| 1416 | goto write_err; | 1361 | goto write_err; |
| 1417 | *retlen += written; | 1362 | *retlen += written; |
| 1418 | i += written; | 1363 | i += written; |
| 1419 | if (written != page_remain) { | 1364 | if (written != page_remain) { |
| 1420 | ret = -EIO; | 1365 | ret = -EIO; |
| 1421 | goto write_err; | 1366 | goto write_err; |
| 1422 | } | 1367 | } |
| 1423 | } | 1368 | } |
| 1424 | 1369 | ||
| 1425 | write_err: | 1370 | write_err: |
| 1426 | #ifdef CONFIG_SPI_FLASH_BAR | 1371 | #ifdef CONFIG_SPI_FLASH_BAR |
| 1427 | ret = clean_bar(nor); | 1372 | ret = clean_bar(nor); |
| 1428 | #endif | 1373 | #endif |
| 1429 | return ret; | 1374 | return ret; |
| 1430 | } | 1375 | } |
| 1431 | 1376 | ||
| 1432 | #ifdef CONFIG_SPI_FLASH_MACRONIX | 1377 | #ifdef CONFIG_SPI_FLASH_MACRONIX |
| 1433 | /** | 1378 | /** |
| 1434 | * macronix_quad_enable() - set QE bit in Status Register. | 1379 | * macronix_quad_enable() - set QE bit in Status Register. |
| 1435 | * @nor: pointer to a 'struct spi_nor' | 1380 | * @nor: pointer to a 'struct spi_nor' |
| 1436 | * | 1381 | * |
| 1437 | * Set the Quad Enable (QE) bit in the Status Register. | 1382 | * Set the Quad Enable (QE) bit in the Status Register. |
| 1438 | * | 1383 | * |
| 1439 | * bit 6 of the Status Register is the QE bit for Macronix like QSPI memories. | 1384 | * bit 6 of the Status Register is the QE bit for Macronix like QSPI memories. |
| 1440 | * | 1385 | * |
| 1441 | * Return: 0 on success, -errno otherwise. | 1386 | * Return: 0 on success, -errno otherwise. |
| 1442 | */ | 1387 | */ |
| 1443 | static int macronix_quad_enable(struct spi_nor *nor) | 1388 | static int macronix_quad_enable(struct spi_nor *nor) |
| 1444 | { | 1389 | { |
| 1445 | int ret, val; | 1390 | int ret, val; |
| 1446 | 1391 | ||
| 1447 | val = read_sr(nor); | 1392 | val = read_sr(nor); |
| 1448 | if (val < 0) | 1393 | if (val < 0) |
| 1449 | return val; | 1394 | return val; |
| 1450 | if (val & SR_QUAD_EN_MX) | 1395 | if (val & SR_QUAD_EN_MX) |
| 1451 | return 0; | 1396 | return 0; |
| 1452 | 1397 | ||
| 1453 | write_enable(nor); | 1398 | write_enable(nor); |
| 1454 | 1399 | ||
| 1455 | write_sr(nor, val | SR_QUAD_EN_MX); | 1400 | write_sr(nor, val | SR_QUAD_EN_MX); |
| 1456 | 1401 | ||
| 1457 | ret = spi_nor_wait_till_ready(nor); | 1402 | ret = spi_nor_wait_till_ready(nor); |
| 1458 | if (ret) | 1403 | if (ret) |
| 1459 | return ret; | 1404 | return ret; |
| 1460 | 1405 | ||
| 1461 | ret = read_sr(nor); | 1406 | ret = read_sr(nor); |
| 1462 | if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { | 1407 | if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { |
| 1463 | dev_err(nor->dev, "Macronix Quad bit not set\n"); | 1408 | dev_err(nor->dev, "Macronix Quad bit not set\n"); |
| 1464 | return -EINVAL; | 1409 | return -EINVAL; |
| 1465 | } | 1410 | } |
| 1466 | 1411 | ||
| 1467 | return 0; | 1412 | return 0; |
| 1468 | } | 1413 | } |
| 1469 | #endif | 1414 | #endif |
| 1470 | 1415 | ||
| 1471 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 1416 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
| 1472 | /* | 1417 | /* |
| 1473 | * Write status Register and configuration register with 2 bytes | 1418 | * Write status Register and configuration register with 2 bytes |
| 1474 | * The first byte will be written to the status register, while the | 1419 | * The first byte will be written to the status register, while the |
| 1475 | * second byte will be written to the configuration register. | 1420 | * second byte will be written to the configuration register. |
| 1476 | * Return negative if error occurred. | 1421 | * Return negative if error occurred. |
| 1477 | */ | 1422 | */ |
| 1478 | static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) | 1423 | static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) |
| 1479 | { | 1424 | { |
| 1480 | int ret; | 1425 | int ret; |
| 1481 | 1426 | ||
| 1482 | write_enable(nor); | 1427 | write_enable(nor); |
| 1483 | 1428 | ||
| 1484 | ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); | 1429 | ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); |
| 1485 | if (ret < 0) { | 1430 | if (ret < 0) { |
| 1486 | dev_dbg(nor->dev, | 1431 | dev_dbg(nor->dev, |
| 1487 | "error while writing configuration register\n"); | 1432 | "error while writing configuration register\n"); |
| 1488 | return -EINVAL; | 1433 | return -EINVAL; |
| 1489 | } | 1434 | } |
| 1490 | 1435 | ||
| 1491 | ret = spi_nor_wait_till_ready(nor); | 1436 | ret = spi_nor_wait_till_ready(nor); |
| 1492 | if (ret) { | 1437 | if (ret) { |
| 1493 | dev_dbg(nor->dev, | 1438 | dev_dbg(nor->dev, |
| 1494 | "timeout while writing configuration register\n"); | 1439 | "timeout while writing configuration register\n"); |
| 1495 | return ret; | 1440 | return ret; |
| 1496 | } | 1441 | } |
| 1497 | 1442 | ||
| 1498 | return 0; | 1443 | return 0; |
| 1499 | } | 1444 | } |
| 1500 | 1445 | ||
| 1501 | /** | 1446 | /** |
| 1502 | * spansion_read_cr_quad_enable() - set QE bit in Configuration Register. | 1447 | * spansion_read_cr_quad_enable() - set QE bit in Configuration Register. |
| 1503 | * @nor: pointer to a 'struct spi_nor' | 1448 | * @nor: pointer to a 'struct spi_nor' |
| 1504 | * | 1449 | * |
| 1505 | * Set the Quad Enable (QE) bit in the Configuration Register. | 1450 | * Set the Quad Enable (QE) bit in the Configuration Register. |
| 1506 | * This function should be used with QSPI memories supporting the Read | 1451 | * This function should be used with QSPI memories supporting the Read |
| 1507 | * Configuration Register (35h) instruction. | 1452 | * Configuration Register (35h) instruction. |
| 1508 | * | 1453 | * |
| 1509 | * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI | 1454 | * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI |
| 1510 | * memories. | 1455 | * memories. |
| 1511 | * | 1456 | * |
| 1512 | * Return: 0 on success, -errno otherwise. | 1457 | * Return: 0 on success, -errno otherwise. |
| 1513 | */ | 1458 | */ |
| 1514 | static int spansion_read_cr_quad_enable(struct spi_nor *nor) | 1459 | static int spansion_read_cr_quad_enable(struct spi_nor *nor) |
| 1515 | { | 1460 | { |
| 1516 | u8 sr_cr[2]; | 1461 | u8 sr_cr[2]; |
| 1517 | int ret; | 1462 | int ret; |
| 1518 | 1463 | ||
| 1519 | /* Check current Quad Enable bit value. */ | 1464 | /* Check current Quad Enable bit value. */ |
| 1520 | ret = read_cr(nor); | 1465 | ret = read_cr(nor); |
| 1521 | if (ret < 0) { | 1466 | if (ret < 0) { |
| 1522 | dev_dbg(dev, "error while reading configuration register\n"); | 1467 | dev_dbg(dev, "error while reading configuration register\n"); |
| 1523 | return -EINVAL; | 1468 | return -EINVAL; |
| 1524 | } | 1469 | } |
| 1525 | 1470 | ||
| 1526 | if (ret & CR_QUAD_EN_SPAN) | 1471 | if (ret & CR_QUAD_EN_SPAN) |
| 1527 | return 0; | 1472 | return 0; |
| 1528 | 1473 | ||
| 1529 | sr_cr[1] = ret | CR_QUAD_EN_SPAN; | 1474 | sr_cr[1] = ret | CR_QUAD_EN_SPAN; |
| 1530 | 1475 | ||
| 1531 | /* Keep the current value of the Status Register. */ | 1476 | /* Keep the current value of the Status Register. */ |
| 1532 | ret = read_sr(nor); | 1477 | ret = read_sr(nor); |
| 1533 | if (ret < 0) { | 1478 | if (ret < 0) { |
| 1534 | dev_dbg(dev, "error while reading status register\n"); | 1479 | dev_dbg(dev, "error while reading status register\n"); |
| 1535 | return -EINVAL; | 1480 | return -EINVAL; |
| 1536 | } | 1481 | } |
| 1537 | sr_cr[0] = ret; | 1482 | sr_cr[0] = ret; |
| 1538 | 1483 | ||
| 1539 | ret = write_sr_cr(nor, sr_cr); | 1484 | ret = write_sr_cr(nor, sr_cr); |
| 1540 | if (ret) | 1485 | if (ret) |
| 1541 | return ret; | 1486 | return ret; |
| 1542 | 1487 | ||
| 1543 | /* Read back and check it. */ | 1488 | /* Read back and check it. */ |
| 1544 | ret = read_cr(nor); | 1489 | ret = read_cr(nor); |
| 1545 | if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { | 1490 | if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { |
| 1546 | dev_dbg(nor->dev, "Spansion Quad bit not set\n"); | 1491 | dev_dbg(nor->dev, "Spansion Quad bit not set\n"); |
| 1547 | return -EINVAL; | 1492 | return -EINVAL; |
| 1548 | } | 1493 | } |
| 1549 | 1494 | ||
| 1550 | return 0; | 1495 | return 0; |
| 1551 | } | 1496 | } |
| 1552 | 1497 | ||
| 1553 | #if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) | 1498 | #if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) |
| 1554 | /** | 1499 | /** |
| 1555 | * spansion_no_read_cr_quad_enable() - set QE bit in Configuration Register. | 1500 | * spansion_no_read_cr_quad_enable() - set QE bit in Configuration Register. |
| 1556 | * @nor: pointer to a 'struct spi_nor' | 1501 | * @nor: pointer to a 'struct spi_nor' |
| 1557 | * | 1502 | * |
| 1558 | * Set the Quad Enable (QE) bit in the Configuration Register. | 1503 | * Set the Quad Enable (QE) bit in the Configuration Register. |
| 1559 | * This function should be used with QSPI memories not supporting the Read | 1504 | * This function should be used with QSPI memories not supporting the Read |
| 1560 | * Configuration Register (35h) instruction. | 1505 | * Configuration Register (35h) instruction. |
| 1561 | * | 1506 | * |
| 1562 | * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI | 1507 | * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI |
| 1563 | * memories. | 1508 | * memories. |
| 1564 | * | 1509 | * |
| 1565 | * Return: 0 on success, -errno otherwise. | 1510 | * Return: 0 on success, -errno otherwise. |
| 1566 | */ | 1511 | */ |
| 1567 | static int spansion_no_read_cr_quad_enable(struct spi_nor *nor) | 1512 | static int spansion_no_read_cr_quad_enable(struct spi_nor *nor) |
| 1568 | { | 1513 | { |
| 1569 | u8 sr_cr[2]; | 1514 | u8 sr_cr[2]; |
| 1570 | int ret; | 1515 | int ret; |
| 1571 | 1516 | ||
| 1572 | /* Keep the current value of the Status Register. */ | 1517 | /* Keep the current value of the Status Register. */ |
| 1573 | ret = read_sr(nor); | 1518 | ret = read_sr(nor); |
| 1574 | if (ret < 0) { | 1519 | if (ret < 0) { |
| 1575 | dev_dbg(nor->dev, "error while reading status register\n"); | 1520 | dev_dbg(nor->dev, "error while reading status register\n"); |
| 1576 | return -EINVAL; | 1521 | return -EINVAL; |
| 1577 | } | 1522 | } |
| 1578 | sr_cr[0] = ret; | 1523 | sr_cr[0] = ret; |
| 1579 | sr_cr[1] = CR_QUAD_EN_SPAN; | 1524 | sr_cr[1] = CR_QUAD_EN_SPAN; |
| 1580 | 1525 | ||
| 1581 | return write_sr_cr(nor, sr_cr); | 1526 | return write_sr_cr(nor, sr_cr); |
| 1582 | } | 1527 | } |
| 1583 | 1528 | ||
| 1584 | #endif /* CONFIG_SPI_FLASH_SFDP_SUPPORT */ | 1529 | #endif /* CONFIG_SPI_FLASH_SFDP_SUPPORT */ |
| 1585 | #endif /* CONFIG_SPI_FLASH_SPANSION */ | 1530 | #endif /* CONFIG_SPI_FLASH_SPANSION */ |
| 1586 | 1531 | ||
| 1587 | struct spi_nor_read_command { | 1532 | struct spi_nor_read_command { |
| 1588 | u8 num_mode_clocks; | 1533 | u8 num_mode_clocks; |
| 1589 | u8 num_wait_states; | 1534 | u8 num_wait_states; |
| 1590 | u8 opcode; | 1535 | u8 opcode; |
| 1591 | enum spi_nor_protocol proto; | 1536 | enum spi_nor_protocol proto; |
| 1592 | }; | 1537 | }; |
| 1593 | 1538 | ||
| 1594 | struct spi_nor_pp_command { | 1539 | struct spi_nor_pp_command { |
| 1595 | u8 opcode; | 1540 | u8 opcode; |
| 1596 | enum spi_nor_protocol proto; | 1541 | enum spi_nor_protocol proto; |
| 1597 | }; | 1542 | }; |
| 1598 | 1543 | ||
| 1599 | enum spi_nor_read_command_index { | 1544 | enum spi_nor_read_command_index { |
| 1600 | SNOR_CMD_READ, | 1545 | SNOR_CMD_READ, |
| 1601 | SNOR_CMD_READ_FAST, | 1546 | SNOR_CMD_READ_FAST, |
| 1602 | SNOR_CMD_READ_1_1_1_DTR, | 1547 | SNOR_CMD_READ_1_1_1_DTR, |
| 1603 | 1548 | ||
| 1604 | /* Dual SPI */ | 1549 | /* Dual SPI */ |
| 1605 | SNOR_CMD_READ_1_1_2, | 1550 | SNOR_CMD_READ_1_1_2, |
| 1606 | SNOR_CMD_READ_1_2_2, | 1551 | SNOR_CMD_READ_1_2_2, |
| 1607 | SNOR_CMD_READ_2_2_2, | 1552 | SNOR_CMD_READ_2_2_2, |
| 1608 | SNOR_CMD_READ_1_2_2_DTR, | 1553 | SNOR_CMD_READ_1_2_2_DTR, |
| 1609 | 1554 | ||
| 1610 | /* Quad SPI */ | 1555 | /* Quad SPI */ |
| 1611 | SNOR_CMD_READ_1_1_4, | 1556 | SNOR_CMD_READ_1_1_4, |
| 1612 | SNOR_CMD_READ_1_4_4, | 1557 | SNOR_CMD_READ_1_4_4, |
| 1613 | SNOR_CMD_READ_4_4_4, | 1558 | SNOR_CMD_READ_4_4_4, |
| 1614 | SNOR_CMD_READ_1_4_4_DTR, | 1559 | SNOR_CMD_READ_1_4_4_DTR, |
| 1615 | 1560 | ||
| 1616 | /* Octo SPI */ | 1561 | /* Octo SPI */ |
| 1617 | SNOR_CMD_READ_1_1_8, | 1562 | SNOR_CMD_READ_1_1_8, |
| 1618 | SNOR_CMD_READ_1_8_8, | 1563 | SNOR_CMD_READ_1_8_8, |
| 1619 | SNOR_CMD_READ_8_8_8, | 1564 | SNOR_CMD_READ_8_8_8, |
| 1620 | SNOR_CMD_READ_1_8_8_DTR, | 1565 | SNOR_CMD_READ_1_8_8_DTR, |
| 1621 | 1566 | ||
| 1622 | SNOR_CMD_READ_MAX | 1567 | SNOR_CMD_READ_MAX |
| 1623 | }; | 1568 | }; |
| 1624 | 1569 | ||
| 1625 | enum spi_nor_pp_command_index { | 1570 | enum spi_nor_pp_command_index { |
| 1626 | SNOR_CMD_PP, | 1571 | SNOR_CMD_PP, |
| 1627 | 1572 | ||
| 1628 | /* Quad SPI */ | 1573 | /* Quad SPI */ |
| 1629 | SNOR_CMD_PP_1_1_4, | 1574 | SNOR_CMD_PP_1_1_4, |
| 1630 | SNOR_CMD_PP_1_4_4, | 1575 | SNOR_CMD_PP_1_4_4, |
| 1631 | SNOR_CMD_PP_4_4_4, | 1576 | SNOR_CMD_PP_4_4_4, |
| 1632 | 1577 | ||
| 1633 | /* Octo SPI */ | 1578 | /* Octo SPI */ |
| 1634 | SNOR_CMD_PP_1_1_8, | 1579 | SNOR_CMD_PP_1_1_8, |
| 1635 | SNOR_CMD_PP_1_8_8, | 1580 | SNOR_CMD_PP_1_8_8, |
| 1636 | SNOR_CMD_PP_8_8_8, | 1581 | SNOR_CMD_PP_8_8_8, |
| 1637 | 1582 | ||
| 1638 | SNOR_CMD_PP_MAX | 1583 | SNOR_CMD_PP_MAX |
| 1639 | }; | 1584 | }; |
| 1640 | 1585 | ||
| 1641 | struct spi_nor_flash_parameter { | 1586 | struct spi_nor_flash_parameter { |
| 1642 | u64 size; | 1587 | u64 size; |
| 1643 | u32 page_size; | 1588 | u32 page_size; |
| 1644 | 1589 | ||
| 1645 | struct spi_nor_hwcaps hwcaps; | 1590 | struct spi_nor_hwcaps hwcaps; |
| 1646 | struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; | 1591 | struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; |
| 1647 | struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; | 1592 | struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; |
| 1648 | 1593 | ||
| 1649 | int (*quad_enable)(struct spi_nor *nor); | 1594 | int (*quad_enable)(struct spi_nor *nor); |
| 1650 | }; | 1595 | }; |
| 1651 | 1596 | ||
| 1652 | static void | 1597 | static void |
| 1653 | spi_nor_set_read_settings(struct spi_nor_read_command *read, | 1598 | spi_nor_set_read_settings(struct spi_nor_read_command *read, |
| 1654 | u8 num_mode_clocks, | 1599 | u8 num_mode_clocks, |
| 1655 | u8 num_wait_states, | 1600 | u8 num_wait_states, |
| 1656 | u8 opcode, | 1601 | u8 opcode, |
| 1657 | enum spi_nor_protocol proto) | 1602 | enum spi_nor_protocol proto) |
| 1658 | { | 1603 | { |
| 1659 | read->num_mode_clocks = num_mode_clocks; | 1604 | read->num_mode_clocks = num_mode_clocks; |
| 1660 | read->num_wait_states = num_wait_states; | 1605 | read->num_wait_states = num_wait_states; |
| 1661 | read->opcode = opcode; | 1606 | read->opcode = opcode; |
| 1662 | read->proto = proto; | 1607 | read->proto = proto; |
| 1663 | } | 1608 | } |
| 1664 | 1609 | ||
| 1665 | static void | 1610 | static void |
| 1666 | spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, | 1611 | spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, |
| 1667 | u8 opcode, | 1612 | u8 opcode, |
| 1668 | enum spi_nor_protocol proto) | 1613 | enum spi_nor_protocol proto) |
| 1669 | { | 1614 | { |
| 1670 | pp->opcode = opcode; | 1615 | pp->opcode = opcode; |
| 1671 | pp->proto = proto; | 1616 | pp->proto = proto; |
| 1672 | } | 1617 | } |
| 1673 | 1618 | ||
| 1674 | #if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) | 1619 | #if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) |
| 1675 | /* | 1620 | /* |
| 1676 | * Serial Flash Discoverable Parameters (SFDP) parsing. | 1621 | * Serial Flash Discoverable Parameters (SFDP) parsing. |
| 1677 | */ | 1622 | */ |
| 1678 | 1623 | ||
| 1679 | /** | 1624 | /** |
| 1680 | * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters. | 1625 | * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters. |
| 1681 | * @nor: pointer to a 'struct spi_nor' | 1626 | * @nor: pointer to a 'struct spi_nor' |
| 1682 | * @addr: offset in the SFDP area to start reading data from | 1627 | * @addr: offset in the SFDP area to start reading data from |
| 1683 | * @len: number of bytes to read | 1628 | * @len: number of bytes to read |
| 1684 | * @buf: buffer where the SFDP data are copied into (dma-safe memory) | 1629 | * @buf: buffer where the SFDP data are copied into (dma-safe memory) |
| 1685 | * | 1630 | * |
| 1686 | * Whatever the actual numbers of bytes for address and dummy cycles are | 1631 | * Whatever the actual numbers of bytes for address and dummy cycles are |
| 1687 | * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always | 1632 | * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always |
| 1688 | * followed by a 3-byte address and 8 dummy clock cycles. | 1633 | * followed by a 3-byte address and 8 dummy clock cycles. |
| 1689 | * | 1634 | * |
| 1690 | * Return: 0 on success, -errno otherwise. | 1635 | * Return: 0 on success, -errno otherwise. |
| 1691 | */ | 1636 | */ |
| 1692 | static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr, | 1637 | static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr, |
| 1693 | size_t len, void *buf) | 1638 | size_t len, void *buf) |
| 1694 | { | 1639 | { |
| 1695 | u8 addr_width, read_opcode, read_dummy; | 1640 | u8 addr_width, read_opcode, read_dummy; |
| 1696 | int ret; | 1641 | int ret; |
| 1697 | 1642 | ||
| 1698 | read_opcode = nor->read_opcode; | 1643 | read_opcode = nor->read_opcode; |
| 1699 | addr_width = nor->addr_width; | 1644 | addr_width = nor->addr_width; |
| 1700 | read_dummy = nor->read_dummy; | 1645 | read_dummy = nor->read_dummy; |
| 1701 | 1646 | ||
| 1702 | nor->read_opcode = SPINOR_OP_RDSFDP; | 1647 | nor->read_opcode = SPINOR_OP_RDSFDP; |
| 1703 | nor->addr_width = 3; | 1648 | nor->addr_width = 3; |
| 1704 | nor->read_dummy = 8; | 1649 | nor->read_dummy = 8; |
| 1705 | 1650 | ||
| 1706 | while (len) { | 1651 | while (len) { |
| 1707 | ret = nor->read(nor, addr, len, (u8 *)buf); | 1652 | ret = nor->read(nor, addr, len, (u8 *)buf); |
| 1708 | if (!ret || ret > len) { | 1653 | if (!ret || ret > len) { |
| 1709 | ret = -EIO; | 1654 | ret = -EIO; |
| 1710 | goto read_err; | 1655 | goto read_err; |
| 1711 | } | 1656 | } |
| 1712 | if (ret < 0) | 1657 | if (ret < 0) |
| 1713 | goto read_err; | 1658 | goto read_err; |
| 1714 | 1659 | ||
| 1715 | buf += ret; | 1660 | buf += ret; |
| 1716 | addr += ret; | 1661 | addr += ret; |
| 1717 | len -= ret; | 1662 | len -= ret; |
| 1718 | } | 1663 | } |
| 1719 | ret = 0; | 1664 | ret = 0; |
| 1720 | 1665 | ||
| 1721 | read_err: | 1666 | read_err: |
| 1722 | nor->read_opcode = read_opcode; | 1667 | nor->read_opcode = read_opcode; |
| 1723 | nor->addr_width = addr_width; | 1668 | nor->addr_width = addr_width; |
| 1724 | nor->read_dummy = read_dummy; | 1669 | nor->read_dummy = read_dummy; |
| 1725 | 1670 | ||
| 1726 | return ret; | 1671 | return ret; |
| 1727 | } | 1672 | } |
| 1728 | 1673 | ||
| 1729 | struct sfdp_parameter_header { | 1674 | struct sfdp_parameter_header { |
| 1730 | u8 id_lsb; | 1675 | u8 id_lsb; |
| 1731 | u8 minor; | 1676 | u8 minor; |
| 1732 | u8 major; | 1677 | u8 major; |
| 1733 | u8 length; /* in double words */ | 1678 | u8 length; /* in double words */ |
| 1734 | u8 parameter_table_pointer[3]; /* byte address */ | 1679 | u8 parameter_table_pointer[3]; /* byte address */ |
| 1735 | u8 id_msb; | 1680 | u8 id_msb; |
| 1736 | }; | 1681 | }; |
| 1737 | 1682 | ||
| 1738 | #define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb) | 1683 | #define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb) |
| 1739 | #define SFDP_PARAM_HEADER_PTP(p) \ | 1684 | #define SFDP_PARAM_HEADER_PTP(p) \ |
| 1740 | (((p)->parameter_table_pointer[2] << 16) | \ | 1685 | (((p)->parameter_table_pointer[2] << 16) | \ |
| 1741 | ((p)->parameter_table_pointer[1] << 8) | \ | 1686 | ((p)->parameter_table_pointer[1] << 8) | \ |
| 1742 | ((p)->parameter_table_pointer[0] << 0)) | 1687 | ((p)->parameter_table_pointer[0] << 0)) |
| 1743 | 1688 | ||
| 1744 | #define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ | 1689 | #define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ |
| 1745 | #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ | 1690 | #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ |
| 1746 | 1691 | ||
| 1747 | #define SFDP_SIGNATURE 0x50444653U | 1692 | #define SFDP_SIGNATURE 0x50444653U |
| 1748 | #define SFDP_JESD216_MAJOR 1 | 1693 | #define SFDP_JESD216_MAJOR 1 |
| 1749 | #define SFDP_JESD216_MINOR 0 | 1694 | #define SFDP_JESD216_MINOR 0 |
| 1750 | #define SFDP_JESD216A_MINOR 5 | 1695 | #define SFDP_JESD216A_MINOR 5 |
| 1751 | #define SFDP_JESD216B_MINOR 6 | 1696 | #define SFDP_JESD216B_MINOR 6 |
| 1752 | 1697 | ||
| 1753 | struct sfdp_header { | 1698 | struct sfdp_header { |
| 1754 | u32 signature; /* Ox50444653U <=> "SFDP" */ | 1699 | u32 signature; /* Ox50444653U <=> "SFDP" */ |
| 1755 | u8 minor; | 1700 | u8 minor; |
| 1756 | u8 major; | 1701 | u8 major; |
| 1757 | u8 nph; /* 0-base number of parameter headers */ | 1702 | u8 nph; /* 0-base number of parameter headers */ |
| 1758 | u8 unused; | 1703 | u8 unused; |
| 1759 | 1704 | ||
| 1760 | /* Basic Flash Parameter Table. */ | 1705 | /* Basic Flash Parameter Table. */ |
| 1761 | struct sfdp_parameter_header bfpt_header; | 1706 | struct sfdp_parameter_header bfpt_header; |
| 1762 | }; | 1707 | }; |
| 1763 | 1708 | ||
| 1764 | /* Basic Flash Parameter Table */ | 1709 | /* Basic Flash Parameter Table */ |
| 1765 | 1710 | ||
| 1766 | /* | 1711 | /* |
| 1767 | * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs. | 1712 | * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs. |
| 1768 | * They are indexed from 1 but C arrays are indexed from 0. | 1713 | * They are indexed from 1 but C arrays are indexed from 0. |
| 1769 | */ | 1714 | */ |
| 1770 | #define BFPT_DWORD(i) ((i) - 1) | 1715 | #define BFPT_DWORD(i) ((i) - 1) |
| 1771 | #define BFPT_DWORD_MAX 16 | 1716 | #define BFPT_DWORD_MAX 16 |
| 1772 | 1717 | ||
| 1773 | /* The first version of JESB216 defined only 9 DWORDs. */ | 1718 | /* The first version of JESB216 defined only 9 DWORDs. */ |
| 1774 | #define BFPT_DWORD_MAX_JESD216 9 | 1719 | #define BFPT_DWORD_MAX_JESD216 9 |
| 1775 | 1720 | ||
| 1776 | /* 1st DWORD. */ | 1721 | /* 1st DWORD. */ |
| 1777 | #define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16) | 1722 | #define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16) |
| 1778 | #define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17) | 1723 | #define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17) |
| 1779 | #define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17) | 1724 | #define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17) |
| 1780 | #define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17) | 1725 | #define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17) |
| 1781 | #define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17) | 1726 | #define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17) |
| 1782 | #define BFPT_DWORD1_DTR BIT(19) | 1727 | #define BFPT_DWORD1_DTR BIT(19) |
| 1783 | #define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20) | 1728 | #define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20) |
| 1784 | #define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21) | 1729 | #define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21) |
| 1785 | #define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22) | 1730 | #define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22) |
| 1786 | 1731 | ||
| 1787 | /* 5th DWORD. */ | 1732 | /* 5th DWORD. */ |
| 1788 | #define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0) | 1733 | #define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0) |
| 1789 | #define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4) | 1734 | #define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4) |
| 1790 | 1735 | ||
| 1791 | /* 11th DWORD. */ | 1736 | /* 11th DWORD. */ |
| 1792 | #define BFPT_DWORD11_PAGE_SIZE_SHIFT 4 | 1737 | #define BFPT_DWORD11_PAGE_SIZE_SHIFT 4 |
| 1793 | #define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4) | 1738 | #define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4) |
| 1794 | 1739 | ||
| 1795 | /* 15th DWORD. */ | 1740 | /* 15th DWORD. */ |
| 1796 | 1741 | ||
| 1797 | /* | 1742 | /* |
| 1798 | * (from JESD216 rev B) | 1743 | * (from JESD216 rev B) |
| 1799 | * Quad Enable Requirements (QER): | 1744 | * Quad Enable Requirements (QER): |
| 1800 | * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4 | 1745 | * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4 |
| 1801 | * reads based on instruction. DQ3/HOLD# functions are hold during | 1746 | * reads based on instruction. DQ3/HOLD# functions are hold during |
| 1802 | * instruction phase. | 1747 | * instruction phase. |
| 1803 | * - 001b: QE is bit 1 of status register 2. It is set via Write Status with | 1748 | * - 001b: QE is bit 1 of status register 2. It is set via Write Status with |
| 1804 | * two data bytes where bit 1 of the second byte is one. | 1749 | * two data bytes where bit 1 of the second byte is one. |
| 1805 | * [...] | 1750 | * [...] |
| 1806 | * Writing only one byte to the status register has the side-effect of | 1751 | * Writing only one byte to the status register has the side-effect of |
| 1807 | * clearing status register 2, including the QE bit. The 100b code is | 1752 | * clearing status register 2, including the QE bit. The 100b code is |
| 1808 | * used if writing one byte to the status register does not modify | 1753 | * used if writing one byte to the status register does not modify |
| 1809 | * status register 2. | 1754 | * status register 2. |
| 1810 | * - 010b: QE is bit 6 of status register 1. It is set via Write Status with | 1755 | * - 010b: QE is bit 6 of status register 1. It is set via Write Status with |
| 1811 | * one data byte where bit 6 is one. | 1756 | * one data byte where bit 6 is one. |
| 1812 | * [...] | 1757 | * [...] |
| 1813 | * - 011b: QE is bit 7 of status register 2. It is set via Write status | 1758 | * - 011b: QE is bit 7 of status register 2. It is set via Write status |
| 1814 | * register 2 instruction 3Eh with one data byte where bit 7 is one. | 1759 | * register 2 instruction 3Eh with one data byte where bit 7 is one. |
| 1815 | * [...] | 1760 | * [...] |
| 1816 | * The status register 2 is read using instruction 3Fh. | 1761 | * The status register 2 is read using instruction 3Fh. |
| 1817 | * - 100b: QE is bit 1 of status register 2. It is set via Write Status with | 1762 | * - 100b: QE is bit 1 of status register 2. It is set via Write Status with |
| 1818 | * two data bytes where bit 1 of the second byte is one. | 1763 | * two data bytes where bit 1 of the second byte is one. |
| 1819 | * [...] | 1764 | * [...] |
| 1820 | * In contrast to the 001b code, writing one byte to the status | 1765 | * In contrast to the 001b code, writing one byte to the status |
| 1821 | * register does not modify status register 2. | 1766 | * register does not modify status register 2. |
| 1822 | * - 101b: QE is bit 1 of status register 2. Status register 1 is read using | 1767 | * - 101b: QE is bit 1 of status register 2. Status register 1 is read using |
| 1823 | * Read Status instruction 05h. Status register2 is read using | 1768 | * Read Status instruction 05h. Status register2 is read using |
| 1824 | * instruction 35h. QE is set via Writ Status instruction 01h with | 1769 | * instruction 35h. QE is set via Writ Status instruction 01h with |
| 1825 | * two data bytes where bit 1 of the second byte is one. | 1770 | * two data bytes where bit 1 of the second byte is one. |
| 1826 | * [...] | 1771 | * [...] |
| 1827 | */ | 1772 | */ |
| 1828 | #define BFPT_DWORD15_QER_MASK GENMASK(22, 20) | 1773 | #define BFPT_DWORD15_QER_MASK GENMASK(22, 20) |
| 1829 | #define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ | 1774 | #define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ |
| 1830 | #define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20) | 1775 | #define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20) |
| 1831 | #define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */ | 1776 | #define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */ |
| 1832 | #define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) | 1777 | #define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) |
| 1833 | #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) | 1778 | #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) |
| 1834 | #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ | 1779 | #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ |
| 1835 | 1780 | ||
| 1836 | struct sfdp_bfpt { | 1781 | struct sfdp_bfpt { |
| 1837 | u32 dwords[BFPT_DWORD_MAX]; | 1782 | u32 dwords[BFPT_DWORD_MAX]; |
| 1838 | }; | 1783 | }; |
| 1839 | 1784 | ||
| 1840 | /* Fast Read settings. */ | 1785 | /* Fast Read settings. */ |
| 1841 | 1786 | ||
| 1842 | static void | 1787 | static void |
| 1843 | spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read, | 1788 | spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read, |
| 1844 | u16 half, | 1789 | u16 half, |
| 1845 | enum spi_nor_protocol proto) | 1790 | enum spi_nor_protocol proto) |
| 1846 | { | 1791 | { |
| 1847 | read->num_mode_clocks = (half >> 5) & 0x07; | 1792 | read->num_mode_clocks = (half >> 5) & 0x07; |
| 1848 | read->num_wait_states = (half >> 0) & 0x1f; | 1793 | read->num_wait_states = (half >> 0) & 0x1f; |
| 1849 | read->opcode = (half >> 8) & 0xff; | 1794 | read->opcode = (half >> 8) & 0xff; |
| 1850 | read->proto = proto; | 1795 | read->proto = proto; |
| 1851 | } | 1796 | } |
| 1852 | 1797 | ||
| 1853 | struct sfdp_bfpt_read { | 1798 | struct sfdp_bfpt_read { |
| 1854 | /* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */ | 1799 | /* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */ |
| 1855 | u32 hwcaps; | 1800 | u32 hwcaps; |
| 1856 | 1801 | ||
| 1857 | /* | 1802 | /* |
| 1858 | * The <supported_bit> bit in <supported_dword> BFPT DWORD tells us | 1803 | * The <supported_bit> bit in <supported_dword> BFPT DWORD tells us |
| 1859 | * whether the Fast Read x-y-z command is supported. | 1804 | * whether the Fast Read x-y-z command is supported. |
| 1860 | */ | 1805 | */ |
| 1861 | u32 supported_dword; | 1806 | u32 supported_dword; |
| 1862 | u32 supported_bit; | 1807 | u32 supported_bit; |
| 1863 | 1808 | ||
| 1864 | /* | 1809 | /* |
| 1865 | * The half-word at offset <setting_shift> in <setting_dword> BFPT DWORD | 1810 | * The half-word at offset <setting_shift> in <setting_dword> BFPT DWORD |
| 1866 | * encodes the op code, the number of mode clocks and the number of wait | 1811 | * encodes the op code, the number of mode clocks and the number of wait |
| 1867 | * states to be used by Fast Read x-y-z command. | 1812 | * states to be used by Fast Read x-y-z command. |
| 1868 | */ | 1813 | */ |
| 1869 | u32 settings_dword; | 1814 | u32 settings_dword; |
| 1870 | u32 settings_shift; | 1815 | u32 settings_shift; |
| 1871 | 1816 | ||
| 1872 | /* The SPI protocol for this Fast Read x-y-z command. */ | 1817 | /* The SPI protocol for this Fast Read x-y-z command. */ |
| 1873 | enum spi_nor_protocol proto; | 1818 | enum spi_nor_protocol proto; |
| 1874 | }; | 1819 | }; |
| 1875 | 1820 | ||
| 1876 | static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { | 1821 | static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { |
| 1877 | /* Fast Read 1-1-2 */ | 1822 | /* Fast Read 1-1-2 */ |
| 1878 | { | 1823 | { |
| 1879 | SNOR_HWCAPS_READ_1_1_2, | 1824 | SNOR_HWCAPS_READ_1_1_2, |
| 1880 | BFPT_DWORD(1), BIT(16), /* Supported bit */ | 1825 | BFPT_DWORD(1), BIT(16), /* Supported bit */ |
| 1881 | BFPT_DWORD(4), 0, /* Settings */ | 1826 | BFPT_DWORD(4), 0, /* Settings */ |
| 1882 | SNOR_PROTO_1_1_2, | 1827 | SNOR_PROTO_1_1_2, |
| 1883 | }, | 1828 | }, |
| 1884 | 1829 | ||
| 1885 | /* Fast Read 1-2-2 */ | 1830 | /* Fast Read 1-2-2 */ |
| 1886 | { | 1831 | { |
| 1887 | SNOR_HWCAPS_READ_1_2_2, | 1832 | SNOR_HWCAPS_READ_1_2_2, |
| 1888 | BFPT_DWORD(1), BIT(20), /* Supported bit */ | 1833 | BFPT_DWORD(1), BIT(20), /* Supported bit */ |
| 1889 | BFPT_DWORD(4), 16, /* Settings */ | 1834 | BFPT_DWORD(4), 16, /* Settings */ |
| 1890 | SNOR_PROTO_1_2_2, | 1835 | SNOR_PROTO_1_2_2, |
| 1891 | }, | 1836 | }, |
| 1892 | 1837 | ||
| 1893 | /* Fast Read 2-2-2 */ | 1838 | /* Fast Read 2-2-2 */ |
| 1894 | { | 1839 | { |
| 1895 | SNOR_HWCAPS_READ_2_2_2, | 1840 | SNOR_HWCAPS_READ_2_2_2, |
| 1896 | BFPT_DWORD(5), BIT(0), /* Supported bit */ | 1841 | BFPT_DWORD(5), BIT(0), /* Supported bit */ |
| 1897 | BFPT_DWORD(6), 16, /* Settings */ | 1842 | BFPT_DWORD(6), 16, /* Settings */ |
| 1898 | SNOR_PROTO_2_2_2, | 1843 | SNOR_PROTO_2_2_2, |
| 1899 | }, | 1844 | }, |
| 1900 | 1845 | ||
| 1901 | /* Fast Read 1-1-4 */ | 1846 | /* Fast Read 1-1-4 */ |
| 1902 | { | 1847 | { |
| 1903 | SNOR_HWCAPS_READ_1_1_4, | 1848 | SNOR_HWCAPS_READ_1_1_4, |
| 1904 | BFPT_DWORD(1), BIT(22), /* Supported bit */ | 1849 | BFPT_DWORD(1), BIT(22), /* Supported bit */ |
| 1905 | BFPT_DWORD(3), 16, /* Settings */ | 1850 | BFPT_DWORD(3), 16, /* Settings */ |
| 1906 | SNOR_PROTO_1_1_4, | 1851 | SNOR_PROTO_1_1_4, |
| 1907 | }, | 1852 | }, |
| 1908 | 1853 | ||
| 1909 | /* Fast Read 1-4-4 */ | 1854 | /* Fast Read 1-4-4 */ |
| 1910 | { | 1855 | { |
| 1911 | SNOR_HWCAPS_READ_1_4_4, | 1856 | SNOR_HWCAPS_READ_1_4_4, |
| 1912 | BFPT_DWORD(1), BIT(21), /* Supported bit */ | 1857 | BFPT_DWORD(1), BIT(21), /* Supported bit */ |
| 1913 | BFPT_DWORD(3), 0, /* Settings */ | 1858 | BFPT_DWORD(3), 0, /* Settings */ |
| 1914 | SNOR_PROTO_1_4_4, | 1859 | SNOR_PROTO_1_4_4, |
| 1915 | }, | 1860 | }, |
| 1916 | 1861 | ||
| 1917 | /* Fast Read 4-4-4 */ | 1862 | /* Fast Read 4-4-4 */ |
| 1918 | { | 1863 | { |
| 1919 | SNOR_HWCAPS_READ_4_4_4, | 1864 | SNOR_HWCAPS_READ_4_4_4, |
| 1920 | BFPT_DWORD(5), BIT(4), /* Supported bit */ | 1865 | BFPT_DWORD(5), BIT(4), /* Supported bit */ |
| 1921 | BFPT_DWORD(7), 16, /* Settings */ | 1866 | BFPT_DWORD(7), 16, /* Settings */ |
| 1922 | SNOR_PROTO_4_4_4, | 1867 | SNOR_PROTO_4_4_4, |
| 1923 | }, | 1868 | }, |
| 1924 | }; | 1869 | }; |
| 1925 | 1870 | ||
| 1926 | struct sfdp_bfpt_erase { | 1871 | struct sfdp_bfpt_erase { |
| 1927 | /* | 1872 | /* |
| 1928 | * The half-word at offset <shift> in DWORD <dwoard> encodes the | 1873 | * The half-word at offset <shift> in DWORD <dwoard> encodes the |
| 1929 | * op code and erase sector size to be used by Sector Erase commands. | 1874 | * op code and erase sector size to be used by Sector Erase commands. |
| 1930 | */ | 1875 | */ |
| 1931 | u32 dword; | 1876 | u32 dword; |
| 1932 | u32 shift; | 1877 | u32 shift; |
| 1933 | }; | 1878 | }; |
| 1934 | 1879 | ||
| 1935 | static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = { | 1880 | static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = { |
| 1936 | /* Erase Type 1 in DWORD8 bits[15:0] */ | 1881 | /* Erase Type 1 in DWORD8 bits[15:0] */ |
| 1937 | {BFPT_DWORD(8), 0}, | 1882 | {BFPT_DWORD(8), 0}, |
| 1938 | 1883 | ||
| 1939 | /* Erase Type 2 in DWORD8 bits[31:16] */ | 1884 | /* Erase Type 2 in DWORD8 bits[31:16] */ |
| 1940 | {BFPT_DWORD(8), 16}, | 1885 | {BFPT_DWORD(8), 16}, |
| 1941 | 1886 | ||
| 1942 | /* Erase Type 3 in DWORD9 bits[15:0] */ | 1887 | /* Erase Type 3 in DWORD9 bits[15:0] */ |
| 1943 | {BFPT_DWORD(9), 0}, | 1888 | {BFPT_DWORD(9), 0}, |
| 1944 | 1889 | ||
| 1945 | /* Erase Type 4 in DWORD9 bits[31:16] */ | 1890 | /* Erase Type 4 in DWORD9 bits[31:16] */ |
| 1946 | {BFPT_DWORD(9), 16}, | 1891 | {BFPT_DWORD(9), 16}, |
| 1947 | }; | 1892 | }; |
| 1948 | 1893 | ||
| 1949 | static int spi_nor_hwcaps_read2cmd(u32 hwcaps); | 1894 | static int spi_nor_hwcaps_read2cmd(u32 hwcaps); |
| 1950 | 1895 | ||
| 1951 | /** | 1896 | /** |
| 1952 | * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. | 1897 | * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. |
| 1953 | * @nor: pointer to a 'struct spi_nor' | 1898 | * @nor: pointer to a 'struct spi_nor' |
| 1954 | * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing | 1899 | * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing |
| 1955 | * the Basic Flash Parameter Table length and version | 1900 | * the Basic Flash Parameter Table length and version |
| 1956 | * @params: pointer to the 'struct spi_nor_flash_parameter' to be | 1901 | * @params: pointer to the 'struct spi_nor_flash_parameter' to be |
| 1957 | * filled | 1902 | * filled |
| 1958 | * | 1903 | * |
| 1959 | * The Basic Flash Parameter Table is the main and only mandatory table as | 1904 | * The Basic Flash Parameter Table is the main and only mandatory table as |
| 1960 | * defined by the SFDP (JESD216) specification. | 1905 | * defined by the SFDP (JESD216) specification. |
| 1961 | * It provides us with the total size (memory density) of the data array and | 1906 | * It provides us with the total size (memory density) of the data array and |
| 1962 | * the number of address bytes for Fast Read, Page Program and Sector Erase | 1907 | * the number of address bytes for Fast Read, Page Program and Sector Erase |
| 1963 | * commands. | 1908 | * commands. |
| 1964 | * For Fast READ commands, it also gives the number of mode clock cycles and | 1909 | * For Fast READ commands, it also gives the number of mode clock cycles and |
| 1965 | * wait states (regrouped in the number of dummy clock cycles) for each | 1910 | * wait states (regrouped in the number of dummy clock cycles) for each |
| 1966 | * supported instruction op code. | 1911 | * supported instruction op code. |
| 1967 | * For Page Program, the page size is now available since JESD216 rev A, however | 1912 | * For Page Program, the page size is now available since JESD216 rev A, however |
| 1968 | * the supported instruction op codes are still not provided. | 1913 | * the supported instruction op codes are still not provided. |
| 1969 | * For Sector Erase commands, this table stores the supported instruction op | 1914 | * For Sector Erase commands, this table stores the supported instruction op |
| 1970 | * codes and the associated sector sizes. | 1915 | * codes and the associated sector sizes. |
| 1971 | * Finally, the Quad Enable Requirements (QER) are also available since JESD216 | 1916 | * Finally, the Quad Enable Requirements (QER) are also available since JESD216 |
| 1972 | * rev A. The QER bits encode the manufacturer dependent procedure to be | 1917 | * rev A. The QER bits encode the manufacturer dependent procedure to be |
| 1973 | * executed to set the Quad Enable (QE) bit in some internal register of the | 1918 | * executed to set the Quad Enable (QE) bit in some internal register of the |
| 1974 | * Quad SPI memory. Indeed the QE bit, when it exists, must be set before | 1919 | * Quad SPI memory. Indeed the QE bit, when it exists, must be set before |
| 1975 | * sending any Quad SPI command to the memory. Actually, setting the QE bit | 1920 | * sending any Quad SPI command to the memory. Actually, setting the QE bit |
| 1976 | * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2 | 1921 | * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2 |
| 1977 | * and IO3 hence enabling 4 (Quad) I/O lines. | 1922 | * and IO3 hence enabling 4 (Quad) I/O lines. |
| 1978 | * | 1923 | * |
| 1979 | * Return: 0 on success, -errno otherwise. | 1924 | * Return: 0 on success, -errno otherwise. |
| 1980 | */ | 1925 | */ |
| 1981 | static int spi_nor_parse_bfpt(struct spi_nor *nor, | 1926 | static int spi_nor_parse_bfpt(struct spi_nor *nor, |
| 1982 | const struct sfdp_parameter_header *bfpt_header, | 1927 | const struct sfdp_parameter_header *bfpt_header, |
| 1983 | struct spi_nor_flash_parameter *params) | 1928 | struct spi_nor_flash_parameter *params) |
| 1984 | { | 1929 | { |
| 1985 | struct mtd_info *mtd = &nor->mtd; | 1930 | struct mtd_info *mtd = &nor->mtd; |
| 1986 | struct sfdp_bfpt bfpt; | 1931 | struct sfdp_bfpt bfpt; |
| 1987 | size_t len; | 1932 | size_t len; |
| 1988 | int i, cmd, err; | 1933 | int i, cmd, err; |
| 1989 | u32 addr; | 1934 | u32 addr; |
| 1990 | u16 half; | 1935 | u16 half; |
| 1991 | 1936 | ||
| 1992 | /* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */ | 1937 | /* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */ |
| 1993 | if (bfpt_header->length < BFPT_DWORD_MAX_JESD216) | 1938 | if (bfpt_header->length < BFPT_DWORD_MAX_JESD216) |
| 1994 | return -EINVAL; | 1939 | return -EINVAL; |
| 1995 | 1940 | ||
| 1996 | /* Read the Basic Flash Parameter Table. */ | 1941 | /* Read the Basic Flash Parameter Table. */ |
| 1997 | len = min_t(size_t, sizeof(bfpt), | 1942 | len = min_t(size_t, sizeof(bfpt), |
| 1998 | bfpt_header->length * sizeof(u32)); | 1943 | bfpt_header->length * sizeof(u32)); |
| 1999 | addr = SFDP_PARAM_HEADER_PTP(bfpt_header); | 1944 | addr = SFDP_PARAM_HEADER_PTP(bfpt_header); |
| 2000 | memset(&bfpt, 0, sizeof(bfpt)); | 1945 | memset(&bfpt, 0, sizeof(bfpt)); |
| 2001 | err = spi_nor_read_sfdp(nor, addr, len, &bfpt); | 1946 | err = spi_nor_read_sfdp(nor, addr, len, &bfpt); |
| 2002 | if (err < 0) | 1947 | if (err < 0) |
| 2003 | return err; | 1948 | return err; |
| 2004 | 1949 | ||
| 2005 | /* Fix endianness of the BFPT DWORDs. */ | 1950 | /* Fix endianness of the BFPT DWORDs. */ |
| 2006 | for (i = 0; i < BFPT_DWORD_MAX; i++) | 1951 | for (i = 0; i < BFPT_DWORD_MAX; i++) |
| 2007 | bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]); | 1952 | bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]); |
| 2008 | 1953 | ||
| 2009 | /* Number of address bytes. */ | 1954 | /* Number of address bytes. */ |
| 2010 | switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { | 1955 | switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { |
| 2011 | case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: | 1956 | case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: |
| 2012 | nor->addr_width = 3; | 1957 | nor->addr_width = 3; |
| 2013 | break; | 1958 | break; |
| 2014 | 1959 | ||
| 2015 | case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: | 1960 | case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: |
| 2016 | nor->addr_width = 4; | 1961 | nor->addr_width = 4; |
| 2017 | break; | 1962 | break; |
| 2018 | 1963 | ||
| 2019 | default: | 1964 | default: |
| 2020 | break; | 1965 | break; |
| 2021 | } | 1966 | } |
| 2022 | 1967 | ||
| 2023 | /* Flash Memory Density (in bits). */ | 1968 | /* Flash Memory Density (in bits). */ |
| 2024 | params->size = bfpt.dwords[BFPT_DWORD(2)]; | 1969 | params->size = bfpt.dwords[BFPT_DWORD(2)]; |
| 2025 | if (params->size & BIT(31)) { | 1970 | if (params->size & BIT(31)) { |
| 2026 | params->size &= ~BIT(31); | 1971 | params->size &= ~BIT(31); |
| 2027 | 1972 | ||
| 2028 | /* | 1973 | /* |
| 2029 | * Prevent overflows on params->size. Anyway, a NOR of 2^64 | 1974 | * Prevent overflows on params->size. Anyway, a NOR of 2^64 |
| 2030 | * bits is unlikely to exist so this error probably means | 1975 | * bits is unlikely to exist so this error probably means |
| 2031 | * the BFPT we are reading is corrupted/wrong. | 1976 | * the BFPT we are reading is corrupted/wrong. |
| 2032 | */ | 1977 | */ |
| 2033 | if (params->size > 63) | 1978 | if (params->size > 63) |
| 2034 | return -EINVAL; | 1979 | return -EINVAL; |
| 2035 | 1980 | ||
| 2036 | params->size = 1ULL << params->size; | 1981 | params->size = 1ULL << params->size; |
| 2037 | } else { | 1982 | } else { |
| 2038 | params->size++; | 1983 | params->size++; |
| 2039 | } | 1984 | } |
| 2040 | params->size >>= 3; /* Convert to bytes. */ | 1985 | params->size >>= 3; /* Convert to bytes. */ |
| 2041 | 1986 | ||
| 2042 | /* Fast Read settings. */ | 1987 | /* Fast Read settings. */ |
| 2043 | for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) { | 1988 | for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) { |
| 2044 | const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i]; | 1989 | const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i]; |
| 2045 | struct spi_nor_read_command *read; | 1990 | struct spi_nor_read_command *read; |
| 2046 | 1991 | ||
| 2047 | if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) { | 1992 | if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) { |
| 2048 | params->hwcaps.mask &= ~rd->hwcaps; | 1993 | params->hwcaps.mask &= ~rd->hwcaps; |
| 2049 | continue; | 1994 | continue; |
| 2050 | } | 1995 | } |
| 2051 | 1996 | ||
| 2052 | params->hwcaps.mask |= rd->hwcaps; | 1997 | params->hwcaps.mask |= rd->hwcaps; |
| 2053 | cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps); | 1998 | cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps); |
| 2054 | read = ¶ms->reads[cmd]; | 1999 | read = ¶ms->reads[cmd]; |
| 2055 | half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift; | 2000 | half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift; |
| 2056 | spi_nor_set_read_settings_from_bfpt(read, half, rd->proto); | 2001 | spi_nor_set_read_settings_from_bfpt(read, half, rd->proto); |
| 2057 | } | 2002 | } |
| 2058 | 2003 | ||
| 2059 | /* Sector Erase settings. */ | 2004 | /* Sector Erase settings. */ |
| 2060 | for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { | 2005 | for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { |
| 2061 | const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; | 2006 | const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; |
| 2062 | u32 erasesize; | 2007 | u32 erasesize; |
| 2063 | u8 opcode; | 2008 | u8 opcode; |
| 2064 | 2009 | ||
| 2065 | half = bfpt.dwords[er->dword] >> er->shift; | 2010 | half = bfpt.dwords[er->dword] >> er->shift; |
| 2066 | erasesize = half & 0xff; | 2011 | erasesize = half & 0xff; |
| 2067 | 2012 | ||
| 2068 | /* erasesize == 0 means this Erase Type is not supported. */ | 2013 | /* erasesize == 0 means this Erase Type is not supported. */ |
| 2069 | if (!erasesize) | 2014 | if (!erasesize) |
| 2070 | continue; | 2015 | continue; |
| 2071 | 2016 | ||
| 2072 | erasesize = 1U << erasesize; | 2017 | erasesize = 1U << erasesize; |
| 2073 | opcode = (half >> 8) & 0xff; | 2018 | opcode = (half >> 8) & 0xff; |
| 2074 | #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS | 2019 | #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS |
| 2075 | if (erasesize == SZ_4K) { | 2020 | if (erasesize == SZ_4K) { |
| 2076 | nor->erase_opcode = opcode; | 2021 | nor->erase_opcode = opcode; |
| 2077 | mtd->erasesize = erasesize; | 2022 | mtd->erasesize = erasesize; |
| 2078 | break; | 2023 | break; |
| 2079 | } | 2024 | } |
| 2080 | #endif | 2025 | #endif |
| 2081 | if (!mtd->erasesize || mtd->erasesize < erasesize) { | 2026 | if (!mtd->erasesize || mtd->erasesize < erasesize) { |
| 2082 | nor->erase_opcode = opcode; | 2027 | nor->erase_opcode = opcode; |
| 2083 | mtd->erasesize = erasesize; | 2028 | mtd->erasesize = erasesize; |
| 2084 | } | 2029 | } |
| 2085 | } | 2030 | } |
| 2086 | 2031 | ||
| 2087 | /* Stop here if not JESD216 rev A or later. */ | 2032 | /* Stop here if not JESD216 rev A or later. */ |
| 2088 | if (bfpt_header->length < BFPT_DWORD_MAX) | 2033 | if (bfpt_header->length < BFPT_DWORD_MAX) |
| 2089 | return 0; | 2034 | return 0; |
| 2090 | 2035 | ||
| 2091 | /* Page size: this field specifies 'N' so the page size = 2^N bytes. */ | 2036 | /* Page size: this field specifies 'N' so the page size = 2^N bytes. */ |
| 2092 | params->page_size = bfpt.dwords[BFPT_DWORD(11)]; | 2037 | params->page_size = bfpt.dwords[BFPT_DWORD(11)]; |
| 2093 | params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK; | 2038 | params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK; |
| 2094 | params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT; | 2039 | params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT; |
| 2095 | params->page_size = 1U << params->page_size; | 2040 | params->page_size = 1U << params->page_size; |
| 2096 | 2041 | ||
| 2097 | /* Quad Enable Requirements. */ | 2042 | /* Quad Enable Requirements. */ |
| 2098 | switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) { | 2043 | switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) { |
| 2099 | case BFPT_DWORD15_QER_NONE: | 2044 | case BFPT_DWORD15_QER_NONE: |
| 2100 | params->quad_enable = NULL; | 2045 | params->quad_enable = NULL; |
| 2101 | break; | 2046 | break; |
| 2102 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 2047 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
| 2103 | case BFPT_DWORD15_QER_SR2_BIT1_BUGGY: | 2048 | case BFPT_DWORD15_QER_SR2_BIT1_BUGGY: |
| 2104 | case BFPT_DWORD15_QER_SR2_BIT1_NO_RD: | 2049 | case BFPT_DWORD15_QER_SR2_BIT1_NO_RD: |
| 2105 | params->quad_enable = spansion_no_read_cr_quad_enable; | 2050 | params->quad_enable = spansion_no_read_cr_quad_enable; |
| 2106 | break; | 2051 | break; |
| 2107 | #endif | 2052 | #endif |
| 2108 | #ifdef CONFIG_SPI_FLASH_MACRONIX | 2053 | #ifdef CONFIG_SPI_FLASH_MACRONIX |
| 2109 | case BFPT_DWORD15_QER_SR1_BIT6: | 2054 | case BFPT_DWORD15_QER_SR1_BIT6: |
| 2110 | params->quad_enable = macronix_quad_enable; | 2055 | params->quad_enable = macronix_quad_enable; |
| 2111 | break; | 2056 | break; |
| 2112 | #endif | 2057 | #endif |
| 2113 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 2058 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
| 2114 | case BFPT_DWORD15_QER_SR2_BIT1: | 2059 | case BFPT_DWORD15_QER_SR2_BIT1: |
| 2115 | params->quad_enable = spansion_read_cr_quad_enable; | 2060 | params->quad_enable = spansion_read_cr_quad_enable; |
| 2116 | break; | 2061 | break; |
| 2117 | #endif | 2062 | #endif |
| 2118 | default: | 2063 | default: |
| 2119 | return -EINVAL; | 2064 | return -EINVAL; |
| 2120 | } | 2065 | } |
| 2121 | 2066 | ||
| 2122 | return 0; | 2067 | return 0; |
| 2123 | } | 2068 | } |
| 2124 | 2069 | ||
| 2125 | /** | 2070 | /** |
| 2126 | * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. | 2071 | * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. |
| 2127 | * @nor: pointer to a 'struct spi_nor' | 2072 | * @nor: pointer to a 'struct spi_nor' |
| 2128 | * @params: pointer to the 'struct spi_nor_flash_parameter' to be | 2073 | * @params: pointer to the 'struct spi_nor_flash_parameter' to be |
| 2129 | * filled | 2074 | * filled |
| 2130 | * | 2075 | * |
| 2131 | * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216 | 2076 | * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216 |
| 2132 | * specification. This is a standard which tends to supported by almost all | 2077 | * specification. This is a standard which tends to supported by almost all |
| 2133 | * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at | 2078 | * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at |
| 2134 | * runtime the main parameters needed to perform basic SPI flash operations such | 2079 | * runtime the main parameters needed to perform basic SPI flash operations such |
| 2135 | * as Fast Read, Page Program or Sector Erase commands. | 2080 | * as Fast Read, Page Program or Sector Erase commands. |
| 2136 | * | 2081 | * |
| 2137 | * Return: 0 on success, -errno otherwise. | 2082 | * Return: 0 on success, -errno otherwise. |
| 2138 | */ | 2083 | */ |
| 2139 | static int spi_nor_parse_sfdp(struct spi_nor *nor, | 2084 | static int spi_nor_parse_sfdp(struct spi_nor *nor, |
| 2140 | struct spi_nor_flash_parameter *params) | 2085 | struct spi_nor_flash_parameter *params) |
| 2141 | { | 2086 | { |
| 2142 | const struct sfdp_parameter_header *param_header, *bfpt_header; | 2087 | const struct sfdp_parameter_header *param_header, *bfpt_header; |
| 2143 | struct sfdp_parameter_header *param_headers = NULL; | 2088 | struct sfdp_parameter_header *param_headers = NULL; |
| 2144 | struct sfdp_header header; | 2089 | struct sfdp_header header; |
| 2145 | size_t psize; | 2090 | size_t psize; |
| 2146 | int i, err; | 2091 | int i, err; |
| 2147 | 2092 | ||
| 2148 | /* Get the SFDP header. */ | 2093 | /* Get the SFDP header. */ |
| 2149 | err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header); | 2094 | err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header); |
| 2150 | if (err < 0) | 2095 | if (err < 0) |
| 2151 | return err; | 2096 | return err; |
| 2152 | 2097 | ||
| 2153 | /* Check the SFDP header version. */ | 2098 | /* Check the SFDP header version. */ |
| 2154 | if (le32_to_cpu(header.signature) != SFDP_SIGNATURE || | 2099 | if (le32_to_cpu(header.signature) != SFDP_SIGNATURE || |
| 2155 | header.major != SFDP_JESD216_MAJOR) | 2100 | header.major != SFDP_JESD216_MAJOR) |
| 2156 | return -EINVAL; | 2101 | return -EINVAL; |
| 2157 | 2102 | ||
| 2158 | /* | 2103 | /* |
| 2159 | * Verify that the first and only mandatory parameter header is a | 2104 | * Verify that the first and only mandatory parameter header is a |
| 2160 | * Basic Flash Parameter Table header as specified in JESD216. | 2105 | * Basic Flash Parameter Table header as specified in JESD216. |
| 2161 | */ | 2106 | */ |
| 2162 | bfpt_header = &header.bfpt_header; | 2107 | bfpt_header = &header.bfpt_header; |
| 2163 | if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID || | 2108 | if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID || |
| 2164 | bfpt_header->major != SFDP_JESD216_MAJOR) | 2109 | bfpt_header->major != SFDP_JESD216_MAJOR) |
| 2165 | return -EINVAL; | 2110 | return -EINVAL; |
| 2166 | 2111 | ||
| 2167 | /* | 2112 | /* |
| 2168 | * Allocate memory then read all parameter headers with a single | 2113 | * Allocate memory then read all parameter headers with a single |
| 2169 | * Read SFDP command. These parameter headers will actually be parsed | 2114 | * Read SFDP command. These parameter headers will actually be parsed |
| 2170 | * twice: a first time to get the latest revision of the basic flash | 2115 | * twice: a first time to get the latest revision of the basic flash |
| 2171 | * parameter table, then a second time to handle the supported optional | 2116 | * parameter table, then a second time to handle the supported optional |
| 2172 | * tables. | 2117 | * tables. |
| 2173 | * Hence we read the parameter headers once for all to reduce the | 2118 | * Hence we read the parameter headers once for all to reduce the |
| 2174 | * processing time. Also we use kmalloc() instead of devm_kmalloc() | 2119 | * processing time. Also we use kmalloc() instead of devm_kmalloc() |
| 2175 | * because we don't need to keep these parameter headers: the allocated | 2120 | * because we don't need to keep these parameter headers: the allocated |
| 2176 | * memory is always released with kfree() before exiting this function. | 2121 | * memory is always released with kfree() before exiting this function. |
| 2177 | */ | 2122 | */ |
| 2178 | if (header.nph) { | 2123 | if (header.nph) { |
| 2179 | psize = header.nph * sizeof(*param_headers); | 2124 | psize = header.nph * sizeof(*param_headers); |
| 2180 | 2125 | ||
| 2181 | param_headers = kmalloc(psize, GFP_KERNEL); | 2126 | param_headers = kmalloc(psize, GFP_KERNEL); |
| 2182 | if (!param_headers) | 2127 | if (!param_headers) |
| 2183 | return -ENOMEM; | 2128 | return -ENOMEM; |
| 2184 | 2129 | ||
| 2185 | err = spi_nor_read_sfdp(nor, sizeof(header), | 2130 | err = spi_nor_read_sfdp(nor, sizeof(header), |
| 2186 | psize, param_headers); | 2131 | psize, param_headers); |
| 2187 | if (err < 0) { | 2132 | if (err < 0) { |
| 2188 | dev_err(dev, "failed to read SFDP parameter headers\n"); | 2133 | dev_err(dev, "failed to read SFDP parameter headers\n"); |
| 2189 | goto exit; | 2134 | goto exit; |
| 2190 | } | 2135 | } |
| 2191 | } | 2136 | } |
| 2192 | 2137 | ||
| 2193 | /* | 2138 | /* |
| 2194 | * Check other parameter headers to get the latest revision of | 2139 | * Check other parameter headers to get the latest revision of |
| 2195 | * the basic flash parameter table. | 2140 | * the basic flash parameter table. |
| 2196 | */ | 2141 | */ |
| 2197 | for (i = 0; i < header.nph; i++) { | 2142 | for (i = 0; i < header.nph; i++) { |
| 2198 | param_header = ¶m_headers[i]; | 2143 | param_header = ¶m_headers[i]; |
| 2199 | 2144 | ||
| 2200 | if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID && | 2145 | if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID && |
| 2201 | param_header->major == SFDP_JESD216_MAJOR && | 2146 | param_header->major == SFDP_JESD216_MAJOR && |
| 2202 | (param_header->minor > bfpt_header->minor || | 2147 | (param_header->minor > bfpt_header->minor || |
| 2203 | (param_header->minor == bfpt_header->minor && | 2148 | (param_header->minor == bfpt_header->minor && |
| 2204 | param_header->length > bfpt_header->length))) | 2149 | param_header->length > bfpt_header->length))) |
| 2205 | bfpt_header = param_header; | 2150 | bfpt_header = param_header; |
| 2206 | } | 2151 | } |
| 2207 | 2152 | ||
| 2208 | err = spi_nor_parse_bfpt(nor, bfpt_header, params); | 2153 | err = spi_nor_parse_bfpt(nor, bfpt_header, params); |
| 2209 | if (err) | 2154 | if (err) |
| 2210 | goto exit; | 2155 | goto exit; |
| 2211 | 2156 | ||
| 2212 | /* Parse other parameter headers. */ | 2157 | /* Parse other parameter headers. */ |
| 2213 | for (i = 0; i < header.nph; i++) { | 2158 | for (i = 0; i < header.nph; i++) { |
| 2214 | param_header = ¶m_headers[i]; | 2159 | param_header = ¶m_headers[i]; |
| 2215 | 2160 | ||
| 2216 | switch (SFDP_PARAM_HEADER_ID(param_header)) { | 2161 | switch (SFDP_PARAM_HEADER_ID(param_header)) { |
| 2217 | case SFDP_SECTOR_MAP_ID: | 2162 | case SFDP_SECTOR_MAP_ID: |
| 2218 | dev_info(dev, "non-uniform erase sector maps are not supported yet.\n"); | 2163 | dev_info(dev, "non-uniform erase sector maps are not supported yet.\n"); |
| 2219 | break; | 2164 | break; |
| 2220 | 2165 | ||
| 2221 | default: | 2166 | default: |
| 2222 | break; | 2167 | break; |
| 2223 | } | 2168 | } |
| 2224 | 2169 | ||
| 2225 | if (err) | 2170 | if (err) |
| 2226 | goto exit; | 2171 | goto exit; |
| 2227 | } | 2172 | } |
| 2228 | 2173 | ||
| 2229 | exit: | 2174 | exit: |
| 2230 | kfree(param_headers); | 2175 | kfree(param_headers); |
| 2231 | return err; | 2176 | return err; |
| 2232 | } | 2177 | } |
| 2233 | #else | 2178 | #else |
| 2234 | static int spi_nor_parse_sfdp(struct spi_nor *nor, | 2179 | static int spi_nor_parse_sfdp(struct spi_nor *nor, |
| 2235 | struct spi_nor_flash_parameter *params) | 2180 | struct spi_nor_flash_parameter *params) |
| 2236 | { | 2181 | { |
| 2237 | return -EINVAL; | 2182 | return -EINVAL; |
| 2238 | } | 2183 | } |
| 2239 | #endif /* SPI_FLASH_SFDP_SUPPORT */ | 2184 | #endif /* SPI_FLASH_SFDP_SUPPORT */ |
| 2240 | 2185 | ||
| 2241 | static int spi_nor_init_params(struct spi_nor *nor, | 2186 | static int spi_nor_init_params(struct spi_nor *nor, |
| 2242 | const struct flash_info *info, | 2187 | const struct flash_info *info, |
| 2243 | struct spi_nor_flash_parameter *params) | 2188 | struct spi_nor_flash_parameter *params) |
| 2244 | { | 2189 | { |
| 2245 | /* Set legacy flash parameters as default. */ | 2190 | /* Set legacy flash parameters as default. */ |
| 2246 | memset(params, 0, sizeof(*params)); | 2191 | memset(params, 0, sizeof(*params)); |
| 2247 | 2192 | ||
| 2248 | /* Set SPI NOR sizes. */ | 2193 | /* Set SPI NOR sizes. */ |
| 2249 | params->size = info->sector_size * info->n_sectors; | 2194 | params->size = info->sector_size * info->n_sectors; |
| 2250 | params->page_size = info->page_size; | 2195 | params->page_size = info->page_size; |
| 2251 | 2196 | ||
| 2252 | /* (Fast) Read settings. */ | 2197 | /* (Fast) Read settings. */ |
| 2253 | params->hwcaps.mask |= SNOR_HWCAPS_READ; | 2198 | params->hwcaps.mask |= SNOR_HWCAPS_READ; |
| 2254 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ], | 2199 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ], |
| 2255 | 0, 0, SPINOR_OP_READ, | 2200 | 0, 0, SPINOR_OP_READ, |
| 2256 | SNOR_PROTO_1_1_1); | 2201 | SNOR_PROTO_1_1_1); |
| 2257 | 2202 | ||
| 2258 | if (!(info->flags & SPI_NOR_NO_FR)) { | 2203 | if (!(info->flags & SPI_NOR_NO_FR)) { |
| 2259 | params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST; | 2204 | params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST; |
| 2260 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST], | 2205 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST], |
| 2261 | 0, 8, SPINOR_OP_READ_FAST, | 2206 | 0, 8, SPINOR_OP_READ_FAST, |
| 2262 | SNOR_PROTO_1_1_1); | 2207 | SNOR_PROTO_1_1_1); |
| 2263 | } | 2208 | } |
| 2264 | 2209 | ||
| 2265 | if (info->flags & SPI_NOR_DUAL_READ) { | 2210 | if (info->flags & SPI_NOR_DUAL_READ) { |
| 2266 | params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; | 2211 | params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; |
| 2267 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_2], | 2212 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_2], |
| 2268 | 0, 8, SPINOR_OP_READ_1_1_2, | 2213 | 0, 8, SPINOR_OP_READ_1_1_2, |
| 2269 | SNOR_PROTO_1_1_2); | 2214 | SNOR_PROTO_1_1_2); |
| 2270 | } | 2215 | } |
| 2271 | 2216 | ||
| 2272 | if (info->flags & SPI_NOR_QUAD_READ) { | 2217 | if (info->flags & SPI_NOR_QUAD_READ) { |
| 2273 | params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; | 2218 | params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; |
| 2274 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], | 2219 | spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], |
| 2275 | 0, 8, SPINOR_OP_READ_1_1_4, | 2220 | 0, 8, SPINOR_OP_READ_1_1_4, |
| 2276 | SNOR_PROTO_1_1_4); | 2221 | SNOR_PROTO_1_1_4); |
| 2277 | } | 2222 | } |
| 2278 | 2223 | ||
| 2279 | /* Page Program settings. */ | 2224 | /* Page Program settings. */ |
| 2280 | params->hwcaps.mask |= SNOR_HWCAPS_PP; | 2225 | params->hwcaps.mask |= SNOR_HWCAPS_PP; |
| 2281 | spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], | 2226 | spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], |
| 2282 | SPINOR_OP_PP, SNOR_PROTO_1_1_1); | 2227 | SPINOR_OP_PP, SNOR_PROTO_1_1_1); |
| 2283 | 2228 | ||
| 2284 | if (info->flags & SPI_NOR_QUAD_READ) { | 2229 | if (info->flags & SPI_NOR_QUAD_READ) { |
| 2285 | params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; | 2230 | params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; |
| 2286 | spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4], | 2231 | spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4], |
| 2287 | SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4); | 2232 | SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4); |
| 2288 | } | 2233 | } |
| 2289 | 2234 | ||
| 2290 | /* Select the procedure to set the Quad Enable bit. */ | 2235 | /* Select the procedure to set the Quad Enable bit. */ |
| 2291 | if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD | | 2236 | if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD | |
| 2292 | SNOR_HWCAPS_PP_QUAD)) { | 2237 | SNOR_HWCAPS_PP_QUAD)) { |
| 2293 | switch (JEDEC_MFR(info)) { | 2238 | switch (JEDEC_MFR(info)) { |
| 2294 | #ifdef CONFIG_SPI_FLASH_MACRONIX | 2239 | #ifdef CONFIG_SPI_FLASH_MACRONIX |
| 2295 | case SNOR_MFR_MACRONIX: | 2240 | case SNOR_MFR_MACRONIX: |
| 2296 | params->quad_enable = macronix_quad_enable; | 2241 | params->quad_enable = macronix_quad_enable; |
| 2297 | break; | 2242 | break; |
| 2298 | #endif | 2243 | #endif |
| 2299 | case SNOR_MFR_ST: | 2244 | case SNOR_MFR_ST: |
| 2300 | case SNOR_MFR_MICRON: | 2245 | case SNOR_MFR_MICRON: |
| 2301 | break; | 2246 | break; |
| 2302 | 2247 | ||
| 2303 | default: | 2248 | default: |
| 2304 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 2249 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
| 2305 | /* Kept only for backward compatibility purpose. */ | 2250 | /* Kept only for backward compatibility purpose. */ |
| 2306 | params->quad_enable = spansion_read_cr_quad_enable; | 2251 | params->quad_enable = spansion_read_cr_quad_enable; |
| 2307 | #endif | 2252 | #endif |
| 2308 | break; | 2253 | break; |
| 2309 | } | 2254 | } |
| 2310 | } | 2255 | } |
| 2311 | 2256 | ||
| 2312 | /* Override the parameters with data read from SFDP tables. */ | 2257 | /* Override the parameters with data read from SFDP tables. */ |
| 2313 | nor->addr_width = 0; | 2258 | nor->addr_width = 0; |
| 2314 | nor->mtd.erasesize = 0; | 2259 | nor->mtd.erasesize = 0; |
| 2315 | if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && | 2260 | if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && |
| 2316 | !(info->flags & SPI_NOR_SKIP_SFDP)) { | 2261 | !(info->flags & SPI_NOR_SKIP_SFDP)) { |
| 2317 | struct spi_nor_flash_parameter sfdp_params; | 2262 | struct spi_nor_flash_parameter sfdp_params; |
| 2318 | 2263 | ||
| 2319 | memcpy(&sfdp_params, params, sizeof(sfdp_params)); | 2264 | memcpy(&sfdp_params, params, sizeof(sfdp_params)); |
| 2320 | if (spi_nor_parse_sfdp(nor, &sfdp_params)) { | 2265 | if (spi_nor_parse_sfdp(nor, &sfdp_params)) { |
| 2321 | nor->addr_width = 0; | 2266 | nor->addr_width = 0; |
| 2322 | nor->mtd.erasesize = 0; | 2267 | nor->mtd.erasesize = 0; |
| 2323 | } else { | 2268 | } else { |
| 2324 | memcpy(params, &sfdp_params, sizeof(*params)); | 2269 | memcpy(params, &sfdp_params, sizeof(*params)); |
| 2325 | } | 2270 | } |
| 2326 | } | 2271 | } |
| 2327 | 2272 | ||
| 2328 | return 0; | 2273 | return 0; |
| 2329 | } | 2274 | } |
| 2330 | 2275 | ||
| 2331 | static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size) | 2276 | static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size) |
| 2332 | { | 2277 | { |
| 2333 | size_t i; | 2278 | size_t i; |
| 2334 | 2279 | ||
| 2335 | for (i = 0; i < size; i++) | 2280 | for (i = 0; i < size; i++) |
| 2336 | if (table[i][0] == (int)hwcaps) | 2281 | if (table[i][0] == (int)hwcaps) |
| 2337 | return table[i][1]; | 2282 | return table[i][1]; |
| 2338 | 2283 | ||
| 2339 | return -EINVAL; | 2284 | return -EINVAL; |
| 2340 | } | 2285 | } |
| 2341 | 2286 | ||
| 2342 | static int spi_nor_hwcaps_read2cmd(u32 hwcaps) | 2287 | static int spi_nor_hwcaps_read2cmd(u32 hwcaps) |
| 2343 | { | 2288 | { |
| 2344 | static const int hwcaps_read2cmd[][2] = { | 2289 | static const int hwcaps_read2cmd[][2] = { |
| 2345 | { SNOR_HWCAPS_READ, SNOR_CMD_READ }, | 2290 | { SNOR_HWCAPS_READ, SNOR_CMD_READ }, |
| 2346 | { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST }, | 2291 | { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST }, |
| 2347 | { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, | 2292 | { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, |
| 2348 | { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, | 2293 | { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, |
| 2349 | { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, | 2294 | { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, |
| 2350 | { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 }, | 2295 | { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 }, |
| 2351 | { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, | 2296 | { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, |
| 2352 | { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, | 2297 | { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, |
| 2353 | { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, | 2298 | { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, |
| 2354 | { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 }, | 2299 | { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 }, |
| 2355 | { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, | 2300 | { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, |
| 2356 | { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, | 2301 | { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, |
| 2357 | { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, | 2302 | { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, |
| 2358 | { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 }, | 2303 | { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 }, |
| 2359 | { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, | 2304 | { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, |
| 2360 | }; | 2305 | }; |
| 2361 | 2306 | ||
| 2362 | return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, | 2307 | return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, |
| 2363 | ARRAY_SIZE(hwcaps_read2cmd)); | 2308 | ARRAY_SIZE(hwcaps_read2cmd)); |
| 2364 | } | 2309 | } |
| 2365 | 2310 | ||
| 2366 | static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) | 2311 | static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) |
| 2367 | { | 2312 | { |
| 2368 | static const int hwcaps_pp2cmd[][2] = { | 2313 | static const int hwcaps_pp2cmd[][2] = { |
| 2369 | { SNOR_HWCAPS_PP, SNOR_CMD_PP }, | 2314 | { SNOR_HWCAPS_PP, SNOR_CMD_PP }, |
| 2370 | { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 }, | 2315 | { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 }, |
| 2371 | { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 }, | 2316 | { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 }, |
| 2372 | { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 }, | 2317 | { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 }, |
| 2373 | { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, | 2318 | { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, |
| 2374 | { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, | 2319 | { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, |
| 2375 | { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, | 2320 | { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, |
| 2376 | }; | 2321 | }; |
| 2377 | 2322 | ||
| 2378 | return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, | 2323 | return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, |
| 2379 | ARRAY_SIZE(hwcaps_pp2cmd)); | 2324 | ARRAY_SIZE(hwcaps_pp2cmd)); |
| 2380 | } | 2325 | } |
| 2381 | 2326 | ||
| 2382 | static int spi_nor_select_read(struct spi_nor *nor, | 2327 | static int spi_nor_select_read(struct spi_nor *nor, |
| 2383 | const struct spi_nor_flash_parameter *params, | 2328 | const struct spi_nor_flash_parameter *params, |
| 2384 | u32 shared_hwcaps) | 2329 | u32 shared_hwcaps) |
| 2385 | { | 2330 | { |
| 2386 | int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1; | 2331 | int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1; |
| 2387 | const struct spi_nor_read_command *read; | 2332 | const struct spi_nor_read_command *read; |
| 2388 | 2333 | ||
| 2389 | if (best_match < 0) | 2334 | if (best_match < 0) |
| 2390 | return -EINVAL; | 2335 | return -EINVAL; |
| 2391 | 2336 | ||
| 2392 | cmd = spi_nor_hwcaps_read2cmd(BIT(best_match)); | 2337 | cmd = spi_nor_hwcaps_read2cmd(BIT(best_match)); |
| 2393 | if (cmd < 0) | 2338 | if (cmd < 0) |
| 2394 | return -EINVAL; | 2339 | return -EINVAL; |
| 2395 | 2340 | ||
| 2396 | read = ¶ms->reads[cmd]; | 2341 | read = ¶ms->reads[cmd]; |
| 2397 | nor->read_opcode = read->opcode; | 2342 | nor->read_opcode = read->opcode; |
| 2398 | nor->read_proto = read->proto; | 2343 | nor->read_proto = read->proto; |
| 2399 | 2344 | ||
| 2400 | /* | 2345 | /* |
| 2401 | * In the spi-nor framework, we don't need to make the difference | 2346 | * In the spi-nor framework, we don't need to make the difference |
| 2402 | * between mode clock cycles and wait state clock cycles. | 2347 | * between mode clock cycles and wait state clock cycles. |
| 2403 | * Indeed, the value of the mode clock cycles is used by a QSPI | 2348 | * Indeed, the value of the mode clock cycles is used by a QSPI |
| 2404 | * flash memory to know whether it should enter or leave its 0-4-4 | 2349 | * flash memory to know whether it should enter or leave its 0-4-4 |
| 2405 | * (Continuous Read / XIP) mode. | 2350 | * (Continuous Read / XIP) mode. |
| 2406 | * eXecution In Place is out of the scope of the mtd sub-system. | 2351 | * eXecution In Place is out of the scope of the mtd sub-system. |
| 2407 | * Hence we choose to merge both mode and wait state clock cycles | 2352 | * Hence we choose to merge both mode and wait state clock cycles |
| 2408 | * into the so called dummy clock cycles. | 2353 | * into the so called dummy clock cycles. |
| 2409 | */ | 2354 | */ |
| 2410 | nor->read_dummy = read->num_mode_clocks + read->num_wait_states; | 2355 | nor->read_dummy = read->num_mode_clocks + read->num_wait_states; |
| 2411 | return 0; | 2356 | return 0; |
| 2412 | } | 2357 | } |
| 2413 | 2358 | ||
| 2414 | static int spi_nor_select_pp(struct spi_nor *nor, | 2359 | static int spi_nor_select_pp(struct spi_nor *nor, |
| 2415 | const struct spi_nor_flash_parameter *params, | 2360 | const struct spi_nor_flash_parameter *params, |
| 2416 | u32 shared_hwcaps) | 2361 | u32 shared_hwcaps) |
| 2417 | { | 2362 | { |
| 2418 | int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1; | 2363 | int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1; |
| 2419 | const struct spi_nor_pp_command *pp; | 2364 | const struct spi_nor_pp_command *pp; |
| 2420 | 2365 | ||
| 2421 | if (best_match < 0) | 2366 | if (best_match < 0) |
| 2422 | return -EINVAL; | 2367 | return -EINVAL; |
| 2423 | 2368 | ||
| 2424 | cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match)); | 2369 | cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match)); |
| 2425 | if (cmd < 0) | 2370 | if (cmd < 0) |
| 2426 | return -EINVAL; | 2371 | return -EINVAL; |
| 2427 | 2372 | ||
| 2428 | pp = ¶ms->page_programs[cmd]; | 2373 | pp = ¶ms->page_programs[cmd]; |
| 2429 | nor->program_opcode = pp->opcode; | 2374 | nor->program_opcode = pp->opcode; |
| 2430 | nor->write_proto = pp->proto; | 2375 | nor->write_proto = pp->proto; |
| 2431 | return 0; | 2376 | return 0; |
| 2432 | } | 2377 | } |
| 2433 | 2378 | ||
| 2434 | static int spi_nor_select_erase(struct spi_nor *nor, | 2379 | static int spi_nor_select_erase(struct spi_nor *nor, |
| 2435 | const struct flash_info *info) | 2380 | const struct flash_info *info) |
| 2436 | { | 2381 | { |
| 2437 | struct mtd_info *mtd = &nor->mtd; | 2382 | struct mtd_info *mtd = &nor->mtd; |
| 2438 | 2383 | ||
| 2439 | /* Do nothing if already configured from SFDP. */ | 2384 | /* Do nothing if already configured from SFDP. */ |
| 2440 | if (mtd->erasesize) | 2385 | if (mtd->erasesize) |
| 2441 | return 0; | 2386 | return 0; |
| 2442 | 2387 | ||
| 2443 | #ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS | 2388 | #ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS |
| 2444 | /* prefer "small sector" erase if possible */ | 2389 | /* prefer "small sector" erase if possible */ |
| 2445 | if (info->flags & SECT_4K) { | 2390 | if (info->flags & SECT_4K) { |
| 2446 | nor->erase_opcode = SPINOR_OP_BE_4K; | 2391 | nor->erase_opcode = SPINOR_OP_BE_4K; |
| 2447 | mtd->erasesize = 4096; | 2392 | mtd->erasesize = 4096; |
| 2448 | } else if (info->flags & SECT_4K_PMC) { | 2393 | } else if (info->flags & SECT_4K_PMC) { |
| 2449 | nor->erase_opcode = SPINOR_OP_BE_4K_PMC; | 2394 | nor->erase_opcode = SPINOR_OP_BE_4K_PMC; |
| 2450 | mtd->erasesize = 4096; | 2395 | mtd->erasesize = 4096; |
| 2451 | } else | 2396 | } else |
| 2452 | #endif | 2397 | #endif |
| 2453 | { | 2398 | { |
| 2454 | nor->erase_opcode = SPINOR_OP_SE; | 2399 | nor->erase_opcode = SPINOR_OP_SE; |
| 2455 | mtd->erasesize = info->sector_size; | 2400 | mtd->erasesize = info->sector_size; |
| 2456 | } | 2401 | } |
| 2457 | return 0; | 2402 | return 0; |
| 2458 | } | 2403 | } |
| 2459 | 2404 | ||
| 2460 | static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, | 2405 | static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, |
| 2461 | const struct spi_nor_flash_parameter *params, | 2406 | const struct spi_nor_flash_parameter *params, |
| 2462 | const struct spi_nor_hwcaps *hwcaps) | 2407 | const struct spi_nor_hwcaps *hwcaps) |
| 2463 | { | 2408 | { |
| 2464 | u32 ignored_mask, shared_mask; | 2409 | u32 ignored_mask, shared_mask; |
| 2465 | bool enable_quad_io; | 2410 | bool enable_quad_io; |
| 2466 | int err; | 2411 | int err; |
| 2467 | 2412 | ||
| 2468 | /* | 2413 | /* |
| 2469 | * Keep only the hardware capabilities supported by both the SPI | 2414 | * Keep only the hardware capabilities supported by both the SPI |
| 2470 | * controller and the SPI flash memory. | 2415 | * controller and the SPI flash memory. |
| 2471 | */ | 2416 | */ |
| 2472 | shared_mask = hwcaps->mask & params->hwcaps.mask; | 2417 | shared_mask = hwcaps->mask & params->hwcaps.mask; |
| 2473 | 2418 | ||
| 2474 | /* SPI n-n-n protocols are not supported yet. */ | 2419 | /* SPI n-n-n protocols are not supported yet. */ |
| 2475 | ignored_mask = (SNOR_HWCAPS_READ_2_2_2 | | 2420 | ignored_mask = (SNOR_HWCAPS_READ_2_2_2 | |
| 2476 | SNOR_HWCAPS_READ_4_4_4 | | 2421 | SNOR_HWCAPS_READ_4_4_4 | |
| 2477 | SNOR_HWCAPS_READ_8_8_8 | | 2422 | SNOR_HWCAPS_READ_8_8_8 | |
| 2478 | SNOR_HWCAPS_PP_4_4_4 | | 2423 | SNOR_HWCAPS_PP_4_4_4 | |
| 2479 | SNOR_HWCAPS_PP_8_8_8); | 2424 | SNOR_HWCAPS_PP_8_8_8); |
| 2480 | if (shared_mask & ignored_mask) { | 2425 | if (shared_mask & ignored_mask) { |
| 2481 | dev_dbg(nor->dev, | 2426 | dev_dbg(nor->dev, |
| 2482 | "SPI n-n-n protocols are not supported yet.\n"); | 2427 | "SPI n-n-n protocols are not supported yet.\n"); |
| 2483 | shared_mask &= ~ignored_mask; | 2428 | shared_mask &= ~ignored_mask; |
| 2484 | } | 2429 | } |
| 2485 | 2430 | ||
| 2486 | /* Select the (Fast) Read command. */ | 2431 | /* Select the (Fast) Read command. */ |
| 2487 | err = spi_nor_select_read(nor, params, shared_mask); | 2432 | err = spi_nor_select_read(nor, params, shared_mask); |
| 2488 | if (err) { | 2433 | if (err) { |
| 2489 | dev_dbg(nor->dev, | 2434 | dev_dbg(nor->dev, |
| 2490 | "can't select read settings supported by both the SPI controller and memory.\n"); | 2435 | "can't select read settings supported by both the SPI controller and memory.\n"); |
| 2491 | return err; | 2436 | return err; |
| 2492 | } | 2437 | } |
| 2493 | 2438 | ||
| 2494 | /* Select the Page Program command. */ | 2439 | /* Select the Page Program command. */ |
| 2495 | err = spi_nor_select_pp(nor, params, shared_mask); | 2440 | err = spi_nor_select_pp(nor, params, shared_mask); |
| 2496 | if (err) { | 2441 | if (err) { |
| 2497 | dev_dbg(nor->dev, | 2442 | dev_dbg(nor->dev, |
| 2498 | "can't select write settings supported by both the SPI controller and memory.\n"); | 2443 | "can't select write settings supported by both the SPI controller and memory.\n"); |
| 2499 | return err; | 2444 | return err; |
| 2500 | } | 2445 | } |
| 2501 | 2446 | ||
| 2502 | /* Select the Sector Erase command. */ | 2447 | /* Select the Sector Erase command. */ |
| 2503 | err = spi_nor_select_erase(nor, info); | 2448 | err = spi_nor_select_erase(nor, info); |
| 2504 | if (err) { | 2449 | if (err) { |
| 2505 | dev_dbg(nor->dev, | 2450 | dev_dbg(nor->dev, |
| 2506 | "can't select erase settings supported by both the SPI controller and memory.\n"); | 2451 | "can't select erase settings supported by both the SPI controller and memory.\n"); |
| 2507 | return err; | 2452 | return err; |
| 2508 | } | 2453 | } |
| 2509 | 2454 | ||
| 2510 | /* Enable Quad I/O if needed. */ | 2455 | /* Enable Quad I/O if needed. */ |
| 2511 | enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 || | 2456 | enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 || |
| 2512 | spi_nor_get_protocol_width(nor->write_proto) == 4); | 2457 | spi_nor_get_protocol_width(nor->write_proto) == 4); |
| 2513 | if (enable_quad_io && params->quad_enable) | 2458 | if (enable_quad_io && params->quad_enable) |
| 2514 | nor->quad_enable = params->quad_enable; | 2459 | nor->quad_enable = params->quad_enable; |
| 2515 | else | 2460 | else |
| 2516 | nor->quad_enable = NULL; | 2461 | nor->quad_enable = NULL; |
| 2517 | 2462 | ||
| 2518 | return 0; | 2463 | return 0; |
| 2519 | } | 2464 | } |
| 2520 | 2465 | ||
| 2521 | static int spi_nor_init(struct spi_nor *nor) | 2466 | static int spi_nor_init(struct spi_nor *nor) |
| 2522 | { | 2467 | { |
| 2523 | int err; | 2468 | int err; |
| 2524 | 2469 | ||
| 2525 | /* | 2470 | /* |
| 2526 | * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up | 2471 | * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up |
| 2527 | * with the software protection bits set | 2472 | * with the software protection bits set |
| 2528 | */ | 2473 | */ |
| 2529 | if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || | 2474 | if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || |
| 2530 | JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || | 2475 | JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || |
| 2531 | JEDEC_MFR(nor->info) == SNOR_MFR_SST || | 2476 | JEDEC_MFR(nor->info) == SNOR_MFR_SST || |
| 2532 | nor->info->flags & SPI_NOR_HAS_LOCK) { | 2477 | nor->info->flags & SPI_NOR_HAS_LOCK) { |
| 2533 | write_enable(nor); | 2478 | write_enable(nor); |
| 2534 | write_sr(nor, 0); | 2479 | write_sr(nor, 0); |
| 2535 | spi_nor_wait_till_ready(nor); | 2480 | spi_nor_wait_till_ready(nor); |
| 2536 | } | 2481 | } |
| 2537 | 2482 | ||
| 2538 | if (nor->quad_enable) { | 2483 | if (nor->quad_enable) { |
| 2539 | err = nor->quad_enable(nor); | 2484 | err = nor->quad_enable(nor); |
| 2540 | if (err) { | 2485 | if (err) { |
| 2541 | dev_dbg(nor->dev, "quad mode not supported\n"); | 2486 | dev_dbg(nor->dev, "quad mode not supported\n"); |
| 2542 | return err; | 2487 | return err; |
| 2543 | } | 2488 | } |
| 2544 | } | 2489 | } |
| 2545 | 2490 | ||
| 2546 | if (nor->addr_width == 4 && | 2491 | if (nor->addr_width == 4 && |
| 2547 | (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && | 2492 | (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && |
| 2548 | !(nor->info->flags & SPI_NOR_4B_OPCODES)) { | 2493 | !(nor->info->flags & SPI_NOR_4B_OPCODES)) { |
| 2549 | /* | 2494 | /* |
| 2550 | * If the RESET# pin isn't hooked up properly, or the system | 2495 | * If the RESET# pin isn't hooked up properly, or the system |
| 2551 | * otherwise doesn't perform a reset command in the boot | 2496 | * otherwise doesn't perform a reset command in the boot |
| 2552 | * sequence, it's impossible to 100% protect against unexpected | 2497 | * sequence, it's impossible to 100% protect against unexpected |
| 2553 | * reboots (e.g., crashes). Warn the user (or hopefully, system | 2498 | * reboots (e.g., crashes). Warn the user (or hopefully, system |
| 2554 | * designer) that this is bad. | 2499 | * designer) that this is bad. |
| 2555 | */ | 2500 | */ |
| 2556 | if (nor->flags & SNOR_F_BROKEN_RESET) | 2501 | if (nor->flags & SNOR_F_BROKEN_RESET) |
| 2557 | printf("enabling reset hack; may not recover from unexpected reboots\n"); | 2502 | printf("enabling reset hack; may not recover from unexpected reboots\n"); |
| 2558 | set_4byte(nor, nor->info, 1); | 2503 | set_4byte(nor, nor->info, 1); |
| 2559 | } | 2504 | } |
| 2560 | 2505 | ||
| 2561 | return 0; | 2506 | return 0; |
| 2562 | } | 2507 | } |
| 2563 | 2508 | ||
| 2564 | int spi_nor_scan(struct spi_nor *nor) | 2509 | int spi_nor_scan(struct spi_nor *nor) |
| 2565 | { | 2510 | { |
| 2566 | struct spi_nor_flash_parameter params; | 2511 | struct spi_nor_flash_parameter params; |
| 2567 | const struct flash_info *info = NULL; | 2512 | const struct flash_info *info = NULL; |
| 2568 | struct mtd_info *mtd = &nor->mtd; | 2513 | struct mtd_info *mtd = &nor->mtd; |
| 2569 | struct spi_nor_hwcaps hwcaps = { | 2514 | struct spi_nor_hwcaps hwcaps = { |
| 2570 | .mask = SNOR_HWCAPS_READ | | 2515 | .mask = SNOR_HWCAPS_READ | |
| 2571 | SNOR_HWCAPS_READ_FAST | | 2516 | SNOR_HWCAPS_READ_FAST | |
| 2572 | SNOR_HWCAPS_PP, | 2517 | SNOR_HWCAPS_PP, |
| 2573 | }; | 2518 | }; |
| 2574 | struct spi_slave *spi = nor->spi; | 2519 | struct spi_slave *spi = nor->spi; |
| 2575 | int ret; | 2520 | int ret; |
| 2576 | 2521 | ||
| 2577 | /* Reset SPI protocol for all commands. */ | 2522 | /* Reset SPI protocol for all commands. */ |
| 2578 | nor->reg_proto = SNOR_PROTO_1_1_1; | 2523 | nor->reg_proto = SNOR_PROTO_1_1_1; |
| 2579 | nor->read_proto = SNOR_PROTO_1_1_1; | 2524 | nor->read_proto = SNOR_PROTO_1_1_1; |
| 2580 | nor->write_proto = SNOR_PROTO_1_1_1; | 2525 | nor->write_proto = SNOR_PROTO_1_1_1; |
| 2581 | nor->read = spi_nor_read_data; | 2526 | nor->read = spi_nor_read_data; |
| 2582 | nor->write = spi_nor_write_data; | 2527 | nor->write = spi_nor_write_data; |
| 2583 | nor->read_reg = spi_nor_read_reg; | 2528 | nor->read_reg = spi_nor_read_reg; |
| 2584 | nor->write_reg = spi_nor_write_reg; | 2529 | nor->write_reg = spi_nor_write_reg; |
| 2585 | 2530 | ||
| 2586 | if (spi->mode & SPI_RX_QUAD) { | 2531 | if (spi->mode & SPI_RX_QUAD) { |
| 2587 | hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; | 2532 | hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; |
| 2588 | 2533 | ||
| 2589 | if (spi->mode & SPI_TX_QUAD) | 2534 | if (spi->mode & SPI_TX_QUAD) |
| 2590 | hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | | 2535 | hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | |
| 2591 | SNOR_HWCAPS_PP_1_1_4 | | 2536 | SNOR_HWCAPS_PP_1_1_4 | |
| 2592 | SNOR_HWCAPS_PP_1_4_4); | 2537 | SNOR_HWCAPS_PP_1_4_4); |
| 2593 | } else if (spi->mode & SPI_RX_DUAL) { | 2538 | } else if (spi->mode & SPI_RX_DUAL) { |
| 2594 | hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; | 2539 | hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; |
| 2595 | 2540 | ||
| 2596 | if (spi->mode & SPI_TX_DUAL) | 2541 | if (spi->mode & SPI_TX_DUAL) |
| 2597 | hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; | 2542 | hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; |
| 2598 | } | 2543 | } |
| 2599 | 2544 | ||
| 2600 | info = spi_nor_read_id(nor); | 2545 | info = spi_nor_read_id(nor); |
| 2601 | if (IS_ERR_OR_NULL(info)) | 2546 | if (IS_ERR_OR_NULL(info)) |
| 2602 | return -ENOENT; | 2547 | return -ENOENT; |
| 2603 | /* Parse the Serial Flash Discoverable Parameters table. */ | 2548 | /* Parse the Serial Flash Discoverable Parameters table. */ |
| 2604 | ret = spi_nor_init_params(nor, info, ¶ms); | 2549 | ret = spi_nor_init_params(nor, info, ¶ms); |
| 2605 | if (ret) | 2550 | if (ret) |
| 2606 | return ret; | 2551 | return ret; |
| 2607 | 2552 | ||
| 2608 | if (!mtd->name) | 2553 | if (!mtd->name) |
| 2609 | mtd->name = info->name; | 2554 | mtd->name = info->name; |
| 2610 | mtd->priv = nor; | 2555 | mtd->priv = nor; |
| 2611 | mtd->type = MTD_NORFLASH; | 2556 | mtd->type = MTD_NORFLASH; |
| 2612 | mtd->writesize = 1; | 2557 | mtd->writesize = 1; |
| 2613 | mtd->flags = MTD_CAP_NORFLASH; | 2558 | mtd->flags = MTD_CAP_NORFLASH; |
| 2614 | mtd->size = params.size; | 2559 | mtd->size = params.size; |
| 2615 | mtd->_erase = spi_nor_erase; | 2560 | mtd->_erase = spi_nor_erase; |
| 2616 | mtd->_read = spi_nor_read; | 2561 | mtd->_read = spi_nor_read; |
| 2617 | 2562 | ||
| 2618 | #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) | 2563 | #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) |
| 2619 | /* NOR protection support for STmicro/Micron chips and similar */ | 2564 | /* NOR protection support for STmicro/Micron chips and similar */ |
| 2620 | if (JEDEC_MFR(info) == SNOR_MFR_ST || | 2565 | if (JEDEC_MFR(info) == SNOR_MFR_ST || |
| 2621 | JEDEC_MFR(info) == SNOR_MFR_MICRON || | 2566 | JEDEC_MFR(info) == SNOR_MFR_MICRON || |
| 2622 | JEDEC_MFR(info) == SNOR_MFR_SST || | 2567 | JEDEC_MFR(info) == SNOR_MFR_SST || |
| 2623 | info->flags & SPI_NOR_HAS_LOCK) { | 2568 | info->flags & SPI_NOR_HAS_LOCK) { |
| 2624 | nor->flash_lock = stm_lock; | 2569 | nor->flash_lock = stm_lock; |
| 2625 | nor->flash_unlock = stm_unlock; | 2570 | nor->flash_unlock = stm_unlock; |
| 2626 | nor->flash_is_locked = stm_is_locked; | 2571 | nor->flash_is_locked = stm_is_locked; |
| 2627 | } | 2572 | } |
| 2628 | #endif | 2573 | #endif |
| 2629 | 2574 | ||
| 2630 | #ifdef CONFIG_SPI_FLASH_SST | 2575 | #ifdef CONFIG_SPI_FLASH_SST |
| 2631 | /* sst nor chips use AAI word program */ | 2576 | /* sst nor chips use AAI word program */ |
| 2632 | if (info->flags & SST_WRITE) | 2577 | if (info->flags & SST_WRITE) |
| 2633 | mtd->_write = sst_write; | 2578 | mtd->_write = sst_write; |
| 2634 | else | 2579 | else |
| 2635 | #endif | 2580 | #endif |
| 2636 | mtd->_write = spi_nor_write; | 2581 | mtd->_write = spi_nor_write; |
| 2637 | 2582 | ||
| 2638 | if (info->flags & USE_FSR) | 2583 | if (info->flags & USE_FSR) |
| 2639 | nor->flags |= SNOR_F_USE_FSR; | 2584 | nor->flags |= SNOR_F_USE_FSR; |
| 2640 | if (info->flags & SPI_NOR_HAS_TB) | 2585 | if (info->flags & SPI_NOR_HAS_TB) |
| 2641 | nor->flags |= SNOR_F_HAS_SR_TB; | 2586 | nor->flags |= SNOR_F_HAS_SR_TB; |
| 2642 | if (info->flags & NO_CHIP_ERASE) | 2587 | if (info->flags & NO_CHIP_ERASE) |
| 2643 | nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; | 2588 | nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; |
| 2644 | if (info->flags & USE_CLSR) | 2589 | if (info->flags & USE_CLSR) |
| 2645 | nor->flags |= SNOR_F_USE_CLSR; | 2590 | nor->flags |= SNOR_F_USE_CLSR; |
| 2646 | 2591 | ||
| 2647 | if (info->flags & SPI_NOR_NO_ERASE) | 2592 | if (info->flags & SPI_NOR_NO_ERASE) |
| 2648 | mtd->flags |= MTD_NO_ERASE; | 2593 | mtd->flags |= MTD_NO_ERASE; |
| 2649 | 2594 | ||
| 2650 | nor->page_size = params.page_size; | 2595 | nor->page_size = params.page_size; |
| 2651 | mtd->writebufsize = nor->page_size; | 2596 | mtd->writebufsize = nor->page_size; |
| 2652 | 2597 | ||
| 2653 | /* Some devices cannot do fast-read, no matter what DT tells us */ | 2598 | /* Some devices cannot do fast-read, no matter what DT tells us */ |
| 2654 | if ((info->flags & SPI_NOR_NO_FR) || (spi->mode & SPI_RX_SLOW)) | 2599 | if ((info->flags & SPI_NOR_NO_FR) || (spi->mode & SPI_RX_SLOW)) |
| 2655 | params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST; | 2600 | params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST; |
| 2656 | 2601 | ||
| 2657 | /* | 2602 | /* |
| 2658 | * Configure the SPI memory: | 2603 | * Configure the SPI memory: |
| 2659 | * - select op codes for (Fast) Read, Page Program and Sector Erase. | 2604 | * - select op codes for (Fast) Read, Page Program and Sector Erase. |
| 2660 | * - set the number of dummy cycles (mode cycles + wait states). | 2605 | * - set the number of dummy cycles (mode cycles + wait states). |
| 2661 | * - set the SPI protocols for register and memory accesses. | 2606 | * - set the SPI protocols for register and memory accesses. |
| 2662 | * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). | 2607 | * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). |
| 2663 | */ | 2608 | */ |
| 2664 | ret = spi_nor_setup(nor, info, ¶ms, &hwcaps); | 2609 | ret = spi_nor_setup(nor, info, ¶ms, &hwcaps); |
| 2665 | if (ret) | 2610 | if (ret) |
| 2666 | return ret; | 2611 | return ret; |
| 2667 | 2612 | ||
| 2668 | if (nor->addr_width) { | 2613 | if (nor->addr_width) { |
| 2669 | /* already configured from SFDP */ | 2614 | /* already configured from SFDP */ |
| 2670 | } else if (info->addr_width) { | 2615 | } else if (info->addr_width) { |
| 2671 | nor->addr_width = info->addr_width; | 2616 | nor->addr_width = info->addr_width; |
| 2672 | } else if (mtd->size > SZ_16M) { | 2617 | } else if (mtd->size > SZ_16M) { |
| 2673 | #ifndef CONFIG_SPI_FLASH_BAR | 2618 | #ifndef CONFIG_SPI_FLASH_BAR |
| 2674 | /* enable 4-byte addressing if the device exceeds 16MiB */ | 2619 | /* enable 4-byte addressing if the device exceeds 16MiB */ |
| 2675 | nor->addr_width = 4; | 2620 | nor->addr_width = 4; |
| 2676 | if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || | 2621 | if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || |
| 2677 | info->flags & SPI_NOR_4B_OPCODES) | 2622 | info->flags & SPI_NOR_4B_OPCODES) |
| 2678 | spi_nor_set_4byte_opcodes(nor, info); | 2623 | spi_nor_set_4byte_opcodes(nor, info); |
| 2679 | #else | 2624 | #else |
| 2680 | /* Configure the BAR - discover bank cmds and read current bank */ | 2625 | /* Configure the BAR - discover bank cmds and read current bank */ |
| 2681 | nor->addr_width = 3; | 2626 | nor->addr_width = 3; |
| 2682 | ret = read_bar(nor, info); | 2627 | ret = read_bar(nor, info); |
| 2683 | if (ret < 0) | 2628 | if (ret < 0) |
| 2684 | return ret; | 2629 | return ret; |
| 2685 | #endif | 2630 | #endif |
| 2686 | } else { | 2631 | } else { |
| 2687 | nor->addr_width = 3; | 2632 | nor->addr_width = 3; |
| 2688 | } | 2633 | } |
| 2689 | 2634 | ||
| 2690 | if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { | 2635 | if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { |
| 2691 | dev_dbg(dev, "address width is too large: %u\n", | 2636 | dev_dbg(dev, "address width is too large: %u\n", |
| 2692 | nor->addr_width); | 2637 | nor->addr_width); |
| 2693 | return -EINVAL; | 2638 | return -EINVAL; |
| 2694 | } | 2639 | } |
| 2695 | 2640 | ||
| 2696 | /* Send all the required SPI flash commands to initialize device */ | 2641 | /* Send all the required SPI flash commands to initialize device */ |
| 2697 | nor->info = info; | 2642 | nor->info = info; |
| 2698 | ret = spi_nor_init(nor); | 2643 | ret = spi_nor_init(nor); |
| 2699 | if (ret) | 2644 | if (ret) |
| 2700 | return ret; | 2645 | return ret; |
| 2701 | 2646 | ||
| 2702 | nor->name = mtd->name; | 2647 | nor->name = mtd->name; |
| 2703 | nor->size = mtd->size; | 2648 | nor->size = mtd->size; |
| 2704 | nor->erase_size = mtd->erasesize; | 2649 | nor->erase_size = mtd->erasesize; |
| 2705 | nor->sector_size = mtd->erasesize; | 2650 | nor->sector_size = mtd->erasesize; |
| 2706 | 2651 | ||
| 2707 | #ifndef CONFIG_SPL_BUILD | 2652 | #ifndef CONFIG_SPL_BUILD |
| 2708 | printf("SF: Detected %s with page size ", nor->name); | 2653 | printf("SF: Detected %s with page size ", nor->name); |
| 2709 | print_size(nor->page_size, ", erase size "); | 2654 | print_size(nor->page_size, ", erase size "); |
| 2710 | print_size(nor->erase_size, ", total "); | 2655 | print_size(nor->erase_size, ", total "); |
| 2711 | print_size(nor->size, ""); | 2656 | print_size(nor->size, ""); |
| 2712 | puts("\n"); | 2657 | puts("\n"); |
| 2713 | #endif | 2658 | #endif |
| 2714 | 2659 | ||
| 2715 | return 0; | 2660 | return 0; |
| 2716 | } | 2661 | } |
| 2717 | 2662 | ||
| 2718 | /* U-Boot specific functions, need to extend MTD to support these */ | 2663 | /* U-Boot specific functions, need to extend MTD to support these */ |
| 2719 | int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) | 2664 | int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) |
| 2720 | { | 2665 | { |
| 2721 | int sr = read_sr(nor); | 2666 | int sr = read_sr(nor); |
| 2722 | 2667 | ||
| 2723 | if (sr < 0) | 2668 | if (sr < 0) |
| 2724 | return sr; | 2669 | return sr; |
| 2725 | 2670 | ||
| 2726 | return (sr >> 2) & 7; | 2671 | return (sr >> 2) & 7; |
| 1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* | 2 | /* |
| 3 | * (C) Copyright 2016 | 3 | * (C) Copyright 2016 |
| 4 | * | 4 | * |
| 5 | * Michael Kurz, <michi.kurz@gmail.com> | 5 | * Michael Kurz, <michi.kurz@gmail.com> |
| 6 | * | 6 | * |
| 7 | * STM32 QSPI driver | 7 | * STM32 QSPI driver |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <common.h> | 10 | #include <common.h> |
| 11 | #include <clk.h> | 11 | #include <clk.h> |
| 12 | #include <dm.h> | 12 | #include <dm.h> |
| 13 | #include <errno.h> | 13 | #include <errno.h> |
| 14 | #include <malloc.h> | 14 | #include <malloc.h> |
| 15 | #include <reset.h> | 15 | #include <reset.h> |
| 16 | #include <spi.h> | 16 | #include <spi.h> |
| 17 | #include <spi_flash.h> | 17 | #include <spi_flash.h> |
| 18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
| 19 | #include <asm/arch/stm32.h> | 19 | #include <asm/arch/stm32.h> |
| 20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
| 21 | 21 | ||
| 22 | struct stm32_qspi_regs { | 22 | struct stm32_qspi_regs { |
| 23 | u32 cr; /* 0x00 */ | 23 | u32 cr; /* 0x00 */ |
| 24 | u32 dcr; /* 0x04 */ | 24 | u32 dcr; /* 0x04 */ |
| 25 | u32 sr; /* 0x08 */ | 25 | u32 sr; /* 0x08 */ |
| 26 | u32 fcr; /* 0x0C */ | 26 | u32 fcr; /* 0x0C */ |
| 27 | u32 dlr; /* 0x10 */ | 27 | u32 dlr; /* 0x10 */ |
| 28 | u32 ccr; /* 0x14 */ | 28 | u32 ccr; /* 0x14 */ |
| 29 | u32 ar; /* 0x18 */ | 29 | u32 ar; /* 0x18 */ |
| 30 | u32 abr; /* 0x1C */ | 30 | u32 abr; /* 0x1C */ |
| 31 | u32 dr; /* 0x20 */ | 31 | u32 dr; /* 0x20 */ |
| 32 | u32 psmkr; /* 0x24 */ | 32 | u32 psmkr; /* 0x24 */ |
| 33 | u32 psmar; /* 0x28 */ | 33 | u32 psmar; /* 0x28 */ |
| 34 | u32 pir; /* 0x2C */ | 34 | u32 pir; /* 0x2C */ |
| 35 | u32 lptr; /* 0x30 */ | 35 | u32 lptr; /* 0x30 */ |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | /* | 38 | /* |
| 39 | * QUADSPI control register | 39 | * QUADSPI control register |
| 40 | */ | 40 | */ |
| 41 | #define STM32_QSPI_CR_EN BIT(0) | 41 | #define STM32_QSPI_CR_EN BIT(0) |
| 42 | #define STM32_QSPI_CR_ABORT BIT(1) | 42 | #define STM32_QSPI_CR_ABORT BIT(1) |
| 43 | #define STM32_QSPI_CR_DMAEN BIT(2) | 43 | #define STM32_QSPI_CR_DMAEN BIT(2) |
| 44 | #define STM32_QSPI_CR_TCEN BIT(3) | 44 | #define STM32_QSPI_CR_TCEN BIT(3) |
| 45 | #define STM32_QSPI_CR_SSHIFT BIT(4) | 45 | #define STM32_QSPI_CR_SSHIFT BIT(4) |
| 46 | #define STM32_QSPI_CR_DFM BIT(6) | 46 | #define STM32_QSPI_CR_DFM BIT(6) |
| 47 | #define STM32_QSPI_CR_FSEL BIT(7) | 47 | #define STM32_QSPI_CR_FSEL BIT(7) |
| 48 | #define STM32_QSPI_CR_FTHRES_MASK GENMASK(4, 0) | 48 | #define STM32_QSPI_CR_FTHRES_MASK GENMASK(4, 0) |
| 49 | #define STM32_QSPI_CR_FTHRES_SHIFT (8) | 49 | #define STM32_QSPI_CR_FTHRES_SHIFT (8) |
| 50 | #define STM32_QSPI_CR_TEIE BIT(16) | 50 | #define STM32_QSPI_CR_TEIE BIT(16) |
| 51 | #define STM32_QSPI_CR_TCIE BIT(17) | 51 | #define STM32_QSPI_CR_TCIE BIT(17) |
| 52 | #define STM32_QSPI_CR_FTIE BIT(18) | 52 | #define STM32_QSPI_CR_FTIE BIT(18) |
| 53 | #define STM32_QSPI_CR_SMIE BIT(19) | 53 | #define STM32_QSPI_CR_SMIE BIT(19) |
| 54 | #define STM32_QSPI_CR_TOIE BIT(20) | 54 | #define STM32_QSPI_CR_TOIE BIT(20) |
| 55 | #define STM32_QSPI_CR_APMS BIT(22) | 55 | #define STM32_QSPI_CR_APMS BIT(22) |
| 56 | #define STM32_QSPI_CR_PMM BIT(23) | 56 | #define STM32_QSPI_CR_PMM BIT(23) |
| 57 | #define STM32_QSPI_CR_PRESCALER_MASK GENMASK(7, 0) | 57 | #define STM32_QSPI_CR_PRESCALER_MASK GENMASK(7, 0) |
| 58 | #define STM32_QSPI_CR_PRESCALER_SHIFT (24) | 58 | #define STM32_QSPI_CR_PRESCALER_SHIFT (24) |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * QUADSPI device configuration register | 61 | * QUADSPI device configuration register |
| 62 | */ | 62 | */ |
| 63 | #define STM32_QSPI_DCR_CKMODE BIT(0) | 63 | #define STM32_QSPI_DCR_CKMODE BIT(0) |
| 64 | #define STM32_QSPI_DCR_CSHT_MASK GENMASK(2, 0) | 64 | #define STM32_QSPI_DCR_CSHT_MASK GENMASK(2, 0) |
| 65 | #define STM32_QSPI_DCR_CSHT_SHIFT (8) | 65 | #define STM32_QSPI_DCR_CSHT_SHIFT (8) |
| 66 | #define STM32_QSPI_DCR_FSIZE_MASK GENMASK(4, 0) | 66 | #define STM32_QSPI_DCR_FSIZE_MASK GENMASK(4, 0) |
| 67 | #define STM32_QSPI_DCR_FSIZE_SHIFT (16) | 67 | #define STM32_QSPI_DCR_FSIZE_SHIFT (16) |
| 68 | 68 | ||
| 69 | /* | 69 | /* |
| 70 | * QUADSPI status register | 70 | * QUADSPI status register |
| 71 | */ | 71 | */ |
| 72 | #define STM32_QSPI_SR_TEF BIT(0) | 72 | #define STM32_QSPI_SR_TEF BIT(0) |
| 73 | #define STM32_QSPI_SR_TCF BIT(1) | 73 | #define STM32_QSPI_SR_TCF BIT(1) |
| 74 | #define STM32_QSPI_SR_FTF BIT(2) | 74 | #define STM32_QSPI_SR_FTF BIT(2) |
| 75 | #define STM32_QSPI_SR_SMF BIT(3) | 75 | #define STM32_QSPI_SR_SMF BIT(3) |
| 76 | #define STM32_QSPI_SR_TOF BIT(4) | 76 | #define STM32_QSPI_SR_TOF BIT(4) |
| 77 | #define STM32_QSPI_SR_BUSY BIT(5) | 77 | #define STM32_QSPI_SR_BUSY BIT(5) |
| 78 | #define STM32_QSPI_SR_FLEVEL_MASK GENMASK(5, 0) | 78 | #define STM32_QSPI_SR_FLEVEL_MASK GENMASK(5, 0) |
| 79 | #define STM32_QSPI_SR_FLEVEL_SHIFT (8) | 79 | #define STM32_QSPI_SR_FLEVEL_SHIFT (8) |
| 80 | 80 | ||
| 81 | /* | 81 | /* |
| 82 | * QUADSPI flag clear register | 82 | * QUADSPI flag clear register |
| 83 | */ | 83 | */ |
| 84 | #define STM32_QSPI_FCR_CTEF BIT(0) | 84 | #define STM32_QSPI_FCR_CTEF BIT(0) |
| 85 | #define STM32_QSPI_FCR_CTCF BIT(1) | 85 | #define STM32_QSPI_FCR_CTCF BIT(1) |
| 86 | #define STM32_QSPI_FCR_CSMF BIT(3) | 86 | #define STM32_QSPI_FCR_CSMF BIT(3) |
| 87 | #define STM32_QSPI_FCR_CTOF BIT(4) | 87 | #define STM32_QSPI_FCR_CTOF BIT(4) |
| 88 | 88 | ||
| 89 | /* | 89 | /* |
| 90 | * QUADSPI communication configuration register | 90 | * QUADSPI communication configuration register |
| 91 | */ | 91 | */ |
| 92 | #define STM32_QSPI_CCR_DDRM BIT(31) | 92 | #define STM32_QSPI_CCR_DDRM BIT(31) |
| 93 | #define STM32_QSPI_CCR_DHHC BIT(30) | 93 | #define STM32_QSPI_CCR_DHHC BIT(30) |
| 94 | #define STM32_QSPI_CCR_SIOO BIT(28) | 94 | #define STM32_QSPI_CCR_SIOO BIT(28) |
| 95 | #define STM32_QSPI_CCR_FMODE_SHIFT (26) | 95 | #define STM32_QSPI_CCR_FMODE_SHIFT (26) |
| 96 | #define STM32_QSPI_CCR_DMODE_SHIFT (24) | 96 | #define STM32_QSPI_CCR_DMODE_SHIFT (24) |
| 97 | #define STM32_QSPI_CCR_DCYC_SHIFT (18) | 97 | #define STM32_QSPI_CCR_DCYC_SHIFT (18) |
| 98 | #define STM32_QSPI_CCR_DCYC_MASK GENMASK(4, 0) | 98 | #define STM32_QSPI_CCR_DCYC_MASK GENMASK(4, 0) |
| 99 | #define STM32_QSPI_CCR_ABSIZE_SHIFT (16) | 99 | #define STM32_QSPI_CCR_ABSIZE_SHIFT (16) |
| 100 | #define STM32_QSPI_CCR_ABMODE_SHIFT (14) | 100 | #define STM32_QSPI_CCR_ABMODE_SHIFT (14) |
| 101 | #define STM32_QSPI_CCR_ADSIZE_SHIFT (12) | 101 | #define STM32_QSPI_CCR_ADSIZE_SHIFT (12) |
| 102 | #define STM32_QSPI_CCR_ADMODE_SHIFT (10) | 102 | #define STM32_QSPI_CCR_ADMODE_SHIFT (10) |
| 103 | #define STM32_QSPI_CCR_IMODE_SHIFT (8) | 103 | #define STM32_QSPI_CCR_IMODE_SHIFT (8) |
| 104 | #define STM32_QSPI_CCR_INSTRUCTION_MASK GENMASK(7, 0) | 104 | #define STM32_QSPI_CCR_INSTRUCTION_MASK GENMASK(7, 0) |
| 105 | 105 | ||
| 106 | enum STM32_QSPI_CCR_IMODE { | 106 | enum STM32_QSPI_CCR_IMODE { |
| 107 | STM32_QSPI_CCR_IMODE_NONE = 0, | 107 | STM32_QSPI_CCR_IMODE_NONE = 0, |
| 108 | STM32_QSPI_CCR_IMODE_ONE_LINE = 1, | 108 | STM32_QSPI_CCR_IMODE_ONE_LINE = 1, |
| 109 | STM32_QSPI_CCR_IMODE_TWO_LINE = 2, | 109 | STM32_QSPI_CCR_IMODE_TWO_LINE = 2, |
| 110 | STM32_QSPI_CCR_IMODE_FOUR_LINE = 3, | 110 | STM32_QSPI_CCR_IMODE_FOUR_LINE = 3, |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | enum STM32_QSPI_CCR_ADMODE { | 113 | enum STM32_QSPI_CCR_ADMODE { |
| 114 | STM32_QSPI_CCR_ADMODE_NONE = 0, | 114 | STM32_QSPI_CCR_ADMODE_NONE = 0, |
| 115 | STM32_QSPI_CCR_ADMODE_ONE_LINE = 1, | 115 | STM32_QSPI_CCR_ADMODE_ONE_LINE = 1, |
| 116 | STM32_QSPI_CCR_ADMODE_TWO_LINE = 2, | 116 | STM32_QSPI_CCR_ADMODE_TWO_LINE = 2, |
| 117 | STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3, | 117 | STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3, |
| 118 | }; | 118 | }; |
| 119 | 119 | ||
| 120 | enum STM32_QSPI_CCR_ADSIZE { | 120 | enum STM32_QSPI_CCR_ADSIZE { |
| 121 | STM32_QSPI_CCR_ADSIZE_8BIT = 0, | 121 | STM32_QSPI_CCR_ADSIZE_8BIT = 0, |
| 122 | STM32_QSPI_CCR_ADSIZE_16BIT = 1, | 122 | STM32_QSPI_CCR_ADSIZE_16BIT = 1, |
| 123 | STM32_QSPI_CCR_ADSIZE_24BIT = 2, | 123 | STM32_QSPI_CCR_ADSIZE_24BIT = 2, |
| 124 | STM32_QSPI_CCR_ADSIZE_32BIT = 3, | 124 | STM32_QSPI_CCR_ADSIZE_32BIT = 3, |
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | enum STM32_QSPI_CCR_ABMODE { | 127 | enum STM32_QSPI_CCR_ABMODE { |
| 128 | STM32_QSPI_CCR_ABMODE_NONE = 0, | 128 | STM32_QSPI_CCR_ABMODE_NONE = 0, |
| 129 | STM32_QSPI_CCR_ABMODE_ONE_LINE = 1, | 129 | STM32_QSPI_CCR_ABMODE_ONE_LINE = 1, |
| 130 | STM32_QSPI_CCR_ABMODE_TWO_LINE = 2, | 130 | STM32_QSPI_CCR_ABMODE_TWO_LINE = 2, |
| 131 | STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3, | 131 | STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | enum STM32_QSPI_CCR_ABSIZE { | 134 | enum STM32_QSPI_CCR_ABSIZE { |
| 135 | STM32_QSPI_CCR_ABSIZE_8BIT = 0, | 135 | STM32_QSPI_CCR_ABSIZE_8BIT = 0, |
| 136 | STM32_QSPI_CCR_ABSIZE_16BIT = 1, | 136 | STM32_QSPI_CCR_ABSIZE_16BIT = 1, |
| 137 | STM32_QSPI_CCR_ABSIZE_24BIT = 2, | 137 | STM32_QSPI_CCR_ABSIZE_24BIT = 2, |
| 138 | STM32_QSPI_CCR_ABSIZE_32BIT = 3, | 138 | STM32_QSPI_CCR_ABSIZE_32BIT = 3, |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
| 141 | enum STM32_QSPI_CCR_DMODE { | 141 | enum STM32_QSPI_CCR_DMODE { |
| 142 | STM32_QSPI_CCR_DMODE_NONE = 0, | 142 | STM32_QSPI_CCR_DMODE_NONE = 0, |
| 143 | STM32_QSPI_CCR_DMODE_ONE_LINE = 1, | 143 | STM32_QSPI_CCR_DMODE_ONE_LINE = 1, |
| 144 | STM32_QSPI_CCR_DMODE_TWO_LINE = 2, | 144 | STM32_QSPI_CCR_DMODE_TWO_LINE = 2, |
| 145 | STM32_QSPI_CCR_DMODE_FOUR_LINE = 3, | 145 | STM32_QSPI_CCR_DMODE_FOUR_LINE = 3, |
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | enum STM32_QSPI_CCR_FMODE { | 148 | enum STM32_QSPI_CCR_FMODE { |
| 149 | STM32_QSPI_CCR_IND_WRITE = 0, | 149 | STM32_QSPI_CCR_IND_WRITE = 0, |
| 150 | STM32_QSPI_CCR_IND_READ = 1, | 150 | STM32_QSPI_CCR_IND_READ = 1, |
| 151 | STM32_QSPI_CCR_AUTO_POLL = 2, | 151 | STM32_QSPI_CCR_AUTO_POLL = 2, |
| 152 | STM32_QSPI_CCR_MEM_MAP = 3, | 152 | STM32_QSPI_CCR_MEM_MAP = 3, |
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | /* default SCK frequency, unit: HZ */ | 155 | /* default SCK frequency, unit: HZ */ |
| 156 | #define STM32_QSPI_DEFAULT_SCK_FREQ 108000000 | 156 | #define STM32_QSPI_DEFAULT_SCK_FREQ 108000000 |
| 157 | 157 | ||
| 158 | #define STM32_MAX_NORCHIP 2 | 158 | #define STM32_MAX_NORCHIP 2 |
| 159 | 159 | ||
| 160 | struct stm32_qspi_platdata { | 160 | struct stm32_qspi_platdata { |
| 161 | u32 base; | 161 | u32 base; |
| 162 | u32 memory_map; | 162 | u32 memory_map; |
| 163 | u32 max_hz; | 163 | u32 max_hz; |
| 164 | }; | 164 | }; |
| 165 | 165 | ||
| 166 | struct stm32_qspi_priv { | 166 | struct stm32_qspi_priv { |
| 167 | struct stm32_qspi_regs *regs; | 167 | struct stm32_qspi_regs *regs; |
| 168 | ulong clock_rate; | 168 | ulong clock_rate; |
| 169 | u32 max_hz; | 169 | u32 max_hz; |
| 170 | u32 mode; | 170 | u32 mode; |
| 171 | 171 | ||
| 172 | u32 command; | 172 | u32 command; |
| 173 | u32 address; | 173 | u32 address; |
| 174 | u32 dummycycles; | 174 | u32 dummycycles; |
| 175 | #define CMD_HAS_ADR BIT(24) | 175 | #define CMD_HAS_ADR BIT(24) |
| 176 | #define CMD_HAS_DUMMY BIT(25) | 176 | #define CMD_HAS_DUMMY BIT(25) |
| 177 | #define CMD_HAS_DATA BIT(26) | 177 | #define CMD_HAS_DATA BIT(26) |
| 178 | }; | 178 | }; |
| 179 | 179 | ||
| 180 | static void _stm32_qspi_disable(struct stm32_qspi_priv *priv) | 180 | static void _stm32_qspi_disable(struct stm32_qspi_priv *priv) |
| 181 | { | 181 | { |
| 182 | clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); | 182 | clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | static void _stm32_qspi_enable(struct stm32_qspi_priv *priv) | 185 | static void _stm32_qspi_enable(struct stm32_qspi_priv *priv) |
| 186 | { | 186 | { |
| 187 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); | 187 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv) | 190 | static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv) |
| 191 | { | 191 | { |
| 192 | while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY) | 192 | while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY) |
| 193 | ; | 193 | ; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv) | 196 | static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv) |
| 197 | { | 197 | { |
| 198 | while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF)) | 198 | while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF)) |
| 199 | ; | 199 | ; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv) | 202 | static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv) |
| 203 | { | 203 | { |
| 204 | while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF)) | 204 | while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF)) |
| 205 | ; | 205 | ; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size) | 208 | static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size) |
| 209 | { | 209 | { |
| 210 | u32 fsize = fls(size) - 1; | 210 | u32 fsize = fls(size) - 1; |
| 211 | 211 | ||
| 212 | clrsetbits_le32(&priv->regs->dcr, | 212 | clrsetbits_le32(&priv->regs->dcr, |
| 213 | STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT, | 213 | STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT, |
| 214 | fsize << STM32_QSPI_DCR_FSIZE_SHIFT); | 214 | fsize << STM32_QSPI_DCR_FSIZE_SHIFT); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs) | 217 | static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs) |
| 218 | { | 218 | { |
| 219 | clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL, | 219 | clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL, |
| 220 | cs ? STM32_QSPI_CR_FSEL : 0); | 220 | cs ? STM32_QSPI_CR_FSEL : 0); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode) | 223 | static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode) |
| 224 | { | 224 | { |
| 225 | unsigned int ccr_reg = 0; | 225 | unsigned int ccr_reg = 0; |
| 226 | u8 imode, admode, dmode; | 226 | u8 imode, admode, dmode; |
| 227 | u32 mode = priv->mode; | 227 | u32 mode = priv->mode; |
| 228 | u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK); | 228 | u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK); |
| 229 | 229 | ||
| 230 | imode = STM32_QSPI_CCR_IMODE_ONE_LINE; | 230 | imode = STM32_QSPI_CCR_IMODE_ONE_LINE; |
| 231 | admode = STM32_QSPI_CCR_ADMODE_ONE_LINE; | 231 | admode = STM32_QSPI_CCR_ADMODE_ONE_LINE; |
| 232 | dmode = STM32_QSPI_CCR_DMODE_ONE_LINE; | 232 | dmode = STM32_QSPI_CCR_DMODE_ONE_LINE; |
| 233 | 233 | ||
| 234 | if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) { | 234 | if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) { |
| 235 | if (fmode == STM32_QSPI_CCR_IND_WRITE) { | 235 | if (fmode == STM32_QSPI_CCR_IND_WRITE) { |
| 236 | if (mode & SPI_TX_QUAD) | 236 | if (mode & SPI_TX_QUAD) |
| 237 | dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; | 237 | dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; |
| 238 | else if (mode & SPI_TX_DUAL) | 238 | else if (mode & SPI_TX_DUAL) |
| 239 | dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; | 239 | dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; |
| 240 | } else if ((fmode == STM32_QSPI_CCR_MEM_MAP) || | 240 | } else if ((fmode == STM32_QSPI_CCR_MEM_MAP) || |
| 241 | (fmode == STM32_QSPI_CCR_IND_READ)) { | 241 | (fmode == STM32_QSPI_CCR_IND_READ)) { |
| 242 | if (mode & SPI_RX_QUAD) | 242 | if (mode & SPI_RX_QUAD) |
| 243 | dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; | 243 | dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; |
| 244 | else if (mode & SPI_RX_DUAL) | 244 | else if (mode & SPI_RX_DUAL) |
| 245 | dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; | 245 | dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; |
| 246 | } | 246 | } |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | if (priv->command & CMD_HAS_DATA) | 249 | if (priv->command & CMD_HAS_DATA) |
| 250 | ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT); | 250 | ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT); |
| 251 | 251 | ||
| 252 | if (priv->command & CMD_HAS_DUMMY) | 252 | if (priv->command & CMD_HAS_DUMMY) |
| 253 | ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK) | 253 | ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK) |
| 254 | << STM32_QSPI_CCR_DCYC_SHIFT); | 254 | << STM32_QSPI_CCR_DCYC_SHIFT); |
| 255 | 255 | ||
| 256 | if (priv->command & CMD_HAS_ADR) { | 256 | if (priv->command & CMD_HAS_ADR) { |
| 257 | ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT | 257 | ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT |
| 258 | << STM32_QSPI_CCR_ADSIZE_SHIFT); | 258 | << STM32_QSPI_CCR_ADSIZE_SHIFT); |
| 259 | ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT); | 259 | ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT); | 262 | ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT); |
| 263 | ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT); | 263 | ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT); |
| 264 | ccr_reg |= cmd; | 264 | ccr_reg |= cmd; |
| 265 | 265 | ||
| 266 | return ccr_reg; | 266 | return ccr_reg; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, | 269 | static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, |
| 270 | struct spi_flash *flash) | 270 | struct spi_flash *flash) |
| 271 | { | 271 | { |
| 272 | unsigned int ccr_reg; | 272 | unsigned int ccr_reg; |
| 273 | 273 | ||
| 274 | priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA | 274 | priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA |
| 275 | | CMD_HAS_DUMMY; | 275 | | CMD_HAS_DUMMY; |
| 276 | priv->dummycycles = flash->dummy_byte * 8; | 276 | priv->dummycycles = flash->read_dummy; |
| 277 | 277 | ||
| 278 | ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); | 278 | ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); |
| 279 | 279 | ||
| 280 | _stm32_qspi_wait_for_not_busy(priv); | 280 | _stm32_qspi_wait_for_not_busy(priv); |
| 281 | 281 | ||
| 282 | writel(ccr_reg, &priv->regs->ccr); | 282 | writel(ccr_reg, &priv->regs->ccr); |
| 283 | 283 | ||
| 284 | priv->dummycycles = 0; | 284 | priv->dummycycles = 0; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv) | 287 | static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv) |
| 288 | { | 288 | { |
| 289 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT); | 289 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv, | 292 | static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv, |
| 293 | u32 length) | 293 | u32 length) |
| 294 | { | 294 | { |
| 295 | writel(length - 1, &priv->regs->dlr); | 295 | writel(length - 1, &priv->regs->dlr); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg) | 298 | static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg) |
| 299 | { | 299 | { |
| 300 | writel(cr_reg, &priv->regs->ccr); | 300 | writel(cr_reg, &priv->regs->ccr); |
| 301 | 301 | ||
| 302 | if (priv->command & CMD_HAS_ADR) | 302 | if (priv->command & CMD_HAS_ADR) |
| 303 | writel(priv->address, &priv->regs->ar); | 303 | writel(priv->address, &priv->regs->ar); |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv, | 306 | static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv, |
| 307 | struct spi_flash *flash, unsigned int bitlen, | 307 | struct spi_flash *flash, unsigned int bitlen, |
| 308 | const u8 *dout, u8 *din, unsigned long flags) | 308 | const u8 *dout, u8 *din, unsigned long flags) |
| 309 | { | 309 | { |
| 310 | unsigned int words = bitlen / 8; | 310 | unsigned int words = bitlen / 8; |
| 311 | u32 ccr_reg; | 311 | u32 ccr_reg; |
| 312 | int i; | 312 | int i; |
| 313 | 313 | ||
| 314 | if (flags & SPI_XFER_MMAP) { | 314 | if (flags & SPI_XFER_MMAP) { |
| 315 | _stm32_qspi_enable_mmap(priv, flash); | 315 | _stm32_qspi_enable_mmap(priv, flash); |
| 316 | return 0; | 316 | return 0; |
| 317 | } else if (flags & SPI_XFER_MMAP_END) { | 317 | } else if (flags & SPI_XFER_MMAP_END) { |
| 318 | _stm32_qspi_disable_mmap(priv); | 318 | _stm32_qspi_disable_mmap(priv); |
| 319 | return 0; | 319 | return 0; |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | if (bitlen == 0) | 322 | if (bitlen == 0) |
| 323 | return -1; | 323 | return -1; |
| 324 | 324 | ||
| 325 | if (bitlen % 8) { | 325 | if (bitlen % 8) { |
| 326 | debug("spi_xfer: Non byte aligned SPI transfer\n"); | 326 | debug("spi_xfer: Non byte aligned SPI transfer\n"); |
| 327 | return -1; | 327 | return -1; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | if (dout && din) { | 330 | if (dout && din) { |
| 331 | debug("spi_xfer: QSPI cannot have data in and data out set\n"); | 331 | debug("spi_xfer: QSPI cannot have data in and data out set\n"); |
| 332 | return -1; | 332 | return -1; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | if (!dout && (flags & SPI_XFER_BEGIN)) { | 335 | if (!dout && (flags & SPI_XFER_BEGIN)) { |
| 336 | debug("spi_xfer: QSPI transfer must begin with command\n"); | 336 | debug("spi_xfer: QSPI transfer must begin with command\n"); |
| 337 | return -1; | 337 | return -1; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | if (dout) { | 340 | if (dout) { |
| 341 | if (flags & SPI_XFER_BEGIN) { | 341 | if (flags & SPI_XFER_BEGIN) { |
| 342 | /* data is command */ | 342 | /* data is command */ |
| 343 | priv->command = dout[0] | CMD_HAS_DATA; | 343 | priv->command = dout[0] | CMD_HAS_DATA; |
| 344 | if (words >= 4) { | 344 | if (words >= 4) { |
| 345 | /* address is here too */ | 345 | /* address is here too */ |
| 346 | priv->address = (dout[1] << 16) | | 346 | priv->address = (dout[1] << 16) | |
| 347 | (dout[2] << 8) | dout[3]; | 347 | (dout[2] << 8) | dout[3]; |
| 348 | priv->command |= CMD_HAS_ADR; | 348 | priv->command |= CMD_HAS_ADR; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | if (words > 4) { | 351 | if (words > 4) { |
| 352 | /* rest is dummy bytes */ | 352 | /* rest is dummy bytes */ |
| 353 | priv->dummycycles = (words - 4) * 8; | 353 | priv->dummycycles = (words - 4) * 8; |
| 354 | priv->command |= CMD_HAS_DUMMY; | 354 | priv->command |= CMD_HAS_DUMMY; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | if (flags & SPI_XFER_END) { | 357 | if (flags & SPI_XFER_END) { |
| 358 | /* command without data */ | 358 | /* command without data */ |
| 359 | priv->command &= ~(CMD_HAS_DATA); | 359 | priv->command &= ~(CMD_HAS_DATA); |
| 360 | } | 360 | } |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | if (flags & SPI_XFER_END) { | 363 | if (flags & SPI_XFER_END) { |
| 364 | ccr_reg = _stm32_qspi_gen_ccr(priv, | 364 | ccr_reg = _stm32_qspi_gen_ccr(priv, |
| 365 | STM32_QSPI_CCR_IND_WRITE); | 365 | STM32_QSPI_CCR_IND_WRITE); |
| 366 | 366 | ||
| 367 | _stm32_qspi_wait_for_not_busy(priv); | 367 | _stm32_qspi_wait_for_not_busy(priv); |
| 368 | 368 | ||
| 369 | if (priv->command & CMD_HAS_DATA) | 369 | if (priv->command & CMD_HAS_DATA) |
| 370 | _stm32_qspi_set_xfer_length(priv, words); | 370 | _stm32_qspi_set_xfer_length(priv, words); |
| 371 | 371 | ||
| 372 | _stm32_qspi_start_xfer(priv, ccr_reg); | 372 | _stm32_qspi_start_xfer(priv, ccr_reg); |
| 373 | 373 | ||
| 374 | debug("%s: write: ccr:0x%08x adr:0x%08x\n", | 374 | debug("%s: write: ccr:0x%08x adr:0x%08x\n", |
| 375 | __func__, priv->regs->ccr, priv->regs->ar); | 375 | __func__, priv->regs->ccr, priv->regs->ar); |
| 376 | 376 | ||
| 377 | if (priv->command & CMD_HAS_DATA) { | 377 | if (priv->command & CMD_HAS_DATA) { |
| 378 | _stm32_qspi_wait_for_ftf(priv); | 378 | _stm32_qspi_wait_for_ftf(priv); |
| 379 | 379 | ||
| 380 | debug("%s: words:%d data:", __func__, words); | 380 | debug("%s: words:%d data:", __func__, words); |
| 381 | 381 | ||
| 382 | i = 0; | 382 | i = 0; |
| 383 | while (words > i) { | 383 | while (words > i) { |
| 384 | writeb(dout[i], &priv->regs->dr); | 384 | writeb(dout[i], &priv->regs->dr); |
| 385 | debug("%02x ", dout[i]); | 385 | debug("%02x ", dout[i]); |
| 386 | i++; | 386 | i++; |
| 387 | } | 387 | } |
| 388 | debug("\n"); | 388 | debug("\n"); |
| 389 | 389 | ||
| 390 | _stm32_qspi_wait_for_complete(priv); | 390 | _stm32_qspi_wait_for_complete(priv); |
| 391 | } else { | 391 | } else { |
| 392 | _stm32_qspi_wait_for_not_busy(priv); | 392 | _stm32_qspi_wait_for_not_busy(priv); |
| 393 | } | 393 | } |
| 394 | } | 394 | } |
| 395 | } else if (din) { | 395 | } else if (din) { |
| 396 | ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ); | 396 | ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ); |
| 397 | 397 | ||
| 398 | _stm32_qspi_wait_for_not_busy(priv); | 398 | _stm32_qspi_wait_for_not_busy(priv); |
| 399 | 399 | ||
| 400 | _stm32_qspi_set_xfer_length(priv, words); | 400 | _stm32_qspi_set_xfer_length(priv, words); |
| 401 | 401 | ||
| 402 | _stm32_qspi_start_xfer(priv, ccr_reg); | 402 | _stm32_qspi_start_xfer(priv, ccr_reg); |
| 403 | 403 | ||
| 404 | debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__, | 404 | debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__, |
| 405 | priv->regs->ccr, priv->regs->ar, priv->regs->dlr); | 405 | priv->regs->ccr, priv->regs->ar, priv->regs->dlr); |
| 406 | 406 | ||
| 407 | debug("%s: data:", __func__); | 407 | debug("%s: data:", __func__); |
| 408 | 408 | ||
| 409 | i = 0; | 409 | i = 0; |
| 410 | while (words > i) { | 410 | while (words > i) { |
| 411 | din[i] = readb(&priv->regs->dr); | 411 | din[i] = readb(&priv->regs->dr); |
| 412 | debug("%02x ", din[i]); | 412 | debug("%02x ", din[i]); |
| 413 | i++; | 413 | i++; |
| 414 | } | 414 | } |
| 415 | debug("\n"); | 415 | debug("\n"); |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | return 0; | 418 | return 0; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | static int stm32_qspi_ofdata_to_platdata(struct udevice *bus) | 421 | static int stm32_qspi_ofdata_to_platdata(struct udevice *bus) |
| 422 | { | 422 | { |
| 423 | struct resource res_regs, res_mem; | 423 | struct resource res_regs, res_mem; |
| 424 | struct stm32_qspi_platdata *plat = bus->platdata; | 424 | struct stm32_qspi_platdata *plat = bus->platdata; |
| 425 | int ret; | 425 | int ret; |
| 426 | 426 | ||
| 427 | ret = dev_read_resource_byname(bus, "qspi", &res_regs); | 427 | ret = dev_read_resource_byname(bus, "qspi", &res_regs); |
| 428 | if (ret) { | 428 | if (ret) { |
| 429 | debug("Error: can't get regs base addresses(ret = %d)!\n", ret); | 429 | debug("Error: can't get regs base addresses(ret = %d)!\n", ret); |
| 430 | return -ENOMEM; | 430 | return -ENOMEM; |
| 431 | } | 431 | } |
| 432 | ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem); | 432 | ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem); |
| 433 | if (ret) { | 433 | if (ret) { |
| 434 | debug("Error: can't get mmap base address(ret = %d)!\n", ret); | 434 | debug("Error: can't get mmap base address(ret = %d)!\n", ret); |
| 435 | return -ENOMEM; | 435 | return -ENOMEM; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency", | 438 | plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency", |
| 439 | STM32_QSPI_DEFAULT_SCK_FREQ); | 439 | STM32_QSPI_DEFAULT_SCK_FREQ); |
| 440 | 440 | ||
| 441 | plat->base = res_regs.start; | 441 | plat->base = res_regs.start; |
| 442 | plat->memory_map = res_mem.start; | 442 | plat->memory_map = res_mem.start; |
| 443 | 443 | ||
| 444 | debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n", | 444 | debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n", |
| 445 | __func__, | 445 | __func__, |
| 446 | plat->base, | 446 | plat->base, |
| 447 | plat->memory_map, | 447 | plat->memory_map, |
| 448 | plat->max_hz | 448 | plat->max_hz |
| 449 | ); | 449 | ); |
| 450 | 450 | ||
| 451 | return 0; | 451 | return 0; |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | static int stm32_qspi_probe(struct udevice *bus) | 454 | static int stm32_qspi_probe(struct udevice *bus) |
| 455 | { | 455 | { |
| 456 | struct stm32_qspi_platdata *plat = dev_get_platdata(bus); | 456 | struct stm32_qspi_platdata *plat = dev_get_platdata(bus); |
| 457 | struct stm32_qspi_priv *priv = dev_get_priv(bus); | 457 | struct stm32_qspi_priv *priv = dev_get_priv(bus); |
| 458 | struct dm_spi_bus *dm_spi_bus; | 458 | struct dm_spi_bus *dm_spi_bus; |
| 459 | struct clk clk; | 459 | struct clk clk; |
| 460 | struct reset_ctl reset_ctl; | 460 | struct reset_ctl reset_ctl; |
| 461 | int ret; | 461 | int ret; |
| 462 | 462 | ||
| 463 | dm_spi_bus = bus->uclass_priv; | 463 | dm_spi_bus = bus->uclass_priv; |
| 464 | 464 | ||
| 465 | dm_spi_bus->max_hz = plat->max_hz; | 465 | dm_spi_bus->max_hz = plat->max_hz; |
| 466 | 466 | ||
| 467 | priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base; | 467 | priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base; |
| 468 | 468 | ||
| 469 | priv->max_hz = plat->max_hz; | 469 | priv->max_hz = plat->max_hz; |
| 470 | 470 | ||
| 471 | ret = clk_get_by_index(bus, 0, &clk); | 471 | ret = clk_get_by_index(bus, 0, &clk); |
| 472 | if (ret < 0) | 472 | if (ret < 0) |
| 473 | return ret; | 473 | return ret; |
| 474 | 474 | ||
| 475 | ret = clk_enable(&clk); | 475 | ret = clk_enable(&clk); |
| 476 | 476 | ||
| 477 | if (ret) { | 477 | if (ret) { |
| 478 | dev_err(bus, "failed to enable clock\n"); | 478 | dev_err(bus, "failed to enable clock\n"); |
| 479 | return ret; | 479 | return ret; |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | priv->clock_rate = clk_get_rate(&clk); | 482 | priv->clock_rate = clk_get_rate(&clk); |
| 483 | if (priv->clock_rate < 0) { | 483 | if (priv->clock_rate < 0) { |
| 484 | clk_disable(&clk); | 484 | clk_disable(&clk); |
| 485 | return priv->clock_rate; | 485 | return priv->clock_rate; |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | ret = reset_get_by_index(bus, 0, &reset_ctl); | 488 | ret = reset_get_by_index(bus, 0, &reset_ctl); |
| 489 | if (ret) { | 489 | if (ret) { |
| 490 | if (ret != -ENOENT) { | 490 | if (ret != -ENOENT) { |
| 491 | dev_err(bus, "failed to get reset\n"); | 491 | dev_err(bus, "failed to get reset\n"); |
| 492 | clk_disable(&clk); | 492 | clk_disable(&clk); |
| 493 | return ret; | 493 | return ret; |
| 494 | } | 494 | } |
| 495 | } else { | 495 | } else { |
| 496 | /* Reset QSPI controller */ | 496 | /* Reset QSPI controller */ |
| 497 | reset_assert(&reset_ctl); | 497 | reset_assert(&reset_ctl); |
| 498 | udelay(2); | 498 | udelay(2); |
| 499 | reset_deassert(&reset_ctl); | 499 | reset_deassert(&reset_ctl); |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT); | 502 | setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT); |
| 503 | 503 | ||
| 504 | return 0; | 504 | return 0; |
| 505 | } | 505 | } |
| 506 | 506 | ||
| 507 | static int stm32_qspi_remove(struct udevice *bus) | 507 | static int stm32_qspi_remove(struct udevice *bus) |
| 508 | { | 508 | { |
| 509 | return 0; | 509 | return 0; |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | static int stm32_qspi_claim_bus(struct udevice *dev) | 512 | static int stm32_qspi_claim_bus(struct udevice *dev) |
| 513 | { | 513 | { |
| 514 | struct stm32_qspi_priv *priv; | 514 | struct stm32_qspi_priv *priv; |
| 515 | struct udevice *bus; | 515 | struct udevice *bus; |
| 516 | struct spi_flash *flash; | 516 | struct spi_flash *flash; |
| 517 | struct dm_spi_slave_platdata *slave_plat; | 517 | struct dm_spi_slave_platdata *slave_plat; |
| 518 | 518 | ||
| 519 | bus = dev->parent; | 519 | bus = dev->parent; |
| 520 | priv = dev_get_priv(bus); | 520 | priv = dev_get_priv(bus); |
| 521 | flash = dev_get_uclass_priv(dev); | 521 | flash = dev_get_uclass_priv(dev); |
| 522 | slave_plat = dev_get_parent_platdata(dev); | 522 | slave_plat = dev_get_parent_platdata(dev); |
| 523 | 523 | ||
| 524 | if (slave_plat->cs >= STM32_MAX_NORCHIP) | 524 | if (slave_plat->cs >= STM32_MAX_NORCHIP) |
| 525 | return -ENODEV; | 525 | return -ENODEV; |
| 526 | 526 | ||
| 527 | _stm32_qspi_set_cs(priv, slave_plat->cs); | 527 | _stm32_qspi_set_cs(priv, slave_plat->cs); |
| 528 | 528 | ||
| 529 | _stm32_qspi_set_flash_size(priv, flash->size); | 529 | _stm32_qspi_set_flash_size(priv, flash->size); |
| 530 | 530 | ||
| 531 | _stm32_qspi_enable(priv); | 531 | _stm32_qspi_enable(priv); |
| 532 | 532 | ||
| 533 | return 0; | 533 | return 0; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | static int stm32_qspi_release_bus(struct udevice *dev) | 536 | static int stm32_qspi_release_bus(struct udevice *dev) |
| 537 | { | 537 | { |
| 538 | struct stm32_qspi_priv *priv; | 538 | struct stm32_qspi_priv *priv; |
| 539 | struct udevice *bus; | 539 | struct udevice *bus; |
| 540 | 540 | ||
| 541 | bus = dev->parent; | 541 | bus = dev->parent; |
| 542 | priv = dev_get_priv(bus); | 542 | priv = dev_get_priv(bus); |
| 543 | 543 | ||
| 544 | _stm32_qspi_disable(priv); | 544 | _stm32_qspi_disable(priv); |
| 545 | 545 | ||
| 546 | return 0; | 546 | return 0; |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen, | 549 | static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen, |
| 550 | const void *dout, void *din, unsigned long flags) | 550 | const void *dout, void *din, unsigned long flags) |
| 551 | { | 551 | { |
| 552 | struct stm32_qspi_priv *priv; | 552 | struct stm32_qspi_priv *priv; |
| 553 | struct udevice *bus; | 553 | struct udevice *bus; |
| 554 | struct spi_flash *flash; | 554 | struct spi_flash *flash; |
| 555 | 555 | ||
| 556 | bus = dev->parent; | 556 | bus = dev->parent; |
| 557 | priv = dev_get_priv(bus); | 557 | priv = dev_get_priv(bus); |
| 558 | flash = dev_get_uclass_priv(dev); | 558 | flash = dev_get_uclass_priv(dev); |
| 559 | 559 | ||
| 560 | return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout, | 560 | return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout, |
| 561 | (u8 *)din, flags); | 561 | (u8 *)din, flags); |
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | static int stm32_qspi_set_speed(struct udevice *bus, uint speed) | 564 | static int stm32_qspi_set_speed(struct udevice *bus, uint speed) |
| 565 | { | 565 | { |
| 566 | struct stm32_qspi_platdata *plat = bus->platdata; | 566 | struct stm32_qspi_platdata *plat = bus->platdata; |
| 567 | struct stm32_qspi_priv *priv = dev_get_priv(bus); | 567 | struct stm32_qspi_priv *priv = dev_get_priv(bus); |
| 568 | u32 qspi_clk = priv->clock_rate; | 568 | u32 qspi_clk = priv->clock_rate; |
| 569 | u32 prescaler = 255; | 569 | u32 prescaler = 255; |
| 570 | u32 csht; | 570 | u32 csht; |
| 571 | 571 | ||
| 572 | if (speed > plat->max_hz) | 572 | if (speed > plat->max_hz) |
| 573 | speed = plat->max_hz; | 573 | speed = plat->max_hz; |
| 574 | 574 | ||
| 575 | if (speed > 0) { | 575 | if (speed > 0) { |
| 576 | prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1; | 576 | prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1; |
| 577 | if (prescaler > 255) | 577 | if (prescaler > 255) |
| 578 | prescaler = 255; | 578 | prescaler = 255; |
| 579 | else if (prescaler < 0) | 579 | else if (prescaler < 0) |
| 580 | prescaler = 0; | 580 | prescaler = 0; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000); | 583 | csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000); |
| 584 | csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK; | 584 | csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK; |
| 585 | 585 | ||
| 586 | _stm32_qspi_wait_for_not_busy(priv); | 586 | _stm32_qspi_wait_for_not_busy(priv); |
| 587 | 587 | ||
| 588 | clrsetbits_le32(&priv->regs->cr, | 588 | clrsetbits_le32(&priv->regs->cr, |
| 589 | STM32_QSPI_CR_PRESCALER_MASK << | 589 | STM32_QSPI_CR_PRESCALER_MASK << |
| 590 | STM32_QSPI_CR_PRESCALER_SHIFT, | 590 | STM32_QSPI_CR_PRESCALER_SHIFT, |
| 591 | prescaler << STM32_QSPI_CR_PRESCALER_SHIFT); | 591 | prescaler << STM32_QSPI_CR_PRESCALER_SHIFT); |
| 592 | 592 | ||
| 593 | clrsetbits_le32(&priv->regs->dcr, | 593 | clrsetbits_le32(&priv->regs->dcr, |
| 594 | STM32_QSPI_DCR_CSHT_MASK << STM32_QSPI_DCR_CSHT_SHIFT, | 594 | STM32_QSPI_DCR_CSHT_MASK << STM32_QSPI_DCR_CSHT_SHIFT, |
| 595 | csht << STM32_QSPI_DCR_CSHT_SHIFT); | 595 | csht << STM32_QSPI_DCR_CSHT_SHIFT); |
| 596 | 596 | ||
| 597 | debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, | 597 | debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, |
| 598 | (qspi_clk / (prescaler + 1))); | 598 | (qspi_clk / (prescaler + 1))); |
| 599 | 599 | ||
| 600 | return 0; | 600 | return 0; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | static int stm32_qspi_set_mode(struct udevice *bus, uint mode) | 603 | static int stm32_qspi_set_mode(struct udevice *bus, uint mode) |
| 604 | { | 604 | { |
| 605 | struct stm32_qspi_priv *priv = dev_get_priv(bus); | 605 | struct stm32_qspi_priv *priv = dev_get_priv(bus); |
| 606 | 606 | ||
| 607 | _stm32_qspi_wait_for_not_busy(priv); | 607 | _stm32_qspi_wait_for_not_busy(priv); |
| 608 | 608 | ||
| 609 | if ((mode & SPI_CPHA) && (mode & SPI_CPOL)) | 609 | if ((mode & SPI_CPHA) && (mode & SPI_CPOL)) |
| 610 | setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE); | 610 | setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE); |
| 611 | else if (!(mode & SPI_CPHA) && !(mode & SPI_CPOL)) | 611 | else if (!(mode & SPI_CPHA) && !(mode & SPI_CPOL)) |
| 612 | clrbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE); | 612 | clrbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE); |
| 613 | else | 613 | else |
| 614 | return -ENODEV; | 614 | return -ENODEV; |
| 615 | 615 | ||
| 616 | if (mode & SPI_CS_HIGH) | 616 | if (mode & SPI_CS_HIGH) |
| 617 | return -ENODEV; | 617 | return -ENODEV; |
| 618 | 618 | ||
| 619 | if (mode & SPI_RX_QUAD) | 619 | if (mode & SPI_RX_QUAD) |
| 620 | priv->mode |= SPI_RX_QUAD; | 620 | priv->mode |= SPI_RX_QUAD; |
| 621 | else if (mode & SPI_RX_DUAL) | 621 | else if (mode & SPI_RX_DUAL) |
| 622 | priv->mode |= SPI_RX_DUAL; | 622 | priv->mode |= SPI_RX_DUAL; |
| 623 | else | 623 | else |
| 624 | priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL); | 624 | priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL); |
| 625 | 625 | ||
| 626 | if (mode & SPI_TX_QUAD) | 626 | if (mode & SPI_TX_QUAD) |
| 627 | priv->mode |= SPI_TX_QUAD; | 627 | priv->mode |= SPI_TX_QUAD; |
| 628 | else if (mode & SPI_TX_DUAL) | 628 | else if (mode & SPI_TX_DUAL) |
| 629 | priv->mode |= SPI_TX_DUAL; | 629 | priv->mode |= SPI_TX_DUAL; |
| 630 | else | 630 | else |
| 631 | priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL); | 631 | priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL); |
| 632 | 632 | ||
| 633 | debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode); | 633 | debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode); |
| 634 | 634 | ||
| 635 | if (mode & SPI_RX_QUAD) | 635 | if (mode & SPI_RX_QUAD) |
| 636 | debug("quad, tx: "); | 636 | debug("quad, tx: "); |
| 637 | else if (mode & SPI_RX_DUAL) | 637 | else if (mode & SPI_RX_DUAL) |
| 638 | debug("dual, tx: "); | 638 | debug("dual, tx: "); |
| 639 | else | 639 | else |
| 640 | debug("single, tx: "); | 640 | debug("single, tx: "); |
| 641 | 641 | ||
| 642 | if (mode & SPI_TX_QUAD) | 642 | if (mode & SPI_TX_QUAD) |
| 643 | debug("quad\n"); | 643 | debug("quad\n"); |
| 644 | else if (mode & SPI_TX_DUAL) | 644 | else if (mode & SPI_TX_DUAL) |
| 645 | debug("dual\n"); | 645 | debug("dual\n"); |
| 646 | else | 646 | else |
| 647 | debug("single\n"); | 647 | debug("single\n"); |
| 648 | 648 | ||
| 649 | return 0; | 649 | return 0; |
| 650 | } | 650 | } |
| 651 | 651 | ||
| 652 | static const struct dm_spi_ops stm32_qspi_ops = { | 652 | static const struct dm_spi_ops stm32_qspi_ops = { |
| 653 | .claim_bus = stm32_qspi_claim_bus, | 653 | .claim_bus = stm32_qspi_claim_bus, |
| 654 | .release_bus = stm32_qspi_release_bus, | 654 | .release_bus = stm32_qspi_release_bus, |
| 655 | .xfer = stm32_qspi_xfer, | 655 | .xfer = stm32_qspi_xfer, |
| 656 | .set_speed = stm32_qspi_set_speed, | 656 | .set_speed = stm32_qspi_set_speed, |
| 657 | .set_mode = stm32_qspi_set_mode, | 657 | .set_mode = stm32_qspi_set_mode, |
| 658 | }; | 658 | }; |
| 659 | 659 | ||
| 660 | static const struct udevice_id stm32_qspi_ids[] = { | 660 | static const struct udevice_id stm32_qspi_ids[] = { |
| 661 | { .compatible = "st,stm32-qspi" }, | 661 | { .compatible = "st,stm32-qspi" }, |
| 662 | { .compatible = "st,stm32f469-qspi" }, | 662 | { .compatible = "st,stm32f469-qspi" }, |
| 663 | { } | 663 | { } |
| 664 | }; | 664 | }; |
| 665 | 665 | ||
| 666 | U_BOOT_DRIVER(stm32_qspi) = { | 666 | U_BOOT_DRIVER(stm32_qspi) = { |
| 667 | .name = "stm32_qspi", | 667 | .name = "stm32_qspi", |
| 668 | .id = UCLASS_SPI, | 668 | .id = UCLASS_SPI, |
| 669 | .of_match = stm32_qspi_ids, | 669 | .of_match = stm32_qspi_ids, |
| 670 | .ops = &stm32_qspi_ops, | 670 | .ops = &stm32_qspi_ops, |
| 671 | .ofdata_to_platdata = stm32_qspi_ofdata_to_platdata, | 671 | .ofdata_to_platdata = stm32_qspi_ofdata_to_platdata, |
| 672 | .platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata), | 672 | .platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata), |
| 673 | .priv_auto_alloc_size = sizeof(struct stm32_qspi_priv), | 673 | .priv_auto_alloc_size = sizeof(struct stm32_qspi_priv), |
| 674 | .probe = stm32_qspi_probe, | 674 | .probe = stm32_qspi_probe, |
| 675 | .remove = stm32_qspi_remove, | 675 | .remove = stm32_qspi_remove, |
| 676 | }; | 676 | }; |
| 677 | 677 |
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* | 2 | /* |
| 3 | * Common SPI flash Interface | 3 | * Common SPI flash Interface |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2008 Atmel Corporation | 5 | * Copyright (C) 2008 Atmel Corporation |
| 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #ifndef _SPI_FLASH_H_ | 9 | #ifndef _SPI_FLASH_H_ |
| 10 | #define _SPI_FLASH_H_ | 10 | #define _SPI_FLASH_H_ |
| 11 | 11 | ||
| 12 | #include <dm.h> /* Because we dereference struct udevice here */ | 12 | #include <dm.h> /* Because we dereference struct udevice here */ |
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/mtd/spi-nor.h> | ||
| 14 | 15 | ||
| 15 | #ifndef CONFIG_SF_DEFAULT_SPEED | 16 | #ifndef CONFIG_SF_DEFAULT_SPEED |
| 16 | # define CONFIG_SF_DEFAULT_SPEED 1000000 | 17 | # define CONFIG_SF_DEFAULT_SPEED 1000000 |
| 17 | #endif | 18 | #endif |
| 18 | #ifndef CONFIG_SF_DEFAULT_MODE | 19 | #ifndef CONFIG_SF_DEFAULT_MODE |
| 19 | # define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 | 20 | # define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 |
| 20 | #endif | 21 | #endif |
| 21 | #ifndef CONFIG_SF_DEFAULT_CS | 22 | #ifndef CONFIG_SF_DEFAULT_CS |
| 22 | # define CONFIG_SF_DEFAULT_CS 0 | 23 | # define CONFIG_SF_DEFAULT_CS 0 |
| 23 | #endif | 24 | #endif |
| 24 | #ifndef CONFIG_SF_DEFAULT_BUS | 25 | #ifndef CONFIG_SF_DEFAULT_BUS |
| 25 | # define CONFIG_SF_DEFAULT_BUS 0 | 26 | # define CONFIG_SF_DEFAULT_BUS 0 |
| 26 | #endif | 27 | #endif |
| 27 | 28 | ||
| 28 | struct spi_slave; | 29 | struct spi_slave; |
| 29 | 30 | ||
| 30 | /** | ||
| 31 | * struct spi_flash - SPI flash structure | ||
| 32 | * | ||
| 33 | * @spi: SPI slave | ||
| 34 | * @dev: SPI flash device | ||
| 35 | * @name: Name of SPI flash | ||
| 36 | * @dual_flash: Indicates dual flash memories - dual stacked, parallel | ||
| 37 | * @shift: Flash shift useful in dual parallel | ||
| 38 | * @flags: Indication of spi flash flags | ||
| 39 | * @size: Total flash size | ||
| 40 | * @page_size: Write (page) size | ||
| 41 | * @sector_size: Sector size | ||
| 42 | * @erase_size: Erase size | ||
| 43 | * @bank_read_cmd: Bank read cmd | ||
| 44 | * @bank_write_cmd: Bank write cmd | ||
| 45 | * @bank_curr: Current flash bank | ||
| 46 | * @erase_cmd: Erase cmd 4K, 32K, 64K | ||
| 47 | * @read_cmd: Read cmd - Array Fast, Extn read and quad read. | ||
| 48 | * @write_cmd: Write cmd - page and quad program. | ||
| 49 | * @dummy_byte: Dummy cycles for read operation. | ||
| 50 | * @memory_map: Address of read-only SPI flash access | ||
| 51 | * @flash_lock: lock a region of the SPI Flash | ||
| 52 | * @flash_unlock: unlock a region of the SPI Flash | ||
| 53 | * @flash_is_locked: check if a region of the SPI Flash is completely locked | ||
| 54 | * @read: Flash read ops: Read len bytes at offset into buf | ||
| 55 | * Supported cmds: Fast Array Read | ||
| 56 | * @write: Flash write ops: Write len bytes from buf into offset | ||
| 57 | * Supported cmds: Page Program | ||
| 58 | * @erase: Flash erase ops: Erase len bytes from offset | ||
| 59 | * Supported cmds: Sector erase 4K, 32K, 64K | ||
| 60 | * return 0 - Success, 1 - Failure | ||
| 61 | */ | ||
| 62 | struct spi_flash { | ||
| 63 | struct spi_slave *spi; | ||
| 64 | #ifdef CONFIG_DM_SPI_FLASH | ||
| 65 | struct udevice *dev; | ||
| 66 | #endif | ||
| 67 | const char *name; | ||
| 68 | u8 dual_flash; | ||
| 69 | u8 shift; | ||
| 70 | u16 flags; | ||
| 71 | |||
| 72 | u32 size; | ||
| 73 | u32 page_size; | ||
| 74 | u32 sector_size; | ||
| 75 | u32 erase_size; | ||
| 76 | #ifdef CONFIG_SPI_FLASH_BAR | ||
| 77 | u8 bank_read_cmd; | ||
| 78 | u8 bank_write_cmd; | ||
| 79 | u8 bank_curr; | ||
| 80 | #endif | ||
| 81 | u8 erase_cmd; | ||
| 82 | u8 read_cmd; | ||
| 83 | u8 write_cmd; | ||
| 84 | u8 dummy_byte; | ||
| 85 | |||
| 86 | void *memory_map; | ||
| 87 | |||
| 88 | int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 89 | int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 90 | int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); | ||
| 91 | #ifndef CONFIG_DM_SPI_FLASH | ||
| 92 | /* | ||
| 93 | * These are not strictly needed for driver model, but keep them here | ||
| 94 | * while the transition is in progress. | ||
| 95 | * | ||
| 96 | * Normally each driver would provide its own operations, but for | ||
| 97 | * SPI flash most chips use the same algorithms. One approach is | ||
| 98 | * to create a 'common' SPI flash device which knows how to talk | ||
| 99 | * to most devices, and then allow other drivers to be used instead | ||
| 100 | * if required, perhaps with a way of scanning through the list to | ||
| 101 | * find the driver that matches the device. | ||
| 102 | */ | ||
| 103 | int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); | ||
| 104 | int (*write)(struct spi_flash *flash, u32 offset, size_t len, | ||
| 105 | const void *buf); | ||
| 106 | int (*erase)(struct spi_flash *flash, u32 offset, size_t len); | ||
| 107 | #endif | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct dm_spi_flash_ops { | 31 | struct dm_spi_flash_ops { |
| 111 | int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); | 32 | int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); |
| 112 | int (*write)(struct udevice *dev, u32 offset, size_t len, | 33 | int (*write)(struct udevice *dev, u32 offset, size_t len, |
| 113 | const void *buf); | 34 | const void *buf); |
| 114 | int (*erase)(struct udevice *dev, u32 offset, size_t len); | 35 | int (*erase)(struct udevice *dev, u32 offset, size_t len); |
| 115 | /** | 36 | /** |
| 116 | * get_sw_write_prot() - Check state of software write-protect feature | 37 | * get_sw_write_prot() - Check state of software write-protect feature |
| 117 | * | 38 | * |
| 118 | * SPI flash chips can lock a region of the flash defined by a | 39 | * SPI flash chips can lock a region of the flash defined by a |
| 119 | * 'protected area'. This function checks if this protected area is | 40 | * 'protected area'. This function checks if this protected area is |
| 120 | * defined. | 41 | * defined. |
| 121 | * | 42 | * |
| 122 | * @dev: SPI flash device | 43 | * @dev: SPI flash device |
| 123 | * @return 0 if no region is write-protected, 1 if a region is | 44 | * @return 0 if no region is write-protected, 1 if a region is |
| 124 | * write-protected, -ENOSYS if the driver does not implement this, | 45 | * write-protected, -ENOSYS if the driver does not implement this, |
| 125 | * other -ve value on error | 46 | * other -ve value on error |
| 126 | */ | 47 | */ |
| 127 | int (*get_sw_write_prot)(struct udevice *dev); | 48 | int (*get_sw_write_prot)(struct udevice *dev); |
| 128 | }; | 49 | }; |
| 129 | 50 | ||
| 130 | /* Access the serial operations for a device */ | 51 | /* Access the serial operations for a device */ |
| 131 | #define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops) | 52 | #define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops) |
| 132 | 53 | ||
| 133 | #ifdef CONFIG_DM_SPI_FLASH | 54 | #ifdef CONFIG_DM_SPI_FLASH |
| 134 | /** | 55 | /** |
| 135 | * spi_flash_read_dm() - Read data from SPI flash | 56 | * spi_flash_read_dm() - Read data from SPI flash |
| 136 | * | 57 | * |
| 137 | * @dev: SPI flash device | 58 | * @dev: SPI flash device |
| 138 | * @offset: Offset into device in bytes to read from | 59 | * @offset: Offset into device in bytes to read from |
| 139 | * @len: Number of bytes to read | 60 | * @len: Number of bytes to read |
| 140 | * @buf: Buffer to put the data that is read | 61 | * @buf: Buffer to put the data that is read |
| 141 | * @return 0 if OK, -ve on error | 62 | * @return 0 if OK, -ve on error |
| 142 | */ | 63 | */ |
| 143 | int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf); | 64 | int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf); |
| 144 | 65 | ||
| 145 | /** | 66 | /** |
| 146 | * spi_flash_write_dm() - Write data to SPI flash | 67 | * spi_flash_write_dm() - Write data to SPI flash |
| 147 | * | 68 | * |
| 148 | * @dev: SPI flash device | 69 | * @dev: SPI flash device |
| 149 | * @offset: Offset into device in bytes to write to | 70 | * @offset: Offset into device in bytes to write to |
| 150 | * @len: Number of bytes to write | 71 | * @len: Number of bytes to write |
| 151 | * @buf: Buffer containing bytes to write | 72 | * @buf: Buffer containing bytes to write |
| 152 | * @return 0 if OK, -ve on error | 73 | * @return 0 if OK, -ve on error |
| 153 | */ | 74 | */ |
| 154 | int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, | 75 | int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, |
| 155 | const void *buf); | 76 | const void *buf); |
| 156 | 77 | ||
| 157 | /** | 78 | /** |
| 158 | * spi_flash_erase_dm() - Erase blocks of the SPI flash | 79 | * spi_flash_erase_dm() - Erase blocks of the SPI flash |
| 159 | * | 80 | * |
| 160 | * Note that @len must be a muiltiple of the flash sector size. | 81 | * Note that @len must be a muiltiple of the flash sector size. |
| 161 | * | 82 | * |
| 162 | * @dev: SPI flash device | 83 | * @dev: SPI flash device |
| 163 | * @offset: Offset into device in bytes to start erasing | 84 | * @offset: Offset into device in bytes to start erasing |
| 164 | * @len: Number of bytes to erase | 85 | * @len: Number of bytes to erase |
| 165 | * @return 0 if OK, -ve on error | 86 | * @return 0 if OK, -ve on error |
| 166 | */ | 87 | */ |
| 167 | int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); | 88 | int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); |
| 168 | 89 | ||
| 169 | /** | 90 | /** |
| 170 | * spl_flash_get_sw_write_prot() - Check state of software write-protect feature | 91 | * spl_flash_get_sw_write_prot() - Check state of software write-protect feature |
| 171 | * | 92 | * |
| 172 | * SPI flash chips can lock a region of the flash defined by a | 93 | * SPI flash chips can lock a region of the flash defined by a |
| 173 | * 'protected area'. This function checks if this protected area is | 94 | * 'protected area'. This function checks if this protected area is |
| 174 | * defined. | 95 | * defined. |
| 175 | * | 96 | * |
| 176 | * @dev: SPI flash device | 97 | * @dev: SPI flash device |
| 177 | * @return 0 if no region is write-protected, 1 if a region is | 98 | * @return 0 if no region is write-protected, 1 if a region is |
| 178 | * write-protected, -ENOSYS if the driver does not implement this, | 99 | * write-protected, -ENOSYS if the driver does not implement this, |
| 179 | * other -ve value on error | 100 | * other -ve value on error |
| 180 | */ | 101 | */ |
| 181 | int spl_flash_get_sw_write_prot(struct udevice *dev); | 102 | int spl_flash_get_sw_write_prot(struct udevice *dev); |
| 182 | 103 | ||
| 183 | int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, | 104 | int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, |
| 184 | unsigned int max_hz, unsigned int spi_mode, | 105 | unsigned int max_hz, unsigned int spi_mode, |
| 185 | struct udevice **devp); | 106 | struct udevice **devp); |
| 186 | 107 | ||
| 187 | /* Compatibility function - this is the old U-Boot API */ | 108 | /* Compatibility function - this is the old U-Boot API */ |
| 188 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | 109 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, |
| 189 | unsigned int max_hz, unsigned int spi_mode); | 110 | unsigned int max_hz, unsigned int spi_mode); |
| 190 | 111 | ||
| 191 | /* Compatibility function - this is the old U-Boot API */ | 112 | /* Compatibility function - this is the old U-Boot API */ |
| 192 | void spi_flash_free(struct spi_flash *flash); | 113 | void spi_flash_free(struct spi_flash *flash); |
| 193 | 114 | ||
| 194 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, | 115 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, |
| 195 | size_t len, void *buf) | 116 | size_t len, void *buf) |
| 196 | { | 117 | { |
| 197 | return spi_flash_read_dm(flash->dev, offset, len, buf); | 118 | return spi_flash_read_dm(flash->dev, offset, len, buf); |
| 198 | } | 119 | } |
| 199 | 120 | ||
| 200 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, | 121 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, |
| 201 | size_t len, const void *buf) | 122 | size_t len, const void *buf) |
| 202 | { | 123 | { |
| 203 | return spi_flash_write_dm(flash->dev, offset, len, buf); | 124 | return spi_flash_write_dm(flash->dev, offset, len, buf); |
| 204 | } | 125 | } |
| 205 | 126 | ||
| 206 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, | 127 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, |
| 207 | size_t len) | 128 | size_t len) |
| 208 | { | 129 | { |
| 209 | return spi_flash_erase_dm(flash->dev, offset, len); | 130 | return spi_flash_erase_dm(flash->dev, offset, len); |
| 210 | } | 131 | } |
| 211 | 132 | ||
| 212 | struct sandbox_state; | 133 | struct sandbox_state; |
| 213 | 134 | ||
| 214 | int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, | 135 | int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, |
| 215 | struct udevice *bus, ofnode node, const char *spec); | 136 | struct udevice *bus, ofnode node, const char *spec); |
| 216 | 137 | ||
| 217 | void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs); | 138 | void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs); |
| 218 | 139 | ||
| 219 | #else | 140 | #else |
| 220 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | 141 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, |
| 221 | unsigned int max_hz, unsigned int spi_mode); | 142 | unsigned int max_hz, unsigned int spi_mode); |
| 222 | 143 | ||
| 223 | void spi_flash_free(struct spi_flash *flash); | 144 | void spi_flash_free(struct spi_flash *flash); |
| 224 | 145 | ||
| 225 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, | 146 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, |
| 226 | size_t len, void *buf) | 147 | size_t len, void *buf) |
| 227 | { | 148 | { |
| 228 | return flash->read(flash, offset, len, buf); | 149 | struct mtd_info *mtd = &flash->mtd; |
| 150 | size_t retlen; | ||
| 151 | |||
| 152 | return mtd->_read(mtd, offset, len, &retlen, buf); | ||
| 229 | } | 153 | } |
| 230 | 154 | ||
| 231 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, | 155 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, |
| 232 | size_t len, const void *buf) | 156 | size_t len, const void *buf) |
| 233 | { | 157 | { |
| 234 | return flash->write(flash, offset, len, buf); | 158 | struct mtd_info *mtd = &flash->mtd; |
| 159 | size_t retlen; | ||
| 160 | |||
| 161 | return mtd->_write(mtd, offset, len, &retlen, buf); | ||
| 235 | } | 162 | } |
| 236 | 163 | ||
| 237 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, | 164 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, |
| 238 | size_t len) | 165 | size_t len) |
| 239 | { | 166 | { |
| 240 | return flash->erase(flash, offset, len); | 167 | struct mtd_info *mtd = &flash->mtd; |
| 168 | struct erase_info instr; | ||
| 169 | |||
| 170 | if (offset % mtd->erasesize || len % mtd->erasesize) { | ||
| 171 | printf("SF: Erase offset/length not multiple of erase size\n"); | ||
| 172 | return -EINVAL; | ||
| 173 | } | ||
| 174 | |||
| 175 | memset(&instr, 0, sizeof(instr)); | ||
| 176 | instr.addr = offset; | ||
| 177 | instr.len = len; |
-
mentioned in commit 591353
-
mentioned in commit 591353
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8
-
mentioned in commit 591353
-
mentioned in commit e0cacd
-
mentioned in commit 718fd8