行業資訊

您所在的位置:首頁 > 關於杏吧 > 行業資訊
攻城獅解析丨時鍾使用之注冊和獲取(一)
發布人:管理員   發布時間:2019/8/30 11:53:04

我們在編寫或修改驅動時,經常會遇到時鍾相關的問題,不知道從什麼地方下手。在本文中,以i.MX6的3.0.35版本的內核舉例時鍾如何獲取和使用。

 

我們常見的獲取時鍾的方法
❶ 通過名稱獲取

例如:獲取時鍾clko

clko = clk_get(NULL, "clko_clk");

❷ 通過設備獲取

例如在音頻接口ssi的驅動中獲時鍾,

ssi->clk = clk_get(&pdev->dev, NULL); //設備的名字是 "imx-ssi"

我們可以通過查看函數clk_get的原型來進一步查看始終是怎麼獲取的

struct clk *clk_get(struct device *dev, const char *con_id)

 { 

       const char *dev_id = dev ? dev_name(dev) : NULL;

 

        return clk_get_sys(dev_id, con_id);

 }

我們繼續查看函數clk_get_sys,此函數通過設備的名字或時鍾的名字來獲取時鍾

struct clk *clk_get_sys(const char *dev_id, const char *con_id)

 {

        struct clk_lookup *cl;

 

        mutex_lock(&clocks_mutex); 

        cl = clk_find(dev_id, con_id);

        if (cl && !__clk_get(cl->clk))

                cl = NULL;

        mutex_unlock(&clocks_mutex);

 

        return cl ? cl->clk : ERR_PTR(-ENOENT);

 }

此函數調用clk_find獲取時鍾,在時鍾列表內按照設備名和時鍾名查找,並返回獲取到的時鍾。

static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)

{

        struct clk_lookup *p, *cl = NULL;

        int match, best = 0;

 

        list_for_each_entry(p, &clocks, node) {

                match = 0;

                if (p->dev_id) {

                        if (!dev_id || strcmp(p->dev_id,dev_id))

                                continue;

                        match += 2;

                } // 先找設備名

                if (p->con_id) {//再找時鍾名

                        if (!con_id || strcmp(p->con_id,con_id))

                                continue;

                        match += 1;

                }

 

                if (match > best) {

                        cl = p;

                        if (match != 3)

                                best=match;

                        else

                                break;

                }

        }

        return cl;}

時鍾的注冊

剛才提到了從時鍾列表內按照設備或時鍾名稱獲取時鍾,時鍾列表是怎麼生成的。

我們在i.Mx6板級文件初始化裏調用了時鍾初始化函數。

static void __init mx6_sabresd_timer_init(void)

{

        struct clk *uart_clk;

#ifdef CONFIG_LOCAL_TIMERS

        twd_base = ioremap(LOCAL_TWD_ADDR,SZ_256);

        BUG_ON(!twd_base);

#endif

        mx6_clocks_init(32768, 24000000, 0, 0);

 

        uart_clk = clk_get_sys("imx-uart.0", NULL);

        early_console_setup(UART1_BASE_ADDR, uart_clk);

}

我們查看mx6_clocks_init函數

int __init mx6_clocks_init(unsigned long ckil, unsigned long osc,

        unsigned long ckih1, unsigned long ckih2)

{

       …

        for (i = 0; i < ARRAY_SIZE(lookups); i++){

                clkdev_add(&lookups[i]);

                clk_debug_register(lookups[i].clk);

        }

….

 }   

先看函數內lookups數組內定了許多時鍾

static struct  clk_lookup lookups[] = {

    ……

_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk),

        _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk),

        _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk),

_REGISTER_CLOCK(NULL, "clko_clk", clko_clk),

……

}

clk_lookup的定義

struct clk_lookup {

        struct list_head        node;

        const char              *dev_id;

        const char              *con_id;

        struct clk              *clk;

  };

clk_lookup的賦值

#define _REGISTER_CLOCK(d, n, c) \

        { \

                .dev_id = d, \

                .con_id = n, \

                .clk = &c, \

        }

再看函數clkdev_add

void clkdev_add(struct clk_lookup *cl){

        mutex_lock(&clocks_mutex);

        list_add_tail(&cl->node, &clocks);

        mutex_unlock(&clocks_mutex);

}

由此我們可以發現mx6_clocks_init函數將數組lookups內的時鍾,全部添加到了鏈表clocks內。我們再通過第一步的方法獲取lookups內定義的時鍾。

 


 

----   END   ----


 長按識別二維碼加關注 

杏吧嵌入式

專注於智能設備核心平台研發與製造


■ 關注“杏吧嵌入式”公眾號,不定期分享行業幹貨及產品一線資料。

■ 直接微信回複產品平台,如“LS1043A”,即可快速獲取對應產品信息。

■ 想要了解杏吧更多信息,歡迎與我們聯係:

銷售工程師:400-699-6866

國際業務部:0312-3102650-854

技術服務部:0312-3119192

方案定製類:17713286015 (杜工),18633238067(王工 

■ 實時技術支持:

AM 9:00―11:30,PM 13:30―17:00(周一至周五)

 

推薦閱讀

您所在的位置:首頁 > 關於杏吧 > 行業資訊



長文分享丨TI AM5718的PRU開發詳解
再見了,省界收費站!LS1012A助力新型RSU(路側單元)實現
站在風口上,邊緣計算牽手LS1043A開發板
解鎖新技能!iMXRT1052核心板支持操作係統RT-Thread
未來觸手可及,智慧燈杆掀起“城市信息革命”IOT風向標丨智慧城市呼喚智能建築
小巧嵌入式平台“玩轉”大型的數據庫管理係統
杏吧幹貨丨芯片在不同電平電路中的應用
無人機在智能交通領域的應用大盤點!
杏吧嵌入式丨我們是如何解決TVS管使用錯誤的
LS1012A丨一文看懂何謂“低耗高速佼佼者”
穩定壓倒一切,開發板電源架構解析之IMX6UL
杏吧嵌入式 S5P4418 核心板為自助加油係統“加油”
小白也能玩轉 i.MX6 平台的 GPIO 應用筆記


Copyright © 2007-2015 保定杏吧嵌入式技術有限公司 All Rights Reserved  冀ICP備12004394號