diff options
-rw-r--r-- | sys/arm/at91/at91_machdep.c | 16 | ||||
-rw-r--r-- | sys/arm/at91/at91_mci.c | 60 | ||||
-rw-r--r-- | sys/arm/at91/at91reg.h | 1 | ||||
-rw-r--r-- | sys/arm/at91/at91rm92reg.h | 4 | ||||
-rw-r--r-- | sys/arm/at91/files.at91sam9 | 6 | ||||
-rw-r--r-- | sys/arm/at91/std.at91sam9 | 1 |
6 files changed, 68 insertions, 20 deletions
diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index 28e6913..7b165a8 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -209,12 +209,11 @@ const struct pmap_devmap at91_devmap[] = { long at91_ramsize(void) { - uint32_t *SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE); uint32_t cr, mr; int banks, rows, cols, bw; if (at91_is_rm92()) { - SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE); + uint32_t *SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE); cr = SDRAMC[AT91RM92_SDRAMC_CR / 4]; mr = SDRAMC[AT91RM92_SDRAMC_MR / 4]; banks = (cr & AT91RM92_SDRAMC_CR_NB_4) ? 2 : 1; @@ -222,9 +221,9 @@ at91_ramsize(void) cols = (cr & AT91RM92_SDRAMC_CR_NC_MASK) + 8; bw = (mr & AT91RM92_SDRAMC_MR_DBW_16) ? 1 : 2; } else { - /* This should be good for the 9260, 9261 and 9G20 as addresses + /* This should be good for the 9260, 9261, 9G20, 9G35 and 9X25 as addresses * and registers are the same */ - SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G20_SDRAMC_BASE); + uint32_t *SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G20_SDRAMC_BASE); cr = SDRAMC[AT91SAM9G20_SDRAMC_CR / 4]; mr = SDRAMC[AT91SAM9G20_SDRAMC_MR / 4]; banks = (cr & AT91SAM9G20_SDRAMC_CR_NB_4) ? 2 : 1; @@ -361,12 +360,13 @@ initarm(void *arg, void *arg2) cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); - cninit(); + /* Initialize all the clocks, so that the console can work */ + at91_pmc_init_clock(); - at91_pmc_init_clock(); /* Get chip id so device drivers know about differences */ - at91_chip_id = *(volatile uint32_t *) - (AT91_BASE + AT91_DBGU_BASE + DBGU_C1R); + at91_chip_id = *(uint32_t *)(AT91_BASE + AT91_DBGU_BASE + DBGU_C1R); + + cninit(); memsize = board_init(); physmem = memsize / PAGE_SIZE; diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index 56cff68..62c35d2 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -69,6 +69,11 @@ __FBSDID("$FreeBSD$"); #define BBSZ 512 +/* + * Note: This driver only supports the SlotA card. No attempt has been made + * to support SlotB. + */ + struct at91_mci_softc { void *intrhand; /* Interrupt handle */ device_t dev; @@ -244,6 +249,13 @@ at91_mci_attach(device_t dev) sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; sc->host.caps = 0; + /* + * The in-tree Linux driver doesn't allow 4-wire operation for the + * at91rm9200, but does for other members of the family. The atmel + * patches to this do allow it, or have in the past. It is unclear + * that the hardware even works, but my boot loader uses 4-bit bus + * in polling mode successfully. + */ if (sc->sc_cap & CAP_HAS_4WIRE) sc->host.caps |= MMC_CAP_4_BIT_DATA; child = device_add_child(dev, "mmc", 0); @@ -363,9 +375,9 @@ at91_mci_update_ios(device_t brdev, device_t reqdev) clkdiv = (at91_master_clock / ios->clock) / 2; } if (ios->bus_width == bus_width_4) - WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) | MCI_SDCR_SDCBUS); + WR4(sc, MCI_SDCR, MCI_SDCR_SDCBUS); else - WR4(sc, MCI_SDCR, RD4(sc, MCI_SDCR) & ~MCI_SDCR_SDCBUS); + WR4(sc, MCI_SDCR, 0); WR4(sc, MCI_MR, (RD4(sc, MCI_MR) & ~MCI_MR_CLKDIV) | clkdiv); /* Do we need a settle time here? */ /* XXX We need to turn the device on/off here with a GPIO pin */ @@ -407,7 +419,9 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) if (!data) { // The no data case is fairly simple at91_mci_pdc_disable(sc); -// printf("CMDR %x ARGR %x\n", cmdr, cmd->arg); +#ifdef AT91_MCI_DEBUG + printf("CMDR %x ARGR %x\n", cmdr, cmd->arg); +#endif WR4(sc, MCI_ARGR, cmd->arg); WR4(sc, MCI_CMDR, cmdr); WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY); @@ -479,7 +493,9 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) ier = MCI_SR_TXBUFE; } } -// printf("CMDR %x ARGR %x with data\n", cmdr, cmd->arg); +#ifdef AT91_MCI_DEBUG + printf("CMDR %x ARGR %x with data\n", cmdr, cmd->arg); +#endif WR4(sc, MCI_ARGR, cmd->arg); if (cmdr & MCI_CMDR_TRCMD_START) { if (cmdr & MCI_CMDR_TRDIR) { @@ -518,6 +534,14 @@ at91_mci_start(struct at91_mci_softc *sc) sc->req = NULL; sc->curcmd = NULL; req->done(req); + /* + * Attempted hack-a-round for the DMA bug for multiple reads. + */ + if (req->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) { + at91_mci_fini(sc->dev); + at91_mci_init(sc->dev); + at91_mci_update_ios(sc->dev, NULL); + } } static int @@ -578,7 +602,9 @@ at91_mci_read_done(struct at91_mci_softc *sc) uint32_t *walker; struct mmc_command *cmd; int i, len; - +#ifdef AT91_MCI_DEBUG + char *w2; +#endif cmd = sc->curcmd; bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->dmatag, sc->map); @@ -589,6 +615,15 @@ at91_mci_read_done(struct at91_mci_softc *sc) for (i = 0; i < len; i++) walker[i] = bswap32(walker[i]); } +#ifdef AT91_MCI_DEBUG + printf("Read data\n"); + for (i = 0, w2 = cmd->data->data; i < cmd->data->len; i++) { + if (i % 16 == 0) + printf("%08x ", cmd->arg + i); + printf("%02x%s", w2[i], (i + 1) % 16 ? " " : "\n"); + } + printf("\n"); +#endif // Finish up the sequence... WR4(sc, MCI_IDR, MCI_SR_ENDRX); WR4(sc, MCI_IER, MCI_SR_RXBUFF); @@ -624,14 +659,19 @@ at91_mci_intr(void *arg) if ((sr & MCI_SR_RCRCE) && (cmd->opcode == MMC_SEND_OP_COND || cmd->opcode == ACMD_SD_SEND_OP_COND)) cmd->error = MMC_ERR_NONE; - else if (sr & (MCI_SR_RTOE | MCI_SR_DTOE)) + else if (sr & (MCI_SR_RTOE | MCI_SR_DTOE)) { + printf("TIMEOUT %#x\n", sr); cmd->error = MMC_ERR_TIMEOUT; - else if (sr & (MCI_SR_RCRCE | MCI_SR_DCRCE)) + } else if (sr & (MCI_SR_RCRCE | MCI_SR_DCRCE)) { + printf("CRC %#x\n", sr); cmd->error = MMC_ERR_BADCRC; - else if (sr & (MCI_SR_OVRE | MCI_SR_UNRE)) + } else if (sr & (MCI_SR_OVRE | MCI_SR_UNRE)) { + printf("FIFO %#x\n", sr); cmd->error = MMC_ERR_FIFO; - else + } else { + printf("FAILED %#x\n", sr); cmd->error = MMC_ERR_FAILED; + } done = 1; if (sc->mapped && cmd->error) { bus_dmamap_unload(sc->dmatag, sc->map); @@ -743,7 +783,7 @@ at91_mci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) *(int *)result = sc->host.caps; break; case MMCBR_IVAR_MAX_DATA: - *(int *)result = 1; + *(int *)result = 1024; break; } return (0); diff --git a/sys/arm/at91/at91reg.h b/sys/arm/at91/at91reg.h index 7493de8..0cd7163 100644 --- a/sys/arm/at91/at91reg.h +++ b/sys/arm/at91/at91reg.h @@ -67,6 +67,7 @@ #define AT91_CPU_SAM9XE128 0x329973a0 #define AT91_CPU_SAM9XE256 0x329a93a0 #define AT91_CPU_SAM9XE512 0x329aa3a0 +#define AT91_CPU_SAM9X25 0x819a05a0 /* Same as the SAM9G35 */ #define AT91_ARCH(chipid) ((chipid >> 20) & 0xff) #define AT91_CPU(chipid) (chipid & ~AT91_CPU_VERSION_MASK) diff --git a/sys/arm/at91/at91rm92reg.h b/sys/arm/at91/at91rm92reg.h index 401d67c..1b2c280 100644 --- a/sys/arm/at91/at91rm92reg.h +++ b/sys/arm/at91/at91rm92reg.h @@ -399,6 +399,10 @@ #define AT91RM92_OHCI_PA_BASE 0x00300000 #define AT91RM92_OHCI_SIZE 0x00100000 +#define AT91RM92_FLS_BASE 0xdf000000 +#define AT91RM92_FLS_PA_BASE 0x10000000 +#define AT91RM92_FLS_SIZE 0x02000000 /* Support up to 32MB flash */ + #define AT91RM92_CF_BASE 0xdfd00000 #define AT91RM92_CF_PA_BASE 0x51400000 #define AT91RM92_CF_SIZE 0x00100000 diff --git a/sys/arm/at91/files.at91sam9 b/sys/arm/at91/files.at91sam9 index a05f883..706cc09 100644 --- a/sys/arm/at91/files.at91sam9 +++ b/sys/arm/at91/files.at91sam9 @@ -25,13 +25,15 @@ dev/usb/controller/ohci_atmelarm.c optional ohci # # All the "systems on a chip" we support # -arm/at91/at91sam9g20.c optional at91sam9g20 arm/at91/at91sam9260.c optional at91sam9260 +arm/at91/at91sam9g20.c optional at91sam9g20 +arm/at91/at91sam9x25.c optional at91sam9x25 # # # All the boards we support # arm/at91/board_ethernut5.c optional at91_board_ethernut5 arm/at91/board_hl201.c optional at91_board_hl201 -arm/at91/board_sam9g20ek.c optional at91_board_sam9g20ek arm/at91/board_qila9g20.c optional at91_board_qila9g20 +arm/at91/board_sam9g20ek.c optional at91_board_sam9g20ek +arm/at91/board_sam9x25ek.c optional at91_board_sam9x25ek diff --git a/sys/arm/at91/std.at91sam9 b/sys/arm/at91/std.at91sam9 index ab1fa95..6e7ba79 100644 --- a/sys/arm/at91/std.at91sam9 +++ b/sys/arm/at91/std.at91sam9 @@ -7,3 +7,4 @@ options PHYSADDR=0x20000000 device at91sam9g20 device at91sam9260 +device at91sam9x25 |