summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2012-06-01 02:55:42 +0000
committerimp <imp@FreeBSD.org>2012-06-01 02:55:42 +0000
commitefd4b91d2ad754279cdcf0d60327eb7eea86523a (patch)
tree770e2102502eadbba882cf074fa93784b15e80d6
parent561f6739ea31a62502eb6920aacd8d77195503b7 (diff)
downloadFreeBSD-src-efd4b91d2ad754279cdcf0d60327eb7eea86523a.zip
FreeBSD-src-efd4b91d2ad754279cdcf0d60327eb7eea86523a.tar.gz
Initialize the clocks before we call cninit() so that the serial
console so initialized will work upon return from cninit. While this is the very next line, other platforms setup all this stuff before calling cninit. Also, initialize the SDRAM base register in the inner block in at91_ramsize().
-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