1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/err.h>
19#include <linux/errno.h>
20#include <linux/module.h>
21#include <linux/device.h>
22
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/partitions.h>
25
26#include <linux/spi/spi.h>
27#include <linux/spi/spi-mem.h>
28#include <linux/spi/flash.h>
29#include <linux/mtd/spi-nor.h>
30
31#define MAX_CMD_SIZE 6
32struct m25p {
33 struct spi_mem *spimem;
34 struct spi_nor spi_nor;
35 u8 command[MAX_CMD_SIZE];
36};
37
38static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
39{
40 struct m25p *flash = nor->priv;
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));
45 int ret;
46
47 ret = spi_mem_exec_op(flash->spimem, &op);
48 if (ret < 0)
49 dev_err(&flash->spimem->spi->dev, "error %d reading %x\n", ret,
50 code);
51
52 return ret;
53}
54
55static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
56{
57 struct m25p *flash = nor->priv;
58 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1),
59 SPI_MEM_OP_NO_ADDR,
60 SPI_MEM_OP_NO_DUMMY,
61 SPI_MEM_OP_DATA_OUT(len, buf, 1));
62
63 return spi_mem_exec_op(flash->spimem, &op);
64}
65
66static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
67 const u_char *buf)
68{
69 struct m25p *flash = nor->priv;
70 struct spi_mem_op op =
71 SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1),
72 SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
73 SPI_MEM_OP_DUMMY(0, 1),
74 SPI_MEM_OP_DATA_OUT(len, buf, 1));
75 size_t remaining = len;
76 int ret;
77
78
79 op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
80 op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
81 op.dummy.buswidth = op.addr.buswidth;
82 op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
83
84 if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
85 op.addr.nbytes = 0;
86
87 while (remaining) {
88 op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
89 ret = spi_mem_adjust_op_size(flash->spimem, &op);
90 if (ret)
91 return ret;
92
93 ret = spi_mem_exec_op(flash->spimem, &op);
94 if (ret)
95 return ret;
96
97 op.addr.val += op.data.nbytes;
98 remaining -= op.data.nbytes;
99 op.data.buf.out += op.data.nbytes;
100 }
101
102 return len;
103}
104
105
106
107
108
109static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
110 u_char *buf)
111{
112 struct m25p *flash = nor->priv;
113 struct spi_mem_op op =
114 SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1),
115 SPI_MEM_OP_ADDR(nor->addr_width, from, 1),
116 SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
117 SPI_MEM_OP_DATA_IN(len, buf, 1));
118 size_t remaining = len;
119 int ret;
120
121
122 op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
123 op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
124 op.dummy.buswidth = op.addr.buswidth;
125 op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
126
127
128 op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
129
130 while (remaining) {
131 op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
132 ret = spi_mem_adjust_op_size(flash->spimem, &op);
133 if (ret)
134 return ret;
135
136 ret = spi_mem_exec_op(flash->spimem, &op);
137 if (ret)
138 return ret;
139
140 op.addr.val += op.data.nbytes;
141 remaining -= op.data.nbytes;
142 op.data.buf.in += op.data.nbytes;
143 }
144
145 return len;
146}
147
148
149
150
151
152
153static int m25p_probe(struct spi_mem *spimem)
154{
155 struct spi_device *spi = spimem->spi;
156 struct flash_platform_data *data;
157 struct m25p *flash;
158 struct spi_nor *nor;
159 struct spi_nor_hwcaps hwcaps = {
160 .mask = SNOR_HWCAPS_READ |
161 SNOR_HWCAPS_READ_FAST |
162 SNOR_HWCAPS_PP,
163 };
164 char *flash_name;
165 int ret;
166
167 data = dev_get_platdata(&spimem->spi->dev);
168
169 flash = devm_kzalloc(&spimem->spi->dev, sizeof(*flash), GFP_KERNEL);
170 if (!flash)
171 return -ENOMEM;
172
173 nor = &flash->spi_nor;
174
175
176 nor->read = m25p80_read;
177 nor->write = m25p80_write;
178 nor->write_reg = m25p80_write_reg;
179 nor->read_reg = m25p80_read_reg;
180
181 nor->dev = &spimem->spi->dev;
182 spi_nor_set_flash_node(nor, spi->dev.of_node);
183 nor->priv = flash;
184
185 spi_mem_set_drvdata(spimem, flash);
186 flash->spimem = spimem;
187
188 if (spi->mode & SPI_RX_QUAD) {
189 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
190
191 if (spi->mode & SPI_TX_QUAD)
192 hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 |
193 SNOR_HWCAPS_PP_1_1_4 |
194 SNOR_HWCAPS_PP_1_4_4);
195 } else if (spi->mode & SPI_RX_DUAL) {
196 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
197
198 if (spi->mode & SPI_TX_DUAL)
199 hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2;
200 }
201
202 if (data && data->name)
203 nor->mtd.name = data->name;
204
205
206
207
208
209
210 if (data && data->type)
211 flash_name = data->type;
212 else if (!strcmp(spi->modalias, "spi-nor"))
213 flash_name = NULL;
214 else
215 flash_name = spi->modalias;
216
217 ret = spi_nor_scan(nor, flash_name, &hwcaps);
218 if (ret)
219 return ret;
220
221 return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
222 data ? data->nr_parts : 0);
223}
224
225
226static int m25p_remove(struct spi_mem *spimem)
227{
228 struct m25p *flash = spi_mem_get_drvdata(spimem);
229
230 spi_nor_restore(&flash->spi_nor);
231
232
233 return mtd_device_unregister(&flash->spi_nor.mtd);
234}
235
236static void m25p_shutdown(struct spi_mem *spimem)
237{
238 struct m25p *flash = spi_mem_get_drvdata(spimem);
239
240 spi_nor_restore(&flash->spi_nor);
241}
242
243
244
245
246
247
248
249
250
251
252
253
254static const struct spi_device_id m25p_ids[] = {
255
256
257
258
259
260 {"spi-nor"},
261
262
263
264
265
266 {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"},
267
268
269
270
271
272 {"at25df321a"}, {"at25df641"}, {"at26df081a"},
273 {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"},
274 {"mx25l25635e"},{"mx66l51235l"},
275 {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"},
276 {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"},
277 {"s25fl064k"},
278 {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"},
279 {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"},
280 {"m25p64"}, {"m25p128"},
281 {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"},
282 {"w25q80bl"}, {"w25q128"}, {"w25q256"},
283
284
285 {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"},
286 {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"},
287 {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"},
288
289
290 { "mr25h128" },
291 { "mr25h256" },
292 { "mr25h10" },
293 { "mr25h40" },
294
295 { },
296};
297MODULE_DEVICE_TABLE(spi, m25p_ids);
298
299static const struct of_device_id m25p_of_table[] = {
300
301
302
303
304 { .compatible = "jedec,spi-nor" },
305 {}
306};
307MODULE_DEVICE_TABLE(of, m25p_of_table);
308
309static struct spi_mem_driver m25p80_driver = {
310 .spidrv = {
311 .driver = {
312 .name = "m25p80",
313 .of_match_table = m25p_of_table,
314 },
315 .id_table = m25p_ids,
316 },
317 .probe = m25p_probe,
318 .remove = m25p_remove,
319 .shutdown = m25p_shutdown,
320
321
322
323
324
325};
326
327module_spi_mem_driver(m25p80_driver);
328
329MODULE_LICENSE("GPL");
330MODULE_AUTHOR("Mike Lavender");
331MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");
332