Date: Sat, 23 Sep 2006 00:52:06 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 106533 for review Message-ID: <200609230052.k8N0q6Dw091998@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=106533 Change 106533 by imp@imp_lighthouse on 2006/09/23 00:51:28 bridge driver, needs work. Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_mci.c#2 edit .. //depot/projects/arm/src/sys/arm/at91/at91_mcireg.h#2 edit .. //depot/projects/arm/src/sys/arm/conf/TSC4370#8 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_mci.c#2 (text+ko) ==== @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2005 Olivier Houchard. All rights reserved. + * Copyright (c) 2006 Berndt Walter. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,13 +51,10 @@ #include <machine/intr.h> #include <arm/at91/at91rm92reg.h> #include <arm/at91/at91var.h> -#include <dev/mmc/mmcreg.h> -#include <arm/at91/at91_qdmmcreg.h> +#include <arm/at91/at91_mcireg.h> #include <arm/at91/at91_pdcreg.h> -#include <geom/geom_disk.h> - -struct at91_qdmmc_softc { +struct at91_mci_softc { void *intrhand; /* Interrupt handle */ device_t dev; struct resource *irq_res; /* IRQ resource */ @@ -67,450 +65,82 @@ struct disk *disk; /* XXX support only one card for */ int nb_cards; struct proc *p; - struct { - struct bio_queue_head bio_queue; - char name[7]; - uint32_t addr; - uint32_t CID[4]; - uint32_t CSD[4]; - uint32_t sector_size; - uint64_t size; - uint32_t mode; - uint32_t flags; -#define READ_PARTIAL 0x001 -#define WRITE_PARTIAL 0x002 -#define ERASE_BLOCK_EN 0x004 -#define READ_MISALIGN 0x008 -#define WRITE_MISALIGN 0x010 - uint32_t read_bl; - uint32_t write_bl; - } cards[MMC_MAX]; }; static inline uint32_t -RD4(struct at91_qdmmc_softc *sc, bus_size_t off) +RD4(struct at91_mci_softc *sc, bus_size_t off) { return bus_read_4(sc->mem_res, off); } static inline void -WR4(struct at91_qdmmc_softc *sc, bus_size_t off, uint32_t val) +WR4(struct at91_mci_softc *sc, bus_size_t off, uint32_t val) { bus_write_4(sc->mem_res, off, val); } /* bus entry points */ -static int at91_qdmmc_probe(device_t dev); -static int at91_qdmmc_attach(device_t dev); -static int at91_qdmmc_detach(device_t dev); -static void at91_qdmmc_intr(void *); +static int at91_mci_probe(device_t dev); +static int at91_mci_attach(device_t dev); +static int at91_mci_detach(device_t dev); +static void at91_mci_intr(void *); /* helper routines */ -static int at91_qdmmc_activate(device_t dev); -static void at91_qdmmc_deactivate(device_t dev); +static int at91_mci_activate(device_t dev); +static void at91_mci_deactivate(device_t dev); -/* disk routines */ -static int at91_qdmmc_open(struct disk *dp); -static int at91_qdmmc_close(struct disk *dp); -static void at91_qdmmc_strategy(struct bio *bp); -static void at91_qdmmc_task(void *arg); - -#define AT91_QDMMC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define AT91_QDMMC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define AT91_QDMMC_LOCK_INIT(_sc) \ +#define AT91_MCI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define AT91_MCI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define AT91_MCI_LOCK_INIT(_sc) \ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ - "qdmmc", MTX_DEF) -#define AT91_QDMMC_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); -#define AT91_QDMMC_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); -#define AT91_QDMMC_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); + "mci", MTX_DEF) +#define AT91_MCI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); +#define AT91_MCI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); +#define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); -static int -at91_qdmmc_SendCommand(device_t dev, uint32_t cmd, uint32_t arg) +static void +at91_mci_init(device_t dev) { - struct at91_qdmmc_softc *sc = device_get_softc(dev); - uint32_t error; + struct at91_mci_softc *sc = device_get_softc(dev); - device_printf(dev, "Sending command %x:%x\n", cmd, arg); - WR4(sc, MCI_ARGR, arg); - WR4(sc, MCI_CMDR, cmd); - - while (!(RD4(sc, MCI_SR) & MCI_SR_CMDRDY)) - continue; - - error = RD4(sc, MCI_SR) & MCI_SR_ERROR; - if (error) { - if ((cmd != SDCARD_APP_OP_COND_CMD) && - (cmd != MMC_SEND_OP_COND_CMD)) { - //printf("qdmmc: Error 0x%x\n", error); - return (error); - } - if (error != MCI_SR_RCRCE) { - //printf("qdmmc: Error 0x%x\n", error); - return (error); - } - } - return (0); + WR4(sc, MCI_CR, MCI_CR_MCIEN); /* Enable controller */ + WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ + WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | MCI_DTOR_DTOCYC); + WR4(sc, MCI_MR, 0x834a); // XXX GROSS HACK FROM LINUX + WR4(sc, MCI_SDCR, 0); /* SLOT A, 1 bit bus */ } -static int -at91_qdmmc_SDCard_SendAppCommand(device_t dev, uint32_t cmd, uint32_t arg) +static void +at91_mci_fini(device_t dev) { - uint32_t status; - struct at91_qdmmc_softc *sc = device_get_softc(dev); + struct at91_mci_softc *sc = device_get_softc(dev); - // Send the CMD55 for application specific command - WR4(sc, MCI_ARGR, sc->cards[0].addr << 16); - WR4(sc, MCI_CMDR, APP_CMD); - - printf("CMD55: %x\n", sc->cards[0].addr << 16); - - // wait for CMDRDY Status flag to read the response - do - { - status = RD4(sc, MCI_SR); - } while(!(status & MCI_SR_CMDRDY)); - - // if an error occurs - if ((status & MCI_SR_ERROR) != 0 ) - return (status & MCI_SR_ERROR); - - return (at91_qdmmc_SendCommand(dev, cmd, arg)); + WR4(sc, MCI_IDR, 0xffffffff); /* Turn off interrupts */ + WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* Put the device into reset */ } static int -at91_qdmmc_probe(device_t dev) +at91_mci_probe(device_t dev) { - //printf("at91_qdmmc_probe: called\n"); - device_set_desc(dev, "MMC"); + device_set_desc(dev, "MCI mmc/sd host bridge"); return (0); } static int -at91_qdmmc_SDCard_GetOCR(device_t dev) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - uint32_t response = 0; - - // The RCA to be used for CMD55 in Idle state shall be the card's - // default RCA=0x0000. - sc->cards[0].addr = 0; - while(!(response & AT91C_CARD_POWER_UP_BUSY)) { - response = at91_qdmmc_SDCard_SendAppCommand(dev, - SDCARD_APP_OP_COND_CMD, AT91C_MMC_HOST_VOLTAGE_RANGE); - if (response != 0) - return (-1); - response = RD4(sc, MCI_RSPR); - printf("card's OCR is %#x\n", response); - } - - return (response); -} - -static int -at91_qdmmc_GetCID(device_t dev, uint32_t *response) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - - if (at91_qdmmc_SendCommand(dev, ALL_SEND_CID_CMD, 0)) - return EIO; - response[0] = RD4(sc, MCI_RSPR + 0 * sizeof(response[0])); - response[1] = RD4(sc, MCI_RSPR + 1 * sizeof(response[0])); - response[2] = RD4(sc, MCI_RSPR + 2 * sizeof(response[0])); - response[3] = RD4(sc, MCI_RSPR + 3 * sizeof(response[0])); - return 0; -} - -static int -at91_qdmmc_GetCSD(device_t dev, uint32_t rca, uint32_t *response) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - - if (at91_qdmmc_SendCommand(dev, SEND_CSD_CMD, rca << 16)) - return EIO; - response[0] = RD4(sc, MCI_RSPR + 0 * sizeof(response[0])); - response[1] = RD4(sc, MCI_RSPR + 1 * sizeof(response[0])); - response[2] = RD4(sc, MCI_RSPR + 2 * sizeof(response[0])); - response[3] = RD4(sc, MCI_RSPR + 3 * sizeof(response[0])); - return 0; -} - -static uint32_t -at91_qdmmc_GetStatus(device_t dev, uint32_t rca) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - - if (at91_qdmmc_SendCommand(dev, SEND_STATUS_CMD, rca << 16) == 0) - return (RD4(sc, MCI_RSPR)); - return 0xffffffff; -} - -static int -at91_qdmmc_SetBlocklength(device_t dev, uint32_t length) -{ - return (at91_qdmmc_SendCommand(dev, SET_BLOCKLEN_CMD, length) ); -} - -static int -at91_qdmmc_SDCard_SetBusWidth(device_t dev) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - uint32_t ret_value, rca; - char bus_width; - - rca = sc->cards[0].addr; - do { - ret_value = at91_qdmmc_GetStatus(dev, rca); - } while (ret_value != 0xffffffff && - !(ret_value & AT91C_SR_READY_FOR_DATA)); - - // Select Card - at91_qdmmc_SendCommand(dev, SEL_DESEL_CARD_CMD, rca << 16); - - // XXX hard code 1. - bus_width = AT91C_BUS_WIDTH_1BIT; - printf("Setting bus width to 1 bit\n"); - if (at91_qdmmc_SDCard_SendAppCommand(dev, SDCARD_SET_BUS_WIDTH_CMD, - bus_width) != 0) - return EIO; - - return 0; -} - -static int -at91_qdmmc_sdcard_init(device_t dev) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - uint32_t *csd, *cid; - - // CMD0 - at91_qdmmc_SendCommand(dev, GO_IDLE_STATE_CMD, 0); - - if (at91_qdmmc_SDCard_GetOCR(dev) == -1) { // ACMD41 - printf("SD: can't get OCR\n"); - return ENXIO; - } - cid = &sc->cards[0].CID[0]; - if (at91_qdmmc_GetCID(dev, cid) != 0) { // CMD2 - printf("SD: cant get cid\n"); - return ENXIO; - } - if (at91_qdmmc_SendCommand(dev, SET_RELATIVE_ADDR_CMD, 0) != 0) { - printf("SD: Can't set RCA to 0\n"); - return ENXIO; - } - sc->cards[0].addr = RD4(sc, MCI_RSPR) >> 16; - printf("SD Card at %#x\n", sc->cards[0].addr); - csd = &sc->cards[0].CSD[0]; - if (at91_qdmmc_GetCSD(dev, sc->cards[0].addr, csd) != 0) { - printf("SD: can't get csd\n"); - return ENXIO; - } - printf("SD Card - CID = 0x%08x%08x%08x%08x\n", - cid[0], - cid[1], - cid[2], - cid[3]); - printf("SD - CSD = 0x%08x%08x%08x%08x\n", csd[0], csd[1], csd[2], - csd[3]); - printf("SD: Vendor-ID = 0x%x\n", cid[0] >> 24); - printf("SD: OEM-ID = 0x%x\n", (cid[0] >> 8) & 0xffff); - sc->cards[0].name[0] = (cid[0] >> 0) & 0xff; - sc->cards[0].name[1] = (cid[1] >> 24) & 0xff; - sc->cards[0].name[2] = (cid[1] >> 16) & 0xff; - sc->cards[0].name[3] = (cid[1] >> 8) & 0xff; - sc->cards[0].name[4] = (cid[1] >> 0) & 0xff; - sc->cards[0].name[5] = (cid[2] >> 24) & 0xff; - sc->cards[0].name[6] = '\0'; - printf("SD: Productname = %s\n", sc->cards[0].name); - printf("SD: Revision = 0x%x\n", (cid[2] >> 16) & 0xff); - printf("SD: Serial = 0x%x\n", (cid[2] << 16) | - (cid[3] >> 16)); - int year = 2001; - year += ((cid[3] >> 8) & 0xf); - int month = 0; - month += ((cid[3] >> 12) & 0xf); - printf("SD: Manufacturing Date = %i/%i\n", year, month); - sc->cards[0].mode = 5 * MCI_MR_CLKDIV | /* MCI_MR_PWSDIV | - (MCI_MR_PWSDIV << 1) | */ MCI_MR_PDCMODE; -// sc->cards[0].mode = 75 * MCI_MR_CLKDIV | MCI_MR_PWSDIV | -// (MCI_MR_PWSDIV << 1); - sc->cards[0].flags = 0; - if (sc->cards[0].CSD[1] & CSD_1_RD_B_PAR_M) - sc->cards[0].flags |= READ_PARTIAL; - if (sc->cards[0].CSD[3] & CSD_3_WBLOCK_P_M) - sc->cards[0].flags |= WRITE_PARTIAL; - sc->cards[0].read_bl = (csd[1] >> CSD_1_RD_B_LEN_S) & - CSD_1_RD_B_LEN_M; - sc->cards[0].write_bl = (csd[3] >> CSD_3_WBLEN_S) & - CSD_3_WBLEN_M; - bioq_init(&sc->cards[0].bio_queue); - - sc->cards[0].sector_size = 1 << sc->cards[0].read_bl; - printf("SD: Blocksize = %i Bytes\n", sc->cards[0].sector_size); - uint64_t c_size; - uint64_t c_size_mult; - c_size = ((sc->cards[0].CSD[1] & CSD_1_CSIZE_H_M) << 2) | - ((sc->cards[0].CSD[2] >> CSD_2_CSIZE_L_S) & CSD_2_CSIZE_L_M); - printf("SD: c_size = %lld\n", c_size); - c_size_mult = (sc->cards[0].CSD[2] >> CSD_2_C_SIZE_M_S) & - CSD_2_C_SIZE_M_M; - c_size_mult = 1 << (c_size_mult + 2); - printf("SD: c_size_mult = %lld\n", c_size_mult); - sc->cards[0].size = sc->cards[0].sector_size * - (c_size + 1) * c_size_mult; - printf("SD: Size = %lld Bytes\n", sc->cards[0].size); - if (at91_qdmmc_SDCard_SetBusWidth(dev)) { - printf("Failed to set bus width"); - return EIO; - } - if (at91_qdmmc_SetBlocklength(dev, sc->cards[0].sector_size) != 0) { - printf("Failed to set block length!\n"); - return EIO; - } - sc->nb_cards++; - return 0; -} - -static int -at91_qdmmc_mmc_init(device_t dev) -{ - struct at91_qdmmc_softc *sc = device_get_softc(dev); - uint32_t cond; - int err; - - err = 0; - /* get all cards into idle state */ - at91_qdmmc_SendCommand(dev, MMC_GO_IDLE_STATE_CMD, 0); - - /* check operating conditions */ - do { /* loop on busy */ - err = at91_qdmmc_SendCommand(dev, MMC_SEND_OP_COND_CMD, - AT91C_MMC_HOST_VOLTAGE_RANGE); - if (err != 0) { - err = ENXIO; - printf("No MMC cards found\n"); - goto out; - } - cond = RD4(sc, MCI_RSPR); - } while ((cond & AT91C_CARD_POWER_UP_BUSY) == 0); - printf("at91_qdmmc_attach: operating conditions: 0x%x\n", - cond & ~(AT91C_CARD_POWER_UP_BUSY)); - - /* now find our cards */ - for(sc->nb_cards = 0; sc->nb_cards < MMC_MAX; sc->nb_cards++) { - int status; - int card = sc->nb_cards; - if (at91_qdmmc_GetCID(dev, sc->cards[card].CID)) - break; - printf("Found MMC %i - CID = 0x%x%x%x%x\n", card, - sc->cards[card].CID[0], - sc->cards[card].CID[1], - sc->cards[card].CID[2], - sc->cards[card].CID[3]); - printf("MMC %i: Vendor-ID = 0x%x\n", card, - sc->cards[card].CID[0] >> 24), - printf("MMC %i: OEM-ID = 0x%x\n", card, - (sc->cards[card].CID[0] >> 8) & 0xffff), - sc->cards[card].name[0] = (sc->cards[card].CID[0] >> 0) & 0xff; - sc->cards[card].name[1] = (sc->cards[card].CID[1] >> 24) & 0xff; - sc->cards[card].name[2] = (sc->cards[card].CID[1] >> 16) & 0xff; - sc->cards[card].name[3] = (sc->cards[card].CID[1] >> 8) & 0xff; - sc->cards[card].name[4] = (sc->cards[card].CID[1] >> 0) & 0xff; - sc->cards[card].name[5] = (sc->cards[card].CID[2] >> 24) & 0xff; - sc->cards[card].name[6] = '\0'; - printf("MMC %i: Productname = %s\n", card, - sc->cards[card].name); - printf("MMC %i: Revision = 0x%x\n", card, - (sc->cards[card].CID[2] >> 16) & 0xff), - printf("MMC %i: Serial = 0x%x\n", card, - (sc->cards[card].CID[2] << 16) | - (sc->cards[card].CID[3] >> 16)); - int year = 1997; - year += ((sc->cards[card].CID[3] >> 8) & 0xf); - int month = 0; - month += ((sc->cards[card].CID[3] >> 12) & 0xf); - printf("MMC %i: Manufacturing Date = %i/%i\n", card, year, - month); - - sc->cards[card].addr = card + MMC_FIRST_RCA; - status = at91_qdmmc_SendCommand(dev, MMC_SET_RELATIVE_ADDR_CMD, - (sc->cards[card].addr) << 16); - if (status != 0) { - printf("Failed to set address for MMC %i\n", card); - goto out; - } - printf("Set MMC %i address to 0x%x\n", card, - sc->cards[card].addr); - - status = at91_qdmmc_SendCommand(dev, SEND_CSD_CMD, - (sc->cards[card].addr) << 16); - if (status != 0) { - printf("Failed to get CSD for MMC %i\n", card); - goto out; - } - sc->cards[card].CSD[0] = RD4(sc, MCI_RSPR + 0); - sc->cards[card].CSD[1] = RD4(sc, MCI_RSPR + 4); - sc->cards[card].CSD[2] = RD4(sc, MCI_RSPR + 8); - sc->cards[card].CSD[3] = RD4(sc, MCI_RSPR + 12); - printf("MMC %i: CSD = 0x%x%x%x%x\n", card, - sc->cards[card].CSD[0], - sc->cards[card].CSD[1], - sc->cards[card].CSD[2], - sc->cards[card].CSD[3]); - uint64_t c_size; - uint64_t c_size_mult; - sc->cards[card].sector_size = - 1 << ((sc->cards[card].CSD[1] >> 16) & 0xf); - printf("MMC %i: Blocksize = %i Bytes\n", card, - sc->cards[card].sector_size); - c_size = ((sc->cards[card].CSD[1] & 0x3ff) << 2) | - ((sc->cards[card].CSD[2] >> 30) & 0x3); - printf("MMC %i: c_size = %lld\n", card, c_size); - c_size_mult = (sc->cards[card].CSD[2] >> 15) & 0x7; - c_size_mult = 1 << (c_size_mult + 2); - printf("MMC %i: c_size_mult = %lld\n", card, c_size_mult); - sc->cards[card].size = sc->cards[card].sector_size * - (c_size + 1) * c_size_mult; - printf("MMC %i: Size = %lld Bytes\n", card, - sc->cards[card].size); - /* declare clockrate to 5MHz - XXX the card may allow more */ - sc->cards[card].mode = 5 * MCI_MR_CLKDIV | /* MCI_MR_PWSDIV | - (MCI_MR_PWSDIV << 1) | */ MCI_MR_PDCMODE; -// sc->cards[card].mode = 75 * MCI_MR_CLKDIV | /* MCI_MR_PWSDIV | -// (MCI_MR_PWSDIV << 1); */ - sc->cards[card].flags = 0; - if (sc->cards[card].CSD[1] & CSD_1_RD_B_PAR_M) - sc->cards[card].flags |= READ_PARTIAL; - if (sc->cards[card].CSD[3] & CSD_3_WBLOCK_P_M) - sc->cards[card].flags |= WRITE_PARTIAL; - sc->cards[card].read_bl = 0; - sc->cards[card].write_bl = 0; - bioq_init(&sc->cards[0].bio_queue); - } - if (sc->nb_cards == 0) - err = ENXIO; -out:; - return (err); -} - -static int -at91_qdmmc_attach(device_t dev) +at91_mci_attach(device_t dev) { /* XXX: asumes MCK = 60MHz */ - struct at91_qdmmc_softc *sc = device_get_softc(dev); + struct at91_mci_softc *sc = device_get_softc(dev); int err; - //printf("at91_qdmmc_attach: called\n"); - sc->dev = dev; - err = at91_qdmmc_activate(dev); + err = at91_mci_activate(dev); if (err) goto out; - AT91_QDMMC_LOCK_INIT(sc); + AT91_MCI_LOCK_INIT(sc); - printf("BEFORE I FUCK WITH IT == mode 0x%x\n", RD4(sc, MCI_MR)); /* * Allocate DMA tags and maps */ @@ -524,99 +154,39 @@ if (err != 0) goto out; - // reset the MCI - WR4(sc, MCI_CR, MCI_CR_SWRST); - // disable all interrupt sources - WR4(sc, MCI_IDR, 0xffffffff); - // set timeout values - WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1048576 | MCI_DTOR_DTOCYC); - //WR4(sc, MCI_MR, AT91C_MCI_MR_PDCMODE); - // set clockrate to just 400kHz needed to identify -// WR4(sc, MCI_MR, 74 * MCI_MR_CLKDIV /* | MCI_MR_PWSDIV | (MCI_MR_PWSDIV << 1) */ -// | MCI_MR_PDCMODE); - WR4(sc, MCI_SDCR, 0); - // enable controller - WR4(sc, MCI_CR, MCI_CR_MCIEN); - - //WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS); - //WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS); - //WR4(sc, PDC_RNPR, 0); - //WR4(sc, PDC_RNCR, 0); - //WR4(sc, PDC_TNPR, 0); - //WR4(sc, PDC_TNCR, 0); - //WR4(sc, PDC_RPR, 0); - //WR4(sc, PDC_RCR, 0); - //WR4(sc, PDC_TPR, 0); - //WR4(sc, PDC_TCR, 0); - //WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); - //WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); + at91_mci_fini(dev); + at91_mci_init(dev); - RD4(sc, MCI_RDR); - RD4(sc, MCI_SR); - /* * Activate the interrupt */ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, - at91_qdmmc_intr, sc, &sc->intrhand); + at91_mci_intr, sc, &sc->intrhand); if (err) { - AT91_QDMMC_LOCK_DESTROY(sc); + AT91_MCI_LOCK_DESTROY(sc); goto out; } - if (at91_qdmmc_mmc_init(dev) != 0) { - printf("MMC FAILED, LET'S TRY SDCARD\n"); - if (at91_qdmmc_sdcard_init(dev) != 0) { - printf("SD CARD FAILED, YOU LOSE\n"); - err = 0; - goto out; - } - } - - if (sc->nb_cards == 0) { - printf("No MMC cards found\n"); - goto out; - } else { - AT91_QDMMC_LOCK(sc); - /* - * Register the (XXX) first media as a disk - */ - sc->disk = disk_alloc(); - sc->disk->d_open = at91_qdmmc_open; - sc->disk->d_close = at91_qdmmc_close; - sc->disk->d_strategy = at91_qdmmc_strategy; - // sc->disk->d_dump = at91_qdmmc_dump; - sc->disk->d_name = "at91_qdmmc"; - sc->disk->d_drv1 = sc; - sc->disk->d_maxsize = DFLTPHYS; - sc->disk->d_unit = 0; - //sc->disk->d_flags = DISKFLAG_NEEDSGIANT; - disk_create(sc->disk, DISK_VERSION); - } - - /* set clockrate to 5MHz - XXX the card may allow more */ -// WR4(sc, MCI_MR, 5 * MCI_MR_CLKDIV | -// /* MCI_MR_PWSDIV | (MCI_MR_PWSDIV << 1) | */ MCI_MR_PDCMODE); - - AT91_QDMMC_UNLOCK(sc); + AT91_MCI_UNLOCK(sc); - kthread_create(&at91_qdmmc_task, sc, &sc->p, 0, 0, "task: at91_qdmmc"); out:; if (err) - at91_qdmmc_deactivate(dev); + at91_mci_deactivate(dev); return (err); } static int -at91_qdmmc_detach(device_t dev) +at91_mci_detach(device_t dev) { + at91_mci_fini(dev); + at91_mci_deactivate(dev); return (EBUSY); /* XXX */ } static int -at91_qdmmc_activate(device_t dev) +at91_mci_activate(device_t dev) { - struct at91_qdmmc_softc *sc; + struct at91_mci_softc *sc; int rid; sc = device_get_softc(dev); @@ -632,14 +202,14 @@ goto errout; return (0); errout: - at91_qdmmc_deactivate(dev); + at91_mci_deactivate(dev); return (ENOMEM); } static void -at91_qdmmc_deactivate(device_t dev) +at91_mci_deactivate(device_t dev) { - struct at91_qdmmc_softc *sc; + struct at91_mci_softc *sc; sc = device_get_softc(dev); if (sc->intrhand) @@ -657,291 +227,41 @@ return; } +#if 0 static void at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { if (error != 0) - return; + return; *(bus_addr_t *)arg = segs[0].ds_addr; } - -static int at91_qdmmc_open(struct disk *dp) -{ - struct at91_qdmmc_softc *sc; - - //printf("at91_qdmmc_open: called\n"); - sc = (struct at91_qdmmc_softc *)dp->d_drv1; - - AT91_QDMMC_LOCK(sc); - sc->disk->d_sectorsize = sc->cards[0].sector_size; - sc->disk->d_mediasize = sc->cards[0].size; - //softc->disk->d_fwsectors = softc->params.secs_per_track; - //softc->disk->d_fwheads = softc->params.heads; - //sc->disk->d_devstat->block_size = sc->cards[0].sector_size; - //softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE; - AT91_QDMMC_UNLOCK(sc); - - return 0; -} - -static int at91_qdmmc_close(struct disk *dp) -{ - struct at91_qdmmc_softc *sc; - - //printf("at91_qdmmc_close: called\n"); - sc = (struct at91_qdmmc_softc *)dp->d_drv1; - - AT91_QDMMC_LOCK(sc); - AT91_QDMMC_UNLOCK(sc); - - // XXX do nothing since we don't lock for now - return 0; -} - -static void at91_qdmmc_strategy(struct bio *bp) -{ - struct at91_qdmmc_softc *sc; - - //printf("at91_qdmmc_strategy: called\n"); - sc = (struct at91_qdmmc_softc *)bp->bio_disk->d_drv1; - -#if 1 - AT91_QDMMC_LOCK(sc); - bioq_disksort(&sc->cards[0].bio_queue, bp); - wakeup(sc); - AT91_QDMMC_UNLOCK(sc); -#else - biofinish(bp, NULL, EIO); #endif -} -static void -at91_qdmmc_wait_ready(struct at91_qdmmc_softc *sc) -{ - int timeout = 100000; - - // Why doesn't this bit ever clear? It does in the boot loader. - printf("Waiting status %#x\n", RD4(sc, MCI_SR)); - while (!(RD4(sc, MCI_SR) & MCI_SR_NOTBUSY) && --timeout) - continue; - printf("Waited status %#x\n", RD4(sc, MCI_SR)); -} - -static void -at91_qdmmc_task(void *arg) -{ - struct at91_qdmmc_softc *sc = (struct at91_qdmmc_softc*)arg; - struct bio *bp; - int status; - bus_addr_t paddr; - int map = 0; - uint32_t *tmpbuf; - uint32_t rv; - int sz; - - tmpbuf = malloc(sc->cards[0].sector_size, M_DEVBUF, M_WAITOK); - AT91_QDMMC_LOCK(sc); - printf("at91_qdmmc_task: start\n"); - for (;;) { - do { - bp = bioq_first(&sc->cards[0].bio_queue); - if (bp == NULL) - msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); - } while (bp == NULL); - bioq_remove(&sc->cards[0].bio_queue, bp); - printf("at91_qdmmc_task: request %p\n", bp); - if (bp->bio_cmd == BIO_READ) { - printf("at91_qdmmc_task: read block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); - uint32_t block; - // Init Mode Register -// WR4(sc, MCI_MR, sc->cards[0].mode | MCI_MR_PDCMODE | -// (sc->cards[0].sector_size << 16)); - WR4(sc, MCI_MR, 0x8301 | (sc->cards[0].sector_size << 16)); - printf("mode 0x%x\n", RD4(sc, MCI_MR)); - sz = sc->cards[0].sector_size; - for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sz); block++) { - - printf("Waiting for not busy\n"); - // wait until completed - while (!(RD4(sc, MCI_SR) & MCI_SR_NOTBUSY)) - continue; - printf("Waiting for the card to become ready\n"); - do { - rv = at91_qdmmc_GetStatus(sc->dev, sc->cards[0].addr); - printf("."); - } while (rv != 0xffffffff && !(rv & AT91C_SR_READY_FOR_DATA)); - - char *vaddr = bp->bio_data + (block - bp->bio_pblkno) * sz; - - if (bus_dmamap_load(sc->dmatag, sc->map, vaddr, - sc->cards[0].sector_size, at91_getaddr, &paddr, 0) != 0) - goto out; - map = 1; - - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREREAD); - at91_qdmmc_wait_ready(sc); - WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); - WR4(sc, PDC_RPR, paddr); - WR4(sc, PDC_RCR, sz); - - printf("block = %#x vaddr = %p, RPR = 0x%x, RCR = 0x%x\n", block, vaddr, - RD4(sc, PDC_RPR), RD4(sc, PDC_RCR)); - printf("SR is %x before we get going\n", RD4(sc, MCI_SR)); - WR4(sc, MCI_IER, MCI_SR_ENDRX | 0xffff0000); - status = at91_qdmmc_SendCommand(sc->dev, READ_SINGLE_BLOCK_CMD, block * sz); - WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); - - printf("at91_qdmmc_task: read-status = 0x%x\n", status); - - // wait for completion - printf("TO SLEEP, PURCHANCE TO DREAM\n"); -#if 1 - msleep(sc, &sc->sc_mtx, PRIBIO, "endrx", 0); - printf("DONE SLEEPING\n"); -#endif - at91_qdmmc_wait_ready(sc); - printf("SR is %x\n", RD4(sc, MCI_SR)); -#if 1 - - // safety check - while ((RD4(sc, MCI_SR) & MCI_SR_ENDRX) == 0) - DELAY(700); -#endif - - printf("DONE WAITING\n"); - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->dmatag, sc->map); - map = 0; - - WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS); - /* Fix Byteorder (Atmel Errata) */ - uint32_t* base = (uint32_t*)vaddr; - for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { - uint32_t tmp = base[i]; - base[i] = (((tmp >> 24) & 0xff)) | - (((tmp >> 16) & 0xff) << 8) | - (((tmp >> 8) & 0xff) << 16) | - ((tmp & 0xff) << 24); - printf("%08x", base[i]); - } - printf("\n"); - } - printf("Delecting card!\n"); - status = at91_qdmmc_SendCommand(sc->dev, - SEL_DESEL_CARD_CMD, 0); - printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); - - // Reset Mode Register -// WR4(sc, MCI_MR, sc->cards[0].mode); - biodone(bp); - continue; - } - if (bp->bio_cmd == BIO_WRITE) { - printf("at91_qdmmc_task: write block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); - uint32_t block; - uint32_t *tmpbuf; - - // Init Mode Register -// WR4(sc, MCI_MR, sc->cards[0].mode | (sc->cards[0].sector_size << 16)); - printf("mode 0x%x\n", RD4(sc, MCI_MR)); - - status = at91_qdmmc_SendCommand(sc->dev, - SEL_DESEL_CARD_CMD, (sc->cards[0].addr) << 16); - printf("at91_qdmmc_task: select_card-status = 0x%x\n", status); - status = at91_qdmmc_SendCommand(sc->dev, - SET_BLOCKLEN_CMD, sc->cards[0].sector_size); - printf("at91_qdmmc_task: set_blocklen-status = 0x%x\n", status); - - tmpbuf = malloc(sc->cards[0].sector_size, M_DEVBUF, M_WAITOK); - for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sc->cards[0].sector_size); block++) { - char *vaddr = bp->bio_data + (block - bp->bio_pblkno) * sc->cards[0].sector_size; - - /* Fix Byteorder (Atmel Errata) */ - uint32_t* base = (uint32_t*)vaddr; - for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { - uint32_t tmp = base[i]; - tmpbuf[i] = (((tmp >> 24) & 0xff)) | - (((tmp >> 16) & 0xff) << 8) | - (((tmp >> 8) & 0xff) << 16) | - ((tmp & 0xff) << 24); - } - - WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); - - if (bus_dmamap_load(sc->dmatag, sc->map, tmpbuf, - sc->cards[0].sector_size, at91_getaddr, &paddr, 0) != 0) - goto out; - map = 1; - - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREWRITE); - WR4(sc, PDC_TPR, paddr); - WR4(sc, PDC_TCR, sc->cards[0].sector_size / 4); - - printf("status = 0x%x, tmpbuf = %p, TPR = 0x%x, TCR = 0x%x\n", status, tmpbuf, - RD4(sc, PDC_TPR), RD4(sc, PDC_TCR)); - status = at91_qdmmc_SendCommand(sc->dev, - WRITE_BLOCK_CMD, block * sc->cards[0].sector_size); - // printf("at91_qdmmc_task: write-status = 0x%x\n", status); - WR4(sc, MCI_IER, MCI_SR_NOTBUSY); - WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); - - // wait for completion - msleep(sc, &sc->sc_mtx, PRIBIO, "notbusy", 0); - // XXX don't know why this safety check is required - while ((RD4(sc, MCI_SR) & MCI_SR_NOTBUSY) == 0) - DELAY(700); - - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmatag, sc->map); - map = 0; - } - free(tmpbuf, M_DEVBUF); - - status = at91_qdmmc_SendCommand(sc->dev, - SEL_DESEL_CARD_CMD, 0); - printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); - - // Reset Mode Register -// WR4(sc, MCI_MR, sc->cards[0].mode); - biodone(bp); - continue; - } - -out: - if (map) - bus_dmamap_unload(sc->dmatag, sc->map); - status = at91_qdmmc_SendCommand(sc->dev, SEL_DESEL_CARD_CMD, 0); - printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); - AT91_QDMMC_UNLOCK(sc); - biofinish(bp, NULL, ENXIO); - } -} - -static device_method_t at91_qdmmc_methods[] = { - DEVMETHOD(device_probe, at91_qdmmc_probe), - DEVMETHOD(device_attach, at91_qdmmc_attach), - DEVMETHOD(device_detach, at91_qdmmc_detach), +static device_method_t at91_mci_methods[] = { + DEVMETHOD(device_probe, at91_mci_probe), + DEVMETHOD(device_attach, at91_mci_attach), + DEVMETHOD(device_detach, at91_mci_detach), {0, 0}, }; -static driver_t at91_qdmmc_driver = { - "at91_qdmmc", - at91_qdmmc_methods, - sizeof(struct at91_qdmmc_softc), +static driver_t at91_mci_driver = { + "at91_mci", + at91_mci_methods, + sizeof(struct at91_mci_softc), }; -static devclass_t at91_qdmmc_devclass; +static devclass_t at91_mci_devclass; -DRIVER_MODULE(at91_qdmmc, atmelarm, at91_qdmmc_driver, at91_qdmmc_devclass, 0, 0); +DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, 0, 0); static void -at91_qdmmc_intr(void *arg) +at91_mci_intr(void *arg) { - struct at91_qdmmc_softc *sc = (struct at91_qdmmc_softc*)arg; + struct at91_mci_softc *sc = (struct at91_mci_softc*)arg; - AT91_QDMMC_LOCK(sc); + AT91_MCI_LOCK(sc); printf("i 0x%x\n", RD4(sc, MCI_SR)); wakeup(sc); WR4(sc, MCI_IDR, 0xffffffff); - AT91_QDMMC_UNLOCK(sc); + AT91_MCI_UNLOCK(sc); } ==== //depot/projects/arm/src/sys/arm/at91/at91_mcireg.h#2 (text+ko) ==== @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2005 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 Berndt Walter. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $FreeBSD: src/sys/arm/at91/at91_streg.h,v 1.1 2006/02/04 23:32:13 imp Exp $ */ +/* $FreeBSD$ */ #ifndef ARM_AT91_AT91QDMMCREG_H #define ARM_AT91_AT91QDMMCREG_H @@ -65,7 +66,7 @@ #define MCI_DTOR_DTOMUL_1024 (0x4u << 4) /* (MCI) DTOCYC x 1024 */ #define MCI_DTOR_DTOMUL_4096 (0x5u << 4) /* (MCI) DTOCYC x 4096 */ #define MCI_DTOR_DTOMUL_65536 (0x6u << 4) /* (MCI) DTOCYC x 65536 */ -#define MCI_DTOR_DTOMUL_1048576 (0x7u << 4) /* (MCI) DTOCYC x 1048576 */ +#define MCI_DTOR_DTOMUL_1M (0x7u << 4) /* (MCI) DTOCYC x 1048576 */ /* -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register -------- */ #define MCI_SDCR_SCDSEL (0x1u << 0) /* (MCI) SD Card Selector */ #define MCI_SDCR_SCDBUS (0x1u << 7) /* (MCI) SD Card Bus Width */ ==== //depot/projects/arm/src/sys/arm/conf/TSC4370#8 (text+ko) ==== @@ -94,7 +94,10 @@ device at91_spi # SPI bridge support device at91_ssc device at91_tc -device at91_qdmmc +device at91_mci +#device mmcsd # mmc/sd bus +#device mmc # mmc flash card >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609230052.k8N0q6Dw091998>