mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-28 06:04:19 +01:00
dma for sdhc.
it still fails after having read a few blocks
This commit is contained in:
parent
2ad64f59a8
commit
5ba315148b
5
ipc.c
5
ipc.c
@ -149,9 +149,12 @@ static u32 process_slow(volatile ipc_request *req)
|
||||
case IPC_DEV_NAND:
|
||||
nand_ipc(req);
|
||||
break;
|
||||
case IPC_DEV_SD:
|
||||
case IPC_DEV_SDHC:
|
||||
sdhc_ipc(req);
|
||||
break;
|
||||
case IPC_DEV_SDMMC:
|
||||
sdmmc_ipc(req);
|
||||
break;
|
||||
case IPC_DEV_KEYS:
|
||||
crypto_ipc(req);
|
||||
break;
|
||||
|
9
ipc.h
9
ipc.h
@ -31,11 +31,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#define IPC_DEV_SYS 0x00
|
||||
#define IPC_DEV_NAND 0x01
|
||||
#define IPC_DEV_SD 0x02
|
||||
#define IPC_DEV_SDHC 0x02
|
||||
#define IPC_DEV_KEYS 0x03
|
||||
#define IPC_DEV_AES 0x04
|
||||
#define IPC_DEV_BOOT2 0x05
|
||||
#define IPC_DEV_PPC 0x06
|
||||
#define IPC_DEV_SDMMC 0x07
|
||||
|
||||
#define IPC_SYS_PING 0x0000
|
||||
#define IPC_SYS_JUMP 0x0001
|
||||
@ -62,7 +63,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define IPC_NAND_ERASE 0x0004
|
||||
#define IPC_NAND_STATUS 0x0005
|
||||
|
||||
#define IPC_SD_DISCOVER 0x0000
|
||||
#define IPC_SDHC_DISCOVER 0x0000
|
||||
|
||||
#define IPC_SDMMC_ACK 0x0000
|
||||
#define IPC_SDMMC_READ 0x0001
|
||||
#define IPC_SDMMC_WRITE 0x0002
|
||||
/*#define IPC_SD_MOUNT 0x0000
|
||||
#define IPC_SD_SELECT 0x0001
|
||||
#define IPC_SD_GETSTATE 0x0002
|
||||
|
74
sdhc.c
74
sdhc.c
@ -44,8 +44,9 @@
|
||||
#include "irq.h"
|
||||
#include "utils.h"
|
||||
#include "ipc.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define SDHC_DEBUG 1
|
||||
//#define SDHC_DEBUG 1
|
||||
|
||||
#define SDHC_COMMAND_TIMEOUT 0
|
||||
#define SDHC_BUFFER_TIMEOUT 0
|
||||
@ -728,16 +729,14 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
mode |= SDHC_READ_MODE;
|
||||
if (blkcount > 0) {
|
||||
mode |= SDHC_BLOCK_COUNT_ENABLE;
|
||||
if (blkcount > 1) {
|
||||
// if (blkcount > 1) {
|
||||
mode |= SDHC_MULTI_BLOCK_MODE;
|
||||
/* XXX only for memory commands? */
|
||||
mode |= SDHC_AUTO_CMD12_ENABLE;
|
||||
}
|
||||
// }
|
||||
}
|
||||
#ifdef notyet
|
||||
if (ISSET(hp->flags, SHF_USE_DMA))
|
||||
mode |= SDHC_DMA_ENABLE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prepare command register value. (2.2.6)
|
||||
@ -770,7 +769,18 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
/* Alert the user not to remove the card. */
|
||||
HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
|
||||
|
||||
/* XXX: Set DMA start address if SHF_USE_DMA is set. */
|
||||
if (ISSET(hp->flags, SHF_USE_DMA) && cmd->c_datalen > 0) {
|
||||
cmd->c_resid = blkcount;
|
||||
cmd->c_buf = cmd->c_data;
|
||||
|
||||
if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
|
||||
dc_invalidaterange(cmd->c_data, cmd->c_datalen);
|
||||
} else {
|
||||
dc_flushrange(cmd->c_data, cmd->c_datalen);
|
||||
ahb_flush_to(AHB_SDHC);
|
||||
}
|
||||
HWRITE4(hp, SDHC_DMA_ADDR, dma_addr(cmd->c_data));
|
||||
}
|
||||
|
||||
DPRINTF(1,("%s: cmd=%#x mode=%#x blksize=%d blkcount=%d\n",
|
||||
HDEVNAME(hp), command, mode, blksize, blkcount));
|
||||
@ -780,7 +790,7 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
* of the SDHC_COMMAND register triggers the SD command. (1.5)
|
||||
*/
|
||||
HWRITE2(hp, SDHC_BLOCK_SIZE, blksize);
|
||||
if (blkcount > 1)
|
||||
if (blkcount > 0)
|
||||
HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount);
|
||||
HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg);
|
||||
HWRITE4(hp, SDHC_TRANSFER_MODE, ((u32)command<<16)|mode);
|
||||
@ -798,14 +808,45 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
int i, datalen;
|
||||
int mask;
|
||||
int error;
|
||||
int status;
|
||||
int left, blkcnt;
|
||||
|
||||
mask = ISSET(cmd->c_flags, SCF_CMD_READ) ?
|
||||
SDHC_BUFFER_READ_ENABLE : SDHC_BUFFER_WRITE_ENABLE;
|
||||
error = 0;
|
||||
datalen = cmd->c_datalen;
|
||||
blkcnt = (cmd->c_datalen / 512);
|
||||
|
||||
DPRINTF(1,("%s: resp=%#x datalen=%d\n", HDEVNAME(hp),
|
||||
MMC_R1(cmd->c_resp), datalen));
|
||||
if (ISSET(hp->flags, SHF_USE_DMA)) {
|
||||
for(;;) {
|
||||
status = sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE |
|
||||
SDHC_DMA_INTERRUPT,
|
||||
SDHC_TRANSFER_TIMEOUT);
|
||||
if (!status) {
|
||||
error = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ISSET(status, SDHC_DMA_INTERRUPT)) {
|
||||
left = HREAD2(hp, SDHC_BLOCK_COUNT);
|
||||
DPRINTF(2,("%s: dma left:%#x\n", HDEVNAME(hp),
|
||||
left));
|
||||
cmd->c_buf = cmd->c_data + (blkcnt - left)*512;
|
||||
HWRITE4(hp, SDHC_DMA_ADDR,
|
||||
dma_addr(cmd->c_buf));
|
||||
continue;
|
||||
}
|
||||
if (ISSET(status, SDHC_TRANSFER_COMPLETE)) {
|
||||
gecko_printf("transfer complete!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
gecko_printf("fail.\n");
|
||||
|
||||
|
||||
|
||||
#ifdef SDHC_DEBUG
|
||||
/* XXX I forgot why I wanted to know when this happens :-( */
|
||||
@ -814,7 +855,17 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
gecko_printf("%s: CMD52/53 error response flags %#x\n",
|
||||
HDEVNAME(hp), MMC_R1(cmd->c_resp) & 0xff00);
|
||||
#endif
|
||||
if (ISSET(cmd->c_flags, SCF_CMD_READ))
|
||||
ahb_flush_from(AHB_SDHC);
|
||||
|
||||
if (error != 0)
|
||||
cmd->c_error = error;
|
||||
SET(cmd->c_flags, SCF_ITSDONE);
|
||||
|
||||
DPRINTF(1,("%s: data transfer done (error=%d)\n",
|
||||
HDEVNAME(hp), cmd->c_error));
|
||||
return;
|
||||
#if 0
|
||||
while (datalen > 0) {
|
||||
if (!sdhc_wait_intr(hp, SDHC_BUFFER_READ_READY|
|
||||
SDHC_BUFFER_WRITE_READY, SDHC_BUFFER_TIMEOUT)) {
|
||||
@ -845,6 +896,7 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
|
||||
DPRINTF(1,("%s: data transfer done (error=%d)\n",
|
||||
HDEVNAME(hp), cmd->c_error));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -852,8 +904,10 @@ sdhc_read_data(struct sdhc_host *hp, u_char *datap, int datalen)
|
||||
{
|
||||
while (datalen > 3) {
|
||||
*(u_int32_t *)datap = HREAD4(hp, SDHC_DATA);
|
||||
gecko_printf("next_data: %08x\n", *datap);
|
||||
datap += 4;
|
||||
datalen -= 4;
|
||||
udelay(1000);
|
||||
}
|
||||
if (datalen > 0) {
|
||||
u_int32_t rv = HREAD4(hp, SDHC_DATA);
|
||||
@ -1007,8 +1061,8 @@ sdhc_intr(void *arg)
|
||||
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) {
|
||||
ipc_request req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.device = IPC_DEV_SD;
|
||||
req.req = IPC_SD_DISCOVER;
|
||||
req.device = IPC_DEV_SDHC;
|
||||
req.req = IPC_SDHC_DISCOVER;
|
||||
req.args[0] = hp->sdmmc;
|
||||
ipc_add_slow(&req);
|
||||
}
|
||||
@ -1083,7 +1137,7 @@ void sdhc_init(void)
|
||||
void sdhc_ipc(volatile ipc_request *req)
|
||||
{
|
||||
switch (req->req) {
|
||||
case IPC_SD_DISCOVER:
|
||||
case IPC_SDHC_DISCOVER:
|
||||
sdmmc_needs_discover((struct device *)req->args[0]);
|
||||
break;
|
||||
}
|
||||
|
90
sdmmc.c
90
sdmmc.c
@ -30,11 +30,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "gecko.h"
|
||||
#include "string.h"
|
||||
#include "utils.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define SDMMC_DEBUG 1
|
||||
|
||||
#ifdef SDMMC_DEBUG
|
||||
static int sdmmcdebug = 5;
|
||||
static int sdmmcdebug = 0;
|
||||
#define DPRINTF(n,s) do { if ((n) <= sdmmcdebug) gecko_printf s; } while (0)
|
||||
#else
|
||||
#define DPRINTF(n,s) do {} while(0)
|
||||
@ -216,6 +217,7 @@ void sdmmc_needs_discover(struct device *dev)
|
||||
c->sdhc_blockmode = 1;
|
||||
else
|
||||
c->sdhc_blockmode = 0;
|
||||
DPRINTF(2, ("sdmmc: SDHC: %d\n", c->sdhc_blockmode));
|
||||
|
||||
DPRINTF(2, ("sdmmc: MMC_ALL_SEND_CID\n"));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
@ -356,6 +358,8 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
|
||||
struct sdmmc_card *c = &cards[no];
|
||||
struct sdmmc_command cmd;
|
||||
|
||||
gecko_printf("reading %d bytes to %p\n", blk_count*512,data);
|
||||
|
||||
if (c->inserted == 0) {
|
||||
gecko_printf("sdmmc: READ: no card inserted.\n");
|
||||
return -1;
|
||||
@ -375,7 +379,10 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
|
||||
|
||||
DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE\n"));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE;
|
||||
if (blk_count == 1)
|
||||
cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE;
|
||||
else
|
||||
cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE;
|
||||
if (c->sdhc_blockmode)
|
||||
cmd.c_arg = blk_start;
|
||||
else
|
||||
@ -386,12 +393,89 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
|
||||
cmd.c_flags = SCF_RSP_R1 | SCF_CMD_READ;
|
||||
sdmmc_host_exec_command(c, &cmd);
|
||||
|
||||
gecko_printf("arg: %08x %08x\n", cmd.c_arg, blk_start);
|
||||
|
||||
if (cmd.c_error) {
|
||||
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed for "
|
||||
"card %d with %d", no, cmd.c_error);
|
||||
return -1;
|
||||
}
|
||||
gecko_printf("success!!\n");
|
||||
DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE done\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdmmc_write(struct device *dev, u32 blk_start, u32 blk_count, void *data)
|
||||
{
|
||||
int no = (int)dev;
|
||||
struct sdmmc_card *c = &cards[no];
|
||||
struct sdmmc_command cmd;
|
||||
|
||||
if (c->inserted == 0) {
|
||||
gecko_printf("sdmmc: READ: no card inserted.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c->selected == 0) {
|
||||
if (sdmmc_select(dev) < 0) {
|
||||
gecko_printf("sdmmc: READ: cannot select card.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->new_card == 1) {
|
||||
gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE\n"));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
if (blk_count == 1)
|
||||
cmd.c_opcode = MMC_WRITE_BLOCK_SINGLE;
|
||||
else
|
||||
cmd.c_opcode = MMC_WRITE_BLOCK_MULTIPLE;
|
||||
if (c->sdhc_blockmode)
|
||||
cmd.c_arg = blk_start;
|
||||
else
|
||||
cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN;
|
||||
cmd.c_data = data;
|
||||
cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN;
|
||||
cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN;
|
||||
cmd.c_flags = SCF_RSP_R1;
|
||||
sdmmc_host_exec_command(c, &cmd);
|
||||
|
||||
if (cmd.c_error) {
|
||||
gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed for "
|
||||
"card %d with %d", no, cmd.c_error);
|
||||
return -1;
|
||||
}
|
||||
DPRINTF(2, ("sdmmc: MMC_WRITE_BLOCK_MULTIPLE done\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sdmmc_ipc(volatile ipc_request *req)
|
||||
{
|
||||
int ret;
|
||||
switch (req->req) {
|
||||
case IPC_SDMMC_ACK:
|
||||
sdmmc_ack_card(SDMMC_DEFAULT_DEVICE);
|
||||
ipc_post(req->code, req->tag, 1);
|
||||
break;
|
||||
case IPC_SDMMC_READ:
|
||||
ret = sdmmc_read(SDMMC_DEFAULT_DEVICE, req->args[0],
|
||||
req->args[1], (void *)req->args[2]);
|
||||
dc_flushrange((void *)req->args[2],
|
||||
req->args[1]*SDMMC_DEFAULT_BLOCKLEN);
|
||||
ipc_post(req->code, req->tag, 1);
|
||||
break;
|
||||
case IPC_SDMMC_WRITE:
|
||||
dc_invalidaterange((void *)req->args[2],
|
||||
req->args[1]*SDMMC_DEFAULT_BLOCKLEN);
|
||||
ret = sdmmc_write(SDMMC_DEFAULT_DEVICE, req->args[0],
|
||||
req->args[1], (void *)req->args[2]);
|
||||
ipc_post(req->code, req->tag, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
2
sdmmc.h
2
sdmmc.h
@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "bsdtypes.h"
|
||||
#include "sdmmcchip.h"
|
||||
#include "sdmmcvar.h"
|
||||
#include "ipc.h"
|
||||
|
||||
#define SDMMC_DEFAULT_CLOCK 25000
|
||||
#define SDMMC_DEFAULT_BLOCKLEN 512
|
||||
@ -43,4 +44,5 @@ int sdmmc_select(struct device *dev);
|
||||
int sdmmc_check_card(struct device *dev);
|
||||
void sdmmc_ack_card(struct device *dev);
|
||||
int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data);
|
||||
void sdmmc_ipc(volatile ipc_request *req);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user