nfc_at91.c revision 266217
1/*- 2 * Copyright (C) 2013 Ian Lepore. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Atmel at91-family integrated NAND controller driver. 29 * 30 * This code relies on the board setup code (in at91/board_whatever.c) having 31 * set up the EBI and SMC registers appropriately for whatever type of nand part 32 * is on the board. 33 */ 34 35#include "opt_platform.h" 36 37#include <sys/cdefs.h> 38__FBSDID("$FreeBSD: stable/10/sys/dev/nand/nfc_at91.c 266217 2014-05-16 12:43:45Z ian $"); 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/proc.h> 43#include <sys/bus.h> 44#include <sys/conf.h> 45#include <sys/kernel.h> 46#include <sys/module.h> 47#include <sys/malloc.h> 48#include <sys/rman.h> 49#include <sys/lock.h> 50#include <sys/mutex.h> 51#include <sys/time.h> 52 53#include <machine/bus.h> 54 55#include <dev/nand/nand.h> 56#include <dev/nand/nandbus.h> 57#include "nfc_if.h" 58 59#include <dev/nand/nfc_at91.h> 60#include <arm/at91/at91_smc.h> 61 62#ifdef FDT 63#include <dev/fdt/fdt_common.h> 64#include <dev/ofw/ofw_bus.h> 65#include <dev/ofw/ofw_bus_subr.h> 66#endif 67 68/* 69 * Data cycles are triggered by access to any address within the EBI CS3 region 70 * that has A21 and A22 clear. Command cycles are any access with bit A21 71 * asserted. Address cycles are any access with bit A22 asserted. Or vice versa. 72 * We get these parameters from the nand_param that the board is required to 73 * call at91_enable_nand, and enable the GPIO lines properly (that will be moved 74 * into at91_enable_nand when the great GPIO pin renumbering happens). We use 75 * ale (Address Latch Enable) and cle (Comand Latch Enable) to match the hardware 76 * names used in NAND. 77 */ 78#define AT91_NAND_DATA 0 79 80struct at91_nand_softc { 81 struct nand_softc nand_sc; 82 struct resource *res; 83 struct at91_nand_params *nand_param; 84}; 85 86static struct at91_nand_params nand_param; 87 88static int at91_nand_attach(device_t); 89static int at91_nand_probe(device_t); 90static uint8_t at91_nand_read_byte(device_t); 91static void at91_nand_read_buf(device_t, void *, uint32_t); 92static int at91_nand_read_rnb(device_t); 93static int at91_nand_select_cs(device_t, uint8_t); 94static int at91_nand_send_command(device_t, uint8_t); 95static int at91_nand_send_address(device_t, uint8_t); 96static void at91_nand_write_buf(device_t, void *, uint32_t); 97 98void 99at91_enable_nand(const struct at91_nand_params *np) 100{ 101 nand_param = *np; 102} 103 104static inline u_int8_t 105dev_read_1(struct at91_nand_softc *sc, bus_size_t offset) 106{ 107 return bus_read_1(sc->res, offset); 108} 109 110static inline void 111dev_write_1(struct at91_nand_softc *sc, bus_size_t offset, u_int8_t value) 112{ 113 bus_write_1(sc->res, offset, value); 114} 115 116static int 117at91_nand_probe(device_t dev) 118{ 119#ifdef FDT 120 if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-nand")) 121 return (ENXIO); 122#endif 123 device_set_desc(dev, "AT91 Integrated NAND controller"); 124 return (BUS_PROBE_DEFAULT); 125} 126 127static int 128at91_nand_attach(device_t dev) 129{ 130 struct at91_nand_softc *sc; 131 int err, rid; 132 133 sc = device_get_softc(dev); 134 sc->nand_param = &nand_param; 135 if (sc->nand_param->width != 8 && sc->nand_param->width != 16) { 136 device_printf(dev, "Bad bus width (%d) defaulting to 8 bits\n", 137 sc->nand_param->width); 138 sc->nand_param->width = 8; 139 } 140 at91_ebi_enable(sc->nand_param->cs); 141 142 rid = 0; 143 sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 144 RF_ACTIVE); 145 if (sc->res == NULL) { 146 device_printf(dev, "could not allocate resources!\n"); 147 return (ENXIO); 148 } 149 150 nand_init(&sc->nand_sc, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); 151 152 err = nandbus_create(dev); 153 154 return (err); 155} 156 157static int 158at91_nand_send_command(device_t dev, uint8_t command) 159{ 160 struct at91_nand_softc *sc; 161 162 nand_debug(NDBG_DRV,"at91_nand_send_command: 0x%02x", command); 163 164 sc = device_get_softc(dev); 165 dev_write_1(sc, sc->nand_param->cle, command); 166 return (0); 167} 168 169static int 170at91_nand_send_address(device_t dev, uint8_t addr) 171{ 172 struct at91_nand_softc *sc; 173 174 nand_debug(NDBG_DRV,"at91_nand_send_address: x%02x", addr); 175 176 sc = device_get_softc(dev); 177 dev_write_1(sc, sc->nand_param->ale, addr); 178 return (0); 179} 180 181static uint8_t 182at91_nand_read_byte(device_t dev) 183{ 184 struct at91_nand_softc *sc; 185 uint8_t data; 186 187 sc = device_get_softc(dev); 188 data = dev_read_1(sc, AT91_NAND_DATA); 189 190 nand_debug(NDBG_DRV,"at91_nand_read_byte: 0x%02x", data); 191 192 return (data); 193} 194 195 196static void 197at91_nand_dump_buf(const char *op, void* buf, uint32_t len) 198{ 199 int i; 200 uint8_t *b = buf; 201 202 printf("at91_nand_%s_buf (hex):", op); 203 for (i = 0; i < len; i++) { 204 if ((i & 0x01f) == 0) 205 printf("\n"); 206 printf(" %02x", b[i]); 207 } 208 printf("\n"); 209} 210 211static void 212at91_nand_read_buf(device_t dev, void* buf, uint32_t len) 213{ 214 struct at91_nand_softc *sc; 215 216 sc = device_get_softc(dev); 217 218 bus_read_multi_1(sc->res, AT91_NAND_DATA, buf, len); 219 220 if (nand_debug_flag & NDBG_DRV) 221 at91_nand_dump_buf("read", buf, len); 222} 223 224static void 225at91_nand_write_buf(device_t dev, void* buf, uint32_t len) 226{ 227 struct at91_nand_softc *sc; 228 229 sc = device_get_softc(dev); 230 231 if (nand_debug_flag & NDBG_DRV) 232 at91_nand_dump_buf("write", buf, len); 233 234 bus_write_multi_1(sc->res, AT91_NAND_DATA, buf, len); 235} 236 237static int 238at91_nand_select_cs(device_t dev, uint8_t cs) 239{ 240 241 if (cs > 0) 242 return (ENODEV); 243 244 return (0); 245} 246 247static int 248at91_nand_read_rnb(device_t dev) 249{ 250#if 0 251 /* 252 * XXX There's no way for this code to know which GPIO pin (if any) is 253 * attached to the chip's RNB line. Not to worry, nothing calls this; 254 * at higher layers, all the nand code uses status commands. 255 */ 256 uint32_t bits; 257 258 bits = at91_pio_gpio_get(AT91RM92_PIOD_BASE, AT91C_PIO_PD15); 259 nand_debug(NDBG_DRV,"at91_nand: read_rnb: %#x", bits); 260 return (bits != 0); /* ready */ 261#endif 262 panic("at91_nand_read_rnb() is not implemented\n"); 263 return (0); 264} 265 266static device_method_t at91_nand_methods[] = { 267 DEVMETHOD(device_probe, at91_nand_probe), 268 DEVMETHOD(device_attach, at91_nand_attach), 269 270 DEVMETHOD(nfc_send_command, at91_nand_send_command), 271 DEVMETHOD(nfc_send_address, at91_nand_send_address), 272 DEVMETHOD(nfc_read_byte, at91_nand_read_byte), 273 DEVMETHOD(nfc_read_buf, at91_nand_read_buf), 274 DEVMETHOD(nfc_write_buf, at91_nand_write_buf), 275 DEVMETHOD(nfc_select_cs, at91_nand_select_cs), 276 DEVMETHOD(nfc_read_rnb, at91_nand_read_rnb), 277 278 DEVMETHOD_END 279}; 280 281static driver_t at91_nand_driver = { 282 "nand", 283 at91_nand_methods, 284 sizeof(struct at91_nand_softc), 285}; 286 287static devclass_t at91_nand_devclass; 288 289#ifdef FDT 290DRIVER_MODULE(at91_nand, simplebus, at91_nand_driver, at91_nand_devclass, 0, 0); 291#else 292DRIVER_MODULE(at91_nand, atmelarm, at91_nand_driver, at91_nand_devclass, 0, 0); 293#endif 294