目錄
一、?pinctrl和gpio子系統(tǒng)
1.pinctrl子系統(tǒng)
1.1 pinctrl子系統(tǒng)簡介
1.2 pinctrl子系統(tǒng)驅(qū)動(dòng)
1.3 設(shè)備樹中添加pinctrl節(jié)點(diǎn)模版
2. gpio子系統(tǒng)
2.1 gpio子系統(tǒng)簡介
2.2 gpio子系統(tǒng)驅(qū)動(dòng)
2.3 gpio子系統(tǒng)API函數(shù)
2.4 設(shè)備樹中添加gpio節(jié)點(diǎn)模板
2.5 與gpio相關(guān)的OF函數(shù)
3. 驅(qū)動(dòng)程序編寫
3.1 驅(qū)動(dòng)入口函數(shù)
3.2 驅(qū)動(dòng)出口函數(shù)
一、?pinctrl和gpio子系統(tǒng)
Linux 是一個(gè)龐大而完善的系統(tǒng),尤其是驅(qū)動(dòng)框架,像 GPIO 這種最基本的驅(qū)動(dòng)不可能采用“原始”的裸機(jī)驅(qū)動(dòng)開發(fā)方式。Linux 內(nèi)核提供了 pinctrl 和 gpio 子系統(tǒng)用于GPIO 驅(qū)動(dòng),
Linux 驅(qū)動(dòng)講究驅(qū)動(dòng)分離與分層,pinctrl 和 gpio 子系統(tǒng)就是驅(qū)動(dòng)分離與分層思想下的產(chǎn)物
要先設(shè)置某個(gè) PIN 的復(fù)用功能、速度、上下拉等,然后再設(shè)置 PIN 所對(duì)應(yīng)的 GPIO。其實(shí)對(duì)于大多數(shù)的 32 位 SOC 而言,引腳的設(shè)置基本都是這兩方面,因此 Linux 內(nèi)核針對(duì) PIN 的配置推出了 pinctrl 子系統(tǒng),對(duì)于 GPIO的配置推出了 gpio 子系統(tǒng)。
1.pinctrl子系統(tǒng)
1.1 pinctrl子系統(tǒng)簡介
-
pinctrl 子系統(tǒng)主要工作內(nèi)容如下:
①、獲取設(shè)備樹中 pin 信息。
②、根據(jù)獲取到的 pin 信息來設(shè)置 pin 的復(fù)用功能
③、根據(jù)獲取到的 pin 信息來設(shè)置 pin 的電氣特性,比如上/下拉、速度、驅(qū)動(dòng)能力等。
1.2 pinctrl子系統(tǒng)驅(qū)動(dòng)
-
PIN配置信息詳解
要使用pinctrl子系統(tǒng),需要在設(shè)備樹里設(shè)置PIN的配置信息,pinctrl子系統(tǒng)會(huì)根據(jù)提供的信息去配置PIN功能,一般會(huì)在設(shè)備樹里創(chuàng)建一個(gè)節(jié)點(diǎn)來描述PIN的配置信息
如何向iomuxc(描述IOMUXC設(shè)備的節(jié)點(diǎn))追加數(shù)據(jù)?
不同的外設(shè)使用的PIN不同,配置也不同,因此一個(gè)蘿卜一個(gè)坑,將某個(gè)外設(shè)所使用的的所有PIN都組織在一個(gè)子節(jié)點(diǎn)里
例如:
iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
imx6ul-evk {
pinctrl_hog_1: hoggrp-1 {
fsl,pins = <
MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059
MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059
MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059
MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x13058
>;
......
};
};
};
"fsl,pins"為pinctrl_hog_1 子節(jié)點(diǎn)所使用的 PIN 配置信息,對(duì)于一個(gè) PIN 的配置主要包括兩方面,一個(gè)是設(shè)置這個(gè) PIN 的復(fù)用功能,另一個(gè)就是設(shè)置這個(gè) PIN 的電氣特性
-
PIN 驅(qū)動(dòng)程序講解
《正點(diǎn)驅(qū)動(dòng)文檔》P1163
?
1.3 設(shè)備樹中添加pinctrl節(jié)點(diǎn)模版
1. 創(chuàng)建對(duì)應(yīng)的節(jié)點(diǎn)
同一個(gè)外設(shè)的PIN都放到一個(gè)節(jié)點(diǎn)里,如在iomuxc節(jié)點(diǎn)中的imx6ul-evk子節(jié)點(diǎn)下添加"pinctrl_test"節(jié)點(diǎn)
pinctrl_test:testgrp
{
? ?/*具體的PIN信息*/
}
2, 添加"fsl,pins"屬性
設(shè)備樹通過屬性來保存信息,對(duì)于I.MX系列SOC而言,pinctrl驅(qū)動(dòng)程序是通過讀取"fsl,pins"屬性值來獲取PIN的配置信息
pinctrl_test:testrp
{
? ?fsl,pins=<
? ?/*設(shè)備所使用的PIN配置信息*/ ? ?
? ?>
}
3. 在“fsl,pins”屬性中添加具體的PIN配置信息
pinctrl_test:testrp
{
? ?fsl,pins=<
? ?MX6UL_PAD_GPIO1_IO00_GPIO1_IO00 config/*config是具體設(shè)置值*/ ? ?
? ?>
}
2. gpio子系統(tǒng)
2.1 gpio子系統(tǒng)簡介
pinctrl子系統(tǒng)重點(diǎn)是設(shè)置PIN(PAD)的復(fù)用和電氣屬性,若pinctrl子系統(tǒng)將一個(gè)PIN復(fù)用為GPIO的話,則接下來就要用到gpio子系統(tǒng)
gpio子系統(tǒng)的主要目的就是方便驅(qū)動(dòng)開發(fā)者使用gpio,驅(qū)動(dòng)開發(fā)者在設(shè)備樹中添加gpio相關(guān)信息
2.2 gpio子系統(tǒng)驅(qū)動(dòng)
-
設(shè)備樹中的gpio信息
pinctrl配置好以后就是設(shè)置gpio了,驅(qū)動(dòng)程序通過相關(guān)GPIO進(jìn)行判斷處理等
-
如何讓驅(qū)動(dòng)程序知道相應(yīng)引腳連接的是相關(guān)的GPIO呢
需要設(shè)備樹來告訴驅(qū)動(dòng),在設(shè)備樹設(shè)備節(jié)點(diǎn)下添加一個(gè)屬性來描述設(shè)備引腳,設(shè)備驅(qū)動(dòng)直接讀取這個(gè)屬性值就知道相應(yīng)引腳使用哪個(gè)GPIO
示例代碼 45.2.2.2 設(shè)備樹中 SD 卡節(jié)點(diǎn)
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
/* pinctrl-3 = <&pinctrl_hog_1>; */
cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
keep-power-in-suspend;
enable-sdio-wakeup;
vmmc-supply = <®_sd1_vmmc>;
status = "okay";
};
-
"cd-gpios"屬性
cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
描述了SD卡的CD引腳使用的哪個(gè)IO,屬性值一共有三個(gè):
-
“&gpio1”:表示CD引腳所使用的的IO屬于GPIO1組
-
“19”:表示GPIO1組的第19號(hào)IO
通過這兩個(gè)值SD卡驅(qū)動(dòng)程序就知道CD引腳使用了GPIO1_IO19這個(gè)GPIO
-
“GPIO_ACTIVE_LOW”:表示低電平有效
-
gpio1節(jié)點(diǎn)
描述了GPIO1控制器的所有信息,重點(diǎn)就是GPIO1外設(shè)寄存器基地址以及兼容屬性
-
GPIO驅(qū)動(dòng)程序簡介
《正點(diǎn)驅(qū)動(dòng)文檔》P1171
2.3 gpio子系統(tǒng)API函數(shù)
對(duì)于驅(qū)動(dòng)開發(fā)人員,設(shè)置好設(shè)備樹以后就可以使用 gpio 子系統(tǒng)提供的 API 函數(shù)來操作指定的 GPIO,gpio 子系統(tǒng)向驅(qū)動(dòng)開發(fā)人員屏蔽了具體的讀寫寄存器過程。這就是驅(qū)動(dòng)分層與分離的好處
-
gpio_request函數(shù)
用于申請一個(gè)GPIO管腳,在使用一個(gè)GPIO之前一定要使用gpio_request進(jìn)行申請
int gpio_request(unsigned gpio, const char *label)
-
gpio_free函數(shù)
如果不使用某個(gè)GPIO了,就可以調(diào)用gpio_free函數(shù)進(jìn)行釋放
void gpio_free(unsigned gpio)
-
gpio_direction_input函數(shù)
此函數(shù)用于設(shè)置某個(gè)GPIO為輸入
int gpio_direction_input(unsigned gpio)
-
gpio_direction_output函數(shù)
此函數(shù)用于設(shè)置某個(gè)GPIO為輸出,并且設(shè)置默認(rèn)輸出值
int gpio_direction_output(unsigned gpio, int value)
-
gpio_get_value函數(shù)
此函數(shù)用于獲取某個(gè)GPIO的值
#define gpio_get_value __gpio_get_value
int __gpio_get_value(unsigned gpio)
-
gpio_set_value函數(shù)
此函數(shù)用于設(shè)置某個(gè)GPIO的值
#define gpio_set_value __gpio_set_value
void __gpio_set_value(unsigned gpio, int value)
2.4 設(shè)備樹中添加gpio節(jié)點(diǎn)模板
-
創(chuàng)建test設(shè)備節(jié)點(diǎn)
在根節(jié)點(diǎn)“/”下創(chuàng)建test設(shè)備子節(jié)點(diǎn)
test{
/*節(jié)點(diǎn)內(nèi)容*/
}
-
添加pinctrl信息
將描述test設(shè)備所使用的的GPIOx_IOxx這個(gè)PIN的信息的pinctrl_test節(jié)點(diǎn)添加到test設(shè)備節(jié)點(diǎn)中
test{
pinctrl-names="default";
pinctrl-0=<&pinctrl_test>;
/*其他節(jié)點(diǎn)內(nèi)容*/
};
3.添加GPIO屬性信息
最后需要在test節(jié)點(diǎn)中添加GPIO屬性信息,表明test設(shè)備所使用的的GPIO是哪個(gè)引腳
test{
pinctrl-names="default";
pinctrl-0=<&pinctrl_test>;
gpio=<&gpio1 0 GPIO_ACTIVE_LOW>;
};
2.5 與gpio相關(guān)的OF函數(shù)
-
of_gpio_named_count函數(shù)
用于獲取設(shè)備樹某個(gè)屬性里面定義了幾個(gè)GPIO信息,空的GPIO信息也會(huì)被統(tǒng)計(jì)到
int of_gpio_named_count(struct device_node *np, const char *propname)
-
of_gpio_count函數(shù)
和of_gpio_named_count函數(shù)一樣,但是不同的地方在于,此函數(shù)統(tǒng)計(jì)的是"gpios"這個(gè)屬性的GPIO數(shù)量,而of_gpio_named_count函數(shù)可以統(tǒng)計(jì)任意屬性的GPIO信息
int of_gpio_count(struct device_node *np)
-
of_get_named_gpio函數(shù)
獲取GPIO編號(hào),Linux內(nèi)核關(guān)于GPIO的API函數(shù)都需要GPIO編號(hào),此函數(shù)會(huì)將設(shè)備樹中類似<&gpio5 7 GPIO_ACTIVE_LOW>的屬性信息轉(zhuǎn)換為對(duì)應(yīng)的 GPIO 編號(hào),此函數(shù)很重要
int of_get_named_gpio(struct device_node *np,const char *propname, int index)
3. 驅(qū)動(dòng)程序編寫
-
test_gpio文章來源:http://www.zghlxwxcb.cn/news/detail-741269.html
int test_gpio; /* test 所使用的 GPIO 編號(hào) */
在設(shè)備結(jié)構(gòu)體test_dev中加入test_gpio這個(gè)成員變量,保存test設(shè)備所使用的的GPIO編號(hào)文章來源地址http://www.zghlxwxcb.cn/news/detail-741269.html
3.1 驅(qū)動(dòng)入口函數(shù)
static int __init led_init(void)
{
? ?/*設(shè)置test設(shè)備所使用的的GPIO*/
/*1、獲取設(shè)備節(jié)點(diǎn):gpiotest (通過設(shè)備樹中的路徑/xxx)*/
/*2、獲取gpio屬性內(nèi)容,得到test要使用的gpio編號(hào)*/
?
/*初始化LED*/
? ?/*1、設(shè)置GPIO引腳的功能*/
? ?/*2、默認(rèn)設(shè)置*/
/*注冊字符設(shè)備驅(qū)動(dòng)*/
/*1、創(chuàng)建設(shè)備號(hào)*/
? ?定義了設(shè)備號(hào):register_chrdev_region()
? ?沒有定義設(shè)備號(hào):alloc_chrdev_region()
/*2、初始化cdev*/
/*3、添加一個(gè)cdev*/
/*4、創(chuàng)建類*/
/*5、創(chuàng)建設(shè)備*/
}
3.2 驅(qū)動(dòng)出口函數(shù)
static void __exit led_exit(void)
{
/*注銷字符設(shè)備驅(qū)動(dòng)*/
/*1、刪除cdev*/
/*2、取消注冊字符設(shè)備*/
/*3、設(shè)備銷毀*/
/*4、類銷毀*/
}
到了這里,關(guān)于Linux驅(qū)動(dòng)開發(fā)之【pinctrl和gpio子系統(tǒng)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!