1/*- 2 * Copyright (c) 2006 Sam Leffler, Errno Consulting 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 --- 14 unchanged lines hidden (view full) --- 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/arm/xscale/ixp425/avila_ata.c 186352 2008-12-20 03:26:09Z sam $"); |
32 33/* 34 * Compact Flash Support for the Avila Gateworks XScale boards. 35 * The CF slot is operated in "True IDE" mode. Registers are on 36 * the Expansion Bus connected to CS1 and CS2. Interrupts are 37 * tied to GPIO pin 12. No DMA, just PIO. 38 * 39 * The ADI Pronghorn Metro is very similar. It use CS3 and CS4 and --- 22 unchanged lines hidden (view full) --- 62 63#include <sys/ata.h> 64#include <sys/sema.h> 65#include <sys/taskqueue.h> 66#include <vm/uma.h> 67#include <dev/ata/ata-all.h> 68#include <ata_if.h> 69 |
70#define AVILA_IDE_CTRL 0x06 |
71 |
72struct ata_config { 73 const char *desc; /* description for probe */ 74 uint8_t gpin; /* GPIO pin */ 75 uint8_t irq; /* IRQ */ 76 uint32_t base16; /* CS base addr for 16-bit */ 77 uint32_t size16; /* CS size for 16-bit */ 78 uint32_t off16; /* CS offset for 16-bit */ 79 uint32_t basealt; /* CS base addr for alt */ 80 uint32_t sizealt; /* CS size for alt */ 81 uint32_t offalt; /* CS offset for alt */ 82}; |
83 |
84static const struct ata_config * 85ata_getconfig(struct ixp425_softc *sa) 86{ 87 static const struct ata_config configs[] = { 88 { .desc = "Gateworks Avila IDE/CF Controller", 89 .gpin = 12, 90 .irq = IXP425_INT_GPIO_12, 91 .base16 = IXP425_EXP_BUS_CS1_HWBASE, 92 .size16 = IXP425_EXP_BUS_CS1_SIZE, 93 .off16 = EXP_TIMING_CS1_OFFSET, 94 .basealt = IXP425_EXP_BUS_CS2_HWBASE, 95 .sizealt = IXP425_EXP_BUS_CS2_SIZE, 96 .offalt = EXP_TIMING_CS2_OFFSET, 97 }, 98 { .desc = "Gateworks Cambria IDE/CF Controller", 99 .gpin = 12, 100 .irq = IXP425_INT_GPIO_12, 101 .base16 = CAMBRIA_CFSEL0_HWBASE, 102 .size16 = CAMBRIA_CFSEL0_SIZE, 103 .off16 = EXP_TIMING_CS3_OFFSET, 104 .basealt = CAMBRIA_CFSEL1_HWBASE, 105 .sizealt = CAMBRIA_CFSEL1_SIZE, 106 .offalt = EXP_TIMING_CS4_OFFSET, 107 }, 108 { .desc = "ADI Pronghorn Metro IDE/CF Controller", 109 .gpin = 0, 110 .irq = IXP425_INT_GPIO_0, 111 .base16 = IXP425_EXP_BUS_CS3_HWBASE, 112 .size16 = IXP425_EXP_BUS_CS3_SIZE, 113 .off16 = EXP_TIMING_CS3_OFFSET, 114 .basealt = IXP425_EXP_BUS_CS4_HWBASE, 115 .sizealt = IXP425_EXP_BUS_CS4_SIZE, 116 .offalt = EXP_TIMING_CS4_OFFSET, 117 }, 118 }; 119 120 /* XXX honor hint? (but then no multi-board support) */ 121 /* XXX total hack */ 122 if ((cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435) 123 return &configs[1]; /* Cambria */ 124 if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0) 125 return &configs[0]; /* Avila */ 126 return &configs[2]; /* Pronghorn */ 127} 128 |
129struct ata_avila_softc { 130 device_t sc_dev; 131 bus_space_tag_t sc_iot; 132 bus_space_handle_t sc_exp_ioh; /* Exp Bus config registers */ 133 bus_space_handle_t sc_ioh; /* CS1/3 data registers */ 134 bus_space_handle_t sc_alt_ioh; /* CS2/4 data registers */ 135 struct bus_space sc_expbus_tag; 136 struct resource sc_ata; /* hand-crafted for ATA */ --- 14 unchanged lines hidden (view full) --- 151 u_int16_t *, bus_size_t); 152static void ata_bs_wm_2_s(void *, bus_space_handle_t, bus_size_t, 153 const u_int16_t *, bus_size_t); 154 155static int 156ata_avila_probe(device_t dev) 157{ 158 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); |
159 const struct ata_config *config; |
160 |
161 config = ata_getconfig(sa); 162 if (config != NULL) { 163 device_set_desc_copy(dev, config->desc); 164 return 0; 165 } 166 return ENXIO; |
167} 168 169static int 170ata_avila_attach(device_t dev) 171{ 172 struct ata_avila_softc *sc = device_get_softc(dev); 173 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); |
174 const struct ata_config *config; |
175 |
176 config = ata_getconfig(sa); 177 KASSERT(config != NULL, ("no board config")); 178 |
179 sc->sc_dev = dev; 180 /* NB: borrow from parent */ 181 sc->sc_iot = sa->sc_iot; 182 sc->sc_exp_ioh = sa->sc_exp_ioh; |
183 |
184 if (bus_space_map(sc->sc_iot, config->base16, config->size16, 185 0, &sc->sc_ioh)) 186 panic("%s: cannot map 16-bit window (0x%x/0x%x)", 187 __func__, config->base16, config->size16); 188 if (bus_space_map(sc->sc_iot, config->basealt, config->sizealt, 189 0, &sc->sc_alt_ioh)) 190 panic("%s: cannot map alt window (0x%x/0x%x)", 191 __func__, config->basealt, config->sizealt); 192 sc->sc_16bit_off = config->off16; 193 |
194 /* 195 * Craft special resource for ATA bus space ops 196 * that go through the expansion bus and require 197 * special hackery to ena/dis 16-bit operations. 198 * 199 * XXX probably should just make this generic for 200 * accessing the expansion bus. 201 */ --- 12 unchanged lines hidden (view full) --- 214 sc->sc_expbus_tag.bs_wm_2_s = ata_bs_wm_2_s, 215 216 rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag); 217 rman_set_bushandle(&sc->sc_ata, sc->sc_ioh); 218 rman_set_bustag(&sc->sc_alt_ata, &sc->sc_expbus_tag); 219 rman_set_bushandle(&sc->sc_alt_ata, sc->sc_alt_ioh); 220 221 GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPOER, |
222 GPIO_CONF_READ_4(sa, IXP425_GPIO_GPOER) | (1<<config->gpin)); |
223 /* set interrupt type */ |
224 GPIO_CONF_WRITE_4(sa, GPIO_TYPE_REG(config->gpin), 225 (GPIO_CONF_READ_4(sa, GPIO_TYPE_REG(config->gpin)) &~ 226 GPIO_TYPE(config->gpin, GPIO_TYPE_MASK)) | 227 GPIO_TYPE(config->gpin, GPIO_TYPE_EDG_RISING)); |
228 229 /* clear ISR */ |
230 GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPISR, (1<<config->gpin)); |
231 232 /* configure CS1/3 window, leaving timing unchanged */ 233 EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, 234 EXP_BUS_READ_4(sc, sc->sc_16bit_off) | 235 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); 236 /* configure CS2/4 window, leaving timing unchanged */ |
237 EXP_BUS_WRITE_4(sc, config->offalt, 238 EXP_BUS_READ_4(sc, config->offalt) | |
239 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); 240 241 /* setup interrupt */ 242 sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid, |
243 config->irq, config->irq, 1, RF_ACTIVE); |
244 if (!sc->sc_irq) |
245 panic("Unable to allocate irq %u.\n", config->irq); |
246 bus_setup_intr(dev, sc->sc_irq, 247 INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY, 248 NULL, ata_avila_intr, sc, &sc->sc_ih); 249 250 /* attach channel on this controller */ 251 device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 0)); 252 bus_generic_attach(dev); 253 --- 6 unchanged lines hidden (view full) --- 260 struct ata_avila_softc *sc = device_get_softc(dev); 261 device_t *children; 262 int nc; 263 264 /* XXX quiesce gpio? */ 265 266 /* detach & delete all children */ 267 if (device_get_children(dev, &children, &nc) == 0) { |
268 if (nc > 0) 269 device_delete_child(dev, children[0]); 270 free(children, M_TEMP); |
271 } 272 273 bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); 274 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq); 275 276 return 0; 277} 278 --- 59 unchanged lines hidden (view full) --- 338 339/* 340 * Bus space accessors for CF-IDE PIO operations. 341 */ 342 343/* 344 * Enable/disable 16-bit ops on the expansion bus. 345 */ |
346static __inline void |
347enable_16(struct ata_avila_softc *sc) 348{ 349 EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, 350 EXP_BUS_READ_4(sc, sc->sc_16bit_off) &~ EXP_BYTE_EN); 351 DELAY(100); /* XXX? */ 352} 353 |
354static __inline void |
355disable_16(struct ata_avila_softc *sc) 356{ 357 DELAY(100); /* XXX? */ 358 EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, 359 EXP_BUS_READ_4(sc, sc->sc_16bit_off) | EXP_BYTE_EN); 360} 361 362uint8_t --- 196 unchanged lines hidden --- |