1:什么是gpiolib,為什么要有gpiolib?
linux中從2.6.35以后就開始有gpiolib庫了,gpiolib的作用是對所有的gpio實行統一管理,因為驅動在工作的時候,會出現好幾個驅動共同使用同一個gpio的情況;
這會造成混亂。所以內核提供了一些方法來管理gpio資源;
2:如何學習gpiolib
第一:gpiolib庫的建立;
第二:gpiolib庫的使用方法:申請、使用、釋放;
3:我們首先來看一下這個文件:mach-smdkc110.c這個文件:
smdkc110_map_io
s5pv210_gpiolib_init 這個函數是gpiolib的初始化函數
__init int s5pv210_gpiolib_init(void)
{
struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
int i = 0;
for (i = 0; i < nr_chips; i++, chip++) {
if (chip->config == NULL)
chip->config = &gpio_cfg;
if (chip->base == NULL)
chip->base = S5PV210_BANK_BASE(i);
}
samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
return 0;
}
gpiolib庫的初始化實質就是對這個結構體數組進行賦值;
下面看一下這個結構體
struct s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg *config;
struct s3c_gpio_pm *pm;
void __iomem *base;
int eint_offset;
spinlock_t lock;
#ifdef CONFIG_PM
u32 pm_save[7];
#endif
};
chpi結構體:為主要結構體
關鍵幾個元素
label
request //申請gpio
free //釋放gpio
direction_input //輸入模式
direction_output //輸出模式
get //讀取gpio的值
set //寫入gpio的值
base //gpio基地址 端口地址
ngpio //引腳地址
names //名字
struct gpio_chip {
const char *label;
struct device *dev;
struct module *owner;
int (*request)(struct gpio_chip *chip,
unsigned offset);
void (*free)(struct gpio_chip *chip,
unsigned offset);
int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
int (*get)(struct gpio_chip *chip,
unsigned offset);
int (*direction_output)(struct gpio_chip *chip,
unsigned offset, int value);
int (*set_debounce)(struct gpio_chip *chip,
unsigned offset, unsigned debounce);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
void (*dbg_show)(struct seq_file *s,
struct gpio_chip *chip);
int base;
u16 ngpio;
const char *const *names;
unsigned can_sleep:1;
unsigned exported:1;
};
內核中建立了
static struct s3c_gpio_chip s5pv210_gpio_4bit[] 這個數組,將所有的gpio的.chip結構體中的一些元素初始化
這個數組的所有元素是與數據手冊中的所有gpio是一一對應的;
我們首先來分析一下.chip->base中的值 通過一下幾個宏定義我們可以知道gpa0中 chip->.chip->base中的值為 0 gpa1中chip->.chip->base中的值為9 這個數字數對應端口的io口的號碼;
#define S5PV210_GPA0(_nr) (S5PV210_GPIO_A0_START + (_nr))
#define S5PV210_GPA1(_nr) (S5PV210_GPIO_A1_START + (_nr))
S5PV210_GPIO_A0_START = 0,
S5PV210_GPIO_A1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_A0),
#define S5PV210_GPIO_NEXT(__gpio)
((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
#define S5PV210_GPIO_A0_NR (8)
#define S5PV210_GPIO_A1_NR (4)
#define S5PV210_GPIO_B_NR (8)
#define S5PV210_GPIO_C0_NR (5)
----------------------------------------------------------------------------------------------------------------------------------------------
接下來是對
chip->config = &gpio_cfg;
chip->config結構體賦值;
然后是對chip->base 賦值
chip->base = S5PV210_BANK_BASE(i);
#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20)
可以看出chip->base是把gpio的虛擬地址賦值給chip->base,每個gpio的地址差0x20;
下面看一下
samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips); 這個函數
void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
int nr_chips)
{
for (; nr_chips > 0; nr_chips--, chip++) {
samsung_gpiolib_add_4bit(chip);
s3c_gpiolib_add(chip);
}
}
這個函數中調用了兩個函數
samsung_gpiolib_add_4bit_chips
samsung_gpiolib_add_4bit
s3c_gpiolib_add
void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = samsung_gpiolib_4bit_input;
chip->chip.direction_output = samsung_gpiolib_4bit_output;
chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
}
這個函數的作用是對每個chip->chip的direction_input direction_output兩個函數賦值
下面看一下s3c_gpiolib_add函數都做了什么:
if (!gc->direction_input)
gc->direction_input = s3c_gpiolib_input;
if (!gc->direction_output)
gc->direction_output = s3c_gpiolib_output;
if (!gc->set)
gc->set = s3c_gpiolib_set;
if (!gc->get)
gc->get = s3c_gpiolib_get;
繼續對chip->中的元素進行賦值,set get賦值,
ret = gpiochip_add(gc);
最后注冊這些gpio_chip結構體;
注冊的實質是:在linux內核中有一個gpio_desc結構體數組,注冊就是把我們封裝的gpio的所有信息的結構體放到數組的格子中;
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
gpiolib庫是linux內核工程師以及三星芯片廠商工程師共同完成的,內核工程師提供搭建好底層框架,三星工程師
把自己開發板的gpio初始化并注冊到內核提供的數組中去;
---------------------------------------------------------------------------------------------------------------
上面講了gpiolib庫的構建,構建的實質是把所有的gpio結構體進行初始化,并且放到內核中gpio_desc這個結構體數組中;
下面看一下我們在開發驅動的時候如何使用gpiolib庫
首先要了解一下linux內核工程師給我們開發的接口:
文件:/drivers/gpio/gpiolib.c文件中提供所有的接口
1:gpio_request:向內核申請gpio
int gpio_request(unsigned gpio, const char *label)
2:gpio_free對應gpio_request,是使用完gpio以后把gpio釋放掉
void gpio_free(unsigned gpio)
3:gpiochip_add:向內核注冊gpio
int gpiochip_add(struct gpio_chip *chip)
4:gpio_request_one 申請gpio
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
5:gpio_request_one申請gpio
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
6:gpiochip_is_requested:用來看gpio是否已經使用
const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
7:gpio_direction_input :設置gpio輸入
int gpio_direction_input(unsigned gpio)
8:gpio_direction_output:gpio輸出
int gpio_direction_output(unsigned gpio, int value)
9:__gpio_get_value :獲取寄存器的值 這里注意由于前面加了__是內核用的函數所以我們不能用這個函數
在/arch/arm/mach-s5pv210/include/mach/gpio.h中定義了以下宏;所以我們使用的時候直接包含這個頭文件使用gpio_get_value 函數即可
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
int __gpio_get_value(unsigned gpio)
10:__gpio_get_value :設置寄存器的值
int __gpio_get_value(unsigned gpio)
http://blog.csdn.net/tongxinv/article/details/54790792
---------------------------------------------------------------------------------------------------------------------------------
上一篇:Linux下GPIO驅動(一) ----一個簡單的LED驅動
下一篇:喜羊羊系列之【設備-驅動 動態載入進內核】
推薦閱讀最新更新時間:2025-04-24 12:07


設計資源 培訓 開發板 精華推薦
- T12絡鐵電路
- 用于大功率通用離線電源的 NCP1217 增強型 PWM 電流模式控制器的典型應用
- EV-AD5415/49SDZ,評估 AD5415 串行輸入、雙通道電流輸出 DAC
- LTC1798CS8-4.1 微功率低壓差負基準電壓源典型應用電路
- RDR-623 - 使用 LinkSwitch-TN2 的低待機電流、非隔離反激式電源
- VND7140AJ評估板
- AT32UC3L-EK、用于 AT32UC3L064 AVR UC3 MCU 的 UC3L-EK 評估套件
- RD-311,適用于筆記本電腦的 65W、19V 交流轉直流單輸出電源的參考設計
- NCP380HSN05AGEVB:高側配電開關評估板
- KSZ8895FMQ-EVAL,評估板使用 KSZ8895FMQ 高度集成的第 2 層管理的五端口交換機