Commit 067951223e3305fce3df972c1970f6ab1ef15e98
1 parent
ff063ed480
Exists in
master
and in
50 other branches
sf: Add macronix set QEB support
This patch adds set QEB support for macronix flash devices which are trying to program/read quad operations. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
Showing 3 changed files with 35 additions and 0 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_3B_ADDR_LEN 3 | 13 | #define SPI_FLASH_3B_ADDR_LEN 3 |
14 | #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) | 14 | #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) |
15 | #define SPI_FLASH_16MB_BOUN 0x1000000 | 15 | #define SPI_FLASH_16MB_BOUN 0x1000000 |
16 | 16 | ||
17 | /* CFI Manufacture ID's */ | 17 | /* CFI Manufacture ID's */ |
18 | #define SPI_FLASH_CFI_MFR_SPANSION 0x01 | 18 | #define SPI_FLASH_CFI_MFR_SPANSION 0x01 |
19 | #define SPI_FLASH_CFI_MFR_STMICRO 0x20 | 19 | #define SPI_FLASH_CFI_MFR_STMICRO 0x20 |
20 | #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 | ||
20 | #define SPI_FLASH_CFI_MFR_WINBOND 0xef | 21 | #define SPI_FLASH_CFI_MFR_WINBOND 0xef |
21 | 22 | ||
22 | /* SECT flags */ | 23 | /* SECT flags */ |
23 | #define SECT_4K (1 << 1) | 24 | #define SECT_4K (1 << 1) |
24 | #define SECT_32K (1 << 2) | 25 | #define SECT_32K (1 << 2) |
25 | #define E_FSR (1 << 3) | 26 | #define E_FSR (1 << 3) |
26 | 27 | ||
27 | /* Erase commands */ | 28 | /* Erase commands */ |
28 | #define CMD_ERASE_4K 0x20 | 29 | #define CMD_ERASE_4K 0x20 |
29 | #define CMD_ERASE_32K 0x52 | 30 | #define CMD_ERASE_32K 0x52 |
30 | #define CMD_ERASE_CHIP 0xc7 | 31 | #define CMD_ERASE_CHIP 0xc7 |
31 | #define CMD_ERASE_64K 0xd8 | 32 | #define CMD_ERASE_64K 0xd8 |
32 | 33 | ||
33 | /* Write commands */ | 34 | /* Write commands */ |
34 | #define CMD_WRITE_STATUS 0x01 | 35 | #define CMD_WRITE_STATUS 0x01 |
35 | #define CMD_PAGE_PROGRAM 0x02 | 36 | #define CMD_PAGE_PROGRAM 0x02 |
36 | #define CMD_WRITE_DISABLE 0x04 | 37 | #define CMD_WRITE_DISABLE 0x04 |
37 | #define CMD_READ_STATUS 0x05 | 38 | #define CMD_READ_STATUS 0x05 |
38 | #define CMD_QUAD_PAGE_PROGRAM 0x32 | 39 | #define CMD_QUAD_PAGE_PROGRAM 0x32 |
39 | #define CMD_READ_STATUS1 0x35 | 40 | #define CMD_READ_STATUS1 0x35 |
40 | #define CMD_WRITE_ENABLE 0x06 | 41 | #define CMD_WRITE_ENABLE 0x06 |
41 | #define CMD_READ_CONFIG 0x35 | 42 | #define CMD_READ_CONFIG 0x35 |
42 | #define CMD_FLAG_STATUS 0x70 | 43 | #define CMD_FLAG_STATUS 0x70 |
43 | 44 | ||
44 | /* Read commands */ | 45 | /* Read commands */ |
45 | #define CMD_READ_ARRAY_SLOW 0x03 | 46 | #define CMD_READ_ARRAY_SLOW 0x03 |
46 | #define CMD_READ_ARRAY_FAST 0x0b | 47 | #define CMD_READ_ARRAY_FAST 0x0b |
47 | #define CMD_READ_DUAL_OUTPUT_FAST 0x3b | 48 | #define CMD_READ_DUAL_OUTPUT_FAST 0x3b |
48 | #define CMD_READ_DUAL_IO_FAST 0xbb | 49 | #define CMD_READ_DUAL_IO_FAST 0xbb |
49 | #define CMD_READ_QUAD_OUTPUT_FAST 0x6b | 50 | #define CMD_READ_QUAD_OUTPUT_FAST 0x6b |
50 | #define CMD_READ_QUAD_IO_FAST 0xeb | 51 | #define CMD_READ_QUAD_IO_FAST 0xeb |
51 | #define CMD_READ_ID 0x9f | 52 | #define CMD_READ_ID 0x9f |
52 | 53 | ||
53 | /* Bank addr access commands */ | 54 | /* Bank addr access commands */ |
54 | #ifdef CONFIG_SPI_FLASH_BAR | 55 | #ifdef CONFIG_SPI_FLASH_BAR |
55 | # define CMD_BANKADDR_BRWR 0x17 | 56 | # define CMD_BANKADDR_BRWR 0x17 |
56 | # define CMD_BANKADDR_BRRD 0x16 | 57 | # define CMD_BANKADDR_BRRD 0x16 |
57 | # define CMD_EXTNADDR_WREAR 0xC5 | 58 | # define CMD_EXTNADDR_WREAR 0xC5 |
58 | # define CMD_EXTNADDR_RDEAR 0xC8 | 59 | # define CMD_EXTNADDR_RDEAR 0xC8 |
59 | #endif | 60 | #endif |
60 | 61 | ||
61 | /* Common status */ | 62 | /* Common status */ |
62 | #define STATUS_WIP 0x01 | 63 | #define STATUS_WIP 0x01 |
63 | #define STATUS_QEB_WINSPAN (1 << 1) | 64 | #define STATUS_QEB_WINSPAN (1 << 1) |
65 | #define STATUS_QEB_MXIC (1 << 6) | ||
64 | #define STATUS_PEC 0x80 | 66 | #define STATUS_PEC 0x80 |
65 | 67 | ||
66 | /* Flash timeout values */ | 68 | /* Flash timeout values */ |
67 | #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) | 69 | #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) |
68 | #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) | 70 | #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) |
69 | #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) | 71 | #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) |
70 | 72 | ||
71 | /* SST specific */ | 73 | /* SST specific */ |
72 | #ifdef CONFIG_SPI_FLASH_SST | 74 | #ifdef CONFIG_SPI_FLASH_SST |
73 | # define SST_WP 0x01 /* Supports AAI word program */ | 75 | # define SST_WP 0x01 /* Supports AAI word program */ |
74 | # define CMD_SST_BP 0x02 /* Byte Program */ | 76 | # define CMD_SST_BP 0x02 /* Byte Program */ |
75 | # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ | 77 | # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ |
76 | 78 | ||
77 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | 79 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, |
78 | const void *buf); | 80 | const void *buf); |
79 | #endif | 81 | #endif |
80 | 82 | ||
81 | /* Send a single-byte command to the device and read the response */ | 83 | /* Send a single-byte command to the device and read the response */ |
82 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); | 84 | int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); |
83 | 85 | ||
84 | /* | 86 | /* |
85 | * Send a multi-byte command to the device and read the response. Used | 87 | * Send a multi-byte command to the device and read the response. Used |
86 | * for flash array reads, etc. | 88 | * for flash array reads, etc. |
87 | */ | 89 | */ |
88 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, | 90 | int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, |
89 | size_t cmd_len, void *data, size_t data_len); | 91 | size_t cmd_len, void *data, size_t data_len); |
90 | 92 | ||
91 | /* | 93 | /* |
92 | * Send a multi-byte command to the device followed by (optional) | 94 | * Send a multi-byte command to the device followed by (optional) |
93 | * data. Used for programming the flash array, etc. | 95 | * data. Used for programming the flash array, etc. |
94 | */ | 96 | */ |
95 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, | 97 | int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, |
96 | const void *data, size_t data_len); | 98 | const void *data, size_t data_len); |
97 | 99 | ||
98 | 100 | ||
99 | /* Flash erase(sectors) operation, support all possible erase commands */ | 101 | /* Flash erase(sectors) operation, support all possible erase commands */ |
100 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); | 102 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); |
101 | 103 | ||
102 | /* Program the status register */ | 104 | /* Program the status register */ |
103 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); | 105 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); |
106 | |||
107 | /* Set quad enbale bit for macronix flashes */ | ||
108 | int spi_flash_set_qeb_mxic(struct spi_flash *flash); | ||
104 | 109 | ||
105 | /* Set quad enbale bit for winbond and spansion flashes */ | 110 | /* Set quad enbale bit for winbond and spansion flashes */ |
106 | int spi_flash_set_qeb_winspan(struct spi_flash *flash); | 111 | int spi_flash_set_qeb_winspan(struct spi_flash *flash); |
107 | 112 | ||
108 | /* Enable writing on the SPI flash */ | 113 | /* Enable writing on the SPI flash */ |
109 | static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) | 114 | static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) |
110 | { | 115 | { |
111 | return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); | 116 | return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); |
112 | } | 117 | } |
113 | 118 | ||
114 | /* Disable writing on the SPI flash */ | 119 | /* Disable writing on the SPI flash */ |
115 | static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) | 120 | static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) |
116 | { | 121 | { |
117 | return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); | 122 | return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); |
118 | } | 123 | } |
119 | 124 | ||
120 | /* | 125 | /* |
121 | * Send the read status command to the device and wait for the wip | 126 | * Send the read status command to the device and wait for the wip |
122 | * (write-in-progress) bit to clear itself. | 127 | * (write-in-progress) bit to clear itself. |
123 | */ | 128 | */ |
124 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); | 129 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); |
125 | 130 | ||
126 | /* | 131 | /* |
127 | * Used for spi_flash write operation | 132 | * Used for spi_flash write operation |
128 | * - SPI claim | 133 | * - SPI claim |
129 | * - spi_flash_cmd_write_enable | 134 | * - spi_flash_cmd_write_enable |
130 | * - spi_flash_cmd_write | 135 | * - spi_flash_cmd_write |
131 | * - spi_flash_cmd_wait_ready | 136 | * - spi_flash_cmd_wait_ready |
132 | * - SPI release | 137 | * - SPI release |
133 | */ | 138 | */ |
134 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | 139 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, |
135 | size_t cmd_len, const void *buf, size_t buf_len); | 140 | size_t cmd_len, const void *buf, size_t buf_len); |
136 | 141 | ||
137 | /* | 142 | /* |
138 | * Flash write operation, support all possible write commands. | 143 | * Flash write operation, support all possible write commands. |
139 | * Write the requested data out breaking it up into multiple write | 144 | * Write the requested data out breaking it up into multiple write |
140 | * commands as needed per the write size. | 145 | * commands as needed per the write size. |
141 | */ | 146 | */ |
142 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | 147 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, |
143 | size_t len, const void *buf); | 148 | size_t len, const void *buf); |
144 | 149 | ||
145 | /* | 150 | /* |
146 | * Same as spi_flash_cmd_read() except it also claims/releases the SPI | 151 | * Same as spi_flash_cmd_read() except it also claims/releases the SPI |
147 | * bus. Used as common part of the ->read() operation. | 152 | * bus. Used as common part of the ->read() operation. |
148 | */ | 153 | */ |
149 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | 154 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, |
150 | size_t cmd_len, void *data, size_t data_len); | 155 | size_t cmd_len, void *data, size_t data_len); |
151 | 156 | ||
152 | /* Flash read operation, support all possible read commands */ | 157 | /* Flash read operation, support all possible read commands */ |
153 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | 158 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, |
154 | size_t len, void *data); | 159 | size_t len, void *data); |
155 | 160 | ||
156 | #endif /* _SF_INTERNAL_H_ */ | 161 | #endif /* _SF_INTERNAL_H_ */ |
157 | 162 |
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 <malloc.h> | 12 | #include <malloc.h> |
13 | #include <spi.h> | 13 | #include <spi.h> |
14 | #include <spi_flash.h> | 14 | #include <spi_flash.h> |
15 | #include <watchdog.h> | 15 | #include <watchdog.h> |
16 | 16 | ||
17 | #include "sf_internal.h" | 17 | #include "sf_internal.h" |
18 | 18 | ||
19 | static void spi_flash_addr(u32 addr, u8 *cmd) | 19 | static void spi_flash_addr(u32 addr, u8 *cmd) |
20 | { | 20 | { |
21 | /* cmd[0] is actual command */ | 21 | /* cmd[0] is actual command */ |
22 | cmd[1] = addr >> 16; | 22 | cmd[1] = addr >> 16; |
23 | cmd[2] = addr >> 8; | 23 | cmd[2] = addr >> 8; |
24 | cmd[3] = addr >> 0; | 24 | cmd[3] = addr >> 0; |
25 | } | 25 | } |
26 | 26 | ||
27 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) | 27 | int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) |
28 | { | 28 | { |
29 | u8 cmd; | 29 | u8 cmd; |
30 | int ret; | 30 | int ret; |
31 | 31 | ||
32 | cmd = CMD_WRITE_STATUS; | 32 | cmd = CMD_WRITE_STATUS; |
33 | ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); | 33 | ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); |
34 | if (ret < 0) { | 34 | if (ret < 0) { |
35 | debug("SF: fail to write status register\n"); | 35 | debug("SF: fail to write status register\n"); |
36 | return ret; | 36 | return ret; |
37 | } | 37 | } |
38 | 38 | ||
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | #ifdef CONFIG_SPI_FLASH_MACRONIX | ||
43 | int spi_flash_set_qeb_mxic(struct spi_flash *flash) | ||
44 | { | ||
45 | u8 qeb_status; | ||
46 | u8 cmd; | ||
47 | int ret; | ||
48 | |||
49 | cmd = CMD_READ_STATUS; | ||
50 | ret = spi_flash_read_common(flash, &cmd, 1, &qeb_status, 1); | ||
51 | if (ret < 0) { | ||
52 | debug("SF: fail to read status register\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | if (qeb_status & STATUS_QEB_MXIC) { | ||
57 | debug("SF: Quad enable bit is already set\n"); | ||
58 | } else { | ||
59 | ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC); | ||
60 | if (ret < 0) | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | #endif | ||
67 | |||
42 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 68 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
43 | static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 cr) | 69 | static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 cr) |
44 | { | 70 | { |
45 | u8 data[2]; | 71 | u8 data[2]; |
46 | u8 cmd; | 72 | u8 cmd; |
47 | int ret; | 73 | int ret; |
48 | 74 | ||
49 | cmd = CMD_READ_STATUS; | 75 | cmd = CMD_READ_STATUS; |
50 | ret = spi_flash_read_common(flash, &cmd, 1, &data[0], 1); | 76 | ret = spi_flash_read_common(flash, &cmd, 1, &data[0], 1); |
51 | if (ret < 0) { | 77 | if (ret < 0) { |
52 | debug("SF: fail to read status register\n"); | 78 | debug("SF: fail to read status register\n"); |
53 | return ret; | 79 | return ret; |
54 | } | 80 | } |
55 | 81 | ||
56 | cmd = CMD_WRITE_STATUS; | 82 | cmd = CMD_WRITE_STATUS; |
57 | data[1] = cr; | 83 | data[1] = cr; |
58 | ret = spi_flash_write_common(flash, &cmd, 1, &data, 2); | 84 | ret = spi_flash_write_common(flash, &cmd, 1, &data, 2); |
59 | if (ret) { | 85 | if (ret) { |
60 | debug("SF: fail to write config register\n"); | 86 | debug("SF: fail to write config register\n"); |
61 | return ret; | 87 | return ret; |
62 | } | 88 | } |
63 | 89 | ||
64 | return 0; | 90 | return 0; |
65 | } | 91 | } |
66 | 92 | ||
67 | int spi_flash_set_qeb_winspan(struct spi_flash *flash) | 93 | int spi_flash_set_qeb_winspan(struct spi_flash *flash) |
68 | { | 94 | { |
69 | u8 qeb_status; | 95 | u8 qeb_status; |
70 | u8 cmd; | 96 | u8 cmd; |
71 | int ret; | 97 | int ret; |
72 | 98 | ||
73 | cmd = CMD_READ_CONFIG; | 99 | cmd = CMD_READ_CONFIG; |
74 | ret = spi_flash_read_common(flash, &cmd, 1, &qeb_status, 1); | 100 | ret = spi_flash_read_common(flash, &cmd, 1, &qeb_status, 1); |
75 | if (ret < 0) { | 101 | if (ret < 0) { |
76 | debug("SF: fail to read config register\n"); | 102 | debug("SF: fail to read config register\n"); |
77 | return ret; | 103 | return ret; |
78 | } | 104 | } |
79 | 105 | ||
80 | if (qeb_status & STATUS_QEB_WINSPAN) { | 106 | if (qeb_status & STATUS_QEB_WINSPAN) { |
81 | debug("SF: Quad enable bit is already set\n"); | 107 | debug("SF: Quad enable bit is already set\n"); |
82 | } else { | 108 | } else { |
83 | ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN); | 109 | ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN); |
84 | if (ret < 0) | 110 | if (ret < 0) |
85 | return ret; | 111 | return ret; |
86 | } | 112 | } |
87 | 113 | ||
88 | return ret; | 114 | return ret; |
89 | } | 115 | } |
90 | #endif | 116 | #endif |
91 | 117 | ||
92 | #ifdef CONFIG_SPI_FLASH_BAR | 118 | #ifdef CONFIG_SPI_FLASH_BAR |
93 | static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) | 119 | static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) |
94 | { | 120 | { |
95 | u8 cmd; | 121 | u8 cmd; |
96 | int ret; | 122 | int ret; |
97 | 123 | ||
98 | if (flash->bank_curr == bank_sel) { | 124 | if (flash->bank_curr == bank_sel) { |
99 | debug("SF: not require to enable bank%d\n", bank_sel); | 125 | debug("SF: not require to enable bank%d\n", bank_sel); |
100 | return 0; | 126 | return 0; |
101 | } | 127 | } |
102 | 128 | ||
103 | cmd = flash->bank_write_cmd; | 129 | cmd = flash->bank_write_cmd; |
104 | ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); | 130 | ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); |
105 | if (ret < 0) { | 131 | if (ret < 0) { |
106 | debug("SF: fail to write bank register\n"); | 132 | debug("SF: fail to write bank register\n"); |
107 | return ret; | 133 | return ret; |
108 | } | 134 | } |
109 | flash->bank_curr = bank_sel; | 135 | flash->bank_curr = bank_sel; |
110 | 136 | ||
111 | return 0; | 137 | return 0; |
112 | } | 138 | } |
113 | 139 | ||
114 | static int spi_flash_bank(struct spi_flash *flash, u32 offset) | 140 | static int spi_flash_bank(struct spi_flash *flash, u32 offset) |
115 | { | 141 | { |
116 | u8 bank_sel; | 142 | u8 bank_sel; |
117 | int ret; | 143 | int ret; |
118 | 144 | ||
119 | bank_sel = offset / SPI_FLASH_16MB_BOUN; | 145 | bank_sel = offset / SPI_FLASH_16MB_BOUN; |
120 | 146 | ||
121 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); | 147 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); |
122 | if (ret) { | 148 | if (ret) { |
123 | debug("SF: fail to set bank%d\n", bank_sel); | 149 | debug("SF: fail to set bank%d\n", bank_sel); |
124 | return ret; | 150 | return ret; |
125 | } | 151 | } |
126 | 152 | ||
127 | return 0; | 153 | return 0; |
128 | } | 154 | } |
129 | #endif | 155 | #endif |
130 | 156 | ||
131 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) | 157 | int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) |
132 | { | 158 | { |
133 | struct spi_slave *spi = flash->spi; | 159 | struct spi_slave *spi = flash->spi; |
134 | unsigned long timebase; | 160 | unsigned long timebase; |
135 | int ret; | 161 | int ret; |
136 | u8 status; | 162 | u8 status; |
137 | u8 check_status = 0x0; | 163 | u8 check_status = 0x0; |
138 | u8 poll_bit = STATUS_WIP; | 164 | u8 poll_bit = STATUS_WIP; |
139 | u8 cmd = flash->poll_cmd; | 165 | u8 cmd = flash->poll_cmd; |
140 | 166 | ||
141 | if (cmd == CMD_FLAG_STATUS) { | 167 | if (cmd == CMD_FLAG_STATUS) { |
142 | poll_bit = STATUS_PEC; | 168 | poll_bit = STATUS_PEC; |
143 | check_status = poll_bit; | 169 | check_status = poll_bit; |
144 | } | 170 | } |
145 | 171 | ||
146 | ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); | 172 | ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); |
147 | if (ret) { | 173 | if (ret) { |
148 | debug("SF: fail to read %s status register\n", | 174 | debug("SF: fail to read %s status register\n", |
149 | cmd == CMD_READ_STATUS ? "read" : "flag"); | 175 | cmd == CMD_READ_STATUS ? "read" : "flag"); |
150 | return ret; | 176 | return ret; |
151 | } | 177 | } |
152 | 178 | ||
153 | timebase = get_timer(0); | 179 | timebase = get_timer(0); |
154 | do { | 180 | do { |
155 | WATCHDOG_RESET(); | 181 | WATCHDOG_RESET(); |
156 | 182 | ||
157 | ret = spi_xfer(spi, 8, NULL, &status, 0); | 183 | ret = spi_xfer(spi, 8, NULL, &status, 0); |
158 | if (ret) | 184 | if (ret) |
159 | return -1; | 185 | return -1; |
160 | 186 | ||
161 | if ((status & poll_bit) == check_status) | 187 | if ((status & poll_bit) == check_status) |
162 | break; | 188 | break; |
163 | 189 | ||
164 | } while (get_timer(timebase) < timeout); | 190 | } while (get_timer(timebase) < timeout); |
165 | 191 | ||
166 | spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); | 192 | spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); |
167 | 193 | ||
168 | if ((status & poll_bit) == check_status) | 194 | if ((status & poll_bit) == check_status) |
169 | return 0; | 195 | return 0; |
170 | 196 | ||
171 | /* Timed out */ | 197 | /* Timed out */ |
172 | debug("SF: time out!\n"); | 198 | debug("SF: time out!\n"); |
173 | return -1; | 199 | return -1; |
174 | } | 200 | } |
175 | 201 | ||
176 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | 202 | int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, |
177 | size_t cmd_len, const void *buf, size_t buf_len) | 203 | size_t cmd_len, const void *buf, size_t buf_len) |
178 | { | 204 | { |
179 | struct spi_slave *spi = flash->spi; | 205 | struct spi_slave *spi = flash->spi; |
180 | unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; | 206 | unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; |
181 | int ret; | 207 | int ret; |
182 | 208 | ||
183 | if (buf == NULL) | 209 | if (buf == NULL) |
184 | timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; | 210 | timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; |
185 | 211 | ||
186 | ret = spi_claim_bus(flash->spi); | 212 | ret = spi_claim_bus(flash->spi); |
187 | if (ret) { | 213 | if (ret) { |
188 | debug("SF: unable to claim SPI bus\n"); | 214 | debug("SF: unable to claim SPI bus\n"); |
189 | return ret; | 215 | return ret; |
190 | } | 216 | } |
191 | 217 | ||
192 | ret = spi_flash_cmd_write_enable(flash); | 218 | ret = spi_flash_cmd_write_enable(flash); |
193 | if (ret < 0) { | 219 | if (ret < 0) { |
194 | debug("SF: enabling write failed\n"); | 220 | debug("SF: enabling write failed\n"); |
195 | return ret; | 221 | return ret; |
196 | } | 222 | } |
197 | 223 | ||
198 | ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); | 224 | ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); |
199 | if (ret < 0) { | 225 | if (ret < 0) { |
200 | debug("SF: write cmd failed\n"); | 226 | debug("SF: write cmd failed\n"); |
201 | return ret; | 227 | return ret; |
202 | } | 228 | } |
203 | 229 | ||
204 | ret = spi_flash_cmd_wait_ready(flash, timeout); | 230 | ret = spi_flash_cmd_wait_ready(flash, timeout); |
205 | if (ret < 0) { | 231 | if (ret < 0) { |
206 | debug("SF: write %s timed out\n", | 232 | debug("SF: write %s timed out\n", |
207 | timeout == SPI_FLASH_PROG_TIMEOUT ? | 233 | timeout == SPI_FLASH_PROG_TIMEOUT ? |
208 | "program" : "page erase"); | 234 | "program" : "page erase"); |
209 | return ret; | 235 | return ret; |
210 | } | 236 | } |
211 | 237 | ||
212 | spi_release_bus(spi); | 238 | spi_release_bus(spi); |
213 | 239 | ||
214 | return ret; | 240 | return ret; |
215 | } | 241 | } |
216 | 242 | ||
217 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) | 243 | int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) |
218 | { | 244 | { |
219 | u32 erase_size; | 245 | u32 erase_size; |
220 | u8 cmd[SPI_FLASH_CMD_LEN]; | 246 | u8 cmd[SPI_FLASH_CMD_LEN]; |
221 | int ret = -1; | 247 | int ret = -1; |
222 | 248 | ||
223 | erase_size = flash->erase_size; | 249 | erase_size = flash->erase_size; |
224 | if (offset % erase_size || len % erase_size) { | 250 | if (offset % erase_size || len % erase_size) { |
225 | debug("SF: Erase offset/length not multiple of erase size\n"); | 251 | debug("SF: Erase offset/length not multiple of erase size\n"); |
226 | return -1; | 252 | return -1; |
227 | } | 253 | } |
228 | 254 | ||
229 | cmd[0] = flash->erase_cmd; | 255 | cmd[0] = flash->erase_cmd; |
230 | while (len) { | 256 | while (len) { |
231 | #ifdef CONFIG_SPI_FLASH_BAR | 257 | #ifdef CONFIG_SPI_FLASH_BAR |
232 | ret = spi_flash_bank(flash, offset); | 258 | ret = spi_flash_bank(flash, offset); |
233 | if (ret < 0) | 259 | if (ret < 0) |
234 | return ret; | 260 | return ret; |
235 | #endif | 261 | #endif |
236 | spi_flash_addr(offset, cmd); | 262 | spi_flash_addr(offset, cmd); |
237 | 263 | ||
238 | debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], | 264 | debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], |
239 | cmd[2], cmd[3], offset); | 265 | cmd[2], cmd[3], offset); |
240 | 266 | ||
241 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); | 267 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); |
242 | if (ret < 0) { | 268 | if (ret < 0) { |
243 | debug("SF: erase failed\n"); | 269 | debug("SF: erase failed\n"); |
244 | break; | 270 | break; |
245 | } | 271 | } |
246 | 272 | ||
247 | offset += erase_size; | 273 | offset += erase_size; |
248 | len -= erase_size; | 274 | len -= erase_size; |
249 | } | 275 | } |
250 | 276 | ||
251 | return ret; | 277 | return ret; |
252 | } | 278 | } |
253 | 279 | ||
254 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | 280 | int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, |
255 | size_t len, const void *buf) | 281 | size_t len, const void *buf) |
256 | { | 282 | { |
257 | unsigned long byte_addr, page_size; | 283 | unsigned long byte_addr, page_size; |
258 | size_t chunk_len, actual; | 284 | size_t chunk_len, actual; |
259 | u8 cmd[SPI_FLASH_CMD_LEN]; | 285 | u8 cmd[SPI_FLASH_CMD_LEN]; |
260 | int ret = -1; | 286 | int ret = -1; |
261 | 287 | ||
262 | page_size = flash->page_size; | 288 | page_size = flash->page_size; |
263 | 289 | ||
264 | cmd[0] = flash->write_cmd; | 290 | cmd[0] = flash->write_cmd; |
265 | for (actual = 0; actual < len; actual += chunk_len) { | 291 | for (actual = 0; actual < len; actual += chunk_len) { |
266 | #ifdef CONFIG_SPI_FLASH_BAR | 292 | #ifdef CONFIG_SPI_FLASH_BAR |
267 | ret = spi_flash_bank(flash, offset); | 293 | ret = spi_flash_bank(flash, offset); |
268 | if (ret < 0) | 294 | if (ret < 0) |
269 | return ret; | 295 | return ret; |
270 | #endif | 296 | #endif |
271 | byte_addr = offset % page_size; | 297 | byte_addr = offset % page_size; |
272 | chunk_len = min(len - actual, page_size - byte_addr); | 298 | chunk_len = min(len - actual, page_size - byte_addr); |
273 | 299 | ||
274 | if (flash->spi->max_write_size) | 300 | if (flash->spi->max_write_size) |
275 | chunk_len = min(chunk_len, flash->spi->max_write_size); | 301 | chunk_len = min(chunk_len, flash->spi->max_write_size); |
276 | 302 | ||
277 | spi_flash_addr(offset, cmd); | 303 | spi_flash_addr(offset, cmd); |
278 | 304 | ||
279 | debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", | 305 | debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", |
280 | buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); | 306 | buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); |
281 | 307 | ||
282 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), | 308 | ret = spi_flash_write_common(flash, cmd, sizeof(cmd), |
283 | buf + actual, chunk_len); | 309 | buf + actual, chunk_len); |
284 | if (ret < 0) { | 310 | if (ret < 0) { |
285 | debug("SF: write failed\n"); | 311 | debug("SF: write failed\n"); |
286 | break; | 312 | break; |
287 | } | 313 | } |
288 | 314 | ||
289 | offset += chunk_len; | 315 | offset += chunk_len; |
290 | } | 316 | } |
291 | 317 | ||
292 | return ret; | 318 | return ret; |
293 | } | 319 | } |
294 | 320 | ||
295 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | 321 | int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, |
296 | size_t cmd_len, void *data, size_t data_len) | 322 | size_t cmd_len, void *data, size_t data_len) |
297 | { | 323 | { |
298 | struct spi_slave *spi = flash->spi; | 324 | struct spi_slave *spi = flash->spi; |
299 | int ret; | 325 | int ret; |
300 | 326 | ||
301 | ret = spi_claim_bus(flash->spi); | 327 | ret = spi_claim_bus(flash->spi); |
302 | if (ret) { | 328 | if (ret) { |
303 | debug("SF: unable to claim SPI bus\n"); | 329 | debug("SF: unable to claim SPI bus\n"); |
304 | return ret; | 330 | return ret; |
305 | } | 331 | } |
306 | 332 | ||
307 | ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); | 333 | ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); |
308 | if (ret < 0) { | 334 | if (ret < 0) { |
309 | debug("SF: read cmd failed\n"); | 335 | debug("SF: read cmd failed\n"); |
310 | return ret; | 336 | return ret; |
311 | } | 337 | } |
312 | 338 | ||
313 | spi_release_bus(spi); | 339 | spi_release_bus(spi); |
314 | 340 | ||
315 | return ret; | 341 | return ret; |
316 | } | 342 | } |
317 | 343 | ||
318 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | 344 | int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, |
319 | size_t len, void *data) | 345 | size_t len, void *data) |
320 | { | 346 | { |
321 | u8 *cmd, cmdsz, bank_sel = 0; | 347 | u8 *cmd, cmdsz, bank_sel = 0; |
322 | u32 remain_len, read_len; | 348 | u32 remain_len, read_len; |
323 | int ret = -1; | 349 | int ret = -1; |
324 | 350 | ||
325 | /* Handle memory-mapped SPI */ | 351 | /* Handle memory-mapped SPI */ |
326 | if (flash->memory_map) { | 352 | if (flash->memory_map) { |
327 | ret = spi_claim_bus(flash->spi); | 353 | ret = spi_claim_bus(flash->spi); |
328 | if (ret) { | 354 | if (ret) { |
329 | debug("SF: unable to claim SPI bus\n"); | 355 | debug("SF: unable to claim SPI bus\n"); |
330 | return ret; | 356 | return ret; |
331 | } | 357 | } |
332 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); | 358 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); |
333 | memcpy(data, flash->memory_map + offset, len); | 359 | memcpy(data, flash->memory_map + offset, len); |
334 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); | 360 | spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); |
335 | spi_release_bus(flash->spi); | 361 | spi_release_bus(flash->spi); |
336 | return 0; | 362 | return 0; |
337 | } | 363 | } |
338 | 364 | ||
339 | cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; | 365 | cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; |
340 | cmd = malloc(cmdsz); | 366 | cmd = malloc(cmdsz); |
341 | memset(cmd, 0, cmdsz); | 367 | memset(cmd, 0, cmdsz); |
342 | 368 | ||
343 | cmd[0] = flash->read_cmd; | 369 | cmd[0] = flash->read_cmd; |
344 | while (len) { | 370 | while (len) { |
345 | #ifdef CONFIG_SPI_FLASH_BAR | 371 | #ifdef CONFIG_SPI_FLASH_BAR |
346 | bank_sel = offset / SPI_FLASH_16MB_BOUN; | 372 | bank_sel = offset / SPI_FLASH_16MB_BOUN; |
347 | 373 | ||
348 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); | 374 | ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); |
349 | if (ret) { | 375 | if (ret) { |
350 | debug("SF: fail to set bank%d\n", bank_sel); | 376 | debug("SF: fail to set bank%d\n", bank_sel); |
351 | return ret; | 377 | return ret; |
352 | } | 378 | } |
353 | #endif | 379 | #endif |
354 | remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; | 380 | remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; |
355 | if (len < remain_len) | 381 | if (len < remain_len) |
356 | read_len = len; | 382 | read_len = len; |
357 | else | 383 | else |
358 | read_len = remain_len; | 384 | read_len = remain_len; |
359 | 385 | ||
360 | spi_flash_addr(offset, cmd); | 386 | spi_flash_addr(offset, cmd); |
361 | 387 | ||
362 | ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); | 388 | ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); |
363 | if (ret < 0) { | 389 | if (ret < 0) { |
364 | debug("SF: read failed\n"); | 390 | debug("SF: read failed\n"); |
365 | break; | 391 | break; |
366 | } | 392 | } |
367 | 393 | ||
368 | offset += read_len; | 394 | offset += read_len; |
369 | len -= read_len; | 395 | len -= read_len; |
370 | data += read_len; | 396 | data += read_len; |
371 | } | 397 | } |
372 | 398 | ||
373 | return ret; | 399 | return ret; |
374 | } | 400 | } |
375 | 401 | ||
376 | #ifdef CONFIG_SPI_FLASH_SST | 402 | #ifdef CONFIG_SPI_FLASH_SST |
377 | static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) | 403 | static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) |
378 | { | 404 | { |
379 | int ret; | 405 | int ret; |
380 | u8 cmd[4] = { | 406 | u8 cmd[4] = { |
381 | CMD_SST_BP, | 407 | CMD_SST_BP, |
382 | offset >> 16, | 408 | offset >> 16, |
383 | offset >> 8, | 409 | offset >> 8, |
384 | offset, | 410 | offset, |
385 | }; | 411 | }; |
386 | 412 | ||
387 | debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", | 413 | debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", |
388 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); | 414 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); |
389 | 415 | ||
390 | ret = spi_flash_cmd_write_enable(flash); | 416 | ret = spi_flash_cmd_write_enable(flash); |
391 | if (ret) | 417 | if (ret) |
392 | return ret; | 418 | return ret; |
393 | 419 | ||
394 | ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); | 420 | ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); |
395 | if (ret) | 421 | if (ret) |
396 | return ret; | 422 | return ret; |
397 | 423 | ||
398 | return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); | 424 | return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); |
399 | } | 425 | } |
400 | 426 | ||
401 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | 427 | int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, |
402 | const void *buf) | 428 | const void *buf) |
403 | { | 429 | { |
404 | size_t actual, cmd_len; | 430 | size_t actual, cmd_len; |
405 | int ret; | 431 | int ret; |
406 | u8 cmd[4]; | 432 | u8 cmd[4]; |
407 | 433 | ||
408 | ret = spi_claim_bus(flash->spi); | 434 | ret = spi_claim_bus(flash->spi); |
409 | if (ret) { | 435 | if (ret) { |
410 | debug("SF: Unable to claim SPI bus\n"); | 436 | debug("SF: Unable to claim SPI bus\n"); |
411 | return ret; | 437 | return ret; |
412 | } | 438 | } |
413 | 439 | ||
414 | /* If the data is not word aligned, write out leading single byte */ | 440 | /* If the data is not word aligned, write out leading single byte */ |
415 | actual = offset % 2; | 441 | actual = offset % 2; |
416 | if (actual) { | 442 | if (actual) { |
417 | ret = sst_byte_write(flash, offset, buf); | 443 | ret = sst_byte_write(flash, offset, buf); |
418 | if (ret) | 444 | if (ret) |
419 | goto done; | 445 | goto done; |
420 | } | 446 | } |
421 | offset += actual; | 447 | offset += actual; |
422 | 448 | ||
423 | ret = spi_flash_cmd_write_enable(flash); | 449 | ret = spi_flash_cmd_write_enable(flash); |
424 | if (ret) | 450 | if (ret) |
425 | goto done; | 451 | goto done; |
426 | 452 | ||
427 | cmd_len = 4; | 453 | cmd_len = 4; |
428 | cmd[0] = CMD_SST_AAI_WP; | 454 | cmd[0] = CMD_SST_AAI_WP; |
429 | cmd[1] = offset >> 16; | 455 | cmd[1] = offset >> 16; |
430 | cmd[2] = offset >> 8; | 456 | cmd[2] = offset >> 8; |
431 | cmd[3] = offset; | 457 | cmd[3] = offset; |
432 | 458 | ||
433 | for (; actual < len - 1; actual += 2) { | 459 | for (; actual < len - 1; actual += 2) { |
434 | debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", | 460 | debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", |
435 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, | 461 | spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, |
436 | cmd[0], offset); | 462 | cmd[0], offset); |
437 | 463 | ||
438 | ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, | 464 | ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, |
439 | buf + actual, 2); | 465 | buf + actual, 2); |
440 | if (ret) { | 466 | if (ret) { |
441 | debug("SF: sst word program failed\n"); | 467 | debug("SF: sst word program failed\n"); |
442 | break; | 468 | break; |
443 | } | 469 | } |
444 | 470 | ||
445 | ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); | 471 | ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); |
446 | if (ret) | 472 | if (ret) |
447 | break; | 473 | break; |
448 | 474 | ||
449 | cmd_len = 1; | 475 | cmd_len = 1; |
450 | offset += 2; | 476 | offset += 2; |
451 | } | 477 | } |
452 | 478 | ||
453 | if (!ret) | 479 | if (!ret) |
454 | ret = spi_flash_cmd_write_disable(flash); | 480 | ret = spi_flash_cmd_write_disable(flash); |
455 | 481 | ||
456 | /* If there is a single trailing byte, write it out */ | 482 | /* If there is a single trailing byte, write it out */ |
457 | if (!ret && actual != len) | 483 | if (!ret && actual != len) |
458 | ret = sst_byte_write(flash, offset, buf + actual); | 484 | ret = sst_byte_write(flash, offset, buf + actual); |
459 | 485 | ||
460 | done: | 486 | done: |
461 | debug("SF: sst: program %s %zu bytes @ 0x%zx\n", | 487 | debug("SF: sst: program %s %zu bytes @ 0x%zx\n", |
462 | ret ? "failure" : "success", len, offset - actual); | 488 | ret ? "failure" : "success", len, offset - actual); |
463 | 489 | ||
464 | spi_release_bus(flash->spi); | 490 | spi_release_bus(flash->spi); |
465 | return ret; | 491 | return ret; |
466 | } | 492 | } |
467 | #endif | 493 | #endif |
468 | 494 |
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 | /* Read commands array */ | 22 | /* Read commands array */ |
23 | static u8 spi_read_cmds_array[] = { | 23 | static u8 spi_read_cmds_array[] = { |
24 | CMD_READ_ARRAY_SLOW, | 24 | CMD_READ_ARRAY_SLOW, |
25 | CMD_READ_DUAL_OUTPUT_FAST, | 25 | CMD_READ_DUAL_OUTPUT_FAST, |
26 | CMD_READ_DUAL_IO_FAST, | 26 | CMD_READ_DUAL_IO_FAST, |
27 | CMD_READ_QUAD_OUTPUT_FAST, | 27 | CMD_READ_QUAD_OUTPUT_FAST, |
28 | CMD_READ_QUAD_IO_FAST, | 28 | CMD_READ_QUAD_IO_FAST, |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) | 31 | static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) |
32 | { | 32 | { |
33 | switch (idcode0) { | 33 | switch (idcode0) { |
34 | #ifdef CONFIG_SPI_FLASH_MACRONIX | ||
35 | case SPI_FLASH_CFI_MFR_MACRONIX: | ||
36 | return spi_flash_set_qeb_mxic(flash); | ||
37 | #endif | ||
34 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) | 38 | #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) |
35 | case SPI_FLASH_CFI_MFR_SPANSION: | 39 | case SPI_FLASH_CFI_MFR_SPANSION: |
36 | case SPI_FLASH_CFI_MFR_WINBOND: | 40 | case SPI_FLASH_CFI_MFR_WINBOND: |
37 | return spi_flash_set_qeb_winspan(flash); | 41 | return spi_flash_set_qeb_winspan(flash); |
38 | #endif | 42 | #endif |
39 | #ifdef CONFIG_SPI_FLASH_STMICRO | 43 | #ifdef CONFIG_SPI_FLASH_STMICRO |
40 | case SPI_FLASH_CFI_MFR_STMICRO: | 44 | case SPI_FLASH_CFI_MFR_STMICRO: |
41 | debug("SF: QEB is volatile for %02x flash\n", idcode0); | 45 | debug("SF: QEB is volatile for %02x flash\n", idcode0); |
42 | return 0; | 46 | return 0; |
43 | #endif | 47 | #endif |
44 | default: | 48 | default: |
45 | printf("SF: Need set QEB func for %02x flash\n", idcode0); | 49 | printf("SF: Need set QEB func for %02x flash\n", idcode0); |
46 | return -1; | 50 | return -1; |
47 | } | 51 | } |
48 | } | 52 | } |
49 | 53 | ||
50 | static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, | 54 | static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, |
51 | u8 *idcode) | 55 | u8 *idcode) |
52 | { | 56 | { |
53 | const struct spi_flash_params *params; | 57 | const struct spi_flash_params *params; |
54 | struct spi_flash *flash; | 58 | struct spi_flash *flash; |
55 | u8 cmd; | 59 | u8 cmd; |
56 | u16 jedec = idcode[1] << 8 | idcode[2]; | 60 | u16 jedec = idcode[1] << 8 | idcode[2]; |
57 | u16 ext_jedec = idcode[3] << 8 | idcode[4]; | 61 | u16 ext_jedec = idcode[3] << 8 | idcode[4]; |
58 | 62 | ||
59 | params = spi_flash_params_table; | 63 | params = spi_flash_params_table; |
60 | for (; params->name != NULL; params++) { | 64 | for (; params->name != NULL; params++) { |
61 | if ((params->jedec >> 16) == idcode[0]) { | 65 | if ((params->jedec >> 16) == idcode[0]) { |
62 | if ((params->jedec & 0xFFFF) == jedec) { | 66 | if ((params->jedec & 0xFFFF) == jedec) { |
63 | if (params->ext_jedec == 0) | 67 | if (params->ext_jedec == 0) |
64 | break; | 68 | break; |
65 | else if (params->ext_jedec == ext_jedec) | 69 | else if (params->ext_jedec == ext_jedec) |
66 | break; | 70 | break; |
67 | } | 71 | } |
68 | } | 72 | } |
69 | } | 73 | } |
70 | 74 | ||
71 | if (!params->name) { | 75 | if (!params->name) { |
72 | printf("SF: Unsupported flash IDs: "); | 76 | printf("SF: Unsupported flash IDs: "); |
73 | printf("manuf %02x, jedec %04x, ext_jedec %04x\n", | 77 | printf("manuf %02x, jedec %04x, ext_jedec %04x\n", |
74 | idcode[0], jedec, ext_jedec); | 78 | idcode[0], jedec, ext_jedec); |
75 | return NULL; | 79 | return NULL; |
76 | } | 80 | } |
77 | 81 | ||
78 | flash = malloc(sizeof(*flash)); | 82 | flash = malloc(sizeof(*flash)); |
79 | if (!flash) { | 83 | if (!flash) { |
80 | debug("SF: Failed to allocate spi_flash\n"); | 84 | debug("SF: Failed to allocate spi_flash\n"); |
81 | return NULL; | 85 | return NULL; |
82 | } | 86 | } |
83 | memset(flash, '\0', sizeof(*flash)); | 87 | memset(flash, '\0', sizeof(*flash)); |
84 | 88 | ||
85 | /* Assign spi data */ | 89 | /* Assign spi data */ |
86 | flash->spi = spi; | 90 | flash->spi = spi; |
87 | flash->name = params->name; | 91 | flash->name = params->name; |
88 | flash->memory_map = spi->memory_map; | 92 | flash->memory_map = spi->memory_map; |
89 | 93 | ||
90 | /* Assign spi_flash ops */ | 94 | /* Assign spi_flash ops */ |
91 | flash->write = spi_flash_cmd_write_ops; | 95 | flash->write = spi_flash_cmd_write_ops; |
92 | #ifdef CONFIG_SPI_FLASH_SST | 96 | #ifdef CONFIG_SPI_FLASH_SST |
93 | if (params->flags & SST_WP) | 97 | if (params->flags & SST_WP) |
94 | flash->write = sst_write_wp; | 98 | flash->write = sst_write_wp; |
95 | #endif | 99 | #endif |
96 | flash->erase = spi_flash_cmd_erase_ops; | 100 | flash->erase = spi_flash_cmd_erase_ops; |
97 | flash->read = spi_flash_cmd_read_ops; | 101 | flash->read = spi_flash_cmd_read_ops; |
98 | 102 | ||
99 | /* Compute the flash size */ | 103 | /* Compute the flash size */ |
100 | flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; | 104 | flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; |
101 | flash->sector_size = params->sector_size; | 105 | flash->sector_size = params->sector_size; |
102 | flash->size = flash->sector_size * params->nr_sectors; | 106 | flash->size = flash->sector_size * params->nr_sectors; |
103 | 107 | ||
104 | /* Compute erase sector and command */ | 108 | /* Compute erase sector and command */ |
105 | if (params->flags & SECT_4K) { | 109 | if (params->flags & SECT_4K) { |
106 | flash->erase_cmd = CMD_ERASE_4K; | 110 | flash->erase_cmd = CMD_ERASE_4K; |
107 | flash->erase_size = 4096; | 111 | flash->erase_size = 4096; |
108 | } else if (params->flags & SECT_32K) { | 112 | } else if (params->flags & SECT_32K) { |
109 | flash->erase_cmd = CMD_ERASE_32K; | 113 | flash->erase_cmd = CMD_ERASE_32K; |
110 | flash->erase_size = 32768; | 114 | flash->erase_size = 32768; |
111 | } else { | 115 | } else { |
112 | flash->erase_cmd = CMD_ERASE_64K; | 116 | flash->erase_cmd = CMD_ERASE_64K; |
113 | flash->erase_size = flash->sector_size; | 117 | flash->erase_size = flash->sector_size; |
114 | } | 118 | } |
115 | 119 | ||
116 | /* Look for the fastest read cmd */ | 120 | /* Look for the fastest read cmd */ |
117 | cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); | 121 | cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); |
118 | if (cmd) { | 122 | if (cmd) { |
119 | cmd = spi_read_cmds_array[cmd - 1]; | 123 | cmd = spi_read_cmds_array[cmd - 1]; |
120 | flash->read_cmd = cmd; | 124 | flash->read_cmd = cmd; |
121 | } else { | 125 | } else { |
122 | /* Go for for default supported read cmd */ | 126 | /* Go for for default supported read cmd */ |
123 | flash->read_cmd = CMD_READ_ARRAY_FAST; | 127 | flash->read_cmd = CMD_READ_ARRAY_FAST; |
124 | } | 128 | } |
125 | 129 | ||
126 | /* Not require to look for fastest only two write cmds yet */ | 130 | /* Not require to look for fastest only two write cmds yet */ |
127 | if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) | 131 | if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) |
128 | flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; | 132 | flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; |
129 | else | 133 | else |
130 | /* Go for default supported write cmd */ | 134 | /* Go for default supported write cmd */ |
131 | flash->write_cmd = CMD_PAGE_PROGRAM; | 135 | flash->write_cmd = CMD_PAGE_PROGRAM; |
132 | 136 | ||
133 | /* Set the quad enable bit - only for quad commands */ | 137 | /* Set the quad enable bit - only for quad commands */ |
134 | if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || | 138 | if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || |
135 | (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || | 139 | (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || |
136 | (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { | 140 | (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { |
137 | if (spi_flash_set_qeb(flash, idcode[0])) { | 141 | if (spi_flash_set_qeb(flash, idcode[0])) { |
138 | debug("SF: Fail to set QEB for %02x\n", idcode[0]); | 142 | debug("SF: Fail to set QEB for %02x\n", idcode[0]); |
139 | return NULL; | 143 | return NULL; |
140 | } | 144 | } |
141 | } | 145 | } |
142 | 146 | ||
143 | /* Read dummy_byte: dummy byte is determined based on the | 147 | /* Read dummy_byte: dummy byte is determined based on the |
144 | * dummy cycles of a particular command. | 148 | * dummy cycles of a particular command. |
145 | * Fast commands - dummy_byte = dummy_cycles/8 | 149 | * Fast commands - dummy_byte = dummy_cycles/8 |
146 | * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 | 150 | * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 |
147 | * For I/O commands except cmd[0] everything goes on no.of lines | 151 | * For I/O commands except cmd[0] everything goes on no.of lines |
148 | * based on particular command but incase of fast commands except | 152 | * based on particular command but incase of fast commands except |
149 | * data all go on single line irrespective of command. | 153 | * data all go on single line irrespective of command. |
150 | */ | 154 | */ |
151 | switch (flash->read_cmd) { | 155 | switch (flash->read_cmd) { |
152 | case CMD_READ_QUAD_IO_FAST: | 156 | case CMD_READ_QUAD_IO_FAST: |
153 | flash->dummy_byte = 2; | 157 | flash->dummy_byte = 2; |
154 | break; | 158 | break; |
155 | case CMD_READ_ARRAY_SLOW: | 159 | case CMD_READ_ARRAY_SLOW: |
156 | flash->dummy_byte = 0; | 160 | flash->dummy_byte = 0; |
157 | break; | 161 | break; |
158 | default: | 162 | default: |
159 | flash->dummy_byte = 1; | 163 | flash->dummy_byte = 1; |
160 | } | 164 | } |
161 | 165 | ||
162 | /* Poll cmd seclection */ | 166 | /* Poll cmd seclection */ |
163 | flash->poll_cmd = CMD_READ_STATUS; | 167 | flash->poll_cmd = CMD_READ_STATUS; |
164 | #ifdef CONFIG_SPI_FLASH_STMICRO | 168 | #ifdef CONFIG_SPI_FLASH_STMICRO |
165 | if (params->flags & E_FSR) | 169 | if (params->flags & E_FSR) |
166 | flash->poll_cmd = CMD_FLAG_STATUS; | 170 | flash->poll_cmd = CMD_FLAG_STATUS; |
167 | #endif | 171 | #endif |
168 | 172 | ||
169 | /* Configure the BAR - discover bank cmds and read current bank */ | 173 | /* Configure the BAR - discover bank cmds and read current bank */ |
170 | #ifdef CONFIG_SPI_FLASH_BAR | 174 | #ifdef CONFIG_SPI_FLASH_BAR |
171 | u8 curr_bank = 0; | 175 | u8 curr_bank = 0; |
172 | if (flash->size > SPI_FLASH_16MB_BOUN) { | 176 | if (flash->size > SPI_FLASH_16MB_BOUN) { |
173 | flash->bank_read_cmd = (idcode[0] == 0x01) ? | 177 | flash->bank_read_cmd = (idcode[0] == 0x01) ? |
174 | CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; | 178 | CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; |
175 | flash->bank_write_cmd = (idcode[0] == 0x01) ? | 179 | flash->bank_write_cmd = (idcode[0] == 0x01) ? |
176 | CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; | 180 | CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; |
177 | 181 | ||
178 | if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, | 182 | if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, |
179 | &curr_bank, 1)) { | 183 | &curr_bank, 1)) { |
180 | debug("SF: fail to read bank addr register\n"); | 184 | debug("SF: fail to read bank addr register\n"); |
181 | return NULL; | 185 | return NULL; |
182 | } | 186 | } |
183 | flash->bank_curr = curr_bank; | 187 | flash->bank_curr = curr_bank; |
184 | } else { | 188 | } else { |
185 | flash->bank_curr = curr_bank; | 189 | flash->bank_curr = curr_bank; |
186 | } | 190 | } |
187 | #endif | 191 | #endif |
188 | 192 | ||
189 | /* Flash powers up read-only, so clear BP# bits */ | 193 | /* Flash powers up read-only, so clear BP# bits */ |
190 | #if defined(CONFIG_SPI_FLASH_ATMEL) || \ | 194 | #if defined(CONFIG_SPI_FLASH_ATMEL) || \ |
191 | defined(CONFIG_SPI_FLASH_MACRONIX) || \ | 195 | defined(CONFIG_SPI_FLASH_MACRONIX) || \ |
192 | defined(CONFIG_SPI_FLASH_SST) | 196 | defined(CONFIG_SPI_FLASH_SST) |
193 | spi_flash_cmd_write_status(flash, 0); | 197 | spi_flash_cmd_write_status(flash, 0); |
194 | #endif | 198 | #endif |
195 | 199 | ||
196 | return flash; | 200 | return flash; |
197 | } | 201 | } |
198 | 202 | ||
199 | #ifdef CONFIG_OF_CONTROL | 203 | #ifdef CONFIG_OF_CONTROL |
200 | int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) | 204 | int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) |
201 | { | 205 | { |
202 | fdt_addr_t addr; | 206 | fdt_addr_t addr; |
203 | fdt_size_t size; | 207 | fdt_size_t size; |
204 | int node; | 208 | int node; |
205 | 209 | ||
206 | /* If there is no node, do nothing */ | 210 | /* If there is no node, do nothing */ |
207 | node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); | 211 | node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); |
208 | if (node < 0) | 212 | if (node < 0) |
209 | return 0; | 213 | return 0; |
210 | 214 | ||
211 | addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); | 215 | addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); |
212 | if (addr == FDT_ADDR_T_NONE) { | 216 | if (addr == FDT_ADDR_T_NONE) { |
213 | debug("%s: Cannot decode address\n", __func__); | 217 | debug("%s: Cannot decode address\n", __func__); |
214 | return 0; | 218 | return 0; |
215 | } | 219 | } |
216 | 220 | ||
217 | if (flash->size != size) { | 221 | if (flash->size != size) { |
218 | debug("%s: Memory map must cover entire device\n", __func__); | 222 | debug("%s: Memory map must cover entire device\n", __func__); |
219 | return -1; | 223 | return -1; |
220 | } | 224 | } |
221 | flash->memory_map = map_sysmem(addr, size); | 225 | flash->memory_map = map_sysmem(addr, size); |
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
225 | #endif /* CONFIG_OF_CONTROL */ | 229 | #endif /* CONFIG_OF_CONTROL */ |
226 | 230 | ||
227 | static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi) | 231 | static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi) |
228 | { | 232 | { |
229 | struct spi_flash *flash = NULL; | 233 | struct spi_flash *flash = NULL; |
230 | u8 idcode[5]; | 234 | u8 idcode[5]; |
231 | int ret; | 235 | int ret; |
232 | 236 | ||
233 | /* Setup spi_slave */ | 237 | /* Setup spi_slave */ |
234 | if (!spi) { | 238 | if (!spi) { |
235 | printf("SF: Failed to set up slave\n"); | 239 | printf("SF: Failed to set up slave\n"); |
236 | return NULL; | 240 | return NULL; |
237 | } | 241 | } |
238 | 242 | ||
239 | /* Claim spi bus */ | 243 | /* Claim spi bus */ |
240 | ret = spi_claim_bus(spi); | 244 | ret = spi_claim_bus(spi); |
241 | if (ret) { | 245 | if (ret) { |
242 | debug("SF: Failed to claim SPI bus: %d\n", ret); | 246 | debug("SF: Failed to claim SPI bus: %d\n", ret); |
243 | goto err_claim_bus; | 247 | goto err_claim_bus; |
244 | } | 248 | } |
245 | 249 | ||
246 | /* Read the ID codes */ | 250 | /* Read the ID codes */ |
247 | ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); | 251 | ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); |
248 | if (ret) { | 252 | if (ret) { |
249 | printf("SF: Failed to get idcodes\n"); | 253 | printf("SF: Failed to get idcodes\n"); |
250 | goto err_read_id; | 254 | goto err_read_id; |
251 | } | 255 | } |
252 | 256 | ||
253 | #ifdef DEBUG | 257 | #ifdef DEBUG |
254 | printf("SF: Got idcodes\n"); | 258 | printf("SF: Got idcodes\n"); |
255 | print_buffer(0, idcode, 1, sizeof(idcode), 0); | 259 | print_buffer(0, idcode, 1, sizeof(idcode), 0); |
256 | #endif | 260 | #endif |
257 | 261 | ||
258 | /* Validate params from spi_flash_params table */ | 262 | /* Validate params from spi_flash_params table */ |
259 | flash = spi_flash_validate_params(spi, idcode); | 263 | flash = spi_flash_validate_params(spi, idcode); |
260 | if (!flash) | 264 | if (!flash) |
261 | goto err_read_id; | 265 | goto err_read_id; |
262 | 266 | ||
263 | #ifdef CONFIG_OF_CONTROL | 267 | #ifdef CONFIG_OF_CONTROL |
264 | if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { | 268 | if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { |
265 | debug("SF: FDT decode error\n"); | 269 | debug("SF: FDT decode error\n"); |
266 | goto err_read_id; | 270 | goto err_read_id; |
267 | } | 271 | } |
268 | #endif | 272 | #endif |
269 | #ifndef CONFIG_SPL_BUILD | 273 | #ifndef CONFIG_SPL_BUILD |
270 | printf("SF: Detected %s with page size ", flash->name); | 274 | printf("SF: Detected %s with page size ", flash->name); |
271 | print_size(flash->page_size, ", erase size "); | 275 | print_size(flash->page_size, ", erase size "); |
272 | print_size(flash->erase_size, ", total "); | 276 | print_size(flash->erase_size, ", total "); |
273 | print_size(flash->size, ""); | 277 | print_size(flash->size, ""); |
274 | if (flash->memory_map) | 278 | if (flash->memory_map) |
275 | printf(", mapped at %p", flash->memory_map); | 279 | printf(", mapped at %p", flash->memory_map); |
276 | puts("\n"); | 280 | puts("\n"); |
277 | #endif | 281 | #endif |
278 | #ifndef CONFIG_SPI_FLASH_BAR | 282 | #ifndef CONFIG_SPI_FLASH_BAR |
279 | if (flash->size > SPI_FLASH_16MB_BOUN) { | 283 | if (flash->size > SPI_FLASH_16MB_BOUN) { |
280 | puts("SF: Warning - Only lower 16MiB accessible,"); | 284 | puts("SF: Warning - Only lower 16MiB accessible,"); |
281 | puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); | 285 | puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); |
282 | } | 286 | } |
283 | #endif | 287 | #endif |
284 | 288 | ||
285 | /* Release spi bus */ | 289 | /* Release spi bus */ |
286 | spi_release_bus(spi); | 290 | spi_release_bus(spi); |
287 | 291 | ||
288 | return flash; | 292 | return flash; |
289 | 293 | ||
290 | err_read_id: | 294 | err_read_id: |
291 | spi_release_bus(spi); | 295 | spi_release_bus(spi); |
292 | err_claim_bus: | 296 | err_claim_bus: |
293 | spi_free_slave(spi); | 297 | spi_free_slave(spi); |
294 | return NULL; | 298 | return NULL; |
295 | } | 299 | } |
296 | 300 | ||
297 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | 301 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, |
298 | unsigned int max_hz, unsigned int spi_mode) | 302 | unsigned int max_hz, unsigned int spi_mode) |
299 | { | 303 | { |
300 | struct spi_slave *spi; | 304 | struct spi_slave *spi; |
301 | 305 | ||
302 | spi = spi_setup_slave(bus, cs, max_hz, spi_mode); | 306 | spi = spi_setup_slave(bus, cs, max_hz, spi_mode); |
303 | return spi_flash_probe_slave(spi); | 307 | return spi_flash_probe_slave(spi); |
304 | } | 308 | } |
305 | 309 | ||
306 | #ifdef CONFIG_OF_SPI_FLASH | 310 | #ifdef CONFIG_OF_SPI_FLASH |
307 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, | 311 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, |
308 | int spi_node) | 312 | int spi_node) |
309 | { | 313 | { |
310 | struct spi_slave *spi; | 314 | struct spi_slave *spi; |
311 | 315 | ||
312 | spi = spi_setup_slave_fdt(blob, slave_node, spi_node); | 316 | spi = spi_setup_slave_fdt(blob, slave_node, spi_node); |
313 | return spi_flash_probe_slave(spi); | 317 | return spi_flash_probe_slave(spi); |
314 | } | 318 | } |
315 | #endif | 319 | #endif |
316 | 320 | ||
317 | void spi_flash_free(struct spi_flash *flash) | 321 | void spi_flash_free(struct spi_flash *flash) |
318 | { | 322 | { |
319 | spi_free_slave(flash->spi); | 323 | spi_free_slave(flash->spi); |
320 | free(flash); | 324 | free(flash); |
321 | } | 325 | } |
322 | 326 |