1/*- 2 * Copyright (c) 2008 Deglitch Networks, Stanislav Sedov 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 ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * Driver for the AT91RM9200 CompactFlash controller operating in a 26 * common memory mode. Interrupts are driven by polling. The driver 27 * implements an ATA bridge and attached ATA channel driver on top 28 * of it. 29 * NOTE WELL: this driver uses polling mode. To achieve an acceptable 30 * operating speed you will probably want to use HZ=2000 in kernel 31 * config. 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/11/sys/arm/at91/at91_cfata.c 308325 2016-11-05 04:30:44Z mmel $"); 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40#include <sys/module.h> 41#include <sys/time.h> 42#include <sys/bus.h> 43#include <sys/resource.h> 44#include <sys/rman.h> 45#include <sys/sema.h> 46#include <sys/taskqueue.h> 47#include <vm/uma.h> 48 49#include <machine/bus.h> 50#include <machine/resource.h> 51#include <machine/intr.h> 52 53#include <sys/ata.h> 54#include <dev/ata/ata-all.h> 55#include <ata_if.h> 56 57struct at91_cfata_softc { 58 device_t dev; 59 struct resource *mem_res; 60 struct resource irq; 61 void (*isr_cb)(void *); 62 void *isr_arg; 63 struct callout tick; 64}; 65 66static int at91_cfata_detach(device_t dev); 67static void at91_cfata_callout(void *arg); 68 69static int 70at91_cfata_probe(device_t dev) 71{ 72 73 device_set_desc_copy(dev, "AT91RM9200 CompactFlash controller"); 74 return (0); 75} 76 77static int 78at91_cfata_attach(device_t dev) 79{ 80 struct at91_cfata_softc *sc; 81 int rid, error; 82 83 sc = device_get_softc(dev); 84 sc->dev = dev; 85 rid = 0; 86 error = 0; 87 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 88 RF_ACTIVE); 89 if (sc->mem_res == NULL) 90 return (ENOMEM); 91 92 /* XXX: init CF controller? */ 93 94 callout_init(&sc->tick, 1); /* Callout to poll the device. */ 95 device_add_child(dev, "ata", -1); 96 bus_generic_attach(dev); 97 return (0); 98} 99 100static int 101at91_cfata_detach(device_t dev) 102{ 103 struct at91_cfata_softc *sc; 104 105 sc = device_get_softc(dev); 106 bus_generic_detach(sc->dev); 107 if (sc->mem_res != NULL) { 108 bus_release_resource(dev, SYS_RES_MEMORY, 109 rman_get_rid(sc->mem_res), sc->mem_res); 110 sc->mem_res = NULL; 111 } 112 return (0); 113} 114 115static struct resource * 116ata_at91_alloc_resource(device_t dev, device_t child, int type, int *rid, 117 u_long start, u_long end, u_long count, u_int flags) 118{ 119 struct at91_cfata_softc *sc = device_get_softc(dev); 120 121 KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID, 122 ("[at91_cfata, %d]: illegal resource request (type %u rid %u)", 123 __LINE__, type, *rid)); 124 return (&sc->irq); 125} 126 127static int 128ata_at91_release_resource(device_t dev, device_t child, int type, int rid, 129 struct resource *r) 130{ 131 132 KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID, 133 ("[at91_cfata, %d]: illegal resource request (type %u rid %u)", 134 __LINE__, type, rid)); 135 return (0); 136} 137 138 139static int 140ata_at91_setup_intr(device_t dev, device_t child, struct resource *irq, 141 int flags, driver_filter_t *filt, 142 driver_intr_t *function, void *argument, void **cookiep) 143{ 144 struct at91_cfata_softc *sc = device_get_softc(dev); 145 146 KASSERT(sc->isr_cb == NULL, 147 ("[at91_cfata, %d]: overwriting the old handler", __LINE__)); 148 sc->isr_cb = function; 149 sc->isr_arg = argument; 150 *cookiep = sc; 151 callout_reset(&sc->tick, 1, at91_cfata_callout, sc); 152 return (0); 153} 154 155static int 156ata_at91_teardown_intr(device_t dev, device_t child, struct resource *irq, 157 void *cookie) 158{ 159 struct at91_cfata_softc *sc = device_get_softc(dev); 160 161 sc->isr_cb = NULL; 162 sc->isr_arg = NULL; 163 return (0); 164} 165 166static void 167at91_cfata_callout(void *arg) 168{ 169 struct at91_cfata_softc *sc; 170 171 sc = (struct at91_cfata_softc *)arg; 172 if (sc->isr_cb != NULL) 173 sc->isr_cb(sc->isr_arg); 174 callout_reset(&sc->tick, 1, at91_cfata_callout, sc); 175} 176 177static int 178at91_channel_probe(device_t dev) 179{ 180 struct ata_channel *ch = device_get_softc(dev); 181 182 ch->unit = 0; 183 ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE; 184 device_set_desc_copy(dev, "ATA channel 0"); 185 186 return (ata_probe(dev)); 187} 188 189static int 190at91_channel_attach(device_t dev) 191{ 192 struct at91_cfata_softc *sc = device_get_softc(device_get_parent(dev)); 193 struct ata_channel *ch = device_get_softc(dev); 194 int i; 195 196 for (i = 0; i < ATA_MAX_RES; i++) 197 ch->r_io[i].res = sc->mem_res; 198 199 /* 200 * CF+ Specification. 201 * 6.1.3 Memory Mapped Addressing. 202 */ 203 ch->r_io[ATA_DATA].offset = 0x00; 204 ch->r_io[ATA_FEATURE].offset = 0x01; 205 ch->r_io[ATA_COUNT].offset = 0x02; 206 ch->r_io[ATA_SECTOR].offset = 0x03; 207 ch->r_io[ATA_CYL_LSB].offset = 0x04; 208 ch->r_io[ATA_CYL_MSB].offset = 0x05; 209 ch->r_io[ATA_DRIVE].offset = 0x06; 210 ch->r_io[ATA_COMMAND].offset = 0x07; 211 ch->r_io[ATA_ERROR].offset = 0x01; 212 ch->r_io[ATA_IREASON].offset = 0x02; 213 ch->r_io[ATA_STATUS].offset = 0x07; 214 ch->r_io[ATA_ALTSTAT].offset = 0x0e; 215 ch->r_io[ATA_CONTROL].offset = 0x0e; 216 217 /* Should point at the base of registers. */ 218 ch->r_io[ATA_IDX_ADDR].offset = 0x0; 219 220 ata_generic_hw(dev); 221 return (ata_attach(dev)); 222} 223 224static device_method_t at91_cfata_methods[] = { 225 /* Device interface. */ 226 DEVMETHOD(device_probe, at91_cfata_probe), 227 DEVMETHOD(device_attach, at91_cfata_attach), 228 DEVMETHOD(device_detach, at91_cfata_detach), 229 DEVMETHOD(device_shutdown, bus_generic_shutdown), 230 DEVMETHOD(device_suspend, bus_generic_suspend), 231 DEVMETHOD(device_resume, bus_generic_resume), 232 233 /* ATA bus methods. */ 234 DEVMETHOD(bus_alloc_resource, ata_at91_alloc_resource), 235 DEVMETHOD(bus_release_resource, ata_at91_release_resource), 236 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 237 DEVMETHOD(bus_deactivate_resource, 238 bus_generic_deactivate_resource), 239 DEVMETHOD(bus_setup_intr, ata_at91_setup_intr), 240 DEVMETHOD(bus_teardown_intr, ata_at91_teardown_intr), 241 242 { 0, 0 } 243}; 244 245devclass_t at91_cfata_devclass; 246 247static driver_t at91_cfata_driver = { 248 "at91_cfata", 249 at91_cfata_methods, 250 sizeof(struct at91_cfata_softc), 251}; 252 253DRIVER_MODULE(at91_cfata, atmelarm, at91_cfata_driver, at91_cfata_devclass, 0, 254 0); 255MODULE_VERSION(at91_cfata, 1); 256MODULE_DEPEND(at91_cfata, ata, 1, 1, 1); 257 258/* 259 * ATA channel driver. 260 */ 261static device_method_t at91_channel_methods[] = { 262 /* device interface */ 263 DEVMETHOD(device_probe, at91_channel_probe), 264 DEVMETHOD(device_attach, at91_channel_attach), 265 DEVMETHOD(device_detach, ata_detach), 266 DEVMETHOD(device_shutdown, bus_generic_shutdown), 267 DEVMETHOD(device_suspend, ata_suspend), 268 DEVMETHOD(device_resume, ata_resume), 269 270 { 0, 0 } 271}; 272 273driver_t at91_channel_driver = { 274 "ata", 275 at91_channel_methods, 276 sizeof(struct ata_channel), 277}; 278 279DRIVER_MODULE(ata, at91_cfata, at91_channel_driver, ata_devclass, 0, 0); 280