前言
注: 所有文章基于linux-3.13以上,本系列主要介紹 GPIO的一些基本知識(shí),驅(qū)動(dòng)操作GPIO的接口,應(yīng)用層通過sysfs操作GPIO的接口,GPIO一些debug信息查看,以及對(duì)高通相關(guān)GPIO的寄存器操作。分享給剛剛接觸外設(shè)bsp的小伙伴們。當(dāng)然后面有時(shí)間還會(huì)分享GPIO子系統(tǒng)框架和pinctrl子系統(tǒng)框架,先知道黑盒怎么使用,然后咱再打開仔細(xì)瞅瞅。
本篇為驅(qū)動(dòng)申請(qǐng)GPIO和操作GPIO接口篇,分別介紹驅(qū)動(dòng)通過GPIO子系統(tǒng)和PINCTRL 子系統(tǒng)提供的接口對(duì)GPIO的操作
GPIO 子系統(tǒng)操作GPIO
GPIO子系統(tǒng)接口簡(jiǎn)介
相關(guān)實(shí)現(xiàn)在driver/gpio/gpiolib.c 下
1、gpio_request 申請(qǐng)GPIO
?
int?gpio_request(unsigned?gpio,?const?char?*label)
?
參數(shù)解析:
gpio: gpio編號(hào)
label: 名稱
返回值: 成功返回0,失敗返回負(fù)值
2、gpio_request_one 申請(qǐng)GPIO,同時(shí)制定配置方式 輸出或輸入模式
?
int?gpio_request_one(unsigned?gpio,?unsigned?long?flags,?const?char?*label)
?
3、gpio_free 釋放GPIO
?
void?gpio_free(unsigned?gpio)
?
參數(shù)解析:
gpio: gpio編號(hào)
4、gpio_direction_input 設(shè)置GPIO為輸入模式
?
int?gpio_direction_input(unsigned?gpio)
?
參數(shù)解析:
gpio: gpio編號(hào)
返回值: 成功返回0,失敗返回負(fù)值
5、gpio_direction_output 設(shè)置GPIO為輸出模式
?
int?gpio_direction_output(unsigned?gpio,?int?value)
?
參數(shù)解析:
gpio: gpio編號(hào)
value: 設(shè)置為輸出模式時(shí)的初始值
返回值: 成功返回0,失敗返回負(fù)值
6、gpio_set_value 設(shè)置(寫)GPIO的值
?
void?__gpio_set_value(unsigned?gpio,?int?value) #define?gpio_set_value??__gpio_set_value
?
gpio: gpio編號(hào)
value: 設(shè)置的值
返回值: 成功返回0,失敗返回負(fù)值
7、gpio_get_value 獲取(讀)GPIO的值
?
int?__gpio_get_value(unsigned?gpio) #define?gpio_get_value??__gpio_get_value
?
gpio: gpio編號(hào)
返回值: 獲取的值
8、gpio_to_irq 內(nèi)核通過調(diào)用該函數(shù)將gpio端口轉(zhuǎn)換為中斷
?
int?gpio_to_irq(unsigned?gpio);?
?
gpio: gpio編號(hào)
返回值:中斷編號(hào)可以傳給request_irq()和free_irq()
舉個(gè)例子:?jiǎn)蝹€(gè)GPIO
申請(qǐng)gpio4,輸出模式,輸出高(從設(shè)備樹配置)
設(shè)備樹設(shè)置
?
gpio_test{ ?status="ok"; ?gpio_req=<&tlmn?4?0>;
?
代碼實(shí)現(xiàn)
?
struct?device?dev; gpio4?=?of_get_named_gpio(dev.of_node,"gpio_req",?0); err?=?gpio_request(gpio4,?"qti-can-reset"); ?if?(err?0)?{ ?????????return?err; ?}? gpio_direction_output(gpio4,?0);???????????????? gpio_set_value(gpio4,1);????????????????
?
GPIO數(shù)組申請(qǐng)一個(gè)gpio數(shù)組 [36,42,132],主要是設(shè)備樹 設(shè)備樹
?
gpios?=?<&tlmm?36?0>, ????????????????<&tlmm?42?0>, ????????????????<&tlmm 132 0>; ????????qcom,gpio-reset?=?<1>; ????????qcom,gpio-standby?=?<2>; ????????qcom,gpio-req-tbl-num?=?<0?1?2>;?? ????????qcom,gpio-req-tbl-flags?=?<1?0?0>;? ????????qcom,gpio-req-tbl-label?=?"CAMIF_MCLK2",?? ????????????????????????????????????????????????????????????????"CAM_RESET2", ???????????????????????????????????????????????????????????????"CAM_STANDBY2";
?
解析:
PINCTRL 子系統(tǒng)操作GPIO
pinctrl 子系統(tǒng)相關(guān)接口
1、devm_pinctrl_get 解析對(duì)應(yīng)的設(shè)備樹,獲取pinctrl資源
?
struct?pinctrl?*devm_pinctrl_get(struct?device?*dev)
?
dev: 驅(qū)動(dòng)設(shè)備結(jié)構(gòu)體
返回值:pinctrl節(jié)點(diǎn)
2、pinctrl_lookup_state 獲取各種state的gpio配置
?
struct?pinctrl_state?*pinctrl_lookup_state(struct?pinctrl?*p,?const?char?*name)?
?
p: pinctrl節(jié)點(diǎn)
name:gpio配置的名字
3、pinctrl_select_state 將上面獲取的指定state狀態(tài)設(shè)置到硬件中*/
?
int?pinctrl_select_state(struct?pinctrl?*p,?struct?pinctrl_state?*state)
?
舉個(gè)例子
高通的配置為例子
在pinctrl設(shè)備樹添加一個(gè)節(jié)點(diǎn)
?
&tlmn{ ? ?pin_teset_default:pin_teset_default{ ?????????????????mux?{ ??????????????????????????pins?=?"gpio0",?"gpio1";? ??????????????????????????function?=?"qup00"; ??????????????????}; ??????????????????config?{ ??????????????????????????pins?=?"gpio0",?"gpio1";? ??????????????????????????drive-strength?=?<2>; ??????????????????????????bias-disable; ??????????????????}; ?} }
?
在xxx.dtsi中添加一個(gè)設(shè)備 使用
?
pinctrl_test{ ??status="ok"; ??pinctrl-name="default"; ??pinctrl-0=<&pin_teset_default>; }
?
代碼實(shí)現(xiàn)
?
dev->pins->p?=?devm_pinctrl_get(dev); ?dev->pins->default_state?=?pinctrl_lookup_state(dev->pins->p,?PINCTRL_STATE_DEFAULT);? ??pinctrl_select_state(dev->pins->p,?dev->pins->default_state);
?
probe自動(dòng)配置pinctrl
如上個(gè)例子中,我們是不需要自己進(jìn)行pinctrl適配的,device和驅(qū)動(dòng)在匹配之后會(huì)進(jìn)行適配。調(diào)用我們驅(qū)動(dòng)的probe時(shí),pinctrl相關(guān)已經(jīng)初始化好了。獲取相關(guān)狀態(tài)和設(shè)置相關(guān)狀態(tài)
?
__device_attach ????bus_for_each_drv(dev->bus,?NULL,?&data,?__device_attach_driver); ????????__device_attach_driver? ????????????driver_match_device(drv,?dev);? ????????????driver_probe_device(struct?device_driver?*drv,?struct?device?*dev) ????????????????really_probe ????????????????????pinctrl_bind_pins? ????????????????????????drv->probe(dev) int?pinctrl_bind_pins(struct?device?*dev) { ??? ???dev->pins->p?=?devm_pinctrl_get(dev); ??? ???dev->pins->default_state?=?pinctrl_lookup_state(dev->pins->p,?PINCTRL_STATE_DEFAULT);? ???dev->pins->init_state?=?pinctrl_lookup_state(dev->pins->p,?PINCTRL_STATE_INIT); ??? ???if?(IS_ERR(dev->pins->init_state))?{ ??????? ???????ret?=?pinctrl_select_state(dev->pins->p,?dev->pins->default_state);? ???}?else?{ ???????ret?=?pinctrl_select_state(dev->pins->p,?dev->pins->init_state); ???} #ifdef?CONFIG_PM? ???dev->pins->sleep_state?=?pinctrl_lookup_state(dev->pins->p,?PINCTRL_STATE_SLEEP); ???dev->pins->idle_state?=?pinctrl_lookup_state(dev->pins->p,?PINCTRL_STATE_IDLE); #endif ???return?0; }
?
?
審核編輯:湯梓紅
評(píng)論