国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

linux驅動-gpio

這篇具有很好參考價值的文章主要介紹了linux驅動-gpio。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

最近處理es8336聲卡問題,最后排查是spk_ctl_gpio和hp_det_gpio這兩個gpio導致的,所以惡補了一下gpio相關的知識,現(xiàn)在總結一下。
源代碼使用的是飛騰的gitee上開源的內(nèi)核:https://gitee.com/phytium_embedded/phytium-linux-kernel.git

1. 概述

gpiod_get_value_cansleep,linux,運維,服務器

  1. 設備驅動層:定義了與硬件無關的GPIO API,包括GPIO的注冊、卸載和控制等功能,而實現(xiàn)了某個模塊的具體實現(xiàn),比如led燈、按鍵等等。

  2. gpiolib抽象層:GPIO框架中的核心抽象層,它的作用是為設備驅動層和控制器層提供一致的接口,該層提供了包括上層設備驅動和下層控制器驅動的API接口。

  3. 控制器層:GPIO控制器的實現(xiàn)和管理,在該層中實現(xiàn)特定GPIO控制器的底層硬件操作和功能實現(xiàn)包括GPIO控制器的初始化、操作和管理等。負責GPIO寄存器的讀寫操作和GPIO中斷的處理等。

其中gpiolib抽象層是GPIO框架中的核心層,也是linux內(nèi)核自己實現(xiàn)的,一般情況下沒有人會修改這部分的代碼,控制器層一般是芯片廠家BSP工程師實現(xiàn)的,設備驅動層是驅動工程師根據(jù)開發(fā)版的實際情況實現(xiàn)的。優(yōu)秀的BSP工程師和驅動工程師可以把驅動寫得與硬件解耦,把硬件的信息填充到設備樹中,驅動讀取設備樹的信息進行各種操作。

2. 控制器

這里以飛騰e2000為例子看看gpio控制器的驅動是怎么樣的,在文件drivers/gpio/gpio-phytium-platform.c中,但是gpio的操作函數(shù)寫在drivers/gpio/gpio-phytium-core.c和drivers/gpio/gpio-phytium-core.h中。

2.1 設備樹

		gpio0: gpio@28034000 {
			compatible = "phytium,gpio";
			reg = <0x0 0x28034000 0x0 0x1000>;
			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
			gpio-controller;
			#gpio-cells = <2>;
			#address-cells = <1>;
			#size-cells = <0>;

			porta {
				compatible = "phytium,gpio-port";
				reg = <0>;
				ngpios = <16>;
			};
		};

		gpio3: gpio@28037000 {
			compatible = "phytium,gpio";
			reg = <0x0 0x28037000 0x0 0x1000>;
			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
			gpio-controller;
			#gpio-cells = <2>;
			#address-cells = <1>;
			#size-cells = <0>;
			status = "disabled";

			porta {
				compatible = "phytium,gpio-port";
				reg = <0>;
				ngpios = <16>;
			};
		};

這里是gpio0和gpio3這個兩個gpio模塊,其實e2000有0到5,一共6個gpio模塊,每個模塊都有16個gpio,其中gpio0-2每個gpio都有一個硬件中斷號,而gpio3-5則是這個組共享一個硬件中斷號。當然,我看其他arm64的gpio都有復用功能,所以gpio的設備樹寫在pinctrl里面,現(xiàn)在e2000的gpio沒有復用到其他模塊,所以沒有使用pinctrl。

2.2 驅動的數(shù)據(jù)結構

以我多年的驅動經(jīng)驗來看,所有的gpio控制器驅動做的事情不外乎以下幾種:

  1. 分配私有數(shù)據(jù)結構體,這個結構體會包含struct gpio_chip結構體
  2. 讀取設備樹信息,填充gpio_chip結構體
  3. 把gpio_chip結構體綁定到平臺設備中

實際上gpio的驅動跟中斷和pinctrl放在一起的,初始化的時候會把irq_chip和 struct pinctrl_desc 和pinctrl_dev 一起填充的,這里主要講解gpio,就不多擴展了。我們先看struct gpio_chip結構體:

struct gpio_chip {
	const char		*label;				//gpio控制器的名字
	struct gpio_device	*gpiodev;		//gpio設備描述符
	struct device		*parent;		//gpio的父設備
	struct module		*owner;

	//下面是一系列的操作函數(shù)
	int	 (*get_direction)(struct gpio_chip *gc,unsigned int offset);
	int	 (*direction_input)(struct gpio_chip *gc,unsigned int offset);
	int  (*direction_output)(struct gpio_chip *gc,unsigned int offset, int value);
	int	 (*get)(struct gpio_chip *gc,unsigned int offset);
	void (*set)(struct gpio_chip *gc,unsigned int offset, int value);

	int			base;		//gpio引腳基值
	u16			ngpio;		//gpio引腳個數(shù)
	const char		*const *names;		//每一個引腳的名字
	bool			can_sleep;			//控制器是否能睡眠

	void __iomem *reg_dat;			//gpio數(shù)據(jù)寄存器基地址
	void __iomem *reg_set;			//gpio設置寄存器基地址
	void __iomem *reg_clr;			//gpio控制寄存器基地址
	void __iomem *reg_dir_out;		//gpio輸出寄存器基地址
	void __iomem *reg_dir_in;		//gpio輸入寄存器基地址
};

gpio_chip結構體中包含了對應GPIO端口的硬件基地址、引腳數(shù)、GPIO組數(shù)、GPIO編號和IRQ號等重要信息。同時,它還包括了訪問GPIO寄存器的函數(shù)指針,例如讀取和寫入寄存器等函數(shù),以及描述GPIO的信息和配置的特定標志。其中最重要的是struct gpio_device *gpiodev; 他表示gpio設備描述符。這個結構體存放著gpio控制器的設備信息和每個引腳的描述符結構體,我們來看看struct gpio_device結構體:

struct gpio_device {
	int			id;				//表示這是系統(tǒng)中第幾個GPIO控制器
	struct device		dev;
	struct cdev		chrdev;
	struct device		*mockdev;
	struct module		*owner;
	struct gpio_chip	*chip;		//gpio管理硬件的結構體,記錄寄存器信息及其操作函數(shù)
	struct gpio_desc	*descs;		//引腳的描述符指針,每一個引腳對應一個gpio_desc結構體
	int			base;				//gpio號碼基值
	u16			ngpio;				//gpio個數(shù)
	const char		*label;			//gpio控制器的名字
	void			*data;
	struct list_head        list;
	struct blocking_notifier_head notifier;
};

gpio_device結構體中包含了與GPIO設備(GPIO控制器)相關的重要信息,例如GPIO控制器ID、GPIO號、GPIO個數(shù)、GPIO管理硬件的結構體和gpio引腳描述符結構體。最重要的是GPIO管理硬件的結構體gpio_chip 就是剛剛第一個介紹的數(shù)據(jù)結構,gpio設備是通過gpio_chip 找到對用的硬件信息和操作方法的;其次是gpio_desc結構體,每一個引腳對應一個gpio_desc結構體,他們通過數(shù)組的形式排列,我們看看gpio_desc結構體:

struct gpio_desc {
	struct gpio_device	*gdev;		//屬于哪個GPIO控制器
	unsigned long		flags;		//gpio引腳屬性,比如是否被使用、是否開漏等等
	
	/* Connection label */
	const char		*label;
	/* Name of the GPIO */
	const char		*name;			//引腳名字
#ifdef CONFIG_OF_DYNAMIC
	struct device_node	*hog;
#endif
#ifdef CONFIG_GPIO_CDEV
	/* debounce period in microseconds */
	unsigned int		debounce_period_us;
#endif
};

gpio_desc結構體主要記錄GPIO引腳的硬件信息和狀態(tài)信息。

gpiod_get_value_cansleep,linux,運維,服務器
這3個結構體的關系如上圖所示,以上這3個結構體就包含了gpio控制器的硬件信息、狀態(tài)信息和操作方法集合,這就我們的設備驅動提供了底層的基礎,我們的驅動就是通過gpiolib抽象層提供的API調(diào)用到這個操作方法的。

3. 設備驅動

在控制器驅動準備好的情況下,我們使用gpio是一件很簡單的事情,就拿es8336這個網(wǎng)卡驅動舉個例子,先看設備樹:

	mio14: i2c@28030000 {
...
		codec0:es8336@10 {
			det-gpios = <&gpio2 5 0>;
			sel-gpios = <&gpio2 6 0>;
...
	   };
	};

其中gpio的設備樹就兩行,其他不重要的就忽略了。
驅動文件在sound/soc/codecs/es8336.c:

	es8336->spk_ctl_gpio = devm_gpiod_get_index_optional(&i2c->dev, "sel", 0,
							GPIOD_OUT_HIGH);
	ret = of_property_read_u8(i2c->dev.of_node, "mic-src", &es8336->mic_src);
	if (ret != 0) {
		dev_dbg(&i2c->dev, "mic1-src return %d", ret);
		es8336->mic_src = 0x20;
	}
	dev_dbg(&i2c->dev, "mic1-src %x", es8336->mic_src);

	if (!es8336->spk_ctl_gpio)
		dev_info(&i2c->dev, "Can not get spk_ctl_gpio\n");
	else
		es8336_enable_spk(es8336, false);

	es8336->hp_det_gpio = devm_gpiod_get_index_optional(&i2c->dev, "det", 0,
							GPIOD_IN);

	if (!es8336->hp_det_gpio) {
		dev_info(&i2c->dev, "Can not get hp_det_gpio\n");
	} else {
		INIT_DELAYED_WORK(&es8336->work, hp_work);
		hp_irq = gpiod_to_irq(es8336->hp_det_gpio);
		ret = devm_request_threaded_irq(&i2c->dev, hp_irq, NULL,
						es8336_irq_handler,
						IRQF_TRIGGER_FALLING |
						IRQF_TRIGGER_RISING |
						IRQF_ONESHOT,
						"es8336_interrupt", es8336);
		if (ret < 0) {
			dev_err(&i2c->dev, "request_irq failed: %d\n", ret);
			return ret;
		}
	}

其實設備驅動都是使用gpiolib提供的API:文章來源地址http://www.zghlxwxcb.cn/news/detail-646990.html

  1. gpiod_get_indexed:通過索引號獲取GPIO設備引腳。
  2. gpiod_get_optional:嘗試獲取GPIO設備引腳,如果失敗返回NULL,不會導致注冊失敗。
  3. gpiod_get_optional_indexed:與gpiod_get_optional類似,但通過索引號獲取GPIO設備引腳。
  4. gpiod_get_raw:通過GPIO編號獲取GPIO設備引腳,不進行方向和值的配置。
  5. devm_gpiod_get:這個函數(shù)自動為一個特定的設備申請所需的GPIO,不需要手動釋放,適合臨時使用的GPIO資源。
  6. devm_gpiod_get_index:這個函數(shù)允許為使用多個GPIO的設備申請多個GPIO引腳,返回一個struct gpiod_hanlde數(shù)組。
  7. devm_gpiod_get_optional:如果存在,允許驅動程序獲取所需的GPIO,而不會阻止設備與其余的GPIO資源一起初始化。
  8. devm_gpiod_get_optional_index:類似于devm_gpiod_get_optional,支持索引GPIO。
  9. gpio_request:向內(nèi)核申請一個GPIO引腳。
  10. gpio_free:釋放一個已經(jīng)使用的GPIO引腳。
  11. gpio_direction_input:配置GPIO引腳為輸入模式。
  12. gpio_direction_output:配置GPIO引腳為輸出模式。
  13. gpio_get_value:讀取GPIO引腳狀態(tài)。如果 GPIO 引腳已配置為輸出模式,則返回當前輸出值。如果 GPIO 引腳未配置或配置為輸入模式,則返回實際引腳上的輸入值。
  14. gpio_set_value:設置GPIO引腳狀態(tài)為高或低電平。如果 GPIO 引腳已配置為輸出模式,則設置GPIO引腳狀態(tài)為用戶指定電平;如果 GPIO 引腳是輸入模式,此函數(shù)沒有作用。
  15. gpio_to_irq:將 GPIO 引腳轉換為專用中斷號。
  16. gpio_request_one:請求單個GPIO。
  17. gpio_free_array:釋放一組由gpio_request_array()調(diào)用請求的GPIO。
  18. gpio_direction_input_array:將一組GPIO方向設置為輸入模式。
  19. gpio_direction_output_array:將一組GPIO方向設置為輸出模式。
  20. gpio_get_array:將一組GPIO值讀入緩沖區(qū)中。
  21. gpio_set_array:將一組GPIO指定的值寫入用戶指定的緩沖區(qū)中。
  22. gpio_get_value_cansleep:讀取GPIO引腳狀態(tài),如果引腳已配置為輸出模式,則將與其關聯(lián)的電平值復制到調(diào)用函數(shù)的參數(shù)變量中,如果引腳已配置為輸入模式,則等待GPIO中斷或超時發(fā)生后將其值復制到調(diào)用函數(shù)的參數(shù)變量中。
  23. gpio_set_value_cansleep:設置GPIO端口電平,如果引腳仍被配置為輸入模式,則什么也不做。

到了這里,關于linux驅動-gpio的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Linux中apt-get入門

    目錄 Linux中apt-get入門 安裝apt-get 使用apt-get管理軟件包 更新軟件包列表 搜索軟件包 安裝軟件包 升級軟件包 卸載軟件包 清理無用的軟件包 結論 在Linux系統(tǒng)中,有多種工具可以用來管理和安裝軟件包。其中,apt-get是一種在Debian和基于Debian的發(fā)行版上常用的軟件包管理工具。它

    2024年02月04日
    瀏覽(18)
  • linux apt-get安裝Jenkins

    這個錯誤信息表明在嘗試更新軟件包索引時,APT 軟件包管理器無法驗證 Jenkins 存儲庫的 GPG 簽名,因為缺少相應的公鑰。此外,還提示 sources.list 和 jenkins.list 文件重復配置了相同的目標。 要解決這個問題,請按照以下步驟操作: 導入 Jenkins GPG 密鑰 : 你需要導入 Jenkins 存儲

    2024年04月29日
    瀏覽(22)
  • 【Linux】 apt-get:找不到命令

    【Linux】 apt-get:找不到命令

    ? 這是我在虛機上安裝gcc編譯器時遇到的問題,輸入命令出現(xiàn)如上提示 輸入命令 sudo yum install gcc 原因是:CentOS的軟件安裝工具不是apt-get,而是yum,使用yum命令代替apt-get即可。 ? ?

    2024年02月11日
    瀏覽(17)
  • 在 Linux 系統(tǒng)中,如何發(fā)起POST/GET請求

    在 Linux 系統(tǒng)中,可以使用命令行工具 `curl` 或者 `wget` 來發(fā)送 POST 請求。這兩個工具都是非常常用的命令行工具,可以通過命令行直接發(fā)送 HTTP 請求。 1. 使用 `curl` 發(fā)送 POST 請求: 解釋: - `-X POST`: 指定請求的方法為 POST。 - `-H \\\"Content-Type: application/json\\\"`: 指定請求頭中的 Cont

    2024年02月15日
    瀏覽(20)
  • 使用bash腳本在Linux中發(fā)送HTTP GET請求

    使用bash腳本在Linux中發(fā)送HTTP GET請求

    在Linux中,使用bash腳本發(fā)送HTTP GET請求是一種常見的自動化任務。下面是一個簡單的bash腳本示例,用于發(fā)送HTTP GET請求并處理響應: bash 復制代碼 #!/bin/bash # 定義URL url= \\\"http://example.com\\\" ? # 發(fā)送GET請求并獲取響應 response=$(curl -s \\\" $url \\\" ) # 檢查響應狀態(tài)碼 if ?[ $? -eq 0 ]; then ? e

    2024年01月22日
    瀏覽(89)
  • 深入理解Linux中的“sudo apt-get update“命令

    在Linux操作系統(tǒng)中,sudo apt-get update 是一個常用的命令,用于更新系統(tǒng)中可用軟件包的信息。這個命令允許用戶獲取最新的軟件包列表和更新信息,以確保系統(tǒng)上的軟件保持最新狀態(tài)。在本文中,我們將詳細解釋sudo apt-get update命令的用法和工作原理。 目錄 1.什么是 \\\"sudo apt-g

    2024年02月05日
    瀏覽(23)
  • 三、全網(wǎng)最全Linux軟件包管理apt-get命令

    在Linux系統(tǒng)中,軟件的安裝、更新和刪除是一項非常重要的任務。為了方便用戶進行軟件管理,Linux提供了許多工具集,其中一個廣泛使用的工具就是apt-get。本文將詳細介紹apt-get工具集的使用方法和常見操作。 1. apt-get命令 apt-get是Debian及其衍生發(fā)行版(如Ubuntu)中用于管理軟

    2024年02月13日
    瀏覽(17)
  • linux tracert:未找到命令 sudo apt-get:找不到命令

    linux tracert:未找到命令 sudo apt-get:找不到命令

    第一次用tracert命令,提示未找到命令,換成traceroute可以了 ?原因:tracert命令是windows系統(tǒng)使用的,linux系統(tǒng)要用traceroute命令 ?安裝抓包軟件wireshark, 輸入?sudo apt-get install wireshark命令提示找不到命令 ?把apt-get換成yum可以了。 原因:CentOS的軟件安裝工具不是apt-get,而是yum,使

    2024年02月06日
    瀏覽(24)
  • <Linux開發(fā)>驅動開發(fā) -Linux MISC 驅動

    <Linux開發(fā)>驅動開發(fā) -Linux MISC 驅動

    <Linux開發(fā)>驅動開發(fā) -Linux MISC 驅動 交叉編譯環(huán)境搭建: <Linux開發(fā)> linux開發(fā)工具-之-交叉編譯環(huán)境搭建 uboot移植可參考以下: <Linux開發(fā)> -之-系統(tǒng)移植 uboot移植過程詳細記錄(第一部分) <Linux開發(fā)> -之-系統(tǒng)移植 uboot移植過程詳細記錄(第二部分) <Linux開發(fā)> -之

    2024年02月13日
    瀏覽(18)
  • <Linux開發(fā)>驅動開發(fā) -之- Linux RTC 驅動

    <Linux開發(fā)>驅動開發(fā) -之- Linux RTC 驅動

    <Linux開發(fā)>驅動開發(fā) -之- Linux RTC 驅動 交叉編譯環(huán)境搭建: <Linux開發(fā)> linux開發(fā)工具-之-交叉編譯環(huán)境搭建 uboot移植可參考以下: <Linux開發(fā)> -之-系統(tǒng)移植 uboot移植過程詳細記錄(第一部分) <Linux開發(fā)> -之-系統(tǒng)移植 uboot移植過程詳細記錄(第二部分) <Linux開發(fā)>

    2024年02月11日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包