免费注册 查看新帖 |

Chinaunix

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

linux驱动的clk问题请教 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-08 19:17 |只看该作者 |倒序浏览
为什么很多模块 比如SPI  ADC在驱动probe中,都有个clk_get  clk_enable()  等函数?难道系统启动后,这些外围器件的时钟都是关闭的?需要开启?

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
2 [报告]
发表于 2011-12-08 20:19 |只看该作者
回复 1# jlinkv8


    系统启动的时候暂时不需要的时钟是disable的,需要的时候enable.
  1. /* We must be careful disabling the clocks we are not intending to  
  2.      * be using at boot time, as subsystems such as the LCD which do  
  3.      * their own DMA requests to the bus can cause the system to lockup  
  4.      * if they where in the middle of requesting bus access.  
  5.      *  
  6.      * Disabling the LCD clock if the LCD is active is very dangerous,  
  7.      * and therefore the bootloader should be careful to not enable  
  8.      * the LCD clock if it is not needed.  
  9.     */   
  10.    
  11.     /* install (and disable) the clocks we do not need immediately */  
复制代码

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
3 [报告]
发表于 2011-12-08 20:23 |只看该作者

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
4 [报告]
发表于 2011-12-08 22:40 |只看该作者
不同的device要求运行的频率不一样, 需要配置。
如果ADC采样频率6M,ADC的configuration register里prescaler就要配置成6M;在linux就是用clock framwork实现的。你就要调用clk_get()得到时钟数据结构,对其进行配置

论坛徽章:
0
5 [报告]
发表于 2011-12-09 09:55 |只看该作者
回复 2# embeddedlwp


    你好。我现在用at91sam9261
   内核代码
clk_get(NULL "spi_clock")
/* clocks cannot be de-registered no refcounting necessary */
struct clk *clk_get(struct device *dev, const char *id)
{
        struct clk *clk;

        list_for_each_entry(clk, [b]&clocks, node) {
                if (strcmp(id, clk->name) == 0)
                        return clk;
                if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
                        return clk;
        }

        return ERR_PTR(-ENOENT);
}
&clocks:
这个clock时钟数组竟然没有定义。在mach-at91sam9200中的clock.c中找不到。那不是等于获取时钟失败,退出吗?
这个数组只有这个:

/* --------------------------------------------------------------------
*  Clocks
* -------------------------------------------------------------------- */

/*
* The peripheral clocks.
*/
static struct clk pioA_clk = {
        .name                = "pioA_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_PIOA,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk pioB_clk = {
        .name                = "pioB_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_PIOB,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk pioC_clk = {
        .name                = "pioC_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_PIOC,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk adc_clk = {
        .name                = "adc_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_ADC,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart0_clk = {
        .name                = "usart0_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US0,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart1_clk = {
        .name                = "usart1_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US1,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart2_clk = {
        .name                = "usart2_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US2,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk mmc_clk = {
        .name                = "mci_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_MCI,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk udc_clk = {
        .name                = "udc_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_UDP,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk twi_clk = {
        .name                = "twi_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_TWI,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk spi0_clk = {
        .name                = "spi0_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_SPI0,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk spi1_clk = {
        .name                = "spi1_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_SPI1,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk ohci_clk = {
        .name                = "ohci_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_UHP,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk ether_clk = {
        .name                = "ether_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_EMAC,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk isi_clk = {
        .name                = "isi_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_ISI,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart3_clk = {
        .name                = "usart3_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US3,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart4_clk = {
        .name                = "usart4_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US4,
        .type                = CLK_TYPE_PERIPHERAL,
};
static struct clk usart5_clk = {
        .name                = "usart5_clk",
        .pmc_mask        = 1 << AT91SAM9260_ID_US5,
        .type                = CLK_TYPE_PERIPHERAL,
};

static struct clk *periph_clocks[] __initdata = {
        &pioA_clk,
        &pioB_clk,
        &pioC_clk,
        &adc_clk,
        &usart0_clk,
        &usart1_clk,
        &usart2_clk,
        &mmc_clk,
        &udc_clk,
        &twi_clk,
        &spi0_clk,
        &spi1_clk,
        // ssc
        // tc0 .. tc2
        &ohci_clk,
        &ether_clk,
        &isi_clk,
        &usart3_clk,
        &usart4_clk,
        &usart5_clk,
        // tc3 .. tc5
        // irq0 .. irq2
};

论坛徽章:
0
6 [报告]
发表于 2011-12-09 11:11 |只看该作者
回复 4# linuxfellow


    要怎么才知道,开始时候,哪些外围已经使能,哪些没有使能。已经使能的 是不是不需要再enable()了

论坛徽章:
0
7 [报告]
发表于 2014-05-05 21:40 |只看该作者
为什么时钟使能函数clk_enable(struct clk *){  return 0},他的函数体内只有一条语句 return 0;他是怎么办到使能的;求解;

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
8 [报告]
发表于 2014-05-06 09:41 |只看该作者
本帖最后由 arm-linux-gcc 于 2014-05-07 10:38 编辑

挂在local bus上的设备,工作时钟是local bus提供的,在设备内部一般还会对这个时钟再进行分频和倍频(以便达到自己对时钟的特殊需求)

例如apb总线,设备为uart,总线时钟进入uart内部,再经过uart自身的分频倍频电路就得到了波特率
然而分频和倍频系数是需要按照datasheet上的公式来计算,现在已知公式、已知波特率(由app传进给driver,如115200)、还需要知道apb总线频率才能够计算出分频和倍频系数
所以需要使用clk_get得到struct clk*,然后再调用clk_get_rate得到uart所在总线(apb)的频率


你的内核版本是什么?
因为clk这一块旧内核和新内核变化挺大的,旧内核这一块实现的很乱,较新的内核已经把clk这一块整理的非常好了。
所以需要知道你的内核版本才好回答的问题





您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP