1e41f4b71Sopenharmony_ci# MMC
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Function
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciA multimedia card (MMC) is a small-sized and large-capacity flash memory card used for solid-state non-volatile storage.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciNowadays, MMC refers to a standard driver interface to solid-state storage cards. Memory devices that comply with this standard can be called MMCs. An MMC consists of the MMC controller, MMC bus, and memory card, which can be an MMC, Secure Digital (SD) card, Secure Digital Input Output (SDIO) card, or TransFlash (TF) card.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ciThe MMC, SD, and SDIO buses have similar bus specifications, which have evolved from the MMC bus specifications. The MMC features multimedia storage; the SD focuses on security and data protection; the SDIO, evolving from the SD, provides the interface regardless of the specific form of the peer end (Wi-Fi, Bluetooth, or GPS device).
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci### Basic Concepts
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci- SD card
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci  Introduced as an improvement over the MMC, the SD cards can protect their contents from erasure or modification, prevent unauthorized access, and protect copyrighted content using digital rights management. The size of a standard SD card is 24 mm x 32 mm x 2.1 mm, which is a little thicker than an MMC card. The SD cards are forward compatible with MMC cards, that is, all devices that support SD cards also support MMC cards.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci- SDIO
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci  SDIO is an interface designed as an extension for the SD card standard. It introduces the low-speed transfer standard, which supports low-speed I/O with the minimum hardware overhead. The SDIO interface is compatible with the SD cards.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci### Working Principles
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ciIn the Hardware Driver Foundation (HDF), the MMC uses the independent service mode (see Figure 1) for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage.
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ciIn the independent service mode, the core layer does not publish a service for the upper layer. Therefore, a service must be published for each controller. To achieve this purpose:
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services.
30e41f4b71Sopenharmony_ci- The **policy** field of **deviceNode** in the **device_info.hcs** file must be **1** or **2**, but not **0**.
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ciThe MMC module is divided into the following layers:
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci- Interface layer: provides APIs for opening an MMC device, checking whether the MMC controller has devices, and closing an MMC device.
35e41f4b71Sopenharmony_ci- Core layer: provides the capabilities of adding or removing an MMC controller, performing device management, and providing common controller services. The core layer interacts with the adaptation layer through hook functions.
36e41f4b71Sopenharmony_ci- Adaptation layer: instantiates the hook functions to implement specific features.
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci**Figure 1** Independent service mode
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci![img1](figures/independent-service-mode.png)
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci## Development Guidelines
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci### When to Use
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ciThe MMC is used to store multimedia files. Before using your MMC device with OpenHarmony, you need to perform MMC driver adaptation.
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci### Available APIs
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ciTo enable the upper layer to successfully operate the MMC controller by calling the MMC APIs, hook functions are defined in **//drivers/hdf_core/framework/model/storage/include/mmc/mmc_corex.h** for the core layer. You need to implement these hook functions at the adaptation layer and hook them to implement the interaction between the interface layer and the core layer.
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci**MmcCntlrOps**:
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci```c
55e41f4b71Sopenharmony_cistruct MmcCntlrOps {
56e41f4b71Sopenharmony_ci    int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
57e41f4b71Sopenharmony_ci    int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock);
58e41f4b71Sopenharmony_ci    int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode);
59e41f4b71Sopenharmony_ci    int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width);
60e41f4b71Sopenharmony_ci    int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
61e41f4b71Sopenharmony_ci    int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable);
62e41f4b71Sopenharmony_ci    int32_t (*hardwareReset)(struct MmcCntlr *cntlr);
63e41f4b71Sopenharmony_ci    int32_t (*systemInit)(struct MmcCntlr *cntlr);
64e41f4b71Sopenharmony_ci    int32_t (*setEnhanceStrobe)(struct MmcCntlr *cntlr, bool enable);
65e41f4b71Sopenharmony_ci    int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt);
66e41f4b71Sopenharmony_ci    bool (*devReadOnly)(struct MmcCntlr *cntlr);
67e41f4b71Sopenharmony_ci    bool (*devPlugged)(struct MmcCntlr *cntlr);
68e41f4b71Sopenharmony_ci    bool (*devBusy)(struct MmcCntlr *cntlr);
69e41f4b71Sopenharmony_ci    int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode);
70e41f4b71Sopenharmony_ci    int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr);
71e41f4b71Sopenharmony_ci};
72e41f4b71Sopenharmony_ci```
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci**Table 1** Hook functions in **MmcCntlrOps**
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci| Function| Input Parameter| Return Value| Description|
77e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- |
78e41f4b71Sopenharmony_ci| doRequest | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmd**: structure pointer to the command to execute.| HDF_STATUS| Processes the request.|
79e41f4b71Sopenharmony_ci| setClock | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**clock**: clock frequency to set.| HDF_STATUS| Sets the clock frequency.|
80e41f4b71Sopenharmony_ci| setPowerMode | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**mode**: power consumption mode. For details, see **MmcPowerMode**.| HDF_STATUS| Sets the power consumption mode.|
81e41f4b71Sopenharmony_ci| setBusWidth | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**width**: bus width. For details, see **MmcBusWidth**.| HDF_STATUS| Sets the bus width.|
82e41f4b71Sopenharmony_ci| setBusTiming | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**timing**: bus timing. For details, see **MmcBusTiming**.| HDF_STATUS| Sets the bus timing.|
83e41f4b71Sopenharmony_ci| setSdioIrq | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable SDIO interrupts.| HDF_STATUS| Enables or disables SDIO interrupts.|
84e41f4b71Sopenharmony_ci| hardwareReset | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Resets hardware.|
85e41f4b71Sopenharmony_ci| systemInit | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Performs system initialization.|
86e41f4b71Sopenharmony_ci| setEnhanceStrobe | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable the enhanced strobe feature.| HDF_STATUS| Sets the enhanced strobe feature.|
87e41f4b71Sopenharmony_ci| switchVoltage | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**volt**: voltage to set, which can be 3.3 V, 1.8 V, or 1.2 V.| HDF_STATUS| Sets the voltage.|
88e41f4b71Sopenharmony_ci| devReadOnly | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is read-only.|
89e41f4b71Sopenharmony_ci| cardPlugged | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is removed.|
90e41f4b71Sopenharmony_ci| devBusy | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is being used.|
91e41f4b71Sopenharmony_ci| tune | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmdCode**: command code, which is of the uint32_t type.| HDF_STATUS| Tunes the oscillator circuit frequency.|
92e41f4b71Sopenharmony_ci| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci### How to Develop
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ciThe MMC module adaptation procedure is as follows:
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci1. Instantiate the driver entry.
99e41f4b71Sopenharmony_ci2. Configure attribute files.
100e41f4b71Sopenharmony_ci3. Instantiate the MMC controller object.
101e41f4b71Sopenharmony_ci4. Debug the driver.
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci### Example
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ciThe following uses the **//device_soc_hisilicon/common/platform/mmc/himci_v200/himci.c** driver of the Hi3516D V300 development board as an example to describe the driver adaptation.
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci1. Instantiate the driver entry.
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci   The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
110e41f4b71Sopenharmony_ci   Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci   MMC driver entry example:
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ci   ```c
115e41f4b71Sopenharmony_ci   struct HdfDriverEntry g_mmcDriverEntry = {
116e41f4b71Sopenharmony_ci       .moduleVersion = 1,
117e41f4b71Sopenharmony_ci       .Bind = HimciMmcBind,                 // See the Bind function.
118e41f4b71Sopenharmony_ci       .Init = HimciMmcInit,                 // See the Init function.
119e41f4b71Sopenharmony_ci       .Release = HimciMmcRelease,           // See the Release function.
120e41f4b71Sopenharmony_ci       .moduleName = "hi3516_mmc_driver",    // (Mandatory) The value must be the same as that of moduleName in the .hcs file.
121e41f4b71Sopenharmony_ci   };
122e41f4b71Sopenharmony_ci   HDF_INIT(g_mmcDriverEntry);               // Call HDF_INIT to register the driver entry with the HDF.
123e41f4b71Sopenharmony_ci   ```
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ci2. Configure attribute files.
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci   Add the deviceNode information to the **device_info.hcs** file. The deviceNode information is related to the driver entry registration. The following example uses three MMC controllers as an example. If there are more MMC controllers, add the deviceNode information to the **device_info.hcs** file for each controller. The device attribute values configured in **mmc_config.hcs** are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer.
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci   - **device_info.hcs** example:
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci      Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci      ```c
134e41f4b71Sopenharmony_ci      root {
135e41f4b71Sopenharmony_ci          device_info {
136e41f4b71Sopenharmony_ci              match_attr = "hdf_manager";
137e41f4b71Sopenharmony_ci              platform :: host {
138e41f4b71Sopenharmony_ci                  hostName = "platform_host";
139e41f4b71Sopenharmony_ci                  priority = 50;
140e41f4b71Sopenharmony_ci                  device_mmc:: device {
141e41f4b71Sopenharmony_ci                      device0 :: deviceNode {                     // DeviceNode of the driver.
142e41f4b71Sopenharmony_ci                          policy = 2;                             // The value 2 means to publish services for both kernel- and user-mode processes. 
143e41f4b71Sopenharmony_ci                          priority = 10;                          // Driver startup priority.
144e41f4b71Sopenharmony_ci                          permission = 0644;                      // Permission for the device node created.
145e41f4b71Sopenharmony_ci                          moduleName = "hi3516_mmc_driver";       // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
146e41f4b71Sopenharmony_ci                          serviceName = "HDF_PLATFORM_MMC_0";     // (Mandatory) Unique name of the service published by the driver.
147e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hi3516_mmc_emmc";    // (Mandatory) Private data of the controller. The value must be the same as the controller information in mmc_config.hcs.
148e41f4b71Sopenharmony_ci                      }
149e41f4b71Sopenharmony_ci                      device1 :: deviceNode {
150e41f4b71Sopenharmony_ci                          policy = 1;
151e41f4b71Sopenharmony_ci                          priority = 20;
152e41f4b71Sopenharmony_ci                          permission = 0644;
153e41f4b71Sopenharmony_ci                          moduleName = "hi3516_mmc_driver";
154e41f4b71Sopenharmony_ci                          serviceName = "HDF_PLATFORM_MMC_1";
155e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hi3516_mmc_sd";      // The MMC is an SD card.
156e41f4b71Sopenharmony_ci                      }
157e41f4b71Sopenharmony_ci                      device2 :: deviceNode {
158e41f4b71Sopenharmony_ci                          policy = 1;
159e41f4b71Sopenharmony_ci                          priority = 30;
160e41f4b71Sopenharmony_ci                          permission = 0644;
161e41f4b71Sopenharmony_ci                          moduleName = "hi3516_mmc_driver";
162e41f4b71Sopenharmony_ci                          serviceName = "HDF_PLATFORM_MMC_2";
163e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hi3516_mmc_sdio";    // The MMC is an SDIO card.
164e41f4b71Sopenharmony_ci                      }
165e41f4b71Sopenharmony_ci                      ... 
166e41f4b71Sopenharmony_ci                  }
167e41f4b71Sopenharmony_ci              }
168e41f4b71Sopenharmony_ci          }
169e41f4b71Sopenharmony_ci      }
170e41f4b71Sopenharmony_ci      ```
171e41f4b71Sopenharmony_ci
172e41f4b71Sopenharmony_ci   - **mmc_config.hcs** example
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ci      Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/mmc/mmc_config.hcs** file. The parameters are as follows:
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci      ```c
177e41f4b71Sopenharmony_ci      root {
178e41f4b71Sopenharmony_ci          platform {
179e41f4b71Sopenharmony_ci              mmc_config {
180e41f4b71Sopenharmony_ci                  template mmc_controller {                     // Template configuration. If the template is used to configure device node information, the default values in the template will be used for the fields that are not declared for the node.
181e41f4b71Sopenharmony_ci                      match_attr = "";
182e41f4b71Sopenharmony_ci                      voltDef = 0;                              // MMC default voltage. The value 0 stands for 3.3 V, 1 for 1.8 V, and 2 for 1.2 V.
183e41f4b71Sopenharmony_ci                      freqMin = 50000;                          // (Mandatory) Minimum frequency.
184e41f4b71Sopenharmony_ci                      freqMax = 100000000;                      // (Mandatory) Maximum frequency.
185e41f4b71Sopenharmony_ci                      freqDef = 400000;                         // (Mandatory) Default frequency.
186e41f4b71Sopenharmony_ci                      maxBlkNum = 2048;                         // (Mandatory) Maximum block number.
187e41f4b71Sopenharmony_ci                      maxBlkSize = 512;                         // (Mandatory) Maximum block size.
188e41f4b71Sopenharmony_ci                      ocrDef = 0x300000;                        // (Mandatory) working voltage.
189e41f4b71Sopenharmony_ci                      caps2 = 0;                                // (Mandatory) Attribute register. For details, see MmcCaps2 in mmc_caps.h.
190e41f4b71Sopenharmony_ci                      regSize = 0x118;                          // (Mandatory) Register size.
191e41f4b71Sopenharmony_ci                      hostId = 0;                               // (Mandatory) Host number.
192e41f4b71Sopenharmony_ci                      regBasePhy = 0x10020000;                  // (Mandatory) Physical base address of the register.
193e41f4b71Sopenharmony_ci                      irqNum = 63;                              // (Mandatory) IRQ number.
194e41f4b71Sopenharmony_ci                      devType = 2;                              // (Mandatory) Device type, which can be eMMC, SD, SDIO, or COMBO.
195e41f4b71Sopenharmony_ci                      caps = 0x0001e045;                        // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h.
196e41f4b71Sopenharmony_ci                  }
197e41f4b71Sopenharmony_ci                  controller_0x10100000 :: mmc_controller {
198e41f4b71Sopenharmony_ci                      match_attr = "hi3516_mmc_emmc";           // (Mandatory) The value must be the same as deviceMatchAttr in device_info.hcs.
199e41f4b71Sopenharmony_ci                      hostId = 0;
200e41f4b71Sopenharmony_ci                      regBasePhy = 0x10100000;
201e41f4b71Sopenharmony_ci                      irqNum = 96;
202e41f4b71Sopenharmony_ci                      devType = 0;                              // The device is an eMMC card.
203e41f4b71Sopenharmony_ci                      caps = 0xd001e045;
204e41f4b71Sopenharmony_ci                      caps2 = 0x60;
205e41f4b71Sopenharmony_ci                  }
206e41f4b71Sopenharmony_ci                  controller_0x100f0000 :: mmc_controller {
207e41f4b71Sopenharmony_ci                      match_attr = "hi3516_mmc_sd";
208e41f4b71Sopenharmony_ci                      hostId = 1;
209e41f4b71Sopenharmony_ci                      regBasePhy = 0x100f0000;
210e41f4b71Sopenharmony_ci                      irqNum = 62;
211e41f4b71Sopenharmony_ci                      devType = 1;                              // The device is an SD card.
212e41f4b71Sopenharmony_ci                      caps = 0xd001e005;
213e41f4b71Sopenharmony_ci                  }
214e41f4b71Sopenharmony_ci                  controller_0x10020000 :: mmc_controller {
215e41f4b71Sopenharmony_ci                      match_attr = "hi3516_mmc_sdio";
216e41f4b71Sopenharmony_ci                      hostId = 2;
217e41f4b71Sopenharmony_ci                      regBasePhy = 0x10020000;
218e41f4b71Sopenharmony_ci                      irqNum = 63;
219e41f4b71Sopenharmony_ci                      devType = 2;                              // The device is an SDIO card.
220e41f4b71Sopenharmony_ci                      caps = 0x0001e04d;
221e41f4b71Sopenharmony_ci                  }
222e41f4b71Sopenharmony_ci              }
223e41f4b71Sopenharmony_ci          }
224e41f4b71Sopenharmony_ci      }
225e41f4b71Sopenharmony_ci      ```
226e41f4b71Sopenharmony_ci
227e41f4b71Sopenharmony_ci      After the **mmc_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect.
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci      ```c
230e41f4b71Sopenharmony_ci      #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/mmc/mmc_config.hcs" // Relative path of the file.
231e41f4b71Sopenharmony_ci      ```
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_ci3. Instantiate the MMC controller object.
234e41f4b71Sopenharmony_ci
235e41f4b71Sopenharmony_ci   Initialize the **MmcCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **MmcCntlrOps** in **MmcCntlr** (so that the underlying driver functions can be called).
236e41f4b71Sopenharmony_ci
237e41f4b71Sopenharmony_ci   - Define a custom structure.
238e41f4b71Sopenharmony_ci
239e41f4b71Sopenharmony_ci      To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **mmc_config.hcs** file to initialize the members in the custom structure and passes important parameters to the **MmcCntlr** object at the core layer.
240e41f4b71Sopenharmony_ci
241e41f4b71Sopenharmony_ci      ```c
242e41f4b71Sopenharmony_ci      struct HimciHost {
243e41f4b71Sopenharmony_ci          struct MmcCntlr *mmc;                             // (Mandatory) Core layer control object.
244e41f4b71Sopenharmony_ci          struct MmcCmd *cmd                                // (Mandatory) Core layer structure used to pass commands. For details about related commands, see MmcCmdCode.
245e41f4b71Sopenharmony_ci          void *base;                                       // Register base address used for address mapping.
246e41f4b71Sopenharmony_ci          enum HimciPowerStatus powerStatus;
247e41f4b71Sopenharmony_ci          uint8_t *alignedBuff;
248e41f4b71Sopenharmony_ci          uint32_t buffLen;
249e41f4b71Sopenharmony_ci          struct scatterlist dmaSg;
250e41f4b71Sopenharmony_ci          struct scatterlist *sg;
251e41f4b71Sopenharmony_ci          uint32_t dmaSgNum;
252e41f4b71Sopenharmony_ci          DMA_ADDR_T dmaPaddr;
253e41f4b71Sopenharmony_ci          uint32_t *dmaVaddr;
254e41f4b71Sopenharmony_ci          uint32_t irqNum;
255e41f4b71Sopenharmony_ci          bool isTuning;
256e41f4b71Sopenharmony_ci          uint32_t id;
257e41f4b71Sopenharmony_ci          struct OsalMutex mutex;
258e41f4b71Sopenharmony_ci          bool waitForEvent;
259e41f4b71Sopenharmony_ci          HIMCI_EVENT himciEvent;
260e41f4b71Sopenharmony_ci      };
261e41f4b71Sopenharmony_ci      // MmcCntlr is the core layer controller structure. The Bind function assigns values to the members of MmcCntlr.
262e41f4b71Sopenharmony_ci      struct MmcCntlr {
263e41f4b71Sopenharmony_ci          struct IDeviceIoService service;
264e41f4b71Sopenharmony_ci          struct HdfDeviceObject *hdfDevObj;
265e41f4b71Sopenharmony_ci          struct PlatformDevice device;
266e41f4b71Sopenharmony_ci          struct OsalMutex mutex;
267e41f4b71Sopenharmony_ci          struct OsalSem released;
268e41f4b71Sopenharmony_ci          uint32_t devType;
269e41f4b71Sopenharmony_ci          struct MmcDevice *curDev;
270e41f4b71Sopenharmony_ci          struct MmcCntlrOps *ops;
271e41f4b71Sopenharmony_ci          struct PlatformQueue *msgQueue;
272e41f4b71Sopenharmony_ci          uint16_t index;
273e41f4b71Sopenharmony_ci          uint16_t voltDef;
274e41f4b71Sopenharmony_ci          uint32_t vddBit;
275e41f4b71Sopenharmony_ci          uint32_t freqMin;
276e41f4b71Sopenharmony_ci          uint32_t freqMax;
277e41f4b71Sopenharmony_ci          uint32_t freqDef;
278e41f4b71Sopenharmony_ci          union MmcOcr ocrDef;
279e41f4b71Sopenharmony_ci          union MmcCaps caps;
280e41f4b71Sopenharmony_ci          union MmcCaps2 caps2;
281e41f4b71Sopenharmony_ci          uint32_t maxBlkNum;
282e41f4b71Sopenharmony_ci          uint32_t maxBlkSize;
283e41f4b71Sopenharmony_ci          uint32_t maxReqSize;
284e41f4b71Sopenharmony_ci          bool devPlugged;
285e41f4b71Sopenharmony_ci          bool detecting;
286e41f4b71Sopenharmony_ci          void *priv;
287e41f4b71Sopenharmony_ci      };
288e41f4b71Sopenharmony_ci      ```
289e41f4b71Sopenharmony_ci
290e41f4b71Sopenharmony_ci   - Instantiate **MmcCntlrOps** in **MmcCntlr**.
291e41f4b71Sopenharmony_ci
292e41f4b71Sopenharmony_ci      ```c
293e41f4b71Sopenharmony_ci      static struct MmcCntlrOps g_himciHostOps = {
294e41f4b71Sopenharmony_ci          .request = HimciDoRequest,
295e41f4b71Sopenharmony_ci          .setClock = HimciSetClock,
296e41f4b71Sopenharmony_ci          .setPowerMode = HimciSetPowerMode,
297e41f4b71Sopenharmony_ci          .setBusWidth = HimciSetBusWidth,
298e41f4b71Sopenharmony_ci          .setBusTiming = HimciSetBusTiming,
299e41f4b71Sopenharmony_ci          .setSdioIrq = HimciSetSdioIrq,
300e41f4b71Sopenharmony_ci          .hardwareReset = HimciHardwareReset,
301e41f4b71Sopenharmony_ci          .systemInit = HimciSystemInit,
302e41f4b71Sopenharmony_ci          .setEnhanceStrobe = HimciSetEnhanceStrobe,
303e41f4b71Sopenharmony_ci          .switchVoltage = HimciSwitchVoltage,
304e41f4b71Sopenharmony_ci          .devReadOnly = HimciDevReadOnly,
305e41f4b71Sopenharmony_ci          .devPlugged = HimciCardPlugged,
306e41f4b71Sopenharmony_ci          .devBusy = HimciDevBusy,
307e41f4b71Sopenharmony_ci          .tune = HimciTune,
308e41f4b71Sopenharmony_ci          .rescanSdioDev = HimciRescanSdioDev,
309e41f4b71Sopenharmony_ci      };
310e41f4b71Sopenharmony_ci      ```
311e41f4b71Sopenharmony_ci
312e41f4b71Sopenharmony_ci   - Implement the **Bind** function.
313e41f4b71Sopenharmony_ci
314e41f4b71Sopenharmony_ci      **Input parameter**:
315e41f4b71Sopenharmony_ci
316e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
317e41f4b71Sopenharmony_ci
318e41f4b71Sopenharmony_ci      **Return value**:
319e41f4b71Sopenharmony_ci
320e41f4b71Sopenharmony_ci      **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **//drivers/hdf_core/framework/include/utils/hdf_base.h** file.
321e41f4b71Sopenharmony_ci
322e41f4b71Sopenharmony_ci      **Table 2** HDF_STATUS description
323e41f4b71Sopenharmony_ci
324e41f4b71Sopenharmony_ci      | Status| Description|
325e41f4b71Sopenharmony_ci      | -------- | -------- |
326e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
327e41f4b71Sopenharmony_ci      | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
328e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_PARAM | Invalid parameter.|
329e41f4b71Sopenharmony_ci      | HDF_ERR_IO | I/O error.|
330e41f4b71Sopenharmony_ci      | HDF_SUCCESS | Initialization successful.|
331e41f4b71Sopenharmony_ci      | HDF_FAILURE | Initialization failed.|
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci      **Function description**:
334e41f4b71Sopenharmony_ci
335e41f4b71Sopenharmony_ci      Initializes the **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer to add the MMC controllers.
336e41f4b71Sopenharmony_ci
337e41f4b71Sopenharmony_ci      ```c
338e41f4b71Sopenharmony_ci      static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
339e41f4b71Sopenharmony_ci      {
340e41f4b71Sopenharmony_ci          struct MmcCntlr *cntlr = NULL;
341e41f4b71Sopenharmony_ci          struct HimciHost *host = NULL;
342e41f4b71Sopenharmony_ci          int32_t ret;
343e41f4b71Sopenharmony_ci          cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
344e41f4b71Sopenharmony_ci          host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
345e41f4b71Sopenharmony_ci          
346e41f4b71Sopenharmony_ci          host->mmc = cntlr;                              // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
347e41f4b71Sopenharmony_ci          cntlr->priv = (void *)host;                     // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
348e41f4b71Sopenharmony_ci          cntlr->ops = &g_himciHostOps;                   // (Mandatory) Attach the MmcCntlrOps instance to MmcCntlr.
349e41f4b71Sopenharmony_ci          cntlr->hdfDevObj = obj;                         // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
350e41f4b71Sopenharmony_ci          obj->service = &cntlr->service;                 // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
351e41f4b71Sopenharmony_ci          ret = MmcCntlrParse(cntlr, obj);                // (Mandatory) Initialize MmcCntlr. If the initialization fails, execute goto _ERR.
352e41f4b71Sopenharmony_ci          ...
353e41f4b71Sopenharmony_ci          ret = HimciHostParse(host, obj);                // (Mandatory) Initialize HimciHost. If the initialization fails, execute goto _ERR.
354e41f4b71Sopenharmony_ci          ...
355e41f4b71Sopenharmony_ci          ret = HimciHostInit(host, cntlr);               // Customized initizlization. If the initialization fails, goto _ERR.
356e41f4b71Sopenharmony_ci          ...
357e41f4b71Sopenharmony_ci          ret = MmcCntlrAdd(cntlr);                       // Call MmcCntlrAdd at the core layer. If the operation fails, execute goto _ERR.
358e41f4b71Sopenharmony_ci          ...
359e41f4b71Sopenharmony_ci          (void)MmcCntlrAddDetectMsgToQueue(cntlr);       // Add the card detection message to the queue.
360e41f4b71Sopenharmony_ci          HDF_LOGD("HimciMmcBind: success.");
361e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
362e41f4b71Sopenharmony_ci      ERR:
363e41f4b71Sopenharmony_ci          HimciDeleteHost(host);
364e41f4b71Sopenharmony_ci          HDF_LOGD("HimciMmcBind: fail, err = %d.", ret);
365e41f4b71Sopenharmony_ci          return ret;
366e41f4b71Sopenharmony_ci      }
367e41f4b71Sopenharmony_ci      ```
368e41f4b71Sopenharmony_ci
369e41f4b71Sopenharmony_ci   - Implement the **Init** function.
370e41f4b71Sopenharmony_ci
371e41f4b71Sopenharmony_ci      **Input parameter**:
372e41f4b71Sopenharmony_ci
373e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
374e41f4b71Sopenharmony_ci
375e41f4b71Sopenharmony_ci      **Return value**:
376e41f4b71Sopenharmony_ci
377e41f4b71Sopenharmony_ci      HDF_STATUS
378e41f4b71Sopenharmony_ci
379e41f4b71Sopenharmony_ci      **Function description**:
380e41f4b71Sopenharmony_ci
381e41f4b71Sopenharmony_ci      Implements **ProcMciInit**.
382e41f4b71Sopenharmony_ci
383e41f4b71Sopenharmony_ci      ```c
384e41f4b71Sopenharmony_ci      static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
385e41f4b71Sopenharmony_ci      {
386e41f4b71Sopenharmony_ci          static bool procInit = false;
387e41f4b71Sopenharmony_ci          (void)obj;
388e41f4b71Sopenharmony_ci          if (procInit == false) {
389e41f4b71Sopenharmony_ci              if (ProcMciInit() == HDF_SUCCESS) {
390e41f4b71Sopenharmony_ci                  procInit = true;
391e41f4b71Sopenharmony_ci                  HDF_LOGD("HimciMmcInit: proc init success.");
392e41f4b71Sopenharmony_ci              }
393e41f4b71Sopenharmony_ci          }
394e41f4b71Sopenharmony_ci          HDF_LOGD("HimciMmcInit: success.");
395e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
396e41f4b71Sopenharmony_ci      }
397e41f4b71Sopenharmony_ci      ```
398e41f4b71Sopenharmony_ci
399e41f4b71Sopenharmony_ci   - Implement the **Release** function.
400e41f4b71Sopenharmony_ci
401e41f4b71Sopenharmony_ci      **Input parameter**:
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_ci      **Return value**:
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ci      No value is returned.
408e41f4b71Sopenharmony_ci
409e41f4b71Sopenharmony_ci      **Function description**:
410e41f4b71Sopenharmony_ci
411e41f4b71Sopenharmony_ci      Releases the memory and deletes the controller. This function assigns values to **Release()** in the driver entry structure. If the HDF fails to call **Init()** to initialize the driver, **Release()** is called to release driver resources.
412e41f4b71Sopenharmony_ci
413e41f4b71Sopenharmony_ci      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
414e41f4b71Sopenharmony_ci      > All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
415e41f4b71Sopenharmony_ci
416e41f4b71Sopenharmony_ci      ```c
417e41f4b71Sopenharmony_ci      static void HimciMmcRelease(struct HdfDeviceObject *obj)
418e41f4b71Sopenharmony_ci      {
419e41f4b71Sopenharmony_ci          struct MmcCntlr *cntlr = NULL;
420e41f4b71Sopenharmony_ci          ...
421e41f4b71Sopenharmony_ci          cntlr = (struct MmcCntlr *)obj->service;             // Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function.
422e41f4b71Sopenharmony_ci          ...
423e41f4b71Sopenharmony_ci          HimciDeleteHost((struct HimciHost *)cntlr->priv);    // Memory release function customized. Forced conversion between MmcCntlr and HimciHost is involved.
424e41f4b71Sopenharmony_ci      }
425e41f4b71Sopenharmony_ci      ```
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci4. Debug the driver.
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_ci   (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted.
430