• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SDIO
2
3
4## Overview
5
6A Secure Digital Input Output (SDIO) card is an extension of the SD specification to cover I/O functions. SD and SDIO cards are called multimedia cards (MMCs). In the Hardware Driver Foundation (HDF), the SDIO module uses the independent service mode 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.
7
8  **Figure 1** Independent service mode
9
10  ![image](figures/independent-service-mode.png)
11
12
13## Available APIs
14
15**SdioDeviceOps**:
16
17
18```
19// Function template
20struct SdioDeviceOps {
21  int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
22  int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
23  int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
24  int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
25  int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
26  int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
27  int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize);
28  int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
29  int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
30  int32_t (*flushData)(struct SdioDevice *dev);
31  int32_t (*enableFunc)(struct SdioDevice *dev);
32  int32_t (*disableFunc)(struct SdioDevice *dev);
33  int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler);
34  int32_t (*releaseIrq)(struct SdioDevice *dev);
35  int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData);
36  int32_t (*claimHost)(struct SdioDevice *dev);
37  int32_t (*releaseHost)(struct SdioDevice *dev);
38};
39```
40
41  **Table 1** Description of the callback functions in SdioDeviceOps
42
43| Function| Input Parameter| Output Parameter| Return Value| Description|
44| -------- | -------- | -------- | -------- | -------- |
45| incrAddrReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Incrementally reads data of a given length from the specified SDIO address.|
46| incrAddrWriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.| –| HDF_STATUS| Incrementally writes data of a given length to the specified SDIO address.|
47| fixedAddrReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.<br>**scatterLen**: data length, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Reads data of a given length from a fixed SDIO address.|
48| fixedAddrWriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.<br>**scatterLen**: data length, which is of the uint32_t type.| –| HDF_STATUS| Writes data of a given length to the fixed SDIO address.|
49| func0ReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Reads data of a given length from the address space of SDIO function 0.|
50| func0WriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.| –| HDF_STATUS| Writes data of a given length to the address space of SDIO function 0.|
51| setBlockSize | **dev**: structure pointer to the SDIO device controller.<br>**blockSize**: block size, which is of the uint32_t type.| –| HDF_STATUS| Sets the block size.|
52| getCommonInfo | **dev**: structure pointer to the SDIO device controller.  <br>**infoType**: info type, which is of the uint32_t type.| **info**: structure pointer to the output **SdioFuncInfo**.| HDF_STATUS| Obtains **CommonInfo**. For details, see the **NOTE** below this table.|
53| setCommonInfo | **dev**: structure pointer to the SDIO device controller.<br>**info**: union pointer to the input **SdioFuncInfo**.<br>**infoType**: info type, which is of the uint32_t type.| –| HDF_STATUS| Sets **CommonInfo**. For details, see the **NOTE** below this table.|
54| flushData | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Called to flush data when the SDIO device needs to be re-initialized or an error occurs.|
55| enableFunc | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Enables an SDIO device.|
56| disableFunc | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Disables an SDIO device.|
57| claimIrq | **dev**: structure pointer to the SDIO device controller.<br>**irqHandler**: void function pointer to the interrupt request (IRQ) handler.| –| HDF_STATUS| Claims an SDIO IRQ.|
58| releaseIrq | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Releases an SDIO IRQ.|
59| findFunc | **dev**: structure pointer to the SDIO device controller.<br>**configData**: structure pointer to the key SDIO function information.| –| HDF_STATUS| Obtains the matching funcNum.|
60| claimHost | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Claims a host exclusively.|
61| releaseHost | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Releases the exclusively claimed host.|
62
63
64> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
65> CommonInfo includes the following information:<br>- **maxBlockNum**: specifies the maximum number of blocks in a request. <br>- **maxBlockSize**: specifies the maximum number of bytes in a block. <br>- **maxRequestSize**: specifies the maximum number of bytes in a request. <br>- **enTimeout**: specifies the maximum timeout period, in milliseconds. <br>- **funcNum**: specifies the function number, which ranges from 1 to 7. <br>- **irqCap**: specifies the IRQ capabilities. <br>- **(void \*)data**
66
67
68## How to Develop
69
70The SDIO module adaptation involves the following steps:
71
721. Instantiate the driver entry.
73   - Instantiate the **HdfDriverEntry** structure.
74   - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
75
762. Configure attribute files.
77   - Add the **deviceNode** information to the **device_info.hcs** file.
78   - (Optional) Add the **sdio_config.hcs** file.
79
803. Instantiate the SDIO controller object.
81   - Initialize **SdioDevice**.
82   - Instantiate **SdioDeviceOps** in the **SdioDevice** object.
83      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
84      > For details about the functions in **SdioDeviceOps**, see [Available APIs](#available-apis).
85
864. Debug the driver.
87
88   (Optional) For new drivers, verify the basic functions, such as the SDIO control status and response to interrupts.
89
90
91## Development Example
92
93The following uses **sdio_adapter.c** as an example to present the information required for implementing device functions.
94
951. Instantiate the driver entry.
96
97   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**.
98
99   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.
100
101   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.
102
103   SDIO driver entry example:
104
105   ```
106   struct HdfDriverEntry g_sdioDriverEntry = {
107       .moduleVersion = 1,
108       .Bind = Hi35xxLinuxSdioBind,       // See the Bind function.
109       .Init = Hi35xxLinuxSdioInit,       // See the Init function.
110       .Release = Hi35xxLinuxSdioRelease, // See the Release function.
111       .moduleName = "HDF_PLATFORM_SDIO",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
112   };
113   // Call HDF_INIT to register the driver entry with the HDF.
114   HDF_INIT(g_sdioDriverEntry);
115   ```
116
1172. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **sdio_config.hcs** file.
118
119   The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **SdioDevice** members at the core layer.
120
121   In this example, there is only one SDIO controller. If there are multiple SDIO controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **sdio_config** file for each controller.
122
123   - **device_info.hcs** configuration example:
124
125
126     ```
127      root {
128       device_info {
129         match_attr = "hdf_manager";
130         platform :: host {
131           hostName = "platform_host";
132           priority = 50;
133           device_sdio :: device {
134             device0 :: deviceNode {
135               policy = 1;
136               priority = 70;
137               permission = 0644;
138               moduleName = "HDF_PLATFORM_SDIO";          // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
139               serviceName = "HDF_PLATFORM_MMC_2";        // (Mandatory) Unique name of the service published by the driver.
140               deviceMatchAttr = "hisilicon_hi35xx_sdio_0";// (Mandatory) Private data of the controller. The value must be the same as the controller information in sdio_config.hcs.
141             }
142           }
143         }
144       }
145     }
146     ```
147
148   - **sdio_config.hcs** configuration example:
149
150
151     ```
152     root {
153       platform {
154         sdio_config {
155           template sdio_controller {
156             match_attr = "";
157             hostId = 2;                            // (Mandatory) The value must be 2. For details, see mmc_config.hcs.
158             devType = 2;                           // (Mandatory) The value must be 2. For details, see mmc_config.hcs.
159           }
160           controller_0x2dd1 :: sdio_controller {
161             match_attr = "hisilicon_hi35xx_sdio_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
162         }
163       }
164     }
165     ```
166
1673. Initialize the **SdioDevice** 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 **SdioDeviceOps** in **SdioDevice** (so that the underlying driver functions can be called).
168
169   - Defining a custom structure
170
171     To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **sdio_config.hcs** file to initialize the members in the custom structure and passes important parameters to the object at the core layer.
172
173
174      ```
175      typedef struct {
176          uint32_t maxBlockNum;    // Maximum number of blocks in a request.
177          uint32_t maxBlockSize;   // Maximum number of bytes in a block. The value range is 1 to 2048.
178          uint32_t maxRequestSize; // Maximum number of bytes in a request. The value range is 1 to 2048.
179          uint32_t enTimeout;      // Maximum timeout period in milliseconds. The value cannot exceed one second.
180          uint32_t funcNum;        // Function number, which ranges from 1 to 7.
181          uint32_t irqCap;         // IRQ capabilities.
182          void *data;              // Private data.
183      } SdioFuncInfo;
184
185      // SdioDevice is the core layer controller structure. The Bind function assigns values to the members of SdioDevice.
186      struct SdioDevice {
187          struct SdDevice sd;
188          struct SdioDeviceOps *sdioOps;
189          struct SdioRegister sdioReg;
190          uint32_t functions;
191          struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];
192          struct SdioFunction *curFunction;
193          struct OsalThread thread;  /* irq thread */
194          struct OsalSem sem;
195          bool irqPending;
196          bool threadRunning;
197      };
198      ```
199
200   - Instantiating **SdioDeviceOps** in **SdioDevice** (other members are initialized by **Init**)
201
202
203      ```
204      static struct SdioDeviceOps g_sdioDeviceOps = {
205          .incrAddrReadBytes   = Hi35xxLinuxSdioIncrAddrReadBytes,
206          .incrAddrWriteBytes  = Hi35xxLinuxSdioIncrAddrWriteBytes,
207          .fixedAddrReadBytes  = Hi35xxLinuxSdioFixedAddrReadBytes,
208          .fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes,
209          .func0ReadBytes  = Hi35xxLinuxSdioFunc0ReadBytes,
210          .func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes,
211          .setBlockSize    = Hi35xxLinuxSdioSetBlockSize,
212          .getCommonInfo   = Hi35xxLinuxSdioGetCommonInfo,
213          .setCommonInfo   = Hi35xxLinuxSdioSetCommonInfo,
214          .flushData       = Hi35xxLinuxSdioFlushData,
215          .enableFunc      = Hi35xxLinuxSdioEnableFunc,
216          .disableFunc = Hi35xxLinuxSdioDisableFunc,
217          .claimIrq    = Hi35xxLinuxSdioClaimIrq,
218          .releaseIrq  = Hi35xxLinuxSdioReleaseIrq,
219          .findFunc    = Hi35xxLinuxSdioFindFunc,
220          .claimHost   = Hi35xxLinuxSdioClaimHost,
221          .releaseHost = Hi35xxLinuxSdioReleaseHost,
222      };
223      ```
224
225- **Bind** function
226
227   **Input parameter**:
228
229   **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
230
231   **Return value**:
232
233   **HDF_STATUS**
234
235   The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
236
237   **Table 2** Description of HDF_STATUS
238
239   | Status                 | Description                |
240   | ---------------------- | -------------------------- |
241   | HDF_ERR_INVALID_OBJECT | Invalid controller object. |
242   | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory. |
243   | HDF_ERR_INVALID_PARAM  | Invalid parameter.         |
244   | HDF_ERR_IO             | I/O error.                 |
245   | HDF_SUCCESS            | Initialization successful. |
246   | HDF_FAILURE            | Initialization failed.     |
247
248   **Function description**:
249
250   Initializes the custom structure object and **SdioCntlr**, calls the **SdioCntlrAdd** function at the core layer, and performs other initialization operations customized by the vendor.
251
252   ```
253   static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
254      {
255          struct MmcCntlr *cntlr = NULL;
256          int32_t ret;
257          ...
258           cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// Allocate memory.
259          ...
260          cntlr->ops = &g_sdioCntlrOps;                                     // (Mandatory) struct MmcCntlrOps g_sdioCntlrOps={
261                                                                            // .rescanSdioDev = Hi35xxLinuxSdioRescan,};
262          cntlr->hdfDevObj = obj;                                           // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
263          obj->service = &cntlr->service;                                   // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
264          ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);                      // (Mandatory) Initialize index and devType of cntlr. If the initialization fails, execute goto _ERR.
265          ...
266          ret = MmcCntlrAdd(cntlr);                                         // (Mandatory) Call the function in mmc_core.c. If the operation fails, execute goto _ERR.
267          ...
268          ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);   // (Mandatory) Call the function in mmc_core.c. If the operation fails, execute goto _ERR.
269          ...
270
271          MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);                // (Mandatory) Call the function in mmc_core.c to hook the related functions.
272          HDF_LOGD("Hi35xxLinuxSdioBind: Success!");
273          return HDF_SUCCESS;
274
275      _ERR:
276          Hi35xxLinuxSdioDeleteCntlr(cntlr);
277          HDF_LOGE("Hi35xxLinuxSdioBind: Fail!");
278       return HDF_FAILURE;
279      }
280   ```
281
282- **Init** function
283
284   **Input parameter**:
285
286   **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
287
288   **Return value**:
289
290   **HDF_STATUS**
291
292   **Function description**:
293
294   You can add operations as required.
295
296   ```
297   static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
298      {
299          (void)obj;// No operation. You can add operations as required.
300          HDF_LOGD("Hi35xxLinuxSdioInit: Success!");
301          return HDF_SUCCESS;
302   }
303   ```
304
305- **Release** function
306
307   **Input parameter**:
308
309   **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
310
311   **Return value**:
312
313   No value is returned.
314
315   **Function description**:
316
317   Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
318
319   > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
320   > All forced conversion operations for obtaining the corresponding object can be successful only when the **Bind** function has the corresponding value assignment operations.
321
322   ```
323   static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
324   {
325       if (obj == NULL) {
326           return;
327       }
328       Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// (Mandatory) Custom function for releasing memory. A forced conversion from HdfDeviceObject to MmcCntlr is involved.
329   }
330   ```
331