more sd code simplification, removing bsd cruft

This commit is contained in:
bushing 2009-10-26 02:19:37 -07:00
parent 1fcd51701f
commit d7e80776a2
6 changed files with 112 additions and 262 deletions

View File

@ -23,11 +23,6 @@ typedef u8 u_char;
typedef u32 bus_space_tag_t; typedef u32 bus_space_tag_t;
typedef u32 bus_space_handle_t; typedef u32 bus_space_handle_t;
struct device {
char dv_xname[255];
void *dummy;
};
#define MIN(a, b) (((a)>(b))?(b):(a)) #define MIN(a, b) (((a)>(b))?(b):(a))
#define wakeup(...) #define wakeup(...)

View File

@ -18,34 +18,34 @@ Copyright (C) 2008, 2009 Haxx Enterprises <bushing@gmail.com>
#endif #endif
static u8 buffer[512] MEM2_BSS ALIGNED(32); static u8 buffer[512] MEM2_BSS ALIGNED(32);
// Initialize a Drive // Initialize a Drive
DSTATUS disk_initialize (BYTE drv) { DSTATUS disk_initialize (BYTE drv) {
if (sdmmc_check_card(SDMMC_DEFAULT_DEVICE) == SDMMC_NO_CARD) if (sdmmc_check_card() == SDMMC_NO_CARD)
return STA_NOINIT; return STA_NOINIT;
sdmmc_ack_card(SDMMC_DEFAULT_DEVICE); sdmmc_ack_card();
return disk_status(drv); return disk_status(drv);
} }
// Return Disk Status // Return Disk Status
DSTATUS disk_status (BYTE drv) { DSTATUS disk_status (BYTE drv) {
(void)drv; (void)drv;
if (sdmmc_check_card(SDMMC_DEFAULT_DEVICE) == SDMMC_INSERTED) if (sdmmc_check_card() == SDMMC_INSERTED)
return 0; return 0;
else else
return STA_NODISK; return STA_NODISK;
} }
// Read Sector(s) // Read Sector(s)
DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, BYTE count) { DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, BYTE count) {
int i; int i;
(void)drv; (void)drv;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (sdmmc_read(SDMMC_DEFAULT_DEVICE, sector+i, 1, buffer) != 0) if (sdmmc_read(sector+i, 1, buffer) != 0)
return RES_ERROR; return RES_ERROR;
memcpy(buff + i * 512, buffer, 512); memcpy(buff + i * 512, buffer, 512);
} }
return RES_OK; return RES_OK;
} }
@ -55,13 +55,13 @@ DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, BYTE count) {
DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, BYTE count) { DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, BYTE count) {
int i; int i;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
memcpy(buffer, buff + i * 512, 512); memcpy(buffer, buff + i * 512, 512);
if(sdmmc_write(SDMMC_DEFAULT_DEVICE, sector + i, 1, buffer) != 0) if(sdmmc_write(sector + i, 1, buffer) != 0)
return RES_ERROR; return RES_ERROR;
} }
return RES_OK; return RES_OK;
} }
#endif /* _READONLY */ #endif /* _READONLY */

91
sdhc.c
View File

@ -41,7 +41,6 @@
#define SDHC_COMMAND_TIMEOUT 500 #define SDHC_COMMAND_TIMEOUT 500
#define SDHC_TRANSFER_TIMEOUT 5000 #define SDHC_TRANSFER_TIMEOUT 5000
#define HDEVNAME(hp) ((hp)->sc->sc_dev.dv_xname)
#define sdmmc_delay(t) udelay(t) #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)
@ -138,24 +137,6 @@ void sdhc_dump_regs(struct sdhc_host *);
#define DPRINTF(n,s) do {} while(0) #define DPRINTF(n,s) do {} while(0)
#endif #endif
struct sdmmc_chip_functions sdhc_functions = {
/* host controller reset */
sdhc_host_reset,
/* host controller capabilities */
sdhc_host_ocr,
sdhc_host_maxblklen,
/* card detection */
sdhc_card_detect,
/* bus power and clock frequency */
sdhc_bus_power,
sdhc_bus_clock,
/* command execution */
sdhc_exec_command,
/* card interrupt */
sdhc_card_intr_mask,
sdhc_card_intr_ack
};
/* /*
* Called by attachment driver. For each SD card slot there is one SD * Called by attachment driver. For each SD card slot there is one SD
* host controller standard register set. (1.3) * host controller standard register set. (1.3)
@ -169,13 +150,12 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
u_int32_t caps; u_int32_t caps;
int error = 1; int error = 1;
strlcpy(sc->sc_dev.dv_xname, "sdhc", 5);
#ifdef SDHC_DEBUG #ifdef SDHC_DEBUG
u_int16_t version; u_int16_t version;
version = bus_space_read_2(ioh, SDHC_HOST_CTL_VERSION); version = bus_space_read_2(ioh, SDHC_HOST_CTL_VERSION);
gecko_printf("%s: SD Host Specification/Vendor Version ", gecko_printf("sdhc: SD Host Specification/Vendor Version ");
sc->sc_dev.dv_xname);
switch(SDHC_SPEC_VERSION(version)) { switch(SDHC_SPEC_VERSION(version)) {
case 0x00: case 0x00:
gecko_printf("1.0/%u\n", SDHC_VENDOR_VERSION(version)); gecko_printf("1.0/%u\n", SDHC_VENDOR_VERSION(version));
@ -220,13 +200,12 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
hp->clkbase = SDHC_BASE_FREQ_KHZ(caps); hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
if (hp->clkbase == 0) { if (hp->clkbase == 0) {
/* The attachment driver must tell us. */ /* The attachment driver must tell us. */
gecko_printf("%s: base clock frequency unknown\n", gecko_printf("sdhc: base clock frequency unknown\n");
sc->sc_dev.dv_xname);
goto err; goto err;
} else if (hp->clkbase < 10000 || hp->clkbase > 63000) { } else if (hp->clkbase < 10000 || hp->clkbase > 63000) {
/* SDHC 1.0 supports only 10-63 MHz. */ /* SDHC 1.0 supports only 10-63 MHz. */
gecko_printf("%s: base clock frequency out of range: %u MHz\n", gecko_printf("sdhc: base clock frequency out of range: %u MHz\n",
sc->sc_dev.dv_xname, hp->clkbase / 1000); hp->clkbase / 1000);
goto err; goto err;
} }
@ -262,10 +241,9 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
*/ */
bzero(&saa, sizeof(saa)); bzero(&saa, sizeof(saa));
saa.saa_busname = "sdmmc"; saa.saa_busname = "sdmmc";
saa.sct = &sdhc_functions;
saa.sch = hp; saa.sch = hp;
hp->sdmmc = sdmmc_attach(&sdhc_functions, hp, "sdhc", ioh); sdmmc_attach(hp, "sdhc", ioh);
return 0; return 0;
@ -463,6 +441,7 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
sdmmc_delay(10); sdmmc_delay(10);
} }
if (timo == 0) { if (timo == 0) {
gecko_printf("sdhc: internal clock never stabilized\n");
error = ETIMEDOUT; error = ETIMEDOUT;
goto ret; goto ret;
} }
@ -510,8 +489,7 @@ sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value)
return 0; return 0;
sdmmc_delay(10000); sdmmc_delay(10000);
} }
DPRINTF(0,("%s: timeout waiting for %x (state=%d)\n", DPRINTF(0,("sdhc: timeout waiting for %x (state=%d)\n", value, state));
HDEVNAME(hp), value, state));
return ETIMEDOUT; return ETIMEDOUT;
} }
@ -588,8 +566,8 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
/* Turn off the LED. */ /* Turn off the LED. */
HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON); HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
DPRINTF(1,("%s: 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",
HDEVNAME(hp), 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);
hp->data_command = 0; hp->data_command = 0;
} }
@ -603,9 +581,8 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
u_int16_t command; u_int16_t command;
int error; int error;
DPRINTF(1,("%s: start cmd %u arg=%#x data=%p dlen=%d flags=%#x " DPRINTF(1,("sdhc: start cmd %u arg=%#x data=%p dlen=%d flags=%#x\n",
"proc=\"%s\"\n", HDEVNAME(hp), cmd->c_opcode, cmd->c_arg, cmd->c_opcode, cmd->c_arg, cmd->c_data, cmd->c_datalen, cmd->c_flags));
cmd->c_data, cmd->c_datalen, cmd->c_flags, ""));
/* /*
* The maximum block length for commands should be the minimum * The maximum block length for commands should be the minimum
@ -618,15 +595,14 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
blkcount = cmd->c_datalen / blksize; blkcount = cmd->c_datalen / blksize;
if (cmd->c_datalen % blksize > 0) { if (cmd->c_datalen % blksize > 0) {
/* XXX: Split this command. (1.7.4) */ /* XXX: Split this command. (1.7.4) */
gecko_printf("%s: data not a multiple of %d bytes\n", gecko_printf("sdhc: data not a multiple of %d bytes\n", blksize);
HDEVNAME(hp), blksize);
return EINVAL; return EINVAL;
} }
} }
/* Check limit imposed by 9-bit block count. (1.7.2) */ /* Check limit imposed by 9-bit block count. (1.7.2) */
if (blkcount > SDHC_BLOCK_COUNT_MAX) { if (blkcount > SDHC_BLOCK_COUNT_MAX) {
gecko_printf("%s: too much data\n", HDEVNAME(hp)); gecko_printf("sdhc: too much data\n");
return EINVAL; return EINVAL;
} }
@ -687,8 +663,8 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
HWRITE4(hp, SDHC_DMA_ADDR, (u32)cmd->c_data); HWRITE4(hp, SDHC_DMA_ADDR, (u32)cmd->c_data);
} }
DPRINTF(1,("%s: cmd=%#x mode=%#x blksize=%d blkcount=%d\n", DPRINTF(1,("sdhc: cmd=%#x mode=%#x blksize=%d blkcount=%d\n",
HDEVNAME(hp), command, mode, blksize, blkcount)); command, mode, blksize, blkcount));
/* /*
* Start a CPU data transfer. Writing to the high order byte * Start a CPU data transfer. Writing to the high order byte
@ -713,8 +689,7 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
error = 0; error = 0;
DPRINTF(1,("%s: resp=%#x datalen=%d\n", HDEVNAME(hp), DPRINTF(1,("resp=%#x datalen=%d\n", MMC_R1(cmd->c_resp), cmd->c_datalen));
MMC_R1(cmd->c_resp), cmd->c_datalen));
if (ISSET(hp->flags, SHF_USE_DMA)) { if (ISSET(hp->flags, SHF_USE_DMA)) {
for(;;) { for(;;) {
status = sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE | status = sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE |
@ -731,8 +706,7 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
break; break;
} }
if (ISSET(status, SDHC_DMA_INTERRUPT)) { if (ISSET(status, SDHC_DMA_INTERRUPT)) {
DPRINTF(2,("%s: dma left:%#x\n", HDEVNAME(hp), DPRINTF(2,("sdhc: dma left:%#x\n", HREAD2(hp, SDHC_BLOCK_COUNT)));
HREAD2(hp, SDHC_BLOCK_COUNT)));
// this works because our virtual memory // this works because our virtual memory
// addresses are equal to the physical memory // addresses are equal to the physical memory
// addresses and because we require the target // addresses and because we require the target
@ -751,8 +725,8 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
/* XXX I forgot why I wanted to know when this happens :-( */ /* XXX I forgot why I wanted to know when this happens :-( */
if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) && if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) &&
ISSET(MMC_R1(cmd->c_resp), 0xcb00)) ISSET(MMC_R1(cmd->c_resp), 0xcb00))
gecko_printf("%s: CMD52/53 error response flags %#x\n", gecko_printf("sdhc: CMD52/53 error response flags %#x\n",
HDEVNAME(hp), MMC_R1(cmd->c_resp) & 0xff00); MMC_R1(cmd->c_resp) & 0xff00);
#endif #endif
if (ISSET(cmd->c_flags, SCF_CMD_READ)) if (ISSET(cmd->c_flags, SCF_CMD_READ))
ahb_flush_from(AHB_SDHC); ahb_flush_from(AHB_SDHC);
@ -761,8 +735,7 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
cmd->c_error = error; cmd->c_error = error;
SET(cmd->c_flags, SCF_ITSDONE); SET(cmd->c_flags, SCF_ITSDONE);
DPRINTF(1,("%s: data transfer done (error=%d)\n", DPRINTF(1,("sdhc: data transfer done (error=%d)\n", cmd->c_error));
HDEVNAME(hp), cmd->c_error));
return; return;
} }
@ -772,7 +745,7 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
{ {
int timo; int timo;
DPRINTF(1,("%s: software reset reg=%#x\n", HDEVNAME(hp), mask)); DPRINTF(1,("sdhc: software reset reg=%#x\n", mask));
HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); HWRITE1(hp, SDHC_SOFTWARE_RESET, mask);
for (timo = 10; timo > 0; timo--) { for (timo = 10; timo > 0; timo--) {
@ -782,8 +755,7 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
} }
if (timo == 0) { if (timo == 0) {
DPRINTF(1,("%s: timeout reg=%#x\n", HDEVNAME(hp), DPRINTF(1,("sdhc: timeout reg=%#x\n", HREAD1(hp, SDHC_SOFTWARE_RESET)));
HREAD1(hp, SDHC_SOFTWARE_RESET)));
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
return (ETIMEDOUT); return (ETIMEDOUT);
} }
@ -823,9 +795,9 @@ sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int m
} }
hp->intr_status &= ~status; hp->intr_status &= ~status;
DPRINTF(2,("%s: funcname=%s, line=%d, timo=%d status=%#x intr status=%#x error %#x\n", DPRINTF(2,("sdhc: funcname=%s, line=%d, timo=%d status=%#x intr status=%#x error %#x\n",
HDEVNAME(hp), funcname, line, timo, status, hp->intr_status, hp->intr_error_status)); funcname, line, timo, status, hp->intr_status, hp->intr_error_status));
/* Command timeout has higher priority than command complete. */ /* Command timeout has higher priority than command complete. */
if (ISSET(status, SDHC_ERROR_INTERRUPT)) { if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
gecko_printf("resetting due to error interrupt\n"); gecko_printf("resetting due to error interrupt\n");
@ -877,8 +849,7 @@ sdhc_intr(void *arg)
/* Acknowledge the interrupts we are about to handle. */ /* Acknowledge the interrupts we are about to handle. */
HWRITE2(hp, SDHC_NINTR_STATUS, status); HWRITE2(hp, SDHC_NINTR_STATUS, status);
DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp), DPRINTF(2,("sdhc: interrupt status=%d\n", status));
status));
/* Claim this interrupt. */ /* Claim this interrupt. */
@ -906,8 +877,7 @@ sdhc_intr(void *arg)
HWRITE2(hp, SDHC_EINTR_STATUS, error); HWRITE2(hp, SDHC_EINTR_STATUS, error);
HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, signal); HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, signal);
DPRINTF(2,("%s: error interrupt, status=%d\n", DPRINTF(2,("sdhc: error interrupt, status=%d\n", error));
HDEVNAME(hp), error));
if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR| if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR|
SDHC_DATA_TIMEOUT_ERROR)) { SDHC_DATA_TIMEOUT_ERROR)) {
@ -923,8 +893,7 @@ sdhc_intr(void *arg)
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, 1, ipc_enqueue_slow(IPC_DEV_SDHC, IPC_SDHC_DISCOVER, 0);
(u32) hp->sdmmc);
} }
#endif #endif
@ -1013,7 +982,7 @@ void sdhc_ipc(volatile ipc_request *req)
{ {
switch (req->req) { switch (req->req) {
case IPC_SDHC_DISCOVER: case IPC_SDHC_DISCOVER:
sdmmc_needs_discover((struct device *)req->args[0]); sdmmc_needs_discover();
break; break;
case IPC_SDHC_EXIT: case IPC_SDHC_EXIT:
sdhc_exit(); sdhc_exit();

1
sdhc.h
View File

@ -44,7 +44,6 @@ struct sdhc_host {
}; };
struct sdhc_softc { struct sdhc_softc {
struct device sc_dev;
struct sdhc_host sc_host[SDHC_MAX_HOSTS]; struct sdhc_host sc_host[SDHC_MAX_HOSTS];
int sc_nhosts; int sc_nhosts;
}; };

152
sdmmc.c
View File

@ -48,23 +48,18 @@ static struct sdmmc_card cards[SDHC_MAX_HOSTS] MEM2_BSS;
static int n_cards = 0; static int n_cards = 0;
struct device *sdmmc_attach(struct sdmmc_chip_functions *functions, void sdmmc_attach(sdmmc_chipset_handle_t handle, const char *name, int no)
sdmmc_chipset_handle_t handle, const char *name, int no)
{ {
struct sdmmc_card *c; struct sdmmc_card *c;
if (n_cards >= SDHC_MAX_HOSTS) { if (n_cards >= SDHC_MAX_HOSTS) {
gecko_printf("n_cards(%d) >= %d!\n", n_cards, SDHC_MAX_HOSTS); gecko_printf("n_cards(%d) >= %d!\n", n_cards, SDHC_MAX_HOSTS);
gecko_printf("starlet is soo going to crash very soon...\n"); gecko_printf("starlet is soo going to crash very soon...\n");
// HACK
return (struct device *)-1;
} }
c = &cards[n_cards++]; c = &cards[n_cards++];
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->functions = functions;
c->handle = handle; c->handle = handle;
c->no = no; c->no = no;
strlcpy(c->name, name, sizeof(c->name)); strlcpy(c->name, name, sizeof(c->name));
@ -76,11 +71,8 @@ struct device *sdmmc_attach(struct sdmmc_chip_functions *functions,
if (sdhc_card_detect(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((struct device *)(n_cards-1)); sdmmc_needs_discover();
} }
// HACK
return (struct device *)(n_cards-1);
} }
void sdmmc_abort(void) { void sdmmc_abort(void) {
@ -94,36 +86,35 @@ void sdmmc_abort(void) {
sdhc_exec_command(&cards[0].handle, &cmd); sdhc_exec_command(&cards[0].handle, &cmd);
} }
void sdmmc_needs_discover(struct device *dev) void sdmmc_needs_discover(void)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
struct sdmmc_command cmd; struct sdmmc_command cmd;
u32 ocr; u32 ocr;
DPRINTF(0, ("sdmmc: card %d needs discovery.\n", no)); DPRINTF(0, ("sdmmc: card needs discovery.\n"));
sdhc_host_reset(c->handle); sdhc_host_reset(c->handle);
c->new_card = 1; c->new_card = 1;
if (!sdhc_card_detect(c->handle)) { if (!sdhc_card_detect(c->handle)) {
DPRINTF(1, ("sdmmc: card %d (no longer?) inserted.\n", no)); DPRINTF(1, ("sdmmc: card (no longer?) inserted.\n"));
c->inserted = 0; c->inserted = 0;
return; return;
} }
DPRINTF(1, ("sdmmc: enabling power for %d\n", no)); DPRINTF(1, ("sdmmc: enabling power\n"));
if (sdhc_bus_power(c->handle, 1) != 0) { if (sdhc_bus_power(c->handle, 1) != 0) {
gecko_printf("sdmmc: powerup failed for card %d\n", no); gecko_printf("sdmmc: powerup failed for card\n");
goto out; goto out;
} }
DPRINTF(1, ("sdmmc: enabling clock for %d\n", no)); DPRINTF(1, ("sdmmc: enabling clock\n"));
if (sdhc_bus_clock(c->handle, SDMMC_DEFAULT_CLOCK) != 0) { if (sdhc_bus_clock(c->handle, SDMMC_DEFAULT_CLOCK) != 0) {
gecko_printf("sdmmc: could not enable clock for card %d\n", no); gecko_printf("sdmmc: could not enable clock for card\n");
goto out_power; goto out_power;
} }
DPRINTF(1, ("sdmmc: sending GO_IDLE_STATE for %d\n", no)); DPRINTF(1, ("sdmmc: sending GO_IDLE_STATE\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_GO_IDLE_STATE; cmd.c_opcode = MMC_GO_IDLE_STATE;
@ -131,14 +122,12 @@ void sdmmc_needs_discover(struct device *dev)
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: GO_IDLE_STATE failed with %d for card %d\n", gecko_printf("sdmmc: GO_IDLE_STATE failed with %d\n", cmd.c_error);
cmd.c_error, no);
goto out_clock; goto out_clock;
} }
DPRINTF(2, ("sdmmc: GO_IDLE_STATE response for %d: %x\n", no, DPRINTF(2, ("sdmmc: GO_IDLE_STATE response: %x\n", MMC_R1(cmd.c_resp)));
MMC_R1(cmd.c_resp)));
DPRINTF(1, ("sdmmc: sending SEND_IF_COND for %d\n", no)); DPRINTF(1, ("sdmmc: sending SEND_IF_COND\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = SD_SEND_IF_COND; cmd.c_opcode = SD_SEND_IF_COND;
@ -181,7 +170,7 @@ void sdmmc_needs_discover(struct device *dev)
break; break;
} }
if (!ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) { if (!ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) {
gecko_printf("sdmmc: card %d failed to powerup.\n", no); gecko_printf("sdmmc: card failed to powerup.\n");
goto out_power; goto out_power;
} }
@ -199,8 +188,7 @@ void sdmmc_needs_discover(struct device *dev)
cmd.c_flags = SCF_RSP_R2; cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_ALL_SEND_CID failed with %d for card %d\n", gecko_printf("sdmmc: MMC_ALL_SEND_CID failed with %d\n", cmd.c_error);
cmd.c_error, no);
goto out_clock; goto out_clock;
} }
@ -217,8 +205,7 @@ void sdmmc_needs_discover(struct device *dev)
cmd.c_flags = SCF_RSP_R6; cmd.c_flags = SCF_RSP_R6;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: SD_SEND_RCA failed with %d for card %d\n", gecko_printf("sdmmc: SD_SEND_RCA failed with %d\n", cmd.c_error);
cmd.c_error, no);
goto out_clock; goto out_clock;
} }
@ -234,8 +221,7 @@ void sdmmc_needs_discover(struct device *dev)
cmd.c_flags = SCF_RSP_R2; cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_SEND_CSD failed for " gecko_printf("sdmmc: MMC_SEND_CSD failed with %d\n", cmd.c_error);
"card %d with %d\n", no, cmd.c_error);
goto out_power; goto out_power;
} }
@ -272,7 +258,7 @@ void sdmmc_needs_discover(struct device *dev)
c->num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512; c->num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512;
} }
sdmmc_select(dev); sdmmc_select();
DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n")); DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SET_BLOCKLEN; cmd.c_opcode = MMC_SET_BLOCKLEN;
@ -280,63 +266,25 @@ void sdmmc_needs_discover(struct device *dev)
cmd.c_flags = SCF_RSP_R1; cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_SET_BLOCKLEN failed with %d for card %d\n", gecko_printf("sdmmc: MMC_SET_BLOCKLEN failed with %d\n", cmd.c_error);
cmd.c_error, no);
c->inserted = c->selected = 0; c->inserted = c->selected = 0;
goto out_clock; goto out_clock;
} }
return; return;
out_clock: out_clock:
sdhc_bus_clock(c->handle, SDMMC_SDCLK_OFF);
out_power: out_power:
sdhc_bus_power(c->handle, 0); sdhc_bus_power(c->handle, 0);
out: out:
return; return;
#if 0
// struct sdmmc_task c_task; /* task queue entry */
u_int16_t c_opcode; /* SD or MMC command index */
u_int32_t c_arg; /* SD/MMC command argument */
sdmmc_response c_resp; /* response buffer */
void *c_data; /* buffer to send or read into */
int c_datalen; /* length of data buffer */
int c_blklen; /* block length */
int c_flags; /* see below */
#define SCF_ITSDONE 0x0001 /* command is complete */
#define SCF_CMD(flags) ((flags) & 0x00f0)
#define SCF_CMD_AC 0x0000
#define SCF_CMD_ADTC 0x0010
#define SCF_CMD_BC 0x0020
#define SCF_CMD_BCR 0x0030
#define SCF_CMD_READ 0x0040 /* read command (data expected) */
#define SCF_RSP_BSY 0x0100
#define SCF_RSP_136 0x0200
#define SCF_RSP_CRC 0x0400
#define SCF_RSP_IDX 0x0800
#define SCF_RSP_PRESENT 0x1000
/* response types */
#define SCF_RSP_R0 0 /* none */
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
int c_error; /* errno value on completion */
/* Host controller owned fields for data xfer in progress */
int c_resid; /* remaining I/O */
u_char *c_buf; /* remaining data */
#endif
} }
int sdmmc_select(struct device *dev)
int sdmmc_select(void)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
struct sdmmc_command cmd; struct sdmmc_command cmd;
DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n")); DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n"));
@ -350,8 +298,7 @@ int sdmmc_select(struct device *dev)
// 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) {
gecko_printf("sdmmc: MMC_SELECT card failed with %d for %d.\n", gecko_printf("sdmmc: MMC_SELECT card failed with %d.\n", cmd.c_error);
cmd.c_error, no);
return -1; return -1;
} }
@ -359,10 +306,9 @@ int sdmmc_select(struct device *dev)
return 0; return 0;
} }
int sdmmc_check_card(struct device *dev) int sdmmc_check_card(void)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
if (c->inserted == 0) if (c->inserted == 0)
return SDMMC_NO_CARD; return SDMMC_NO_CARD;
@ -373,10 +319,9 @@ int sdmmc_check_card(struct device *dev)
return SDMMC_INSERTED; return SDMMC_INSERTED;
} }
int sdmmc_ack_card(struct device *dev) int sdmmc_ack_card(void)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
if (c->new_card == 1) { if (c->new_card == 1) {
c->new_card = 0; c->new_card = 0;
@ -386,10 +331,9 @@ int sdmmc_ack_card(struct device *dev)
return -1; return -1;
} }
int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data) int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
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);
@ -399,7 +343,7 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
} }
if (c->selected == 0) { if (c->selected == 0) {
if (sdmmc_select(dev) < 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;
} }
@ -424,8 +368,7 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed for " gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error);
"card %d with %d\n", no, cmd.c_error);
return -1; return -1;
} }
DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE done\n")); DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE done\n"));
@ -434,10 +377,9 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
} }
#ifndef LOADER #ifndef LOADER
int sdmmc_write(struct device *dev, u32 blk_start, u32 blk_count, void *data) int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
struct sdmmc_command cmd; struct sdmmc_command cmd;
if (c->inserted == 0) { if (c->inserted == 0) {
@ -446,7 +388,7 @@ int sdmmc_write(struct device *dev, u32 blk_start, u32 blk_count, void *data)
} }
if (c->selected == 0) { if (c->selected == 0) {
if (sdmmc_select(dev) < 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;
} }
@ -471,8 +413,7 @@ int sdmmc_write(struct device *dev, u32 blk_start, u32 blk_count, void *data)
sdhc_exec_command(c->handle, &cmd); sdhc_exec_command(c->handle, &cmd);
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed for " gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed with %d\n", cmd.c_error);
"card %d with %d\n", no, cmd.c_error);
return -1; return -1;
} }
DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE done\n")); DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE done\n"));
@ -480,10 +421,9 @@ int sdmmc_write(struct device *dev, u32 blk_start, u32 blk_count, void *data)
return 0; return 0;
} }
int sdmmc_get_sectors(struct device *dev) int sdmmc_get_sectors(void)
{ {
int no = (int)dev; struct sdmmc_card *c = &cards[0];
struct sdmmc_card *c = &cards[no];
if (c->inserted == 0) { if (c->inserted == 0) {
gecko_printf("sdmmc: READ: no card inserted.\n"); gecko_printf("sdmmc: READ: no card inserted.\n");
@ -507,12 +447,11 @@ void sdmmc_ipc(volatile ipc_request *req)
int ret; int ret;
switch (req->req) { switch (req->req) {
case IPC_SDMMC_ACK: case IPC_SDMMC_ACK:
ret = sdmmc_ack_card(SDMMC_DEFAULT_DEVICE); ret = sdmmc_ack_card();
ipc_post(req->code, req->tag, 1, ret); ipc_post(req->code, req->tag, 1, ret);
break; break;
case IPC_SDMMC_READ: case IPC_SDMMC_READ:
ret = sdmmc_read(SDMMC_DEFAULT_DEVICE, req->args[0], ret = sdmmc_read(req->args[0], req->args[1], (void *)req->args[2]);
req->args[1], (void *)req->args[2]);
dc_flushrange((void *)req->args[2], dc_flushrange((void *)req->args[2],
req->args[1]*SDMMC_DEFAULT_BLOCKLEN); req->args[1]*SDMMC_DEFAULT_BLOCKLEN);
ipc_post(req->code, req->tag, 1, ret); ipc_post(req->code, req->tag, 1, ret);
@ -520,17 +459,16 @@ void sdmmc_ipc(volatile ipc_request *req)
case IPC_SDMMC_WRITE: case IPC_SDMMC_WRITE:
dc_invalidaterange((void *)req->args[2], dc_invalidaterange((void *)req->args[2],
req->args[1]*SDMMC_DEFAULT_BLOCKLEN); req->args[1]*SDMMC_DEFAULT_BLOCKLEN);
ret = sdmmc_write(SDMMC_DEFAULT_DEVICE, req->args[0], ret = sdmmc_write(req->args[0], req->args[1], (void *)req->args[2]);
req->args[1], (void *)req->args[2]);
ipc_post(req->code, req->tag, 1, ret); ipc_post(req->code, req->tag, 1, ret);
break; break;
case IPC_SDMMC_STATE: case IPC_SDMMC_STATE:
ipc_post(req->code, req->tag, 1, ipc_post(req->code, req->tag, 1,
sdmmc_check_card(SDMMC_DEFAULT_DEVICE)); sdmmc_check_card());
break; break;
case IPC_SDMMC_SIZE: case IPC_SDMMC_SIZE:
ipc_post(req->code, req->tag, 1, ipc_post(req->code, req->tag, 1,
sdmmc_get_sectors(SDMMC_DEFAULT_DEVICE)); sdmmc_get_sectors());
break; break;
} }
} }

63
sdmmc.h
View File

@ -18,50 +18,6 @@ struct sdmmc_command;
typedef struct sdmmc_chip_functions *sdmmc_chipset_tag_t; typedef struct sdmmc_chip_functions *sdmmc_chipset_tag_t;
typedef void *sdmmc_chipset_handle_t; typedef void *sdmmc_chipset_handle_t;
struct sdmmc_chip_functions {
/* host controller reset */
int (*host_reset)(sdmmc_chipset_handle_t);
/* host capabilities */
u_int32_t (*host_ocr)(sdmmc_chipset_handle_t);
int (*host_maxblklen)(sdmmc_chipset_handle_t);
/* card detection */
int (*card_detect)(sdmmc_chipset_handle_t);
/* bus power and clock frequency */
int (*bus_power)(sdmmc_chipset_handle_t, u_int32_t);
int (*bus_clock)(sdmmc_chipset_handle_t, int);
/* command execution */
void (*exec_command)(sdmmc_chipset_handle_t,
struct sdmmc_command *);
/* card interrupt */
void (*card_intr_mask)(sdmmc_chipset_handle_t, int);
void (*card_intr_ack)(sdmmc_chipset_handle_t);
};
/* host controller reset */
#define sdmmc_chip_host_reset(tag, handle) \
((tag)->host_reset((handle)))
/* host capabilities */
#define sdmmc_chip_host_ocr(tag, handle) \
((tag)->host_ocr((handle)))
#define sdmmc_chip_host_maxblklen(tag, handle) \
((tag)->host_maxblklen((handle)))
/* card detection */
#define sdmmc_chip_card_detect(tag, handle) \
((tag)->card_detect((handle)))
/* bus power and clock frequency */
#define sdmmc_chip_bus_power(tag, handle, ocr) \
((tag)->bus_power((handle), (ocr)))
#define sdmmc_chip_bus_clock(tag, handle, freq) \
((tag)->bus_clock((handle), (freq)))
/* command execution */
#define sdmmc_chip_exec_command(tag, handle, cmdp) \
((tag)->exec_command((handle), (cmdp)))
/* card interrupt */
#define sdmmc_chip_card_intr_mask(tag, handle, enable) \
((tag)->card_intr_mask((handle), (enable)))
#define sdmmc_chip_card_intr_ack(tag, handle) \
((tag)->card_intr_ack((handle)))
/* clock frequencies for sdmmc_chip_bus_clock() */ /* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0 #define SDMMC_SDCLK_OFF 0
#define SDMMC_SDCLK_400KHZ 400 #define SDMMC_SDCLK_400KHZ 400
@ -189,7 +145,6 @@ struct sdmmc_function {
#define SFF_SDHC 0x0002 /* SD High Capacity card */ #define SFF_SDHC 0x0002 /* SD High Capacity card */
/* SD card I/O function members */ /* SD card I/O function members */
int number; /* I/O function number or -1 */ int number; /* I/O function number or -1 */
struct device *child; /* function driver */
struct sdmmc_cis cis; /* decoded CIS */ struct sdmmc_cis cis; /* decoded CIS */
/* SD/MMC memory card members */ /* SD/MMC memory card members */
struct sdmmc_csd csd; /* decoded CSD value */ struct sdmmc_csd csd; /* decoded CSD value */
@ -201,8 +156,6 @@ struct sdmmc_function {
* Structure describing a single SD/MMC/SDIO card slot. * Structure describing a single SD/MMC/SDIO card slot.
*/ */
struct sdmmc_softc { struct sdmmc_softc {
struct device sc_dev; /* base device */
#define SDMMCDEVNAME(sc) ((sc)->sc_dev.dv_xname)
sdmmc_chipset_tag_t sct; /* host controller chipset tag */ sdmmc_chipset_tag_t sct; /* host controller chipset tag */
sdmmc_chipset_handle_t sch; /* host controller chipset handle */ sdmmc_chipset_handle_t sch; /* host controller chipset handle */
#define SMF_SD_MODE 0x0001 /* host in SD mode (MMC otherwise) */ #define SMF_SD_MODE 0x0001 /* host in SD mode (MMC otherwise) */
@ -248,16 +201,12 @@ struct sdmmc_attach_args {
#define SDMMC_NEW_CARD 2 #define SDMMC_NEW_CARD 2
#define SDMMC_INSERTED 3 #define SDMMC_INSERTED 3
// HACK void sdmmc_attach(sdmmc_chipset_handle_t handle, const char *name, int no);
#define SDMMC_DEFAULT_DEVICE ((struct device *)0) void sdmmc_needs_discover(void);
int sdmmc_select(void);
struct device *sdmmc_attach(struct sdmmc_chip_functions *functions, int sdmmc_check_card(void);
sdmmc_chipset_handle_t handle, const char *name, int no); int sdmmc_ack_card(void);
void sdmmc_needs_discover(struct device *dev); int sdmmc_read(u32 blk_start, u32 blk_count, void *data);
int sdmmc_select(struct device *dev);
int sdmmc_check_card(struct device *dev);
int sdmmc_ack_card(struct device *dev);
int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data);
#ifdef CAN_HAZ_IPC #ifdef CAN_HAZ_IPC
void sdmmc_ipc(volatile ipc_request *req); void sdmmc_ipc(volatile ipc_request *req);
#endif #endif