前言
注: 所有文章基于linux-3.13以上,本系列主要介紹 GPIO的一些基本知識,驅動操作GPIO的接口,應用層通過sysfs操作GPIO的接口,GPIO一些debug信息查看,以及對高通相關GPIO的寄存器操作。分享給剛剛接觸外設bsp的小伙伴們。當然后面有時間還會分享GPIO子系統框架和pinctrl子系統框架,先知道黑盒怎么使用,然后咱再打開仔細瞅瞅。
本篇為驅動申請GPIO和操作GPIO接口篇,分別介紹驅動通過GPIO子系統和PINCTRL 子系統提供的接口對GPIO的操作
GPIO 子系統操作GPIO
GPIO子系統接口簡介
相關實現在driver/gpio/gpiolib.c 下
1、gpio_request 申請GPIO
?
int?gpio_request(unsigned?gpio,?const?char?*label)
?
參數解析:
gpio: gpio編號
label: 名稱
返回值: 成功返回0,失敗返回負值
2、gpio_request_one 申請GPIO,同時制定配置方式 輸出或輸入模式
?
int?gpio_request_one(unsigned?gpio,?unsigned?long?flags,?const?char?*label)
?
3、gpio_free 釋放GPIO
?
void?gpio_free(unsigned?gpio)
?
參數解析:
gpio: gpio編號
4、gpio_direction_input 設置GPIO為輸入模式
?
int?gpio_direction_input(unsigned?gpio)
?
參數解析:
gpio: gpio編號
返回值: 成功返回0,失敗返回負值
5、gpio_direction_output 設置GPIO為輸出模式
?
int?gpio_direction_output(unsigned?gpio,?int?value)
?
參數解析:
gpio: gpio編號
value: 設置為輸出模式時的初始值
返回值: 成功返回0,失敗返回負值
6、gpio_set_value 設置(寫)GPIO的值
?
void?__gpio_set_value(unsigned?gpio,?int?value) #define?gpio_set_value??__gpio_set_value
?
gpio: gpio編號
value: 設置的值
返回值: 成功返回0,失敗返回負值
7、gpio_get_value 獲取(讀)GPIO的值
?
int?__gpio_get_value(unsigned?gpio) #define?gpio_get_value??__gpio_get_value
?
gpio: gpio編號
返回值: 獲取的值
8、gpio_to_irq 內核通過調用該函數將gpio端口轉換為中斷
?
int?gpio_to_irq(unsigned?gpio);?
?
gpio: gpio編號
返回值:中斷編號可以傳給request_irq()和free_irq()
舉個例子:單個GPIO
申請gpio4,輸出模式,輸出高(從設備樹配置)
設備樹設置
?
gpio_test{ ?status="ok"; ?gpio_req=<&tlmn?4?0>;
?
代碼實現
?
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數組申請一個gpio數組 [36,42,132],主要是設備樹 設備樹
?
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 子系統操作GPIO
pinctrl 子系統相關接口
1、devm_pinctrl_get 解析對應的設備樹,獲取pinctrl資源
?
struct?pinctrl?*devm_pinctrl_get(struct?device?*dev)
?
dev: 驅動設備結構體
返回值:pinctrl節點
2、pinctrl_lookup_state 獲取各種state的gpio配置
?
struct?pinctrl_state?*pinctrl_lookup_state(struct?pinctrl?*p,?const?char?*name)?
?
p: pinctrl節點
name:gpio配置的名字
3、pinctrl_select_state 將上面獲取的指定state狀態設置到硬件中*/
?
int?pinctrl_select_state(struct?pinctrl?*p,?struct?pinctrl_state?*state)
?
舉個例子
高通的配置為例子
在pinctrl設備樹添加一個節點
?
&tlmn{ ? ?pin_teset_default:pin_teset_default{ ?????????????????mux?{ ??????????????????????????pins?=?"gpio0",?"gpio1";? ??????????????????????????function?=?"qup00"; ??????????????????}; ??????????????????config?{ ??????????????????????????pins?=?"gpio0",?"gpio1";? ??????????????????????????drive-strength?=?<2>; ??????????????????????????bias-disable; ??????????????????}; ?} }
?
在xxx.dtsi中添加一個設備 使用
?
pinctrl_test{ ??status="ok"; ??pinctrl-name="default"; ??pinctrl-0=<&pin_teset_default>; }
?
代碼實現
?
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自動配置pinctrl
如上個例子中,我們是不需要自己進行pinctrl適配的,device和驅動在匹配之后會進行適配。調用我們驅動的probe時,pinctrl相關已經初始化好了。獲取相關狀態和設置相關狀態
?
__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; }
?
?
審核編輯:湯梓紅
評論
查看更多