nfc_at91.c revision 266087
1258828Sian/*- 2258828Sian * Copyright (C) 2013 Ian Lepore. 3258828Sian * All rights reserved. 4258828Sian * 5258828Sian * Redistribution and use in source and binary forms, with or without 6258828Sian * modification, are permitted provided that the following conditions 7258828Sian * are met: 8258828Sian * 1. Redistributions of source code must retain the above copyright 9258828Sian * notice, this list of conditions and the following disclaimer. 10258828Sian * 2. Redistributions in binary form must reproduce the above copyright 11258828Sian * notice, this list of conditions and the following disclaimer in the 12258828Sian * documentation and/or other materials provided with the distribution. 13258828Sian * 14258828Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15258828Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16258828Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17258828Sian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18258828Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19258828Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20258828Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21258828Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22258828Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23258828Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24258828Sian * SUCH DAMAGE. 25258828Sian */ 26258828Sian 27258828Sian/* 28258828Sian * Atmel at91-family integrated NAND controller driver. 29258828Sian * 30258828Sian * This code relies on the board setup code (in at91/board_whatever.c) having 31258828Sian * set up the EBI and SMC registers appropriately for whatever type of nand part 32258828Sian * is on the board. 33258828Sian */ 34258828Sian 35258828Sian#include <sys/cdefs.h> 36258828Sian__FBSDID("$FreeBSD: stable/10/sys/dev/nand/nfc_at91.c 266087 2014-05-14 20:31:54Z ian $"); 37258828Sian 38258828Sian#include <sys/param.h> 39258828Sian#include <sys/systm.h> 40258828Sian#include <sys/proc.h> 41258828Sian#include <sys/bus.h> 42258828Sian#include <sys/conf.h> 43258828Sian#include <sys/kernel.h> 44258828Sian#include <sys/module.h> 45258828Sian#include <sys/malloc.h> 46258828Sian#include <sys/rman.h> 47258828Sian#include <sys/lock.h> 48258828Sian#include <sys/mutex.h> 49258828Sian#include <sys/time.h> 50258828Sian 51258828Sian#include <machine/bus.h> 52258828Sian 53258828Sian#include <dev/nand/nand.h> 54258828Sian#include <dev/nand/nandbus.h> 55258828Sian#include "nfc_if.h" 56258828Sian 57266087Sian#include <dev/nand/nfc_at91.h> 58266087Sian#include <arm/at91/at91_smc.h> 59266087Sian 60258828Sian/* 61258828Sian * Data cycles are triggered by access to any address within the EBI CS3 region 62258828Sian * that has A21 and A22 clear. Command cycles are any access with bit A21 63266087Sian * asserted. Address cycles are any access with bit A22 asserted. Or vice versa. 64266087Sian * We get these parameters from the nand_param that the board is required to 65266087Sian * call at91_enable_nand, and enable the GPIO lines properly (that will be moved 66266087Sian * into at91_enable_nand when the great GPIO pin renumbering happens). We use 67266087Sian * ale (Address Latch Enable) and cle (Comand Latch Enable) to match the hardware 68266087Sian * names used in NAND. 69258828Sian */ 70258828Sian#define AT91_NAND_DATA 0 71258828Sian 72258828Sianstruct at91_nand_softc { 73258828Sian struct nand_softc nand_sc; 74258828Sian struct resource *res; 75266087Sian struct at91_nand_params *nand_param; 76258828Sian}; 77258828Sian 78266087Sianstatic struct at91_nand_params nand_param; 79266087Sian 80258828Sianstatic int at91_nand_attach(device_t); 81258828Sianstatic int at91_nand_probe(device_t); 82258828Sianstatic uint8_t at91_nand_read_byte(device_t); 83258828Sianstatic void at91_nand_read_buf(device_t, void *, uint32_t); 84258828Sianstatic int at91_nand_read_rnb(device_t); 85258828Sianstatic int at91_nand_select_cs(device_t, uint8_t); 86258828Sianstatic int at91_nand_send_command(device_t, uint8_t); 87258828Sianstatic int at91_nand_send_address(device_t, uint8_t); 88258828Sianstatic void at91_nand_write_buf(device_t, void *, uint32_t); 89258828Sian 90266087Sianvoid 91266087Sianat91_enable_nand(const struct at91_nand_params *np) 92266087Sian{ 93266087Sian nand_param = *np; 94266087Sian} 95266087Sian 96258828Sianstatic inline u_int8_t 97258828Siandev_read_1(struct at91_nand_softc *sc, bus_size_t offset) 98258828Sian{ 99258828Sian return bus_read_1(sc->res, offset); 100258828Sian} 101258828Sian 102258828Sianstatic inline void 103258828Siandev_write_1(struct at91_nand_softc *sc, bus_size_t offset, u_int8_t value) 104258828Sian{ 105258828Sian bus_write_1(sc->res, offset, value); 106258828Sian} 107258828Sian 108258828Sianstatic int 109258828Sianat91_nand_probe(device_t dev) 110258828Sian{ 111258828Sian 112258828Sian device_set_desc(dev, "AT91 Integrated NAND controller"); 113258828Sian return (BUS_PROBE_DEFAULT); 114258828Sian} 115258828Sian 116258828Sianstatic int 117258828Sianat91_nand_attach(device_t dev) 118258828Sian{ 119258828Sian struct at91_nand_softc *sc; 120258828Sian int err, rid; 121258828Sian 122258828Sian sc = device_get_softc(dev); 123266087Sian sc->nand_param = &nand_param; 124266087Sian if (sc->nand_param->width != 8 && sc->nand_param->width != 16) { 125266087Sian device_printf(dev, "Bad bus width (%d) defaulting to 8 bits\n", 126266087Sian sc->nand_param->width); 127266087Sian sc->nand_param->width = 8; 128266087Sian } 129266087Sian at91_ebi_enable(sc->nand_param->cs); 130266087Sian 131258828Sian rid = 0; 132258828Sian sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 133258828Sian RF_ACTIVE); 134258828Sian if (sc->res == NULL) { 135258828Sian device_printf(dev, "could not allocate resources!\n"); 136258828Sian return (ENXIO); 137258828Sian } 138258828Sian 139258828Sian nand_init(&sc->nand_sc, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); 140258828Sian 141258828Sian err = nandbus_create(dev); 142258828Sian 143258828Sian return (err); 144258828Sian} 145258828Sian 146258828Sianstatic int 147258828Sianat91_nand_send_command(device_t dev, uint8_t command) 148258828Sian{ 149258828Sian struct at91_nand_softc *sc; 150258828Sian 151266087Sian nand_debug(NDBG_DRV,"at91_nand_send_command: 0x%02x", command); 152258828Sian 153258828Sian sc = device_get_softc(dev); 154266087Sian dev_write_1(sc, sc->nand_param->cle, command); 155258828Sian return (0); 156258828Sian} 157258828Sian 158258828Sianstatic int 159258828Sianat91_nand_send_address(device_t dev, uint8_t addr) 160258828Sian{ 161258828Sian struct at91_nand_softc *sc; 162258828Sian 163266087Sian nand_debug(NDBG_DRV,"at91_nand_send_address: x%02x", addr); 164258828Sian 165258828Sian sc = device_get_softc(dev); 166266087Sian dev_write_1(sc, sc->nand_param->ale, addr); 167258828Sian return (0); 168258828Sian} 169258828Sian 170258828Sianstatic uint8_t 171258828Sianat91_nand_read_byte(device_t dev) 172258828Sian{ 173258828Sian struct at91_nand_softc *sc; 174258828Sian uint8_t data; 175258828Sian 176258828Sian sc = device_get_softc(dev); 177258828Sian data = dev_read_1(sc, AT91_NAND_DATA); 178258828Sian 179266087Sian nand_debug(NDBG_DRV,"at91_nand_read_byte: 0x%02x", data); 180258828Sian 181258828Sian return (data); 182258828Sian} 183258828Sian 184258828Sian 185258828Sianstatic void 186258828Sianat91_nand_dump_buf(const char *op, void* buf, uint32_t len) 187258828Sian{ 188258828Sian int i; 189258828Sian uint8_t *b = buf; 190258828Sian 191258828Sian printf("at91_nand_%s_buf (hex):", op); 192258828Sian for (i = 0; i < len; i++) { 193258828Sian if ((i & 0x01f) == 0) 194258828Sian printf("\n"); 195258828Sian printf(" %02x", b[i]); 196258828Sian } 197258828Sian printf("\n"); 198258828Sian} 199258828Sian 200258828Sianstatic void 201258828Sianat91_nand_read_buf(device_t dev, void* buf, uint32_t len) 202258828Sian{ 203258828Sian struct at91_nand_softc *sc; 204258828Sian 205258828Sian sc = device_get_softc(dev); 206258828Sian 207258828Sian bus_read_multi_1(sc->res, AT91_NAND_DATA, buf, len); 208258828Sian 209258828Sian if (nand_debug_flag & NDBG_DRV) 210258828Sian at91_nand_dump_buf("read", buf, len); 211258828Sian} 212258828Sian 213258828Sianstatic void 214258828Sianat91_nand_write_buf(device_t dev, void* buf, uint32_t len) 215258828Sian{ 216258828Sian struct at91_nand_softc *sc; 217258828Sian 218258828Sian sc = device_get_softc(dev); 219258828Sian 220258828Sian if (nand_debug_flag & NDBG_DRV) 221258828Sian at91_nand_dump_buf("write", buf, len); 222258828Sian 223258828Sian bus_write_multi_1(sc->res, AT91_NAND_DATA, buf, len); 224258828Sian} 225258828Sian 226258828Sianstatic int 227258828Sianat91_nand_select_cs(device_t dev, uint8_t cs) 228258828Sian{ 229258828Sian 230258828Sian if (cs > 0) 231258828Sian return (ENODEV); 232258828Sian 233258828Sian return (0); 234258828Sian} 235258828Sian 236258828Sianstatic int 237258828Sianat91_nand_read_rnb(device_t dev) 238258828Sian{ 239258828Sian#if 0 240258828Sian /* 241258828Sian * XXX There's no way for this code to know which GPIO pin (if any) is 242258828Sian * attached to the chip's RNB line. Not to worry, nothing calls this; 243258828Sian * at higher layers, all the nand code uses status commands. 244258828Sian */ 245258828Sian uint32_t bits; 246258828Sian 247258828Sian bits = at91_pio_gpio_get(AT91RM92_PIOD_BASE, AT91C_PIO_PD15); 248258828Sian nand_debug(NDBG_DRV,"at91_nand: read_rnb: %#x", bits); 249258828Sian return (bits != 0); /* ready */ 250258828Sian#endif 251258828Sian panic("at91_nand_read_rnb() is not implemented\n"); 252258828Sian return (0); 253258828Sian} 254258828Sian 255258828Sianstatic device_method_t at91_nand_methods[] = { 256258828Sian DEVMETHOD(device_probe, at91_nand_probe), 257258828Sian DEVMETHOD(device_attach, at91_nand_attach), 258258828Sian 259258828Sian DEVMETHOD(nfc_send_command, at91_nand_send_command), 260258828Sian DEVMETHOD(nfc_send_address, at91_nand_send_address), 261258828Sian DEVMETHOD(nfc_read_byte, at91_nand_read_byte), 262258828Sian DEVMETHOD(nfc_read_buf, at91_nand_read_buf), 263258828Sian DEVMETHOD(nfc_write_buf, at91_nand_write_buf), 264258828Sian DEVMETHOD(nfc_select_cs, at91_nand_select_cs), 265258828Sian DEVMETHOD(nfc_read_rnb, at91_nand_read_rnb), 266258828Sian 267258828Sian DEVMETHOD_END 268258828Sian}; 269258828Sian 270258828Sianstatic driver_t at91_nand_driver = { 271258828Sian "nand", 272258828Sian at91_nand_methods, 273258828Sian sizeof(struct at91_nand_softc), 274258828Sian}; 275258828Sian 276258828Sianstatic devclass_t at91_nand_devclass; 277258828SianDRIVER_MODULE(at91_nand, atmelarm, at91_nand_driver, at91_nand_devclass, 0, 0); 278258828Sian 279