Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 102168
b: refs/heads/master
c: c5a89c6
h: refs/heads/master
v: v3
  • Loading branch information
Marc Pignat authored and Pierre Ossman committed Jul 15, 2008
1 parent ec263a4 commit f716ff0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e181dce8acab4f7d7c4772d2a8281510d503ab21
refs/heads/master: c5a89c6c0805959f813e8342d6f4040860f6d7db
48 changes: 48 additions & 0 deletions trunk/drivers/mmc/host/at91_mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,43 @@ struct at91mci_host
struct timer_list timer;
};

/*
* Reset the controller and restore most of the state
*/
static void at91_reset_host(struct at91mci_host *host)
{
unsigned long flags;
u32 mr;
u32 sdcr;
u32 dtor;
u32 imr;

local_irq_save(flags);
imr = at91_mci_read(host, AT91_MCI_IMR);

at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);

/* save current state */
mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
sdcr = at91_mci_read(host, AT91_MCI_SDCR);
dtor = at91_mci_read(host, AT91_MCI_DTOR);

/* reset the controller */
at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);

/* restore state */
at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
at91_mci_write(host, AT91_MCI_MR, mr);
at91_mci_write(host, AT91_MCI_SDCR, sdcr);
at91_mci_write(host, AT91_MCI_DTOR, dtor);
at91_mci_write(host, AT91_MCI_IER, imr);

/* make sure sdio interrupts will fire */
at91_mci_read(host, AT91_MCI_SR);

local_irq_restore(flags);
}

static void at91_timeout_timer(unsigned long data)
{
struct at91mci_host *host;
Expand All @@ -148,6 +185,7 @@ static void at91_timeout_timer(unsigned long data)
host->request->cmd->error = -ETIMEDOUT;
}

at91_reset_host(host);
mmc_request_done(host->mmc, host->request);
}
}
Expand Down Expand Up @@ -512,6 +550,11 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
mr |= AT91_MCI_PDCMODE;
at91_mci_write(host, AT91_MCI_MR, mr);

if (!cpu_is_at91rm9200())
at91_mci_write(host, AT91_MCI_BLKR,
AT91_MCI_BLKR_BCNT(blocks) |
AT91_MCI_BLKR_BLKLEN(block_length));

/*
* Disable the PDC controller
*/
Expand Down Expand Up @@ -584,6 +627,11 @@ static void at91_mci_process_next(struct at91mci_host *host)
at91_mci_send_command(host, host->request->stop);
} else {
del_timer(&host->timer);
/* the at91rm9200 mci controller hangs after some transfers,
* and the workaround is to reset it after each transfer.
*/
if (cpu_is_at91rm9200())
at91_reset_host(host);
mmc_request_done(host->mmc, host->request);
}
}
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/asm-arm/arch-at91/at91_mci.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
#define AT91_MCI_TRTYP_MULTIPLE (1 << 19)
#define AT91_MCI_TRTYP_STREAM (2 << 19)

#define AT91_MCI_BLKR 0x18 /* Block Register */
#define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */
#define AT91_MCI_BLKR_BLKLEN(n) ((0xffff & (n)) << 16) /* Block lenght */

#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */
#define AT91_MCR_RDR 0x30 /* Receive Data Register */
#define AT91_MCR_TDR 0x34 /* Transmit Data Register */
Expand Down

0 comments on commit f716ff0

Please sign in to comment.