linux2.6.20 sd/mmcカード駆動学習日記2(s 3 c 2440ベース)


私たちはs 3 cmciに来ました.cファイルs 3 cmci_init----->platform_driver_register(&s3cmci_driver_2440)------------>s3cmci_probe_2440----->s3cmci_probeはs 3 cmci_probeでは主にstruct mmc_の割り当てと初期化host     *mmc;     struct s3cmci_host     *host; この2つの構造体.DMAチャネルが割り当てられ、登録irqが中断される.以下、個別関数の役割について説明する:1:clk_getシステムの初期化時に周辺バスのデバイスがクロックに与えられるのではなく、主に省電力のためです.2.6.20では、ファイルarch/arm/mach-s 3 c 2410/s 3 c 2410-clockでnand,sdi,adc,i 2 c,iisこれらはクロックを与えないlcd,gpio,usb,uartこれらはクロックを与えるclk_getはarch/arm/mach-s 3 c 2410/clock.cで定義2:mmc_alloc_host     mmc_alloc_hostはsizeof(struct mmc_host)+extraという大きな空間を割り当て、以下の初期化host=mmc_alloc_host_sysfs(extra, dev);     host->parent = dev;     host->class_dev.parent = dev;     host->class_dev.class = &mmc_host_class;     device_initialize(&host->class_dev);     spin_lock_init(&host->lock);     init_waitqueue_head(&host->wq);     INIT_LIST_HEAD(&host->cards);     INIT_DELAYED_WORK(&host->detect, mmc_rescan);             * By default, hosts do not support SGIO or large requests.     * They have to set these according to their abilities.             host->max_hw_segs = 1;     host->max_phys_segs = 1;     host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);     host->max_seg_size = PAGE_CACHE_SIZE; 3:     mmc_add_host呼び出しmmc_add_ホストの最終結果はdevice_add(&host->class->dev)です(したがって/sys/class/mmc/ディレクトリの下にmmc 0ファイルが表示されます).mmc_が呼び出されますpower_off(host);mmc_detect_change(host, 0);     mmc_power_off関数は比較的簡単で、その名の通りSD/MMCカードを停止させ、対応するIOポートやクロックなどを構成します.mmcを見てみましょうdetect_change関数でしょう.void mmc_detect_change(struct mmc_host *host, unsigned long delay) {     mmc_schedule_delayed_work(&host->detect, delay); } int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) {     return queue_delayed_work(workqueue, work, delay); } queue_delayed_workはhost->detectをworkqueueワークペア列にコミットします.対応する定義:INIT_DELAYED_WORK(&host->detect, mmc_rescan); workqueue = create_singlethread_workqueue("kmmcd"); だからdelayed_ワーク実行時、mmc_rescanが呼び出されます
static void mmc_rescan( struct work_struct * work)
{
    struct mmc_host * host =
        container_of( work, struct mmc_host, detect. work) ; // s3cmci_probe mmc_host

    struct list_head * l, * n;
    unsigned char power_mode;

    mmc_claim_host( host) ;
    /*
     mmc_claim_host(host); , mmc , mmc , host->claimed = 1; 0, 1, for(;;) schedule , mmc , mmc_release_host() , &host->wq mmc
    */

    /*
     * Check for removed cards and newly inserted ones. We check for
     * removed cards first so we can intelligently re-select the VDD.
    */

    power_mode = host- > ios . power_mode;
    if ( power_mode = = MMC_POWER_ON)
        mmc_check_cards( host) ;
    mmc_setup( host) ;
    /*
     * Some broken cards process CMD1 even in stand-by state. There is
     * no reply, but an ILLEGAL_COMMAND error is cached and returned
     * after next command. We poll for card status here to clear any
     * possibly pending error.
    */

    if ( power_mode = = MMC_POWER_ON)
        mmc_check_cards( host) ;

    if ( ! list_empty( & host- > cards) ) {
        /*
         * (Re-)calculate the fastest clock rate which the
         * attached cards and the host support.
        */

        host- > ios . clock = mmc_calculate_clock( host) ;
        mmc_set_ios( host) ;
    }

    mmc_release_host( host) ;

    list_for_each_safe( l, n, & host- > cards) {
        struct mmc_card * card = mmc_list_to_card( l) ;

        /*
         * If this is a new and good card, register it.
        */

        if ( ! mmc_card_present( card) & & ! mmc_card_dead( card) ) {
            if ( mmc_register_card( card) )
                mmc_card_set_dead( card) ;
            else
                mmc_card_set_present( card) ;
        }

        /*s
         * If this card is dead, destroy it.
        */

        if ( mmc_card_dead( card) ) {
            list_del( & card- > node) ;
            mmc_remove_card( card) ;
        }
    }

    /*
     * If we discover that there are no cards on the
     * bus, turn off the clock and power down.
    */

    if ( list_empty( & host- > cards) )
        mmc_power_off( host) ;
}

最初はパワーmode = MMC_POWER_OFFするので、最初のmmc_check_cards(host)は実行されません.ただしmmc_setup関数にpower_が設定されていますmode = MMC_POWER_ON.だから2番目のmmc_check_cards(host)は実行されます.mmc_setupではmmc_が呼び出されますdiscover_cards.カードが見つかったらadd new card to list.今カードが見つからないので、host->card=NULLなのでmmc_check_cardsとmmc_rescanのlist_for_each_safeループの内容も実行されません.static void mmc_check_cards( struct mmc_host * host)
{
    struct list_head * l, * n;

    mmc_deselect_cards( host) ; // Ensure that no card is selected.


    list_for_each_safe( l, n, & host- > cards) {
        struct mmc_card * card = mmc_list_to_card( l) ;
        struct mmc_command cmd;
        int err;

        cmd. opcode = MMC_SEND_STATUS;
        cmd. arg = card- > rca < < 16;
        cmd. flags = MMC_RSP_R1 | MMC_CMD_AC;

        err = mmc_wait_for_cmd( host, & cmd, CMD_RETRIES) ;
        if ( err = = MMC_ERR_NONE)
            continue ;

        mmc_card_set_dead( card) ;
}
}

s 3 cmciの実行が完了しました.probe後、端末には、s 3 c 2410-sdi s 3 c 2410-sdi:powered downという情報がある.s3c2410-sdi s3c2410-sdi: initialisation done. s3c2410-sdi s3c2410-sdi: running at 0kHz (requested: 0kHz). s3c2410-sdi s3c2410-sdi: running at 198kHz (requested: 197kHz). s3c2410-sdi s3c2410-sdi: running at 198kHz (requested: 197kHz). s3c2410-sdi s3c2410-sdi: running at 198kHz (requested: 197kHz). s3c2410-sdi s3c2410-sdi: CMD[TIMEOUT] #2 op:APP_CMD(55) arg:0x00000000 flags:0xe s3c2410-sdi s3c2410-sdi: CMD[TIMEOUT] #3 op:APP_CMD(55) arg:0x00000000 flags:0xe s3c2410-sdi s3c2410-sdi: CMD[TIMEOUT] #4 op:APP_CMD(55) arg:0x00000000 flags:0xe s3c2410-sdi s3c2410-sdi: CMD[TIMEOUT] #5 op:APP_CMD(55) arg:0x00000000 flags:0xe s3c2410-sdi s3c2410-sdi: CMD[TIMEOUT] #6 op:ALL_SEND_OCR(1) arg:0x00000000 flage s3c2410-sdi s3c2410-sdi: powered down. ------------------------------------未完待機-----------------------------------------------------
 
http://blog.chinaunix.net/space.php?uid=14782631&do=blog&id=111889