removed more useless SD code

This commit is contained in:
bushing 2009-10-26 14:41:40 -07:00
parent 661a30fc21
commit fa08fede1e
4 changed files with 175 additions and 335 deletions

253
sdhc.c
View File

@ -36,12 +36,13 @@
#include "ipc.h" #include "ipc.h"
#endif #endif
struct sdhc_host sc_host;
//#define SDHC_DEBUG //#define SDHC_DEBUG
#define SDHC_COMMAND_TIMEOUT 500 #define SDHC_COMMAND_TIMEOUT 500
#define SDHC_TRANSFER_TIMEOUT 5000 #define SDHC_TRANSFER_TIMEOUT 5000
#define sdmmc_delay(t) udelay(t)
#define sdhc_wait_intr(a,b,c) sdhc_wait_intr_debug(__func__, __LINE__, a, b, c) #define sdhc_wait_intr(a,b,c) sdhc_wait_intr_debug(__func__, __LINE__, a, b, c)
static inline u32 bus_space_read_4(bus_space_handle_t ioh, u32 reg) static inline u32 bus_space_read_4(bus_space_handle_t ioh, u32 reg)
@ -142,11 +143,8 @@ void sdhc_dump_regs(struct sdhc_host *);
* host controller standard register set. (1.3) * host controller standard register set. (1.3)
*/ */
int int
sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot, sdhc_host_found(bus_space_tag_t iot, bus_space_handle_t ioh, int usedma)
bus_space_handle_t ioh, int usedma)
{ {
struct sdmmcbus_attach_args saa;
struct sdhc_host *hp;
u_int32_t caps; u_int32_t caps;
int error = 1; int error = 1;
@ -166,46 +164,38 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
} }
#endif #endif
/* Allocate one more host structure. */ memset(&sc_host, 0, sizeof(sc_host));
if (sc->sc_nhosts < SDHC_MAX_HOSTS) {
sc->sc_nhosts++;
hp = &sc->sc_host[sc->sc_nhosts - 1];
memset(hp, 0, sizeof(*hp));
}
else
return -EINVAL;
/* Fill in the new host structure. */ /* Fill in the new host structure. */
hp->sc = sc; sc_host.iot = iot;
hp->iot = iot; sc_host.ioh = ioh;
hp->ioh = ioh; sc_host.data_command = 0;
hp->data_command = 0;
/* /*
* Reset the host controller and enable interrupts. * Reset the host controller and enable interrupts.
*/ */
(void)sdhc_host_reset(hp); (void)sdhc_host_reset(&sc_host);
/* Determine host capabilities. */ /* Determine host capabilities. */
caps = HREAD4(hp, SDHC_CAPABILITIES); caps = HREAD4(&sc_host, SDHC_CAPABILITIES);
/* Use DMA if the host system and the controller support it. */ /* Use DMA if the host system and the controller support it. */
if (usedma && ISSET(caps, SDHC_DMA_SUPPORT)) if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
SET(hp->flags, SHF_USE_DMA); SET(sc_host.flags, SHF_USE_DMA);
/* /*
* Determine the base clock frequency. (2.2.24) * Determine the base clock frequency. (2.2.24)
*/ */
if (SDHC_BASE_FREQ_KHZ(caps) != 0) if (SDHC_BASE_FREQ_KHZ(caps) != 0)
hp->clkbase = SDHC_BASE_FREQ_KHZ(caps); sc_host.clkbase = SDHC_BASE_FREQ_KHZ(caps);
if (hp->clkbase == 0) { if (sc_host.clkbase == 0) {
/* The attachment driver must tell us. */ /* The attachment driver must tell us. */
gecko_printf("sdhc: base clock frequency unknown\n"); gecko_printf("sdhc: base clock frequency unknown\n");
goto err; goto err;
} else if (hp->clkbase < 10000 || hp->clkbase > 63000) { } else if (sc_host.clkbase < 10000 || sc_host.clkbase > 63000) {
/* SDHC 1.0 supports only 10-63 MHz. */ /* SDHC 1.0 supports only 10-63 MHz. */
gecko_printf("sdhc: base clock frequency out of range: %u MHz\n", gecko_printf("sdhc: base clock frequency out of range: %u MHz\n",
hp->clkbase / 1000); sc_host.clkbase / 1000);
goto err; goto err;
} }
@ -214,41 +204,17 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
* capabilities. (2.2.15) * capabilities. (2.2.15)
*/ */
SET(hp->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V); SET(sc_host.ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
/*
* Determine the maximum block length supported by the host
* controller. (2.2.24)
*/
switch((caps >> SDHC_MAX_BLK_LEN_SHIFT) & SDHC_MAX_BLK_LEN_MASK) {
case SDHC_MAX_BLK_LEN_512:
hp->maxblklen = 512;
break;
case SDHC_MAX_BLK_LEN_1024:
hp->maxblklen = 1024;
break;
case SDHC_MAX_BLK_LEN_2048:
hp->maxblklen = 2048;
break;
default:
hp->maxblklen = 1;
break;
}
/* /*
* Attach the generic SD/MMC bus driver. (The bus driver must * Attach the generic SD/MMC bus driver. (The bus driver must
* not invoke any chipset functions before it is attached.) * not invoke any chipset functions before it is attached.)
*/ */
bzero(&saa, sizeof(saa)); sdmmc_attach(&sc_host);
saa.saa_busname = "sdmmc";
saa.sch = hp;
sdmmc_attach(hp, "sdhc", ioh);
return 0; return 0;
err: err:
sc->sc_nhosts--;
return (error); return (error);
} }
@ -257,17 +223,10 @@ err:
* Shutdown hook established by or called from attachment driver. * Shutdown hook established by or called from attachment driver.
*/ */
void void
sdhc_shutdown(void *arg) sdhc_shutdown(void)
{ {
struct sdhc_softc *sc = arg;
struct sdhc_host *hp;
int i;
/* XXX chip locks up if we don't disable it before reboot. */ /* XXX chip locks up if we don't disable it before reboot. */
for (i = 0; i < sc->sc_nhosts; i++) { (void)sdhc_host_reset(&sc_host);
hp = &sc->sc_host[i];
(void)sdhc_host_reset(hp);
}
} }
#endif #endif
@ -276,9 +235,8 @@ sdhc_shutdown(void *arg)
* cards are removed, upon resume, and during error recovery. * cards are removed, upon resume, and during error recovery.
*/ */
int int
sdhc_host_reset(sdmmc_chipset_handle_t sch) sdhc_host_reset(struct sdhc_host *hp)
{ {
struct sdhc_host *hp = sch;
u_int16_t imask; u_int16_t imask;
int error; int error;
@ -313,27 +271,12 @@ sdhc_host_reset(sdmmc_chipset_handle_t sch)
return 0; return 0;
} }
u_int32_t
sdhc_host_ocr(sdmmc_chipset_handle_t sch)
{
struct sdhc_host *hp = sch;
return hp->ocr;
}
int
sdhc_host_maxblklen(sdmmc_chipset_handle_t sch)
{
struct sdhc_host *hp = sch;
return hp->maxblklen;
}
/* /*
* Return non-zero if the card is currently inserted. * Return non-zero if the card is currently inserted.
*/ */
int int
sdhc_card_detect(sdmmc_chipset_handle_t sch) sdhc_card_detect(struct sdhc_host *hp)
{ {
struct sdhc_host *hp = sch;
return ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED) ? return ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED) ?
1 : 0; 1 : 0;
} }
@ -343,10 +286,8 @@ sdhc_card_detect(sdmmc_chipset_handle_t sch)
* Return zero on success. * Return zero on success.
*/ */
int int
sdhc_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr) sdhc_bus_power(struct sdhc_host *hp, u_int32_t ocr)
{ {
struct sdhc_host *hp = sch;
gecko_printf("sdhc_bus_power(%u)\n", ocr); gecko_printf("sdhc_bus_power(%u)\n", ocr);
/* Disable bus power before voltage change. */ /* Disable bus power before voltage change. */
HWRITE1(hp, SDHC_POWER_CTL, 0); HWRITE1(hp, SDHC_POWER_CTL, 0);
@ -363,7 +304,7 @@ sdhc_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr)
*/ */
HWRITE1(hp, SDHC_POWER_CTL, (SDHC_VOLTAGE_3_3V << SDHC_VOLTAGE_SHIFT) | HWRITE1(hp, SDHC_POWER_CTL, (SDHC_VOLTAGE_3_3V << SDHC_VOLTAGE_SHIFT) |
SDHC_BUS_POWER); SDHC_BUS_POWER);
sdmmc_delay(10000); udelay(10000);
/* /*
* The host system may not power the bus due to battery low, * The host system may not power the bus due to battery low,
@ -399,12 +340,10 @@ sdhc_clock_divisor(struct sdhc_host *hp, u_int freq)
* Return zero on success. * Return zero on success.
*/ */
int int
sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq) sdhc_bus_clock(struct sdhc_host *hp, int freq)
{ {
struct sdhc_host *hp = sch;
int div; int div;
int timo; int timo;
int error = 0;
gecko_printf("%s(%d)\n", __FUNCTION__, freq); gecko_printf("%s(%d)\n", __FUNCTION__, freq);
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
@ -414,52 +353,39 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
gecko_printf("sdhc_sdclk_frequency_select: command in progress\n"); gecko_printf("sdhc_sdclk_frequency_select: command in progress\n");
#endif #endif
/* /* Stop SD clock before changing the frequency. */
* Stop SD clock before changing the frequency.
*/
HWRITE2(hp, SDHC_CLOCK_CTL, 0); HWRITE2(hp, SDHC_CLOCK_CTL, 0);
if (freq == SDMMC_SDCLK_OFF) if (freq == SDMMC_SDCLK_OFF)
goto ret; return 0;
/* /* Set the minimum base clock frequency divisor. */
* Set the minimum base clock frequency divisor.
*/
if ((div = sdhc_clock_divisor(hp, freq)) < 0) { if ((div = sdhc_clock_divisor(hp, freq)) < 0) {
/* Invalid base clock frequency or `freq' value. */ /* Invalid base clock frequency or `freq' value. */
error = EINVAL; return EINVAL;
goto ret;
} }
HWRITE2(hp, SDHC_CLOCK_CTL, div << SDHC_SDCLK_DIV_SHIFT); HWRITE2(hp, SDHC_CLOCK_CTL, div << SDHC_SDCLK_DIV_SHIFT);
/* /* Start internal clock. Wait 10ms for stabilization. */
* Start internal clock. Wait 10ms for stabilization.
*/
HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE); HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE);
for (timo = 1000; timo > 0; timo--) { for (timo = 1000; timo > 0; timo--) {
if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE)) if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE))
break; break;
sdmmc_delay(10); udelay(10);
} }
if (timo == 0) { if (timo == 0) {
gecko_printf("sdhc: internal clock never stabilized\n"); gecko_printf("sdhc: internal clock never stabilized\n");
error = ETIMEDOUT; return ETIMEDOUT;
goto ret;
} }
/* /* Enable SD clock. */
* Enable SD clock.
*/
HSET2(hp, SDHC_CLOCK_CTL, SDHC_SDCLK_ENABLE); HSET2(hp, SDHC_CLOCK_CTL, SDHC_SDCLK_ENABLE);
ret: return 0;
return error;
} }
void void
sdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable) sdhc_card_intr_mask(struct sdhc_host *hp, int enable)
{ {
struct sdhc_host *hp = sch;
if (enable) { if (enable) {
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT); HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
@ -470,10 +396,8 @@ sdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable)
} }
void void
sdhc_card_intr_ack(sdmmc_chipset_handle_t sch) sdhc_card_intr_ack(struct sdhc_host *hp)
{ {
struct sdhc_host *hp = sch;
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
} }
@ -487,16 +411,15 @@ sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value)
if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask) if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask)
== value) == value)
return 0; return 0;
sdmmc_delay(10000); udelay(10000);
} }
DPRINTF(0,("sdhc: timeout waiting for %x (state=%d)\n", value, state)); DPRINTF(0,("sdhc: timeout waiting for %x (state=%d)\n", value, state));
return ETIMEDOUT; return ETIMEDOUT;
} }
void void
sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) sdhc_exec_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
{ {
struct sdhc_host *hp = sch;
int error; int error;
if (cmd->c_datalen > 0) if (cmd->c_datalen > 0)
@ -509,8 +432,7 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
cmd->c_timeout = SDHC_COMMAND_TIMEOUT; cmd->c_timeout = SDHC_COMMAND_TIMEOUT;
} }
hp->intr_status = 0;
sdhc_reset_intr_status(hp);
/* /*
* Start the MMC command, or mark `cmd' as failed and return. * Start the MMC command, or mark `cmd' as failed and return.
@ -563,9 +485,6 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
if (cmd->c_error == 0 && cmd->c_datalen > 0) if (cmd->c_error == 0 && cmd->c_datalen > 0)
sdhc_transfer_data(hp, cmd); sdhc_transfer_data(hp, cmd);
/* Turn off the LED. */
HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
DPRINTF(1,("sdhc: cmd %u done (flags=%#x error=%d prev state=%d)\n", DPRINTF(1,("sdhc: cmd %u done (flags=%#x error=%d prev state=%d)\n",
cmd->c_opcode, cmd->c_flags, cmd->c_error, (cmd->c_resp[0] >> 9) & 15)); cmd->c_opcode, cmd->c_flags, cmd->c_error, (cmd->c_resp[0] >> 9) & 15));
SET(cmd->c_flags, SCF_ITSDONE); SET(cmd->c_flags, SCF_ITSDONE);
@ -647,9 +566,6 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
if ((error = sdhc_wait_state(hp, SDHC_CMD_INHIBIT_MASK, 0)) != 0) if ((error = sdhc_wait_state(hp, SDHC_CMD_INHIBIT_MASK, 0)) != 0)
return error; return error;
/* Alert the user not to remove the card. */
HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
if (ISSET(hp->flags, SHF_USE_DMA) && cmd->c_datalen > 0) { if (ISSET(hp->flags, SHF_USE_DMA) && cmd->c_datalen > 0) {
cmd->c_resid = blkcount; cmd->c_resid = blkcount;
cmd->c_buf = cmd->c_data; cmd->c_buf = cmd->c_data;
@ -751,7 +667,7 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
for (timo = 10; timo > 0; timo--) { for (timo = 10; timo > 0; timo--) {
if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
break; break;
sdmmc_delay(10000); udelay(10000);
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
} }
if (timo == 0) { if (timo == 0) {
@ -762,12 +678,6 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
return (0); return (0);
} }
void sdhc_reset_intr_status(struct sdhc_host *hp)
{
hp->intr_status = 0;
}
int int
sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int mask, int timo) sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int mask, int timo)
{ {
@ -778,7 +688,6 @@ sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int m
status = hp->intr_status & mask; status = hp->intr_status & mask;
for (; timo > 0; timo--) { for (; timo > 0; timo--) {
#ifndef CAN_HAZ_IRQ #ifndef CAN_HAZ_IRQ
sdhc_irq(); // seems backwards but ok sdhc_irq(); // seems backwards but ok
@ -825,78 +734,61 @@ sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int m
* Established by attachment driver at interrupt priority IPL_SDMMC. * Established by attachment driver at interrupt priority IPL_SDMMC.
*/ */
int int
sdhc_intr(void *arg) sdhc_intr(void)
{ {
struct sdhc_softc *sc = arg;
int host;
int done = 0;
/* We got an interrupt, but we don't know from which slot. */
for (host = 0; host < sc->sc_nhosts; host++) {
struct sdhc_host *hp = &sc->sc_host[host];
u_int16_t status; u_int16_t status;
if (hp == NULL) DPRINTF(1,("shdc_intr():\n"));
continue; sdhc_dump_regs(&sc_host);
DPRINTF(1,("shdc_intr(%d):\n", host));
sdhc_dump_regs(hp);
/* Find out which interrupts are pending. */ /* Find out which interrupts are pending. */
status = HREAD2(hp, SDHC_NINTR_STATUS); status = HREAD2(&sc_host, SDHC_NINTR_STATUS);
if (!ISSET(status, SDHC_NINTR_STATUS_MASK)) if (!ISSET(status, SDHC_NINTR_STATUS_MASK)) {
continue; /* no interrupt for us */ DPRINTF(1, ("unknown interrupt\n"));
return 0;
}
/* Acknowledge the interrupts we are about to handle. */ /* Acknowledge the interrupts we are about to handle. */
HWRITE2(hp, SDHC_NINTR_STATUS, status); HWRITE2(&sc_host, SDHC_NINTR_STATUS, status);
DPRINTF(2,("sdhc: interrupt status=%d\n", status)); DPRINTF(2,("sdhc: interrupt status=%d\n", status));
/* Service error interrupts. */
/* Claim this interrupt. */
done = 1;
/*
* Service error interrupts.
*/
if (ISSET(status, SDHC_ERROR_INTERRUPT)) { if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
u_int16_t error; u_int16_t error;
u_int16_t signal; u_int16_t signal;
/* Acknowledge error interrupts. */ /* Acknowledge error interrupts. */
error = HREAD2(hp, SDHC_EINTR_STATUS); error = HREAD2(&sc_host, SDHC_EINTR_STATUS);
signal = HREAD2(hp, SDHC_EINTR_SIGNAL_EN); signal = HREAD2(&sc_host, SDHC_EINTR_SIGNAL_EN);
HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, 0); HWRITE2(&sc_host, SDHC_EINTR_SIGNAL_EN, 0);
(void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD); (void)sdhc_soft_reset(&sc_host, SDHC_RESET_DAT|SDHC_RESET_CMD);
if (hp->data_command == 1) { if (sc_host.data_command == 1) {
hp->data_command = 0; sc_host.data_command = 0;
// TODO: add a way to send commands from irq // TODO: add a way to send commands from irq
// context and uncomment this // context and uncomment this
// sdmmc_abort(); // sdmmc_abort();
} }
HWRITE2(hp, SDHC_EINTR_STATUS, error); HWRITE2(&sc_host, SDHC_EINTR_STATUS, error);
HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, signal); HWRITE2(&sc_host, SDHC_EINTR_SIGNAL_EN, signal);
DPRINTF(2,("sdhc: error interrupt, status=%d\n", error)); DPRINTF(2,("sdhc: error interrupt, status=%d\n", error));
if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR| if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR|
SDHC_DATA_TIMEOUT_ERROR)) { SDHC_DATA_TIMEOUT_ERROR)) {
hp->intr_error_status |= error; sc_host.intr_error_status |= error;
hp->intr_status |= status; sc_host.intr_status |= status;
} }
} }
#ifdef CAN_HAZ_IPC #ifdef CAN_HAZ_IPC
/* /* Wake up the sdmmc event thread to scan for cards. */
* Wake up the sdmmc event thread to scan for cards.
*/
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) {
// this pushes a request to the slow queue so that we // this pushes a request to the slow queue so that we
// don't block other IRQs. // don't block other IRQs.
ipc_enqueue_slow(IPC_DEV_SDHC, IPC_SDHC_DISCOVER, 0); ipc_enqueue_slow(IPC_DEV_SDHC, IPC_SDHC_DISCOVER, 0);
} }
#endif #endif
/* /*
* Wake up the blocking process to service command * Wake up the blocking process to service command
* related interrupt(s). * related interrupt(s).
@ -904,19 +796,15 @@ sdhc_intr(void *arg)
if (ISSET(status, SDHC_BUFFER_READ_READY| if (ISSET(status, SDHC_BUFFER_READ_READY|
SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE| SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE|
SDHC_TRANSFER_COMPLETE|SDHC_DMA_INTERRUPT)) { SDHC_TRANSFER_COMPLETE|SDHC_DMA_INTERRUPT)) {
hp->intr_status |= status; sc_host.intr_status |= status;
} }
/* /* Service SD card interrupts. */
* Service SD card interrupts.
*/
if (ISSET(status, SDHC_CARD_INTERRUPT)) { if (ISSET(status, SDHC_CARD_INTERRUPT)) {
// DPRINTF(0,("%s: card interrupt\n", HDEVNAME(hp))); DPRINTF(0,("sdhc: card interrupt\n"));
HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); HCLR2(&sc_host, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
// sdmmc_card_intr(hp->sdmmc);
} }
} return 1;
return done;
} }
#ifdef SDHC_DEBUG #ifdef SDHC_DEBUG
@ -947,15 +835,10 @@ sdhc_dump_regs(struct sdhc_host *hp)
#endif #endif
#include "hollywood.h" #include "hollywood.h"
#ifdef LOADER
static struct sdhc_softc __softc;
#else
static struct sdhc_softc __softc MEM2_BSS;
#endif
void sdhc_irq(void) void sdhc_irq(void)
{ {
sdhc_intr(&__softc); sdhc_intr();
} }
void sdhc_init(void) void sdhc_init(void)
@ -963,10 +846,7 @@ void sdhc_init(void)
#ifdef CAN_HAZ_IRQ #ifdef CAN_HAZ_IRQ
irq_enable(IRQ_SDHC); irq_enable(IRQ_SDHC);
#endif #endif
memset(&__softc, 0, sizeof(__softc)); sdhc_host_found(0, SDHC_REG_BASE, 1);
sdhc_host_found(&__softc, 0, SDHC_REG_BASE, 1);
// sdhc_host_found(&__softc, 0, SDHC_REG_BASE + 0x100, 1);
// sdhc_host_found(&__softc, 0, 0x0d080000, 1);
} }
void sdhc_exit(void) void sdhc_exit(void)
@ -987,6 +867,7 @@ void sdhc_ipc(volatile ipc_request *req)
case IPC_SDHC_EXIT: case IPC_SDHC_EXIT:
sdhc_exit(); sdhc_exit();
ipc_post(req->code, req->tag, 0); ipc_post(req->code, req->tag, 0);
break;
} }
} }
#endif #endif

14
sdhc.h
View File

@ -25,16 +25,10 @@
#include "ipc.h" #include "ipc.h"
#endif #endif
#include "sdmmc.h" #include "sdmmc.h"
#define SDHC_MAX_HOSTS 4
struct sdhc_host { struct sdhc_host {
struct sdhc_softc *sc; /* host controller device */
struct device *sdmmc; /* generic SD/MMC device */
bus_space_tag_t iot; /* host register set tag */ bus_space_tag_t iot; /* host register set tag */
bus_space_handle_t ioh; /* host register set handle */ bus_space_handle_t ioh; /* host register set handle */
u_int clkbase; /* base clock frequency in KHz */ u_int clkbase; /* base clock frequency in KHz */
int maxblklen; /* maximum block length */
int flags; /* flags for this host */ int flags; /* flags for this host */
u_int32_t ocr; /* OCR value from capabilities */ u_int32_t ocr; /* OCR value from capabilities */
u_int8_t regs[14]; /* host controller state */ u_int8_t regs[14]; /* host controller state */
@ -174,11 +168,6 @@ void sdhc_ipc(volatile ipc_request *req);
#define SDHC_VOLTAGE_SUPP_3_3V (1<<24) #define SDHC_VOLTAGE_SUPP_3_3V (1<<24)
#define SDHC_DMA_SUPPORT (1<<22) #define SDHC_DMA_SUPPORT (1<<22)
#define SDHC_HIGH_SPEED_SUPP (1<<21) #define SDHC_HIGH_SPEED_SUPP (1<<21)
#define SDHC_MAX_BLK_LEN_512 0
#define SDHC_MAX_BLK_LEN_1024 1
#define SDHC_MAX_BLK_LEN_2048 2
#define SDHC_MAX_BLK_LEN_SHIFT 16
#define SDHC_MAX_BLK_LEN_MASK 0x3
#define SDHC_BASE_FREQ_SHIFT 8 #define SDHC_BASE_FREQ_SHIFT 8
#define SDHC_BASE_FREQ_MASK 0x3f #define SDHC_BASE_FREQ_MASK 0x3f
#define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */ #define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */
@ -208,12 +197,9 @@ void sdhc_ipc(volatile ipc_request *req);
#define SDHC_VENDOR_VERSION(hcv) \ #define SDHC_VENDOR_VERSION(hcv) \
(((hcv) >> SDHC_VENDOR_VERS_SHIFT) & SDHC_VENDOR_VERS_MASK) (((hcv) >> SDHC_VENDOR_VERS_SHIFT) & SDHC_VENDOR_VERS_MASK)
//typedef void *sdmmc_chipset_handle_t;
struct sdmmc_command; struct sdmmc_command;
int sdhc_host_reset(struct sdhc_host *hp); int sdhc_host_reset(struct sdhc_host *hp);
u_int32_t sdhc_host_ocr(struct sdhc_host *hp);
int sdhc_host_maxblklen(struct sdhc_host *hp);
int sdhc_card_detect(struct sdhc_host *hp); int sdhc_card_detect(struct sdhc_host *hp);
int sdhc_bus_power(struct sdhc_host *hp, u_int32_t); int sdhc_bus_power(struct sdhc_host *hp, u_int32_t);
int sdhc_bus_clock(struct sdhc_host *hp, int); int sdhc_bus_clock(struct sdhc_host *hp, int);

150
sdmmc.c
View File

@ -25,10 +25,7 @@ static int sdmmcdebug = 0;
#endif #endif
struct sdmmc_card { struct sdmmc_card {
struct sdmmc_chip_functions *functions;
sdmmc_chipset_handle_t handle; sdmmc_chipset_handle_t handle;
char name[30];
int no;
int inserted; int inserted;
int sdhc_blockmode; int sdhc_blockmode;
int selected; int selected;
@ -41,35 +38,22 @@ struct sdmmc_card {
}; };
#ifdef LOADER #ifdef LOADER
static struct sdmmc_card cards[SDHC_MAX_HOSTS]; static struct sdmmc_card card;
#else #else
static struct sdmmc_card cards[SDHC_MAX_HOSTS] MEM2_BSS; static struct sdmmc_card card MEM2_BSS;
#endif #endif
static int n_cards = 0; void sdmmc_attach(sdmmc_chipset_handle_t handle)
void sdmmc_attach(sdmmc_chipset_handle_t handle, const char *name, int no)
{ {
struct sdmmc_card *c; memset(&card, 0, sizeof(card));
if (n_cards >= SDHC_MAX_HOSTS) { card.handle = handle;
gecko_printf("n_cards(%d) >= %d!\n", n_cards, SDHC_MAX_HOSTS);
gecko_printf("starlet is soo going to crash very soon...\n");
}
c = &cards[n_cards++]; DPRINTF(0, ("sdmmc: attached new SD/MMC card\n"));
memset(c, 0, sizeof(*c));
c->handle = handle; sdhc_host_reset(card.handle);
c->no = no;
strlcpy(c->name, name, sizeof(c->name));
DPRINTF(0, ("sdmmc: attached new SD/MMC card %d for host [%s:%d]\n", if (sdhc_card_detect(card.handle)) {
n_cards-1, c->name, c->no));
sdhc_host_reset(c->handle);
if (sdhc_card_detect(c->handle)) {
DPRINTF(1, ("card is inserted. starting init sequence.\n")); DPRINTF(1, ("card is inserted. starting init sequence.\n"));
sdmmc_needs_discover(); sdmmc_needs_discover();
} }
@ -83,33 +67,32 @@ void sdmmc_abort(void) {
cmd.c_opcode = MMC_STOP_TRANSMISSION; cmd.c_opcode = MMC_STOP_TRANSMISSION;
cmd.c_arg = 0; cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R1B; cmd.c_flags = SCF_RSP_R1B;
sdhc_exec_command(&cards[0].handle, &cmd); sdhc_exec_command(card.handle, &cmd);
} }
void sdmmc_needs_discover(void) void sdmmc_needs_discover(void)
{ {
struct sdmmc_card *c = &cards[0];
struct sdmmc_command cmd; struct sdmmc_command cmd;
u32 ocr; u32 ocr;
DPRINTF(0, ("sdmmc: card needs discovery.\n")); DPRINTF(0, ("sdmmc: card needs discovery.\n"));
sdhc_host_reset(c->handle); sdhc_host_reset(card.handle);
c->new_card = 1; card.new_card = 1;
if (!sdhc_card_detect(c->handle)) { if (!sdhc_card_detect(card.handle)) {
DPRINTF(1, ("sdmmc: card (no longer?) inserted.\n")); DPRINTF(1, ("sdmmc: card (no longer?) inserted.\n"));
c->inserted = 0; card.inserted = 0;
return; return;
} }
DPRINTF(1, ("sdmmc: enabling power\n")); DPRINTF(1, ("sdmmc: enabling power\n"));
if (sdhc_bus_power(c->handle, 1) != 0) { if (sdhc_bus_power(card.handle, 1) != 0) {
gecko_printf("sdmmc: powerup failed for card\n"); gecko_printf("sdmmc: powerup failed for card\n");
goto out; goto out;
} }
DPRINTF(1, ("sdmmc: enabling clock\n")); DPRINTF(1, ("sdmmc: enabling clock\n"));
if (sdhc_bus_clock(c->handle, SDMMC_DEFAULT_CLOCK) != 0) { if (sdhc_bus_clock(card.handle, SDMMC_DEFAULT_CLOCK) != 0) {
gecko_printf("sdmmc: could not enable clock for card\n"); gecko_printf("sdmmc: could not enable clock for card\n");
goto out_power; goto out_power;
} }
@ -119,7 +102,7 @@ void sdmmc_needs_discover(void)
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_GO_IDLE_STATE; cmd.c_opcode = MMC_GO_IDLE_STATE;
cmd.c_flags = SCF_RSP_R0; cmd.c_flags = SCF_RSP_R0;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: GO_IDLE_STATE failed with %d\n", cmd.c_error); gecko_printf("sdmmc: GO_IDLE_STATE failed with %d\n", cmd.c_error);
@ -134,9 +117,9 @@ void sdmmc_needs_discover(void)
cmd.c_arg = 0x1aa; cmd.c_arg = 0x1aa;
cmd.c_flags = SCF_RSP_R7; cmd.c_flags = SCF_RSP_R7;
cmd.c_timeout = 100; cmd.c_timeout = 100;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
ocr = sdhc_host_ocr(c->handle); ocr = card.handle->ocr;
if (cmd.c_error || (cmd.c_resp[0] & 0xff) != 0xaa) if (cmd.c_error || (cmd.c_resp[0] & 0xff) != 0xaa)
ocr &= ~SD_OCR_SDHC_CAP; ocr &= ~SD_OCR_SDHC_CAP;
else else
@ -151,7 +134,7 @@ void sdmmc_needs_discover(void)
cmd.c_opcode = MMC_APP_CMD; cmd.c_opcode = MMC_APP_CMD;
cmd.c_arg = 0; cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R1; cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) if (cmd.c_error)
continue; continue;
@ -160,7 +143,7 @@ void sdmmc_needs_discover(void)
cmd.c_opcode = SD_APP_OP_COND; cmd.c_opcode = SD_APP_OP_COND;
cmd.c_arg = ocr; cmd.c_arg = ocr;
cmd.c_flags = SCF_RSP_R3; cmd.c_flags = SCF_RSP_R3;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) if (cmd.c_error)
continue; continue;
@ -175,10 +158,10 @@ void sdmmc_needs_discover(void)
} }
if (ISSET(MMC_R1(cmd.c_resp), SD_OCR_SDHC_CAP)) if (ISSET(MMC_R1(cmd.c_resp), SD_OCR_SDHC_CAP))
c->sdhc_blockmode = 1; card.sdhc_blockmode = 1;
else else
c->sdhc_blockmode = 0; card.sdhc_blockmode = 0;
DPRINTF(2, ("sdmmc: SDHC: %d\n", c->sdhc_blockmode)); DPRINTF(2, ("sdmmc: SDHC: %d\n", card.sdhc_blockmode));
u8 *resp; u8 *resp;
DPRINTF(2, ("sdmmc: MMC_ALL_SEND_CID\n")); DPRINTF(2, ("sdmmc: MMC_ALL_SEND_CID\n"));
@ -186,13 +169,13 @@ void sdmmc_needs_discover(void)
cmd.c_opcode = MMC_ALL_SEND_CID; cmd.c_opcode = MMC_ALL_SEND_CID;
cmd.c_arg = 0; cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R2; cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_ALL_SEND_CID failed with %d\n", cmd.c_error); gecko_printf("sdmmc: MMC_ALL_SEND_CID failed with %d\n", cmd.c_error);
goto out_clock; goto out_clock;
} }
c->cid = MMC_R1(cmd.c_resp); card.cid = MMC_R1(cmd.c_resp);
resp = (u8 *)cmd.c_resp; resp = (u8 *)cmd.c_resp;
gecko_printf("CID: mid=%02x name='%c%c%c%c%c%c%c' prv=%d.%d psn=%02x%02x%02x%02x mdt=%d/%d\n", resp[14], gecko_printf("CID: mid=%02x name='%c%c%c%c%c%c%c' prv=%d.%d psn=%02x%02x%02x%02x mdt=%d/%d\n", resp[14],
resp[13],resp[12],resp[11],resp[10],resp[9],resp[8],resp[7], resp[6], resp[5] >> 4, resp[5] & 0xf, resp[13],resp[12],resp[11],resp[10],resp[9],resp[8],resp[7], resp[6], resp[5] >> 4, resp[5] & 0xf,
@ -203,23 +186,23 @@ void sdmmc_needs_discover(void)
cmd.c_opcode = SD_SEND_RELATIVE_ADDR; cmd.c_opcode = SD_SEND_RELATIVE_ADDR;
cmd.c_arg = 0; cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R6; cmd.c_flags = SCF_RSP_R6;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: SD_SEND_RCA failed with %d\n", cmd.c_error); gecko_printf("sdmmc: SD_SEND_RCA failed with %d\n", cmd.c_error);
goto out_clock; goto out_clock;
} }
c->rca = MMC_R1(cmd.c_resp)>>16; card.rca = MMC_R1(cmd.c_resp)>>16;
DPRINTF(2, ("sdmmc: rca: %08x\n", c->rca)); DPRINTF(2, ("sdmmc: rca: %08x\n", card.rca));
c->selected = 0; card.selected = 0;
c->inserted = 1; card.inserted = 1;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SEND_CSD; cmd.c_opcode = MMC_SEND_CSD;
cmd.c_arg = ((u32)c->rca)<<16; cmd.c_arg = ((u32)card.rca)<<16;
cmd.c_flags = SCF_RSP_R2; cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_SEND_CSD failed with %d\n", cmd.c_error); gecko_printf("sdmmc: MMC_SEND_CSD failed with %d\n", cmd.c_error);
goto out_power; goto out_power;
@ -235,8 +218,8 @@ void sdmmc_needs_discover(void)
if (resp[13] == 0xe) { // sdhc if (resp[13] == 0xe) { // sdhc
unsigned int c_size = resp[7] << 16 | resp[6] << 8 | resp[5]; unsigned int c_size = resp[7] << 16 | resp[6] << 8 | resp[5];
gecko_printf("sdmmc: sdhc mode, c_size=%u, card size = %uk\n", c_size, (c_size + 1)* 512); gecko_printf("sdmmc: sdhc mode, c_size=%u, card size = %uk\n", c_size, (c_size + 1)* 512);
c->timeout = 250 * 1000000; // spec says read timeout is 100ms and write/erase timeout is 250ms card.timeout = 250 * 1000000; // spec says read timeout is 100ms and write/erase timeout is 250ms
c->num_sectors = (c_size + 1) * 1024; // number of 512-byte sectors card.num_sectors = (c_size + 1) * 1024; // number of 512-byte sectors
} }
else { else {
unsigned int taac, nsac, read_bl_len, c_size, c_size_mult; unsigned int taac, nsac, read_bl_len, c_size, c_size_mult;
@ -253,9 +236,9 @@ void sdmmc_needs_discover(void)
taac, nsac, read_bl_len, c_size, c_size_mult, (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len)); taac, nsac, read_bl_len, c_size, c_size_mult, (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len));
static const unsigned int time_unit[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000}; static const unsigned int time_unit[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
static const unsigned int time_value[] = {1, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80}; // must div by 10 static const unsigned int time_value[] = {1, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80}; // must div by 10
c->timeout = time_unit[taac & 7] * time_value[(taac >> 3) & 0xf] / 10; card.timeout = time_unit[taac & 7] * time_value[(taac >> 3) & 0xf] / 10;
gecko_printf("calculated timeout = %uns\n", c->timeout); gecko_printf("calculated timeout = %uns\n", card.timeout);
c->num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512; card.num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512;
} }
sdmmc_select(); sdmmc_select();
@ -264,19 +247,19 @@ void sdmmc_needs_discover(void)
cmd.c_opcode = MMC_SET_BLOCKLEN; cmd.c_opcode = MMC_SET_BLOCKLEN;
cmd.c_arg = SDMMC_DEFAULT_BLOCKLEN; cmd.c_arg = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1; cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_SET_BLOCKLEN failed with %d\n", cmd.c_error); gecko_printf("sdmmc: MMC_SET_BLOCKLEN failed with %d\n", cmd.c_error);
c->inserted = c->selected = 0; card.inserted = card.selected = 0;
goto out_clock; goto out_clock;
} }
return; return;
out_clock: out_clock:
sdhc_bus_clock(c->handle, SDMMC_SDCLK_OFF); sdhc_bus_clock(card.handle, SDMMC_SDCLK_OFF);
out_power: out_power:
sdhc_bus_power(c->handle, 0); sdhc_bus_power(card.handle, 0);
out: out:
return; return;
} }
@ -284,17 +267,16 @@ out:
int sdmmc_select(void) int sdmmc_select(void)
{ {
struct sdmmc_card *c = &cards[0];
struct sdmmc_command cmd; struct sdmmc_command cmd;
DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n")); DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SELECT_CARD; cmd.c_opcode = MMC_SELECT_CARD;
cmd.c_arg = ((u32)c->rca)<<16; cmd.c_arg = ((u32)card.rca)<<16;
cmd.c_flags = SCF_RSP_R1B; cmd.c_flags = SCF_RSP_R1B;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
gecko_printf("%s: resp=%x\n", __FUNCTION__, MMC_R1(cmd.c_resp)); gecko_printf("%s: resp=%x\n", __FUNCTION__, MMC_R1(cmd.c_resp));
sdhc_dump_regs(c->handle); sdhc_dump_regs(card.handle);
// gecko_printf("present state = %x\n", HREAD4(hp, SDHC_PRESENT_STATE)); // gecko_printf("present state = %x\n", HREAD4(hp, SDHC_PRESENT_STATE));
if (cmd.c_error) { if (cmd.c_error) {
@ -302,18 +284,16 @@ int sdmmc_select(void)
return -1; return -1;
} }
c->selected = 1; card.selected = 1;
return 0; return 0;
} }
int sdmmc_check_card(void) int sdmmc_check_card(void)
{ {
struct sdmmc_card *c = &cards[0]; if (card.inserted == 0)
if (c->inserted == 0)
return SDMMC_NO_CARD; return SDMMC_NO_CARD;
if (c->new_card == 1) if (card.new_card == 1)
return SDMMC_NEW_CARD; return SDMMC_NEW_CARD;
return SDMMC_INSERTED; return SDMMC_INSERTED;
@ -321,10 +301,8 @@ int sdmmc_check_card(void)
int sdmmc_ack_card(void) int sdmmc_ack_card(void)
{ {
struct sdmmc_card *c = &cards[0]; if (card.new_card == 1) {
card.new_card = 0;
if (c->new_card == 1) {
c->new_card = 0;
return 0; return 0;
} }
@ -333,23 +311,22 @@ int sdmmc_ack_card(void)
int sdmmc_read(u32 blk_start, u32 blk_count, void *data) int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
{ {
struct sdmmc_card *c = &cards[0];
struct sdmmc_command cmd; struct sdmmc_command cmd;
gecko_printf("%s(%u, %u, %p)\n", __FUNCTION__, blk_start, blk_count, data); gecko_printf("%s(%u, %u, %p)\n", __FUNCTION__, blk_start, blk_count, data);
if (c->inserted == 0) { if (card.inserted == 0) {
gecko_printf("sdmmc: READ: no card inserted.\n"); gecko_printf("sdmmc: READ: no card inserted.\n");
return -1; return -1;
} }
if (c->selected == 0) { if (card.selected == 0) {
if (sdmmc_select() < 0) { if (sdmmc_select() < 0) {
gecko_printf("sdmmc: READ: cannot select card.\n"); gecko_printf("sdmmc: READ: cannot select card.\n");
return -1; return -1;
} }
} }
if (c->new_card == 1) { if (card.new_card == 1) {
gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n"); gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n");
return -1; return -1;
} }
@ -357,7 +334,7 @@ int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE\n")); DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE; cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE;
if (c->sdhc_blockmode) if (card.sdhc_blockmode)
cmd.c_arg = blk_start; cmd.c_arg = blk_start;
else else
cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN; cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN;
@ -365,7 +342,7 @@ int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN; cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN; cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1 | SCF_CMD_READ; cmd.c_flags = SCF_RSP_R1 | SCF_CMD_READ;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error); gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error);
@ -379,22 +356,21 @@ int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
#ifndef LOADER #ifndef LOADER
int sdmmc_write(u32 blk_start, u32 blk_count, void *data) int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
{ {
struct sdmmc_card *c = &cards[0];
struct sdmmc_command cmd; struct sdmmc_command cmd;
if (c->inserted == 0) { if (card.inserted == 0) {
gecko_printf("sdmmc: READ: no card inserted.\n"); gecko_printf("sdmmc: READ: no card inserted.\n");
return -1; return -1;
} }
if (c->selected == 0) { if (card.selected == 0) {
if (sdmmc_select() < 0) { if (sdmmc_select() < 0) {
gecko_printf("sdmmc: READ: cannot select card.\n"); gecko_printf("sdmmc: READ: cannot select card.\n");
return -1; return -1;
} }
} }
if (c->new_card == 1) { if (card.new_card == 1) {
gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n"); gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n");
return -1; return -1;
} }
@ -402,7 +378,7 @@ int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE\n")); DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_WRITE_BLOCK_MULTIPLE; cmd.c_opcode = MMC_WRITE_BLOCK_MULTIPLE;
if (c->sdhc_blockmode) if (card.sdhc_blockmode)
cmd.c_arg = blk_start; cmd.c_arg = blk_start;
else else
cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN; cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN;
@ -410,7 +386,7 @@ int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN; cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN; cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1; cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error); gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error);
@ -423,21 +399,19 @@ int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
int sdmmc_get_sectors(void) int sdmmc_get_sectors(void)
{ {
struct sdmmc_card *c = &cards[0]; if (card.inserted == 0) {
if (c->inserted == 0) {
gecko_printf("sdmmc: READ: no card inserted.\n"); gecko_printf("sdmmc: READ: no card inserted.\n");
return -1; return -1;
} }
if (c->new_card == 1) { if (card.new_card == 1) {
gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n"); gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n");
return -1; return -1;
} }
// sdhc_error(sdhci->reg_base, "num sectors = %u", sdhci->num_sectors); // sdhc_error(sdhci->reg_base, "num sectors = %u", sdhci->num_sectors);
return c->num_sectors; return card.num_sectors;
} }
#endif #endif

View File

@ -15,8 +15,7 @@ Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
struct sdmmc_command; struct sdmmc_command;
typedef struct sdmmc_chip_functions *sdmmc_chipset_tag_t; typedef struct sdhc_host * sdmmc_chipset_handle_t;
typedef void *sdmmc_chipset_handle_t;
/* clock frequencies for sdmmc_chip_bus_clock() */ /* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0 #define SDMMC_SDCLK_OFF 0
@ -157,7 +156,7 @@ struct sdmmc_function {
#define SDMMC_NEW_CARD 2 #define SDMMC_NEW_CARD 2
#define SDMMC_INSERTED 3 #define SDMMC_INSERTED 3
void sdmmc_attach(sdmmc_chipset_handle_t handle, const char *name, int no); void sdmmc_attach(sdmmc_chipset_handle_t handle);
void sdmmc_needs_discover(void); void sdmmc_needs_discover(void);
int sdmmc_select(void); int sdmmc_select(void);
int sdmmc_check_card(void); int sdmmc_check_card(void);