# SDIO
## Overview
Secure Digital Input/Output \(SDIO\) is a peripheral interface evolved from the Secure Digital \(SD\) memory card interface. The SDIO interface is compatible with SD memory cards and can be connected to devices that support the SDIO interface.
SDIO is widely used. Currently, many smartphones support SDIO, and many SDIO peripherals are developed for connections to smartphones. Common SDIO peripherals include WLAN, GPS, cameras, and Bluetooth.
The SDIO bus has two ends, named host and device. All communication starts when the host sends a command. The device can communicate with the host as long as it can parse the command of the host. An SDIO host can connect to multiple devices, as shown in the figure below.
- CLK signal: clock signal sent from the host to the device
- VDD signal: power signal
- VSS signal: ground signal
- D0-3 signal: four data lines. The DAT1 signal cable is multiplexed as the interrupt line. In 1-bit mode, DAT0 is used to transmit data. In 4-bit mode, DAT0 to DAT3 are used to transmit data.
- CMD signal: used by the host to send commands and the device to respond to commands.
**Figure 1** Connections between the host and devices in SDIO
![](figures/en-us_image_0000001160971556.png)
The SDIO interface defines a set of common methods for operating an SDIO device, including opening and closing an SDIO controller, exclusively claiming and releasing the host, enabling and disabling devices, claiming and releasing an SDIO IRQ, reading and writing data based on SDIO, and obtaining and setting common information.
## Available APIs
**Table 1** APIs available for the SDIO driver
Capability
|
Function
|
Description
|
SDIO device opening/closing
|
SdioOpen
|
Opens an SDIO controller with a specified bus number.
|
SdioClose
|
Closes an SDIO controller.
|
SDIO reading/writing
|
SdioReadBytes
|
Incrementally reads a given length of data from a specified SDIO address.
|
SdioWriteBytes
|
Incrementally writes a given length of data into a specified SDIO address.
|
SdioReadBytesFromFixedAddr
|
Reads a given length of data from a fixed SDIO address.
|
SdioWriteBytesToFixedAddr
|
Writes a given length of data into a fixed SDIO address.
|
SdioReadBytesFromFunc0
|
Reads a given length of data from the address space of SDIO function 0.
|
SdioWriteBytesToFunc0
|
Writes a given length of data into the address space of SDIO function 0.
|
SDIO block size setting
|
SdioSetBlockSize
|
Sets the block size.
|
SDIO common information retrieval/setting
|
SdioGetCommonInfo
|
Obtains common information.
|
SdioSetCommonInfo
|
Sets common information.
|
SDIO data flushing
|
SdioFlushData
|
Flushes data.
|
SDIO host exclusively claiming or releasing
|
SdioClaimHost
|
Claims a host exclusively.
|
SdioReleaseHost
|
Releases the exclusively claimed host.
|
SDIO device enablement
|
SdioEnableFunc
|
Enables an SDIO device.
|
SdioDisableFunc
|
Disables an SDIO device.
|
SDIO IRQ claiming/releasing
|
SdioClaimIrq
|
Claims an SDIO IRQ.
|
SdioReleaseIrq
|
Releases an SDIO IRQ.
|
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>All functions provided in this document can be called only in kernel mode.
## Usage Guidelines
### How to Use
[Figure 2](#fig1343742311264) illustrates the process of using an SDIO.
**Figure 2** Process of using an SDIO
![](figures/en-us_image_0000001206291517.png)
### Opening an SDIO Controller
Before performing SDIO communication, obtain the device handle of an SDIO controller by calling **SdioOpen**. This function returns the device handle of the SDIO controller with a specified bus number.
DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\);
**Table 2** Parameters and return values of SdioOpen
Parameter
|
Description
|
mmcBusNum
|
Bus number.
|
config
|
SDIO functionality configurations.
|
Return Value
|
Description
|
NULL
|
Failed to obtain the device handle of an SDIO controller.
|
Device handle
|
Device handle of an SDIO controller.
|
The following example shows how to open an SDIO controller.
```
DevHandle handle = NULL;
struct SdioFunctionConfig config;
config.funcNr = 1;
config.vendorId = 0x123;
config.deviceId = 0x456;
/* Open an SDIO controller whose bus number is 1. */
handle = SdioOpen(1, &config);
if (handle == NULL) {
HDF_LOGE("SdioOpen: failed!\n");
}
```
### Claiming a Host Exclusively
After obtaining the device handle of an SDIO controller, exclusively claim the host before performing subsequent operations on the SDIO device.
void SdioClaimHost\(DevHandle handle\);
**Table 3** Parameter description of SdioClaimHost
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
The following example shows how to exclusively claim a host.
```
SdioClaimHost(handle); /* Claim a host exclusively. */
```
### Enabling the SDIO Device
Before accessing a register, enable the SDIO device.
int32\_t SdioEnableFunc\(DevHandle handle\);
**Table 4** Parameters and return values of SdioEnableFunc
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
Return Value
|
Description
|
0
|
The SDIO device is enabled.
|
Negative value
|
Failed to enable the SDIO device.
|
The following example shows how to enable the SDIO device.
```
int32_t ret;
/* Enable the SDIO device. */
ret = SdioEnableFunc(handle);
if (ret != 0) {
HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret);
}
```
### Claiming an SDIO IRQ
Before SDIO communication, claim an SDIO IRQ.
int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\);
**Table 5** Parameters and return values of SdioClaimIrq
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
handler
|
Pointer to the SDIO IRQ function.
|
Return Value
|
Description
|
0
|
The SDIO IRQ is claimed.
|
Negative value
|
Failed to claim an SDIO IRQ.
|
The following example shows how to claim an SDIO IRQ.
```
/* Implement the SDIO IRQ function based on the application. */
static void SdioIrqFunc(void *data)
{
if (data == NULL) {
HDF_LOGE("SdioIrqFunc: data is NULL.\n");
return;
}
/* You need to add specific implementations. */
}
int32_t ret;
/* Claim an SDIO IRQ. */
ret = SdioClaimIrq(handle, SdioIrqFunc);
if (ret != 0) {
HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret);
}
```
### Performing SDIO Communication
- Incrementally write a given length of data into the SDIO device.
The corresponding function is as follows:
int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 6** Parameters and return values of SdioWriteBytes
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to write.
|
addr
|
Start address where the data is written into.
|
size
|
Length of the data to write.
|
Return Value
|
Description
|
0
|
Data is written into the SDIO device.
|
Negative value
|
Failed to write data into the SDIO device.
|
The following example shows how to incrementally write a given length of data into the SDIO device.
```
int32_t ret;
uint8_t wbuff[] = {1,2,3,4,5};
uint32_t addr = 0x100 + 0x09;
/* Incrementally write 5-byte data into the start address 0x109 of the SDIO device. */
ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]));
if (ret != 0) {
HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret);
}
```
- Incrementally read a given length of data from the SDIO device.
The corresponding function is as follows:
int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 7** Parameters and return values of SdioReadBytes
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to read.
|
addr
|
Start address where the data is read from.
|
size
|
Length of the data to read.
|
Return Value
|
Description
|
0
|
Data is read from the SDIO device.
|
Negative value
|
Failed to read data from the SDIO device.
|
The following example shows how to incrementally read a given length of data from the SDIO device.
```
int32_t ret;
uint8_t rbuff[5] = {0};
uint32_t addr = 0x100 + 0x09;
/* Incrementally read 5-byte data from the start address 0x109 of the SDIO device. */
ret = SdioReadBytes(handle, rbuff, addr, 5);
if (ret != 0) {
HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret);
}
```
- Write a given length of data into the fixed address of an SDIO device.
The corresponding function is as follows:
int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
**Table 8** Parameters and return values of SdioWriteBytesToFixedAddr
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to write.
|
addr
|
Fixed address where the data is written into.
|
size
|
Length of the data to write.
|
scatterLen
|
Length of the scatter list. If the value is not 0, the data is of the scatter list type.
|
Return Value
|
Description
|
0
|
Data is written into the SDIO device.
|
Negative value
|
Failed to write data into the SDIO device.
|
The following example shows how to write a given length of data into the fixed address of an SDIO device.
```
int32_t ret;
uint8_t wbuff[] = {1, 2, 3, 4, 5};
uint32_t addr = 0x100 + 0x09;
/* Write 5-byte data into the fixed address 0x109 of the SDIO device. */
ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0);
if (ret != 0) {
HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret);
}
```
- Read a given length of data from the fixed address of an SDIO device.
The corresponding function is as follows:
int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
**Table 9** Parameters and return values of SdioReadBytesFromFixedAddr
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to read.
|
addr
|
Start address where the data is read from.
|
size
|
Length of the data to read.
|
scatterLen
|
Length of the scatter list. If the value is not 0, the data is of the scatter list type.
|
Return Value
|
Description
|
0
|
Data is read from the SDIO device.
|
Negative value
|
Failed to read data from the SDIO device.
|
The following example shows how to read a given length of data from the fixed address of an SDIO device.
```
int32_t ret;
uint8_t rbuff[5] = {0};
uint32_t addr = 0x100 + 0x09;
/* Read 5-byte data from the fixed address 0x109 of the SDIO device. */
ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0);
if (ret != 0) {
HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret);
}
```
- Writes a given length of data into the address space of SDIO function 0.
Currently, only 1-byte data can be written. The corresponding function is as follows:
int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 10** Parameters and return values of SdioWriteBytesToFunc0
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to write.
|
addr
|
Start address where the data is written into.
|
size
|
Length of the data to write.
|
Return Value
|
Description
|
0
|
Data is written into the SDIO device.
|
Negative value
|
Failed to write data into the SDIO device.
|
The following example shows how to write a given length of data into the address space of SDIO function 0.
```
int32_t ret;
uint8_t wbuff = 1;
/* Write 1-byte data into the address 0x2 of SDIO function 0. */
ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1);
if (ret != 0) {
HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret);
}
```
- Reads a given length of data from the address space of SDIO function 0.
Currently, only 1-byte data can be read. The corresponding function is as follows:
int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**Table 11** Parameters and return values of SdioReadBytesFromFunc0
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
data
|
Pointer to the data to read.
|
addr
|
Start address where the data is read from.
|
size
|
Length of the data to read.
|
Return Value
|
Description
|
0
|
Data is read from the SDIO device.
|
Negative value
|
Failed to read data from the SDIO device.
|
The following example shows how to read a given length of data from the address space of SDIO function 0.
```
int32_t ret;
uint8_t rbuff;
/* Read 1-byte data from the address 0x2 of SDIO function 0. */
ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1);
if (ret != 0) {
HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret);
}
```
### Releasing the SDIO IRQ
After the SDIO communication, release the SDIO IRQ.
int32\_t SdioReleaseIrq\(DevHandle handle\);
**Table 12** Parameters and return values of SdioReleaseIrq
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
Return Value
|
Description
|
0
|
The SDIO IRQ is released.
|
Negative value
|
Failed to release the SDIO IRQ.
|
The following example shows how to release the SDIO IRQ.
```
int32_t ret;
/* Release the SDIO IRQ. */
ret = SdioReleaseIrq(handle);
if (ret != 0) {
HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret);
}
```
### Disabling the SDIO Device
After the SDIO communication, disable the SDIO device.
int32\_t SdioDisableFunc\(DevHandle handle\);
**Table 13** Parameters and return values of SdioDisableFunc
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
Return Value
|
Description
|
0
|
The SDIO device is disabled.
|
Negative value
|
Failed to disable the SDIO device.
|
The following example shows how to disable the SDIO device.
```
int32_t ret;
/* Disable the SDIO device. */
ret = SdioDisableFunc(handle);
if (ret != 0) {
HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret);
}
```
### Releasing the Exclusively Claimed Host
After the SDIO communication, release the exclusively claimed host.
void SdioReleaseHost\(DevHandle handle\);
**Table 14** Parameter description of SdioReleaseHost
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
The following example shows how to release the exclusively claimed host.
```
SdioReleaseHost(handle); /* Release the exclusively claimed host. */
```
### Closing an SDIO Controller
After the SDIO communication, close the SDIO controller.
void SdioClose\(DevHandle handle\);
This function releases the resources requested.
**Table 15** Parameter description of SdioClose
Parameter
|
Description
|
handle
|
Device handle of an SDIO controller.
|
The following example shows how to close an SDIO controller.
```
SdioClose(handle); /* Close an SDIO controller. */
```
## Usage Example
The following example shows how to use an SDIO device. First, open an SDIO controller whose bus number is 1, exclusively claim a host, enable the SDIO device, claim an SDIO IRQ, and then perform SDIO communication \(such as reading and writing\). After the SDIO communication, release the SDIO IRQ, disable the SDIO device, release the host, and close the SDIO controller.
```
#include "hdf_log.h"
#include "sdio_if.h"
#define TEST_FUNC_NUM 1 /* The I/O function whose ID is 1 is used. */
#define TEST_FBR_BASE_ADDR 0x100 /* FBR base address of the I/O function whose ID is 1 */
#define TEST_ADDR_OFFSET 9 /* Address offset of the register to read or write */
#define TEST_DATA_LEN 3 /* Length of the data to read or write */
#define TEST_BLOCKSIZE 2 /* Size of a data block, in bytes */
/* Implement the SDIO IRQ function based on the application. */
static void SdioIrqFunc(void *data)
{
if (data == NULL) {
HDF_LOGE("SdioIrqFunc: data is NULL.\n");
return;
}
/* You need to add specific implementations. */
}
void SdioTestSample(void)
{
int32_t ret;
DevHandle handle = NULL;
uint8_t data[TEST_DATA_LEN] = {0};
struct SdioFunctionConfig config = {1, 0x123, 0x456};
uint8_t val;
uint32_t addr;
/* Open an SDIO controller whose bus number is 1. */
handle = SdioOpen(1, &config);
if (handle == NULL) {
HDF_LOGE("SdioOpen: failed!\n");
return;
}
/* Claim a host exclusively. */
SdioClaimHost(handle);
/* Enable the SDIO device. */
ret = SdioEnableFunc(handle);
if (ret != 0) {
HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret);
goto ENABLE_ERR;
}
/* Claim an SDIO IRQ. */
ret = SdioClaimIrq(handle, SdioIrqFunc);
if (ret != 0) {
HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret);
goto CLAIM_IRQ_ERR;
}
/* Set the block size to 2 bytes. */
ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE);
if (ret != 0) {
HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Read 3-byte data from the incremental address of an SDIO device. */
addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET;
ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN);
if (ret != 0) {
HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Write 3-byte data into the incremental address of an SDIO device. */
ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN);
if (ret != 0) {
HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Read 1-byte data from the SDIO device. */
ret = SdioReadBytes(handle, &val, addr, 1);
if (ret != 0) {
HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Write 1-byte data into the SDIO device. */
ret = SdioWriteBytes(handle, &val, addr, 1);
if (ret != 0) {
HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Read 3-byte data from the fixed address of an SDIO device. */
ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0);
if (ret != 0) {
HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Write 1-byte data to the fixed address of an SDIO device. */
ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0);
if (ret != 0) {
HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Read 1-byte data from SDIO function 0. */
addr = 0x02;
ret = SdioReadBytesFromFunc0(handle, &val, addr, 1);
if (ret != 0) {
HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret);
goto COMM_ERR;
}
/* Write 1-byte data into SDIO function 0. */
ret = SdioWriteBytesToFunc0(handle, &val, addr, 1);
if (ret != 0) {
HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret);
goto COMM_ERR;
}
COMM_ERR:
/* Release the SDIO IRQ. */
ret = SdioReleaseIrq(handle);
if (ret != 0) {
HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret);
}
CLAIM_IRQ_ERR:
/* Disable the SDIO device. */
ret = SdioDisableFunc(handle);
if (ret != 0) {
HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret);
}
ENABLE_ERR:
/* Release the exclusively claimed host. */
SdioReleaseHost(handle);
/* Close an SDIO controller. */
SdioClose(handle);
}
```