at91_cfata.c revision 256281
1263508Sdim/*- 2249259Sdim * Copyright (c) 2008 Deglitch Networks, Stanislav Sedov 3249259Sdim * All rights reserved. 4249259Sdim * 5249259Sdim * Redistribution and use in source and binary forms, with or without 6249259Sdim * modification, are permitted provided that the following conditions 7249259Sdim * are met: 8249259Sdim * 1. Redistributions of source code must retain the above copyright 9249259Sdim * notice, this list of conditions and the following disclaimer. 10249259Sdim * 2. Redistributions in binary form must reproduce the above copyright 11249259Sdim * notice, this list of conditions and the following disclaimer in the 12249259Sdim * documentation and/or other materials provided with the distribution. 13249259Sdim * 14249259Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15249259Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16249259Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17249259Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18249259Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19249259Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20249259Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21249259Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22249259Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23249259Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24249259Sdim * 25249259Sdim * Driver for the AT91RM9200 CompactFlash controller operating in a 26249259Sdim * common memory mode. Interrupts are driven by polling. The driver 27249259Sdim * implements an ATA bridge and attached ATA channel driver on top 28249259Sdim * of it. 29249259Sdim * NOTE WELL: this driver uses polling mode. To achive an acceptable 30249259Sdim * operating speed you will probably want to use HZ=2000 in kernel 31249259Sdim * config. 32249259Sdim */ 33249259Sdim 34249259Sdim#include <sys/cdefs.h> 35249259Sdim__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91_cfata.c 193934 2009-06-10 17:39:19Z imp $"); 36249259Sdim 37249259Sdim#include <sys/param.h> 38249259Sdim#include <sys/systm.h> 39249259Sdim#include <sys/kernel.h> 40249259Sdim#include <sys/module.h> 41249259Sdim#include <sys/time.h> 42249259Sdim#include <sys/bus.h> 43249259Sdim#include <sys/resource.h> 44249259Sdim#include <sys/rman.h> 45249259Sdim#include <sys/sema.h> 46249259Sdim#include <sys/taskqueue.h> 47249259Sdim#include <vm/uma.h> 48249259Sdim 49249259Sdim#include <machine/bus.h> 50249259Sdim#include <machine/cpu.h> 51249259Sdim#include <machine/cpufunc.h> 52249259Sdim#include <machine/resource.h> 53249259Sdim#include <machine/intr.h> 54249259Sdim 55249259Sdim#include <sys/ata.h> 56249259Sdim#include <dev/ata/ata-all.h> 57249259Sdim#include <ata_if.h> 58249259Sdim 59249259Sdimstruct at91_cfata_softc { 60249259Sdim device_t dev; 61249259Sdim struct resource *mem_res; 62249259Sdim struct resource irq; 63249259Sdim void (*isr_cb)(void *); 64249259Sdim void *isr_arg; 65249259Sdim struct callout tick; 66249259Sdim}; 67249259Sdim 68249259Sdimstatic int at91_cfata_detach(device_t dev); 69249259Sdimstatic void at91_cfata_callout(void *arg); 70249259Sdim 71249259Sdimstatic int 72249259Sdimat91_cfata_probe(device_t dev) 73249259Sdim{ 74249259Sdim 75249259Sdim device_set_desc_copy(dev, "AT91RM9200 CompactFlash controller"); 76249259Sdim return (0); 77249259Sdim} 78249259Sdim 79249259Sdimstatic int 80249259Sdimat91_cfata_attach(device_t dev) 81{ 82 struct at91_cfata_softc *sc; 83 int rid, error; 84 85 sc = device_get_softc(dev); 86 sc->dev = dev; 87 rid = 0; 88 error = 0; 89 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 90 RF_ACTIVE); 91 if (sc->mem_res == NULL) 92 return (ENOMEM); 93 94 /* XXX: init CF controller? */ 95 96 callout_init(&sc->tick, 1); /* Callout to poll the device. */ 97 device_add_child(dev, "ata", -1); 98 bus_generic_attach(dev); 99 return (0); 100} 101 102static int 103at91_cfata_detach(device_t dev) 104{ 105 struct at91_cfata_softc *sc; 106 107 sc = device_get_softc(dev); 108 bus_generic_detach(sc->dev); 109 if (sc->mem_res != NULL) { 110 bus_release_resource(dev, SYS_RES_MEMORY, 111 rman_get_rid(sc->mem_res), sc->mem_res); 112 sc->mem_res = NULL; 113 } 114 return (0); 115} 116 117static struct resource * 118ata_at91_alloc_resource(device_t dev, device_t child, int type, int *rid, 119 u_long start, u_long end, u_long count, u_int flags) 120{ 121 struct at91_cfata_softc *sc = device_get_softc(dev); 122 123 KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID, 124 ("[at91_cfata, %d]: illegal resource request (type %u rid %u)", 125 __LINE__, type, *rid)); 126 return (&sc->irq); 127} 128 129static int 130ata_at91_release_resource(device_t dev, device_t child, int type, int rid, 131 struct resource *r) 132{ 133 134 KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID, 135 ("[at91_cfata, %d]: illegal resource request (type %u rid %u)", 136 __LINE__, type, rid)); 137 return (0); 138} 139 140 141static int 142ata_at91_setup_intr(device_t dev, device_t child, struct resource *irq, 143 int flags, driver_filter_t *filt, 144 driver_intr_t *function, void *argument, void **cookiep) 145{ 146 struct at91_cfata_softc *sc = device_get_softc(dev); 147 148 KASSERT(sc->isr_cb == NULL, 149 ("[at91_cfata, %d]: overwriting the old handler", __LINE__)); 150 sc->isr_cb = function; 151 sc->isr_arg = argument; 152 *cookiep = sc; 153 callout_reset(&sc->tick, 1, at91_cfata_callout, sc); 154 return (0); 155} 156 157static int 158ata_at91_teardown_intr(device_t dev, device_t child, struct resource *irq, 159 void *cookie) 160{ 161 struct at91_cfata_softc *sc = device_get_softc(dev); 162 163 sc->isr_cb = NULL; 164 sc->isr_arg = NULL; 165 return (0); 166} 167 168static void 169at91_cfata_callout(void *arg) 170{ 171 struct at91_cfata_softc *sc; 172 173 sc = (struct at91_cfata_softc *)arg; 174 if (sc->isr_cb != NULL) 175 sc->isr_cb(sc->isr_arg); 176 callout_reset(&sc->tick, 1, at91_cfata_callout, sc); 177} 178 179static int 180at91_channel_probe(device_t dev) 181{ 182 struct ata_channel *ch = device_get_softc(dev); 183 184 ch->unit = 0; 185 ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE; 186 device_set_desc_copy(dev, "ATA channel 0"); 187 188 return (ata_probe(dev)); 189} 190 191static int 192at91_channel_attach(device_t dev) 193{ 194 struct at91_cfata_softc *sc = device_get_softc(device_get_parent(dev)); 195 struct ata_channel *ch = device_get_softc(dev); 196 int i; 197 198 for (i = 0; i < ATA_MAX_RES; i++) 199 ch->r_io[i].res = sc->mem_res; 200 201 /* 202 * CF+ Specification. 203 * 6.1.3 Memory Mapped Addressing. 204 */ 205 ch->r_io[ATA_DATA].offset = 0x00; 206 ch->r_io[ATA_FEATURE].offset = 0x01; 207 ch->r_io[ATA_COUNT].offset = 0x02; 208 ch->r_io[ATA_SECTOR].offset = 0x03; 209 ch->r_io[ATA_CYL_LSB].offset = 0x04; 210 ch->r_io[ATA_CYL_MSB].offset = 0x05; 211 ch->r_io[ATA_DRIVE].offset = 0x06; 212 ch->r_io[ATA_COMMAND].offset = 0x07; 213 ch->r_io[ATA_ERROR].offset = 0x01; 214 ch->r_io[ATA_IREASON].offset = 0x02; 215 ch->r_io[ATA_STATUS].offset = 0x07; 216 ch->r_io[ATA_ALTSTAT].offset = 0x0e; 217 ch->r_io[ATA_CONTROL].offset = 0x0e; 218 219 /* Should point at the base of registers. */ 220 ch->r_io[ATA_IDX_ADDR].offset = 0x0; 221 222 ata_generic_hw(dev); 223 return (ata_attach(dev)); 224} 225 226static device_method_t at91_cfata_methods[] = { 227 /* Device interface. */ 228 DEVMETHOD(device_probe, at91_cfata_probe), 229 DEVMETHOD(device_attach, at91_cfata_attach), 230 DEVMETHOD(device_detach, at91_cfata_detach), 231 DEVMETHOD(device_shutdown, bus_generic_shutdown), 232 DEVMETHOD(device_suspend, bus_generic_suspend), 233 DEVMETHOD(device_resume, bus_generic_resume), 234 235 /* ATA bus methods. */ 236 DEVMETHOD(bus_alloc_resource, ata_at91_alloc_resource), 237 DEVMETHOD(bus_release_resource, ata_at91_release_resource), 238 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 239 DEVMETHOD(bus_deactivate_resource, 240 bus_generic_deactivate_resource), 241 DEVMETHOD(bus_setup_intr, ata_at91_setup_intr), 242 DEVMETHOD(bus_teardown_intr, ata_at91_teardown_intr), 243 244 { 0, 0 } 245}; 246 247devclass_t at91_cfata_devclass; 248 249static driver_t at91_cfata_driver = { 250 "at91_cfata", 251 at91_cfata_methods, 252 sizeof(struct at91_cfata_softc), 253}; 254 255DRIVER_MODULE(at91_cfata, atmelarm, at91_cfata_driver, at91_cfata_devclass, 0, 256 0); 257MODULE_VERSION(at91_cfata, 1); 258MODULE_DEPEND(at91_cfata, ata, 1, 1, 1); 259 260/* 261 * ATA channel driver. 262 */ 263static device_method_t at91_channel_methods[] = { 264 /* device interface */ 265 DEVMETHOD(device_probe, at91_channel_probe), 266 DEVMETHOD(device_attach, at91_channel_attach), 267 DEVMETHOD(device_detach, ata_detach), 268 DEVMETHOD(device_shutdown, bus_generic_shutdown), 269 DEVMETHOD(device_suspend, ata_suspend), 270 DEVMETHOD(device_resume, ata_resume), 271 272 { 0, 0 } 273}; 274 275driver_t at91_channel_driver = { 276 "ata", 277 at91_channel_methods, 278 sizeof(struct ata_channel), 279}; 280 281DRIVER_MODULE(ata, at91_cfata, at91_channel_driver, ata_devclass, 0, 0); 282