1 // SPDX-License-Identifier: GPL-2.0-only
3 * NAND driver for the MikroTik RouterBoard 4xx series
5 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7 * Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
8 * Copyright (C) 2020 Christopher Hill <ch6574@gmail.com>
10 * This file was based on the driver for Linux 2.6.22 published by
11 * MikroTik for their RouterBoard 4xx series devices.
13 * N.B. driver probe reports "DMA mask not set" warnings which are
14 * an artifact of using a platform_driver as an MFD device child.
15 * See conversation here https://lkml.org/lkml/2020/4/28/675
17 #include <linux/platform_device.h>
18 #include <linux/mtd/rawnand.h>
19 #include <linux/gpio/consumer.h>
20 #include <linux/module.h>
21 #include <linux/of_device.h>
22 #include <linux/version.h>
24 #include <mfd/rb4xx-cpld.h>
27 struct rb4xx_cpld
*cpld
;
30 struct nand_chip chip
;
31 struct gpio_desc
*ale
;
32 struct gpio_desc
*cle
;
33 struct gpio_desc
*nce
;
34 struct gpio_desc
*rdy
;
37 static int rb4xx_ooblayout_ecc(struct mtd_info
*mtd
, int section
,
38 struct mtd_oob_region
*oobregion
)
42 oobregion
->offset
= 8;
43 oobregion
->length
= 3;
46 oobregion
->offset
= 13;
47 oobregion
->length
= 3;
54 static int rb4xx_ooblayout_free(struct mtd_info
*mtd
, int section
,
55 struct mtd_oob_region
*oobregion
)
59 oobregion
->offset
= 0;
60 oobregion
->length
= 4;
63 oobregion
->offset
= 4;
64 oobregion
->length
= 1;
67 oobregion
->offset
= 6;
68 oobregion
->length
= 2;
71 oobregion
->offset
= 11;
72 oobregion
->length
= 2;
79 static const struct mtd_ooblayout_ops rb4xx_nand_ecclayout_ops
= {
80 .ecc
= rb4xx_ooblayout_ecc
,
81 .free
= rb4xx_ooblayout_free
,
84 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
85 static uint8_t rb4xx_nand_read_byte(struct mtd_info
*mtd
)
87 struct rb4xx_nand
*nand
= mtd
->priv
;
89 static u8
rb4xx_nand_read_byte(struct nand_chip
*chip
)
91 struct rb4xx_nand
*nand
= chip
->priv
;
93 struct rb4xx_cpld
*cpld
= nand
->cpld
;
97 ret
= cpld
->read_nand(cpld
, &data
, 1);
104 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
105 static void rb4xx_nand_write_buf(struct mtd_info
*mtd
, const uint8_t *buf
,
108 struct rb4xx_nand
*nand
= mtd
->priv
;
110 static void rb4xx_nand_write_buf(struct nand_chip
*chip
, const u8
*buf
, int len
)
112 struct rb4xx_nand
*nand
= chip
->priv
;
114 struct rb4xx_cpld
*cpld
= nand
->cpld
;
116 cpld
->write_nand(cpld
, buf
, len
);
119 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
120 static void rb4xx_nand_read_buf(struct mtd_info
*mtd
, uint8_t *buf
, int len
)
122 struct rb4xx_nand
*nand
= mtd
->priv
;
124 static void rb4xx_nand_read_buf(struct nand_chip
*chip
, u8
*buf
, int len
)
126 struct rb4xx_nand
*nand
= chip
->priv
;
128 struct rb4xx_cpld
*cpld
= nand
->cpld
;
130 cpld
->read_nand(cpld
, buf
, len
);
133 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
134 static void rb4xx_nand_cmd_ctrl(struct mtd_info
*mtd
, int dat
, unsigned int ctrl
)
136 struct rb4xx_nand
*nand
= mtd
->priv
;
138 static void rb4xx_nand_cmd_ctrl(struct nand_chip
*chip
, int dat
,
141 struct rb4xx_nand
*nand
= chip
->priv
;
143 struct rb4xx_cpld
*cpld
= nand
->cpld
;
146 if (ctrl
& NAND_CTRL_CHANGE
) {
147 gpiod_set_value_cansleep(nand
->cle
, !!(ctrl
& NAND_CLE
));
148 gpiod_set_value_cansleep(nand
->ale
, !!(ctrl
& NAND_ALE
));
149 gpiod_set_value_cansleep(nand
->nce
, !(ctrl
& NAND_NCE
));
152 if (dat
!= NAND_CMD_NONE
)
153 cpld
->write_nand(cpld
, &data
, 1);
156 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
157 static int rb4xx_nand_dev_ready(struct mtd_info
*mtd
)
159 struct rb4xx_nand
*nand
= mtd
->priv
;
161 static int rb4xx_nand_dev_ready(struct nand_chip
*chip
)
163 struct rb4xx_nand
*nand
= chip
->priv
;
166 return gpiod_get_value_cansleep(nand
->rdy
);
169 static int rb4xx_nand_probe(struct platform_device
*pdev
)
171 struct device
*dev
= &pdev
->dev
;
172 struct device
*parent
= dev
->parent
;
173 struct rb4xx_nand
*nand
;
174 struct mtd_info
*mtd
;
180 nand
= devm_kzalloc(dev
, sizeof(*nand
), GFP_KERNEL
);
184 platform_set_drvdata(pdev
, nand
);
185 nand
->cpld
= dev_get_drvdata(parent
);
188 nand
->ale
= devm_gpiod_get_index(dev
, NULL
, 0, GPIOD_OUT_LOW
);
189 if (IS_ERR(nand
->ale
))
190 dev_err(dev
, "missing gpio ALE: %ld\n", PTR_ERR(nand
->ale
));
192 nand
->cle
= devm_gpiod_get_index(dev
, NULL
, 1, GPIOD_OUT_LOW
);
193 if (IS_ERR(nand
->cle
))
194 dev_err(dev
, "missing gpio CLE: %ld\n", PTR_ERR(nand
->cle
));
196 nand
->nce
= devm_gpiod_get_index(dev
, NULL
, 2, GPIOD_OUT_LOW
);
197 if (IS_ERR(nand
->nce
))
198 dev_err(dev
, "missing gpio nCE: %ld\n", PTR_ERR(nand
->nce
));
200 nand
->rdy
= devm_gpiod_get_index(dev
, NULL
, 3, GPIOD_IN
);
201 if (IS_ERR(nand
->rdy
))
202 dev_err(dev
, "missing gpio RDY: %ld\n", PTR_ERR(nand
->rdy
));
204 if (IS_ERR(nand
->ale
) || IS_ERR(nand
->cle
) ||
205 IS_ERR(nand
->nce
) || IS_ERR(nand
->rdy
))
208 gpiod_set_consumer_name(nand
->ale
, "mikrotik:nand:ALE");
209 gpiod_set_consumer_name(nand
->cle
, "mikrotik:nand:CLE");
210 gpiod_set_consumer_name(nand
->nce
, "mikrotik:nand:nCE");
211 gpiod_set_consumer_name(nand
->rdy
, "mikrotik:nand:RDY");
213 mtd
= nand_to_mtd(&nand
->chip
);
215 mtd
->owner
= THIS_MODULE
;
216 mtd
->dev
.parent
= dev
;
217 mtd_set_of_node(mtd
, dev
->of_node
);
219 if (mtd
->writesize
== 512)
220 mtd_set_ooblayout(mtd
, &rb4xx_nand_ecclayout_ops
);
222 nand
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
223 nand
->chip
.ecc
.algo
= NAND_ECC_HAMMING
;
224 nand
->chip
.options
= NAND_NO_SUBPAGE_WRITE
;
225 nand
->chip
.priv
= nand
;
227 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
228 nand
->chip
.read_byte
= rb4xx_nand_read_byte
;
229 nand
->chip
.write_buf
= rb4xx_nand_write_buf
;
230 nand
->chip
.read_buf
= rb4xx_nand_read_buf
;
231 nand
->chip
.cmd_ctrl
= rb4xx_nand_cmd_ctrl
;
232 nand
->chip
.dev_ready
= rb4xx_nand_dev_ready
;
233 nand
->chip
.chip_delay
= 25;
235 ret
= nand_scan(mtd
, 1);
237 nand
->chip
.legacy
.read_byte
= rb4xx_nand_read_byte
;
238 nand
->chip
.legacy
.write_buf
= rb4xx_nand_write_buf
;
239 nand
->chip
.legacy
.read_buf
= rb4xx_nand_read_buf
;
240 nand
->chip
.legacy
.cmd_ctrl
= rb4xx_nand_cmd_ctrl
;
241 nand
->chip
.legacy
.dev_ready
= rb4xx_nand_dev_ready
;
242 nand
->chip
.legacy
.chip_delay
= 25;
244 ret
= nand_scan(&nand
->chip
, 1);
249 ret
= mtd_device_register(mtd
, NULL
, 0);
251 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
254 nand_release(&nand
->chip
);
262 static int rb4xx_nand_remove(struct platform_device
*pdev
)
264 struct rb4xx_nand
*nand
= platform_get_drvdata(pdev
);
266 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
267 nand_release(nand_to_mtd(&nand
->chip
));
269 nand_release(&nand
->chip
);
275 static const struct platform_device_id rb4xx_nand_id_table
[] = {
276 { "mikrotik,rb4xx-nand", },
279 MODULE_DEVICE_TABLE(platform
, rb4xx_nand_id_table
);
281 static struct platform_driver rb4xx_nand_driver
= {
282 .probe
= rb4xx_nand_probe
,
283 .remove
= rb4xx_nand_remove
,
284 .id_table
= rb4xx_nand_id_table
,
286 .name
= "rb4xx-nand",
290 module_platform_driver(rb4xx_nand_driver
);
292 MODULE_DESCRIPTION("Mikrotik RB4xx NAND driver");
293 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
294 MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>");
295 MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
296 MODULE_AUTHOR("Christopher Hill <ch6574@gmail.com");
297 MODULE_LICENSE("GPL v2");