1. 程式人生 > >使用pinctrl子系統實現引腳功能動態切換

使用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