2011-02-16 00:53:07     error when mount the SD card!

Document created by Aaronwu Employee on Aug 26, 2013
Version 1Show Document
  • View in full screen mode

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

Attachments

    Outcomes