1282430Sjhibbits/*-
2282430Sjhibbits * Copyright (C) 2015 Justin Hibbits
3282430Sjhibbits * All rights reserved.
4282430Sjhibbits *
5282430Sjhibbits * Redistribution and use in source and binary forms, with or without
6282430Sjhibbits * modification, are permitted provided that the following conditions
7282430Sjhibbits * are met:
8282430Sjhibbits * 1. Redistributions of source code must retain the above copyright
9282430Sjhibbits *    notice, this list of conditions and the following disclaimer.
10282430Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright
11282430Sjhibbits *    notice, this list of conditions and the following disclaimer in the
12282430Sjhibbits *    documentation and/or other materials provided with the distribution.
13282430Sjhibbits *
14282430Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15282430Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16282430Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17282430Sjhibbits * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18282430Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19282430Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20282430Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21282430Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22282430Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23282430Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24282430Sjhibbits * SUCH DAMAGE.
25282430Sjhibbits */
26282430Sjhibbits
27282430Sjhibbits/* RouterBoard 600/800 NAND controller driver. */
28282430Sjhibbits
29282430Sjhibbits#include <sys/cdefs.h>
30282430Sjhibbits__FBSDID("$FreeBSD: releng/11.0/sys/dev/nand/nfc_rb.c 286299 2015-08-05 01:52:52Z jhibbits $");
31282430Sjhibbits
32282430Sjhibbits#include <sys/param.h>
33282430Sjhibbits#include <sys/systm.h>
34282430Sjhibbits#include <sys/bus.h>
35282430Sjhibbits#include <sys/kernel.h>
36282430Sjhibbits#include <sys/module.h>
37282430Sjhibbits#include <sys/malloc.h>
38282430Sjhibbits#include <sys/rman.h>
39282430Sjhibbits
40282430Sjhibbits#include <machine/bus.h>
41282430Sjhibbits
42282430Sjhibbits#include <dev/ofw/ofw_bus.h>
43282430Sjhibbits#include <dev/ofw/ofw_bus_subr.h>
44282430Sjhibbits
45282430Sjhibbits#include <dev/nand/nand.h>
46282430Sjhibbits#include <dev/nand/nandbus.h>
47284083Sjhibbits
48284083Sjhibbits#include <powerpc/mpc85xx/mpc85xx.h>
49284083Sjhibbits
50282430Sjhibbits#include "nfc_if.h"
51282430Sjhibbits#include "gpio_if.h"
52282430Sjhibbits
53282430Sjhibbits#define RB_NAND_DATA	(0x00)
54282430Sjhibbits
55282430Sjhibbitsstruct rb_nand_softc {
56282430Sjhibbits	struct nand_softc 	nand_dev;
57282430Sjhibbits	struct resource		*sc_mem;
58282430Sjhibbits	int			rid;
59282430Sjhibbits	device_t		sc_gpio;
60282430Sjhibbits	uint32_t		sc_rdy_pin;
61282430Sjhibbits	uint32_t		sc_nce_pin;
62282430Sjhibbits	uint32_t		sc_cle_pin;
63282430Sjhibbits	uint32_t		sc_ale_pin;
64282430Sjhibbits};
65282430Sjhibbits
66282430Sjhibbitsstatic int	rb_nand_attach(device_t);
67282430Sjhibbitsstatic int	rb_nand_probe(device_t);
68282430Sjhibbitsstatic int	rb_nand_send_command(device_t, uint8_t);
69282430Sjhibbitsstatic int	rb_nand_send_address(device_t, uint8_t);
70282430Sjhibbitsstatic uint8_t	rb_nand_read_byte(device_t);
71282430Sjhibbitsstatic void	rb_nand_read_buf(device_t, void *, uint32_t);
72282430Sjhibbitsstatic void	rb_nand_write_buf(device_t, void *, uint32_t);
73282430Sjhibbitsstatic int	rb_nand_select_cs(device_t, uint8_t);
74282430Sjhibbitsstatic int	rb_nand_read_rnb(device_t);
75282430Sjhibbits
76282430Sjhibbitsstatic device_method_t rb_nand_methods[] = {
77282430Sjhibbits	DEVMETHOD(device_probe,		rb_nand_probe),
78282430Sjhibbits	DEVMETHOD(device_attach,	rb_nand_attach),
79282430Sjhibbits
80282430Sjhibbits	DEVMETHOD(nfc_send_command,	rb_nand_send_command),
81282430Sjhibbits	DEVMETHOD(nfc_send_address,	rb_nand_send_address),
82282430Sjhibbits	DEVMETHOD(nfc_read_byte,	rb_nand_read_byte),
83282430Sjhibbits	DEVMETHOD(nfc_read_buf,		rb_nand_read_buf),
84282430Sjhibbits	DEVMETHOD(nfc_write_buf,	rb_nand_write_buf),
85282430Sjhibbits	DEVMETHOD(nfc_select_cs,	rb_nand_select_cs),
86282430Sjhibbits	DEVMETHOD(nfc_read_rnb,		rb_nand_read_rnb),
87282430Sjhibbits
88282430Sjhibbits	{ 0, 0 },
89282430Sjhibbits};
90282430Sjhibbits
91282430Sjhibbitsstatic driver_t rb_nand_driver = {
92282430Sjhibbits	"nand",
93282430Sjhibbits	rb_nand_methods,
94282430Sjhibbits	sizeof(struct rb_nand_softc),
95282430Sjhibbits};
96282430Sjhibbits
97282430Sjhibbitsstatic devclass_t rb_nand_devclass;
98282430SjhibbitsDRIVER_MODULE(rb_nand, ofwbus, rb_nand_driver, rb_nand_devclass, 0, 0);
99282430Sjhibbits
100282430Sjhibbits#if 0
101282430Sjhibbitsstatic const struct nand_ecc_data rb_ecc = {
102282430Sjhibbits	.eccsize = 6,
103282430Sjhibbits	.eccmode = NAND_ECC_SOFT,
104282430Sjhibbits	.eccbytes = 6,
105282430Sjhibbits	.eccpositions = { 8, 9, 10, 13, 14, 15 },
106282430Sjhibbits};
107282430Sjhibbits#endif
108282430Sjhibbits
109282430Sjhibbitsstatic int
110282430Sjhibbitsrb_nand_probe(device_t dev)
111282430Sjhibbits{
112282430Sjhibbits	const char *device_type;
113282430Sjhibbits
114282430Sjhibbits	device_type = ofw_bus_get_type(dev);
115282430Sjhibbits
116282430Sjhibbits	if (!device_type || strcmp(device_type, "rb,nand"))
117282430Sjhibbits		return (ENXIO);
118282430Sjhibbits
119282430Sjhibbits	device_set_desc(dev, "RouterBoard 333/600/800 NAND controller");
120282430Sjhibbits	return (BUS_PROBE_DEFAULT);
121282430Sjhibbits}
122282430Sjhibbits
123282430Sjhibbitsstatic int
124282430Sjhibbitsrb_nand_attach(device_t dev)
125282430Sjhibbits{
126282430Sjhibbits	struct rb_nand_softc *sc;
127282430Sjhibbits	phandle_t node;
128282430Sjhibbits	uint32_t ale[2],cle[2],nce[2],rdy[2];
129284083Sjhibbits	u_long size,start;
130282430Sjhibbits	int err;
131282430Sjhibbits
132282430Sjhibbits	sc = device_get_softc(dev);
133282430Sjhibbits	node = ofw_bus_get_node(dev);
134282430Sjhibbits
135282430Sjhibbits	if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) {
136282430Sjhibbits		return (ENXIO);
137282430Sjhibbits	}
138282430Sjhibbits	if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) {
139282430Sjhibbits		return (ENXIO);
140282430Sjhibbits	}
141282430Sjhibbits	if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) {
142282430Sjhibbits		return (ENXIO);
143282430Sjhibbits	}
144282430Sjhibbits	if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) {
145282430Sjhibbits		return (ENXIO);
146282430Sjhibbits	}
147282430Sjhibbits
148282430Sjhibbits	if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) {
149282430Sjhibbits		device_printf(dev, "GPIO handles for signals must match.\n");
150282430Sjhibbits		return (ENXIO);
151282430Sjhibbits	}
152282430Sjhibbits	sc->sc_ale_pin = ale[1];
153282430Sjhibbits	sc->sc_cle_pin = cle[1];
154282430Sjhibbits	sc->sc_nce_pin = nce[1];
155282430Sjhibbits	sc->sc_rdy_pin = rdy[1];
156282430Sjhibbits
157282430Sjhibbits	sc->sc_gpio = OF_device_from_xref(ale[0]);
158282430Sjhibbits	if (sc->sc_gpio == NULL) {
159282430Sjhibbits		device_printf(dev, "No GPIO resource found!\n");
160282430Sjhibbits		return (ENXIO);
161282430Sjhibbits	}
162282430Sjhibbits
163282430Sjhibbits	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
164282430Sjhibbits	    RF_ACTIVE);
165282430Sjhibbits	if (sc->sc_mem == NULL) {
166282430Sjhibbits		device_printf(dev, "could not allocate resources!\n");
167282430Sjhibbits		return (ENXIO);
168282430Sjhibbits	}
169282430Sjhibbits
170284083Sjhibbits	start = rman_get_start(sc->sc_mem);
171284083Sjhibbits	size = rman_get_size(sc->sc_mem);
172284083Sjhibbits	if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) {
173284083Sjhibbits		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem);
174284083Sjhibbits		device_printf(dev, "could not allocate local address window.\n");
175284083Sjhibbits		return (ENXIO);
176284083Sjhibbits	}
177284083Sjhibbits
178282430Sjhibbits	nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
179282430Sjhibbits
180282430Sjhibbits	err = nandbus_create(dev);
181282430Sjhibbits
182282430Sjhibbits	return (err);
183282430Sjhibbits}
184282430Sjhibbits
185282430Sjhibbitsstatic int
186282430Sjhibbitsrb_nand_send_command(device_t dev, uint8_t command)
187282430Sjhibbits{
188282430Sjhibbits	struct rb_nand_softc *sc;
189282430Sjhibbits
190282430Sjhibbits	nand_debug(NDBG_DRV,"rb_nand: send command %x", command);
191282430Sjhibbits
192282430Sjhibbits	sc = device_get_softc(dev);
193282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 1);
194282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
195282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
196282430Sjhibbits	bus_write_1(sc->sc_mem, RB_NAND_DATA, command);
197282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
198282430Sjhibbits	return (0);
199282430Sjhibbits}
200282430Sjhibbits
201282430Sjhibbitsstatic int
202282430Sjhibbitsrb_nand_send_address(device_t dev, uint8_t addr)
203282430Sjhibbits{
204282430Sjhibbits	struct rb_nand_softc *sc;
205282430Sjhibbits
206282430Sjhibbits	nand_debug(NDBG_DRV,"rb_nand: send address %x", addr);
207282430Sjhibbits
208282430Sjhibbits	sc = device_get_softc(dev);
209282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
210282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 1);
211282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
212282430Sjhibbits	bus_write_1(sc->sc_mem, RB_NAND_DATA, addr);
213282430Sjhibbits	GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
214282430Sjhibbits	return (0);
215282430Sjhibbits}
216282430Sjhibbits
217282430Sjhibbitsstatic uint8_t
218282430Sjhibbitsrb_nand_read_byte(device_t dev)
219282430Sjhibbits{
220282430Sjhibbits	struct rb_nand_softc *sc;
221282430Sjhibbits	uint8_t data;
222282430Sjhibbits
223282430Sjhibbits	sc = device_get_softc(dev);
224282430Sjhibbits	data = bus_read_1(sc->sc_mem, RB_NAND_DATA);
225282430Sjhibbits
226282430Sjhibbits	nand_debug(NDBG_DRV,"rb_nand: read %x", data);
227282430Sjhibbits
228282430Sjhibbits	return (data);
229282430Sjhibbits}
230282430Sjhibbits
231282430Sjhibbitsstatic void
232282430Sjhibbitsrb_nand_read_buf(device_t dev, void* buf, uint32_t len)
233282430Sjhibbits{
234282430Sjhibbits	struct rb_nand_softc *sc;
235282430Sjhibbits
236282430Sjhibbits	sc = device_get_softc(dev);
237282430Sjhibbits
238282430Sjhibbits	bus_read_region_1(sc->sc_mem, RB_NAND_DATA, buf, len);
239282430Sjhibbits}
240282430Sjhibbits
241282430Sjhibbitsstatic void
242282430Sjhibbitsrb_nand_write_buf(device_t dev, void* buf, uint32_t len)
243282430Sjhibbits{
244282430Sjhibbits	struct rb_nand_softc *sc;
245282430Sjhibbits	int i;
246282430Sjhibbits	uint8_t *b = (uint8_t*)buf;
247282430Sjhibbits
248282430Sjhibbits	sc = device_get_softc(dev);
249282430Sjhibbits
250282430Sjhibbits	for (i = 0; i < len; i++) {
251282430Sjhibbits#ifdef NAND_DEBUG
252282430Sjhibbits		if (!(i % 16))
253282430Sjhibbits			printf("%s", i == 0 ? "rb_nand:\n" : "\n");
254282430Sjhibbits		printf(" %x", b[i]);
255282430Sjhibbits		if (i == len - 1)
256282430Sjhibbits			printf("\n");
257282430Sjhibbits#endif
258282430Sjhibbits		bus_write_1(sc->sc_mem, RB_NAND_DATA, b[i]);
259282430Sjhibbits	}
260282430Sjhibbits}
261282430Sjhibbits
262282430Sjhibbitsstatic int
263282430Sjhibbitsrb_nand_select_cs(device_t dev, uint8_t cs)
264282430Sjhibbits{
265282430Sjhibbits
266282430Sjhibbits	if (cs > 0)
267282430Sjhibbits		return (ENODEV);
268282430Sjhibbits
269282430Sjhibbits	return (0);
270282430Sjhibbits}
271282430Sjhibbits
272282430Sjhibbitsstatic int
273282430Sjhibbitsrb_nand_read_rnb(device_t dev)
274282430Sjhibbits{
275282430Sjhibbits	struct rb_nand_softc *sc;
276282430Sjhibbits	uint32_t rdy_bit;
277282430Sjhibbits
278282430Sjhibbits	sc = device_get_softc(dev);
279282430Sjhibbits	GPIO_PIN_GET(sc->sc_gpio, sc->sc_rdy_pin, &rdy_bit);
280282430Sjhibbits
281282430Sjhibbits	return (rdy_bit); /* ready */
282282430Sjhibbits}
283