字符设备驱动(1)代码分析---之gpio_get_value
2025-02-05 来源:cnblogs
在中断处理函数中,调用gpio_get_value/gpio_set_value()函数来获取/设置gpio端口的值,在这里简单分析一下内核的实现流程。
tmp = gpio_get_value(S5PV210_GPH2(0));
#define gpio_get_value __gpio_get_value
int __gpio_get_value(unsigned gpio)
{
struct gpio_chip *chip;
int value;
chip = gpio_to_chip(gpio);
##
{
.base = (S5P_VA_GPIO + 0xC40),
.config = &gpio_cfg_noint,
.irq_base = IRQ_EINT(16),
.chip = {
.base = S5PV210_GPH2(0),
.ngpio = S5PV210_GPIO_H2_NR,
.label = 'GPH2',
.to_irq = samsung_gpiolib_to_irq,
},
##
value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
//offset = gpio - chip->base
trace_gpio_value(gpio, 1, value);
return value;
##
/****************************************************
chip->get()函数的内核实现
****************************************************/
//drivers/gpio/gpio-plat-samsung.c
void __init samsung_gpiolib_add_4bit_chips
(structs 3c_gpio_chip *chip,int nr_chips)
{
for (; nr_chips > 0; nr_chips--, chip++) {
samsung_gpiolib_add_4bit(chip);
s3c_gpiolib_add(chip);
}
}
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);
}
//arch/arm/plat_samsung/gpio.c
__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
{
struct gpio_chip *gc = &chip->chip;
int ret;
....
....
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;
//至此完善后的结构体gc变为:
gc = {
.base = (S5P_VA_GPIO + 0xC40),
.config = &gpio_cfg_noint,
.irq_base = IRQ_EINT(16),
.pm = __gpio_pm(&s3c_gpio_pm_4bit),
.chip = {
.base = S5PV210_GPH2(0),
.ngpio = S5PV210_GPIO_H2_NR,
.label = 'GPH2',
.to_irq = samsung_gpiolib_to_irq,
.direction_input = samsung_gpiolib_4bit_input,
.direction_output = samsung_gpiolib_4bit_output,
.set = s3c_gpiolib_set,
.get = s3c_gpiolib_get,
},
###
//samsung_gpiolib_4bit_input具体实现函数
static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
unsigned int offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long con;
con = __raw_readl(base + GPIOCON_OFF);
con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, base + GPIOCON_OFF);
gpio_dbg('%s: %p: CON now %08lxn', __func__, base, con);
return 0;
}
static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long con;
unsigned long dat;
con = __raw_readl(base + GPIOCON_OFF);
con &= ~(0xf << con_4bit_shift(offset));
con |= 0x1 << con_4bit_shift(offset);
dat = __raw_readl(base + GPIODAT_OFF);
if (value)
dat |= 1 << offset;
else
dat &= ~(1 << offset);
//有点小疑问:为啥要写两次数据???
__raw_writel(dat, base + GPIODAT_OFF);
__raw_writel(con, base + GPIOCON_OFF);
__raw_writel(dat, base + GPIODAT_OFF);
gpio_dbg('%s: %p: CON %08lx, DAT %08lxn', __func__, base, con, dat);
return 0;
}
//s3c_gpiolib_set、s3c_gpiolib_get的具体实现函数
static void s3c_gpiolib_set(struct gpio_chip *chip,
unsigned offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;
s3c_gpio_lock(ourchip, flags);
dat = __raw_readl(base + 0x04);
//将需要设定的位清零
dat &= ~(1 << offset);
//如果设定的值是1,则将相应位置1
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);
s3c_gpio_unlock(ourchip, flags);
}
static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
unsigned long val;
val = __raw_readl(ourchip->base + 0x04);
//将需要获取的位右移至最低位
val >>= offset;
//获取最低位的值并返回
val &= 1;
return val;
}
###
....
}
##
}
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 蓝牙信道探测技术原理与开发套件实践
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策




