基于MainLine Kernel的GPIO子系统分析

一、层次与数据结构

GPIO子系统主要的几个数据结构:

struct gpio_chip {};

struct gpio_device {};

struct gpio_desc {};

对于一个GPIO Cnotroller ,都有相对应的一个 gpio_chip结构体,通过其内部的函数指针最终来操作硬件。

struct gpio_chip定义如下 include\linux\gpio\driver.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
struct gpio_chip {
const char *label;
struct gpio_device *gpiodev;
struct device *parent;
struct fwnode_handle *fwnode;
struct module *owner;

int (*request)(struct gpio_chip *gc,
unsigned int offset);
void (*free)(struct gpio_chip *gc,
unsigned int offset);
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);
int (*get_multiple)(struct gpio_chip *gc,
unsigned long *mask,
unsigned long *bits);
void (*set)(struct gpio_chip *gc,
unsigned int offset, int value);
void (*set_multiple)(struct gpio_chip *gc,
unsigned long *mask,
unsigned long *bits);
int (*set_rv)(struct gpio_chip *gc,
unsigned int offset,
int value);
int (*set_multiple_rv)(struct gpio_chip *gc,
unsigned long *mask,
unsigned long *bits);
int (*set_config)(struct gpio_chip *gc,
unsigned int offset,
unsigned long config);
int (*to_irq)(struct gpio_chip *gc,
unsigned int offset);
..........

int base;
u16 ngpio;
u16 offset;
const char *const *names;
bool can_sleep;

在驱动里定义并初始化一个gpio_chip,使用 gpiochip_add_data()注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#define gpiochip_add_data(gc, data) ({		\
static struct lock_class_key lock_key; \
static struct lock_class_key request_key; \
gpiochip_add_data_with_key(gc, data, &lock_key, \ <-----实际调用函数
&request_key); \
})

************
************
gpiochip_add_data_with_key(gc, data, &lock_key,
&request_key)
{
........

gdev->dev.type = &gpio_dev_type;
gdev->dev.bus = &gpio_bus_type;

/* gdev 绑定 gpio_device */
gdev->dev.parent = gc->parent;
rcu_assign_pointer(gdev->chip, gc);
/* 反向绑定 */
gc->gpiodev = gdev;
gpiochip_set_data(gc, data);

........

base = gc->base;
if (base < 0) {
/* 自动分配 */
base = gpiochip_find_base_unlocked(gc->ngpio);
if (base < 0) {
ret = base;
base = 0;
goto err_free_label;
}

/*
* TODO: it should not be necessary to reflect the
* assigned base outside of the GPIO subsystem. Go over
* drivers and see if anyone makes use of this, else
* drop this and assign a poison instead.
*/
gc->base = base;
} else {
dev_warn(&gdev->dev,
"Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
}

gdev->base = base;
/* 添加到链表 */
ret = gpiodev_add_to_list_unlocked(gdev);
if (ret) {
chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
goto err_free_label;
}
......
}

其中比较关键的是

​ gdev->dev.parent = gc->parent;
​ rcu_assign_pointer(gdev->chip, gc);
​ /* 反向绑定 */
​ gc->gpiodev = gdev;

实现了gpio_chip <——-> gpio_device 的双向绑定。

我们可以看到,这个函数在初始化完这个结构体后,piodev_add_to_list_unlocked 并把它加入全局链表 gpio_devices,正式注册到系统中供其他子系统(比如 pinctrl、IRQ、设备树解析等)使用。

问:那么全局链表 gpio_devices 是干嘛的?

这是所有注册到内核的 GPIO 控制器的“数据库”,很多操作都会遍历它,比如:

1.用户态访问 /sys/class/gpio/

2.设备树中 gpio = <&gpioX ...> 时查找控制器

3.子系统(如 pinctrl, irqchip)查找 GPIO 资源

1
2
3
4
5
gpio_devices 里存的是所有注册的 gpio_device(每个 controller 一份);

每个 gpio_device 管理一个 desc 数组;

查找 GPIO 时,从dtb → 找 gpio controller → 找 desc[offset]

二、函数分析

我们在分配GPIO资源的时候一般有两种方法,第一种是传统方法,自己在驱动手动实现一个gpio_request()gpio_direction_input()等,另一种则是使用dtb来指定好引脚信息,通过platfrom_device解析后,系统自动gpio_request() gpio_direction_input()…….。

1.首先是gpiod_get()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* gpiod_get - obtain a GPIO for a given GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Returns:
* The GPIO descriptor corresponding to the function @con_id of device
* dev, -ENOENT if no GPIO has been assigned to the requested function, or
* another IS_ERR() code if an error occurred while trying to acquire the GPIO.
*/
struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return gpiod_get_index(dev, con_id, 0, flags);
}
EXPORT_SYMBOL_GPL(gpiod_get);

2.gpiod_get( ) —-> gpiod_get_index()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* gpiod_get_index - obtain a GPIO from a multi-index GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
* @flags: optional GPIO initialization flags
*
* This variant of gpiod_get() allows to access GPIOs other than the first
* defined one for functions that define several GPIOs.
*
* Returns:
* A valid GPIO descriptor, -ENOENT if no GPIO has been assigned to the
* requested function and/or index, or another IS_ERR() code if an error
* occurred while trying to acquire the GPIO.
*/
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags flags)
{
struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL;
const char *devname = dev ? dev_name(dev) : "?";
const char *label = con_id ?: devname;

return gpiod_find_and_request(dev, fwnode, con_id, idx, flags, label, true);
}
EXPORT_SYMBOL_GPL(gpiod_get_index);

3, —–>gpiod_find_and_request():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
struct gpio_desc *gpiod_find_and_request(struct device *consumer,
struct fwnode_handle *fwnode,
const char *con_id,
unsigned int idx,
enum gpiod_flags flags,
const char *label,
bool platform_lookup_allowed)
{
unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT;
const char *name = function_name_or_default(con_id);
/*
* scoped_guard() is implemented as a for loop, meaning static
* analyzers will complain about these two not being initialized.
*/
struct gpio_desc *desc = NULL;
int ret = 0;

scoped_guard(srcu, &gpio_devices_srcu) {
/*gpiod_find_by_fwnode 从设备树 (DT) 或 ACPI 中查找该 GPIO 的 gpio_desc。
利用 con_id 和 idx 来定位某个 label 名下的某个 GPIO。
*/
desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx,
&flags, &lookupflags);
if (gpiod_not_found(desc) && platform_lookup_allowed) {
/*
* Either we are not using DT or ACPI, or their lookup
* did not return a result. In that case, use platform
* lookup as a fallback.
*/
dev_dbg(consumer,
"using lookup tables for GPIO lookup\n");
desc = gpiod_find(consumer, con_id, idx, &lookupflags);
}

if (IS_ERR(desc)) {
dev_dbg(consumer, "No GPIO consumer %s found\n", name);
return desc;
}

/*
* If a connection label was passed use that, else attempt to use
* the device name as label
*/
/* 这里就是通过DTB规定好的GPIO引脚,自动申请 */
ret = gpiod_request(desc, label);
}
if (ret) {
if (!(ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
return ERR_PTR(ret);

/*
* This happens when there are several consumers for
* the same GPIO line: we just return here without
* further initialization. It is a bit of a hack.
* This is necessary to support fixed regulators.
*
* FIXME: Make this more sane and safe.
*/
dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
return desc;
}

ret = gpiod_configure_flags(desc, con_id, lookupflags, flags);
if (ret < 0) {
gpiod_put(desc);
dev_err(consumer, "setup of GPIO %s failed: %d\n", name, ret);
return ERR_PTR(ret);
}

gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);

return desc;
}

可以看到这和函数内部实现了解析设备树 gpiod_find_by_fwnode ,引脚申请、标志位设置。

三、i.mx6ull probe解析

1.打开驱动源码 drivers\gpio\gpio-mxc.c,找到probe函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static int mxc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mxc_gpio_port *port;
int irq_count;
int irq_base;
int err;

port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;

port->dev = &pdev->dev;
port->hwdata = device_get_match_data(&pdev->dev);

port->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(port->base))
return PTR_ERR(port->base);
......
mxc_update_irq_chained_handler(port, true);
err = bgpio_init(&port->gc, &pdev->dev, 4,
port->base + GPIO_PSR,
port->base + GPIO_DR, NULL,
port->base + GPIO_GDIR, NULL,
BGPIOF_READ_OUTPUT_REG_SET);
if (err)
goto out_bgio;
.......
port->gc.request = mxc_gpio_request;
port->gc.free = mxc_gpio_free;
port->gc.to_irq = mxc_gpio_to_irq;
port->gc.base = of_alias_get_id(np, "gpio") * 32;

err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port);
if (err)
goto out_bgio;

irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
if (irq_base < 0) {
err = irq_base;
goto out_bgio;
}
......
list_add_tail(&port->node, &mxc_gpio_ports);
return err;
}

**************************
struct mxc_gpio_port {
struct list_head node;
void __iomem *base;
struct clk *clk;
int irq;
int irq_high;
void (*mx_irq_handler)(struct irq_desc *desc);
struct irq_domain *domain;
struct gpio_chip gc;
.....
};

可以看到这个函数主要就是在对一个gpio_chip进行分配、设置、注册。gpio_chip 在struct mxc_gpio_port *port; 结构体中。

2.bgpio_init()

重点关注probe里的 bgpio_init 函数,我们首先看传的参数: port->base + GPIO_PSR, port->base + GPIO_DR, NULL, port->base + GPIO_GDIR, NULL,这几个参数就是一些寄存器的虚拟地址,分别是状态寄存器,数据寄存器,方向寄存器.

我们再进入函数内部:核心函数bgpio_setup_io

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int bgpio_init(struct gpio_chip *gc, struct device *dev,
unsigned long sz, void __iomem *dat, void __iomem *set,
void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
unsigned long flags)
{
int ret;

raw_spin_lock_init(&gc->bgpio_lock);
gc->parent = dev;
gc->label = dev_name(dev);
gc->base = -1;
gc->request = bgpio_request;
gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN);

ret = gpiochip_get_ngpios(gc, dev);
if (ret)
gc->ngpio = gc->bgpio_bits;

ret = bgpio_setup_io(gc, dat, set, clr, flags);
if (ret)
return ret;

return ret;
}

3.bgpio_setup_io()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
static int bgpio_setup_io(struct gpio_chip *gc,
void __iomem *dat,
void __iomem *set,
void __iomem *clr,
unsigned long flags)
{

gc->reg_dat = dat;
if (!gc->reg_dat)
return -EINVAL;

if (set && clr) {
gc->reg_set = set;
gc->reg_clr = clr;
gc->set = bgpio_set_with_clear;
gc->set_multiple = bgpio_set_multiple_with_clear;
} else if (set && !clr) {
gc->reg_set = set;
gc->set = bgpio_set_set;
gc->set_multiple = bgpio_set_multiple_set;
} else if (flags & BGPIOF_NO_OUTPUT) {
gc->set = bgpio_set_none;
gc->set_multiple = NULL;
} else {
gc->set = bgpio_set;
gc->set_multiple = bgpio_set_multiple;
}

if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
(flags & BGPIOF_READ_OUTPUT_REG_SET)) {
gc->get = bgpio_get_set;
if (!gc->be_bits)
gc->get_multiple = bgpio_get_set_multiple;
/*
* We deliberately avoid assigning the ->get_multiple() call
* for big endian mirrored registers which are ALSO reflecting
* their value in the set register when used as output. It is
* simply too much complexity, let the GPIO core fall back to
* reading each line individually in that fringe case.
*/
} else {
gc->get = bgpio_get;
if (gc->be_bits)
gc->get_multiple = bgpio_get_multiple_be;
else
gc->get_multiple = bgpio_get_multiple;
}

return 0;
}

可以看到它给我们去绑定了一些设置函数,这些函数都不需要我们去实现。这就是我们在驱动层调用gpiod_set最终执行到的地方。

这个功能都是由bgpio_init()提供的,这个函数是 Linux GPIO 子系统提供的一个通用框架函数,用于简化标准寄存器布局的 GPIO 控制器驱动编写。在bgpio_init()之后赋值的部分是 针对特定平台额外补充的能力函数,比如request/free/to_irq….

接着我们再次回到probe函数,有一个注册函数 err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port);

我们跳进去查看:

1
2
3
4
5
6
#define devm_gpiochip_add_data(dev, gc, data) ({ \
static struct lock_class_key lock_key; \
static struct lock_class_key request_key; \
devm_gpiochip_add_data_with_key(dev, gc, data, &lock_key, \
&request_key); \
})

可以看到这里调用的就是我们之前分析过的 gpio_chip注册的那一套流程 devm_gpiochip_add_data_with_key();

到此关于GPIO子系统的内部实现就简单分析到此。

未完……….

四、platfrom_device 、platfrom_driver match 过程

1.platfrom_device 注册过程

platfrom_device 注册的方式有两种:第一种是手动注册,用 platform_device_register() 自己注册设备,另一种则是设备树生成,系统启动时,of_platform_populate() 扫描设备树,发现 compatible 字段的节点就注册成 platform_device

首先分析手动注册:进入platform_device_register();

1
2
3
4
5
6
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev); ###初始化设备结构体 pdev->dev,清除未初始化字段,确保设备结构体状态正确。
setup_pdev_dma_masks(pdev);
return platform_device_add(pdev); ###将驱动注册到内核中
}

依次进入platform_device_add()—>device_add()

1
2
3
4
5
6
7
8
9
10
11
int platform_device_add(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
u32 i;
int ret;
...
ret = device_add(dev); <----------- 添加到设备总线
if (ret)
goto failed;
...
}

device_add()

1
2
3
4
5
6
7
8
9
10
11
12
int device_add(struct device *dev)
{
struct subsys_private *sp;
...
/* notify platform of device entry */
device_platform_notify(dev);

error = bus_add_device(dev); <-----将device加入到对应的 bus
if (error)
goto BusError;
.........
}

设备一旦添加到总线上,系统就会自动调用总线的匹配机制,找到与之匹配的驱动,进而调用驱动的 .probe() 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int bus_add_device(struct device *dev)
{
pr_debug("bus: '%s': add device %s\n", sp->bus->name, dev_name(dev));

error = device_add_groups(dev, sp->bus->dev_groups);
if (error)
goto out_put;

error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev));
if (error)
goto out_groups;

error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem");
if (error)
goto out_subsys;

klist_add_tail(&dev->p->knode_bus, &sp->klist_devices);
}
1
2
3
4
5
6
device_add()
└── bus_add_device()
└── bus_probe_device()
└── device_initial_probe()
└── driver_match_device()
└── probe()

2.设备树转换platfrom_device

3.platfrom_driver 注册过程

详细讲述了platfrom_driver .probe函数是如何调用的。

但是二者之间稍有不同。暂时没有深入研究….(二者间.probe调用方式和时间)

五、GPIO 与Pinctrl 的关联

在硬件上并没有Pinctrl这个模块,它是由软件虚拟出来的一个概念,很多时候Pinctrl的功能都是由GPIO控制器来完成的,所以说他们是密切相关的。

有时候在去操作一个gpio引脚时,明明没有把它通过pinctrl配置为gpio模式,但还是能去使用,这是因为在硬件上gpio引脚都是连接在gpio控制器上的,所以默认就是gpio模式。

1.gpio与pinctrl的映射关系

pinctrl_desc 和 gpio_device结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct pinctrl_desc {
const char *name;
const struct pinctrl_pin_desc *pins;
unsigned int npins;
const struct pinctrl_ops *pctlops;
const struct pinmux_ops *pmxops;
const struct pinconf_ops *confops;
struct module *owner;
#ifdef CONFIG_GENERIC_PINCONF
unsigned int num_custom_params;
const struct pinconf_generic_params *custom_params;
const struct pin_config_item *custom_conf_items;
#endif
bool link_consumers;
};
*******************************************************************
struct gpio_device {
struct device dev;
struct cdev chrdev;
int id;
struct device *mockdev;
struct module *owner;
struct gpio_chip __rcu *chip;
struct gpio_desc *descs;
unsigned long *valid_mask;
struct srcu_struct desc_srcu;
unsigned int base;
u16 ngpio;
bool can_sleep;
const char *label;
void *data;
struct list_head list;
struct raw_notifier_head line_state_notifier;
rwlock_t line_state_lock;
struct workqueue_struct *line_state_wq;
struct blocking_notifier_head device_notifier;
struct srcu_struct srcu;
...
};

先说结果,struct gpio_device里有一个struct gpio_desc *desc结构体,我们知道gpio_desc 就是某一个pin的描述符,我们说的映射关系就是如何将 struct gpio_desc *desc ——> pinctrl_pin_desc *pins,然后由 pinctrl_desc 里的struct pinmux_ops *pmxops提供的reset()、gpio_set_direction()函数去操作设置gpio pin。

需要研究的就是这个映射过程。

设备树方面,以gpio1为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
gpio1: gpio@209c000 {
compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
reg = <0x0209c000 0x4000>;
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_GPIO1>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-ranges = <&iomuxc 0 23 10>, <&iomuxc 10 17 6>,
<&iomuxc 16 33 16>;
};

可以看到有一个gpio-ranges = <&iomuxc 0 23 10>, <&iomuxc 10 17 6>,
<&iomuxc 16 33 16>; 属性:

<&iomuxc 0 23 10> :gpio1的第0个引脚要映射到pinctrl里的第23个引脚上,有10个引脚,可以看出一共有32个引脚。

那么在代码里怎么去表示呢?有两个结构体:gpio_pin_range pinctrl_gpio_range

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev; <-------
struct pinctrl_gpio_range range;
};

struct pinctrl_gpio_range {
struct list_head node;
const char *name;
unsigned int id;
unsigned int base; <-------
unsigned int pin_base; <-------
unsigned int npins;
unsigned int const *pins; <--------
struct gpio_chip *gc;
};

最终就是映射到 pctldev 里,怎么映射?使用 range 表示,base表示GPIO系统中的引脚编号(注意,是整个GPIO系统,而不是某一个GPIO控制器,如gpio1_0 在这里可能就是 100,gpio1_1 在这里可能就是 101)。

pin_base则是pinctrl里的引脚编号(0~xxx),pins表示引脚个数。

从gpiod_get()入手:

1
2
3
4
5
6
gpiod_get
gpiod_get_index
gpiod_find_and_request
gpiod_request
gpiod_request_commit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
{
...
CLASS(gpio_chip_guard, guard)(desc);
if (guard.gc->request) {
ret = guard.gc->request(guard.gc, offset);
if (ret > 0)
ret = -EBADE;
...
}

struct gpio_chip_guard {
struct gpio_device *gdev;
struct gpio_chip *gc;
int idx;
};

可以看到就是我们如上所说最终调用的就是 gpio_chip 里的 request 函数。(其实这里和上面分析的gpiod_get()差不多,只是分析的不是同一个功能)。

在上面分析 device driver match 的过程中,gpio-mxc.c 里的probe函数有这么一段:

1
2
3
4
port->gc.request = mxc_gpio_request;
port->gc.free = mxc_gpio_free;
port->gc.to_irq = mxc_gpio_to_irq;
port->gc.base = of_alias_get_id(np, "gpio") * 32;

可有看到这里设置了一个 mxc_gpio_request函数。

1
2
3
4
5
6
7
8
9
10
static int mxc_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
int ret;

ret = gpiochip_generic_request(chip, offset);
if (ret)
return ret;

return pm_runtime_resume_and_get(chip->parent);
}

这里调用了一个通用的gpio_request函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset)
{
#ifdef CONFIG_PINCTRL
if (list_empty(&gc->gpiodev->pin_ranges))
return 0;
#endif

return pinctrl_gpio_request(gc, offset); <------
}

#########################################################

int pinctrl_gpio_request(struct gpio_chip *gc, unsigned int offset)
{
struct pinctrl_gpio_range *range;
struct pinctrl_dev *pctldev;
int ret, pin;

ret = pinctrl_get_device_gpio_range(gc, offset, &pctldev, &range);
if (ret) {
if (pinctrl_ready_for_gpio_range(gc, offset))
ret = 0;
return ret;
}

mutex_lock(&pctldev->mutex);

/* Convert to the pin controllers number space */
pin = gpio_to_pin(range, gc, offset);

ret = pinmux_request_gpio(pctldev, range, pin, gc->base + offset);

mutex_unlock(&pctldev->mutex);

return ret;
}

pinctrl_gpio_request()里果然有一个pinctrl_ready_for_gpio_range()函数得到range,再通过gpio_to_pin()将这个引脚转换为pin controllers number,然后执行pinmux_request_gpio(pctldev, range, pin, gc->base + offset)(这里从参数可以看出,传入的就是gpio系统的全局编号)。

再接着往下看,进入 pinmux_request_gpio()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin, unsigned int gpio)
{
const char *owner;
int ret;

/* Conjure some name stating what chip and pin this is taken by */
owner = kasprintf(GFP_KERNEL, "%s:%d", range->name, gpio);
if (!owner)
return -ENOMEM;

ret = pin_request(pctldev, pin, owner, range); <--------
if (ret < 0)
kfree(owner);

return ret;
}


#############################################

static int pin_request(struct pinctrl_dev *pctldev,
int pin, const char *owner,
struct pinctrl_gpio_range *gpio_range)
{
struct pin_desc *desc;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
...
/*
* If there is no kind of request function for the pin we just assume
* we got it by default and proceed.
*/
if (gpio_range && ops->gpio_request_enable)
/* This requests and enables a single GPIO pin */
status = ops->gpio_request_enable(pctldev, gpio_range, pin);
else if (ops->request)
status = ops->request(pctldev, pin);
else
status = 0;
...
}

pin_request()里看到,如果 struct pinctrl_gpio_range 里提供了gpio_request_enable、request 函数,就把他设置为gpio功能,如果没有怎什么都不做。

以上就是大致的映射过程。有不对的地方望指正。


基于MainLine Kernel的GPIO子系统分析
http://example.com/2025/05/03/GPIO子系统/
作者
Encrow
发布于
2025年5月3日
许可协议