오래전에 Linux Kernel 2.4 기준으로 TI DM320 SD Card 와 SD-IO Spec 보고,직접 Linux Device Driver를 내 마음대로 만들어 본 경험이 있다.
물론 이 때는 Chip vendor들이 Device Driver를 제공 해주지 않으니, Chip Vendor 3rd Party에서 근무했던,
내가 만들어 직접 개발하고 3rd Party에서 국내 각 회사에 공급했다.
SDCard 뿐만아니라, HDMI를 비롯하여 각종 Device Drivers(Camera/LCD/Touch/Bus/등)들을 많이 만들었는데,
우연히 예전에 정리했던 자료를 발견했으며, 그것을 오늘 간단히만 정리하려고 하며,
현재 Linux Kernel과는 너무 많이 다르므로, 참조만 하도록하자.
Device Driver 개발자 입장에서 생각해보면,
USB/PCI/HPI 각 종 Bus Device Driver를 비롯하여, PATA도 만들어보고, Video MUX를 비롯하여 각종 여러 Device Driver를 개발해봤는데,
가장 후회로 남는 것이 있다면, PCIe를 직접 개발 못해본게 좀 후회로 많이 남는다.
MMC/SD가 현재 와 많은 부분이 다를 것이며, MMC Interface 또한 많이 변경되어 왔다.
또한 MMC Host에 따라 많이 다를 것으로 예상한다.
더불어 Linux Kernel 도 버전업 되면서 , 각 Device Driver가 Platform 화 되었으므로,
더불어 Linux Kernel 도 버전업 되면서 , 각 Device Driver가 Platform 화 되었으므로,
이전과는 구조가 다르므로 주의하자.
1.1 SD/MMC Driver 기본전체구성
전체 TI의 MMC&SD Device Driver는 크게 3 부분으로 구분이 되고,Core 모듈과 MMC Block 모듈 그리고, 하드웨어에 종속적인 모듈로 구성이 된다.
만약 MMC&SD카드 Driver을 작성하고자 한다면, 전체 Driver를 작성할 필요 없이 mmc_hardware 부분 소스만 TI의 Datasheet를 보고 새로 작성을 하면된다.
1.2 MMC & MMC_BLOCK 구성
MMC/SD Driver는 SD Card를 Hard disk Driver와 유사하게 인식을 하며, 그래서 기본적인 구성은 Hard disk의 Block Device Driver의 기본구조 유사하다.
이전에 FPGA관련 PATA Block Device driver도 직접 만들었 본 경험이 있어 볼 때마다 재미있다.
SD/MMC Block device driver의 구성은 다음과 같다
중요함수: register_blkdev(major, "mmc");
중요함수: unregister_blkdev(major, "mmc");
이전에 MMC Device Driver (SD Card / SD IO)를 Linux에서 직접구현하면서 간단히 정리 한 후 만든 간단히 도표이며,
나의 경우는 아래와 같이 Polling 모드로 동작하는 구조구현을 했다.
- MMC&SD Card Driver 위치
Kernel/driver/mmc
1.1 SD/MMC Driver 기본전체구성
전체 TI의 MMC&SD Device Driver는 크게 3 부분으로 구분이 되고,Core 모듈과 MMC Block 모듈 그리고, 하드웨어에 종속적인 모듈로 구성이 된다.
만약 MMC&SD카드 Driver을 작성하고자 한다면, 전체 Driver를 작성할 필요 없이 mmc_hardware 부분 소스만 TI의 Datasheet를 보고 새로 작성을 하면된다.
- MMC_CORE (MMC 공통사항)
Files: mmc.c mmc_queue.c mmc_sysfs.c Description: mmc_block에서 등록이 된, Device들을 초기화 하고, MMC&SD Spec에 관한 Function 및 Hotplug에 관한 Function으로 구성이 되어있다.
- MMC_BLOCK ( block device driver)
Files: mmc_block.c Description: mmc & sd card block device driver 함수들이 존재 한다. mmcblk의 block device 관련 함수들이 존재 한다.
- mmc_hardware ( TI DM320 관련부분)
Files: dm320_mmc.c Description: 실제적인 MMC & SD Card Driver이며, Hardware에 종속적인 소스들로만 구성이 되어있다. 이 부분은 아래에서 자세히 다루겠다.
1.2 MMC & MMC_BLOCK 구성
MMC/SD Driver는 SD Card를 Hard disk Driver와 유사하게 인식을 하며, 그래서 기본적인 구성은 Hard disk의 Block Device Driver의 기본구조 유사하다.
이전에 FPGA관련 PATA Block Device driver도 직접 만들었 본 경험이 있어 볼 때마다 재미있다.
SD/MMC Block device driver의 구성은 다음과 같다
- static int __init mmc_blk_init(void)
중요함수: register_blkdev(major, "mmc");
- static void __exit mmc_blk_exit(void)
중요함수: unregister_blkdev(major, "mmc");
- static int mmc_blk_probe(struct mmc_card *card)
mmc_blk_alloc *alloc_disk *mmc_init_queue *blk_init_queue() (request 함수를 등록을 한다.) *mmc_queue_thread (mmc_queue thread 시작) *md->block_bits = 9; // 2G 이상 지원 (이 부분만 수정하면, 2G 이상 지원) *blk_queue_hardsect_size(Sector 크기 설정) *set_capacity (block 수 설정) *md->queue.prep_fn = mmc_blk_prep_rq; *md->queue.issue_fn = mmc_blk_issue_rq; (MMC Request 함수)
- static void mmc_blk_remove(struct mmc_card *card)
- static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
- static int mmc_blk_resume(struct mmc_card *card)
이전에 MMC Device Driver (SD Card / SD IO)를 Linux에서 직접구현하면서 간단히 정리 한 후 만든 간단히 도표이며,
나의 경우는 아래와 같이 Polling 모드로 동작하는 구조구현을 했다.
- DM320 MMC Block Device Driver 내부동작
mmc_queue_thread (Block Device Request 함수) *mmc_blk_issue_rq (실제적인 Request 함수) blk_rq_map_sg (block driver의 make_request 함수) MMC_READ_MULTIPLE_BLOCK *mmc_wait_for_read_data() *read_from_card() MMC_WRITE_MULTIPLE_BLOCK *mmc_wait_for_write_data() *write_from_card()
위에서 전체 Block Device Driver의 Flow을 보면 동작방식은 간단히 다음과 같다.
- Block Device Driver를 등록하고, blk_init_queue 함수를 이용하여 request 함수를 등록한다.
- Kernel Queue Thread를 생성하고 항시 mmc_request가 오기를 항상 대기한다.(무한 루프)
- 커널에서 mmc_request 요청이 오면, 멈춰 있던 Kernel Thread를 작동시킨다.
- 커널에서 요청한 Request Function을 수행을 한다( Read & Write)
1.3 DM320 MMC/SD Device Driver
앞서 말한 것와 같이 MMC/SD Device Driver는 Hardrware 부분의 종속된 부분만 구현하면 되지만,
이전에 Dm320는 다른부분(mmc.c 및 기타부분)도 같이 보완해서 구현했다.
그리고, 추후에 WIFI를 위해서 SDIO를 지원하기 위해서 다른부분도 넣고 수정했는데, 거의 10년 전일이라 정리를 못하겠다.
그리고, 추후에 WIFI를 위해서 SDIO를 지원하기 위해서 다른부분도 넣고 수정했는데, 거의 10년 전일이라 정리를 못하겠다.
이 부분은 문서는 Linux에서 제공하는 Platform에 맞추어 Porting하는 부분으로 구성하였다.
추후 다시 구현하거나 수정할 기회가 있다면 그때 정리하자
Kernel에서 요청하는 Page 수를 크게 하고 싶다면, 아래의 Segments 값을 변경을 하면되지만,
- Linux에서 구현해야 할 함수 및 설정
static struct mmc_host_ops< .request = mmc_request //MMC Request 이 전체의 Block Device의 실제적인 Request .set_ios = mmc_set_ios //Hardware Setting Init혹은 Voltage 설정. Bus width설정. Power 설정. Busmode .get_ro = get_write_protect_status //ReadOnly 지원할 경우 static struct device_driver .bus = &platform_bus_type, .probe = mmc_probe, //MMC Host 에 관련된 초기화 설정 .remove = mmc_remove, .suspend = NULL, .resume = NULL,
Kernel에서 요청하는 Page 수를 크게 하고 싶다면, 아래의 Segments 값을 변경을 하면되지만,
변경시 한번에 전송하는 사이즈 값이 커진다. (주의: DMA 크기문제)
세부 구현 내용은 다른 소스를 참고하며 각 Chip Maker마다 다르므로 Datasheet를 보고 동작원리를 파악하자
1.4 Kernel 설정 및 MMC device 설정
Kernel의 Config 생성 및 설정 및 설치 (Module설정시 변경)
상위와 같이 Kernel을 update 한 후 Board에서 SD Card를 삽입을 하고, SD Card의 Partition Table을 확인한 후 Device file을 확인.
Linux는 SD Card를 Hard disk처럼 인식하기 때문에, 반드시 SD Disk내에 Partition Table이 존재.
1.5 TI DM320 관련설정 부분
2. 다른 MMC/SD Driver 구조 (drivers/mmc )
MMC interface는 card or sdio 같은 소스를 사용하기에, 크게 수정할 일 없었으나,Host쪽 설정과 인식문제를 부분이 있어 이를 해결을 해야 할 것 같다.
(추후 시간이 있을 경우 최신것을 보도록 하자)
각 vendor에서 제공을 하며, MCU에 의존적으로 설정
sd card의 독립적인 모듈로 block device driver 구조로 각 thread queue를 사용하여 sd disk를 운영
각 bus 및 interface 관련소스들로 구성이 되어있다. (SDIO 및 SD 기본 interface)
2.1 MMC/SD 관련 함수
2.2 MMC/SD Register 구조
SD는 CMD로 Host와 Device와 통신을 하며, 아래와 같이 Host에 Registers 존재하며,Device에 역시 이에 관련된 Register들이 존재한다. 이부분은 Spec을 참조.
위 Register는 SDIO 로 갈 경우 조금씩 달라지며, 각각의 최신 Spec를 참조.
mmc->max_hw_segs = 64; //DMA Size 주의 mmc->max_phys_segs = 64; mmc->max_sectors = 128; // MAX Segments 값
- Linux에서 각 함수 동작순서
mmc_alloc_host mmc_rescan mmc_claim_host mmc_check_cards mmc_setup mmc_power_up mmc_idle_cards mmc_send_op_cond //OCR Register Read , 아래 참조 mmc_discover_cards //ALL_CID & SEND_RELATIVE_ADDRESS mmc_read_csds // CSD Register Read mmc_read_scrs // SCR Register Read src_read init_clocks // 변경 25MHz , SDIO일 경우는 50MHz mmc_calculate_clock mmc_release_host
세부 구현 내용은 다른 소스를 참고하며 각 Chip Maker마다 다르므로 Datasheet를 보고 동작원리를 파악하자
1.4 Kernel 설정 및 MMC device 설정
Kernel의 Config 생성 및 설정 및 설치 (Module설정시 변경)
>make menuconfig Device Drivers->MMC/SD Card support-> MMC support [*] MMC debugging MMC block device driver [*] Write work-around for incompatible cards [*] Multi-block writes (EXPERIMENTAL) < > Winbond W83L51xD SD/MMC Card Interface support < > TI DAVINCI Multimedia Card Interface support TI DM320 Multimedia Card In > make modules > make modules_install
상위와 같이 Kernel을 update 한 후 Board에서 SD Card를 삽입을 하고, SD Card의 Partition Table을 확인한 후 Device file을 확인.
Linux는 SD Card를 Hard disk처럼 인식하기 때문에, 반드시 SD Disk내에 Partition Table이 존재.
- Partition Table 확인
> cat /proc/partitions 254 0 249856 mmcblk0 254 1 249805 mmcblk0p1 >ls /dev/mmcblk* //device node 확인 //만약 없다면, Device File 없다면,새로 생성 > # mknod /dev/mmcblk0 b 254 0 > # mknod /dev/mmcblk0p1 b 254 1 //만약 Partition Table이 존재 하지 않는다면, 다음과 같이 fdisk를 이용하여 만들어 준다. > fdisk /dev/mmcblk0 //FileSystem이 없다면, FAT 혹은 EXT2,3를 Format >mkefs /dev/mmcblk0p1 or mkfs.ext2 >mount /dev/mmcblk0p1 /mnt/sd0
1.5 TI DM320 관련설정 부분
- /mmc/dm320_mmc.c/init_clocks 함수 (clock 설정 , SDCard 와 SDIO는 25MHz/50MHz)
- Clock Controller - INV Register 설정.
- Clock Controller - DIV3 Register
- MMC/SD Interface - MMCCLK Register
- MMC/SD Interface 와 Memory Stick Controller
- Clock Controller – MOD2
2. 다른 MMC/SD Driver 구조 (drivers/mmc )
MMC interface는 card or sdio 같은 소스를 사용하기에, 크게 수정할 일 없었으나,Host쪽 설정과 인식문제를 부분이 있어 이를 해결을 해야 할 것 같다.
(추후 시간이 있을 경우 최신것을 보도록 하자)
- host (이외 HOST, MCU에 의존적인 소스이며 설정소스 )
각 vendor에서 제공을 하며, MCU에 의존적으로 설정
- card ( block device driver)
sd card의 독립적인 모듈로 block device driver 구조로 각 thread queue를 사용하여 sd disk를 운영
- core ( sd card, mmc card, sdio interface 및 기본 interface)
각 bus 및 interface 관련소스들로 구성이 되어있다. (SDIO 및 SD 기본 interface)
- 관련 headers
2.1 MMC/SD 관련 함수
- Core interface 주요 함수 및 구조체
drivers/mmc/core/core.h struct mmc_bus_ops { // 각 sd, mmc, sdio bus function int (*awake)(struct mmc_host *); int (*sleep)(struct mmc_host *); void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); int (*suspend)(struct mmc_host *); int (*resume)(struct mmc_host *); int (*power_save)(struct mmc_host *); int (*power_restore)(struct mmc_host *); }; mmc_wait_for_cmd() 함수 // SD Interface Command 함수 , 이 함수를 이용하여 host에서 command를 보낸다.
- Host interface 주요 함수 및 구조체
ex) const struct mmc_host_ops static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, // SD Card Block Device의 Request 함수 .set_ios = sdhci_set_ios, // Hardware Setting Init혹은 Voltage 설정. Bus width설정. Power 설정. Busmode .get_ro = sdhci_get_ro, //ReadOnly 지원할 경우 .hw_reset = sdhci_hw_reset, .enable_sdio_irq = sdhci_enable_sdio_irq, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .execute_tuning = sdhci_execute_tuning, .enable_preset_value = sdhci_enable_preset_value, }; static struct platform_driver sdhci_s3c_driver = { .probe =sdhci_s3c_probe, // mmc_alloc_host 이 호출되며, Device 인식 및 등록이 되므로 중요. .remove = __devexit_p(sdhci_s3c_remove), .suspend = sdhci_s3c_suspend, .resume = sdhci_s3c_resume, .driver = { .owner = THIS_MODULE, .name = "s3c-sdhci", }, };
- Host interface의 Probe 함수 SD Interface 인식
mmc_alloc_host (host_ops 의 probe 에서 mmc_alloc_host 호출) >mmc_rescan >mmc_rescan_try_freq >mmc_power_up >mmc_hw_reset_for_init >sdio_reset >mmc_attach_sdio (3 중 하나로 mmc_bus_ops 등록 ) or mmc_attach_sd or mmc_attach_mmc or mmc_power_off
2.2 MMC/SD Register 구조
SD는 CMD로 Host와 Device와 통신을 하며, 아래와 같이 Host에 Registers 존재하며,Device에 역시 이에 관련된 Register들이 존재한다. 이부분은 Spec을 참조.
- SD Host Controller Register Map
- SD Device Registers (SD Card)
위 Register는 SDIO 로 갈 경우 조금씩 달라지며, 각각의 최신 Spec를 참조.
- OCR: Card의 Voltage Status 및 High Capacity or Standard Capacity 인지를 나타낸다. (Response)
- CID: Card의 관련 제조사의 정보가 있다.
- CSD: Card의 핵심 레지스터 군들이 모두 이곳에 있다. (자세한 내용은 Spec) (Read &Write Block size, Transfer Speed , etc )
- SCR: Card의 Data bus width, SD Spec Version, Security 지원여부를 나타낸다.
- RCA: Card의 Relative Card Address. (Host가 설정.)
- SSR: Card의 Status (Card의 설정된 정보 Card Type, Speed Class, Data bus width)
- CSR: Card의 Status (Card의 Error Check & Card의 State)