Commit 4e09cc1e2c5d22735d0fa3d2d1eaecd27e19948e
1 parent
12f00caf61
Exists in
master
and in
50 other branches
sf: Add extended read commands support
Current sf uses FAST_READ command, this patch adds support to use the different/extended read command. This implementation will determine the fastest command by taking the supported commands from the flash and the controller, controller is always been a priority. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
Showing 5 changed files with 126 additions and 86 deletions Inline Diff
drivers/mtd/spi/sf_internal.h
1 | /* | 1 | /* |
2 | * SPI flash internal definitions | 2 | * SPI flash internal definitions |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Atmel Corporation | 4 | * Copyright (C) 2008 Atmel Corporation |
5 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 5 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: GPL-2.0+ | 7 | * SPDX-License-Identifier: GPL-2.0+ |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef _SF_INTERNAL_H_ | 10 | #ifndef _SF_INTERNAL_H_ |
11 | #define _SF_INTERNAL_H_ | 11 | #define _SF_INTERNAL_H_ |
12 | 12 | ||
13 | #define SPI_FLASH_16MB_BOUN 0x1000000 | 13 | #define SPI_FLASH_16MB_BOUN 0x1000000 |
14 | 14 | ||
15 | /* SECT flags */ | 15 | /* SECT flags */ |
16 | #define SECT_4K (1 << 1) | 16 | #define SECT_4K (1 << 1) |
17 | #define SECT_32K (1 << 2) | 17 | #define SECT_32K (1 << 2) |
18 | #define E_FSR (1 << 3) | 18 | #define E_FSR (1 << 3) |
19 | 19 | ||
20 | /* Erase commands */ | 20 | /* Erase commands */ |
21 | #define CMD_ERASE_4K 0x20 | 21 | #define CMD_ERASE_4K 0x20 |
22 | #define CMD_ERASE_32K 0x52 | 22 | #define CMD_ERASE_32K 0x52 |
23 | #define CMD_ERASE_CHIP 0xc7 | 23 | #define CMD_ERASE_CHIP 0xc7 |
24 | #define CMD_ERASE_64K 0xd8 | 24 | #define CMD_ERASE_64K 0xd8 |
25 | 25 | ||
26 | /* Write commands */ | 26 | /* Write commands */ |
27 | #define CMD_WRITE_STATUS 0x01 | 27 | #define CMD_WRITE_STATUS 0x01 |
28 | #define CMD_PAGE_PROGRAM 0x02 | 28 | #define CMD_PAGE_PROGRAM 0x02 |
29 | #define CMD_WRITE_DISABLE 0x04 | 29 | #define CMD_WRITE_DISABLE 0x04 |
30 | #define CMD_READ_STATUS 0x05 | 30 | #define CMD_READ_STATUS 0x05 |
31 | #define CMD_READ_STATUS1 0x35 | 31 | #define CMD_READ_STATUS1 0x35 |
32 | #define CMD_WRITE_ENABLE 0x06 | 32 | #define CMD_WRITE_ENABLE 0x06 |
33 | #define CMD_READ_CONFIG 0x35 | 33 | #define CMD_READ_CONFIG 0x35 |
34 | #define CMD_FLAG_STATUS 0x70 | 34 | #define CMD_FLAG_STATUS 0x70 |
35 | 35 | ||
36 | /* Read commands */ | 36 | /* Read commands */ |
37 | #define CMD_READ_ARRAY_SLOW 0x03 | 37 | #define CMD_READ_ARRAY_SLOW 0x03 |
38 | #define CMD_READ_ARRAY_FAST 0x0b | 38 | #define CMD_READ_ARRAY_FAST 0x0b |
39 | #define CMD_READ_DUAL_OUTPUT_FAST 0x3b | ||
40 | #define CMD_READ_DUAL_IO_FAST 0xbb | ||
39 | #define CMD_READ_ID 0x9f | 41 | #define CMD_READ_ID 0x9f |
40 | 42 | ||
41 | /* Bank addr access commands */ | 43 | /* Bank addr access commands */ |
42 | #ifdef CONFIG_SPI_FLASH_BAR | 44 | #ifdef CONFIG_SPI_FLASH_BAR |
43 | # define CMD_BANKADDR_BRWR 0x17 | 45 | # define CMD_BANKADDR_BRWR 0x17 |
44 | # define CMD_BANKADDR_BRRD 0x16 | 46 | # define CMD_BANKADDR_BRRD 0x16 |
45 | # define CMD_EXTNADDR_WREAR 0xC5 | 47 | # define CMD_EXTNADDR_WREAR 0xC5 |
46 | # define CMD_EXTNADDR_RDEAR 0xC8 | 48 | # define CMD_EXTNADDR_RDEAR 0xC8 |
47 | #endif | 49 | #endif |
48 | 50 | ||
49 | /* Common status */ | 51 | /* Common status */ |
50 | #define STATUS_WIP 0x01 | 52 | #define STATUS_WIP 0x01 |
51 | #define STATUS_PEC 0x80 | 53 | #define STATUS_PEC 0x80 |
52 | 54 | ||
53 | /* Flash timeout values */ | 55 | /* Flash timeout values */ |
54 | #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) | 56 | #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) |
55 | #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) | 57 | #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) |
56 | #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) | 58 | #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) |
57 | 59 | ||
58 | /* SST specific */ | 60 | /* SST specific */ |
59 | #ifdef CONFIG_SPI_FLASH_SST | 61 | #ifdef CONFIG_SPI_FLASH_SST |
60 | # define SST_WP 0x01 /* Supports AAI word program */ | 62 | # define SST_WP 0x01 /* Supports AAI word program */ |
61 | # define CMD_SST_BP 0x02 /* Byte Program */ | 63 | # define CMD_SST_BP 0x02 /* Byte Program */ |
62 | # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ | 64 | # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ |
63 | 65 | ||
64 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | 66 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, |
65 | const void *buf); | 67 | const void *buf); |
66 | #endif | 68 | #endif |
67 | 69 | ||
68 | /* Send a single-byte command to the device and read the response */ | 70 | /* Send a single-byte command to the device and read the response */ |
69 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); | 71 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); |
70 | 72 | ||
71 | /* | 73 | /* |
72 | * Send a multi-byte command to the device and read the response. Used | 74 | * Send a multi-byte command to the device and read the response. Used |
73 | * for flash array reads, etc. | 75 | * for flash array reads, etc. |
74 | */ | 76 | */ |
75 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, | 77 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, |
76 | size_t cmd_len, void *data, size_t data_len); | 78 | size_t cmd_len, void *data, size_t data_len); |
77 | 79 | ||
78 | /* | 80 | /* |
79 | * Send a multi-byte command to the device followed by (optional) | 81 | * Send a multi-byte command to the device followed by (optional) |
80 | * data. Used for programming the flash array, etc. | 82 | * data. Used for programming the flash array, etc. |
81 | */ | 83 | */ |
82 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, | 84 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, |
83 | const void *data, size_t data_len); | 85 | const void *data, size_t data_len); |
84 | 86 | ||
85 | 87 | ||
86 | /* Flash erase(sectors) operation, support all possible erase commands */ | 88 | /* Flash erase(sectors) operation, support all possible erase commands */ |
87 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); | 89 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); |
88 | 90 | ||
89 | /* Program the status register */ | 91 | /* Program the status register */ |
90 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); | 92 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); |
91 | 93 | ||
92 | /* Set quad enbale bit */ | 94 | /* Set quad enbale bit */ |
93 | int spi_flash_set_qeb(struct spi_flash *flash); | 95 | int spi_flash_set_qeb(struct spi_flash *flash); |
94 | 96 | ||
95 | /* Enable writing on the SPI flash */ | 97 | /* Enable writing on the SPI flash */ |
96 | static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) | 98 | static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) |
97 | { | 99 | { |
98 | return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); | 100 | return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); |
99 | } | 101 | } |
100 | 102 | ||
101 | /* Disable writing on the SPI flash */ | 103 | /* Disable writing on the SPI flash */ |
102 | static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) | 104 | static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) |
103 | { | 105 | { |
104 | return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); | 106 | return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); |
105 | } | 107 | } |
106 | 108 | ||
107 | /* | 109 | /* |
108 | * Send the read status command to the device and wait for the wip | 110 | * Send the read status command to the device and wait for the wip |
109 | * (write-in-progress) bit to clear itself. | 111 | * (write-in-progress) bit to clear itself. |
110 | */ | 112 | */ |
111 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); | 113 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); |
112 | 114 | ||
113 | /* | 115 | /* |
114 | * Used for spi_flash write operation | 116 | * Used for spi_flash write operation |
115 | * - SPI claim | 117 | * - SPI claim |
116 | * - spi_flash_cmd_write_enable | 118 | * - spi_flash_cmd_write_enable |
117 | * - spi_flash_cmd_write | 119 | * - spi_flash_cmd_write |
118 | * - spi_flash_cmd_wait_ready | 120 | * - spi_flash_cmd_wait_ready |
119 | * - SPI release | 121 | * - SPI release |
120 | */ | 122 | */ |
121 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | 123 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, |
122 | size_t cmd_len, const void *buf, size_t buf_len); | 124 | size_t cmd_len, const void *buf, size_t buf_len); |
123 | 125 | ||
124 | /* | 126 | /* |
125 | * Flash write operation, support all possible write commands. | 127 | * Flash write operation, support all possible write commands. |
126 | * Write the requested data out breaking it up into multiple write | 128 | * Write the requested data out breaking it up into multiple write |
127 | * commands as needed per the write size. | 129 | * commands as needed per the write size. |
128 | */ | 130 | */ |
129 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | 131 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, |
130 | size_t len, const void *buf); | 132 | size_t len, const void *buf); |
131 | 133 | ||
132 | /* | 134 | /* |
133 | * Same as spi_flash_cmd_read() except it also claims/releases the SPI | 135 | * Same as spi_flash_cmd_read() except it also claims/releases the SPI |
134 | * bus. Used as common part of the ->read() operation. | 136 | * bus. Used as common part of the ->read() operation. |
135 | */ | 137 | */ |
136 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | 138 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, |
137 | size_t cmd_len, void *data, size_t data_len); | 139 | size_t cmd_len, void *data, size_t data_len); |
138 | 140 | ||
139 | /* Flash read operation, support all possible read commands */ | 141 | /* Flash read operation, support all possible read commands */ |
140 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | 142 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, |
141 | size_t len, void *data); | 143 | size_t len, void *data); |
142 | 144 | ||
143 | #endif /* _SF_INTERNAL_H_ */ | 145 | #endif /* _SF_INTERNAL_H_ */ |
144 | 146 |
drivers/mtd/spi/sf_ops.c
1 | /* | 1 | /* |
2 | * SPI flash operations | 2 | * SPI flash operations |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Atmel Corporation | 4 | * Copyright (C) 2008 Atmel Corporation |
5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik | 5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik |
6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
7 | * | 7 | * |
8 | * SPDX-License-Identifier: GPL-2.0+ | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <spi.h> | 12 | #include <spi.h> |
13 | #include <spi_flash.h> | 13 | #include <spi_flash.h> |
14 | #include <watchdog.h> | 14 | #include <watchdog.h> |
15 | 15 | ||
16 | #include "sf_internal.h" | 16 | #include "sf_internal.h" |
17 | 17 | ||
18 | static void spi_flash_addr(u32 addr, u8 *cmd) | 18 | static void spi_flash_addr(u32 addr, u8 *cmd) |
19 | { | 19 | { |
20 | /* cmd[0] is actual command */ | 20 | /* cmd[0] is actual command */ |
21 | cmd[1] = addr >> 16; | 21 | cmd[1] = addr >> 16; |
22 | cmd[2] = addr >> 8; | 22 | cmd[2] = addr >> 8; |
23 | cmd[3] = addr >> 0; | 23 | cmd[3] = addr >> 0; |
24 | } | 24 | } |
25 | 25 | ||
26 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) | 26 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) |
27 | { | 27 | { |
28 | u8 cmd; | 28 | u8 cmd; |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
31 | cmd = CMD_WRITE_STATUS; | 31 | cmd = CMD_WRITE_STATUS; |
32 | ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); | 32 | ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); |
33 | if (ret < 0) { | 33 | if (ret < 0) { |
34 | debug("SF: fail to write status register\n"); | 34 | debug("SF: fail to write status register\n"); |
35 | return ret; | 35 | return ret; |
36 | } | 36 | } |
37 | 37 | ||
38 | return 0; | 38 | return 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | #ifdef CONFIG_SPI_FLASH_BAR | 41 | #ifdef CONFIG_SPI_FLASH_BAR |
42 | static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) | 42 | static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) |
43 | { | 43 | { |
44 | u8 cmd; | 44 | u8 cmd; |
45 | int ret; | 45 | int ret; |
46 | 46 | ||
47 | if (flash->bank_curr == bank_sel) { | 47 | if (flash->bank_curr == bank_sel) { |
48 | debug("SF: not require to enable bank%d\n", bank_sel); | 48 | debug("SF: not require to enable bank%d\n", bank_sel); |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | cmd = flash->bank_write_cmd; | 52 | cmd = flash->bank_write_cmd; |
53 | ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); | 53 | ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); |
54 | if (ret < 0) { | 54 | if (ret < 0) { |
55 | debug("SF: fail to write bank register\n"); | 55 | debug("SF: fail to write bank register\n"); |
56 | return ret; | 56 | return ret; |
57 | } | 57 | } |
58 | flash->bank_curr = bank_sel; | 58 | flash->bank_curr = bank_sel; |
59 | 59 | ||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | static int spi_flash_bank(struct spi_flash *flash, u32 offset) | 63 | static int spi_flash_bank(struct spi_flash *flash, u32 offset) |
64 | { | 64 | { |
65 | u8 bank_sel; | 65 | u8 bank_sel; |
66 | int ret; | 66 | int ret; |
67 | 67 | ||
68 | bank_sel = offset / SPI_FLASH_16MB_BOUN; | 68 | bank_sel = offset / SPI_FLASH_16MB_BOUN; |
69 | 69 | ||
70 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); | 70 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); |
71 | if (ret) { | 71 | if (ret) { |
72 | debug("SF: fail to set bank%d\n", bank_sel); | 72 | debug("SF: fail to set bank%d\n", bank_sel); |
73 | return ret; | 73 | return ret; |
74 | } | 74 | } |
75 | 75 | ||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) | 80 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) |
81 | { | 81 | { |
82 | struct spi_slave *spi = flash->spi; | 82 | struct spi_slave *spi = flash->spi; |
83 | unsigned long timebase; | 83 | unsigned long timebase; |
84 | int ret; | 84 | int ret; |
85 | u8 status; | 85 | u8 status; |
86 | u8 check_status = 0x0; | 86 | u8 check_status = 0x0; |
87 | u8 poll_bit = STATUS_WIP; | 87 | u8 poll_bit = STATUS_WIP; |
88 | u8 cmd = flash->poll_cmd; | 88 | u8 cmd = flash->poll_cmd; |
89 | 89 | ||
90 | if (cmd == CMD_FLAG_STATUS) { | 90 | if (cmd == CMD_FLAG_STATUS) { |
91 | poll_bit = STATUS_PEC; | 91 | poll_bit = STATUS_PEC; |
92 | check_status = poll_bit; | 92 | check_status = poll_bit; |
93 | } | 93 | } |
94 | 94 | ||
95 | ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); | 95 | ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); |
96 | if (ret) { | 96 | if (ret) { |
97 | debug("SF: fail to read %s status register\n", | 97 | debug("SF: fail to read %s status register\n", |
98 | cmd == CMD_READ_STATUS ? "read" : "flag"); | 98 | cmd == CMD_READ_STATUS ? "read" : "flag"); |
99 | return ret; | 99 | return ret; |
100 | } | 100 | } |
101 | 101 | ||
102 | timebase = get_timer(0); | 102 | timebase = get_timer(0); |
103 | do { | 103 | do { |
104 | WATCHDOG_RESET(); | 104 | WATCHDOG_RESET(); |
105 | 105 | ||
106 | ret = spi_xfer(spi, 8, NULL, &status, 0); | 106 | ret = spi_xfer(spi, 8, NULL, &status, 0); |
107 | if (ret) | 107 | if (ret) |
108 | return -1; | 108 | return -1; |
109 | 109 | ||
110 | if ((status & poll_bit) == check_status) | 110 | if ((status & poll_bit) == check_status) |
111 | break; | 111 | break; |
112 | 112 | ||
113 | } while (get_timer(timebase) < timeout); | 113 | } while (get_timer(timebase) < timeout); |
114 | 114 | ||
115 | spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); | 115 | spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); |
116 | 116 | ||
117 | if ((status & poll_bit) == check_status) | 117 | if ((status & poll_bit) == check_status) |
118 | return 0; | 118 | return 0; |
119 | 119 | ||
120 | /* Timed out */ | 120 | /* Timed out */ |
121 | debug("SF: time out!\n"); | 121 | debug("SF: time out!\n"); |
122 | return -1; | 122 | return -1; |
123 | } | 123 | } |
124 | 124 | ||
125 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | 125 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, |
126 | size_t cmd_len, const void *buf, size_t buf_len) | 126 | size_t cmd_len, const void *buf, size_t buf_len) |
127 | { | 127 | { |
128 | struct spi_slave *spi = flash->spi; | 128 | struct spi_slave *spi = flash->spi; |
129 | unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; | 129 | unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; |
130 | int ret; | 130 | int ret; |
131 | 131 | ||
132 | if (buf == NULL) | 132 | if (buf == NULL) |
133 | timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; | 133 | timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; |
134 | 134 | ||
135 | ret = spi_claim_bus(flash->spi); | 135 | ret = spi_claim_bus(flash->spi); |
136 | if (ret) { | 136 | if (ret) { |
137 | debug("SF: unable to claim SPI bus\n"); | 137 | debug("SF: unable to claim SPI bus\n"); |
138 | return ret; | 138 | return ret; |
139 | } | 139 | } |
140 | 140 | ||
141 | ret = spi_flash_cmd_write_enable(flash); | 141 | ret = spi_flash_cmd_write_enable(flash); |
142 | if (ret < 0) { | 142 | if (ret < 0) { |
143 | debug("SF: enabling write failed\n"); | 143 | debug("SF: enabling write failed\n"); |
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
146 | 146 | ||
147 | ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); | 147 | ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); |
148 | if (ret < 0) { | 148 | if (ret < 0) { |
149 | debug("SF: write cmd failed\n"); | 149 | debug("SF: write cmd failed\n"); |
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
152 | 152 | ||
153 | ret = spi_flash_cmd_wait_ready(flash, timeout); | 153 | ret = spi_flash_cmd_wait_ready(flash, timeout); |
154 | if (ret < 0) { | 154 | if (ret < 0) { |
155 | debug("SF: write %s timed out\n", | 155 | debug("SF: write %s timed out\n", |
156 | timeout == SPI_FLASH_PROG_TIMEOUT ? | 156 | timeout == SPI_FLASH_PROG_TIMEOUT ? |
157 | "program" : "page erase"); | 157 | "program" : "page erase"); |
158 | return ret; | 158 | return ret; |
159 | } | 159 | } |
160 | 160 | ||
161 | spi_release_bus(spi); | 161 | spi_release_bus(spi); |
162 | 162 | ||
163 | return ret; | 163 | return ret; |
164 | } | 164 | } |
165 | 165 | ||
166 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) | 166 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) |
167 | { | 167 | { |
168 | u32 erase_size; | 168 | u32 erase_size; |
169 | u8 cmd[4]; | 169 | u8 cmd[4]; |
170 | int ret = -1; | 170 | int ret = -1; |
171 | 171 | ||
172 | erase_size = flash->erase_size; | 172 | erase_size = flash->erase_size; |
173 | if (offset % erase_size || len % erase_size) { | 173 | if (offset % erase_size || len % erase_size) { |
174 | debug("SF: Erase offset/length not multiple of erase size\n"); | 174 | debug("SF: Erase offset/length not multiple of erase size\n"); |
175 | return -1; | 175 | return -1; |
176 | } | 176 | } |
177 | 177 | ||
178 | cmd[0] = flash->erase_cmd; | 178 | cmd[0] = flash->erase_cmd; |
179 | while (len) { | 179 | while (len) { |
180 | #ifdef CONFIG_SPI_FLASH_BAR | 180 | #ifdef CONFIG_SPI_FLASH_BAR |
181 | ret = spi_flash_bank(flash, offset); | 181 | ret = spi_flash_bank(flash, offset); |
182 | if (ret < 0) | 182 | if (ret < 0) |
183 | return ret; | 183 | return ret; |
184 | #endif | 184 | #endif |
185 | spi_flash_addr(offset, cmd); | 185 | spi_flash_addr(offset, cmd); |
186 | 186 | ||
187 | debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], | 187 | debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], |
188 | cmd[2], cmd[3], offset); | 188 | cmd[2], cmd[3], offset); |
189 | 189 | ||
190 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); | 190 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); |
191 | if (ret < 0) { | 191 | if (ret < 0) { |
192 | debug("SF: erase failed\n"); | 192 | debug("SF: erase failed\n"); |
193 | break; | 193 | break; |
194 | } | 194 | } |
195 | 195 | ||
196 | offset += erase_size; | 196 | offset += erase_size; |
197 | len -= erase_size; | 197 | len -= erase_size; |
198 | } | 198 | } |
199 | 199 | ||
200 | return ret; | 200 | return ret; |
201 | } | 201 | } |
202 | 202 | ||
203 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | 203 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, |
204 | size_t len, const void *buf) | 204 | size_t len, const void *buf) |
205 | { | 205 | { |
206 | unsigned long byte_addr, page_size; | 206 | unsigned long byte_addr, page_size; |
207 | size_t chunk_len, actual; | 207 | size_t chunk_len, actual; |
208 | u8 cmd[4]; | 208 | u8 cmd[4]; |
209 | int ret = -1; | 209 | int ret = -1; |
210 | 210 | ||
211 | page_size = flash->page_size; | 211 | page_size = flash->page_size; |
212 | 212 | ||
213 | cmd[0] = CMD_PAGE_PROGRAM; | 213 | cmd[0] = CMD_PAGE_PROGRAM; |
214 | for (actual = 0; actual < len; actual += chunk_len) { | 214 | for (actual = 0; actual < len; actual += chunk_len) { |
215 | #ifdef CONFIG_SPI_FLASH_BAR | 215 | #ifdef CONFIG_SPI_FLASH_BAR |
216 | ret = spi_flash_bank(flash, offset); | 216 | ret = spi_flash_bank(flash, offset); |
217 | if (ret < 0) | 217 | if (ret < 0) |
218 | return ret; | 218 | return ret; |
219 | #endif | 219 | #endif |
220 | byte_addr = offset % page_size; | 220 | byte_addr = offset % page_size; |
221 | chunk_len = min(len - actual, page_size - byte_addr); | 221 | chunk_len = min(len - actual, page_size - byte_addr); |
222 | 222 | ||
223 | if (flash->spi->max_write_size) | 223 | if (flash->spi->max_write_size) |
224 | chunk_len = min(chunk_len, flash->spi->max_write_size); | 224 | chunk_len = min(chunk_len, flash->spi->max_write_size); |
225 | 225 | ||
226 | spi_flash_addr(offset, cmd); | 226 | spi_flash_addr(offset, cmd); |
227 | 227 | ||
228 | debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", | 228 | debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", |
229 | buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); | 229 | buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); |
230 | 230 | ||
231 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), | 231 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), |
232 | buf + actual, chunk_len); | 232 | buf + actual, chunk_len); |
233 | if (ret < 0) { | 233 | if (ret < 0) { |
234 | debug("SF: write failed\n"); | 234 | debug("SF: write failed\n"); |
235 | break; | 235 | break; |
236 | } | 236 | } |
237 | 237 | ||
238 | offset += chunk_len; | 238 | offset += chunk_len; |
239 | } | 239 | } |
240 | 240 | ||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | 244 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, |
245 | size_t cmd_len, void *data, size_t data_len) | 245 | size_t cmd_len, void *data, size_t data_len) |
246 | { | 246 | { |
247 | struct spi_slave *spi = flash->spi; | 247 | struct spi_slave *spi = flash->spi; |
248 | int ret; | 248 | int ret; |
249 | 249 | ||
250 | ret = spi_claim_bus(flash->spi); | 250 | ret = spi_claim_bus(flash->spi); |
251 | if (ret) { | 251 | if (ret) { |
252 | debug("SF: unable to claim SPI bus\n"); | 252 | debug("SF: unable to claim SPI bus\n"); |
253 | return ret; | 253 | return ret; |
254 | } | 254 | } |
255 | 255 | ||
256 | ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); | 256 | ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); |
257 | if (ret < 0) { | 257 | if (ret < 0) { |
258 | debug("SF: read cmd failed\n"); | 258 | debug("SF: read cmd failed\n"); |
259 | return ret; | 259 | return ret; |
260 | } | 260 | } |
261 | 261 | ||
262 | spi_release_bus(spi); | 262 | spi_release_bus(spi); |
263 | 263 | ||
264 | return ret; | 264 | return ret; |
265 | } | 265 | } |
266 | 266 | ||
267 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | 267 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, |
268 | size_t len, void *data) | 268 | size_t len, void *data) |
269 | { | 269 | { |
270 | u8 cmd[5], bank_sel = 0; | 270 | u8 cmd[5], bank_sel = 0; |
271 | u32 remain_len, read_len; | 271 | u32 remain_len, read_len; |
272 | int ret = -1; | 272 | int ret = -1; |
273 | 273 | ||
274 | /* Handle memory-mapped SPI */ | 274 | /* Handle memory-mapped SPI */ |
275 | if (flash->memory_map) { | 275 | if (flash->memory_map) { |
276 | ret = spi_claim_bus(flash->spi); | 276 | ret = spi_claim_bus(flash->spi); |
277 | if (ret) { | 277 | if (ret) { |
278 | debug("SF: unable to claim SPI bus\n"); | 278 | debug("SF: unable to claim SPI bus\n"); |
279 | return ret; | 279 | return ret; |
280 | } | 280 | } |
281 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); | 281 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); |
282 | memcpy(data, flash->memory_map + offset, len); | 282 | memcpy(data, flash->memory_map + offset, len); |
283 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); | 283 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); |
284 | spi_release_bus(flash->spi); | 284 | spi_release_bus(flash->spi); |
285 | return 0; | 285 | return 0; |
286 | } | 286 | } |
287 | 287 | ||
288 | cmd[0] = CMD_READ_ARRAY_FAST; | 288 | cmd[0] = flash->read_cmd; |
289 | cmd[4] = 0x00; | 289 | cmd[4] = 0x00; |
290 | 290 | ||
291 | while (len) { | 291 | while (len) { |
292 | #ifdef CONFIG_SPI_FLASH_BAR | 292 | #ifdef CONFIG_SPI_FLASH_BAR |
293 | bank_sel = offset / SPI_FLASH_16MB_BOUN; | 293 | bank_sel = offset / SPI_FLASH_16MB_BOUN; |
294 | 294 | ||
295 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); | 295 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); |
296 | if (ret) { | 296 | if (ret) { |
297 | debug("SF: fail to set bank%d\n", bank_sel); | 297 | debug("SF: fail to set bank%d\n", bank_sel); |
298 | return ret; | 298 | return ret; |
299 | } | 299 | } |
300 | #endif | 300 | #endif |
301 | remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; | 301 | remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; |
302 | if (len < remain_len) | 302 | if (len < remain_len) |
303 | read_len = len; | 303 | read_len = len; |
304 | else | 304 | else |
305 | read_len = remain_len; | 305 | read_len = remain_len; |
306 | 306 | ||
307 | spi_flash_addr(offset, cmd); | 307 | spi_flash_addr(offset, cmd); |
308 | 308 | ||
309 | ret = spi_flash_read_common(flash, cmd, sizeof(cmd), | 309 | ret = spi_flash_read_common(flash, cmd, sizeof(cmd), |
310 | data, read_len); | 310 | data, read_len); |
311 | if (ret < 0) { | 311 | if (ret < 0) { |
312 | debug("SF: read failed\n"); | 312 | debug("SF: read failed\n"); |
313 | break; | 313 | break; |
314 | } | 314 | } |
315 | 315 | ||
316 | offset += read_len; | 316 | offset += read_len; |
317 | len -= read_len; | 317 | len -= read_len; |
318 | data += read_len; | 318 | data += read_len; |
319 | } | 319 | } |
320 | 320 | ||
321 | return ret; | 321 | return ret; |
322 | } | 322 | } |
323 | 323 | ||
324 | #ifdef CONFIG_SPI_FLASH_SST | 324 | #ifdef CONFIG_SPI_FLASH_SST |
325 | static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) | 325 | static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) |
326 | { | 326 | { |
327 | int ret; | 327 | int ret; |
328 | u8 cmd[4] = { | 328 | u8 cmd[4] = { |
329 | CMD_SST_BP, | 329 | CMD_SST_BP, |
330 | offset >> 16, | 330 | offset >> 16, |
331 | offset >> 8, | 331 | offset >> 8, |
332 | offset, | 332 | offset, |
333 | }; | 333 | }; |
334 | 334 | ||
335 | debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", | 335 | debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", |
336 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); | 336 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); |
337 | 337 | ||
338 | ret = spi_flash_cmd_write_enable(flash); | 338 | ret = spi_flash_cmd_write_enable(flash); |
339 | if (ret) | 339 | if (ret) |
340 | return ret; | 340 | return ret; |
341 | 341 | ||
342 | ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); | 342 | ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); |
343 | if (ret) | 343 | if (ret) |
344 | return ret; | 344 | return ret; |
345 | 345 | ||
346 | return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); | 346 | return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); |
347 | } | 347 | } |
348 | 348 | ||
349 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | 349 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, |
350 | const void *buf) | 350 | const void *buf) |
351 | { | 351 | { |
352 | size_t actual, cmd_len; | 352 | size_t actual, cmd_len; |
353 | int ret; | 353 | int ret; |
354 | u8 cmd[4]; | 354 | u8 cmd[4]; |
355 | 355 | ||
356 | ret = spi_claim_bus(flash->spi); | 356 | ret = spi_claim_bus(flash->spi); |
357 | if (ret) { | 357 | if (ret) { |
358 | debug("SF: Unable to claim SPI bus\n"); | 358 | debug("SF: Unable to claim SPI bus\n"); |
359 | return ret; | 359 | return ret; |
360 | } | 360 | } |
361 | 361 | ||
362 | /* If the data is not word aligned, write out leading single byte */ | 362 | /* If the data is not word aligned, write out leading single byte */ |
363 | actual = offset % 2; | 363 | actual = offset % 2; |
364 | if (actual) { | 364 | if (actual) { |
365 | ret = sst_byte_write(flash, offset, buf); | 365 | ret = sst_byte_write(flash, offset, buf); |
366 | if (ret) | 366 | if (ret) |
367 | goto done; | 367 | goto done; |
368 | } | 368 | } |
369 | offset += actual; | 369 | offset += actual; |
370 | 370 | ||
371 | ret = spi_flash_cmd_write_enable(flash); | 371 | ret = spi_flash_cmd_write_enable(flash); |
372 | if (ret) | 372 | if (ret) |
373 | goto done; | 373 | goto done; |
374 | 374 | ||
375 | cmd_len = 4; | 375 | cmd_len = 4; |
376 | cmd[0] = CMD_SST_AAI_WP; | 376 | cmd[0] = CMD_SST_AAI_WP; |
377 | cmd[1] = offset >> 16; | 377 | cmd[1] = offset >> 16; |
378 | cmd[2] = offset >> 8; | 378 | cmd[2] = offset >> 8; |
379 | cmd[3] = offset; | 379 | cmd[3] = offset; |
380 | 380 | ||
381 | for (; actual < len - 1; actual += 2) { | 381 | for (; actual < len - 1; actual += 2) { |
382 | debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", | 382 | debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", |
383 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, | 383 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, |
384 | cmd[0], offset); | 384 | cmd[0], offset); |
385 | 385 | ||
386 | ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, | 386 | ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, |
387 | buf + actual, 2); | 387 | buf + actual, 2); |
388 | if (ret) { | 388 | if (ret) { |
389 | debug("SF: sst word program failed\n"); | 389 | debug("SF: sst word program failed\n"); |
390 | break; | 390 | break; |
391 | } | 391 | } |
392 | 392 | ||
393 | ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); | 393 | ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); |
394 | if (ret) | 394 | if (ret) |
395 | break; | 395 | break; |
396 | 396 | ||
397 | cmd_len = 1; | 397 | cmd_len = 1; |
398 | offset += 2; | 398 | offset += 2; |
399 | } | 399 | } |
400 | 400 | ||
401 | if (!ret) | 401 | if (!ret) |
402 | ret = spi_flash_cmd_write_disable(flash); | 402 | ret = spi_flash_cmd_write_disable(flash); |
403 | 403 | ||
404 | /* If there is a single trailing byte, write it out */ | 404 | /* If there is a single trailing byte, write it out */ |
405 | if (!ret && actual != len) | 405 | if (!ret && actual != len) |
406 | ret = sst_byte_write(flash, offset, buf + actual); | 406 | ret = sst_byte_write(flash, offset, buf + actual); |
407 | 407 | ||
408 | done: | 408 | done: |
409 | debug("SF: sst: program %s %zu bytes @ 0x%zx\n", | 409 | debug("SF: sst: program %s %zu bytes @ 0x%zx\n", |
410 | ret ? "failure" : "success", len, offset - actual); | 410 | ret ? "failure" : "success", len, offset - actual); |
411 | 411 | ||
412 | spi_release_bus(flash->spi); | 412 | spi_release_bus(flash->spi); |
413 | return ret; | 413 | return ret; |
414 | } | 414 | } |
415 | #endif | 415 | #endif |
416 | 416 |
drivers/mtd/spi/sf_probe.c
1 | /* | 1 | /* |
2 | * SPI flash probing | 2 | * SPI flash probing |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Atmel Corporation | 4 | * Copyright (C) 2008 Atmel Corporation |
5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik | 5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik |
6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
7 | * | 7 | * |
8 | * SPDX-License-Identifier: GPL-2.0+ | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <fdtdec.h> | 12 | #include <fdtdec.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 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | 17 | ||
18 | #include "sf_internal.h" | 18 | #include "sf_internal.h" |
19 | 19 | ||
20 | DECLARE_GLOBAL_DATA_PTR; | 20 | DECLARE_GLOBAL_DATA_PTR; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * struct spi_flash_params - SPI/QSPI flash device params structure | 23 | * struct spi_flash_params - SPI/QSPI flash device params structure |
24 | * | 24 | * |
25 | * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) | 25 | * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) |
26 | * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) | 26 | * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) |
27 | * @ext_jedec: Device ext_jedec ID | 27 | * @ext_jedec: Device ext_jedec ID |
28 | * @sector_size: Sector size of this device | 28 | * @sector_size: Sector size of this device |
29 | * @nr_sectors: No.of sectors on this device | 29 | * @nr_sectors: No.of sectors on this device |
30 | * @e_rd_cmd: Enum list for read commands | ||
30 | * @flags: Importent param, for flash specific behaviour | 31 | * @flags: Importent param, for flash specific behaviour |
31 | */ | 32 | */ |
32 | struct spi_flash_params { | 33 | struct spi_flash_params { |
33 | const char *name; | 34 | const char *name; |
34 | u32 jedec; | 35 | u32 jedec; |
35 | u16 ext_jedec; | 36 | u16 ext_jedec; |
36 | u32 sector_size; | 37 | u32 sector_size; |
37 | u32 nr_sectors; | 38 | u32 nr_sectors; |
39 | u8 e_rd_cmd; | ||
38 | u16 flags; | 40 | u16 flags; |
39 | }; | 41 | }; |
40 | 42 | ||
41 | static const struct spi_flash_params spi_flash_params_table[] = { | 43 | static const struct spi_flash_params spi_flash_params_table[] = { |
42 | #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ | 44 | #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ |
43 | {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, SECT_4K}, | 45 | {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, 0, SECT_4K}, |
44 | {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, SECT_4K}, | 46 | {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, 0, SECT_4K}, |
45 | {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, SECT_4K}, | 47 | {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, 0, SECT_4K}, |
46 | {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, SECT_4K}, | 48 | {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, 0, SECT_4K}, |
47 | {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, SECT_4K}, | 49 | {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, 0, SECT_4K}, |
48 | {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, SECT_4K}, | 50 | {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
49 | {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, SECT_4K}, | 51 | {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
50 | {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, SECT_4K}, | 52 | {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
51 | #endif | 53 | #endif |
52 | #ifdef CONFIG_SPI_FLASH_EON /* EON */ | 54 | #ifdef CONFIG_SPI_FLASH_EON /* EON */ |
53 | {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0}, | 55 | {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0, 0}, |
54 | {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, SECT_4K}, | 56 | {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
55 | {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0}, | 57 | {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0, 0}, |
56 | {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0}, | 58 | {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0, 0}, |
57 | #endif | 59 | #endif |
58 | #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ | 60 | #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ |
59 | {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, SECT_4K}, | 61 | {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
60 | {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, SECT_4K}, | 62 | {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
61 | #endif | 63 | #endif |
62 | #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ | 64 | #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ |
63 | {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0}, | 65 | {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0, 0}, |
64 | {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0}, | 66 | {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0, 0}, |
65 | {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0}, | 67 | {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0, 0}, |
66 | {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0}, | 68 | {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0, 0}, |
67 | {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0}, | 69 | {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0, 0}, |
68 | {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0}, | 70 | {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0, 0}, |
69 | {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0}, | 71 | {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0, 0}, |
70 | {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0}, | 72 | {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0, 0}, |
71 | {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, 0}, | 73 | {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, 0, 0}, |
72 | {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0}, | 74 | {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0, 0}, |
73 | #endif | 75 | #endif |
74 | #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ | 76 | #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ |
75 | {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0}, | 77 | {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0, 0}, |
76 | {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0}, | 78 | {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0, 0}, |
77 | {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0}, | 79 | {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0, 0}, |
78 | {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0}, | 80 | {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0, 0}, |
79 | {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0}, | 81 | {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0, 0}, |
80 | {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0}, | 82 | {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0, 0}, |
81 | {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0}, | 83 | {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0, 0}, |
82 | {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0}, | 84 | {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0, 0}, |
83 | {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0}, | 85 | {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0, 0}, |
84 | {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, 0}, | 86 | {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, RD_EXTN, 0}, |
85 | {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, 0}, | 87 | {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_EXTN, 0}, |
86 | {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0}, | 88 | {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0, 0}, |
87 | {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0}, | 89 | {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0, 0}, |
88 | #endif | 90 | #endif |
89 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ | 91 | #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ |
90 | {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0}, | 92 | {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0, 0}, |
91 | {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0}, | 93 | {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0, 0}, |
92 | {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0}, | 94 | {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0, 0}, |
93 | {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0}, | 95 | {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0, 0}, |
94 | {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0}, | 96 | {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0, 0}, |
95 | {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0}, | 97 | {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0, 0}, |
96 | {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0}, | 98 | {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0, 0}, |
97 | {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0}, | 99 | {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0, 0}, |
98 | {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, SECT_4K}, | 100 | {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
99 | {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, SECT_4K}, | 101 | {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
100 | {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, SECT_4K}, | 102 | {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
101 | {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, SECT_4K}, | 103 | {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
102 | {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, SECT_4K}, | 104 | {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, 0, SECT_4K}, |
103 | {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, SECT_4K}, | 105 | {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, 0, SECT_4K}, |
104 | {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, SECT_4K}, | 106 | {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, 0, SECT_4K}, |
105 | {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, SECT_4K}, | 107 | {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, 0, SECT_4K}, |
106 | {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K}, | 108 | {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, 0, E_FSR | SECT_4K}, |
107 | {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K}, | 109 | {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, 0, E_FSR | SECT_4K}, |
108 | {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K}, | 110 | {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, 0, E_FSR | SECT_4K}, |
109 | {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K}, | 111 | {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, 0, E_FSR | SECT_4K}, |
110 | #endif | 112 | #endif |
111 | #ifdef CONFIG_SPI_FLASH_SST /* SST */ | 113 | #ifdef CONFIG_SPI_FLASH_SST /* SST */ |
112 | {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WP}, | 114 | {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP}, |
113 | {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WP}, | 115 | {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP}, |
114 | {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WP}, | 116 | {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, 0, SECT_4K | SST_WP}, |
115 | {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WP}, | 117 | {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, 0, SECT_4K | SST_WP}, |
116 | {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, SECT_4K}, | 118 | {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
117 | {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WP}, | 119 | {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, 0, SECT_4K | SST_WP}, |
118 | {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WP}, | 120 | {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, 0, SECT_4K | SST_WP}, |
119 | {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WP}, | 121 | {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, 0, SECT_4K | SST_WP}, |
120 | {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WP}, | 122 | {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP}, |
121 | {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WP}, | 123 | {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP}, |
122 | #endif | 124 | #endif |
123 | #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ | 125 | #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ |
124 | {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0}, | 126 | {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0, 0}, |
125 | {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0}, | 127 | {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0, 0}, |
126 | {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0}, | 128 | {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0, 0}, |
127 | {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, SECT_4K}, | 129 | {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, 0, SECT_4K}, |
128 | {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, SECT_4K}, | 130 | {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, 0, SECT_4K}, |
129 | {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, SECT_4K}, | 131 | {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
130 | {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, SECT_4K}, | 132 | {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
131 | {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, SECT_4K}, | 133 | {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, 0, SECT_4K}, |
132 | {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, SECT_4K}, | 134 | {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, 0, SECT_4K}, |
133 | {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, SECT_4K}, | 135 | {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
134 | {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, SECT_4K}, | 136 | {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
135 | {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, SECT_4K}, | 137 | {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, 0, SECT_4K}, |
136 | {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, SECT_4K}, | 138 | {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, 0, SECT_4K}, |
137 | {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, SECT_4K}, | 139 | {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, 0, SECT_4K}, |
138 | {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, SECT_4K}, | 140 | {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, 0, SECT_4K}, |
139 | {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, SECT_4K}, | 141 | {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, 0, SECT_4K}, |
140 | {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, SECT_4K}, | 142 | {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, 0, SECT_4K}, |
141 | {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, SECT_4K}, | 143 | {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, 0, SECT_4K}, |
142 | #endif | 144 | #endif |
143 | /* | 145 | /* |
144 | * Note: | 146 | * Note: |
145 | * Below paired flash devices has similar spi_flash params. | 147 | * Below paired flash devices has similar spi_flash params. |
146 | * (S25FL129P_64K, S25FL128S_64K) | 148 | * (S25FL129P_64K, S25FL128S_64K) |
147 | * (W25Q80BL, W25Q80BV) | 149 | * (W25Q80BL, W25Q80BV) |
148 | * (W25Q16CL, W25Q16DV) | 150 | * (W25Q16CL, W25Q16DV) |
149 | * (W25Q32BV, W25Q32FV_SPI) | 151 | * (W25Q32BV, W25Q32FV_SPI) |
150 | * (W25Q64CV, W25Q64FV_SPI) | 152 | * (W25Q64CV, W25Q64FV_SPI) |
151 | * (W25Q128BV, W25Q128FV_SPI) | 153 | * (W25Q128BV, W25Q128FV_SPI) |
152 | * (W25Q32DW, W25Q32FV_QPI) | 154 | * (W25Q32DW, W25Q32FV_QPI) |
153 | * (W25Q64DW, W25Q64FV_QPI) | 155 | * (W25Q64DW, W25Q64FV_QPI) |
154 | * (W25Q128FW, W25Q128FV_QPI) | 156 | * (W25Q128FW, W25Q128FV_QPI) |
155 | */ | 157 | */ |
156 | }; | 158 | }; |
157 | 159 | ||
160 | /* Read commands array */ | ||
161 | static u8 spi_read_cmds_array[] = { | ||
162 | CMD_READ_ARRAY_SLOW, | ||
163 | CMD_READ_DUAL_OUTPUT_FAST, | ||
164 | CMD_READ_DUAL_IO_FAST, | ||
165 | }; | ||
166 | |||
158 | static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, | 167 | static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, |
159 | u8 *idcode) | 168 | u8 *idcode) |
160 | { | 169 | { |
161 | const struct spi_flash_params *params; | 170 | const struct spi_flash_params *params; |
162 | struct spi_flash *flash; | 171 | struct spi_flash *flash; |
163 | int i; | 172 | int i; |
173 | u8 cmd; | ||
164 | u16 jedec = idcode[1] << 8 | idcode[2]; | 174 | u16 jedec = idcode[1] << 8 | idcode[2]; |
165 | u16 ext_jedec = idcode[3] << 8 | idcode[4]; | 175 | u16 ext_jedec = idcode[3] << 8 | idcode[4]; |
166 | 176 | ||
167 | /* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */ | 177 | /* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */ |
168 | for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) { | 178 | for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) { |
169 | params = &spi_flash_params_table[i]; | 179 | params = &spi_flash_params_table[i]; |
170 | if ((params->jedec >> 16) == idcode[0]) { | 180 | if ((params->jedec >> 16) == idcode[0]) { |
171 | if ((params->jedec & 0xFFFF) == jedec) { | 181 | if ((params->jedec & 0xFFFF) == jedec) { |
172 | if (params->ext_jedec == 0) | 182 | if (params->ext_jedec == 0) |
173 | break; | 183 | break; |
174 | else if (params->ext_jedec == ext_jedec) | 184 | else if (params->ext_jedec == ext_jedec) |
175 | break; | 185 | break; |
176 | } | 186 | } |
177 | } | 187 | } |
178 | } | 188 | } |
179 | 189 | ||
180 | if (i == ARRAY_SIZE(spi_flash_params_table)) { | 190 | if (i == ARRAY_SIZE(spi_flash_params_table)) { |
181 | printf("SF: Unsupported flash IDs: "); | 191 | printf("SF: Unsupported flash IDs: "); |
182 | printf("manuf %02x, jedec %04x, ext_jedec %04x\n", | 192 | printf("manuf %02x, jedec %04x, ext_jedec %04x\n", |
183 | idcode[0], jedec, ext_jedec); | 193 | idcode[0], jedec, ext_jedec); |
184 | return NULL; | 194 | return NULL; |
185 | } | 195 | } |
186 | 196 | ||
187 | flash = malloc(sizeof(*flash)); | 197 | flash = malloc(sizeof(*flash)); |
188 | if (!flash) { | 198 | if (!flash) { |
189 | debug("SF: Failed to allocate spi_flash\n"); | 199 | debug("SF: Failed to allocate spi_flash\n"); |
190 | return NULL; | 200 | return NULL; |
191 | } | 201 | } |
192 | memset(flash, '\0', sizeof(*flash)); | 202 | memset(flash, '\0', sizeof(*flash)); |
193 | 203 | ||
194 | /* Assign spi data */ | 204 | /* Assign spi data */ |
195 | flash->spi = spi; | 205 | flash->spi = spi; |
196 | flash->name = params->name; | 206 | flash->name = params->name; |
197 | flash->memory_map = spi->memory_map; | 207 | flash->memory_map = spi->memory_map; |
198 | 208 | ||
199 | /* Assign spi_flash ops */ | 209 | /* Assign spi_flash ops */ |
200 | flash->write = spi_flash_cmd_write_ops; | 210 | flash->write = spi_flash_cmd_write_ops; |
201 | #ifdef CONFIG_SPI_FLASH_SST | 211 | #ifdef CONFIG_SPI_FLASH_SST |
202 | if (params->flags & SST_WP) | 212 | if (params->flags & SST_WP) |
203 | flash->write = sst_write_wp; | 213 | flash->write = sst_write_wp; |
204 | #endif | 214 | #endif |
205 | flash->erase = spi_flash_cmd_erase_ops; | 215 | flash->erase = spi_flash_cmd_erase_ops; |
206 | flash->read = spi_flash_cmd_read_ops; | 216 | flash->read = spi_flash_cmd_read_ops; |
207 | 217 | ||
208 | /* Compute the flash size */ | 218 | /* Compute the flash size */ |
209 | flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; | 219 | flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; |
210 | flash->sector_size = params->sector_size; | 220 | flash->sector_size = params->sector_size; |
211 | flash->size = flash->sector_size * params->nr_sectors; | 221 | flash->size = flash->sector_size * params->nr_sectors; |
212 | 222 | ||
213 | /* Compute erase sector and command */ | 223 | /* Compute erase sector and command */ |
214 | if (params->flags & SECT_4K) { | 224 | if (params->flags & SECT_4K) { |
215 | flash->erase_cmd = CMD_ERASE_4K; | 225 | flash->erase_cmd = CMD_ERASE_4K; |
216 | flash->erase_size = 4096; | 226 | flash->erase_size = 4096; |
217 | } else if (params->flags & SECT_32K) { | 227 | } else if (params->flags & SECT_32K) { |
218 | flash->erase_cmd = CMD_ERASE_32K; | 228 | flash->erase_cmd = CMD_ERASE_32K; |
219 | flash->erase_size = 32768; | 229 | flash->erase_size = 32768; |
220 | } else { | 230 | } else { |
221 | flash->erase_cmd = CMD_ERASE_64K; | 231 | flash->erase_cmd = CMD_ERASE_64K; |
222 | flash->erase_size = flash->sector_size; | 232 | flash->erase_size = flash->sector_size; |
233 | } | ||
234 | |||
235 | /* Look for the fastest read cmd */ | ||
236 | cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); | ||
237 | if (cmd) { | ||
238 | cmd = spi_read_cmds_array[cmd - 1]; | ||
239 | flash->read_cmd = cmd; | ||
240 | } else { | ||
241 | /* Go for for default supported read cmd */ | ||
242 | flash->read_cmd = CMD_READ_ARRAY_FAST; | ||
223 | } | 243 | } |
224 | 244 | ||
225 | /* Poll cmd seclection */ | 245 | /* Poll cmd seclection */ |
226 | flash->poll_cmd = CMD_READ_STATUS; | 246 | flash->poll_cmd = CMD_READ_STATUS; |
227 | #ifdef CONFIG_SPI_FLASH_STMICRO | 247 | #ifdef CONFIG_SPI_FLASH_STMICRO |
228 | if (params->flags & E_FSR) | 248 | if (params->flags & E_FSR) |
229 | flash->poll_cmd = CMD_FLAG_STATUS; | 249 | flash->poll_cmd = CMD_FLAG_STATUS; |
230 | #endif | 250 | #endif |
231 | 251 | ||
232 | /* Configure the BAR - discover bank cmds and read current bank */ | 252 | /* Configure the BAR - discover bank cmds and read current bank */ |
233 | #ifdef CONFIG_SPI_FLASH_BAR | 253 | #ifdef CONFIG_SPI_FLASH_BAR |
234 | u8 curr_bank = 0; | 254 | u8 curr_bank = 0; |
235 | if (flash->size > SPI_FLASH_16MB_BOUN) { | 255 | if (flash->size > SPI_FLASH_16MB_BOUN) { |
236 | flash->bank_read_cmd = (idcode[0] == 0x01) ? | 256 | flash->bank_read_cmd = (idcode[0] == 0x01) ? |
237 | CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; | 257 | CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; |
238 | flash->bank_write_cmd = (idcode[0] == 0x01) ? | 258 | flash->bank_write_cmd = (idcode[0] == 0x01) ? |
239 | CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; | 259 | CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; |
240 | 260 | ||
241 | if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, | 261 | if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, |
242 | &curr_bank, 1)) { | 262 | &curr_bank, 1)) { |
243 | debug("SF: fail to read bank addr register\n"); | 263 | debug("SF: fail to read bank addr register\n"); |
244 | return NULL; | 264 | return NULL; |
245 | } | 265 | } |
246 | flash->bank_curr = curr_bank; | 266 | flash->bank_curr = curr_bank; |
247 | } else { | 267 | } else { |
248 | flash->bank_curr = curr_bank; | 268 | flash->bank_curr = curr_bank; |
249 | } | 269 | } |
250 | #endif | 270 | #endif |
251 | 271 | ||
252 | /* Flash powers up read-only, so clear BP# bits */ | 272 | /* Flash powers up read-only, so clear BP# bits */ |
253 | #if defined(CONFIG_SPI_FLASH_ATMEL) || \ | 273 | #if defined(CONFIG_SPI_FLASH_ATMEL) || \ |
254 | defined(CONFIG_SPI_FLASH_MACRONIX) || \ | 274 | defined(CONFIG_SPI_FLASH_MACRONIX) || \ |
255 | defined(CONFIG_SPI_FLASH_SST) | 275 | defined(CONFIG_SPI_FLASH_SST) |
256 | spi_flash_cmd_write_status(flash, 0); | 276 | spi_flash_cmd_write_status(flash, 0); |
257 | #endif | 277 | #endif |
258 | 278 | ||
259 | return flash; | 279 | return flash; |
260 | } | 280 | } |
261 | 281 | ||
262 | #ifdef CONFIG_OF_CONTROL | 282 | #ifdef CONFIG_OF_CONTROL |
263 | int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) | 283 | int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) |
264 | { | 284 | { |
265 | fdt_addr_t addr; | 285 | fdt_addr_t addr; |
266 | fdt_size_t size; | 286 | fdt_size_t size; |
267 | int node; | 287 | int node; |
268 | 288 | ||
269 | /* If there is no node, do nothing */ | 289 | /* If there is no node, do nothing */ |
270 | node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); | 290 | node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); |
271 | if (node < 0) | 291 | if (node < 0) |
272 | return 0; | 292 | return 0; |
273 | 293 | ||
274 | addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); | 294 | addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); |
275 | if (addr == FDT_ADDR_T_NONE) { | 295 | if (addr == FDT_ADDR_T_NONE) { |
276 | debug("%s: Cannot decode address\n", __func__); | 296 | debug("%s: Cannot decode address\n", __func__); |
277 | return 0; | 297 | return 0; |
278 | } | 298 | } |
279 | 299 | ||
280 | if (flash->size != size) { | 300 | if (flash->size != size) { |
281 | debug("%s: Memory map must cover entire device\n", __func__); | 301 | debug("%s: Memory map must cover entire device\n", __func__); |
282 | return -1; | 302 | return -1; |
283 | } | 303 | } |
284 | flash->memory_map = map_sysmem(addr, size); | 304 | flash->memory_map = map_sysmem(addr, size); |
285 | 305 | ||
286 | return 0; | 306 | return 0; |
287 | } | 307 | } |
288 | #endif /* CONFIG_OF_CONTROL */ | 308 | #endif /* CONFIG_OF_CONTROL */ |
289 | 309 | ||
290 | static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi) | 310 | static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi) |
291 | { | 311 | { |
292 | struct spi_flash *flash = NULL; | 312 | struct spi_flash *flash = NULL; |
293 | u8 idcode[5]; | 313 | u8 idcode[5]; |
294 | int ret; | 314 | int ret; |
295 | 315 | ||
296 | /* Setup spi_slave */ | 316 | /* Setup spi_slave */ |
297 | if (!spi) { | 317 | if (!spi) { |
298 | printf("SF: Failed to set up slave\n"); | 318 | printf("SF: Failed to set up slave\n"); |
299 | return NULL; | 319 | return NULL; |
300 | } | 320 | } |
301 | 321 | ||
302 | /* Claim spi bus */ | 322 | /* Claim spi bus */ |
303 | ret = spi_claim_bus(spi); | 323 | ret = spi_claim_bus(spi); |
304 | if (ret) { | 324 | if (ret) { |
305 | debug("SF: Failed to claim SPI bus: %d\n", ret); | 325 | debug("SF: Failed to claim SPI bus: %d\n", ret); |
306 | goto err_claim_bus; | 326 | goto err_claim_bus; |
307 | } | 327 | } |
308 | 328 | ||
309 | /* Read the ID codes */ | 329 | /* Read the ID codes */ |
310 | ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); | 330 | ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); |
311 | if (ret) { | 331 | if (ret) { |
312 | printf("SF: Failed to get idcodes\n"); | 332 | printf("SF: Failed to get idcodes\n"); |
313 | goto err_read_id; | 333 | goto err_read_id; |
314 | } | 334 | } |
315 | 335 | ||
316 | #ifdef DEBUG | 336 | #ifdef DEBUG |
317 | printf("SF: Got idcodes\n"); | 337 | printf("SF: Got idcodes\n"); |
318 | print_buffer(0, idcode, 1, sizeof(idcode), 0); | 338 | print_buffer(0, idcode, 1, sizeof(idcode), 0); |
319 | #endif | 339 | #endif |
320 | 340 | ||
321 | /* Validate params from spi_flash_params table */ | 341 | /* Validate params from spi_flash_params table */ |
322 | flash = spi_flash_validate_params(spi, idcode); | 342 | flash = spi_flash_validate_params(spi, idcode); |
323 | if (!flash) | 343 | if (!flash) |
324 | goto err_read_id; | 344 | goto err_read_id; |
325 | 345 | ||
326 | #ifdef CONFIG_OF_CONTROL | 346 | #ifdef CONFIG_OF_CONTROL |
327 | if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { | 347 | if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { |
328 | debug("SF: FDT decode error\n"); | 348 | debug("SF: FDT decode error\n"); |
329 | goto err_read_id; | 349 | goto err_read_id; |
330 | } | 350 | } |
331 | #endif | 351 | #endif |
332 | #ifndef CONFIG_SPL_BUILD | 352 | #ifndef CONFIG_SPL_BUILD |
333 | printf("SF: Detected %s with page size ", flash->name); | 353 | printf("SF: Detected %s with page size ", flash->name); |
334 | print_size(flash->page_size, ", erase size "); | 354 | print_size(flash->page_size, ", erase size "); |
335 | print_size(flash->erase_size, ", total "); | 355 | print_size(flash->erase_size, ", total "); |
336 | print_size(flash->size, ""); | 356 | print_size(flash->size, ""); |
337 | if (flash->memory_map) | 357 | if (flash->memory_map) |
338 | printf(", mapped at %p", flash->memory_map); | 358 | printf(", mapped at %p", flash->memory_map); |
339 | puts("\n"); | 359 | puts("\n"); |
340 | #endif | 360 | #endif |
341 | #ifndef CONFIG_SPI_FLASH_BAR | 361 | #ifndef CONFIG_SPI_FLASH_BAR |
342 | if (flash->size > SPI_FLASH_16MB_BOUN) { | 362 | if (flash->size > SPI_FLASH_16MB_BOUN) { |
343 | puts("SF: Warning - Only lower 16MiB accessible,"); | 363 | puts("SF: Warning - Only lower 16MiB accessible,"); |
344 | puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); | 364 | puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); |
345 | } | 365 | } |
346 | #endif | 366 | #endif |
347 | 367 | ||
348 | /* Release spi bus */ | 368 | /* Release spi bus */ |
349 | spi_release_bus(spi); | 369 | spi_release_bus(spi); |
350 | 370 | ||
351 | return flash; | 371 | return flash; |
352 | 372 | ||
353 | err_read_id: | 373 | err_read_id: |
354 | spi_release_bus(spi); | 374 | spi_release_bus(spi); |
355 | err_claim_bus: | 375 | err_claim_bus: |
356 | spi_free_slave(spi); | 376 | spi_free_slave(spi); |
357 | return NULL; | 377 | return NULL; |
358 | } | 378 | } |
359 | 379 | ||
360 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | 380 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, |
361 | unsigned int max_hz, unsigned int spi_mode) | 381 | unsigned int max_hz, unsigned int spi_mode) |
362 | { | 382 | { |
363 | struct spi_slave *spi; | 383 | struct spi_slave *spi; |
364 | 384 | ||
365 | spi = spi_setup_slave(bus, cs, max_hz, spi_mode); | 385 | spi = spi_setup_slave(bus, cs, max_hz, spi_mode); |
366 | return spi_flash_probe_slave(spi); | 386 | return spi_flash_probe_slave(spi); |
367 | } | 387 | } |
368 | 388 | ||
369 | #ifdef CONFIG_OF_SPI_FLASH | 389 | #ifdef CONFIG_OF_SPI_FLASH |
370 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, | 390 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, |
371 | int spi_node) | 391 | int spi_node) |
372 | { | 392 | { |
373 | struct spi_slave *spi; | 393 | struct spi_slave *spi; |
374 | 394 | ||
375 | spi = spi_setup_slave_fdt(blob, slave_node, spi_node); | 395 | spi = spi_setup_slave_fdt(blob, slave_node, spi_node); |
376 | return spi_flash_probe_slave(spi); | 396 | return spi_flash_probe_slave(spi); |
377 | } | 397 | } |
378 | #endif | 398 | #endif |
379 | 399 | ||
380 | void spi_flash_free(struct spi_flash *flash) | 400 | void spi_flash_free(struct spi_flash *flash) |
381 | { | 401 | { |
382 | spi_free_slave(flash->spi); | 402 | spi_free_slave(flash->spi); |
383 | free(flash); | 403 | free(flash); |
384 | } | 404 | } |
385 | 405 |
include/spi.h
1 | /* | 1 | /* |
2 | * Common SPI Interface: Controller-specific definitions | 2 | * Common SPI Interface: Controller-specific definitions |
3 | * | 3 | * |
4 | * (C) Copyright 2001 | 4 | * (C) Copyright 2001 |
5 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. | 5 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: GPL-2.0+ | 7 | * SPDX-License-Identifier: GPL-2.0+ |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef _SPI_H_ | 10 | #ifndef _SPI_H_ |
11 | #define _SPI_H_ | 11 | #define _SPI_H_ |
12 | 12 | ||
13 | /* SPI mode flags */ | 13 | /* SPI mode flags */ |
14 | #define SPI_CPHA 0x01 /* clock phase */ | 14 | #define SPI_CPHA 0x01 /* clock phase */ |
15 | #define SPI_CPOL 0x02 /* clock polarity */ | 15 | #define SPI_CPOL 0x02 /* clock polarity */ |
16 | #define SPI_MODE_0 (0|0) /* (original MicroWire) */ | 16 | #define SPI_MODE_0 (0|0) /* (original MicroWire) */ |
17 | #define SPI_MODE_1 (0|SPI_CPHA) | 17 | #define SPI_MODE_1 (0|SPI_CPHA) |
18 | #define SPI_MODE_2 (SPI_CPOL|0) | 18 | #define SPI_MODE_2 (SPI_CPOL|0) |
19 | #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) | 19 | #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) |
20 | #define SPI_CS_HIGH 0x04 /* CS active high */ | 20 | #define SPI_CS_HIGH 0x04 /* CS active high */ |
21 | #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ | 21 | #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ |
22 | #define SPI_3WIRE 0x10 /* SI/SO signals shared */ | 22 | #define SPI_3WIRE 0x10 /* SI/SO signals shared */ |
23 | #define SPI_LOOP 0x20 /* loopback mode */ | 23 | #define SPI_LOOP 0x20 /* loopback mode */ |
24 | #define SPI_SLAVE 0x40 /* slave mode */ | 24 | #define SPI_SLAVE 0x40 /* slave mode */ |
25 | #define SPI_PREAMBLE 0x80 /* Skip preamble bytes */ | 25 | #define SPI_PREAMBLE 0x80 /* Skip preamble bytes */ |
26 | 26 | ||
27 | /* SPI transfer flags */ | 27 | /* SPI transfer flags */ |
28 | #define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ | 28 | #define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ |
29 | #define SPI_XFER_END 0x02 /* Deassert CS after transfer */ | 29 | #define SPI_XFER_END 0x02 /* Deassert CS after transfer */ |
30 | #define SPI_XFER_MMAP 0x08 /* Memory Mapped start */ | 30 | #define SPI_XFER_MMAP 0x08 /* Memory Mapped start */ |
31 | #define SPI_XFER_MMAP_END 0x10 /* Memory Mapped End */ | 31 | #define SPI_XFER_MMAP_END 0x10 /* Memory Mapped End */ |
32 | #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END) | 32 | #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END) |
33 | 33 | ||
34 | /* SPI RX operation modes */ | ||
35 | #define SPI_OPM_RX_AS 1 << 0 | ||
36 | #define SPI_OPM_RX_DOUT 1 << 1 | ||
37 | #define SPI_OPM_RX_DIO 1 << 2 | ||
38 | #define SPI_OPM_RX_EXTN SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | SPI_OPM_RX_DIO | ||
39 | |||
34 | /* Header byte that marks the start of the message */ | 40 | /* Header byte that marks the start of the message */ |
35 | #define SPI_PREAMBLE_END_BYTE 0xec | 41 | #define SPI_PREAMBLE_END_BYTE 0xec |
36 | 42 | ||
37 | #define SPI_DEFAULT_WORDLEN 8 | 43 | #define SPI_DEFAULT_WORDLEN 8 |
38 | 44 | ||
39 | /** | 45 | /** |
40 | * struct spi_slave - Representation of a SPI slave | 46 | * struct spi_slave - Representation of a SPI slave |
41 | * | 47 | * |
42 | * Drivers are expected to extend this with controller-specific data. | 48 | * Drivers are expected to extend this with controller-specific data. |
43 | * | 49 | * |
44 | * @bus: ID of the bus that the slave is attached to. | 50 | * @bus: ID of the bus that the slave is attached to. |
45 | * @cs: ID of the chip select connected to the slave. | 51 | * @cs: ID of the chip select connected to the slave. |
52 | * @op_mode_rx: SPI RX operation mode. | ||
46 | * @wordlen: Size of SPI word in number of bits | 53 | * @wordlen: Size of SPI word in number of bits |
47 | * @max_write_size: If non-zero, the maximum number of bytes which can | 54 | * @max_write_size: If non-zero, the maximum number of bytes which can |
48 | * be written at once, excluding command bytes. | 55 | * be written at once, excluding command bytes. |
49 | * @memory_map: Address of read-only SPI flash access. | 56 | * @memory_map: Address of read-only SPI flash access. |
50 | */ | 57 | */ |
51 | struct spi_slave { | 58 | struct spi_slave { |
52 | unsigned int bus; | 59 | unsigned int bus; |
53 | unsigned int cs; | 60 | unsigned int cs; |
61 | u8 op_mode_rx; | ||
54 | unsigned int wordlen; | 62 | unsigned int wordlen; |
55 | unsigned int max_write_size; | 63 | unsigned int max_write_size; |
56 | void *memory_map; | 64 | void *memory_map; |
57 | }; | 65 | }; |
58 | 66 | ||
59 | /** | 67 | /** |
60 | * Initialization, must be called once on start up. | 68 | * Initialization, must be called once on start up. |
61 | * | 69 | * |
62 | * TODO: I don't think we really need this. | 70 | * TODO: I don't think we really need this. |
63 | */ | 71 | */ |
64 | void spi_init(void); | 72 | void spi_init(void); |
65 | 73 | ||
66 | /** | 74 | /** |
67 | * spi_do_alloc_slave - Allocate a new SPI slave (internal) | 75 | * spi_do_alloc_slave - Allocate a new SPI slave (internal) |
68 | * | 76 | * |
69 | * Allocate and zero all fields in the spi slave, and set the bus/chip | 77 | * Allocate and zero all fields in the spi slave, and set the bus/chip |
70 | * select. Use the helper macro spi_alloc_slave() to call this. | 78 | * select. Use the helper macro spi_alloc_slave() to call this. |
71 | * | 79 | * |
72 | * @offset: Offset of struct spi_slave within slave structure. | 80 | * @offset: Offset of struct spi_slave within slave structure. |
73 | * @size: Size of slave structure. | 81 | * @size: Size of slave structure. |
74 | * @bus: Bus ID of the slave chip. | 82 | * @bus: Bus ID of the slave chip. |
75 | * @cs: Chip select ID of the slave chip on the specified bus. | 83 | * @cs: Chip select ID of the slave chip on the specified bus. |
76 | */ | 84 | */ |
77 | void *spi_do_alloc_slave(int offset, int size, unsigned int bus, | 85 | void *spi_do_alloc_slave(int offset, int size, unsigned int bus, |
78 | unsigned int cs); | 86 | unsigned int cs); |
79 | 87 | ||
80 | /** | 88 | /** |
81 | * spi_alloc_slave - Allocate a new SPI slave | 89 | * spi_alloc_slave - Allocate a new SPI slave |
82 | * | 90 | * |
83 | * Allocate and zero all fields in the spi slave, and set the bus/chip | 91 | * Allocate and zero all fields in the spi slave, and set the bus/chip |
84 | * select. | 92 | * select. |
85 | * | 93 | * |
86 | * @_struct: Name of structure to allocate (e.g. struct tegra_spi). | 94 | * @_struct: Name of structure to allocate (e.g. struct tegra_spi). |
87 | * This structure must contain a member 'struct spi_slave *slave'. | 95 | * This structure must contain a member 'struct spi_slave *slave'. |
88 | * @bus: Bus ID of the slave chip. | 96 | * @bus: Bus ID of the slave chip. |
89 | * @cs: Chip select ID of the slave chip on the specified bus. | 97 | * @cs: Chip select ID of the slave chip on the specified bus. |
90 | */ | 98 | */ |
91 | #define spi_alloc_slave(_struct, bus, cs) \ | 99 | #define spi_alloc_slave(_struct, bus, cs) \ |
92 | spi_do_alloc_slave(offsetof(_struct, slave), \ | 100 | spi_do_alloc_slave(offsetof(_struct, slave), \ |
93 | sizeof(_struct), bus, cs) | 101 | sizeof(_struct), bus, cs) |
94 | 102 | ||
95 | /** | 103 | /** |
96 | * spi_alloc_slave_base - Allocate a new SPI slave with no private data | 104 | * spi_alloc_slave_base - Allocate a new SPI slave with no private data |
97 | * | 105 | * |
98 | * Allocate and zero all fields in the spi slave, and set the bus/chip | 106 | * Allocate and zero all fields in the spi slave, and set the bus/chip |
99 | * select. | 107 | * select. |
100 | * | 108 | * |
101 | * @bus: Bus ID of the slave chip. | 109 | * @bus: Bus ID of the slave chip. |
102 | * @cs: Chip select ID of the slave chip on the specified bus. | 110 | * @cs: Chip select ID of the slave chip on the specified bus. |
103 | */ | 111 | */ |
104 | #define spi_alloc_slave_base(bus, cs) \ | 112 | #define spi_alloc_slave_base(bus, cs) \ |
105 | spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs) | 113 | spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs) |
106 | 114 | ||
107 | /** | 115 | /** |
108 | * Set up communications parameters for a SPI slave. | 116 | * Set up communications parameters for a SPI slave. |
109 | * | 117 | * |
110 | * This must be called once for each slave. Note that this function | 118 | * This must be called once for each slave. Note that this function |
111 | * usually doesn't touch any actual hardware, it only initializes the | 119 | * usually doesn't touch any actual hardware, it only initializes the |
112 | * contents of spi_slave so that the hardware can be easily | 120 | * contents of spi_slave so that the hardware can be easily |
113 | * initialized later. | 121 | * initialized later. |
114 | * | 122 | * |
115 | * @bus: Bus ID of the slave chip. | 123 | * @bus: Bus ID of the slave chip. |
116 | * @cs: Chip select ID of the slave chip on the specified bus. | 124 | * @cs: Chip select ID of the slave chip on the specified bus. |
117 | * @max_hz: Maximum SCK rate in Hz. | 125 | * @max_hz: Maximum SCK rate in Hz. |
118 | * @mode: Clock polarity, clock phase and other parameters. | 126 | * @mode: Clock polarity, clock phase and other parameters. |
119 | * | 127 | * |
120 | * Returns: A spi_slave reference that can be used in subsequent SPI | 128 | * Returns: A spi_slave reference that can be used in subsequent SPI |
121 | * calls, or NULL if one or more of the parameters are not supported. | 129 | * calls, or NULL if one or more of the parameters are not supported. |
122 | */ | 130 | */ |
123 | struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, | 131 | struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, |
124 | unsigned int max_hz, unsigned int mode); | 132 | unsigned int max_hz, unsigned int mode); |
125 | 133 | ||
126 | /** | 134 | /** |
127 | * Free any memory associated with a SPI slave. | 135 | * Free any memory associated with a SPI slave. |
128 | * | 136 | * |
129 | * @slave: The SPI slave | 137 | * @slave: The SPI slave |
130 | */ | 138 | */ |
131 | void spi_free_slave(struct spi_slave *slave); | 139 | void spi_free_slave(struct spi_slave *slave); |
132 | 140 | ||
133 | /** | 141 | /** |
134 | * Claim the bus and prepare it for communication with a given slave. | 142 | * Claim the bus and prepare it for communication with a given slave. |
135 | * | 143 | * |
136 | * This must be called before doing any transfers with a SPI slave. It | 144 | * This must be called before doing any transfers with a SPI slave. It |
137 | * will enable and initialize any SPI hardware as necessary, and make | 145 | * will enable and initialize any SPI hardware as necessary, and make |
138 | * sure that the SCK line is in the correct idle state. It is not | 146 | * sure that the SCK line is in the correct idle state. It is not |
139 | * allowed to claim the same bus for several slaves without releasing | 147 | * allowed to claim the same bus for several slaves without releasing |
140 | * the bus in between. | 148 | * the bus in between. |
141 | * | 149 | * |
142 | * @slave: The SPI slave | 150 | * @slave: The SPI slave |
143 | * | 151 | * |
144 | * Returns: 0 if the bus was claimed successfully, or a negative value | 152 | * Returns: 0 if the bus was claimed successfully, or a negative value |
145 | * if it wasn't. | 153 | * if it wasn't. |
146 | */ | 154 | */ |
147 | int spi_claim_bus(struct spi_slave *slave); | 155 | int spi_claim_bus(struct spi_slave *slave); |
148 | 156 | ||
149 | /** | 157 | /** |
150 | * Release the SPI bus | 158 | * Release the SPI bus |
151 | * | 159 | * |
152 | * This must be called once for every call to spi_claim_bus() after | 160 | * This must be called once for every call to spi_claim_bus() after |
153 | * all transfers have finished. It may disable any SPI hardware as | 161 | * all transfers have finished. It may disable any SPI hardware as |
154 | * appropriate. | 162 | * appropriate. |
155 | * | 163 | * |
156 | * @slave: The SPI slave | 164 | * @slave: The SPI slave |
157 | */ | 165 | */ |
158 | void spi_release_bus(struct spi_slave *slave); | 166 | void spi_release_bus(struct spi_slave *slave); |
159 | 167 | ||
160 | /** | 168 | /** |
161 | * Set the word length for SPI transactions | 169 | * Set the word length for SPI transactions |
162 | * | 170 | * |
163 | * Set the word length (number of bits per word) for SPI transactions. | 171 | * Set the word length (number of bits per word) for SPI transactions. |
164 | * | 172 | * |
165 | * @slave: The SPI slave | 173 | * @slave: The SPI slave |
166 | * @wordlen: The number of bits in a word | 174 | * @wordlen: The number of bits in a word |
167 | * | 175 | * |
168 | * Returns: 0 on success, -1 on failure. | 176 | * Returns: 0 on success, -1 on failure. |
169 | */ | 177 | */ |
170 | int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen); | 178 | int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen); |
171 | 179 | ||
172 | /** | 180 | /** |
173 | * SPI transfer | 181 | * SPI transfer |
174 | * | 182 | * |
175 | * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks | 183 | * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks |
176 | * "bitlen" bits in the SPI MISO port. That's just the way SPI works. | 184 | * "bitlen" bits in the SPI MISO port. That's just the way SPI works. |
177 | * | 185 | * |
178 | * The source of the outgoing bits is the "dout" parameter and the | 186 | * The source of the outgoing bits is the "dout" parameter and the |
179 | * destination of the input bits is the "din" parameter. Note that "dout" | 187 | * destination of the input bits is the "din" parameter. Note that "dout" |
180 | * and "din" can point to the same memory location, in which case the | 188 | * and "din" can point to the same memory location, in which case the |
181 | * input data overwrites the output data (since both are buffered by | 189 | * input data overwrites the output data (since both are buffered by |
182 | * temporary variables, this is OK). | 190 | * temporary variables, this is OK). |
183 | * | 191 | * |
184 | * spi_xfer() interface: | 192 | * spi_xfer() interface: |
185 | * @slave: The SPI slave which will be sending/receiving the data. | 193 | * @slave: The SPI slave which will be sending/receiving the data. |
186 | * @bitlen: How many bits to write and read. | 194 | * @bitlen: How many bits to write and read. |
187 | * @dout: Pointer to a string of bits to send out. The bits are | 195 | * @dout: Pointer to a string of bits to send out. The bits are |
188 | * held in a byte array and are sent MSB first. | 196 | * held in a byte array and are sent MSB first. |
189 | * @din: Pointer to a string of bits that will be filled in. | 197 | * @din: Pointer to a string of bits that will be filled in. |
190 | * @flags: A bitwise combination of SPI_XFER_* flags. | 198 | * @flags: A bitwise combination of SPI_XFER_* flags. |
191 | * | 199 | * |
192 | * Returns: 0 on success, not 0 on failure | 200 | * Returns: 0 on success, not 0 on failure |
193 | */ | 201 | */ |
194 | int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, | 202 | int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, |
195 | void *din, unsigned long flags); | 203 | void *din, unsigned long flags); |
196 | 204 | ||
197 | /** | 205 | /** |
198 | * Determine if a SPI chipselect is valid. | 206 | * Determine if a SPI chipselect is valid. |
199 | * This function is provided by the board if the low-level SPI driver | 207 | * This function is provided by the board if the low-level SPI driver |
200 | * needs it to determine if a given chipselect is actually valid. | 208 | * needs it to determine if a given chipselect is actually valid. |
201 | * | 209 | * |
202 | * Returns: 1 if bus:cs identifies a valid chip on this board, 0 | 210 | * Returns: 1 if bus:cs identifies a valid chip on this board, 0 |
203 | * otherwise. | 211 | * otherwise. |
204 | */ | 212 | */ |
205 | int spi_cs_is_valid(unsigned int bus, unsigned int cs); | 213 | int spi_cs_is_valid(unsigned int bus, unsigned int cs); |
206 | 214 | ||
207 | /** | 215 | /** |
208 | * Activate a SPI chipselect. | 216 | * Activate a SPI chipselect. |
209 | * This function is provided by the board code when using a driver | 217 | * This function is provided by the board code when using a driver |
210 | * that can't control its chipselects automatically (e.g. | 218 | * that can't control its chipselects automatically (e.g. |
211 | * common/soft_spi.c). When called, it should activate the chip select | 219 | * common/soft_spi.c). When called, it should activate the chip select |
212 | * to the device identified by "slave". | 220 | * to the device identified by "slave". |
213 | */ | 221 | */ |
214 | void spi_cs_activate(struct spi_slave *slave); | 222 | void spi_cs_activate(struct spi_slave *slave); |
215 | 223 | ||
216 | /** | 224 | /** |
217 | * Deactivate a SPI chipselect. | 225 | * Deactivate a SPI chipselect. |
218 | * This function is provided by the board code when using a driver | 226 | * This function is provided by the board code when using a driver |
219 | * that can't control its chipselects automatically (e.g. | 227 | * that can't control its chipselects automatically (e.g. |
220 | * common/soft_spi.c). When called, it should deactivate the chip | 228 | * common/soft_spi.c). When called, it should deactivate the chip |
221 | * select to the device identified by "slave". | 229 | * select to the device identified by "slave". |
222 | */ | 230 | */ |
223 | void spi_cs_deactivate(struct spi_slave *slave); | 231 | void spi_cs_deactivate(struct spi_slave *slave); |
224 | 232 | ||
225 | /** | 233 | /** |
226 | * Set transfer speed. | 234 | * Set transfer speed. |
227 | * This sets a new speed to be applied for next spi_xfer(). | 235 | * This sets a new speed to be applied for next spi_xfer(). |
228 | * @slave: The SPI slave | 236 | * @slave: The SPI slave |
229 | * @hz: The transfer speed | 237 | * @hz: The transfer speed |
230 | */ | 238 | */ |
231 | void spi_set_speed(struct spi_slave *slave, uint hz); | 239 | void spi_set_speed(struct spi_slave *slave, uint hz); |
232 | 240 | ||
233 | /** | 241 | /** |
234 | * Write 8 bits, then read 8 bits. | 242 | * Write 8 bits, then read 8 bits. |
235 | * @slave: The SPI slave we're communicating with | 243 | * @slave: The SPI slave we're communicating with |
236 | * @byte: Byte to be written | 244 | * @byte: Byte to be written |
237 | * | 245 | * |
238 | * Returns: The value that was read, or a negative value on error. | 246 | * Returns: The value that was read, or a negative value on error. |
239 | * | 247 | * |
240 | * TODO: This function probably shouldn't be inlined. | 248 | * TODO: This function probably shouldn't be inlined. |
241 | */ | 249 | */ |
242 | static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) | 250 | static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) |
243 | { | 251 | { |
244 | unsigned char dout[2]; | 252 | unsigned char dout[2]; |
245 | unsigned char din[2]; | 253 | unsigned char din[2]; |
246 | int ret; | 254 | int ret; |
247 | 255 | ||
248 | dout[0] = byte; | 256 | dout[0] = byte; |
249 | dout[1] = 0; | 257 | dout[1] = 0; |
250 | 258 | ||
251 | ret = spi_xfer(slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END); | 259 | ret = spi_xfer(slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END); |
252 | return ret < 0 ? ret : din[1]; | 260 | return ret < 0 ? ret : din[1]; |
253 | } | 261 | } |
254 | 262 | ||
255 | /** | 263 | /** |
256 | * Set up a SPI slave for a particular device tree node | 264 | * Set up a SPI slave for a particular device tree node |
257 | * | 265 | * |
258 | * This calls spi_setup_slave() with the correct bus number. Call | 266 | * This calls spi_setup_slave() with the correct bus number. Call |
259 | * spi_free_slave() to free it later. | 267 | * spi_free_slave() to free it later. |
260 | * | 268 | * |
261 | * @param blob: Device tree blob | 269 | * @param blob: Device tree blob |
262 | * @param slave_node: Slave node to use | 270 | * @param slave_node: Slave node to use |
263 | * @param spi_node: SPI peripheral node to use | 271 | * @param spi_node: SPI peripheral node to use |
264 | * @return pointer to new spi_slave structure | 272 | * @return pointer to new spi_slave structure |
265 | */ | 273 | */ |
266 | struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node, | 274 | struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node, |
267 | int spi_node); | 275 | int spi_node); |
268 | 276 | ||
269 | /** | 277 | /** |
270 | * spi_base_setup_slave_fdt() - helper function to set up a SPI slace | 278 | * spi_base_setup_slave_fdt() - helper function to set up a SPI slace |
271 | * | 279 | * |
272 | * This decodes SPI properties from the slave node to determine the | 280 | * This decodes SPI properties from the slave node to determine the |
273 | * chip select and SPI parameters. | 281 | * chip select and SPI parameters. |
274 | * | 282 | * |
275 | * @blob: Device tree blob | 283 | * @blob: Device tree blob |
276 | * @busnum: Bus number to use | 284 | * @busnum: Bus number to use |
277 | * @node: Device tree node for the SPI bus | 285 | * @node: Device tree node for the SPI bus |
278 | */ | 286 | */ |
279 | struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum, | 287 | struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum, |
280 | int node); | 288 | int node); |
281 | 289 | ||
282 | #endif /* _SPI_H_ */ | 290 | #endif /* _SPI_H_ */ |
283 | 291 |
include/spi_flash.h
1 | /* | 1 | /* |
2 | * Common SPI flash Interface | 2 | * Common SPI flash Interface |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Atmel Corporation | 4 | * Copyright (C) 2008 Atmel Corporation |
5 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | 5 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
6 | * | 6 | * |
7 | * See file CREDITS for list of people who contributed to this | 7 | * See file CREDITS for list of people who contributed to this |
8 | * project. | 8 | * project. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
12 | * version 2 as published by the Free Software Foundation. | 12 | * version 2 as published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #ifndef _SPI_FLASH_H_ | 15 | #ifndef _SPI_FLASH_H_ |
16 | #define _SPI_FLASH_H_ | 16 | #define _SPI_FLASH_H_ |
17 | 17 | ||
18 | #include <spi.h> | 18 | #include <spi.h> |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/compiler.h> | 20 | #include <linux/compiler.h> |
21 | 21 | ||
22 | /* Enum list - Extended read commands */ | ||
23 | enum spi_read_cmds { | ||
24 | ARRAY_SLOW = 1 << 0, | ||
25 | DUAL_OUTPUT_FAST = 1 << 1, | ||
26 | DUAL_IO_FAST = 1 << 2, | ||
27 | }; | ||
28 | #define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST | ||
29 | |||
22 | /** | 30 | /** |
23 | * struct spi_flash - SPI flash structure | 31 | * struct spi_flash - SPI flash structure |
24 | * | 32 | * |
25 | * @spi: SPI slave | 33 | * @spi: SPI slave |
26 | * @name: Name of SPI flash | 34 | * @name: Name of SPI flash |
27 | * @size: Total flash size | 35 | * @size: Total flash size |
28 | * @page_size: Write (page) size | 36 | * @page_size: Write (page) size |
29 | * @sector_size: Sector size | 37 | * @sector_size: Sector size |
30 | * @erase_size: Erase size | 38 | * @erase_size: Erase size |
31 | * @bank_read_cmd: Bank read cmd | 39 | * @bank_read_cmd: Bank read cmd |
32 | * @bank_write_cmd: Bank write cmd | 40 | * @bank_write_cmd: Bank write cmd |
33 | * @bank_curr: Current flash bank | 41 | * @bank_curr: Current flash bank |
34 | * @poll_cmd: Poll cmd - for flash erase/program | 42 | * @poll_cmd: Poll cmd - for flash erase/program |
35 | * @erase_cmd: Erase cmd 4K, 32K, 64K | 43 | * @erase_cmd: Erase cmd 4K, 32K, 64K |
44 | * @read_cmd: Read cmd - Array Fast and Extn read | ||
36 | * @memory_map: Address of read-only SPI flash access | 45 | * @memory_map: Address of read-only SPI flash access |
37 | * @read: Flash read ops: Read len bytes at offset into buf | 46 | * @read: Flash read ops: Read len bytes at offset into buf |
38 | * Supported cmds: Fast Array Read | 47 | * Supported cmds: Fast Array Read |
39 | * @write: Flash write ops: Write len bytes from buf into offeset | 48 | * @write: Flash write ops: Write len bytes from buf into offeset |
40 | * Supported cmds: Page Program | 49 | * Supported cmds: Page Program |
41 | * @erase: Flash erase ops: Erase len bytes from offset | 50 | * @erase: Flash erase ops: Erase len bytes from offset |
42 | * Supported cmds: Sector erase 4K, 32K, 64K | 51 | * Supported cmds: Sector erase 4K, 32K, 64K |
43 | * return 0 - Sucess, 1 - Failure | 52 | * return 0 - Sucess, 1 - Failure |
44 | */ | 53 | */ |
45 | struct spi_flash { | 54 | struct spi_flash { |
46 | struct spi_slave *spi; | 55 | struct spi_slave *spi; |
47 | const char *name; | 56 | const char *name; |
48 | 57 | ||
49 | u32 size; | 58 | u32 size; |
50 | u32 page_size; | 59 | u32 page_size; |
51 | u32 sector_size; | 60 | u32 sector_size; |
52 | u32 erase_size; | 61 | u32 erase_size; |
53 | #ifdef CONFIG_SPI_FLASH_BAR | 62 | #ifdef CONFIG_SPI_FLASH_BAR |
54 | u8 bank_read_cmd; | 63 | u8 bank_read_cmd; |
55 | u8 bank_write_cmd; | 64 | u8 bank_write_cmd; |
56 | u8 bank_curr; | 65 | u8 bank_curr; |
57 | #endif | 66 | #endif |
58 | u8 poll_cmd; | 67 | u8 poll_cmd; |
59 | u8 erase_cmd; | 68 | u8 erase_cmd; |
69 | u8 read_cmd; | ||
60 | 70 | ||
61 | void *memory_map; | 71 | void *memory_map; |
62 | int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); | 72 | int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); |
63 | int (*write)(struct spi_flash *flash, u32 offset, size_t len, | 73 | int (*write)(struct spi_flash *flash, u32 offset, size_t len, |
64 | const void *buf); | 74 | const void *buf); |
65 | int (*erase)(struct spi_flash *flash, u32 offset, size_t len); | 75 | int (*erase)(struct spi_flash *flash, u32 offset, size_t len); |
66 | }; | 76 | }; |
67 | 77 | ||
68 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | 78 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, |
69 | unsigned int max_hz, unsigned int spi_mode); | 79 | unsigned int max_hz, unsigned int spi_mode); |
70 | 80 | ||
71 | /** | 81 | /** |
72 | * Set up a new SPI flash from an fdt node | 82 | * Set up a new SPI flash from an fdt node |
73 | * | 83 | * |
74 | * @param blob Device tree blob | 84 | * @param blob Device tree blob |
75 | * @param slave_node Pointer to this SPI slave node in the device tree | 85 | * @param slave_node Pointer to this SPI slave node in the device tree |
76 | * @param spi_node Cached pointer to the SPI interface this node belongs | 86 | * @param spi_node Cached pointer to the SPI interface this node belongs |
77 | * to | 87 | * to |
78 | * @return 0 if ok, -1 on error | 88 | * @return 0 if ok, -1 on error |
79 | */ | 89 | */ |
80 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, | 90 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, |
81 | int spi_node); | 91 | int spi_node); |
82 | 92 | ||
83 | void spi_flash_free(struct spi_flash *flash); | 93 | void spi_flash_free(struct spi_flash *flash); |
84 | 94 | ||
85 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, | 95 | static inline int spi_flash_read(struct spi_flash *flash, u32 offset, |
86 | size_t len, void *buf) | 96 | size_t len, void *buf) |
87 | { | 97 | { |
88 | return flash->read(flash, offset, len, buf); | 98 | return flash->read(flash, offset, len, buf); |
89 | } | 99 | } |
90 | 100 | ||
91 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, | 101 | static inline int spi_flash_write(struct spi_flash *flash, u32 offset, |
92 | size_t len, const void *buf) | 102 | size_t len, const void *buf) |
93 | { | 103 | { |
94 | return flash->write(flash, offset, len, buf); | 104 | return flash->write(flash, offset, len, buf); |
95 | } | 105 | } |
96 | 106 | ||
97 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, | 107 | static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, |
98 | size_t len) | 108 | size_t len) |
99 | { | 109 | { |
100 | return flash->erase(flash, offset, len); | 110 | return flash->erase(flash, offset, len); |
101 | } | 111 | } |
102 | 112 | ||
103 | void spi_boot(void) __noreturn; | 113 | void spi_boot(void) __noreturn; |
104 | 114 | ||
105 | #endif /* _SPI_FLASH_H_ */ | 115 | #endif /* _SPI_FLASH_H_ */ |
106 | 116 |