diff options
author | jhay <jhay@FreeBSD.org> | 2007-03-14 18:05:04 +0000 |
---|---|---|
committer | jhay <jhay@FreeBSD.org> | 2007-03-14 18:05:04 +0000 |
commit | b4e3b47a9172743ec8091319717e11556b86df77 (patch) | |
tree | bee8ac3091556e2b12b8056a2c75aaace47a3ada /sys | |
parent | 20a6b768be63fa7530ee5a89f9cc5b2af5722abe (diff) | |
download | FreeBSD-src-b4e3b47a9172743ec8091319717e11556b86df77.zip FreeBSD-src-b4e3b47a9172743ec8091319717e11556b86df77.tar.gz |
Map the second CS of the compact flash too. This allow us access to
the alternate status and the control registers. Remove the local
version of ata_reset.
Add support for the ADI Pronghorn Metro boards. They use CS3 and CS4
instead of Avila's CS1 and CS2.
OKed by: sam, cognet
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arm/xscale/ixp425/avila_ata.c | 195 |
1 files changed, 82 insertions, 113 deletions
diff --git a/sys/arm/xscale/ixp425/avila_ata.c b/sys/arm/xscale/ixp425/avila_ata.c index a6f5251..f3cf480 100644 --- a/sys/arm/xscale/ixp425/avila_ata.c +++ b/sys/arm/xscale/ixp425/avila_ata.c @@ -32,9 +32,12 @@ __FBSDID("$FreeBSD$"); /* * Compact Flash Support for the Avila Gateworks XScale boards. - * There are 1 or 2 optional CF slots operated in "True IDE" mode. - * Registers are on the Expansion Bus connected to CS1. Interrupts - * are tied to GPIO pin 12. No DMA, just PIO. + * The CF slot is operated in "True IDE" mode. Registers are on + * the Expansion Bus connected to CS1 and CS2. Interrupts are + * tied to GPIO pin 12. No DMA, just PIO. + * + * The ADI Pronghorn Metro is very similar. It use CS3 and CS4 and + * GPIO pin 0 for interrupts. * * See also http://www.intel.com/design/network/applnots/302456.htm. */ @@ -64,17 +67,24 @@ __FBSDID("$FreeBSD$"); #include <dev/ata/ata-all.h> #include <ata_if.h> -#define AVILA_IDE_GPIN 12 /* GPIO pin # */ -#define AVILA_IDE_IRQ IXP425_INT_GPIO_12 -#define AVILA_IDE_CTRL 0x1e /* control register */ +#define AVILA_IDE_GPIN 12 /* GPIO pin # */ +#define AVILA_IDE_IRQ IXP425_INT_GPIO_12 +#define AVILA_IDE_CTRL 0x06 /* control register */ + +#define PRONGHORN_IDE_GPIN 0 /* GPIO pin # */ +#define PRONGHORN_IDE_IRQ IXP425_INT_GPIO_0 +#define PRONGHORN_IDE_CNTRL 0x06 /* control register */ struct ata_avila_softc { device_t sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_exp_ioh; /* Exp Bus config registers */ - bus_space_handle_t sc_ioh; /* CS1 data registers */ + bus_space_handle_t sc_ioh; /* CS1/3 data registers */ + bus_space_handle_t sc_alt_ioh; /* CS2/4 data registers */ struct bus_space sc_expbus_tag; struct resource sc_ata; /* hand-crafted for ATA */ + struct resource sc_alt_ata; /* hand-crafted for ATA */ + u_int32_t sc_16bit_off; /* EXP_TIMING_CSx_OFFSET */ int sc_rid; /* rid for IRQ */ struct resource *sc_irq; /* IRQ resource */ void *sc_ih; /* interrupt handler */ @@ -94,8 +104,14 @@ static void ata_bs_wm_2_s(void *, bus_space_handle_t, bus_size_t, static int ata_avila_probe(device_t dev) { + struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); + /* XXX any way to check? */ - device_set_desc_copy(dev, "Gateworks Avila IDE/CF Controller"); + if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0) + device_set_desc_copy(dev, "Gateworks Avila IDE/CF Controller"); + else + device_set_desc_copy(dev, + "ADI Pronghorn Metro IDE/CF Controller"); return 0; } @@ -104,14 +120,43 @@ ata_avila_attach(device_t dev) { struct ata_avila_softc *sc = device_get_softc(dev); struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); + u_int32_t alt_t_off, board_type, ide_gpin, ide_irq; + board_type = 0; sc->sc_dev = dev; /* NB: borrow from parent */ sc->sc_iot = sa->sc_iot; sc->sc_exp_ioh = sa->sc_exp_ioh; - if (bus_space_map(sc->sc_iot, - IXP425_EXP_BUS_CS1_HWBASE, IXP425_EXP_BUS_CS1_SIZE, 0, &sc->sc_ioh)) - panic("%s: unable to map Expansion Bus CS1 window", __func__); + if (EXP_BUS_READ_4(sc, EXP_TIMING_CS2_OFFSET) != 0) + board_type = 1; /* Avila board */ + + if (board_type == 1) { + if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS1_HWBASE, + IXP425_EXP_BUS_CS1_SIZE, 0, &sc->sc_ioh)) + panic("%s: unable to map Expansion Bus CS1 window", + __func__); + if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS2_HWBASE, + IXP425_EXP_BUS_CS2_SIZE, 0, &sc->sc_alt_ioh)) + panic("%s: unable to map Expansion Bus CS2 window", + __func__); + ide_gpin = AVILA_IDE_GPIN; + ide_irq = AVILA_IDE_IRQ; + sc->sc_16bit_off = EXP_TIMING_CS1_OFFSET; + alt_t_off = EXP_TIMING_CS2_OFFSET; + } else { + if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS3_HWBASE, + IXP425_EXP_BUS_CS3_SIZE, 0, &sc->sc_ioh)) + panic("%s: unable to map Expansion Bus CS3 window", + __func__); + if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS4_HWBASE, + IXP425_EXP_BUS_CS4_SIZE, 0, &sc->sc_alt_ioh)) + panic("%s: unable to map Expansion Bus CS4 window", + __func__); + ide_gpin = PRONGHORN_IDE_GPIN; + ide_irq = PRONGHORN_IDE_IRQ; + sc->sc_16bit_off = EXP_TIMING_CS3_OFFSET; + alt_t_off = EXP_TIMING_CS4_OFFSET; + } /* * Craft special resource for ATA bus space ops @@ -137,27 +182,34 @@ ata_avila_attach(device_t dev) rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag); rman_set_bushandle(&sc->sc_ata, sc->sc_ioh); + rman_set_bustag(&sc->sc_alt_ata, &sc->sc_expbus_tag); + rman_set_bushandle(&sc->sc_alt_ata, sc->sc_alt_ioh); GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPOER, - GPIO_CONF_READ_4(sa, IXP425_GPIO_GPOER) | (1<<AVILA_IDE_GPIN)); - /* interrupt is active low */ - GPIO_CONF_WRITE_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN), - GPIO_CONF_READ_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN) | - GPIO_TYPE(AVILA_IDE_GPIN, GPIO_TYPE_ACT_LOW))); + GPIO_CONF_READ_4(sa, IXP425_GPIO_GPOER) | (1<<ide_gpin)); + /* interrupt is active high */ + GPIO_CONF_WRITE_4(sa, GPIO_TYPE_REG(ide_gpin), + (GPIO_CONF_READ_4(sa, GPIO_TYPE_REG(ide_gpin)) & + ~GPIO_TYPE(ide_gpin, GPIO_TYPE_MASK)) | + GPIO_TYPE(ide_gpin, GPIO_TYPE_ACT_HIGH)); /* clear ISR */ - GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPISR, (1<<AVILA_IDE_GPIN)); + GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPISR, (1<<ide_gpin)); - /* configure CS1 window, leaving timing unchanged */ - EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET, - EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) | + /* configure CS1/3 window, leaving timing unchanged */ + EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, + EXP_BUS_READ_4(sc, sc->sc_16bit_off) | + EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); + /* configure CS2/4 window, leaving timing unchanged */ + EXP_BUS_WRITE_4(sc, alt_t_off, + EXP_BUS_READ_4(sc, alt_t_off) | EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); /* setup interrupt */ sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid, - AVILA_IDE_IRQ, AVILA_IDE_IRQ, 1, RF_ACTIVE); + ide_irq, ide_irq, 1, RF_ACTIVE); if (!sc->sc_irq) - panic("Unable to allocate irq %u.\n", AVILA_IDE_IRQ); + panic("Unable to allocate irq %u.\n", ide_irq); bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY, NULL, ata_avila_intr, sc, &sc->sc_ih); @@ -261,8 +313,8 @@ ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq, static void __inline enable_16(struct ata_avila_softc *sc) { - EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET, - EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) &~ EXP_BYTE_EN); + EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, + EXP_BUS_READ_4(sc, sc->sc_16bit_off) &~ EXP_BYTE_EN); DELAY(100); /* XXX? */ } @@ -270,8 +322,8 @@ static void __inline disable_16(struct ata_avila_softc *sc) { DELAY(100); /* XXX? */ - EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET, - EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) | EXP_BYTE_EN); + EXP_BUS_WRITE_4(sc, sc->sc_16bit_off, + EXP_BUS_READ_4(sc, sc->sc_16bit_off) | EXP_BYTE_EN); } uint8_t @@ -439,10 +491,11 @@ avila_channel_attach(device_t dev) /* NB: should be used only for ATAPI devices */ ch->r_io[ATA_IREASON].offset = ATA_COUNT; ch->r_io[ATA_STATUS].offset = ATA_COMMAND; - /* alias this; required by ata_generic_status */ - ch->r_io[ATA_ALTSTAT].offset = ch->r_io[ATA_STATUS].offset; - /* NB: the control register is special */ + /* NB: the control and alt status registers are special */ + ch->r_io[ATA_ALTSTAT].res = &sc->sc_alt_ata; + ch->r_io[ATA_ALTSTAT].offset = AVILA_IDE_CTRL; + ch->r_io[ATA_CONTROL].res = &sc->sc_alt_ata; ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL; /* NB: by convention this points at the base of registers */ @@ -452,88 +505,6 @@ avila_channel_attach(device_t dev) return ata_attach(dev); } -/* XXX override ata_generic_reset to handle non-standard status */ -static void -avila_channel_reset(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - u_int8_t ostat0 = 0, stat0 = 0; - u_int8_t err = 0, lsb = 0, msb = 0; - int mask = 0, timeout; - - /* do we have any signs of ATA/ATAPI HW being present ? */ - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER); - DELAY(10); - ostat0 = ATA_IDX_INB(ch, ATA_STATUS); - if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) { - stat0 = ATA_S_BUSY; - mask |= 0x01; - } - - if (bootverbose) - device_printf(dev, "%s: reset tp1 mask=%02x ostat0=%02x\n", - __func__, mask, ostat0); - - /* if nothing showed up there is no need to get any further */ - /* XXX SOS is that too strong?, we just might loose devices here */ - ch->devices = 0; - if (!mask) - return; - - /* reset (both) devices on this channel */ - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER); - DELAY(10); - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET); - ata_udelay(10000); - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS); - ata_udelay(100000); - ATA_IDX_INB(ch, ATA_ERROR); - - /* wait for BUSY to go inactive */ - for (timeout = 0; timeout < 310; timeout++) { - if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) { - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - DELAY(10); - err = ATA_IDX_INB(ch, ATA_ERROR); - lsb = ATA_IDX_INB(ch, ATA_CYL_LSB); - msb = ATA_IDX_INB(ch, ATA_CYL_MSB); - stat0 = ATA_IDX_INB(ch, ATA_STATUS); - if (bootverbose) - device_printf(dev, - "%s: stat0=0x%02x err=0x%02x lsb=0x%02x " - "msb=0x%02x\n", __func__, - stat0, err, lsb, msb); - if (stat0 == err && lsb == err && msb == err && - timeout > (stat0 & ATA_S_BUSY ? 100 : 10)) - mask &= ~0x01; - if (!(stat0 & ATA_S_BUSY)) { - if ((err & 0x7f) == ATA_E_ILI || err == 0) { - if (lsb == ATAPI_MAGIC_LSB && - msb == ATAPI_MAGIC_MSB) { - ch->devices |= ATA_ATAPI_MASTER; - } else if (stat0 & ATA_S_READY) { - ch->devices |= ATA_ATA_MASTER; - } - } else if ((stat0 & 0x0f) && - err == lsb && err == msb) { - stat0 |= ATA_S_BUSY; - } - } - } - if (mask == 0x00) /* nothing to wait for */ - break; - /* wait for master */ - if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10)) - break; - ata_udelay(100000); - } - - if (bootverbose) - device_printf(dev, "%s: reset tp2 stat0=%02x devices=0x%b\n", - __func__, stat0, ch->devices, - "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER"); -} - static device_method_t avila_channel_methods[] = { /* device interface */ DEVMETHOD(device_probe, avila_channel_probe), @@ -543,8 +514,6 @@ static device_method_t avila_channel_methods[] = { DEVMETHOD(device_suspend, ata_suspend), DEVMETHOD(device_resume, ata_resume), - DEVMETHOD(ata_reset, avila_channel_reset), - { 0, 0 } }; |