xref: /openbmc/linux/drivers/mtd/nand/raw/gpio.c (revision ba61bb17)
1 /*
2  * Updated, and converted to generic GPIO based driver by Russell King.
3  *
4  * Written by Ben Dooks <ben@simtec.co.uk>
5  *   Based on 2.4 version by Mark Whittaker
6  *
7  * © 2004 Simtec Electronics
8  *
9  * Device driver for NAND flash that uses a memory mapped interface to
10  * read/write the NAND commands and data, and GPIO pins for control signals
11  * (the DT binding refers to this as "GPIO assisted NAND flash")
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  *
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/err.h>
21 #include <linux/slab.h>
22 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/gpio/consumer.h>
25 #include <linux/io.h>
26 #include <linux/mtd/mtd.h>
27 #include <linux/mtd/rawnand.h>
28 #include <linux/mtd/partitions.h>
29 #include <linux/mtd/nand-gpio.h>
30 #include <linux/of.h>
31 #include <linux/of_address.h>
32 
33 struct gpiomtd {
34 	void __iomem		*io_sync;
35 	struct nand_chip	nand_chip;
36 	struct gpio_nand_platdata plat;
37 	struct gpio_desc *nce; /* Optional chip enable */
38 	struct gpio_desc *cle;
39 	struct gpio_desc *ale;
40 	struct gpio_desc *rdy;
41 	struct gpio_desc *nwp; /* Optional write protection */
42 };
43 
44 static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
45 {
46 	return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip);
47 }
48 
49 
50 #ifdef CONFIG_ARM
51 /* gpio_nand_dosync()
52  *
53  * Make sure the GPIO state changes occur in-order with writes to NAND
54  * memory region.
55  * Needed on PXA due to bus-reordering within the SoC itself (see section on
56  * I/O ordering in PXA manual (section 2.3, p35)
57  */
58 static void gpio_nand_dosync(struct gpiomtd *gpiomtd)
59 {
60 	unsigned long tmp;
61 
62 	if (gpiomtd->io_sync) {
63 		/*
64 		 * Linux memory barriers don't cater for what's required here.
65 		 * What's required is what's here - a read from a separate
66 		 * region with a dependency on that read.
67 		 */
68 		tmp = readl(gpiomtd->io_sync);
69 		asm volatile("mov %1, %0\n" : "=r" (tmp) : "r" (tmp));
70 	}
71 }
72 #else
73 static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {}
74 #endif
75 
76 static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
77 {
78 	struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
79 
80 	gpio_nand_dosync(gpiomtd);
81 
82 	if (ctrl & NAND_CTRL_CHANGE) {
83 		if (gpiomtd->nce)
84 			gpiod_set_value(gpiomtd->nce, !(ctrl & NAND_NCE));
85 		gpiod_set_value(gpiomtd->cle, !!(ctrl & NAND_CLE));
86 		gpiod_set_value(gpiomtd->ale, !!(ctrl & NAND_ALE));
87 		gpio_nand_dosync(gpiomtd);
88 	}
89 	if (cmd == NAND_CMD_NONE)
90 		return;
91 
92 	writeb(cmd, gpiomtd->nand_chip.IO_ADDR_W);
93 	gpio_nand_dosync(gpiomtd);
94 }
95 
96 static int gpio_nand_devready(struct mtd_info *mtd)
97 {
98 	struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
99 
100 	return gpiod_get_value(gpiomtd->rdy);
101 }
102 
103 #ifdef CONFIG_OF
104 static const struct of_device_id gpio_nand_id_table[] = {
105 	{ .compatible = "gpio-control-nand" },
106 	{}
107 };
108 MODULE_DEVICE_TABLE(of, gpio_nand_id_table);
109 
110 static int gpio_nand_get_config_of(const struct device *dev,
111 				   struct gpio_nand_platdata *plat)
112 {
113 	u32 val;
114 
115 	if (!dev->of_node)
116 		return -ENODEV;
117 
118 	if (!of_property_read_u32(dev->of_node, "bank-width", &val)) {
119 		if (val == 2) {
120 			plat->options |= NAND_BUSWIDTH_16;
121 		} else if (val != 1) {
122 			dev_err(dev, "invalid bank-width %u\n", val);
123 			return -EINVAL;
124 		}
125 	}
126 
127 	if (!of_property_read_u32(dev->of_node, "chip-delay", &val))
128 		plat->chip_delay = val;
129 
130 	return 0;
131 }
132 
133 static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
134 {
135 	struct resource *r;
136 	u64 addr;
137 
138 	if (of_property_read_u64(pdev->dev.of_node,
139 				       "gpio-control-nand,io-sync-reg", &addr))
140 		return NULL;
141 
142 	r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
143 	if (!r)
144 		return NULL;
145 
146 	r->start = addr;
147 	r->end = r->start + 0x3;
148 	r->flags = IORESOURCE_MEM;
149 
150 	return r;
151 }
152 #else /* CONFIG_OF */
153 static inline int gpio_nand_get_config_of(const struct device *dev,
154 					  struct gpio_nand_platdata *plat)
155 {
156 	return -ENOSYS;
157 }
158 
159 static inline struct resource *
160 gpio_nand_get_io_sync_of(struct platform_device *pdev)
161 {
162 	return NULL;
163 }
164 #endif /* CONFIG_OF */
165 
166 static inline int gpio_nand_get_config(const struct device *dev,
167 				       struct gpio_nand_platdata *plat)
168 {
169 	int ret = gpio_nand_get_config_of(dev, plat);
170 
171 	if (!ret)
172 		return ret;
173 
174 	if (dev_get_platdata(dev)) {
175 		memcpy(plat, dev_get_platdata(dev), sizeof(*plat));
176 		return 0;
177 	}
178 
179 	return -EINVAL;
180 }
181 
182 static inline struct resource *
183 gpio_nand_get_io_sync(struct platform_device *pdev)
184 {
185 	struct resource *r = gpio_nand_get_io_sync_of(pdev);
186 
187 	if (r)
188 		return r;
189 
190 	return platform_get_resource(pdev, IORESOURCE_MEM, 1);
191 }
192 
193 static int gpio_nand_remove(struct platform_device *pdev)
194 {
195 	struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
196 
197 	nand_release(nand_to_mtd(&gpiomtd->nand_chip));
198 
199 	/* Enable write protection and disable the chip */
200 	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
201 		gpiod_set_value(gpiomtd->nwp, 0);
202 	if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
203 		gpiod_set_value(gpiomtd->nce, 0);
204 
205 	return 0;
206 }
207 
208 static int gpio_nand_probe(struct platform_device *pdev)
209 {
210 	struct gpiomtd *gpiomtd;
211 	struct nand_chip *chip;
212 	struct mtd_info *mtd;
213 	struct resource *res;
214 	struct device *dev = &pdev->dev;
215 	int ret = 0;
216 
217 	if (!dev->of_node && !dev_get_platdata(dev))
218 		return -EINVAL;
219 
220 	gpiomtd = devm_kzalloc(dev, sizeof(*gpiomtd), GFP_KERNEL);
221 	if (!gpiomtd)
222 		return -ENOMEM;
223 
224 	chip = &gpiomtd->nand_chip;
225 
226 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
227 	chip->IO_ADDR_R = devm_ioremap_resource(dev, res);
228 	if (IS_ERR(chip->IO_ADDR_R))
229 		return PTR_ERR(chip->IO_ADDR_R);
230 
231 	res = gpio_nand_get_io_sync(pdev);
232 	if (res) {
233 		gpiomtd->io_sync = devm_ioremap_resource(dev, res);
234 		if (IS_ERR(gpiomtd->io_sync))
235 			return PTR_ERR(gpiomtd->io_sync);
236 	}
237 
238 	ret = gpio_nand_get_config(dev, &gpiomtd->plat);
239 	if (ret)
240 		return ret;
241 
242 	/* Just enable the chip */
243 	gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH);
244 	if (IS_ERR(gpiomtd->nce))
245 		return PTR_ERR(gpiomtd->nce);
246 
247 	/* We disable write protection once we know probe() will succeed */
248 	gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW);
249 	if (IS_ERR(gpiomtd->nwp)) {
250 		ret = PTR_ERR(gpiomtd->nwp);
251 		goto out_ce;
252 	}
253 
254 	gpiomtd->ale = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW);
255 	if (IS_ERR(gpiomtd->ale)) {
256 		ret = PTR_ERR(gpiomtd->ale);
257 		goto out_ce;
258 	}
259 
260 	gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW);
261 	if (IS_ERR(gpiomtd->cle)) {
262 		ret = PTR_ERR(gpiomtd->cle);
263 		goto out_ce;
264 	}
265 
266 	gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN);
267 	if (IS_ERR(gpiomtd->rdy)) {
268 		ret = PTR_ERR(gpiomtd->rdy);
269 		goto out_ce;
270 	}
271 	/* Using RDY pin */
272 	if (gpiomtd->rdy)
273 		chip->dev_ready = gpio_nand_devready;
274 
275 	nand_set_flash_node(chip, pdev->dev.of_node);
276 	chip->IO_ADDR_W		= chip->IO_ADDR_R;
277 	chip->ecc.mode		= NAND_ECC_SOFT;
278 	chip->ecc.algo		= NAND_ECC_HAMMING;
279 	chip->options		= gpiomtd->plat.options;
280 	chip->chip_delay	= gpiomtd->plat.chip_delay;
281 	chip->cmd_ctrl		= gpio_nand_cmd_ctrl;
282 
283 	mtd			= nand_to_mtd(chip);
284 	mtd->dev.parent		= dev;
285 
286 	platform_set_drvdata(pdev, gpiomtd);
287 
288 	/* Disable write protection, if wired up */
289 	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
290 		gpiod_direction_output(gpiomtd->nwp, 1);
291 
292 	ret = nand_scan(mtd, 1);
293 	if (ret)
294 		goto err_wp;
295 
296 	if (gpiomtd->plat.adjust_parts)
297 		gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size);
298 
299 	ret = mtd_device_register(mtd, gpiomtd->plat.parts,
300 				  gpiomtd->plat.num_parts);
301 	if (!ret)
302 		return 0;
303 
304 err_wp:
305 	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
306 		gpiod_set_value(gpiomtd->nwp, 0);
307 out_ce:
308 	if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
309 		gpiod_set_value(gpiomtd->nce, 0);
310 
311 	return ret;
312 }
313 
314 static struct platform_driver gpio_nand_driver = {
315 	.probe		= gpio_nand_probe,
316 	.remove		= gpio_nand_remove,
317 	.driver		= {
318 		.name	= "gpio-nand",
319 		.of_match_table = of_match_ptr(gpio_nand_id_table),
320 	},
321 };
322 
323 module_platform_driver(gpio_nand_driver);
324 
325 MODULE_LICENSE("GPL");
326 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
327 MODULE_DESCRIPTION("GPIO NAND Driver");
328