 Linux 內(nei)核(he)驅(qu)動 - ADC 驅(qu)動
							時間:2018-03-14      來源:基于Linux adc 驅動(dong)實(shi)現
							Linux 內(nei)核(he)驅(qu)動 - ADC 驅(qu)動
							時間:2018-03-14      來源:基于Linux adc 驅動(dong)實(shi)現 
							1. ADC內核驅動實現框架
ADC 內(nei)(nei)核(he)(he)驅(qu)(qu)動的(de)實現是基于 ARM ADC BSP 驅(qu)(qu)動 與(yu) Linux 內(nei)(nei)核(he)(he)驅(qu)(qu)動的(de)框架進(jin)行(xing)銜接,主要分為以下幾個部分構(gou)成:
在底層采(cai)用(yong)的 Linux 內核(he)設備模型,基于 platform 平臺(tai)總線
在(zai) VFS 層使用的是 Linux 內核字(zi)符(fu)設備驅動框架,用于實現 VFS 層 相應的驅動訪問接口
2. ADC 內核驅動 platfrom 總線實現
2.1 platfrom 總線的注冊
基于 platfrom 總線部分,主要用于銜接 BSP 驅動 與上層(ceng)的 字(zi)符設備(bei)驅動的訪問接口.
 platfrom 總線實現包含驅動描述與設備描述,其中設備描述在 Linux 內核設備樹中描述. 需要在 exynos4412-fs4412.dts 中添加如下描述
  adc@126c0000{
 compatible        = "Samsung,exynos4412-adc"; reg  = <0x126c0000 0x20>;
 adc-io-channer    = <3>;
 clocks            = <&clock 326>;
  clock-names       = "adc"; interrupt-parent = <&combiner>;
  interrupts           = <10 3>;
  = "okay";            status      
  };
platfrom 驅動描述結構定義(yi)如下:
 
  在上述結構中, of_match_table 成員的描述如下:
 #if defined(CONFIG_OF)
  static const struct of_device_id exynos_adc_dt_ids[] = {
  { .compatible = "Samsung,exynos4412-adc" },
 { /* sentinel */ },
 };
  MODULE_DEVICE_TABLE(of, exynos_adc_dt_ids);
 #endif
  在 platfrom 平臺總線注冊與卸載 ADC 驅動,具體代碼如下:
 int adc_device_init(void)
 {
 //注冊  platfrom driver
  return platform_driver_register(&exynosadc_driver);
 }
 void adc_device_exit(void)
  {
 //卸載  platfrom driver
  return platform_driver_unregister(&exynosadc_driver);
 }
2.1 probe 函數的(de)實現
在(zai) probe 實現(xian)以下功能:
分配 adc 設(she)備描述(shu)結構體(ti)的空(kong)間獲取 platfrom 驅動私有數(shu)據(ju)
申(shen)請中斷資源
獲取(qu)IO內存資源
申請(qing)IO資(zi)源的使用
寄存器地址(zhi)的映(ying)射獲(huo)取 ADC 的通道注冊 ADC 字符(fu)設備初始化等(deng)待隊列
在 remove 函數中(zhong)主(zhu)要實現相關(guan)資源(yuan)的(de)釋放
2.2.1 adc 設備描述與內存分配(pei)
在(zai) Linux 內核中描述 ADC 使(shi)用下面(mian)的結構(gou),這是我們(men)自(zi)己定義的:
struct adc_device
{
void *reg;//寄存(cun)器映射地(di)址int major_num;//主設備號(hao)(hao)int irq_num;//中斷號(hao)(hao)
int adc_data;//adc 設備(bei)數(shu)據
int io_channer;//io 通 道
struct clk *adc_clk;//adc 時(shi)鐘資源
struct resource *res;//adc io 資(zi) 源
struct class *cls;//adc 設備類
struct device *dev;//adc 設(she)備對(dui)象(xiang)
struct cdev cdev;//adc 字符設備對象
wait_queue_head_t read_event_wait;//等(deng)待隊(dui)列頭
};
在分配 adc 結構(gou)體時,使用的是(shi) kzalloc 函(han)數(shu),具體實現(xian)如下(xia):
 
2.2.2 設置 platform 平臺私有數據
獲取 platform 私有數據(ju),需(xu)要(yao)調(diao)用(yong) platform_set_drvdata 數據(ju)
static inline void platform_set_drvdata(struct platform_device
*pdev,void *data)
@param pdev : platform 平臺總(zong)線設備描述結構
@param data : 需要(yao)存儲的
這里主要是將對應(ying)的(de) struct adc_device 對象的(de)地址存儲在 struct device 結構體中(zhong)的(de)
driver_data 成員中,方便其他函數(shu)訪(fang)問(wen),主要是(shi)針對(dui)有過平臺設備時(shi),不同(tong)的平臺設備有不同(tong)
的結構來描述(shu),在(zai)匹配成功之后要進行區分
2.2.3 獲取中斷資源
這里獲(huo)取中斷資源主要是獲(huo)取中斷號,通過 platform_get_irq 函數來實(shi)現
padc->irq_num = platform_get_irq(pdev, 0);
if(padc->irq_num < 0){
printk("Fail to platform_get_irq\n");
ret = padc->irq_num;
goto err_platform_get_irq;
}
2.2.4 獲取 IO 內存資源
這里獲(huo)取(qu)的(de)資源為 ADC 寄存器(qi)的(de)資源,具體代碼如下:
  
在設備樹已經(jing)有相應的描述
2.2.5 IO資源的(de)占用
在 Linux 內核中,相應的(de)寄存器資源需要申請(qing)才能使用,一旦(dan)申請(qing)成功之后,則不允許別(bie)人來訪問這段空(kong)間(jian).
一般在(zai)映射(she)寄存器地址空間(jian)之前,就需(xu)要(yao)申請,這里需(xu)要(yao)調用(yong) ****
#define request_mem_region(start,n,name)
@param start : 申請(qing)資源開(kai)始(shi)的地址
@param n : 申請資源的(de)長度(du)
@param name : 申請的資源(yuan)的設(she)備的名字(zi)
具體實現如下:
if(!request_mem_region(padc->res->start,io_resource_size,pdev->name))
{
printk("Fail to request_mem_region\n"); ret = -EBUSY;
goto err_request_mem_region;
當需(xu)(xu)要解除相應的 IO 資源時,則需(xu)(xu)要調(diao)用 release_resource 函數(shu)
int release_resource(struct resource *old)
參數:
@param resource : 指(zhi)定 adc 資源結構對象的指(zhi)針
2.2.6 獲取(qu) adc 的數據通道
adc 的數據通(tong)道是(shi)在(zai)(zai)設備樹中進行描(miao)述,在(zai)(zai)這里(li)只是(shi)獲取(qu),具體(ti)需要調用:
of_property_read_u32(pdev->dev.of_node, "adc-io-channer", &padc->io_cha
nner);
由于(yu)(yu)文(wen)章(zhang)字數有限,更多基(ji)于(yu)(yu)Linux adc 驅(qu)動實現(xian)文(wen)章(zhang)請添加QQ:(1912904432)索要完(wan)整(zheng)版文(wen)章(zhang)

