免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1132 | 回复: 0
打印 上一主题 下一主题

s3cmci的 io开关操作分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-02 13:39 |只看该作者 |倒序浏览
s3cmci的 io开关操作分析
一 s3cmci的io操作使用的数据结构
struct mmc_ios {
类型                 名称                             值

unsigned int        clock                           时钟速率

unsigned short      vdd                             电压

unsigned char      bus_mode                      #define MMC_BUSMODE_OPENDRAIN 1
                                                 #define MMC_BUSMODE_PUSHPULL 2

unsigned char      chip_select                   #define MMC_CS_DONTCARE 0
                                                 #define MMC_CS_HIGH 1
                                                 #define MMC_CS_LOW 2

unsigned char      power_mode                    #define MMC_POWER_OFF 0
                                                 #define MMC_POWER_UP 1
                                                 #define MMC_POWER_ON 2

unsigned char       bus_width                    #define MMC_BUS_WIDTH_1 0
                                                 #define MMC_BUS_WIDTH_4 2

unsigned char       timing                      #define MMC_TIMING_LEGACY 0
                                                #define MMC_TIMING_MMC_HS 1
                                                #define MMC_TIMING_SD_HS 2
};
二 s3cmci的io操作的处理函数
static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
主要完成开电源和关电源时的各种寄存器的设置,该处理函数通过一个宿主机操作集(即一个struct mmc_host_ops结构)向MMC核心层注册自己,这样MMC核心层在需要开关电源时即通过调用注册的宿主机操作集中的.set_ios指向函数来完成.
io操作的处理函数的注册
s3cmci的宿主机操作集:
static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
.get_cd = s3cmci_card_present,
};
在s3cmci平台驱动的.probe指向的函数处理中被注册
static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
{
...
mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
...
mmc->ops = &s3cmci_ops;
...
mmc_add_host(mmc);
}
关电操作
mmc_core.c


s3cmci.c


首先调用MMC核心函数 mmc_power_off(...)在此函数设置关电时设置参数,然后经过一个内部函数mmc_set_ios(...)的转换,调用宿主机自己的set_ios函数来处理.核心层只做通用的参数设置,对于不同的硬件的处理,由具体硬件的驱动根据IO设置参数来完成实际硬件的操作.
具体的操作主要完成以几件关机操作:
关闭时钟输出管脚,S3C2410_GPE5
设置电压,如果平台设置有自己的set_power处理,则调用之,
关闭时钟.
static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
// 取得宿主机的私有数据结构.
struct s3cmci_host *host = mmc_priv(mmc);
u32 mci_psc, mci_con;


/* Set the power state */
// 读取当前宿主机的控制寄存器内容 .
mci_con = readl(host->base + S3C2410_SDICON);


switch (ios->power_mode) {
...
case MMC_POWER_OFF://
default:
// 关闭时钟输出管脚,S3C2410_GPE5 为0b10时用于SDCLK,现将其设为为0(输出)
s3c2410_gpio_setpin(S3C2410_GPE5, 0);
s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
......
// 如果平台设置有自己的set_power处理,则调用之.用于设置电压值.
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
break;
}
/******************************************************************/
/* 设置时钟 */
// 设置最大的预引比例因子, 使得宿主机的时钟频率不小于ios->clock设定的值
for (mci_psc = 0; mci_psc
host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));


if (host->real_rate clock)
break;
}
if (mci_psc > 255)
mci_psc = 255;
// 保存宿主机的预比例因子.并写寄存器.
host->prescaler = mci_psc;
writel(host->prescaler, host->base + S3C2410_SDIPRE);


/* If requested clock is 0, real_rate will be 0, too */
if (ios->clock == 0)
host->real_rate = 0;
// 判断时钟使能,如果 ios->clock设定的时钟频率为0,则关闭时钟输出.写入寄存器.
if (ios->clock)
mci_con |= S3C2410_SDICON_CLOCKTYPE;
else
mci_con &= ~S3C2410_SDICON_CLOCKTYPE;//SDCLK out disable.
// 写控制寄存器
writel(mci_con, host->base + S3C2410_SDICON);


/* 设置时钟完毕*/
/**********************************************************************/
.....
// 保存总线宽度 .
host->bus_width = ios->bus_width;
}
开电操作
mmc_core.c

s3cmci.c


static void mmc_power_up(struct mmc_host *host)
{
// 获取电压设置的低位,这样就有方法得到最低的电压.
int bit = fls(host->ocr_avail) - 1;
host->ios.vdd = bit;


if (mmc_host_is_spi(host)) {
host->ios.chip_select = MMC_CS_HIGH;
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
} else {
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
}
host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
// IO设置
mmc_set_ios(host);


// 等待到达最小的电压值.
// 等待两毫秒.
mmc_delay(2);


host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
// IO设置
mmc_set_ios(host);
// 等待至少74个时钟周期,或者一个足够的时间到达稳定电压.这里用2ms
mmc_delay(2);
}


static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
// 取得宿主机的私有数据结构.
struct s3cmci_host *host = mmc_priv(mmc);
u32 mci_psc, mci_con;


/* Set the power state */
// 读取当前宿主机的控制寄存器内容 .
mci_con = readl(host->base + S3C2410_SDICON);


switch (ios->power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
// 设置SD卡的所有IO管脚功能
s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
// 设置电压
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);


if (!host->is2440)
mci_con |= S3C2410_SDICON_FIFORESET;


break;
......
}
/******************************************************************/
/* 设置时钟 */
// 设置最大的预引比例因子, 使得宿主机的时钟频率不小于ios->clock设定的值
for (mci_psc = 0; mci_psc
host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));


if (host->real_rate clock)
break;
}
if (mci_psc > 255)
mci_psc = 255;
// 保存宿主机的预比例因子.并写寄存器.
host->prescaler = mci_psc;
writel(host->prescaler, host->base + S3C2410_SDIPRE);


/* If requested clock is 0, real_rate will be 0, too */
if (ios->clock == 0)
host->real_rate = 0;
// 判断时钟使能,如果 ios->clock设定的时钟频率为0,则关闭时钟输出.写入寄存器.
if (ios->clock)
mci_con |= S3C2410_SDICON_CLOCKTYPE;
else
mci_con &= ~S3C2410_SDICON_CLOCKTYPE;//SDCLK out disable.
// 写控制寄存器
writel(mci_con, host->base + S3C2410_SDICON);


/* 设置时钟完毕*/
/**********************************************************************/
.....
// 保存总线宽度 .
host->bus_width = ios->bus_width;
}
本文来自CSDN博客,转载请标明出处:
http://blog.csdn.net/dujie_abc/archive/2008/11/28/3401020.aspx


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/105635/showart_2109255.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP