nfc_at91.c revision 259379
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 <sys/cdefs.h> 36__FBSDID("$FreeBSD: stable/10/sys/dev/nand/nfc_at91.c 259379 2013-12-14 01:15:26Z ian $"); 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/proc.h> 41#include <sys/bus.h> 42#include <sys/conf.h> 43#include <sys/kernel.h> 44#include <sys/module.h> 45#include <sys/malloc.h> 46#include <sys/rman.h> 47#include <sys/lock.h> 48#include <sys/mutex.h> 49#include <sys/time.h> 50 51#include <machine/bus.h> 52 53#include <dev/nand/nand.h> 54#include <dev/nand/nandbus.h> 55#include "nfc_if.h" 56 57/* 58 * Data cycles are triggered by access to any address within the EBI CS3 region 59 * that has A21 and A22 clear. Command cycles are any access with bit A21 60 * asserted. Address cycles are any access with bit A22 asserted. 61 * 62 * XXX The atmel docs say that any address bits can be used instead of A21 and 63 * A22; these values should be configurable. 64 */ 65#define AT91_NAND_DATA 0 66#define AT91_NAND_COMMAND (1 << 21) 67#define AT91_NAND_ADDRESS (1 << 22) 68 69struct at91_nand_softc { 70 struct nand_softc nand_sc; 71 struct resource *res; 72}; 73 74static int at91_nand_attach(device_t); 75static int at91_nand_probe(device_t); 76static uint8_t at91_nand_read_byte(device_t); 77static void at91_nand_read_buf(device_t, void *, uint32_t); 78static int at91_nand_read_rnb(device_t); 79static int at91_nand_select_cs(device_t, uint8_t); 80static int at91_nand_send_command(device_t, uint8_t); 81static int at91_nand_send_address(device_t, uint8_t); 82static void at91_nand_write_buf(device_t, void *, uint32_t); 83 84static inline u_int8_t 85dev_read_1(struct at91_nand_softc *sc, bus_size_t offset) 86{ 87 return bus_read_1(sc->res, offset); 88} 89 90static inline void 91dev_write_1(struct at91_nand_softc *sc, bus_size_t offset, u_int8_t value) 92{ 93 bus_write_1(sc->res, offset, value); 94} 95 96static int 97at91_nand_probe(device_t dev) 98{ 99 100 device_set_desc(dev, "AT91 Integrated NAND controller"); 101 return (BUS_PROBE_DEFAULT); 102} 103 104static int 105at91_nand_attach(device_t dev) 106{ 107 struct at91_nand_softc *sc; 108 int err, rid; 109 110 sc = device_get_softc(dev); 111 rid = 0; 112 sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 113 RF_ACTIVE); 114 if (sc->res == NULL) { 115 device_printf(dev, "could not allocate resources!\n"); 116 return (ENXIO); 117 } 118 119 nand_init(&sc->nand_sc, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); 120 121 err = nandbus_create(dev); 122 123 return (err); 124} 125 126static int 127at91_nand_send_command(device_t dev, uint8_t command) 128{ 129 struct at91_nand_softc *sc; 130 131 /* nand_debug(NDBG_DRV,"at91_nand_send_command: 0x%02x", command); */ 132 133 sc = device_get_softc(dev); 134 dev_write_1(sc, AT91_NAND_COMMAND, command); 135 return (0); 136} 137 138static int 139at91_nand_send_address(device_t dev, uint8_t addr) 140{ 141 struct at91_nand_softc *sc; 142 143 /* nand_debug(NDBG_DRV,"at91_nand_send_address: x%02x", addr); */ 144 145 sc = device_get_softc(dev); 146 dev_write_1(sc, AT91_NAND_ADDRESS, addr); 147 return (0); 148} 149 150static uint8_t 151at91_nand_read_byte(device_t dev) 152{ 153 struct at91_nand_softc *sc; 154 uint8_t data; 155 156 sc = device_get_softc(dev); 157 data = dev_read_1(sc, AT91_NAND_DATA); 158 159 /* nand_debug(NDBG_DRV,"at91_nand_read_byte: 0x%02x", data); */ 160 161 return (data); 162} 163 164 165static void 166at91_nand_dump_buf(const char *op, void* buf, uint32_t len) 167{ 168 int i; 169 uint8_t *b = buf; 170 171 printf("at91_nand_%s_buf (hex):", op); 172 for (i = 0; i < len; i++) { 173 if ((i & 0x01f) == 0) 174 printf("\n"); 175 printf(" %02x", b[i]); 176 } 177 printf("\n"); 178} 179 180static void 181at91_nand_read_buf(device_t dev, void* buf, uint32_t len) 182{ 183 struct at91_nand_softc *sc; 184 185 sc = device_get_softc(dev); 186 187 bus_read_multi_1(sc->res, AT91_NAND_DATA, buf, len); 188 189 if (nand_debug_flag & NDBG_DRV) 190 at91_nand_dump_buf("read", buf, len); 191} 192 193static void 194at91_nand_write_buf(device_t dev, void* buf, uint32_t len) 195{ 196 struct at91_nand_softc *sc; 197 198 sc = device_get_softc(dev); 199 200 if (nand_debug_flag & NDBG_DRV) 201 at91_nand_dump_buf("write", buf, len); 202 203 bus_write_multi_1(sc->res, AT91_NAND_DATA, buf, len); 204} 205 206static int 207at91_nand_select_cs(device_t dev, uint8_t cs) 208{ 209 210 if (cs > 0) 211 return (ENODEV); 212 213 return (0); 214} 215 216static int 217at91_nand_read_rnb(device_t dev) 218{ 219#if 0 220 /* 221 * XXX There's no way for this code to know which GPIO pin (if any) is 222 * attached to the chip's RNB line. Not to worry, nothing calls this; 223 * at higher layers, all the nand code uses status commands. 224 */ 225 uint32_t bits; 226 227 bits = at91_pio_gpio_get(AT91RM92_PIOD_BASE, AT91C_PIO_PD15); 228 nand_debug(NDBG_DRV,"at91_nand: read_rnb: %#x", bits); 229 return (bits != 0); /* ready */ 230#endif 231 panic("at91_nand_read_rnb() is not implemented\n"); 232 return (0); 233} 234 235static device_method_t at91_nand_methods[] = { 236 DEVMETHOD(device_probe, at91_nand_probe), 237 DEVMETHOD(device_attach, at91_nand_attach), 238 239 DEVMETHOD(nfc_send_command, at91_nand_send_command), 240 DEVMETHOD(nfc_send_address, at91_nand_send_address), 241 DEVMETHOD(nfc_read_byte, at91_nand_read_byte), 242 DEVMETHOD(nfc_read_buf, at91_nand_read_buf), 243 DEVMETHOD(nfc_write_buf, at91_nand_write_buf), 244 DEVMETHOD(nfc_select_cs, at91_nand_select_cs), 245 DEVMETHOD(nfc_read_rnb, at91_nand_read_rnb), 246 247 DEVMETHOD_END 248}; 249 250static driver_t at91_nand_driver = { 251 "nand", 252 at91_nand_methods, 253 sizeof(struct at91_nand_softc), 254}; 255 256static devclass_t at91_nand_devclass; 257DRIVER_MODULE(at91_nand, atmelarm, at91_nand_driver, at91_nand_devclass, 0, 0); 258 259