[MMC Subsystem] MMC core (sixth chapter)--MMC Core Master Module

Source: Internet
Author: User
Tags bind extend goto

MMC subsystem series (in continuous update):
[MMC subsystem] concepts and frameworks
[MMC Subsystem] MMC core (chapter I)--Overview
[MMC Subsystem] MMC core (chapter II)--Description of data structure and macro definitions
[MMC Subsystem] MMC core (chapter III)--bus module description
[MMC Subsystem] MMC core (fourth chapter)--host module description
[MMC Subsystem] MMC core (fifth chapter)--card related modules (MMC type card)
[MMC Subsystem] MMC core (sixth chapter)--MMC Core Master Module

It is recommended that you refer to the [MMC subsystem] concepts and frameworks and [MMC Subsystem] MMC core (chapter I)-Overview for an understanding of the whole.

========================================================================================================= One, Description 1, MMC core Overview

The MMC Core Master module is the implementation core of the MMC core. This chapter is also the focus of the content.
corresponding code location DRIVERS/MMC/CORE/CORE.C.
It is mainly responsible for the following functions: MMC core initialization, including the registration of MMC bus, MM host class, and so on MMC host management and maintenance, including for other modules to provide Mmc_host operation interface, as follows
Host's start-up and stop host's occupy and release host power state save and restore host bus operation set bindings and bind host card status detection provides Mmc_card operation interface for other modules, as follows
Card's wake-up and Hibernate card Erase Card property gets the interface for other modules to provide the bus IO setting for other modules to provide MMC request interface card detection Interface Bkops operation interface regulator operation interface Clock Operation interface MMC core Power management Operation Interface 2, Operation set Description

There are two operation set members in Mmc_host, which need to be understood to avoid misunderstandings in the code: Mmc_host->struct mmc_host_ops *ops, this is the set of operations for host, which is determined by the host controller driver. For SDHCI class host, it is Sdhci_ops (set in SDHCI.C). Mmc_host->struct Mmc_bus_ops *bus_ops, this is the MMC bus operation set (also understood as the host of the MMC bus Handler,host method), determined by the card type on the bus. For MMC card type, it is Mmc_ops_unsafe or mmc_ops (set in Mmc_attach_bus_ops).Second, API overview 1. MMC Core initialization relatedMmc_init & Mmc_exit (for use within modules)2, MMC host management and maintenance relatedMmc_claim_host & Mmc_try_claim_host & Mmc_release_host (used within modules) Mmc_power_up & Mmc_power_off Mmc_start_host & Amp Mmc_stop_host Mmc_power_save_host & mmc_power_restore_host mmc_resume_host & Mmc_suspend_host mmc_pm_notify3, MMC card operation related (including card State acquisition)Mmc_hw_reset & Mmc_hw_reset_check & mmc_card_awake & Mmc_card_sleep mmc_card_is_prog_state mmc_can_erase Mmc_can_trim Mmc_can_discard mmc_can_sanitize Mmc_can_secure_erase_trim mmc_erase_group_aligned4, Bus IO setting relatedMmc_set_ios mmc_set_chip_select mmc_set_clock mmc_set_bus_mode mmc_set_bus_width mmc_select_voltage Mmc_set_signal_ Voltage (Special) mmc_set_timing

Mmc_set_driver_type

Mmc_get_max_frequency & Mmc_get_min_frequency 5, host MMC bus related mmc_resume_bus Mmc_attach_bus & MMC_ Detach_bus 6, MMC request related mmc_request_done mmc_wait_for_req mmc_wait_for_cmd mmc_set_data_timeout mmc_align_data _size 7, card detection related mmc_detect_change mmc_rescan mmc_detect_card_removed 8, bkops operation related mmc_blk_init_ Bkops_statistics mmc_start_delayed_bkops mmc_start_bkops & mmc_stop_bkops mmc_start_idle_time_bkops Mmc_read_ Bkops_status 9, regulator operation related mmc_regulator_get_ocrmask MMC_REGULATOR_SET_OCR mmc_regulator_get_supply 10, Card erase operation related mmc_init_erase mmc_erase 11, clock operation interface mmc_init_clk_scaling & mmc_exit_clk_scaling MMC _CAN_SCALE_CLK mmc_disable_clk_scaling 12, MMC core power management operations Mmc_rpm_hold & Mmc_rpm_release Two, Interface code description-- MMC core initialization related 1, mmc_init implementation

Responsible for initializing the entire MMC core.

Primary work: Assigning a workqueue, a work that is dedicated to the execution of MMC core, registering MMC Bus registration MMC host class

The code is as follows:

static int __init mmc_init (void)
{
    int ret;

/* Assign a workqueue to work specifically with the execution of the MMC core *
    /Workqueue = Alloc_ordered_workqueue ("Kmmcd", 0);

/* Register MMC Bus *
    /ret = Mmc_register_bus ();    Call Mmc_register_bus to register MMC bus, refer to "MMC Core--bus module description"
        //Generate/SYS/BUS/MMC Directory/

* Register MMC Host class */
    ret = MMC _register_host_class ();    Call Mmc_register_host_class to register the MMC host class, specifically refer to the MMC core--host module description
        //Generate/sys/class/mmc_host directory/

* Register SDIO Bus *
    /ret = Sdio_register_bus ();

    return 0;

}

Subsys_initcall (Mmc_init);
third, interface code description--MMC host management and maintenance-related 1, Mmc_claim_host & mmc_try_claim_host & Mmc_release_host

The host cannot be enabled again after it is enabled and can only be occupied by a process alone.
The host can be simply understood as a resource, and can only be obtained by a single process, but may be used repeatedly in the occupied process.
Before the host is operational (including initiating an MMC request), it must be obtained and freed using Mmc_claim_host and Mmc_release_host.

The variable description mmc_host->claimed is used to indicate whether the host is occupied Mmc_host->claimer used to represent the occupier (process) of the host mmc_host->claim_ CNT is used to indicate the occupancy count of the host, which releases the host when it is 0

The code is as follows

static inline void Mmc_claim_host (struct mmc_host *host) {__mmc_claim_host (host, NULL);  Call __mmc_claim_host to get host} int __mmc_claim_host (struct mmc_host *host, atomic_t *abort) {/////Only consider the case of abort null, in MMC    
    The mmc_claim_host in the core is also set to null declare_waitqueue (wait, current);
    unsigned long flags;

    int stop;        Might_sleep ();    Note that this function may cause the process to hibernate add_wait_queue (&host->wq, &wait);
    Add the current process to the waiting queue Spin_lock_irqsave (&host->lock, flags);    while (1) {//The following attempts to get host, if host is being occupied, it will go into hibernation set_current_state (task_uninterruptible); Set the process status to task_uninterruptible status stop = Abort?
        Atomic_read (Abort): 0;
            if (Stop | |!host->claimed | | host->claimer = = current)//when the host's occupancy flag claimed is 0, or if the occupier is the present process, the description can be occupied, exit
        Break
        Spin_unlock_irqrestore (&host->lock, flags);    Schedule ();
    Otherwise, the dispatch enters the dormant spin_lock_irqsave (&host->lock, flags); } set_current_state (TASK_running);    Set the process to a running state if (!stop) {host->claimed = 1;    Set occupancy Mark claimed Host->claimer = current;    Set the occupier to the current process host->claim_cnt + = 1;
    Occupancy count plus 1} else wake_up (&HOST->WQ);
    Spin_unlock_irqrestore (&host->lock, flags);    Remove_wait_queue (&host->wq, &wait); Exits the current process from the wait queue if (host->ops->enable &&!stop && host->claim_cnt = = 1) host->ops  ->enable (host);
Call the Enable method in the host operation set to occupy the host, and the corresponding SDHCI class host is the sdhci_enable return stop;

    } void Mmc_release_host (struct mmc_host *host) {unsigned long flags;

    WARN_ON (!host->claimed); if (host->ops->disable && host->claim_cnt = 1)//Current claim_cnt is 1 (immediately to 0), call Release host Host->op    S->disable (host);
    Call the Disable method in the host operation set to release the host, corresponding to the SDHCI class host is Sdhci_disable Spin_lock_irqsave (&host->lock, flags); if (--host->claim_cnt) {/* Release for nested CLaim */Spin_unlock_irqrestore (&host->lock, flags);    If the count is not 0 after minus one, it indicates that the current process needs to continue to occupy the host, do nothing else} else {//The following need to release the host host->claimed = 0;    Set occupancy flag claimed to 0 host->claimer = NULL;
        Emptying the occupier (process) Spin_unlock_irqrestore (&host->lock, flags);    WAKE_UP (&HOST->WQ); Wake up the wait queue for host, let those processes that call Mmc_claim_host sleep wait for the host resource Wake Up}} int mmc_try_claim_host (struct mmc_host *host) {//And Mmc_claim
    The main difference between _host is that the process does not hibernate, and the gain fails directly returns int claimed_host = 0;

    unsigned long flags;
    Spin_lock_irqsave (&host->lock, flags);
        if (!host->claimed | | host->claimer = = current) {host->claimed = 1;
        Host->claimer = current;
        host->claim_cnt + = 1;
    Claimed_host = 1;
    } spin_unlock_irqrestore (&host->lock, flags); if (host->ops->enable && claimed_host && host->claim_cnt = = 1) host->ops->enable (ho
    ST);
return claimed_host; }

Mmc_host->struct mmc_host_ops->enable and Mmc_host->struct mmc_host_ops->disable are called to enable and disable host.
For the host of the SDHCI class, the corresponding is sdhci_enable and sdhci_disable. 2, Mmc_power_up & Mmc_power_off

Power-on and power-off operation of the MMC host.

Power state of MMC Mmc_power_off: power-down State mmc_power_up: State of the Power-on mmc_power_on: normal state of supply

Main work
The main work is to initialize the host bus settings, bus clock and operating voltage, signal voltage.

The code is as follows

void mmc_power_up (struct mmc_host *host) {int bit;

/* To determine if it is already in mmc_power_on, then do not follow up * * if (Host->ios.power_mode = = mmc_power_on) return;    /* First stage, set the corresponding IO setting to make host in Mmc_power_up state (bus operating frequency is not set) */Mmc_host_clk_hold (host);    First get the host clock/* If OCR is set, we use it */if (HOST->OCR) bit = FFS (HOST->OCR)-1;
    Select an OCR configuration setting to the operating voltage of host else bit = FLS (host->ocr_avail)-1;
    HOST->IOS.VDD = bit;
    if (MMC_HOST_IS_SPI (host)) Host->ios.chip_select = Mmc_cs_high;
        else {host->ios.chip_select = Mmc_cs_dontcare;    Host->ios.bus_mode = Mmc_busmode_opendrain;
    Set Bus mode} Host->ios.power_mode = Mmc_power_up;    Host->ios.bus_width = mmc_bus_width_1;    Set the bus width to 1 host->ios.timing = mmc_timing_legacy;    Serial port sequential Mmc_set_ios (host); Call Mmc_set_ios to set the IO setting of the bus, followed by/* * This delay should is sufficient to make the power supply * to R each The minimum voltage.

*/Mmc_delay (10);    /* Second stage, set the IO setting again with the initialization frequency of host, so that host is in mmc_power_on state */Host->ios.clock = host->f_init;
    Set the bus clock frequency host->ios.power_mode = mmc_power_on;   Mmc_set_ios (host); Call Mmc_set_ios to set the IO setting of the bus, followed by/* * This delay must is at least clock sizes, or 1 ms, or the * ti
     Me required to reach a stable voltage.

*/Mmc_delay (10);

    /* Set the voltage of the signal */* Set signal voltage to 3.3V */__mmc_set_signal_voltage (host, mmc_signal_voltage_330);    Mmc_host_clk_release (host); Release Host Clock}
3, Mmc_start_host & Mmc_stop_host

Mmc_start_host is used to start a host,mmc_stop_host to stop a host.
When the underlying host controller calls Mmc_add_host to register host, the Mmc_start_host is called in Mmc_add_host to start a host. Refer to the "MMC core--host module description" for details.
Corresponding, the Mmc_stop_host stop host is called in the Mmc_remove_host.

void Mmc_start_host (struct mmc_host *host)
{
    mmc_claim_host (host);    Because the power-on operation involves the use and setting of the host, the host

    host->f_init = max (freqs[0], host->f_min) needs to be occupied first;    The initialization frequency to be set by the minimum frequency
    host->rescan_disable = 0;    Set the rescan_disable flag to 0, indicating that the card has already been detected
    if (HOST->CAPS2 & Mmc_cap2_no_prescan_powerup)    // If the MMC property is set to Mmc_cap2_no_prescan_powerup, that is, the power up operation is not required before rescan, the shutdown
        Mmc_power_off (host) is performed;
    else
        mmc_power_up (host);    Otherwise, call mmc_power_up to power on the host. This is also the core function for starting host in MMC core.

    Mmc_release_host (host);    Complete power-on operation, release host

/* Here the host is ready to work, you can start the subsequent card operation *
    /mmc_detect_change (host, 0);    Call Mmc_detect_change to detect card changes, follow-up will continue to explain
}
Iv. Interface Code description--card detection related 1, Mmc_detect_change

In the above we know that in the function Mmc_start_host starting host, we finally call Mmc_detect_change to start the detection card (that is, to detect the state change of the MMC slot).
in fact, Mmc_detect_change is driver to find the MMC slot status changes, call Mmc_detect_change to confirm and handle.

void Mmc_detect_change (struct mmc_host *host, unsigned long delay)
{
#ifdef config_mmc_debug
    unsigned long Flags;
    Spin_lock_irqsave (&host->lock, flags);
    WARN_ON (host->removed);
    Spin_unlock_irqrestore (&host->lock, flags);
#endif
    host->detect_change = 1;    Identification

    mmc_schedule_delayed_work (&host->detect, delay) that detects a change in card status;    Interval delay jiffies After calling Host->detect's work
}

In the host module description, it is known that the host->detect work is set to the Mmc_rescan (card rescan) function by default in Mmc_alloc_host.
Init_delayed_work (&host->detect, Mmc_rescan).
Of course, host can also be set up on its own, but it is generally done using the Mmc_rescan provided by the MMC core as a detect job to search for the card. described below. 2, Mmc_rescan

Used to detect the card slot status of the host and to perform the corresponding operation on the state change.
When a card is inserted, re-scan the MMC card.

void Mmc_rescan (struct work_struct *work) {struct Mmc_host *host = container_of (work, struct mmc_host, detect
    . work);

BOOL Extend_wakelock = false;

/* If rescan_disable is set, the host also prohibits rescan */if (host->rescan_disable) return at this time; /* For hosts that are not removable by the device, you can only rescan once */* if there is a non-removable card registered, only scan once */if ((host->c
    APS & Mmc_cap_nonremovable) && host->rescan_entered) return;

    host->rescan_entered = 1;    Mmc_bus_get (host);    Get the bus mmc_rpm_hold (host, &host->class_dev) corresponding to host; Make host in the state of RPM resume/* below to determine whether the original card has been removed, remove the need to do the appropriate action */* * If there is a _removable_ card registered, CH Eck whether it is * still present */if (host->bus_ops && host->bus_ops->detect && !host->bus_dead &&!
        (Host->caps & Mmc_cap_nonremovable))    
        Host->bus_ops->detect (host); Host->bus_ops existence Words explainBefore there is the status of card insertion//need to call Host->bus_ops->detect detection card is removed, if it is in the host->bus_ops->detect to do the corresponding processing//for MM
    C type card, the corresponding is mmc_detect, specific reference "card related module" Host->detect_change = 0;
    /* If The card was removed the bus would be marked * as Dead-extend the wakelock so userspace * can respond * *    if (host->bus_dead) Extend_wakelock = 1;  Need to set up a wakelock lock so that user space can be made in a timely manner corresponding/* * let Mmc_bus_put () free the bus/bus_ops if we ' ve found that * the card
     is no longer present.    
       */Mmc_bus_put (host); Because a host has been acquired at the front of this function, it may cause host->bus_ops->detect to detect that the card is unplugged and not actually released to the host bus, so put the count of//Host bus first (bus
        _refs) is 0, the __mmc_release_bus will be called to empty the host bus Information Mmc_bus_get (host); Get Host bus/* If there still is a card present, stop here */if (host->bus_ops! = NULL) {//description at this time there is a card
        Insert, exit the subsequent operation Mmc_rpm_release (host, &host->class_dev);
        Mmc_bus_put (host); Goto OUt    

    } mmc_rpm_release (host, &host->class_dev);
     /* * Only we can add a new handler, so it's safe to * release of the lock here.

*/Mmc_bus_put (host); /* Check the current card slot status and do the appropriate operation according to the card slot status */if (HOST->OPS->GET_CD && host->ops->get_cd (host) = = 0) {//Call HOST->OPS->GET_CD to determine the card slot of the host current card insert state//corresponding to the SDHCI type of host, that is, SDHCI_GET_CD//is 0, indicating that there is no card insert, corresponding to the host
        After the power off operation to exit//is 1, indicating that there is currently a card insert, skip to the subsequent operation Mmc_claim_host (host);
        Mmc_power_off (host);
        Mmc_release_host (host);
    Goto out;
    } mmc_rpm_hold (host, &host->class_dev);
    Mmc_claim_host (host); if (!mmc_rescan_try_freq (host, host->f_min))//Call Mmc_rescan_try_freq to the minimum frequency supported as the operating frequency to try to search for the card, follow-up instructions Extend_w
    Akelock = true;
    Mmc_release_host (host);
 Mmc_rpm_release (host, &host->class_dev); Out:/* Only extend the Wakelock, if suspend have not started yet * * if (extend_wakelocK &&!host->rescan_disable) wake_lock_timeout (&host->detect_wake_lock, HZ/2); Occupy Wakelock so that the system does not hibernate within HZ/2 time if (Host->caps & Mmc_cap_needs_poll) mmc_schedule_delayed_work (&hos    
               T->detect, HZ); When host sets the Mmc_cap_needs_poll property, it needs to poll the card slot status of the host at every Hz time,//dispatched host->detect work, corresponding to Mmc_rescan}

The HOST->OPS->GET_CD is called to determine the current card insertion state of the host's slot, and the host that corresponds to the SDHCI type is SDHCI_GET_CD.
The host->bus_ops->detect will be called to detect if the card is removed, and if so, do the corresponding processing in the Host->bus_ops->detect. For MMC type card, this is mmc_detect. 3, Mmc_rescan_try_freq

Search the card on the host bus at a certain frequency.

static int mmc_rescan_try_freq (struct mmc_host *host, unsigned freq) {host->f_init = Freq

    ;    MMC_POWER_UP (host);    Do the power-on Operation Mmc_hw_reset_for_init (host) for host;

    Hardware reset and initialization of the Mmc_go_idle (host);    Mmc_send_if_cond (host, host->ocr_avail); Get the available frequency of the card, store it in host->ocr_avail/* Order ' s important:probe SDIO, then SD, then MMC */* for binding card to host bus (also Is the binding of the card and host).
        */if (!mmc_attach_sdio (host))//First assume that the card is Sdio type card, attempt to bind to the host bus, failure is not sdio type card, continue the subsequent operation, otherwise return
    return 0;
    if (!MMC_ATTACH_SD (host))//Assume that the card is an SD type card, try to bind to the host bus, the failure is not the SD type card, continue the subsequent operation, otherwise return 0; if (!MMC_ATTACH_MMC (host))//Assume that the card is an MMC type card, try to bind to the host bus, the failure is not MMC type card, continue the operation behind, otherwise return//MMC_ATTAC
        H_MMC obtains the MMC type card information through Mmc_host, initializes the Mmc_card, and makes a partial drive, and finally registers it on the Mmc_bus.

    Specific reference to "card related module description" return 0;
    Mmc_power_off (host);
Return-eio; }
Five, interface code description--Bus IO setting correlation 0, Mmc_ios description

The struct Mmc_ios is the structure of the specification defined by the MMC core and is used to maintain some IO setting associated with the MMC bus. As follows:

struct mmc_ios {unsigned int clock;       /* clock rate *//current operating frequency unsigned int old_rate;         /* Saved clock rate *///Last operating frequency unsigned long clk_ts; /* Time stamp of last updated clock *//timestamp of previous update operating frequency unsigned short vdd;/* VDD stores the bit number of the SEL Ected voltage range from below.       *///supported voltmeter unsigned char bus_mode;        /* Command Output Mode *///bus output modes, including open-drain mode and pull-up mode unsigned char chip_select;     /* SPI Chip SELECT *///SPI Slice select unsigned char power_mode;      /* Power supply Mode *////power state pattern unsigned char bus_width;         /* Data Bus width *//bus width unsigned char timing;     /* Timing Specification used *//timing type unsigned char signal_voltage;       /* Signalling voltage (1.8V or 3.3V) *//Signal operating voltage unsigned char drv_type; /* Driver Type (A, B, C, D) *//drive type}; 

In the process of setting up the bus IO setting, you are setting up these members in the Mmc_host->mmc_ios.
It is then unified by calling Mmc_set_ios. Follow-up will continue to explain. 1, Mmc_set_ios

Set the IO settings (IO setting) of the MMC bus uniformly.

void Mmc_set_ios (struct mmc_host *host)
{
    struct Mmc_ios *ios = &host->ios;

    if (Ios->clock > 0)
        mmc_set_ungated (host);    Turn off clock's gated
    Host->ops->set_ios (host, iOS);    Call Host->ops->set_ios to set the IO setting of the MMC bus, the core function
        //For the SDHCI type of host, corresponds to Sdhci_set_ios
}

The Host->ops->set_ios is called to set the IO setting of the MMC bus, the core function. For the SDHCI type of host, the corresponding is Sdhci_set_ios 2, Mmc_set_bus_mode & Mmc_set_bus_width mmc_set_bus_mode for setting the bus mode, There are the following patterns
Mmc_busmode_opendrain (open-drain mode) Mmc_busmode_pushpull (pull-up mode) Mmc_set_bus_width is used to set the bus width in the following mode
mmc_bus_width_1 Mmc_bus_width_4 Mmc_bus_width_8

The code is as follows:

void Mmc_set_bus_mode (struct mmc_host *host, unsigned int mode)
{
    mmc_host_clk_hold (host);
    Host->ios.bus_mode = mode;
    Mmc_set_ios (host);
    Mmc_host_clk_release (host);
}

void Mmc_set_bus_width (struct mmc_host *host, unsigned int width)
{
    mmc_host_clk_hold (host);
    Host->ios.bus_width = width;
    Mmc_set_ios (host);
    Mmc_host_clk_release (host);
}

other functions that set IO setting are similar, not much. Vi. Interface Code Description--host MMC Bus-related 1, Mmc_attach_bus & Mmc_detach_bus

The main function Mmc_attach_bus is used to assign an MMC bus operation set to host. The Mmc_detach_bus is used to release the set of MMC bus operations associated with host.

Some variable mmc_host->bus_ops, representing the host's MMC bus action set Mmc_host->bus_refs, represents the user count Mmc_host->bus_dead of the host's MMC bus, Indicates whether the MMC bus for host is activated, and if Bus_ops is set, it will be activated.

The code is as follows

void mmc_attach_bus (struct mmc_host *host, const struct Mmc_bus_ops *ops) {unsigned long fla

    Gs

    Spin_lock_irqsave (&host->lock, flags);    BUG_ON (Host->bus_ops);    MMC bus operation set bug_on (host->bus_refs) is not allowed to repeat settings for host;    When the user count of the MMC bus is still present, the set of MMC bus operations set for host Host->bus_ops = OPS is not allowed; Set the MMC bus action set for host Host->bus_refs = 1 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.