summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/at91/at91_machdep.c16
-rw-r--r--sys/arm/at91/at91_mci.c60
-rw-r--r--sys/arm/at91/at91reg.h1
-rw-r--r--sys/arm/at91/at91rm92reg.h4
-rw-r--r--sys/arm/at91/files.at91sam96
-rw-r--r--sys/arm/at91/std.at91sam91
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
OpenPOWER on IntegriCloud