2011-02-16 00:53:07 error when mount the SD card!
zhang zhihua (CHINA)
Message: 98190
Hi,I update my kernel to the 2010R1,but when I mount the SD card to the /mnt/,it's error!
root:/> mount /dev/mmcblk0p1 /mnt/
mmcblk0: error -110 sending read/write command, response 0x800900, card status 0
x800900
end_request: I/O error, dev mmcblk0, sector 255
FAT: unable to read boot sector
irq 58: nobody cared (try booting with the "irqpoll" option)
Hardware Trace:
0 Target : <0x00133234> { _dump_stack + 0x0 }
Source : <0x0002f954> { ___report_bad_irq + 0x1c } JUMP.L
1 Target : <0x0002f954> { ___report_bad_irq + 0x1c }
Source : <0x0002f9b0> { ___report_bad_irq + 0x78 } JUMP.S
2 Target : <0x0002f9b0> { ___report_bad_irq + 0x78 }
Source : <0x00133338> { _printk + 0x14 } RTS
3 Target : <0x00133334> { _printk + 0x10 }
Source : <0x00010f06> { _vprintk + 0x16a } RTS
4 Target : <0x00010efa> { _vprintk + 0x15e }
Source : <0x00010eec> { _vprintk + 0x150 } IF CC JUMP pcrel
5 Target : <0x00010ee4> { _vprintk + 0x148 }
Source : <0x00010fce> { _vprintk + 0x232 } JUMP.S
6 Target : <0x00010fce> { _vprintk + 0x232 }
Source : <0x00010b22> { _release_console_sem + 0x1be } RTS
7 Target : <0x00010afc> { _release_console_sem + 0x198 }
Source : <0x00010aee> { _release_console_sem + 0x18a } IF CC JUMP pcrel (BP
)
8 Target : <0x00010ae6> { _release_console_sem + 0x182 }
Source : <0x0002355a> { _up + 0x3e } RTS
9 Target : <0x00023554> { _up + 0x38 }
Source : <0x00023546> { _up + 0x2a } IF CC JUMP pcrel (BP)
10 Target : <0x0002351c> { _up + 0x0 }
Source : <0x00010ae2> { _release_console_sem + 0x17e } CALL pcrel
11 Target : <0x00010ace> { _release_console_sem + 0x16a }
Source : <0x000109c6> { _release_console_sem + 0x62 } IF CC JUMP pcrel
12 Target : <0x000109a6> { _release_console_sem + 0x42 }
Source : <0x000109f8> { _release_console_sem + 0x94 } IF CC JUMP pcrel (BP)
13 Target : <0x000109ee> { _release_console_sem + 0x8a }
Source : <0x00010576> { __call_console_drivers + 0x62 } RTS
14 Target : <0x00010570> { __call_console_drivers + 0x5c }
Source : <0x0001054a> { __call_console_drivers + 0x36 } IF CC JUMP pcrel
15 Target : <0x0001053a> { __call_console_drivers + 0x26 }
Source : <0x0001052a> { __call_console_drivers + 0x16 } IF !CC JUMP pcrel (
BP)
Stack info:
SP: [0x0149dc30] <0x0149dc30> /* kernel dynamic memory */
FP: (0x0149dc88)
Memory from 0x0149dc30 to 0149e000
0149dc30:[ffa003ae] 0002f958 001ae3f4 0000003a <0002eb0e> 0000003a 00000000
0002fac0
0149dc50: 001ae3f4 0000003f 000001c8 00014a5e 000302e8 001ae3f4 0148e3e0
0149c000
0149dc70: 0000003a 0149de00 ffffffc0 0000000a 001a1db0 00014a5e (00000000)<
ffa00352>
0149dc90: 001b2254 0000003a 000dfca6 000080d0 00000000 ffa00c40 001b2254
00000202
0149dcb0: 00000000 <0002eb0e> 00000006 02003025 00014af0 0000c090 00000000
00000000
0149dcd0: 014a0000 0170283c 00014af0 ffa00338 00000007 02002000 00050736
0009c010
0149dcf0: 00050726 0009c00e 00000000 00000000 00001719 00000000 00900000
00000000
0149dd10: 00000000 014bf020 00000000 00000001 00000000 00000000 00000000
00000000
0149dd30: 00000000 00000000 00000001 00000000 00000000 00000000 00000000
0149de00
0149dd50: 00000000 001a1db0 001b2254 0148e3e0 0149c000 001aa454 0149c000
0019d094
0149dd70: 00000202 00000000 ffffffc0 0000000a 0149ddd8 00000100 0149c000
0000ffff
0149dd90: 0000ffff 0019d094 00000006 00000000 000302e8 001ae3f4 0148e3e0
001aa454
0149ddb0: 0000003a 000001c8 ffa00338 001b2254 0148e3e0 001aa454 0000003a
00000000
0149ddd0: ffffffc0 00000118 0149de0c 00040f56 000000e3 ffa00c40 0148e3e0
00000000
0149ddf0: 0000003f 0149de80 0009ba8a 00000002 000127ee 00008090 00000000
00000000
0149de10: 014a0000 0170283c 000127ee 000127d0 00000007 02003025 00050736
0009c010
0149de30: 00050726 0009c00e 00000000 00000000 00001719 00000000 00900000
00000000
0149de50: 00000000 014bf020 00000000 00000001 00000000 00000000 00000000
00000000
0149de70: 00000000 00000000 00000001 00000000 00000000 00000000 00000000
0149fe50
0149de90: 00000000 000001c8 0148e3e0 0148e3e0 001aa454 01004b7c 00000008
01003740
0149deb0: 00000000 0000003f ffffffc0 00000118 0148e3e0 00000000 014983c0
0000ffff
0149ded0: 0000ffff 01003740 00000006 0149defc 00000001 00000008 00000000
00012a94
0149def0: 0148e3e0 00000000 0149df98 000000e4 00000100 000000e4 00000000
0148e3e0
0149df10: 00000000 00000000 00000000 00000000 0149c008 00000008 00000001
0149df98
0149df30: 00012d28 0148e3e0 0148ed84 0148ec80 00000000 00000120 0000010c
0149c000
0149df50: 00000000 00000000 00000000 0149c000 0149c000 0149dfb0 00000000
00012e52
0149df70: 0119bb20 00000000 00000000 00000004 0101e820 0149dfe8 00000000
00000000
0149df90: 0001cc2c 00000000 00000000 00000004 0101e820 00000000 0149dfe8
00000000
0149dfb0: 00000000 0148ec80 00011e4c 01498208 01498208 fffffff6 0001ce6c
00000000
0149dfd0: 00000000 00000000 00000000 00000000 00000000 00000000 00000100 <
000014ae>
0149dff0: 00000000 00000000 ffffffff 00000006
Return addresses in stack:
address : <0xffa003ae> { _bfin_coretmr_interrupt + 0x12 }
address : <0x0002eb0e> { _handle_IRQ_event + 0x4a }
frame 1 : <0xffa00352> { _asm_do_IRQ + 0x72 }
address : <0x0002eb0e> { _handle_IRQ_event + 0x4a }
address : <0x000014ae> { _kernel_thread_helper + 0x6 }
handlers:
[<000dfc70>] (_sdh_stat_irq+0x0/0x170)
Disabling IRQ #58
mount: mounting /dev/mmcblk0p1 on /mnt/ failed: No such device
the kernel config is:
--- MMC/SD/SDIO card support
[ ] MMC debugging
[ ] Assume MMC/SD cards are non-removable (DANGEROUS)
*** MMC/SD/SDIO Card Drivers ***
<*> MMC block device driver
[*] Use bounce buffer for simple hosts
< > SDIO UART/GPS class support
< > MMC host test driver
*** MMC/SD/SDIO Host Controller Drivers ***
< > Secure Digital Host Controller Interface support
< > MMC/SD/SDIO over SPI
<*> Blackfin Secure Digital Host support
[*] Blackfin EZkit Missing SDH_CMD Pull Up Resistor Workaround
TranslateQuoteReplyEditDelete
2011-02-16 02:02:01 Re: error when mount the SD card!
Aaron Wu (CHINA)
Message: 98191
I remember you post a similar issue on the following link. My trial shows that it depend on the specific SD card module, my working card module number is also provided. Maybe this IO error is something about the timming tollerance? Have you tired some other SD card?
blackfin.uclinux.org/gf/project/uclinux-dist/forum/?_forum_action=MessageReply&action=ForumBrowse&message_id=97062
QuoteReplyEditDelete
2011-02-16 22:04:07 Re: error when mount the SD card!
zhang zhihua (CHINA)
Message: 98210
Hi,The card we use not the SD card but a TF card.
I try to use a 2G Kingston card or a Ruineng card,but have the same error!If I use a SanDisk card,I can mount it,but sometimes I can't umount it or can't copy the file to it!
TranslateQuoteReplyEditDelete
2011-02-16 23:43:22 Re: error when mount the SD card!
Aaron Wu (CHINA)
Message: 98211
It does not matter much you use a micsoSD card with a socket. As discussed in another post, the 256MB BLASKs SD memory card I tried works. So looks like it should be related to the timming compatibility. I understand your case, suggest you to follow the SD/MMC protocol spec, along with the blackfin SD driver code, do the debug to find out excactly which command it fails when doing the SD transaction, then add some dealy to ajust the timming.
QuoteReplyEditDelete
2011-02-17 00:47:34 Re: error when mount the SD card!
zhang zhihua (CHINA)
Message: 98212
OK,thank you!I'll try it again!
TranslateQuoteReplyEditDelete
2011-02-17 02:43:25 Re: error when mount the SD card!
zhang zhihua (CHINA)
Message: 98214
Hi,Aaron,
How to add some dealy to ajust the timming,modfiy the /home/uClinux-dist/linux-2.6.x/drivers/mmc/card/block.c?
TranslateQuoteReplyEditDelete
2011-02-17 03:31:28 Re: error when mount the SD card!
Aaron Wu (CHINA)
Message: 98219
I don't think so, it's for the block device support for mmc card. Basically where you add your delay depend on the actual point you get your I/O and SD command failure, however, you may try some general method first, like lowering the SD controller operation speed. The blackfin SD controller driver is located in drivers/mmc/host/bfin_sdh.c, you can find some clock related code there, also please consult the HRM of your processor.
QuoteReplyEditDelete
2011-03-07 06:11:16 Re: error when mount the SD card!
zhang zhihua (CHINA)
Message: 98671
Hi,Aaron,
Is modfiy the "bfin_write_SDH_DATA_TIMER(0xFFFFFFFF)"?
static struct bfin_sd_host *get_sdh_data(struct platform_device *pdev)
{
return pdev->dev.platform_data;
}
static void sdh_stop_clock(struct sdh_host *host)
{
bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() & ~CLK_E);
SSYNC();
}
static void sdh_enable_stat_irq(struct sdh_host *host, unsigned int mask)
{
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
host->imask |= mask;
bfin_write_SDH_MASK0(mask);
SSYNC();
spin_unlock_irqrestore(&host->lock, flags);
}
static void sdh_disable_stat_irq(struct sdh_host *host, unsigned int mask)
{
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
host->imask &= ~mask;
bfin_write_SDH_MASK0(host->imask);
SSYNC();
spin_unlock_irqrestore(&host->lock, flags);
}
static void sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
{
unsigned int length;
unsigned int data_ctl;
unsigned int dma_cfg;
#if defined(CONFIG_BF54x)
int i;
#endif
pr_debug("%s enter flags:0x%x\n", __FUNCTION__, data->flags);
host->data = data;
data_ctl = 0;
dma_cfg = 0;
length = data->blksz * data->blocks;
bfin_write_SDH_DATA_LGTH(length);
if (data->flags & MMC_DATA_STREAM)
data_ctl |= DTX_MODE;
if (data->flags & MMC_DATA_READ)
data_ctl |= DTX_DIR;
BUG_ON(data->blksz & (data->blksz -1));
data_ctl |= ((ffs(data->blksz) -1) << 4);
bfin_write_SDH_DATA_CTL(data_ctl);
/* FIXME later */
bfin_write_SDH_DATA_TIMER(0xFFFFFFFF);
SSYNC();
if (data->flags & MMC_DATA_READ) {
host->dma_dir = DMA_FROM_DEVICE;
dma_cfg |= WNR;
} else
host->dma_dir = DMA_TO_DEVICE;
sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END));
host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir);
#if defined(CONFIG_BF54x)
dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN;
for (i = 0; i < host->dma_len; i++) {
host->sg_cpu[i].start_addr = sg_dma_address(&data->sg[i]);
host->sg_cpu[i].cfg = dma_cfg;
host->sg_cpu[i].x_count = sg_dma_len(&data->sg[i]) / 4;
host->sg_cpu[i].x_modify = 4;
pr_debug("%d: start_addr:0x%lx, cfg:0x%x, x_count:0x%x, x_modify:0x%x\n",
i, host->sg_cpu[i].start_addr, host->sg_cpu[i].cfg,
host->sg_cpu[i].x_count, host->sg_cpu[i].x_modify);
}
flush_dcache_range((unsigned int)host->sg_cpu, \
(unsigned int)host->sg_cpu + \
host->dma_len * sizeof(struct dma_desc_array));
/* Set the last descriptor to stop mode */
host->sg_cpu[host->dma_len - 1].cfg &= ~(DMAFLOW | NDSIZE);
host->sg_cpu[host->dma_len - 1].cfg |= DI_EN;
set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma);
set_dma_x_count(host->dma_ch, 0);
set_dma_x_modify(host->dma_ch, 0);
set_dma_config(host->dma_ch, dma_cfg);
#elif defined(CONFIG_BF51x)
dma_cfg |= WDSIZE_32 | DMAEN;
set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0]));
set_dma_x_count(host->dma_ch, length / 4);
set_dma_x_modify(host->dma_ch, 4);
set_dma_config(host->dma_ch, dma_cfg);
#endif
bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
SSYNC();
pr_debug("%s exit\n", __FUNCTION__);
}
static void sdh_start_cmd(struct sdh_host *host, struct mmc_command *cmd)
{
unsigned int sdh_cmd;
unsigned int stat_mask;
pr_debug("%s enter cmd:0x%p\n", __FUNCTION__, cmd);
WARN_ON(host->cmd != NULL);
host->cmd = cmd;
sdh_cmd = 0;
stat_mask = 0;
sdh_cmd |= cmd->opcode;
if (cmd->flags & MMC_RSP_PRESENT) {
sdh_cmd |= CMD_RSP;
stat_mask |= CMD_RESP_END;
} else
stat_mask |= CMD_SENT;
if (cmd->flags & MMC_RSP_136)
sdh_cmd |= CMD_L_RSP;
stat_mask |= CMD_CRC_FAIL | CMD_TIME_OUT;
sdh_enable_stat_irq(host, stat_mask);
bfin_write_SDH_ARGUMENT(cmd->arg);
bfin_write_SDH_COMMAND(sdh_cmd | CMD_E);
bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() | CLK_E);
SSYNC();
}
static void sdh_finish_request(struct sdh_host *host, struct mmc_request *mrq)
{
pr_debug("%s enter\n", __FUNCTION__);
host->mrq = NULL;
host->cmd = NULL;
host->data = NULL;
mmc_request_done(host->mmc, mrq);
}
static int sdh_cmd_done(struct sdh_host *host, unsigned int stat)
{
struct mmc_command *cmd = host->cmd;
pr_debug("%s enter cmd:%p\n", __FUNCTION__, cmd);
if (!cmd)
return 0;
host->cmd = NULL;
if (cmd->flags & MMC_RSP_PRESENT) {
cmd->resp[0] = bfin_read_SDH_RESPONSE0();
if (cmd->flags & MMC_RSP_136) {
cmd->resp[1] = bfin_read_SDH_RESPONSE1();
cmd->resp[2] = bfin_read_SDH_RESPONSE2();
cmd->resp[3] = bfin_read_SDH_RESPONSE3();
}
}
if (stat & CMD_TIME_OUT)
cmd->error = -ETIMEDOUT;
else if (stat & CMD_CRC_FAIL && cmd->flags & MMC_RSP_CRC)
cmd->error = -EILSEQ;
sdh_disable_stat_irq(host, (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL));
if (host->data && !cmd->error) {
if (host->data->flags & MMC_DATA_WRITE)
sdh_setup_data(host, host->data);
sdh_enable_stat_irq(host, DAT_END | RX_OVERRUN | TX_UNDERRUN | DAT_TIME_OUT);
} else
sdh_finish_request(host, host->mrq);
return 1;
}
static int sdh_data_done(struct sdh_host *host, unsigned int stat)
{
struct mmc_data *data = host->data;
pr_debug("%s enter stat:0x%x\n", __FUNCTION__, stat);
if (!data)
return 0;
disable_dma(host->dma_ch);
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
host->dma_dir);
if (stat & DAT_TIME_OUT)
data->error = -ETIMEDOUT;
else if (stat & DAT_CRC_FAIL)
data->error = -EILSEQ;
else if (stat & (RX_OVERRUN | TX_UNDERRUN))
data->error = -EIO;
if (!data->error)
data->bytes_xfered = data->blocks * data->blksz;
else
data->bytes_xfered = data->blocks * data->blksz - \
bfin_read_SDH_DATA_CNT();
sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN);
bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \
DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN);
bfin_write_SDH_DATA_CTL(0);
SSYNC();
host->data = NULL;
if (host->mrq->stop) {
sdh_stop_clock(host);
sdh_start_cmd(host, host->mrq->stop);
} else
sdh_finish_request(host, host->mrq);
return 1;
}
static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdh_host *host = mmc_priv(mmc);
pr_debug("%s enter, mrp:%p, cmd:%p\n", __FUNCTION__, mrq, mrq->cmd);
WARN_ON(host->mrq != NULL);
host->mrq = mrq;
host->data = mrq->data;
if (mrq->data && mrq->data->flags & MMC_DATA_READ)
sdh_setup_data(host, mrq->data);
sdh_start_cmd(host, mrq->cmd);
}
static int sdh_get_ro(struct mmc_host *mmc)
{
/* Host doesn't support read only detection so assume writeable */
return 0;
}
static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdh_host *host;
unsigned long flags;
u16 clk_ctl = 0;
u16 pwr_ctl = 0;
u16 cfg;
host = mmc_priv(mmc);
spin_lock_irqsave(&host->lock, flags);
if (ios->clock) {
unsigned long clk_div;
unsigned long sys_clk;
sys_clk = get_sclk();
if (sys_clk % (2*ios->clock) == 0)
clk_div = sys_clk / (2*ios->clock) - 1;
else
clk_div = sys_clk / (2*ios->clock);
if (clk_div > 0xff)
clk_div = 0xFF;
clk_ctl |= clk_div & 0xFF;
clk_ctl |= CLK_E;
host->clk_div = clk_div;
} else
sdh_stop_clock(host);
if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
#ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
pwr_ctl |= ROD_CTL;
#else
pwr_ctl |= SD_CMD_OD | ROD_CTL;
#endif
if (ios->bus_width == MMC_BUS_WIDTH_4) {
cfg = bfin_read_SDH_CFG();
cfg &= ~0x80;
cfg |= 0x40;
/* Enable 4 bit SDIO */
cfg |= 0x0c;
bfin_write_SDH_CFG(cfg);
clk_ctl |= WIDE_BUS;
} else {
cfg = bfin_read_SDH_CFG();
cfg |= 0x08;
bfin_write_SDH_CFG(cfg);
}
bfin_write_SDH_CLK_CTL(clk_ctl);
host->power_mode = ios->power_mode;
if (ios->power_mode == MMC_POWER_ON)
pwr_ctl |= PWR_ON;
bfin_write_SDH_PWR_CTL(pwr_ctl);
SSYNC();
spin_unlock_irqrestore(&host->lock, flags);
pr_debug("SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n",
host->clk_div, host->clk_div?get_sclk()/(2 * (host->clk_div + 1)):0,
ios->clock);
}
#ifdef CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ
static void sdh_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
if (enable)
pr_debug("Enable sdio irq\n");
else
pr_debug("Disable sdio irq\n");
}
#endif
static const struct mmc_host_ops sdh_ops = {
.request = sdh_request,
.get_ro = sdh_get_ro,
.set_ios = sdh_set_ios,
#ifdef CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ
.enable_sdio_irq = sdh_enable_sdio_irq,
#endif
};
static irqreturn_t sdh_dma_irq(int irq, void *devid)
{
struct sdh_host *host = devid;
pr_debug("%s enter, irq_stat:0x%04x\n", __FUNCTION__,\
get_dma_curr_irqstat(host->dma_ch));
clear_dma_irqstat(host->dma_ch);
SSYNC();
return IRQ_HANDLED;
}
static irqreturn_t sdh_stat_irq(int irq, void *devid)
{
struct sdh_host *host = devid;
unsigned int status;
int handled = 0;
pr_debug("%s enter\n", __FUNCTION__);
status = bfin_read_SDH_E_STATUS();
if (status & SD_CARD_DET) {
mmc_detect_change(host->mmc, 0);
bfin_write_SDH_E_STATUS(SD_CARD_DET);
}
#ifdef CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ
if (status & SDIO_INT_DET) {
mmc_signal_sdio_irq(host->mmc);
bfin_write_SDH_E_STATUS(SDIO_INT_DET);
handled = 1;
}
#endif
status = bfin_read_SDH_STATUS();
if (status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)) {
handled |= sdh_cmd_done(host, status);
bfin_write_SDH_STATUS_CLR( CMD_SENT_STAT | CMD_RESP_END_STAT | \
CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT);
SSYNC();
}
status = bfin_read_SDH_STATUS();
if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN))
handled |= sdh_data_done(host, status);
pr_debug("%s exit\n\n", __FUNCTION__);
return IRQ_RETVAL(handled);
}
static int proc_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct sdh_host *host = data;
unsigned long cmd = simple_strtoul(buffer, NULL, 16);
switch (cmd) {
case 0:
mmc_detect_change(host->mmc, 0);
break;
default:
printk(KERN_ERR "bfin_sdh: cmd %lu not support\n", cmd);
break;
}
return count;
}
static int __devinit sdh_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct sdh_host *host = NULL;
struct proc_dir_entry *sd_entry;
struct bfin_sd_host *drv_data = get_sdh_data(pdev);
int ret;
if (!drv_data) {
dev_err(&pdev->dev, "missing platform driver data\n");
ret = -EINVAL;
goto out;
}
mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev);
if (!mmc) {
ret = -ENOMEM;
goto out;
}
mmc->ops = &sdh_ops;
mmc->max_phys_segs = NR_SG;
mmc->max_seg_size = 1 << 16;
mmc->max_blk_size = 2 << 11;
mmc->max_blk_count = 2 << 16;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->f_min = get_sclk() >> 9;
mmc->f_max = get_sclk();
#ifndef CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ
mmc->caps = MMC_CAP_4_BIT_DATA;
#endif
host = mmc_priv(mmc);
host->mmc = mmc;
spin_lock_init(&host->lock);
host->irq = drv_data->irq_int0;
host->dma_ch = drv_data->dma_chan;
ret = request_dma(host->dma_ch, DRIVER_NAME "DMA");
if (ret) {
dev_err(&pdev->dev, "unable to request DMA channel\n");
goto out1;
}
ret = set_dma_callback(host->dma_ch, sdh_dma_irq, host);
if (ret) {
dev_err(&pdev->dev, "unable to request DMA irq\n");
goto out2;
}
host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
if (host->sg_cpu == NULL) {
ret = -ENOMEM;
goto out2;
}
platform_set_drvdata(pdev, mmc);
mmc_add_host(mmc);
ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host);
if (ret) {
dev_err(&pdev->dev, "unable to request status irq\n");
goto out3;
}
ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "unable to request peripheral pins\n");
goto out4;
}
#if defined(CONFIG_BF54x)
/* Secure Digital Host shares DMA with Nand controller */
bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
#endif
bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
SSYNC();
/* Disable card inserting detection pin. It's not that useful, since
* we can't detect removal, and it will affect card detection on BF51x.
*/
bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60);
SSYNC();
sd_entry = create_proc_entry("driver/sdh", 0600, NULL);
sd_entry->read_proc = NULL;
sd_entry->write_proc = proc_write;
sd_entry->data = host;
return 0;
out4:
free_irq(host->irq, host);
out3:
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
out2:
free_dma(host->dma_ch);
out1:
mmc_free_host(mmc);
out:
return ret;
}
static int __devexit sdh_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
if (mmc) {
struct sdh_host *host = mmc_priv(mmc);
mmc_remove_host(mmc);
sdh_stop_clock(host);
free_irq(host->irq, host);
free_dma(host->dma_ch);
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
mmc_free_host(mmc);
}
remove_proc_entry("driver/sdh", NULL);
return 0;
}
#ifdef CONFIG_PM
static int sdh_suspend(struct platform_device *dev, pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct bfin_sd_host *drv_data = get_sdh_data(dev);
int ret = 0;
if (mmc)
ret = mmc_suspend_host(mmc, state);
bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON);
peripheral_free_list(drv_data->pin_req);
return ret;
}
static int sdh_resume(struct platform_device *dev)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct bfin_sd_host *drv_data = get_sdh_data(dev);
int ret = 0;
ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME);
if (ret) {
dev_err(&dev->dev, "unable to request peripheral pins\n");
return ret;
}
bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON);
#if defined(CONFIG_BF54x)
/* Secure Digital Host shares DMA with Nand controller */
bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
#endif
bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
SSYNC();
/* Disable card inserting detection pin. It's not that useful, since
* we can't detect removal, and it will affect card detection on BF51x.
*/
bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60);
SSYNC();
if (mmc)
ret = mmc_resume_host(mmc);
return ret;
}
#else
#define sdh_suspend NULL
#define sdh_resume NULL
#endif
static struct platform_driver sdh_driver = {
.probe = sdh_probe,
.remove = sdh_remove,
.suspend = sdh_suspend,
.resume = sdh_resume,
.driver = {
.name = DRIVER_NAME,
},
};
static int __init sdh_init(void)
{
return platform_driver_register(&sdh_driver);
}
static void __exit sdh_exit(void)
{
platform_driver_unregister(&sdh_driver);
}
TranslateQuoteReplyEditDelete
2011-03-07 06:25:00 Re: error when mount the SD card!
Mike Frysinger (UNITED STATES)
Message: 98672
please dont post entire files like that. it's pretty difficult for us to see anything useful at all in the output you've posted here.
instead, post a simple unified diff.
QuoteReplyEditDelete