aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@bootlin.com>2018-04-26 12:18:19 -0400
committerMark Brown <broonie@kernel.org>2018-05-10 22:33:51 -0400
commit4120f8d158ef904fb305b27e4a4524649faf3096 (patch)
tree0ec931c1e37ca8a62928142a5a1ff0d88d08b18d /drivers/mtd
parentb95cb394ab591d1d6dcc7281b415fde0a3de2ae1 (diff)
mtd: spi-nor: Use the spi_mem_xx() API
The spi_mem_xxx() API has been introduced to replace the spi_flash_read() one. Make use of it so we can get rid of spi_flash_read(). Note that using spi_mem_xx() also simplifies the code because this API takes care of using the regular spi_sync() interface when the optimized ->mem_ops interface is not implemented by the controller. Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> Reviewed-by: Frieder Schrempf <frieder.schrempf@exceet.de> Tested-by: Frieder Schrempf <frieder.schrempf@exceet.de> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/devices/Kconfig1
-rw-r--r--drivers/mtd/devices/m25p80.c236
2 files changed, 80 insertions, 157 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 6def5445e03e..57b02c4b3f63 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -81,6 +81,7 @@ config MTD_DATAFLASH_OTP
81config MTD_M25P80 81config MTD_M25P80
82 tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)" 82 tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
83 depends on SPI_MASTER && MTD_SPI_NOR 83 depends on SPI_MASTER && MTD_SPI_NOR
84 select SPI_MEM
84 help 85 help
85 This enables access to most modern SPI flash chips, used for 86 This enables access to most modern SPI flash chips, used for
86 program and data storage. Series supported include Atmel AT26DF, 87 program and data storage. Series supported include Atmel AT26DF,
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index a4e18f6aaa33..3dc022d3b53e 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -24,12 +24,13 @@
24#include <linux/mtd/partitions.h> 24#include <linux/mtd/partitions.h>
25 25
26#include <linux/spi/spi.h> 26#include <linux/spi/spi.h>
27#include <linux/spi/spi-mem.h>
27#include <linux/spi/flash.h> 28#include <linux/spi/flash.h>
28#include <linux/mtd/spi-nor.h> 29#include <linux/mtd/spi-nor.h>
29 30
30#define MAX_CMD_SIZE 6 31#define MAX_CMD_SIZE 6
31struct m25p { 32struct m25p {
32 struct spi_device *spi; 33 struct spi_mem *spimem;
33 struct spi_nor spi_nor; 34 struct spi_nor spi_nor;
34 u8 command[MAX_CMD_SIZE]; 35 u8 command[MAX_CMD_SIZE];
35}; 36};
@@ -37,97 +38,68 @@ struct m25p {
37static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) 38static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
38{ 39{
39 struct m25p *flash = nor->priv; 40 struct m25p *flash = nor->priv;
40 struct spi_device *spi = flash->spi; 41 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1),
42 SPI_MEM_OP_NO_ADDR,
43 SPI_MEM_OP_NO_DUMMY,
44 SPI_MEM_OP_DATA_IN(len, val, 1));
41 int ret; 45 int ret;
42 46
43 ret = spi_write_then_read(spi, &code, 1, val, len); 47 ret = spi_mem_exec_op(flash->spimem, &op);
44 if (ret < 0) 48 if (ret < 0)
45 dev_err(&spi->dev, "error %d reading %x\n", ret, code); 49 dev_err(&flash->spimem->spi->dev, "error %d reading %x\n", ret,
50 code);
46 51
47 return ret; 52 return ret;
48} 53}
49 54
50static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, u8 *cmd)
51{
52 /* opcode is in cmd[0] */
53 cmd[1] = addr >> (nor->addr_width * 8 - 8);
54 cmd[2] = addr >> (nor->addr_width * 8 - 16);
55 cmd[3] = addr >> (nor->addr_width * 8 - 24);
56 cmd[4] = addr >> (nor->addr_width * 8 - 32);
57}
58
59static int m25p_cmdsz(struct spi_nor *nor)
60{
61 return 1 + nor->addr_width;
62}
63
64static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) 55static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
65{ 56{
66 struct m25p *flash = nor->priv; 57 struct m25p *flash = nor->priv;
67 struct spi_device *spi = flash->spi; 58 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1),
68 59 SPI_MEM_OP_NO_ADDR,
69 flash->command[0] = opcode; 60 SPI_MEM_OP_NO_DUMMY,
70 if (buf) 61 SPI_MEM_OP_DATA_OUT(len, buf, 1));
71 memcpy(&flash->command[1], buf, len);
72 62
73 return spi_write(spi, flash->command, len + 1); 63 return spi_mem_exec_op(flash->spimem, &op);
74} 64}
75 65
76static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len, 66static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
77 const u_char *buf) 67 const u_char *buf)
78{ 68{
79 struct m25p *flash = nor->priv; 69 struct m25p *flash = nor->priv;
80 struct spi_device *spi = flash->spi; 70 struct spi_mem_op op =
81 unsigned int inst_nbits, addr_nbits, data_nbits, data_idx; 71 SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1),
82 struct spi_transfer t[3] = {}; 72 SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
83 struct spi_message m; 73 SPI_MEM_OP_DUMMY(0, 1),
84 int cmd_sz = m25p_cmdsz(nor); 74 SPI_MEM_OP_DATA_OUT(len, buf, 1));
85 ssize_t ret; 75 size_t remaining = len;
76 int ret;
86 77
87 /* get transfer protocols. */ 78 /* get transfer protocols. */
88 inst_nbits = spi_nor_get_protocol_inst_nbits(nor->write_proto); 79 op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
89 addr_nbits = spi_nor_get_protocol_addr_nbits(nor->write_proto); 80 op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
90 data_nbits = spi_nor_get_protocol_data_nbits(nor->write_proto); 81 op.dummy.buswidth = op.addr.buswidth;
91 82 op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
92 spi_message_init(&m);
93 83
94 if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) 84 if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
95 cmd_sz = 1; 85 op.addr.nbytes = 0;
96
97 flash->command[0] = nor->program_opcode;
98 m25p_addr2cmd(nor, to, flash->command);
99 86
100 t[0].tx_buf = flash->command; 87 while (remaining) {
101 t[0].tx_nbits = inst_nbits; 88 op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
102 t[0].len = cmd_sz; 89 ret = spi_mem_adjust_op_size(flash->spimem, &op);
103 spi_message_add_tail(&t[0], &m); 90 if (ret)
104 91 return ret;
105 /* split the op code and address bytes into two transfers if needed. */
106 data_idx = 1;
107 if (addr_nbits != inst_nbits) {
108 t[0].len = 1;
109 92
110 t[1].tx_buf = &flash->command[1]; 93 ret = spi_mem_exec_op(flash->spimem, &op);
111 t[1].tx_nbits = addr_nbits; 94 if (ret)
112 t[1].len = cmd_sz - 1; 95 return ret;
113 spi_message_add_tail(&t[1], &m);
114 96
115 data_idx = 2; 97 op.addr.val += op.data.nbytes;
98 remaining -= op.data.nbytes;
99 op.data.buf.out += op.data.nbytes;
116 } 100 }
117 101
118 t[data_idx].tx_buf = buf; 102 return len;
119 t[data_idx].tx_nbits = data_nbits;
120 t[data_idx].len = len;
121 spi_message_add_tail(&t[data_idx], &m);
122
123 ret = spi_sync(spi, &m);
124 if (ret)
125 return ret;
126
127 ret = m.actual_length - cmd_sz;
128 if (ret < 0)
129 return -EIO;
130 return ret;
131} 103}
132 104
133/* 105/*
@@ -138,92 +110,39 @@ static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
138 u_char *buf) 110 u_char *buf)
139{ 111{
140 struct m25p *flash = nor->priv; 112 struct m25p *flash = nor->priv;
141 struct spi_device *spi = flash->spi; 113 struct spi_mem_op op =
142 unsigned int inst_nbits, addr_nbits, data_nbits, data_idx; 114 SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1),
143 struct spi_transfer t[3]; 115 SPI_MEM_OP_ADDR(nor->addr_width, from, 1),
144 struct spi_message m; 116 SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
145 unsigned int dummy = nor->read_dummy; 117 SPI_MEM_OP_DATA_IN(len, buf, 1));
146 ssize_t ret; 118 size_t remaining = len;
147 int cmd_sz; 119 int ret;
148 120
149 /* get transfer protocols. */ 121 /* get transfer protocols. */
150 inst_nbits = spi_nor_get_protocol_inst_nbits(nor->read_proto); 122 op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
151 addr_nbits = spi_nor_get_protocol_addr_nbits(nor->read_proto); 123 op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
152 data_nbits = spi_nor_get_protocol_data_nbits(nor->read_proto); 124 op.dummy.buswidth = op.addr.buswidth;
125 op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
153 126
154 /* convert the dummy cycles to the number of bytes */ 127 /* convert the dummy cycles to the number of bytes */
155 dummy = (dummy * addr_nbits) / 8; 128 op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
156
157 if (spi_flash_read_supported(spi)) {
158 struct spi_flash_read_message msg;
159
160 memset(&msg, 0, sizeof(msg));
161 129
162 msg.buf = buf; 130 while (remaining) {
163 msg.from = from; 131 op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
164 msg.len = len; 132 ret = spi_mem_adjust_op_size(flash->spimem, &op);
165 msg.read_opcode = nor->read_opcode; 133 if (ret)
166 msg.addr_width = nor->addr_width;
167 msg.dummy_bytes = dummy;
168 msg.opcode_nbits = inst_nbits;
169 msg.addr_nbits = addr_nbits;
170 msg.data_nbits = data_nbits;
171
172 ret = spi_flash_read(spi, &msg);
173 if (ret < 0)
174 return ret; 134 return ret;
175 return msg.retlen;
176 }
177 135
178 spi_message_init(&m); 136 ret = spi_mem_exec_op(flash->spimem, &op);
179 memset(t, 0, (sizeof t)); 137 if (ret)
180 138 return ret;
181 flash->command[0] = nor->read_opcode;
182 m25p_addr2cmd(nor, from, flash->command);
183
184 t[0].tx_buf = flash->command;
185 t[0].tx_nbits = inst_nbits;
186 t[0].len = m25p_cmdsz(nor) + dummy;
187 spi_message_add_tail(&t[0], &m);
188
189 /*
190 * Set all dummy/mode cycle bits to avoid sending some manufacturer
191 * specific pattern, which might make the memory enter its Continuous
192 * Read mode by mistake.
193 * Based on the different mode cycle bit patterns listed and described
194 * in the JESD216B specification, the 0xff value works for all memories
195 * and all manufacturers.
196 */
197 cmd_sz = t[0].len;
198 memset(flash->command + cmd_sz - dummy, 0xff, dummy);
199
200 /* split the op code and address bytes into two transfers if needed. */
201 data_idx = 1;
202 if (addr_nbits != inst_nbits) {
203 t[0].len = 1;
204
205 t[1].tx_buf = &flash->command[1];
206 t[1].tx_nbits = addr_nbits;
207 t[1].len = cmd_sz - 1;
208 spi_message_add_tail(&t[1], &m);
209 139
210 data_idx = 2; 140 op.addr.val += op.data.nbytes;
141 remaining -= op.data.nbytes;
142 op.data.buf.in += op.data.nbytes;
211 } 143 }
212 144
213 t[data_idx].rx_buf = buf; 145 return len;
214 t[data_idx].rx_nbits = data_nbits;
215 t[data_idx].len = min3(len, spi_max_transfer_size(spi),
216 spi_max_message_size(spi) - cmd_sz);
217 spi_message_add_tail(&t[data_idx], &m);
218
219 ret = spi_sync(spi, &m);
220 if (ret)
221 return ret;
222
223 ret = m.actual_length - cmd_sz;
224 if (ret < 0)
225 return -EIO;
226 return ret;
227} 146}
228 147
229/* 148/*
@@ -231,8 +150,9 @@ static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
231 * matches what the READ command supports, at least until this driver 150 * matches what the READ command supports, at least until this driver
232 * understands FAST_READ (for clocks over 25 MHz). 151 * understands FAST_READ (for clocks over 25 MHz).
233 */ 152 */
234static int m25p_probe(struct spi_device *spi) 153static int m25p_probe(struct spi_mem *spimem)
235{ 154{
155 struct spi_device *spi = spimem->spi;
236 struct flash_platform_data *data; 156 struct flash_platform_data *data;
237 struct m25p *flash; 157 struct m25p *flash;
238 struct spi_nor *nor; 158 struct spi_nor *nor;
@@ -244,9 +164,9 @@ static int m25p_probe(struct spi_device *spi)
244 char *flash_name; 164 char *flash_name;
245 int ret; 165 int ret;
246 166
247 data = dev_get_platdata(&spi->dev); 167 data = dev_get_platdata(&spimem->spi->dev);
248 168
249 flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); 169 flash = devm_kzalloc(&spimem->spi->dev, sizeof(*flash), GFP_KERNEL);
250 if (!flash) 170 if (!flash)
251 return -ENOMEM; 171 return -ENOMEM;
252 172
@@ -258,12 +178,12 @@ static int m25p_probe(struct spi_device *spi)
258 nor->write_reg = m25p80_write_reg; 178 nor->write_reg = m25p80_write_reg;
259 nor->read_reg = m25p80_read_reg; 179 nor->read_reg = m25p80_read_reg;
260 180
261 nor->dev = &spi->dev; 181 nor->dev = &spimem->spi->dev;
262 spi_nor_set_flash_node(nor, spi->dev.of_node); 182 spi_nor_set_flash_node(nor, spi->dev.of_node);
263 nor->priv = flash; 183 nor->priv = flash;
264 184
265 spi_set_drvdata(spi, flash); 185 spi_set_drvdata(spi, flash);
266 flash->spi = spi; 186 flash->spimem = spimem;
267 187
268 if (spi->mode & SPI_RX_QUAD) { 188 if (spi->mode & SPI_RX_QUAD) {
269 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; 189 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
@@ -303,9 +223,9 @@ static int m25p_probe(struct spi_device *spi)
303} 223}
304 224
305 225
306static int m25p_remove(struct spi_device *spi) 226static int m25p_remove(struct spi_mem *spimem)
307{ 227{
308 struct m25p *flash = spi_get_drvdata(spi); 228 struct m25p *flash = spi_mem_get_drvdata(spimem);
309 229
310 spi_nor_restore(&flash->spi_nor); 230 spi_nor_restore(&flash->spi_nor);
311 231
@@ -313,9 +233,9 @@ static int m25p_remove(struct spi_device *spi)
313 return mtd_device_unregister(&flash->spi_nor.mtd); 233 return mtd_device_unregister(&flash->spi_nor.mtd);
314} 234}
315 235
316static void m25p_shutdown(struct spi_device *spi) 236static void m25p_shutdown(struct spi_mem *spimem)
317{ 237{
318 struct m25p *flash = spi_get_drvdata(spi); 238 struct m25p *flash = spi_mem_get_drvdata(spimem);
319 239
320 spi_nor_restore(&flash->spi_nor); 240 spi_nor_restore(&flash->spi_nor);
321} 241}
@@ -386,12 +306,14 @@ static const struct of_device_id m25p_of_table[] = {
386}; 306};
387MODULE_DEVICE_TABLE(of, m25p_of_table); 307MODULE_DEVICE_TABLE(of, m25p_of_table);
388 308
389static struct spi_driver m25p80_driver = { 309static struct spi_mem_driver m25p80_driver = {
390 .driver = { 310 .spidrv = {
391 .name = "m25p80", 311 .driver = {
392 .of_match_table = m25p_of_table, 312 .name = "m25p80",
313 .of_match_table = m25p_of_table,
314 },
315 .id_table = m25p_ids,
393 }, 316 },
394 .id_table = m25p_ids,
395 .probe = m25p_probe, 317 .probe = m25p_probe,
396 .remove = m25p_remove, 318 .remove = m25p_remove,
397 .shutdown = m25p_shutdown, 319 .shutdown = m25p_shutdown,
@@ -402,7 +324,7 @@ static struct spi_driver m25p80_driver = {
402 */ 324 */
403}; 325};
404 326
405module_spi_driver(m25p80_driver); 327module_spi_mem_driver(m25p80_driver);
406 328
407MODULE_LICENSE("GPL"); 329MODULE_LICENSE("GPL");
408MODULE_AUTHOR("Mike Lavender"); 330MODULE_AUTHOR("Mike Lavender");