This document discusses SD card standards and specifications. It describes the SD card pin definitions, speed modes, bus widths, and register maps. It also provides an overview of the Linux SD device driver stack, including the block driver, file systems, and individual driver components like the host controller and core driver. Code examples are provided for registering hardware resources and accessing register structures through readl/writel functions.
13. User Space
Kernel Space
Request Queue Request Queue
Kernel Space
Storage Media
File I/O File I/O
Virtual File System (VFS) Layer
Individual Filesystems (EXT3,EXT4,JFFS2,Reiserfs,VFAT, …)
Buffer Cache (Page Cache)
I/O Schedulers
Block Driver Block Driver
Disk
CD
Driver
20. What do Probe call back function
platform_get_resource()取得resource,並remap resource
Allocate DMA resources
若有用到work queue,則必需給予初始化
註冊一個中斷服務,並起始中斷服務
向上層MMC block註冊一個host MMC
1) mmc = mmc_alloc_host(priv_size, dev)
2) mmc_add_host(mmc)
3) mmc_priv(mmc)
* 在第一次註冊及後來插入SD卡時系統會掃描SD卡
20
21. MMC block device driver call back function
struct mmc_host_ops sd_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
.get_ro = sdhci_get_ro,
}; // include/linux/mmc/host.h
request
The upper MMC block device driver will send a struct mmc_request *mrq
to this. The mrq will include what want to do. When you finish this request
you must call mmc_request_done() to note upper MMC block device
driver what it is finisned. There include command or data access.
set_ios
1) Set/disable clock
2) Power on/off to offer SD card or not
3) Set SD card bus width 1 or 4
get_ro
1) To check the SD card write protect or not
21
22. Callback function prototype
struct mmc_host_ops {
void (*request)(struct mmc_host *host, struct mmc_request *req);
/*
* Avoid calling these three functions too often or in a "fast path",
* since underlaying controller might implement them in an expensive
* and/or slow way.
*
* Also note that these functions might sleep, so don't call them
* in the atomic contexts!
*
* Return values for the get_ro callback should be:
* 0 for a read/write card
* 1 for a read-only card
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
*
* Return values for the get_ro callback should be:
* 0 for a absent card
* 1 for a present card
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
*/
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
int (*get_ro)(struct mmc_host *host);
int (*get_cd)(struct mmc_host *host);
void (*enable_sdio_irq)(struct mmc_host *host, int enable);
};
24. struct mmc_command
struct mmc_command {
u32 opcode;
u32 arg;
u32 resp[4];
unsigned int flags; /* expected response type
*/
unsigned int retries; /* max number of retries */
unsigned int error; /* command error */
struct mmc_data *data; /* data segment associated
with cmd */
struct mmc_request *mrq; /* associated request */
}; // include/linux/mmc/core.h
25. struct mmc_data
struct mmc_data {
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
unsigned int timeout_clks; /* data timeout (in clocks) */
unsigned int blksz; /* data block size */
unsigned int blocks; /* number of blocks */
unsigned int error; /* data error */
unsigned int flags;
#define MMC_DATA_WRITE (1 << 8)
#define MMC_DATA_READ (1 << 9)
#define MMC_DATA_STREAM (1 << 10)
unsigned int bytes_xfered;
struct mmc_command *stop; /* stop command */
struct mmc_request *mrq; /* associated request */
unsigned int sg_len; /* size of scatter list */
struct scatterlist *sg; /* I/O scatter list */
}; // include/linux/mmc/core.h
26. scattlerlist操作
struct scatterlist {
#ifdef CONFIG_DEBUG_SG
unsigned long sg_magic;
#endif
unsigned long page_link;
unsigned int offset; /* buffer offset */
dma_addr_t dma_address; /* dma address */
unsigned int length; /* length */
};
#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
• int dma_map_sg(struct device *, struct scatterlist *, int, enum
dma_data_direction) - map a set of SG buffers for streaming mode DMA
• kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; /*virtual address */
• kunmap_atomic(buffer, KM_BIO_SRC_IRQ)
#define for_each_sg(sglist, sg, nr, __i)
for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
27. SD card insert detecting flow chart
27
Card change interrupt
happens
Add card change work
queue on interrupt
service
Insert or remove ?
Remove all
queue
Set SD clock
Call upper MMC block driver
by mmc_detect_change()
Send many command
requests to this driver to get
information from inserted
card.
remove insert
Add a new disk to file
manager.
28. Finish all data transfer ?
28
Read/Write data
Received a request from
upper block MMC driver to
transfer data. The request
callback function is called.
1. Initial user space data
context to kernel
context.
2. Set SD chipset for data
length and timeout.
Set DMA transfer
information to DMA chipset
for fist block data.
Send start transfer data
command
Interrupt generates when a
block data is transferred.
Continue to DMA transfer
information to DMA chipset
for next block data.
Send stop transfer data
command
Call upper MMC driver
request done API
Yes
No