Line 71... |
Line 71... |
unsigned int data_int_status;
|
unsigned int data_int_status;
|
} registers;
|
} registers;
|
int clock;
|
int clock;
|
|
|
/* DMA buffer used for transmitting */
|
/* DMA buffer used for transmitting */
|
unsigned int* buffer;
|
|
dma_addr_t physical_address;
|
|
unsigned int total_length;
|
unsigned int total_length;
|
unsigned int dma_len;
|
unsigned int dma_len;
|
/* Latest in the scatterlist that has been enabled for transfer, but not freed */
|
|
int in_use_index;
|
|
|
|
/* Latest in the scatterlist that has been enabled for transfer */
|
|
int transfer_index;
|
int transfer_index;
|
|
|
int free_tx_bd;
|
int free_tx_bd;
|
int free_rx_bd;
|
int free_rx_bd;
|
|
/* Latest in the scatterlist that has been enabled for transfer, but not freed */
|
|
int in_use_index;
|
};
|
};
|
|
|
struct ocores_host *oc_host;
|
|
|
|
static void ocores_tasklet_finish_cmd(unsigned long param);
|
static void ocores_tasklet_finish_cmd(unsigned long param);
|
static void ocores_tasklet_finish_data(unsigned long param);
|
static void ocores_tasklet_finish_data(unsigned long param);
|
|
|
static inline void CMD_IRQ_ON(struct ocores_host *host, u32 mask)
|
static inline void CMD_IRQ_ON(struct ocores_host *host, u32 mask)
|
Line 105... |
Line 104... |
writel (val, host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
writel (val, host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
}
|
}
|
|
|
static inline void DAT_IRQ_ON(struct ocores_host *host, u32 mask)
|
static inline void DAT_IRQ_ON(struct ocores_host *host, u32 mask)
|
{
|
{
|
|
|
|
|
u32 val = readl(host->base + SD_BD_ISER);
|
u32 val = readl(host->base + SD_BD_ISER);
|
val |= mask;
|
val |= mask;
|
writel (val, host->base + SD_BD_ISER);
|
writel (mask, host->base + SD_BD_ISER);
|
|
|
|
|
|
|
}
|
}
|
|
|
static inline void DAT_IRQ_OFF(struct ocores_host *host, u32 mask)
|
static inline void DAT_IRQ_OFF(struct ocores_host *host, u32 mask)
|
{
|
{
|
u32 val = readl(host->base + SD_BD_ISER);
|
u32 val = readl(host->base + SD_BD_ISER);
|
val &= ~mask;
|
val &= ~mask;
|
writel (val, host->base + SD_BD_ISER);
|
writel (val, host->base + SD_BD_ISER);
|
}
|
}
|
|
|
|
|
static void ocores_pre_dma_read(struct ocores_host *host)
|
static void ocores_pre_dma(struct ocores_host *host)
|
{
|
{
|
int i,j;
|
unsigned int i,j;
|
int off_scal;
|
unsigned int off_scal;
|
struct scatterlist *sg;
|
struct scatterlist *sg;
|
struct mmc_command *cmd;
|
struct mmc_command *cmd;
|
struct mmc_data *data;
|
struct mmc_data *data;
|
|
unsigned long flags;
|
|
|
off_scal=512;
|
off_scal=512;
|
if (host->mmc->card!= NULL){
|
if (host->mmc->card!= NULL){
|
|
|
if (mmc_card_blockaddr(host->mmc->card))
|
if (mmc_card_blockaddr(host->mmc->card))
|
off_scal=1;
|
off_scal=1;
|
else
|
else
|
off_scal=512;
|
off_scal=512;
|
}
|
}
|
printk("pre dma read off %d\n", off_scal);
|
pr_debug("Pre block_offset %d\n", off_scal);
|
|
|
cmd = host->cmd;
|
cmd = host->cmd;
|
if (!cmd) {
|
if (!cmd) {
|
pr_debug("no command\n");
|
pr_debug("no command\n");
|
return;
|
return;
|
Line 148... |
Line 153... |
pr_debug("no data\n");
|
pr_debug("no data\n");
|
return;
|
return;
|
}
|
}
|
|
|
/* Setup the next transfer */
|
/* Setup the next transfer */
|
pr_debug("Using transfer index %d\n", host->transfer_index);
|
|
|
|
sg = &data->sg[host->transfer_index++];
|
sg = &data->sg[host->transfer_index++];
|
printk("Using transfer index %d, sg offset %d\n", host->transfer_index,sg->offset);
|
|
pr_debug("sg = %p\n", sg);
|
|
printk("sg = %p\n", sg);
|
|
|
|
|
|
|
if (data->flags & MMC_DATA_READ)
|
host->dma_len = dma_map_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_FROM_DEVICE);
|
host->dma_len = dma_map_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_FROM_DEVICE);
|
printk(KERN_ALERT "dma address = %d, sg_dma_len %d, length = %d, sg_dma_len %d\n", sg_dma_address(&data->sg[0]), sg_dma_len(&data->sg[0]), sg->length, host->dma_len);
|
else
|
|
host->dma_len = dma_map_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_TO_DEVICE);
|
|
pr_debug(KERN_ALERT "Dma address = %d, sg_dma_len %d, length = %d, sg_dma_len %d\n", sg_dma_address(&data->sg[0]), sg_dma_len(&data->sg[0]), sg->length, host->dma_len);
|
|
printk(KERN_ALERT "Dma address = %d, sg_dma_len %d, length = %d, sg_dma_len %d\n", sg_dma_address(&data->sg[0]), sg_dma_len(&data->sg[0]), sg->length, host->dma_len);
|
|
|
for (i = 0; i < host->dma_len; i++) {
|
for (i = 0; i < host->dma_len; i++) {
|
unsigned int length = sg_dma_len(&data->sg[i]);
|
unsigned int length = sg_dma_len(&data->sg[i]);
|
|
|
if (length >= 512)
|
if (length >= 512)
|
length /=512;
|
length /=512;
|
else
|
else
|
length = 1;
|
length = 1;
|
|
|
printk(KERN_ALERT "DMA LEN %d\n", length);
|
|
//XXX:512 SD 1.0 card only.
|
//XXX:512 SD 1.0 card only.
|
|
if (data->flags & MMC_DATA_READ){
|
for (j = 0; j< length;j++) {
|
for (j = 0; j< length;j++) {
|
pr_debug("dma address = %d, length = %d\n", sg_dma_address(&data->sg[i]), sg->length);
|
|
printk(KERN_ALERT "dma address = %d, length = %d, sg_dma_len %d\n", (sg_dma_address(&data->sg[i])+512*j), length, host->dma_len);
|
|
|
|
writel((sg_dma_address(&data->sg[i])+512*j), host->base + BD_RX);
|
writel((sg_dma_address(&data->sg[i])+512*j), host->base + BD_RX);
|
wmb();
|
wmb();
|
writel(cmd->arg+off_scal*j, host->base + BD_RX);
|
writel(cmd->arg+off_scal*j, host->base + BD_RX);
|
|
|
}
|
}
|
|
DAT_IRQ_ON (host,(TRE|CMDE|FIFOE|MRC|TRS));
|
}
|
}
|
|
else{
|
|
|
DAT_IRQ_ON (host,(TRE|FIFOE|MRC|TRS));
|
for (j = 0; j< length;j++) {
|
pr_debug("pre dma read done\n");
|
|
}
|
|
static void ocores_pre_dma_write(struct ocores_host *host)
|
|
{
|
|
int i,j;
|
|
int off_scal;
|
|
struct scatterlist *sg;
|
|
struct mmc_command *cmd;
|
|
struct mmc_data *data;
|
|
|
|
off_scal=512;
|
|
if (host->mmc->card!= NULL){
|
|
|
|
if (mmc_card_blockaddr(host->mmc->card))
|
writel((sg_dma_address(&data->sg[i])+ 512*j), host->base + BD_TX);
|
off_scal=1;
|
wmb();
|
else
|
writel(cmd->arg+off_scal*j, host->base + BD_TX);
|
off_scal=512;
|
|
}
|
|
printk("pre dma write off %d\n", off_scal);
|
|
|
|
cmd = host->cmd;
|
|
if (!cmd) {
|
|
pr_debug("no command\n");
|
|
return;
|
|
}
|
|
data = cmd->data;
|
|
if (!data) {
|
|
pr_debug("no data\n");
|
|
return;
|
|
}
|
}
|
|
|
/* Setup the next transfer */
|
|
pr_debug("Using transfer index %d\n", host->transfer_index);
|
|
|
|
sg = &data->sg[host->transfer_index++];
|
|
printk("Using transfer index %d, sg offset %d\n", host->transfer_index,sg->offset);
|
|
pr_debug("sg = %p\n", sg);
|
|
printk("sg = %p\n", sg);
|
|
|
|
|
DAT_IRQ_ON (host,(TRE|CMDE|FIFOE|MRC|TRS));
|
|
pr_debug("pre dma write done\n");
|
|
}
|
|
|
host->dma_len = dma_map_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_TO_DEVICE);
|
|
printk(KERN_ALERT "dma address = %d, sg_dma_len %d, length = %d, sg_dma_len %d\n", sg_dma_address(&data->sg[0]), sg_dma_len(&data->sg[0]), sg->length, host->dma_len);
|
|
for (i = 0; i < host->dma_len; i++) {
|
|
unsigned int length = sg_dma_len(&data->sg[i]);
|
|
|
|
if (length >= 512)
|
}
|
length /=512;
|
|
else
|
|
length = 1;
|
|
|
|
printk(KERN_ALERT "DMA LEN %d\n", length);
|
|
//XXX:512 SD 1.0 card only.
|
|
for (j = 0; j< length;j++) {
|
|
pr_debug("dma address = %d, length = %d\n", sg_dma_address(&data->sg[i]), sg->length);
|
|
printk(KERN_ALERT "dma address = %d, length = %d, sg_dma_len %d\n", (sg_dma_address(&data->sg[i])+512*j), length, host->dma_len);
|
|
|
|
writel((sg_dma_address(&data->sg[i])+512*j), host->base + BD_TX);
|
|
wmb();
|
|
writel(cmd->arg+off_scal*j, host->base + BD_TX);
|
|
|
|
}
|
}
|
|
|
}
|
|
|
|
DAT_IRQ_ON (host,(TRE|FIFOE|MRC|TRS));
|
|
pr_debug("pre dma read done\n");
|
|
}
|
|
|
|
static void ocores_start_cmd(struct ocores_host *host, struct mmc_command *cmd)
|
static void ocores_start_cmd(struct ocores_host *host, struct mmc_command *cmd)
|
{
|
{
|
unsigned int cmd_arg, cmd_command=0;
|
unsigned int cmd_arg, cmd_command=0;
|
|
|
struct mmc_data *data = cmd->data;
|
struct mmc_data *data = cmd->data;
|
//WARN_ON(host->cmd != NULL);
|
//WARN_ON(host->cmd != NULL);
|
host->cmd = cmd;
|
host->cmd = cmd;
|
|
|
//XXX:opcode == 51 not supported by hardware, hack here
|
//XXX:opcode == 51 not supported by hardware, hack here
|
if (data && ( cmd->opcode != 51)) {
|
if (data && ( cmd->opcode != 51)&& ( cmd->opcode != 12)) {
|
if ( data->blksz & 0x3 ) {
|
if ( data->blksz & 0x3 ) {
|
pr_debug("Unsupported block size\n");
|
pr_debug("Unsupported block size\n");
|
cmd->error = -EINVAL;
|
cmd->error = -EINVAL;
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
return;
|
return;
|
Line 271... |
Line 227... |
data->bytes_xfered = 0;
|
data->bytes_xfered = 0;
|
host->transfer_index = 0;
|
host->transfer_index = 0;
|
host->in_use_index = 0;
|
host->in_use_index = 0;
|
|
|
if (data->flags & MMC_DATA_READ){ //Handle a read
|
if (data->flags & MMC_DATA_READ){ //Handle a read
|
printk(KERN_ALERT "%s: Data read\n", __FUNCTION__);
|
pr_debug(KERN_ALERT "%s: Data read dat Len %u\n", __FUNCTION__,host->total_length);
|
host->buffer = NULL;
|
|
host->total_length = 0;
|
|
ocores_pre_dma_read(host); //Set up BD
|
|
|
|
}
|
|
else if (data->flags & MMC_DATA_WRITE){ //Handle write
|
|
printk(KERN_ALERT "%s: Data write\n", __FUNCTION__); //cmdr |= AT91_MCI_TRCMD_START;
|
|
/*host->buffer = dma_alloc_coherent(NULL,
|
|
host->total_length,
|
|
&host->physical_address, GFP_KERNEL); */
|
|
host->total_length = 0;
|
host->total_length = 0;
|
ocores_pre_dma_write(host); //Set up BD
|
ocores_pre_dma(host); //Set up BD
|
|
|
}
|
}
|
|
else if (data->flags & MMC_DATA_WRITE){ //Handle write
|
|
//cmdr |= AT91_MCI_TRCMD_START;
|
|
|
|
host->total_length = data->sg->length;
|
|
pr_debug(KERN_ALERT "%s: Data write dat Len %u\n", __FUNCTION__,host->total_length);
|
|
|
if (data->flags & MMC_DATA_STREAM)
|
ocores_pre_dma(host); //Set up BD
|
printk(KERN_ALERT "%s: MMC_DATA_STREAM\n", __FUNCTION__);
|
|
if (data->blocks > 1)
|
|
printk(KERN_ALERT "%s: data->blocks %d > 1 \n", __FUNCTION__, data->blocks);
|
|
|
|
|
|
/*
|
|
host->total_length = block_length * blocks;
|
|
host->buffer = dma_alloc_coherent(NULL,
|
|
host->total_length,
|
|
&host->physical_address, GFP_KERNEL);
|
|
|
|
at91_mci_sg_to_dma(host, data);
|
|
|
|
pr_debug("Transmitting %d bytes\n", host->total_length);
|
|
|
|
at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
|
|
at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
|
|
ier = AT91_MCI_CMDRDY; */
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
}
|
else{
|
else{
|
//Set up command
|
//Set up command
|
Line 348... |
Line 281... |
//Send Command
|
//Send Command
|
CMD_IRQ_ON (host,(ECC|EEI));
|
CMD_IRQ_ON (host,(ECC|EEI));
|
writel(cmd_command, host->base + SD_COMMAND);
|
writel(cmd_command, host->base + SD_COMMAND);
|
wmb();
|
wmb();
|
writel(cmd_arg, host->base + SD_ARG);
|
writel(cmd_arg, host->base + SD_ARG);
|
printk(KERN_ALERT "%s: cmd_arg = %08x\n", __FUNCTION__, cmd_arg);
|
//printk(KERN_ALERT "%s: cmd_arg = %08x\n", __FUNCTION__, cmd_arg);
|
printk(KERN_ALERT "%s: cmd_command = %08x\n", __FUNCTION__, cmd_command);
|
//printk(KERN_ALERT "%s: cmd_command = %08x\n", __FUNCTION__, cmd_command);
|
|
|
}
|
}
|
|
|
|
|
oc_host=host;
|
|
|
|
|
|
}
|
}
|
|
|
static void ocores_process_next(struct ocores_host *host)
|
static void ocores_process_next(struct ocores_host *host)
|
{
|
{
|
host->word_cnt=0;
|
host->word_cnt=0;
|
|
|
if (!(host->flags & FL_SENT_COMMAND)) {
|
if (!(host->flags & FL_SENT_COMMAND)) {
|
host->flags |= FL_SENT_COMMAND;
|
host->flags |= FL_SENT_COMMAND;
|
ocores_start_cmd(host, host->mrq->cmd);
|
ocores_start_cmd(host, host->mrq->cmd);
|
}
|
}
|
else if ((!(host->flags & FL_SENT_STOP)) && host->mrq->stop) {
|
else if ((!(host->flags & FL_SENT_STOP)) && host->mrq->stop) {
|
Line 376... |
Line 307... |
|
|
static void ocores_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
static void ocores_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
{
|
{
|
struct ocores_host *host = mmc_priv(mmc);
|
struct ocores_host *host = mmc_priv(mmc);
|
|
|
//unsigned int cmdr, mr;
|
|
|
|
printk(KERN_ALERT "%s: mrq->cmd->opcode = %08x\n", __FUNCTION__, mrq->cmd->opcode);
|
|
printk(KERN_ALERT "%s: mrq->cmd->arg = %08x\n", __FUNCTION__, mrq->cmd->arg);
|
|
|
|
//WARN_ON(host->mrq != NULL);
|
|
|
|
host->mrq = mrq;
|
host->mrq = mrq;
|
host->flags = 0;
|
host->flags = 0;
|
|
|
ocores_process_next(host);
|
ocores_process_next(host);
|
|
|
|
|
printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
|
//printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
|
}
|
}
|
|
|
|
|
|
|
static int ocores_get_ro(struct mmc_host *mmc)
|
static int ocores_get_ro(struct mmc_host *mmc)
|
Line 471... |
Line 395... |
|
|
static irqreturn_t ocores_irq_dat(int irq, void *devid)
|
static irqreturn_t ocores_irq_dat(int irq, void *devid)
|
{
|
{
|
struct ocores_host *host = (struct ocores_host *) devid;
|
struct ocores_host *host = (struct ocores_host *) devid;
|
|
|
disable_irq(host->irq_dat);
|
//disable_irq(host->irq_dat);
|
|
|
printk(KERN_ALERT "%s: DAT IRQ START***** Normal In = %08x\n", __FUNCTION__, readl(host->base + SD_BD_ISR));
|
|
|
|
host->registers.data_int_status = readl(host->base + SD_BD_ISR);
|
host->registers.data_int_status = readl(host->base + SD_BD_ISR);
|
|
|
writel(0,host->base + SD_BD_ISR);
|
writel(0,host->base + SD_BD_ISR);
|
|
|
tasklet_schedule(&host->finish_data);
|
tasklet_schedule(&host->finish_data);
|
|
|
enable_irq(host->irq_dat);
|
//enable_irq(host->irq_dat);
|
|
|
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
|
|
|
|
|
|
Line 528... |
Line 449... |
mmc->ops = &ocores_ops;
|
mmc->ops = &ocores_ops;
|
|
|
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
|
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
|
mmc->caps = MMC_CAP_4_BIT_DATA;
|
mmc->caps = MMC_CAP_4_BIT_DATA;
|
mmc->f_min = 700000; //SYS_CLK 60; 0.7 Mhz
|
mmc->f_min = 700000; //SYS_CLK 60; 0.7 Mhz
|
mmc->f_max = 4166666; //SYS_CLK; 4.166 666 mhz
|
mmc->f_max = 6166666; //SYS_CLK; 4.166 666 mhz
|
|
|
mmc->max_blk_count = 8;//8; //XXX: 8
|
mmc->max_blk_count = 4;//8; //XXX: 8
|
mmc->max_hw_segs = 1;
|
mmc->max_hw_segs = 2;
|
mmc->max_blk_size = MMCOC_MAX_BLOCK_SIZE;
|
mmc->max_blk_size = MMCOC_MAX_BLOCK_SIZE;
|
//mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
|
//mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
|
|
|
|
|
mmc->max_seg_size = PAGE_SIZE;
|
mmc->max_seg_size = PAGE_SIZE;
|
Line 605... |
Line 526... |
enable_irq(host->irq_cmd);
|
enable_irq(host->irq_cmd);
|
enable_irq(host->irq_dat);
|
enable_irq(host->irq_dat);
|
printk(KERN_ALERT "%s: host->base = %p\n", __FUNCTION__, host->base);
|
printk(KERN_ALERT "%s: host->base = %p\n", __FUNCTION__, host->base);
|
printk(KERN_ALERT "%s: SD_BLOCK = %08x\n", __FUNCTION__, readl(host->base + SD_BLOCK));
|
printk(KERN_ALERT "%s: SD_BLOCK = %08x\n", __FUNCTION__, readl(host->base + SD_BLOCK));
|
printk(KERN_ALERT "%s: host->pdata->ocr_mask = %08x\n", __FUNCTION__, host->pdata->ocr_mask);
|
printk(KERN_ALERT "%s: host->pdata->ocr_mask = %08x\n", __FUNCTION__, host->pdata->ocr_mask);
|
oc_host=host;
|
|
mmc_add_host(mmc);
|
mmc_add_host(mmc);
|
|
|
printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
|
printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
|
|
|
return 0;
|
return 0;
|
Line 631... |
Line 552... |
struct mmc_data *data;
|
struct mmc_data *data;
|
struct scatterlist *sg;
|
struct scatterlist *sg;
|
data = host->cmd->data;
|
data = host->cmd->data;
|
sg = &data->sg[0];
|
sg = &data->sg[0];
|
|
|
printk(KERN_ALERT " CMD TASKLET RUNNS************\n");
|
//printk(KERN_ALERT " CMD TASKLET RUNNS************\n");
|
//Check For Transmissions errors
|
//Check For Transmissions errors
|
if ((host->registers.normal_int_status & EI) == EI)
|
if ((host->registers.normal_int_status & EI) == EI)
|
{
|
{
|
printk(KERN_ALERT "TRANSMISSION ERROR DETECTED");
|
printk(KERN_ALERT "TRANSMISSION ERROR DETECTED");
|
switch ( host->registers.error_int_status )
|
switch ( host->registers.error_int_status )
|
{
|
{
|
case (CTE):
|
case (CTE):
|
pr_debug("Card took too long to respond\n");
|
pr_debug("Card took too long to respond\n");
|
host->mrq->cmd->error = -ETIMEDOUT ;
|
host->mrq->cmd->error = -ETIMEDOUT ;
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->error = -ETIMEDOUT ;
|
break;
|
break;
|
case (CCRC ):
|
case (CCRC ):
|
pr_debug(" CRC problem with the received or sent data\n");
|
pr_debug(" CRC problem with the received or sent data\n");
|
host->mrq->cmd->error = -EILSEQ;
|
host->mrq->cmd->error = -EILSEQ;
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->error = -EILSEQ ;
|
break;
|
break;
|
case (CIE ):
|
case (CIE ):
|
pr_debug("Index problem with the received or sent data\n");
|
pr_debug("Index problem with the received or sent data\n");
|
host->mrq->cmd->error = -EILSEQ;
|
host->mrq->cmd->error = -EILSEQ;
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->error = -EILSEQ ;
|
break;
|
break;
|
}
|
}
|
|
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
}
|
}
|
Line 706... |
Line 633... |
}
|
}
|
}
|
}
|
else //Short response
|
else //Short response
|
{
|
{
|
host->mrq->cmd->error = 0 ;
|
host->mrq->cmd->error = 0 ;
|
|
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->resp[0] = readl(host->base + SD_RESP1);
|
|
else
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
printk(KERN_ALERT "Short Response CMD RSP * = %08x\n", host->mrq->cmd->resp[0]);
|
//printk(KERN_ALERT "Short Response CMD RSP * = %08x\n", host->mrq->cmd->resp[0]);
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
}
|
}
|
}
|
}
|
|
|
}
|
}
|
Line 725... |
Line 656... |
int free_bd,i;
|
int free_bd,i;
|
int *adr;
|
int *adr;
|
data = host->cmd->data;
|
data = host->cmd->data;
|
sg = &data->sg[0]; //XXX:O Change to dynamic later?
|
sg = &data->sg[0]; //XXX:O Change to dynamic later?
|
|
|
printk(KERN_ALERT " DATA TASKLET RUNNS************\n");
|
|
|
|
//IF read operation
|
//IF read operation
|
|
|
if ((host->registers.data_int_status & TRS) == TRS){
|
if ((host->registers.data_int_status & TRS) == TRS){
|
if (data->flags & MMC_DATA_READ){
|
if (data->flags & MMC_DATA_READ){
|
free_bd=readl( host->base + BD_STATUS );
|
free_bd=readl( host->base + BD_STATUS );
|
free_bd=(free_bd&0xff00)>>8;
|
free_bd=(free_bd&0xff00)>>8;
|
printk(KERN_ALERT " DATA TASKLET RUNNS*** Free BD %d\n", free_bd);
|
//printk(KERN_ALERT " DATA READ TASKLET RUNNS*** Free BD %d\n", free_bd);
|
if (free_bd == host->free_tx_bd) {
|
if (free_bd == host->free_rx_bd) {
|
dma_unmap_sg(mmc_dev(host->mmc), sg, sg->length, DMA_FROM_DEVICE);
|
dma_unmap_sg(mmc_dev(host->mmc), sg, sg->length, DMA_FROM_DEVICE);
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
|
|
|
DAT_IRQ_OFF (host,(TRE|CMDE|FIFOE|MRC|TRS));
|
data->bytes_xfered = sg->length;
|
data->bytes_xfered = sg->length;
|
DAT_IRQ_OFF (host,(TRE|FIFOE|MRC|TRS));
|
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->resp[0] = readl(host->base + SD_RESP1);
|
|
|
|
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
|
|
}
|
}
|
} else if (data->flags & MMC_DATA_WRITE){
|
} else if (data->flags & MMC_DATA_WRITE){
|
free_bd=readl( host->base + BD_STATUS );
|
free_bd=readl( host->base + BD_STATUS );
|
free_bd=(free_bd&0x00FF);
|
free_bd=(free_bd&0x00FF);
|
printk(KERN_ALERT " DATA TASKLET RUNNS*** Free BD %d\n", free_bd);
|
//printk(KERN_ALERT " DATA WRITE TASKLET RUNNS*** Free BD %d\n", free_bd);
|
if (free_bd == host->free_tx_bd) {
|
if (free_bd == host->free_tx_bd) {
|
dma_unmap_sg(mmc_dev(host->mmc), sg, sg->length, DMA_TO_DEVICE);
|
dma_unmap_sg(mmc_dev(host->mmc), sg, sg->length, DMA_TO_DEVICE);
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
|
|
|
DAT_IRQ_OFF (host,(TRE|CMDE|FIFOE|MRC|TRS));
|
data->bytes_xfered = sg->length;
|
data->bytes_xfered = sg->length;
|
DAT_IRQ_OFF (host,(TRE|FIFOE|MRC|TRS));
|
|
|
|
|
if (host->mrq->stop)
|
|
host->mrq->stop->resp[0] = readl(host->base + SD_RESP1);
|
|
|
|
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
|
|
}
|
}
|
|
|
}
|
}
|
|
|
}
|
}
|
else {
|
else { printk(KERN_ALERT "DATA TRANS ERROR %d\n", host->registers.data_int_status);
|
sg= &data->sg[0];
|
|
writel(SD_DISABLE, host->base + SD_SOFTWARE_RST);
|
|
writel(SD_ENABLE, host->base + SD_SOFTWARE_RST);
|
|
|
|
|
data->error = -ETIMEDOUT;
|
if ((host->registers.data_int_status & MRC) == MRC)
|
if ((host->registers.data_int_status & MRC) == MRC)
|
host->data->error = -ETIMEDOUT;
|
data->error = -ETIMEDOUT;
|
if ((host->registers.data_int_status & CMDE) == CMDE)
|
if ((host->registers.data_int_status & CMDE) == CMDE)
|
host->data->error = -EILSEQ;
|
data->error = -EILSEQ;
|
data->bytes_xfered =0;
|
data->bytes_xfered =0;
|
|
|
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
dma_unmap_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_FROM_DEVICE);
|
dma_unmap_sg(mmc_dev(host->mmc), sg, data->sg_len, DMA_FROM_DEVICE);
|
DAT_IRQ_OFF (host,(TRE|FIFOE|MRC|TRS));
|
DAT_IRQ_OFF (host,(TRE|FIFOE|MRC|TRS));
|
mmc_request_done(host->mmc, host->mrq);
|
mmc_request_done(host->mmc, host->mrq);
|
|
|
|
|
Line 785... |
Line 730... |
|
|
}
|
}
|
static int ocores_remove(struct platform_device *pdev)
|
static int ocores_remove(struct platform_device *pdev)
|
{
|
{
|
struct mmc_host *mmc = platform_get_drvdata(pdev);
|
struct mmc_host *mmc = platform_get_drvdata(pdev);
|
|
struct ocores_host *host;
|
|
struct resource *r;
|
|
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
|
printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
|
|
|
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
|
|
|
tasklet_kill(&host->finish_cmd);
|
|
tasklet_kill(&host->finish_data);
|
|
|
|
free_irq(host->irq_cmd, host);
|
|
free_irq(host->irq_dat, host);
|
|
|
|
iounmap(host->base);
|
|
|
|
release_mem_region(r->start, r->end - r->start + 1);
|
if (mmc) {
|
if (mmc) {
|
struct ocores_host *host = mmc_priv(mmc);
|
struct ocores_host *host = mmc_priv(mmc);
|
|
|
mmc_remove_host(mmc);
|
mmc_remove_host(mmc);
|
|
|