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 static u8
rb4xx_nand_read_byte(struct nand_chip
*chip
)
86 struct rb4xx_nand
*nand
= chip
->priv
;
87 struct rb4xx_cpld
*cpld
= nand
->cpld
;
91 ret
= cpld
->read_nand(cpld
, &data
, 1);
98 static void rb4xx_nand_write_buf(struct nand_chip
*chip
, const u8
*buf
, int len
)
100 struct rb4xx_nand
*nand
= chip
->priv
;
101 struct rb4xx_cpld
*cpld
= nand
->cpld
;
103 cpld
->write_nand(cpld
, buf
, len
);
106 static void rb4xx_nand_read_buf(struct nand_chip
*chip
, u8
*buf
, int len
)
108 struct rb4xx_nand
*nand
= chip
->priv
;
109 struct rb4xx_cpld
*cpld
= nand
->cpld
;
111 cpld
->read_nand(cpld
, buf
, len
);
114 static void rb4xx_nand_cmd_ctrl(struct nand_chip
*chip
, int dat
,
117 struct rb4xx_nand
*nand
= chip
->priv
;
118 struct rb4xx_cpld
*cpld
= nand
->cpld
;
121 if (ctrl
& NAND_CTRL_CHANGE
) {
122 gpiod_set_value_cansleep(nand
->cle
, !!(ctrl
& NAND_CLE
));
123 gpiod_set_value_cansleep(nand
->ale
, !!(ctrl
& NAND_ALE
));
124 gpiod_set_value_cansleep(nand
->nce
, !(ctrl
& NAND_NCE
));
127 if (dat
!= NAND_CMD_NONE
)
128 cpld
->write_nand(cpld
, &data
, 1);
131 static int rb4xx_nand_dev_ready(struct nand_chip
*chip
)
133 struct rb4xx_nand
*nand
= chip
->priv
;
135 return gpiod_get_value_cansleep(nand
->rdy
);
138 static int rb4xx_nand_probe(struct platform_device
*pdev
)
140 struct device
*dev
= &pdev
->dev
;
141 struct device
*parent
= dev
->parent
;
142 struct rb4xx_nand
*nand
;
143 struct mtd_info
*mtd
;
149 nand
= devm_kzalloc(dev
, sizeof(*nand
), GFP_KERNEL
);
153 platform_set_drvdata(pdev
, nand
);
154 nand
->cpld
= dev_get_drvdata(parent
);
157 nand
->ale
= devm_gpiod_get_index(dev
, NULL
, 0, GPIOD_OUT_LOW
);
158 if (IS_ERR(nand
->ale
))
159 dev_err(dev
, "missing gpio ALE: %ld\n", PTR_ERR(nand
->ale
));
161 nand
->cle
= devm_gpiod_get_index(dev
, NULL
, 1, GPIOD_OUT_LOW
);
162 if (IS_ERR(nand
->cle
))
163 dev_err(dev
, "missing gpio CLE: %ld\n", PTR_ERR(nand
->cle
));
165 nand
->nce
= devm_gpiod_get_index(dev
, NULL
, 2, GPIOD_OUT_LOW
);
166 if (IS_ERR(nand
->nce
))
167 dev_err(dev
, "missing gpio nCE: %ld\n", PTR_ERR(nand
->nce
));
169 nand
->rdy
= devm_gpiod_get_index(dev
, NULL
, 3, GPIOD_IN
);
170 if (IS_ERR(nand
->rdy
))
171 dev_err(dev
, "missing gpio RDY: %ld\n", PTR_ERR(nand
->rdy
));
173 if (IS_ERR(nand
->ale
) || IS_ERR(nand
->cle
) ||
174 IS_ERR(nand
->nce
) || IS_ERR(nand
->rdy
))
177 gpiod_set_consumer_name(nand
->ale
, "mikrotik:nand:ALE");
178 gpiod_set_consumer_name(nand
->cle
, "mikrotik:nand:CLE");
179 gpiod_set_consumer_name(nand
->nce
, "mikrotik:nand:nCE");
180 gpiod_set_consumer_name(nand
->rdy
, "mikrotik:nand:RDY");
182 mtd
= nand_to_mtd(&nand
->chip
);
184 mtd
->owner
= THIS_MODULE
;
185 mtd
->dev
.parent
= dev
;
186 mtd_set_of_node(mtd
, dev
->of_node
);
188 if (mtd
->writesize
== 512)
189 mtd_set_ooblayout(mtd
, &rb4xx_nand_ecclayout_ops
);
191 nand
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
192 nand
->chip
.ecc
.algo
= NAND_ECC_HAMMING
;
193 nand
->chip
.options
= NAND_NO_SUBPAGE_WRITE
;
194 nand
->chip
.priv
= nand
;
196 nand
->chip
.legacy
.read_byte
= rb4xx_nand_read_byte
;
197 nand
->chip
.legacy
.write_buf
= rb4xx_nand_write_buf
;
198 nand
->chip
.legacy
.read_buf
= rb4xx_nand_read_buf
;
199 nand
->chip
.legacy
.cmd_ctrl
= rb4xx_nand_cmd_ctrl
;
200 nand
->chip
.legacy
.dev_ready
= rb4xx_nand_dev_ready
;
201 nand
->chip
.legacy
.chip_delay
= 25;
203 ret
= nand_scan(&nand
->chip
, 1);
207 ret
= mtd_device_register(mtd
, NULL
, 0);
209 nand_release(&nand
->chip
);
216 static int rb4xx_nand_remove(struct platform_device
*pdev
)
218 struct rb4xx_nand
*nand
= platform_get_drvdata(pdev
);
220 nand_release(&nand
->chip
);
225 static const struct platform_device_id rb4xx_nand_id_table
[] = {
226 { "mikrotik,rb4xx-nand", },
229 MODULE_DEVICE_TABLE(platform
, rb4xx_nand_id_table
);
231 static struct platform_driver rb4xx_nand_driver
= {
232 .probe
= rb4xx_nand_probe
,
233 .remove
= rb4xx_nand_remove
,
234 .id_table
= rb4xx_nand_id_table
,
236 .name
= "rb4xx-nand",
240 module_platform_driver(rb4xx_nand_driver
);
242 MODULE_DESCRIPTION("Mikrotik RB4xx NAND driver");
243 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
244 MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>");
245 MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
246 MODULE_AUTHOR("Christopher Hill <ch6574@gmail.com");
247 MODULE_LICENSE("GPL v2");