使用pinctrl子系統實現引腳功能動態切換
使用pinctrl子系統實現動態切換引腳功能
裝置dts (msm8909-pinctrl.dtsi)
&soc {
tlmm_pinmux:[email protected] {
compatible= "qcom,msm-tlmm-8916";
reg= <0x1000000 0x300000>;
interrupts= <0 208 0>;
/*Generalpurpose pins*/
gp:gp {
qcom,num-pins= <113>;
#qcom,pin-cells= <1>;
msm_gpio:msm_gpio {
compatible= "qcom,msm-tlmm-gp";
gpio-controller;
#gpio-cells= <2>;
interrupt-controller;
#interrupt-cells= <2>;
num_irqs= <113>;
};
};
cam_sensor_mclk0{
/*MCLK */
qcom,pins= <&gp 26>;
qcom,num-grp-pins= <1>;
qcom,pin-func= <1>;
label= "cam-sensor-mclk0";
/* active state */
cam_sensor_mclk0_default:default {
drive-strength= <2>; /* 2 MA */
bias-disable= <0>; /* No PULL */
};
};
cam_sensor_mclk0_sleep{
/*MCLK */
qcom,pins= <&gp 26>;
qcom,num-grp-pins= <1>;
label= "cam-sensor-mclk0-sleep";
/*suspend state */
cam_sensor_mclk0_sleep:sleep {
drive-strength= <2>; /* 2 MA */
bias-pull-down;/* PULL DOWN */
};
};
/*test */
uart_0_console{
qcom,pins= <&gp 4>, <&gp 5>;
qcom,num-grp-pins= <2>;
qcom,pin-func= <2>;
label= "uart0-console";
uart_0_active:uart_0_active {
drive-strength = <8>;
bias-pull-down;
};
};
uart_0_gpio{
qcom,pins= <&gp 4>, <&gp 5>;
qcom,num-grp-pins= <2>;
qcom,pin-func= <0>;
label= "uart0-gpio";
uart_0_gpio:uart_0_gpio {
drive-strength = <8>;
bias-pull-down;
output-high;
};
};
};
};
定義串列埠引腳的兩個狀態uart_0_console(uart_0_active)和uart_0_gpio(uart_0_gpio)。
前者是配置gpio4/5作為uart功能,function2。後者配置gpio4,5作為普通gpio功能,function0。
具體裝置引用:
&soc {
gpio_uart_exchage{
compatible= "gpio-uart-exchage";
pinctrl-names= "default", "gpio";
pinctrl-0= <&uart_0_active>;
pinctrl-1= <&uart_0_gpio>;
};
};
注意:
"default"對應的引腳配置為pinctrl-0;
"gpio"對應的引腳配置為pinctrl-1;
一般引腳的狀態為兩個就可以了,一個為活躍狀態的引腳狀態,一個是休眠狀態的引腳狀態。
如SDIO介面配置;
pinctrl-names= "active", "sleep";
pinctrl-0= <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
pinctrl-1= <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off&sdc2_cd_off>;
站在應用的邏輯上來講,設定某模組的兩種工作狀態。
驅動
裝置配置好了,我們來看驅動程式。
首先介紹下主要pinctrl函式(Core.c (drivers\pinctrl))
標頭檔案:#include <linux/pinctrl/consumer.h>
1. 獲取一個pinctrl控制代碼,引數是dev是包含這個pin的device結構體即xxx這個裝置的device
/**
* struct devm_pinctrl_get() - Resource managed pinctrl_get()
* @dev: the device to obtain the handle for
*
* If there is a need to explicitly destroy the returned struct pinctrl,
* devm_pinctrl_put() should be used, rather than plain pinctrl_put().
*/
struct pinctrl *devm_pinctrl_get(struct device *dev)
2. 獲取這個pin對應pin_state,引腳狀態
/**
* pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
* @p: the pinctrl handle to retrieve the state from
* @name: the state name to retrieve
*/
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
3.設定引腳為為某個state
/**
* pinctrl_select_state() - select/activate/program a pinctrl state to HW
* @p: the pinctrl handle for the device that requests configuration
* @state: the state handle to select/activate/program
*/
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
下面是一個簡單驅動程式:
#define pr_fmt(fmt) "%s:" fmt, __func__
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include<linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/io.h>
#include<linux/uaccess.h>
#include<linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
#include<linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/gpio.h>
unsigned long isGPIO =0;
struct pinctrl *gp_pinctrl;
struct pinctrl_state*gp_default;//uart
struct pinctrl_state*gp_gpio;//gpio
const char*gp_PINCTRL_STATE_DEFAULT = "default";
const char*gp_PINCTRL_STATE_GPIO = "gpio";
static int gp_request_gpios(intstate)
{
int result = 0;
if(state){
result = pinctrl_select_state(gp_pinctrl, gp_default);
if (result) {
printk("%s: Can not set %s pins\n",
__func__, "default");
}
}else{
result = pinctrl_select_state(gp_pinctrl, gp_gpio);
if (result) {
printk("%s: Can not set %s pins\n",
__func__, "gpio");
}
}
printk(KERN_ERR "%s, eliot request state(%s) ok, result = %d\n",
__func__, state ? "default" : "gpio",result);
return result;
}
static ssize_t lock_show(structdevice* cd,struct device_attribute *attr, char* buf)
{
ssize_t ret = 0;
sprintf(buf, "%lu\n",isGPIO);
ret = strlen(buf) + 1;
return ret;
}
static ssize_tlock_store(struct device* cd, struct device_attribute *attr,
const char* buf, size_tlen)
{
unsigned long on_off = simple_strtoul(buf, NULL, 10);
isGPIO = on_off;
printk("%s: %lu\n",__func__, isGPIO);
gp_request_gpios(!!isGPIO);
if(!isGPIO){
printk(KERN_ERR "set gpio 4 & 5to 0\n");
gpio_set_value(4 + 911, !!isGPIO);
gpio_set_value(5 + 911, !!isGPIO);
}
return len;
}
static DEVICE_ATTR(gp_ex,S_IRUGO | S_IWUSR, lock_show, lock_store);
static intgp_pinctrl_init(struct platform_device *pdata)
{
gp_pinctrl = devm_pinctrl_get(&pdata->dev);
if (IS_ERR_OR_NULL(gp_pinctrl)) {
printk("Failed to get pin ctrl\n");
return PTR_ERR(gp_pinctrl);
}
// default
gp_default = pinctrl_lookup_state(gp_pinctrl,
gp_PINCTRL_STATE_DEFAULT);
if (IS_ERR_OR_NULL(gp_default)) {
printk("Failed to lookup pinctrl default state\n");
return PTR_ERR(gp_default);
}
// gpio
gp_gpio = pinctrl_lookup_state(gp_pinctrl,
gp_PINCTRL_STATE_GPIO);
if (IS_ERR_OR_NULL(gp_gpio)) {
printk("Failed to lookup pinctrl gpio state\n");
return PTR_ERR(gp_gpio);
}
printk("eliot %s,---ok\n", __func__);
return 0;
}
// echo 0 >/sys/bus/platform/devices/gpio_uart_exchage.67/gp_ex //設定為普通GPIO
// echo 1 >/sys/bus/platform/devices/gpio_uart_exchage.67/gp_ex //設定為UART模式
static int gp_ex_probe(structplatform_device *pdev)
{
int ret = 0;
printk(KERN_ERR "eliot :gp_ex_probe\n");
gp_pinctrl_init(pdev);
if(device_create_file(&pdev->dev, &dev_attr_gp_ex))
printk(KERN_ERR "Unable to createsysfs entry: '%s'\n",
dev_attr_gp_ex.attr.name);
return ret;
}
static int gp_ex_remove(structplatform_device *plat)
{
return 0;
}
static struct of_device_id__attribute__ ((unused)) gp_ex_of_match[] = {
{ .compatible = "gpio-uart-exchage", },
{}
};
static struct platform_drivergp_ex_driver = {
.probe = gp_ex_probe,
.remove = gp_ex_remove,
.driver = {
.name = "gpio-exchage",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gp_ex_of_match),
},
};
static int __initgp_ex_init(void)
{
return platform_driver_register(&gp_ex_driver);
}
static void __exitgp_ex_exit(void)
{
platform_driver_unregister(&gp_ex_driver);
}
MODULE_LICENSE("GPLv2");
MODULE_AUTHOR("Eliot shao<http://blog.csdn.net/eliot_shao>");
MODULE_DESCRIPTION("Driverto exchager gpio4/5.");
MODULE_VERSION("1.0");
module_init(gp_ex_init);
module_exit(gp_ex_exit);
在sys檔案系統下面建立一個節點,通過讀寫這個節點來設定gpio4,5的狀態。使用方法:
// echo 0 >/sys/bus/platform/devices/gpio_uart_exchage.67/gp_ex //設定為普通GPIO
// echo 1 >/sys/bus/platform/devices/gpio_uart_exchage.67/gp_ex //設定為UART模式
其中呼叫的介面函式
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
來選擇在dts中配置的兩個引腳狀態。
另外函式:
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
中的name在dts中pinctrl-names ="default", "gpio";配置,驅動中通過名稱進行查詢引腳狀態。
相關推薦
使用pinctrl子系統實現引腳功能動態切換
使用pinctrl子系統實現動態切換引腳功能 裝置dts (msm8909-pinctrl.dtsi) &soc { tlmm_pinmux:[email protected] { compatib
imx6裝置樹pinctrl解析 (配置引腳功能)
最近在移植linux,用到kernel版本為3.14.28,在高版本的核心原始碼中用到了裝置樹(device-tree),裝置樹中用到pinctrl的配置,記錄一下。 1、普通設定 在配置串列埠時,pinctrl的配置資訊如下所示: &uart2 {
使用Jquery的區域性重新整理功能,實現選單內容的動態切換
在以前的開發中,我們很喜歡使用iframe實現選單內容的動態切換。但是iframe的可操作性、搜尋上、與整體頁面的配合上,存在著諸多問題。 現在我們可以使用成熟的jquery ajax技術實現選單的動態切換,簡單而且實用。 我們的選單區域一般是這樣子的: <!-- S
基於spring的aop實現多數據源動態切換
get 聲明式事務 數據庫 abstract 多數據源動態切換 for web開發 pro model https://lanjingling.github.io/2016/02/15/spring-aop-dynamicdatasource/ 基於spring的aop
LCD1602主要引數,引腳功能及初始化方法
LCD1602主要引數,引腳功能 及初始化方法 LCD1602液晶 顯示模組基本技術: 1)、主要功能 A、 40通道點陣LCD 驅動; B、 可選擇當作行驅動或列驅動; C、 輸入/輸出訊號
stm32 引腳功能設定及應用
GPIO_Mode_AIN = 0x0, 模擬輸入 GPIO_Mode_IN_FLOATING = 0x04, 浮空輸入 GPIO_Mode_IPD = 0x28, 帶下拉輸入
你知道STM8引腳可以實現觸控功能嗎?
在後臺看到這麼一條訊息:請問下stm8s003f3p6的管腳能否做成觸控輸入? 我曾開發帶有觸控按鍵功能的消費類電子產品,在起初也是不知道STM8引腳可以實現觸控這個功能,所以這裡寫給大家。 1寫在前面 我們開發帶有觸控功能的產品時,可能首先考慮的就是購買
spring 整合 quertz 並實現定時器頁面動態配置功能,支持腳本參數配置
nts implement cti () xtu ng- man con exists 背景 Java定時任務的實現技術主流的有三種,Java自帶的Java.util.Time類、Quartz、Spring3.0以後自帶的task。下面我們使用的是Quartz。 項
利用shell腳本實現計劃任務功能 V1.2
target 無需重啟 控制 basedir 之間 集中 shell腳本 htm 方便 2013.05.10 mytask 1.2 主程序休眠時間分成若幹小的時間片斷分段休眠,避免長時間的休眠不能及時響應系統信號。 2013.05.07 mytask 1
Ext JS 實現建議詞模糊動態搜索功能
uefi store node cor emp phone jsonstore ons .json 代碼: new Ext.form.ComboBox({ store: new Ext.data.JsonStore({
Spring整合多數據源實現動態切換
sna apach 動態數據 innodb des lis 項目 void getc 在實際項目中時常需要連接多個數據庫,而且不同的業務需求在實現過程當中往往需要訪問不同的數據庫。 jdbc.properties配置文件,配置多個dataSource ##########
vue2.0 實現click點擊當前li,動態切換class
一行 for ont pla false style function float del <template> <div> <ul> <li v-for="(item,$index) in items" @cli
spring+mybatis+tkmapper+atomikos實現分布式事務(3)-動態切換數據源
springmvc mybatis tkmapper atomiks 動態數據源 本文介紹基於spring+mybatis+tkmapper+atomikos+jta實現分布式事務,由程序動態切換數據源,通過atomikos可實現分布式事務一致性。通過繼承MapperScannerConf
Altera FPGA 開啟引腳片上上拉電阻功能
-c p s back 上拉電阻 對話框 列表 sign 圖片 ann 本博文以矩陣鍵盤實驗為例,介紹了如何開啟FPGA管腳的片上上拉電阻。 Cyclone IV E FPGA的通用輸入輸出管腳都支持內部弱上拉電阻,但是時鐘輸入腳不支持。所以,當需要上拉電阻的信號(如本
最新動態: 開源項目 ionic3-awesome — 實現多主題功能
分享圖片 logo log 多語言 安裝git lar 通訊 CA nod 項目地址:https://github.com/alex-0407/ionic3-awesome 從零開始搭建一個ionic3 app,集成更多通用功能,通用組件。 讓ionic開發more and
springboot+mybatis實現動態切換數據源
nbsp targe key component mybatis run 註解 config cte 前幾天有個需求,需要使用不同的數據源,例如某業務要用A數據源,另一個業務要用B數據源。我上網收集了一些資料整合了一下,雖然最後這個需求不了了之了,但是多數據源動態切換還是蠻
SpringCloud之基於SpringCloud+MybatisPlus+Config實現多個數據源的動態切換
一、首先,專案基於SpringCloud,配置檔案在Git上(包括資料來源的配置資訊)。 二、開始基於原有專案進行重構 1、寫一個動態資料來源上下文.程式碼如下: /** * 動態資料來源上下文 */ public class DbContextHolder { p
Spring boot 的profile功能如何實現多環境配置自動切換
通常服務端應用開發需要經過以下幾個流程: 開發 -> 測試 -> RC驗證 -> 上線 這就涉及到四個不同的環境,開發環境、測試環境、RC環境以及生產環境,為了避免不同環境之間相互干擾,通常需要獨立部署資料庫、快取伺服器等,那麼應用配置也要做相應的調整。
MyBatis 配置多資料來源實現多個數據庫動態切換
1.配置properties路徑 我的配置檔案 2.配置mybatis資料來源 配置 第二套資料來源 3 動態資料來源的配置 兩個key分別引入了 兩套資料來源,預設使用jsdx_telecom 4.配置SqlSessionFa
ssm中多資料來源通過Spring aop 實現資料來源的動態切換
【具體步驟】1、編寫動態資料來源相關程式碼。 (1) 編寫DynamicDataSource類。 DynamicDataSource的主要作用是以Map的形式,來儲存多個數據源。 因為該類繼承了父類AbstractRoutingDataSource,在父類中,多資料來源的例項是被存放在一個名為“ta