mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-27 21:54:18 +01:00
more sd code simplification, removing bsd cruft
This commit is contained in:
parent
1fcd51701f
commit
d7e80776a2
@ -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(...)
|
||||||
|
62
diskio.c
62
diskio.c
@ -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
91
sdhc.c
@ -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
1
sdhc.h
@ -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
152
sdmmc.c
@ -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
63
sdmmc.h
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user