pistachio: add 4.9 kernel support
[librecmc/librecmc.git] / target / linux / pistachio / patches-4.9 / 414-mtd-spi-nand-Support-Gigadevice-GD5F.patch
1 From 7723e59d483a883578115a73eb87eb7fff0ff724 Mon Sep 17 00:00:00 2001
2 From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
3 Date: Tue, 28 Feb 2017 10:37:24 +0000
4 Subject: mtd: spi-nand: Support Gigadevice GD5F
5
6 This commit uses the recently introduced SPI NAND framework to support
7 the Gigadevice GD5F serial NAND device.
8
9 The current support includes:
10
11   * Page read and page program operations (using on-die ECC)
12   * Page out-of-band read
13   * Erase
14   * Reset
15   * Device status retrieval
16   * Device ID retrieval
17
18 (based on http://lists.infradead.org/pipermail/linux-mtd/2014-December/056769.html)
19
20 Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
21 Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
22 ---
23  drivers/mtd/spi-nand/Kconfig           |  10 +
24  drivers/mtd/spi-nand/Makefile          |   1 +
25  drivers/mtd/spi-nand/spi-nand-device.c | 472 +++++++++++++++++++++++++++++++++
26  3 files changed, 483 insertions(+)
27  create mode 100644 drivers/mtd/spi-nand/spi-nand-device.c
28
29 diff --git a/drivers/mtd/spi-nand/Kconfig b/drivers/mtd/spi-nand/Kconfig
30 index 17b31e1..ab6bb6c 100644
31 --- a/drivers/mtd/spi-nand/Kconfig
32 +++ b/drivers/mtd/spi-nand/Kconfig
33 @@ -5,3 +5,13 @@ menuconfig MTD_SPI_NAND
34         help
35           This is the framework for the SPI NAND.
36  
37 +if MTD_SPI_NAND
38 +
39 +config MTD_SPI_NAND_DEVICES
40 +       tristate "Support for SPI NAND devices"
41 +       default y
42 +       depends on MTD_SPI_NAND
43 +       help
44 +         Select this option if you require support for SPI NAND devices.
45 +
46 +endif # MTD_SPI_NAND
47 diff --git a/drivers/mtd/spi-nand/Makefile b/drivers/mtd/spi-nand/Makefile
48 index d454c52..6e460d1 100644
49 --- a/drivers/mtd/spi-nand/Makefile
50 +++ b/drivers/mtd/spi-nand/Makefile
51 @@ -1 +1,2 @@
52  obj-$(CONFIG_MTD_SPI_NAND)             += spi-nand-base.o
53 +obj-$(CONFIG_MTD_SPI_NAND_DEVICES)     += spi-nand-device.o
54 diff --git a/drivers/mtd/spi-nand/spi-nand-device.c b/drivers/mtd/spi-nand/spi-nand-device.c
55 new file mode 100644
56 index 0000000..95db20b
57 --- /dev/null
58 +++ b/drivers/mtd/spi-nand/spi-nand-device.c
59 @@ -0,0 +1,472 @@
60 +/*
61 + * Copyright (C) 2014 Imagination Technologies Ltd.
62 + *
63 + * This program is free software; you can redistribute it and/or modify
64 + * it under the terms of the GNU General Public License as published by
65 + * the Free Software Foundation; version 2 of the License.
66 + *
67 + * Notes:
68 + * 1. We avoid using a stack-allocated buffer for SPI messages. Using
69 + *    a kmalloced buffer is probably better, given we shouldn't assume
70 + *    any particular usage by SPI core.
71 + */
72 +
73 +#include <linux/device.h>
74 +#include <linux/err.h>
75 +#include <linux/errno.h>
76 +#include <linux/module.h>
77 +#include <linux/mtd/mtd.h>
78 +#include <linux/mtd/partitions.h>
79 +#include <linux/mtd/spi-nand.h>
80 +#include <linux/sizes.h>
81 +#include <linux/spi/spi.h>
82 +
83 +/* SPI NAND commands */
84 +#define        SPI_NAND_WRITE_ENABLE           0x06
85 +#define        SPI_NAND_WRITE_DISABLE          0x04
86 +#define        SPI_NAND_GET_FEATURE            0x0f
87 +#define        SPI_NAND_SET_FEATURE            0x1f
88 +#define        SPI_NAND_PAGE_READ              0x13
89 +#define        SPI_NAND_READ_CACHE             0x03
90 +#define        SPI_NAND_FAST_READ_CACHE        0x0b
91 +#define        SPI_NAND_READ_CACHE_X2          0x3b
92 +#define        SPI_NAND_READ_CACHE_X4          0x6b
93 +#define        SPI_NAND_READ_CACHE_DUAL_IO     0xbb
94 +#define        SPI_NAND_READ_CACHE_QUAD_IO     0xeb
95 +#define        SPI_NAND_READ_ID                0x9f
96 +#define        SPI_NAND_PROGRAM_LOAD           0x02
97 +#define        SPI_NAND_PROGRAM_LOAD4          0x32
98 +#define        SPI_NAND_PROGRAM_EXEC           0x10
99 +#define        SPI_NAND_PROGRAM_LOAD_RANDOM    0x84
100 +#define        SPI_NAND_PROGRAM_LOAD_RANDOM4   0xc4
101 +#define        SPI_NAND_BLOCK_ERASE            0xd8
102 +#define        SPI_NAND_RESET                  0xff
103 +
104 +#define SPI_NAND_GD5F_READID_LEN       2
105 +
106 +#define SPI_NAND_GD5F_ECC_MASK         (BIT(0) | BIT(1) | BIT(2))
107 +#define SPI_NAND_GD5F_ECC_UNCORR       (BIT(0) | BIT(1) | BIT(2))
108 +#define SPI_NAND_GD5F_ECC_SHIFT                4
109 +
110 +static int spi_nand_gd5f_ooblayout_256_ecc(struct mtd_info *mtd, int section,
111 +                                       struct mtd_oob_region *oobregion)
112 +{
113 +       if (section)
114 +               return -ERANGE;
115 +
116 +       oobregion->offset = 128;
117 +       oobregion->length = 128;
118 +
119 +       return 0;
120 +}
121 +
122 +static int spi_nand_gd5f_ooblayout_256_free(struct mtd_info *mtd, int section,
123 +                                       struct mtd_oob_region *oobregion)
124 +{
125 +       if (section)
126 +               return -ERANGE;
127 +
128 +       oobregion->offset = 1;
129 +       oobregion->length = 127;
130 +
131 +       return 0;
132 +}
133 +
134 +static const struct mtd_ooblayout_ops spi_nand_gd5f_oob_256_ops = {
135 +       .ecc = spi_nand_gd5f_ooblayout_256_ecc,
136 +       .free = spi_nand_gd5f_ooblayout_256_free,
137 +};
138 +
139 +static struct nand_flash_dev spi_nand_flash_ids[] = {
140 +       {
141 +               .name = "SPI NAND 512MiB 3,3V",
142 +               .id = { NAND_MFR_GIGADEVICE, 0xb4 },
143 +               .chipsize = 512,
144 +               .pagesize = SZ_4K,
145 +               .erasesize = SZ_256K,
146 +               .id_len = 2,
147 +               .oobsize = 256,
148 +               .ecc.strength_ds = 8,
149 +               .ecc.step_ds = 512,
150 +       },
151 +       {
152 +               .name = "SPI NAND 512MiB 1,8V",
153 +               .id = { NAND_MFR_GIGADEVICE, 0xa4 },
154 +               .chipsize = 512,
155 +               .pagesize = SZ_4K,
156 +               .erasesize = SZ_256K,
157 +               .id_len = 2,
158 +               .oobsize = 256,
159 +               .ecc.strength_ds = 8,
160 +               .ecc.step_ds = 512,
161 +       },
162 +};
163 +
164 +enum spi_nand_device_variant {
165 +       SPI_NAND_GENERIC,
166 +       SPI_NAND_GD5F,
167 +};
168 +
169 +struct spi_nand_device_cmd {
170 +
171 +       /*
172 +        * Command and address. I/O errors have been observed if a
173 +        * separate spi_transfer is used for command and address,
174 +        * so keep them together.
175 +        */
176 +       u32 n_cmd;
177 +       u8 cmd[5];
178 +
179 +       /* Tx data */
180 +       u32 n_tx;
181 +       u8 *tx_buf;
182 +
183 +       /* Rx data */
184 +       u32 n_rx;
185 +       u8 *rx_buf;
186 +       u8 rx_nbits;
187 +       u8 tx_nbits;
188 +};
189 +
190 +struct spi_nand_device {
191 +       struct spi_nand spi_nand;
192 +       struct spi_device *spi;
193 +
194 +       struct spi_nand_device_cmd cmd;
195 +};
196 +
197 +static int spi_nand_send_command(struct spi_device *spi,
198 +                                struct spi_nand_device_cmd *cmd)
199 +{
200 +       struct spi_message message;
201 +       struct spi_transfer x[2];
202 +
203 +       if (!cmd->n_cmd) {
204 +               dev_err(&spi->dev, "cannot send an empty command\n");
205 +               return -EINVAL;
206 +       }
207 +
208 +       if (cmd->n_tx && cmd->n_rx) {
209 +               dev_err(&spi->dev, "cannot send and receive data at the same time\n");
210 +               return -EINVAL;
211 +       }
212 +
213 +       spi_message_init(&message);
214 +       memset(x, 0, sizeof(x));
215 +
216 +       /* Command and address */
217 +       x[0].len = cmd->n_cmd;
218 +       x[0].tx_buf = cmd->cmd;
219 +       x[0].tx_nbits = cmd->tx_nbits;
220 +       spi_message_add_tail(&x[0], &message);
221 +
222 +       /* Data to be transmitted */
223 +       if (cmd->n_tx) {
224 +               x[1].len = cmd->n_tx;
225 +               x[1].tx_buf = cmd->tx_buf;
226 +               x[1].tx_nbits = cmd->tx_nbits;
227 +               spi_message_add_tail(&x[1], &message);
228 +       }
229 +
230 +       /* Data to be received */
231 +       if (cmd->n_rx) {
232 +               x[1].len = cmd->n_rx;
233 +               x[1].rx_buf = cmd->rx_buf;
234 +               x[1].rx_nbits = cmd->rx_nbits;
235 +               spi_message_add_tail(&x[1], &message);
236 +       }
237 +
238 +       return spi_sync(spi, &message);
239 +}
240 +
241 +static int spi_nand_device_reset(struct spi_nand *snand)
242 +{
243 +       struct spi_nand_device *snand_dev = snand->priv;
244 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
245 +
246 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
247 +       cmd->n_cmd = 1;
248 +       cmd->cmd[0] = SPI_NAND_RESET;
249 +
250 +       dev_dbg(snand->dev, "%s\n", __func__);
251 +
252 +       return spi_nand_send_command(snand_dev->spi, cmd);
253 +}
254 +
255 +static int spi_nand_device_read_reg(struct spi_nand *snand, u8 opcode, u8 *buf)
256 +{
257 +       struct spi_nand_device *snand_dev = snand->priv;
258 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
259 +
260 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
261 +       cmd->n_cmd = 2;
262 +       cmd->cmd[0] = SPI_NAND_GET_FEATURE;
263 +       cmd->cmd[1] = opcode;
264 +       cmd->n_rx = 1;
265 +       cmd->rx_buf = buf;
266 +
267 +       dev_dbg(snand->dev, "%s: reg 0%x\n", __func__, opcode);
268 +
269 +       return spi_nand_send_command(snand_dev->spi, cmd);
270 +}
271 +
272 +static int spi_nand_device_write_reg(struct spi_nand *snand, u8 opcode, u8 *buf)
273 +{
274 +       struct spi_nand_device *snand_dev = snand->priv;
275 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
276 +
277 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
278 +       cmd->n_cmd = 2;
279 +       cmd->cmd[0] = SPI_NAND_SET_FEATURE;
280 +       cmd->cmd[1] = opcode;
281 +       cmd->n_tx = 1;
282 +       cmd->tx_buf = buf;
283 +
284 +       dev_dbg(snand->dev, "%s: reg 0%x\n", __func__, opcode);
285 +
286 +       return spi_nand_send_command(snand_dev->spi, cmd);
287 +}
288 +
289 +static int spi_nand_device_write_enable(struct spi_nand *snand)
290 +{
291 +       struct spi_nand_device *snand_dev = snand->priv;
292 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
293 +
294 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
295 +       cmd->n_cmd = 1;
296 +       cmd->cmd[0] = SPI_NAND_WRITE_ENABLE;
297 +
298 +       dev_dbg(snand->dev, "%s\n", __func__);
299 +
300 +       return spi_nand_send_command(snand_dev->spi, cmd);
301 +}
302 +
303 +static int spi_nand_device_write_disable(struct spi_nand *snand)
304 +{
305 +       struct spi_nand_device *snand_dev = snand->priv;
306 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
307 +
308 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
309 +       cmd->n_cmd = 1;
310 +       cmd->cmd[0] = SPI_NAND_WRITE_DISABLE;
311 +
312 +       dev_dbg(snand->dev, "%s\n", __func__);
313 +
314 +       return spi_nand_send_command(snand_dev->spi, cmd);
315 +}
316 +
317 +static int spi_nand_device_write_page(struct spi_nand *snand,
318 +                                     unsigned int page_addr)
319 +{
320 +       struct spi_nand_device *snand_dev = snand->priv;
321 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
322 +
323 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
324 +       cmd->n_cmd = 4;
325 +       cmd->cmd[0] = SPI_NAND_PROGRAM_EXEC;
326 +       cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
327 +       cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
328 +       cmd->cmd[3] = (u8)(page_addr & 0xff);
329 +
330 +       dev_dbg(snand->dev, "%s: page 0x%x\n", __func__, page_addr);
331 +
332 +       return spi_nand_send_command(snand_dev->spi, cmd);
333 +}
334 +
335 +static int spi_nand_device_store_cache(struct spi_nand *snand,
336 +                                      unsigned int page_offset, size_t length,
337 +                                      u8 *write_buf)
338 +{
339 +       struct spi_nand_device *snand_dev = snand->priv;
340 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
341 +       struct spi_device *spi = snand_dev->spi;
342 +
343 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
344 +       cmd->n_cmd = 3;
345 +       cmd->cmd[0] = spi->mode & SPI_TX_QUAD ? SPI_NAND_PROGRAM_LOAD4 :
346 +                       SPI_NAND_PROGRAM_LOAD;
347 +       cmd->cmd[1] = (u8)((page_offset & 0xff00) >> 8);
348 +       cmd->cmd[2] = (u8)(page_offset & 0xff);
349 +       cmd->n_tx = length;
350 +       cmd->tx_buf = write_buf;
351 +       cmd->tx_nbits = spi->mode & SPI_TX_QUAD ? 4 : 1;
352 +
353 +       dev_dbg(snand->dev, "%s: offset 0x%x\n", __func__, page_offset);
354 +
355 +       return spi_nand_send_command(snand_dev->spi, cmd);
356 +}
357 +
358 +static int spi_nand_device_load_page(struct spi_nand *snand,
359 +                                    unsigned int page_addr)
360 +{
361 +       struct spi_nand_device *snand_dev = snand->priv;
362 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
363 +
364 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
365 +       cmd->n_cmd = 4;
366 +       cmd->cmd[0] = SPI_NAND_PAGE_READ;
367 +       cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
368 +       cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
369 +       cmd->cmd[3] = (u8)(page_addr & 0xff);
370 +
371 +       dev_dbg(snand->dev, "%s: page 0x%x\n", __func__, page_addr);
372 +
373 +       return spi_nand_send_command(snand_dev->spi, cmd);
374 +}
375 +
376 +static int spi_nand_device_read_cache(struct spi_nand *snand,
377 +                                     unsigned int page_offset, size_t length,
378 +                                     u8 *read_buf)
379 +{
380 +       struct spi_nand_device *snand_dev = snand->priv;
381 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
382 +       struct spi_device *spi = snand_dev->spi;
383 +
384 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
385 +       if ((spi->mode & SPI_RX_DUAL) || (spi->mode & SPI_RX_QUAD))
386 +               cmd->n_cmd = 5;
387 +       else
388 +               cmd->n_cmd = 4;
389 +       cmd->cmd[0] = (spi->mode & SPI_RX_QUAD) ? SPI_NAND_READ_CACHE_X4 :
390 +                       ((spi->mode & SPI_RX_DUAL) ? SPI_NAND_READ_CACHE_X2 :
391 +                       SPI_NAND_READ_CACHE);
392 +       cmd->cmd[1] = 0; /* dummy byte */
393 +       cmd->cmd[2] = (u8)((page_offset & 0xff00) >> 8);
394 +       cmd->cmd[3] = (u8)(page_offset & 0xff);
395 +       cmd->cmd[4] = 0; /* dummy byte */
396 +       cmd->n_rx = length;
397 +       cmd->rx_buf = read_buf;
398 +       cmd->rx_nbits = (spi->mode & SPI_RX_QUAD) ? 4 :
399 +                       ((spi->mode & SPI_RX_DUAL) ? 2 : 1);
400 +
401 +       dev_dbg(snand->dev, "%s: offset 0x%x\n", __func__, page_offset);
402 +
403 +       return spi_nand_send_command(snand_dev->spi, cmd);
404 +}
405 +
406 +static int spi_nand_device_block_erase(struct spi_nand *snand,
407 +                                      unsigned int page_addr)
408 +{
409 +       struct spi_nand_device *snand_dev = snand->priv;
410 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
411 +
412 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
413 +       cmd->n_cmd = 4;
414 +       cmd->cmd[0] = SPI_NAND_BLOCK_ERASE;
415 +       cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
416 +       cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
417 +       cmd->cmd[3] = (u8)(page_addr & 0xff);
418 +
419 +       dev_dbg(snand->dev, "%s: block 0x%x\n", __func__, page_addr);
420 +
421 +       return spi_nand_send_command(snand_dev->spi, cmd);
422 +}
423 +
424 +static int spi_nand_gd5f_read_id(struct spi_nand *snand, u8 *buf)
425 +{
426 +       struct spi_nand_device *snand_dev = snand->priv;
427 +       struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
428 +
429 +       memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
430 +       cmd->n_cmd = 1;
431 +       cmd->cmd[0] = SPI_NAND_READ_ID;
432 +       cmd->n_rx = SPI_NAND_GD5F_READID_LEN;
433 +       cmd->rx_buf = buf;
434 +
435 +       dev_dbg(snand->dev, "%s\n", __func__);
436 +
437 +       return spi_nand_send_command(snand_dev->spi, cmd);
438 +}
439 +
440 +static void spi_nand_gd5f_ecc_status(unsigned int status,
441 +                                    unsigned int *corrected,
442 +                                    unsigned int *ecc_error)
443 +{
444 +       unsigned int ecc_status = (status >> SPI_NAND_GD5F_ECC_SHIFT) &
445 +                                            SPI_NAND_GD5F_ECC_MASK;
446 +
447 +       *ecc_error = (ecc_status == SPI_NAND_GD5F_ECC_UNCORR) ? 1 : 0;
448 +       if (*ecc_error == 0)
449 +               *corrected = (ecc_status > 1) ? (2 + ecc_status) : 0;
450 +}
451 +
452 +static int spi_nand_device_probe(struct spi_device *spi)
453 +{
454 +       enum spi_nand_device_variant variant;
455 +       struct spi_nand_device *priv;
456 +       struct spi_nand *snand;
457 +       int ret;
458 +
459 +       priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
460 +       if (!priv)
461 +               return -ENOMEM;
462 +
463 +       snand = &priv->spi_nand;
464 +
465 +       snand->read_cache = spi_nand_device_read_cache;
466 +       snand->load_page = spi_nand_device_load_page;
467 +       snand->store_cache = spi_nand_device_store_cache;
468 +       snand->write_page = spi_nand_device_write_page;
469 +       snand->write_reg = spi_nand_device_write_reg;
470 +       snand->read_reg = spi_nand_device_read_reg;
471 +       snand->block_erase = spi_nand_device_block_erase;
472 +       snand->reset = spi_nand_device_reset;
473 +       snand->write_enable = spi_nand_device_write_enable;
474 +       snand->write_disable = spi_nand_device_write_disable;
475 +       snand->dev = &spi->dev;
476 +       snand->priv = priv;
477 +
478 +       /* This'll mean we won't need to specify any specific compatible string
479 +        * for a given device, and instead just support spi-nand.
480 +        */
481 +       variant = spi_get_device_id(spi)->driver_data;
482 +       switch (variant) {
483 +       case SPI_NAND_GD5F:
484 +               snand->read_id = spi_nand_gd5f_read_id;
485 +               snand->get_ecc_status = spi_nand_gd5f_ecc_status;
486 +               snand->ooblayout = &spi_nand_gd5f_oob_256_ops;
487 +               break;
488 +       default:
489 +               dev_err(snand->dev, "unknown device\n");
490 +               return -ENODEV;
491 +       }
492 +
493 +       spi_set_drvdata(spi, snand);
494 +       priv->spi = spi;
495 +
496 +       ret = spi_nand_register(snand, spi_nand_flash_ids);
497 +       if (ret)
498 +               return ret;
499 +       return 0;
500 +}
501 +
502 +static int spi_nand_device_remove(struct spi_device *spi)
503 +{
504 +       struct spi_nand *snand = spi_get_drvdata(spi);
505 +
506 +       spi_nand_unregister(snand);
507 +
508 +       return 0;
509 +}
510 +
511 +const struct spi_device_id spi_nand_id_table[] = {
512 +       { "spi-nand", SPI_NAND_GENERIC },
513 +       { "gd5f", SPI_NAND_GD5F },
514 +       { },
515 +};
516 +MODULE_DEVICE_TABLE(spi, spi_nand_id_table);
517 +
518 +static struct spi_driver spi_nand_device_driver = {
519 +       .driver = {
520 +               .name   = "spi_nand_device",
521 +               .owner  = THIS_MODULE,
522 +       },
523 +       .id_table = spi_nand_id_table,
524 +       .probe  = spi_nand_device_probe,
525 +       .remove = spi_nand_device_remove,
526 +};
527 +module_spi_driver(spi_nand_device_driver);
528 +
529 +MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@imgtec.com>");
530 +MODULE_DESCRIPTION("SPI NAND device support");
531 +MODULE_LICENSE("GPL v2");
532 -- 
533 2.7.4
534