Line 38... |
Line 38... |
|
|
struct ocores_registers
|
struct ocores_registers
|
{
|
{
|
unsigned int normal_int_status;
|
unsigned int normal_int_status;
|
unsigned int error_int_status;
|
unsigned int error_int_status;
|
|
|
};
|
};
|
|
|
struct ocores_host {
|
struct ocores_host {
|
struct mmc_host *mmc;
|
struct mmc_host *mmc;
|
spinlock_t lock;
|
spinlock_t lock;
|
Line 60... |
Line 59... |
unsigned int flags;
|
unsigned int flags;
|
struct tasklet_struct finish_cmd;
|
struct tasklet_struct finish_cmd;
|
struct {
|
struct {
|
unsigned int normal_int_status;
|
unsigned int normal_int_status;
|
unsigned int error_int_status;
|
unsigned int error_int_status;
|
|
|
} registers;
|
} registers;
|
|
|
};
|
};
|
|
|
struct ocores_host *oc_host;
|
struct ocores_host *oc_host;
|
|
|
static void ocores_tasklet_finish_cmd(unsigned long param);
|
static void ocores_tasklet_finish_cmd(unsigned long param);
|
Line 82... |
Line 79... |
static inline void CMD_IRQ_OFF(struct ocores_host *host, u32 mask)
|
static inline void CMD_IRQ_OFF(struct ocores_host *host, u32 mask)
|
{
|
{
|
u32 val = readl(host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
u32 val = readl(host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
val &= ~mask;
|
val &= ~mask;
|
writel (val, host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
writel (val, host->base + SD_NOMAL_INT_SIGNAL_ENABLE);
|
|
|
}
|
}
|
|
|
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;
|
|
|
Line 127... |
Line 123... |
cmd_command |= CRCE;
|
cmd_command |= CRCE;
|
if ( mmc_resp_type(cmd) == MMC_RSP_OPCODE )
|
if ( mmc_resp_type(cmd) == MMC_RSP_OPCODE )
|
cmd_command |= CICE;
|
cmd_command |= CICE;
|
|
|
|
|
|
|
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);
|
|
|
CMD_IRQ_ON (host,ECC);
|
CMD_IRQ_ON (host,ECC);
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|
|
|
static void ocores_process_next(struct ocores_host *host)
|
static void ocores_process_next(struct ocores_host *host)
|
{
|
{
|
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) {
|
host->flags |= FL_SENT_STOP;
|
host->flags |= FL_SENT_STOP;
|
ocores_start_cmd(host, host->mrq->stop);
|
ocores_start_cmd(host, host->mrq->stop);
|
}
|
}
|
|
|
}
|
}
|
|
|
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;
|
//unsigned int cmdr, mr;
|
|
|
printk(KERN_ALERT "%s: mrq->cmd->opcode = %08x\n", __FUNCTION__, mrq->cmd->opcode);
|
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);
|
printk(KERN_ALERT "%s: mrq->cmd->arg = %08x\n", __FUNCTION__, mrq->cmd->arg);
|
|
|
//WARN_ON(host->mrq != NULL);
|
//WARN_ON(host->mrq != NULL);
|
Line 171... |
Line 162... |
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__);
|
}
|
}
|
|
|
|
|
|
|
Line 220... |
Line 210... |
|
|
writel (clk_div, host->base + SD_CLOCK_DIVIDER);
|
writel (clk_div, host->base + SD_CLOCK_DIVIDER);
|
writel (cmd_timeout, host->base + SD_TIMEOUT);
|
writel (cmd_timeout, host->base + SD_TIMEOUT);
|
|
|
|
|
|
|
writel(SD_ENABLE, host->base + SD_SOFTWARE_RST);
|
writel(SD_ENABLE, host->base + SD_SOFTWARE_RST);
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|
|
|
|
|
|
|
static irqreturn_t ocores_irq_cmd(int irq, void *devid)
|
static irqreturn_t ocores_irq_cmd(int irq, void *devid)
|
Line 252... |
Line 236... |
|
|
printk(KERN_ALERT "%s: IRQ END***** Error In = %08x\n", __FUNCTION__, readl(host->base + SD_ERROR_INT_STATUS));
|
printk(KERN_ALERT "%s: IRQ END***** Error In = %08x\n", __FUNCTION__, readl(host->base + SD_ERROR_INT_STATUS));
|
tasklet_schedule(&host->finish_cmd);
|
tasklet_schedule(&host->finish_cmd);
|
CMD_IRQ_OFF (host,ECC);
|
CMD_IRQ_OFF (host,ECC);
|
enable_irq(host->irq_cmd);
|
enable_irq(host->irq_cmd);
|
|
|
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
}
|
}
|
|
|
static irqreturn_t ocores_irq_dat(int irq, void *dev_id)
|
static irqreturn_t ocores_irq_dat(int irq, void *dev_id)
|
{
|
{
|
|
|
}
|
}
|
|
|
static const struct mmc_host_ops ocores_ops = {
|
static const struct mmc_host_ops ocores_ops = {
|
.request = ocores_request,
|
.request = ocores_request,
|
.get_ro = ocores_get_ro,
|
.get_ro = ocores_get_ro,
|
.set_ios = ocores_set_ios,
|
.set_ios = ocores_set_ios,
|
/* .enable_sdio_irq = ocores_enable_sdio_irq, */
|
/* .enable_sdio_irq = ocores_enable_sdio_irq, */
|
Line 291... |
Line 277... |
ret = -ENOMEM;
|
ret = -ENOMEM;
|
goto out;
|
goto out;
|
}
|
}
|
|
|
|
|
|
|
|
|
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
|
Line 346... |
Line 330... |
goto out;
|
goto out;
|
disable_irq(host->irq_dat);
|
disable_irq(host->irq_dat);
|
|
|
|
|
|
|
|
|
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);
|
Line 369... |
Line 352... |
release_resource(r);
|
release_resource(r);
|
|
|
return ret;
|
return ret;
|
}
|
}
|
|
|
|
static void ocores_tasklet_finish_cmd(unsigned long param)
|
|
{
|
|
struct ocores_host *host = (struct ocores_host *) param;
|
|
|
|
printk(KERN_ALERT " TASKLET RUNNS************\n");
|
|
|
|
printk(KERN_ALERT "%s: TASKLET RUNNS****** Normal INT = %08x\n", __FUNCTION__, host->registers.normal_int_status);
|
|
printk(KERN_ALERT "%s: TASKLET RUNNS****** Error INT = %08x\n", __FUNCTION__, host->registers.error_int_status);
|
|
|
|
//Check For Transmissions errors
|
|
if ((host->registers.normal_int_status & EI) == EI)
|
|
{
|
|
printk(KERN_ALERT "TRANSMISSION ERROR DETECTED");
|
|
switch ( host->registers.error_int_status )
|
|
{
|
|
case (CTE):
|
|
pr_debug("Card took too long to respond\n");
|
|
host->mrq->cmd->error = -ETIMEDOUT ;
|
|
break;
|
|
case (CCRC ):
|
|
pr_debug(" CRC problem with the received or sent data\n");
|
|
host->mrq->cmd->error = -EILSEQ;
|
|
break;
|
|
case (CIE ):
|
|
pr_debug("Index problem with the received or sent data\n");
|
|
host->mrq->cmd->error = -EILSEQ;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
host->mrq->cmd->error = 0 ;
|
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
|
printk(KERN_ALERT " CMD RSP * = %08x\n", host->mrq->cmd->resp[0]);
|
|
}
|
|
|
|
mmc_request_done(host->mmc, host->mrq);
|
|
|
|
}
|
|
|
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);
|
|
|
printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
|
printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
|
Line 439... |
Line 462... |
.driver = {
|
.driver = {
|
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
},
|
},
|
};
|
};
|
|
|
static void ocores_tasklet_finish_cmd(unsigned long param)
|
|
{
|
|
struct ocores_host *host = (struct ocores_host *) param;
|
|
|
|
printk(KERN_ALERT " TASKLET RUNNS************\n");
|
|
|
|
printk(KERN_ALERT "%s: TASKLET RUNNS****** Normal INT = %08x\n", __FUNCTION__, host->registers.normal_int_status);
|
|
printk(KERN_ALERT "%s: TASKLET RUNNS****** Error INT = %08x\n", __FUNCTION__, host->registers.error_int_status);
|
|
|
|
//Check For Transmissions errors
|
|
if ((host->registers.normal_int_status & EI) == EI)
|
|
{
|
|
printk(KERN_ALERT "TRANSMISSION ERROR DETECTED");
|
|
switch ( host->registers.error_int_status )
|
|
{
|
|
case (CTE):
|
|
pr_debug("Card took too long to respond\n");
|
|
host->mrq->cmd->error = -ETIMEDOUT ;
|
|
break;
|
|
case (CCRC ):
|
|
pr_debug(" CRC problem with the received or sent data\n");
|
|
host->mrq->cmd->error = -EILSEQ;
|
|
break;
|
|
case (CIE ):
|
|
pr_debug("Index problem with the received or sent data\n");
|
|
host->mrq->cmd->error = -EILSEQ;
|
|
break;
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
host->mrq->cmd->error = 0 ;
|
|
host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
|
|
printk(KERN_ALERT " CMD RSP * = %08x\n", host->mrq->cmd->resp[0]);
|
|
|
|
}
|
|
|
|
|
|
mmc_request_done(host->mmc, host->mrq);
|
|
|
|
|
|
}
|
|
|
|
static int __init ocores_init(void)
|
static int __init ocores_init(void)
|
{
|
{
|
printk(KERN_ALERT "%s: registering ocores platform_driver\n", __FUNCTION__);
|
printk(KERN_ALERT "%s: registering ocores platform_driver\n", __FUNCTION__);
|
|
|
return platform_driver_register(&ocores_driver);
|
return platform_driver_register(&ocores_driver);
|