日期:2014-05-16  浏览次数:20659 次

块设备驱动2--sd卡驱动1(linux-3.2.36的sdchi.h分析)

我的经历:

看了某些大神的说明,我胆怯地进入了drivers/mmc/host/,看过我之前的文章知道我用的是s3c2440。

看驱动时,我首先会找s3c字样,于是我注意到sdhci-s3c.c和s3cmci.c。

看了一下Kconfig

config MMC_S3C
    tristate "Samsung S3C SD/MMC Card Interface support"
    depends on ARCH_S3C2410
    help
      This selects a driver for the MCI interface found in
          Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
      If you have a board based on one of those and a MMC/SD
      slot, say Y or M here.

      If unsure, say N.

再看Makefile

obj-$(CONFIG_MMC_S3C)       += s3cmci.o

我想我用s3cmci就可以了。我就猜测s3cmci和sdhci-s3c就是寄存器不一样。但是当我看了看代码,不是这样。

记得大神说过struct mmc_host。sd驱动用到的主要结构,但是sdhci-s3c用到的是struct sdhci_host。

这是什么情况。

首先我就考虑sdhci到底是什么,我看所有sdhci-*.c驱动都用到了sdhci.c,我看到sdhci.c对寄存器操作的偏移都

是一样的,这样我想到了usb的ochi驱动。应该有个sd控制器都遵循的协议。

然后我又打开了s3c6410的datasheet

第一行 SD Standard Host很耀眼。最后我在百度找的了这个:

Part_A2_SD_Host_Controller_Simplified_Specification_Ver2.00.pdf

这个就是所说的协议,sdhci.c要实现的东西。s3c2440并不遵循这个。

先看看sdhci吧,看c之前先看.h文件分析

/*
 *  linux/include/linux/mmc/sdhci.h - Secure Digital Host Controller Interface
 *
 *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 */
#ifndef LINUX_MMC_SDHCI_H
#define LINUX_MMC_SDHCI_H

#include <linux/scatterlist.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/mmc/host.h>

struct sdhci_host {
	/* Data set by hardware interface driver */
	const char *hw_name;	/* Hardware bus name */ //硬件总线名

	unsigned int quirks;	/* Deviations from spec. */ //偏离规范

//我们看有哪些怪癖,还有代码会如何处理
/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET			(1<<0)
/*
SDHCI_QUIRK_CLOCK_BEFORE_RESET 是有的要在复位前设置时钟寄存器
会在复位前调用host->ops->set_clock(host, clock);驱动提供
*/

/* Controller has bad caps bits, but really supports DMA */
#define SDHCI_QUIRK_FORCE_DMA				(1<<1)
/*
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
就是支持SDMA
*/

/* Controller doesn't like to be reset when there is no card inserted. */
#define SDHCI_QUIRK_NO_CARD_NO_RESET			(1<<2)

/*
上面英文已说的很清楚:
没有卡插入时,控制器不想复位。
在复位时遇到这个标准,会想尝试读当前的状态,成功返回,失败进行复位。
*/

/* Controller doesn't like clearing the power reg before a change */
#define SDHCI_QUIRK_SINGLE_POWER_WRITE			(1<<3)
/*
控制器不想清除电源寄存器在一个改变MMC_VDD前。
遇到这个,直接改电源寄存器值,不清除。
*/

/* Controller has flaky internal state so reset it on each ios change */
#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS		(1<<4)
/*
在sdhci_do_set_ios()中会用到。
解释:
有些控制器在一些操作时会发疯,即使是CMD0,解决方法就是复位每一个ios.
*/

/* Controller has an unusable DMA engine */
#define SDHCI_QUIRK_BROKEN_DMA				(1<<5)
//控制器有一个无法使用的DMA引擎

//SDMA: secure DMA 
//ADMA: advanced DMA 

/* Controller has an unusable ADMA engine */
#define SDHCI_QUIRK_BROKEN_ADMA				(1<<6)
//控制器有一个无法使用的ADMA引擎

/* Controller can only DMA from 32-bit aligned addresses */
#define SDHCI_QUIRK_32BIT_DMA_ADDR			(1<<7)
//DMA要32位地址对齐

/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
#define SDHCI_QUIRK_32BIT_DMA_SIZE			(1<<8)
//DMA的大小是32的倍数

/* Controller can only ADMA chunks that are a multiple of 32 bits */
#define SDHCI_QUIRK_32BIT_ADMA_SIZE			(1<<9)
//ADMA的大小