build_embed_linux_system

驱动资源管理接口

linux内核提供一系列devm_*开头的函数,在已有的函数基础增加管理,可以在驱动卸载时自动释放资源,无需再手动释放,关于devm的相关接口可以详见Linux/Documentation/driver-api/driver-model/devres.rst。

conclusion

can

alloc_candev

//函数原型
#define alloc_candev(sizeof_priv, echo_skb_max) \
    alloc_candev_mqs(sizeof_priv, echo_skb_max, 1, 1)

struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
                unsigned int txqs, unsigned int rxqs);

//参数
sizeof_priv: 私有数据长度
echo_skb_max: socket buffer数组个数
txqs: 发送队列个数
rxqs: 接收队列个数
返回: 成功获取can设备管理结构,失败返回NULL指针

//例程
struct net_device *dev;
dev = alloc_candev(sizeof(struct flexcan_priv), 1);

clock

of_clk_get

//函数原型
struct clk *of_clk_get(struct device_node *np, int index)

//参数
np: 指向设备device_node的指针
index: dtsclks属性中的索引
返回: 成功获取时钟资源,失败返回对应错误码

//例程
clk[i].clk = of_clk_get(np, i);

devm_clk_get

//函数原型
struct clk *devm_clk_get(struct device *dev, const char *id)
{
    return __devm_clk_get(dev, id, clk_get, NULL, NULL);
}
struct clk *clk_get(struct device *dev, const char *con_id)

//参数
dev: 总线匹配的设备
id: 需要获取的clocks内属性的别名,一般由clock-names定义,没有clock-names属性clocks内只有一个,此时对应NULL
返回: 成功获取的时钟资源,可用于模块时钟管理(使能,关闭),失败返回对应错误码指针ERR_PTR(-err)

//例程
//时钟在设备树的说明
i2c1: i2c@21a0000 {
    //......
    clocks = <&clks IMX6UL_CLK_I2C1>;
}

i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);

devm_clk_get_enabled

//函数原型
struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
{
    return __devm_clk_get(dev, id, clk_get,
                    clk_prepare_enable, clk_disable_unprepare);
}

//参数
dev: 总线匹配的设备
id: 需要获取的clocks内属性的别名,一般由clock-names定义,没有clock-names属性clocks内只有一个,此时对应NULL
返回: 成功则获取时钟资源结构,失败返回NULL指针

//例程
pvt->clk = devm_clk_get_enabled(dev, NULL);

devm_clk_get_optional

//函数原型
struct clk *devm_clk_get_optional(struct device *dev, const char *id)
{
    return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
}
clk *clk_get_optional(struct device *dev, const char *id);

//参数
dev: 总线匹配的设备
id: 需要获取的clocks内属性的别名,一般由clock-names定义,没有clock-names属性clocks内只有一个,此时对应NULL
返回: 成功则获取时钟资源结构,失败返回NULL指针

//例程
//时钟在设备树的说明
i2c1: i2c@21a0000 {
    //......
    clocks = <&clks IMX6UL_CLK_I2C1>;
}

i2c_imx->clk = devm_clk_get_optional(&pdev->dev, NULL);

devm_clk_put

//函数原型
void devm_clk_put(struct device *dev, struct clk *clk)

//参数
dev: 总线匹配的设备
clk: 获取的clocks时钟对象(对应设备树中的clocks定义)

//例程
devm_clk_put(&pdev->dev, clk);

devm_clk_bulk_get

//函数原型
int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
            struct clk_bulk_data *clks)
{
    return __devm_clk_bulk_get(dev, num_clks, clks, false);
}

//参数
dev: 管理资源的设备,一般为总线匹配的设备
num_clks 获取时钟句柄的数目
clks: clk参数列表,分别对应时钟id和时钟句柄
struct clk_bulk_data {
    const char *id;
    struct clk *clk;
};
返回: 成功返回0,其它返回错误码

//例程
ret = devm_clk_bulk_get(&pdev->dev, msm_host->num_bus_clks, msm_host->bus_clks);

devm_clk_bulk_get_all

//函数原型
int __must_check devm_clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
clks: 指向时钟资源指针的指针
struct clk_bulk_data {
    const char *id;
    struct clk *clk;
};
返回: 成功返回0,其它返回错误码

//例程
rc = devm_clk_bulk_get_all(dev, &hpriv->clks);

devm_clk_bulk_get_optional

//函数原型
int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
            struct clk_bulk_data *clks)
{
    return __devm_clk_bulk_get(dev, num_clks, clks, true);
}

//参数
dev: 管理资源的设备,一般为总线匹配的设备
num_clks 获取时钟句柄的数目
clks: clk参数列表,分别对应时钟id和时钟句柄
struct clk_bulk_data {
    const char *id;
    struct clk *clk;
};
返回: 成功返回0,其它返回错误码

//例程
ret = devm_clk_bulk_get_optional(&pdev->dev, num_clocks, bulk);

devm_get_clk_from_child

//函数原型
struct clk *devm_get_clk_from_child(struct device *dev,
                struct device_node *np, const char *con_id)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
np 指向device_node的指针
con_id: 子节点时钟信息别名
返回: 成功返回时钟句柄,失败返回错误码

//例程
qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL);

clk_set_parent

//函数原型
int clk_set_parent(struct clk *clk, struct clk *parent)

//参数
clk: 准备操作的时钟句柄
parent: 父时钟的时钟句柄
返回: 0表示成功,其它表示设置失败

//例程
clk_set_parent(pll1_bypass_clk, pll1_bypass_src_clk);

clk_get_parent

//函数原型
struct clk *clk_get_parent(struct clk *clk)

//参数
clk: 准备操作的时钟句柄
返回: 成功返回父时钟的时钟句柄,失败返回NULL

//例程
parent = clk_get_parent(clk);

clk_prepare

//函数原型
int clk_prepare(struct clk *clk)

//参数
clk: 准备操作的时钟句柄
返回: 成功返回0,失败返回对应时钟句柄

//例程
ret = clk_prepare(clk);

//备注:clk_prepare(该函数可能睡眠)和可以在原子上下文调用的clk_enable,而clk_prepare_enable则同时完成prepare和enable的工作,只能在可能睡眠的上调用API

clk_enable

//函数原型
int clk_enable(struct clk *clk)

//参数
clk: 准备操作的时钟句柄
返回: 成功返回0,失败返回对应时钟句柄

//例程
ret = clk_enable(clk);

clk_prepare_enable

//函数原型
static inline int clk_prepare_enable(struct clk *clk)

//参数
clk:指向准备操作的时钟句柄。这个时钟对象通常是在设备树(Device Tree)中定义的,或者在设备驱动程序初始化时通过其他方式获得的
返回: 0表示启用成功,失败返回负数的错误码

//例程
i2c1: i2c@21a0000 {
    clocks = <&clks IMX6UL_CLK_I2C1>;
};

i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
ret = clk_prepare_enable(i2c_imx->clk);

clk_disable

//函数原型
void clk_disable(struct clk *clk)

//参数
clk:指向准备操作的时钟句柄。

//例程
clk_disable(i2c_imx->clk);

clk_unprepare

//函数原型
void clk_unprepare(struct clk *clk)

//参数
clk:指向准备操作的时钟句柄。

//例程
clk_unprepare(i2c_imx->clk);

clk_disable_unprepare

//函数原型
void clk_disable_unprepare(struct clk *clk)

//参数
clk:指向准备操作的时钟句柄。

//例程
clk_disable_unprepare(i2c_imx->clk);

clk_get_rate

//函数原型
unsigned long clk_get_rate(struct clk *clk)

//参数
clk:准备操作的时钟句柄
返回:获取的时钟频率

//例程
//时钟在设备树的说明
ckil: clock-cli {
    //......
    #clock-cells = <0>;
    clock-frequency = <32768>;
    clock-output-names = "ckil";
};
clks: clock-controller@20c4000 {
    //......
    #clock-cells = <1>;
    clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
    clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
};

clk = devm_clk_get(&pdev->dev, "ckil");
rate = clk_get_rate(clk); //获取clock-frequency属性

clk_set_rate

//函数原型
int clk_set_rate(struct clk *clk, unsigned long rate)

//参数
clk:准备操作的时钟句柄
rate: 希望设备的时钟频率
返回:成功返回0,失败返回对应错误码

//例程
clk_set_rate(ahb_clk, LPAPM_CLK);

devm_clk_hw_register

devm_of_clk_add_hw_provider

devm_clk_hw_register_clkdev

devm_reset_control_get

reset_control_assert

reset_control_deassert

reset_control_reset

gpio

关于gpio的接口可以查看文档: Documentation/driver-api/gpio/consumer.rst

devm_gpiod_get

//函数原型
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
        const char *con_id,
        enum gpiod_flags flags)
{
    return devm_gpiod_get_index(dev, con_id, 0, flags);
}

//参数
dev: 管理资源的设备,一般为总线匹配的设备
con_id: gpio属性id名称,"led"表示led-gpios属性,如果为NULL则表示gpios属性
flags: 设置GPIO的状态
    GPIOD_ASIS  默认状态
    GPIOD_IN    输入状态
    GPIOD_OUT_LOW   输出状态,默认输出为0
    GPIOD_OUT_HIGH  输出状态,默认输出为1
    GPIOD_OUT_LOW_OPEN_DRAIN 输出状态,开漏模式,默认输出0
    GPIOD_OUT_HIGH_OPEN_DRAIN   输出状态,开漏模式,默认输出1
返回:成功返回获取的引脚句柄,失败返回对应错误码

//例程
beep {
    beep-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
};
static gpio_desc *desc = devm_gpiod_get(&pdev-dev, "beep", GPIOD_OUT_LOW);

devm_gpiod_get_optional

devm_gpiod_get_array

//函数原型
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
                        const char *con_id,
                        enum gpiod_flags flags)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
con_id: gpio属性id名称,"led"表示led-gpios属性,如果为NULL则表示gpios属性
flags: 设置GPIO的状态
返回:成功返回引脚句柄数组,失败返回对应错误码

//例程
usr_loopled {
    //...
    leds-gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>,
                <&gpio4 23 GPIO_ACTIVE_HIGH>,
                <&gpio4 25 GPIO_ACTIVE_HIGH>;
};
static gpio_descs *descs = devm_gpiod_get_array(&pdev-dev, "leds", GPIOD_OUT_LOW);

devm_gpiod_get_array_optional

devm_gpiod_get_index

//函数原型
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
              const char *con_id,
              unsigned int idx,
              enum gpiod_flags flags)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
con_id: gpio属性id名称,如led-gpios属性,则输入led,必须时xx-gpios属性
idx: gpio资源中的标签
flags: 详细见devm_gpiod_get
返回:成功返回引脚句柄,失败返回对应错误码

//例程
leds-gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>,
            <&gpio4 23 GPIO_ACTIVE_HIGH>,
            <&gpio4 25 GPIO_ACTIVE_HIGH>; 
chip->desc[0] = devm_gpiod_get_index(&pdev-dev, "leds", 0, GPIOD_OUT_LOW);
chip->desc[1] = devm_gpiod_get_index(&pdev-dev, "leds", 1, GPIOD_OUT_LOW);

devm_gpiod_get_index_optional

devm_gpiod_put

//函数原型
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
desc: 申请的引脚句柄资源

//例程
devm_gpiod_put(&pdev->dev, desc);

devm_gpiod_unhinge

//函数原型
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
desc: 申请的引脚描述符资源

//例程
devm_gpiod_unhinge(&pdev->dev, desc);

devm_gpiochip_add_data

devm_gpio_request

//函数原型
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
gpiogpio对应的标签值,通过of_get_named_gpio可以获取
label: 申请的gpio别名
返回: 0表示申请成功,其它则失败

//例程
ret = devm_gpio_request(&pdev->dev, chip->gpio, "beep");

devm_gpio_request_one

//函数原型
int devm_gpio_request_one(struct device *dev, unsigned gpio,
                    unsigned long flags, const char *label)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
gpiogpio对应的标签值,通过of_get_named_gpio可以获取
flagsGPIOF_*开头定义的gpio配置
* GPIOF_DIR_IN      - to configure direction as input
* GPIOF_DIR_OUT     - to configure direction as output
* GPIOF_INIT_LOW    - as output, set initial level to LOW
* GPIOF_INIT_HIGH   - as output, set initial level to HIGH
* GPIOF_OPEN_DRAIN  - gpio pin is open drain type.
* GPIOF_OPEN_SOURCE - gpio pin is open source type.
* GPIOF_EXPORT_DIR_FIXED    - export gpio to sysfs, keep direction
* GPIOF_EXPORT_DIR_CHANGEABLE   - also export, allow changing direction
* GPIOF_IN              - configure as input
* GPIOF_OUT_INIT_LOW    - configured as output, initial level LOW
* GPIOF_OUT_INIT_HIGH   - configured as output, initial level HIGH

label: 申请的gpio别名
返回: 0表示申请成功,其它则失败

//例程
chip->key_gpio = of_get_named_gpio(nd, "key-gpios", 0);
devm_gpio_request(&pdev->dev, chip->gpio, "beep");

i2c

devm_i2c_add_adapter

devm_i2c_new_dummy_device

io_region

devm_release_mem_region

devm_release_region

devm_release_resource

devm_request_mem_region

//函数原型
#define devm_request_mem_region(dev,start,n,name) \
    __devm_request_region(dev, &iomem_resource, (start), (n), (name))
struct resource *__devm_request_region(struct device *dev, struct resource *parent,
        resource_size_t start, resource_size_t n, const char *name)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
type: 资源指针,这里特指MEM资源
start: 资源的起始地址
n: 资源的总长度
name: 使用资源的用户名称,用于内核标记
返回: NULL表示获取失败,其它返回resoure对应的指针地址

//例程
if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), DRIVER_NAME)) {
    dev_warn(&pdev->dev, "Failed to get memory region resource\n");
    return -ENOENT;
}

devm_request_free_mem_region

devm_request_region

//函数原型
#define devm_request_region(dev,start,n,name) \
        __devm_request_region(dev, &ioport_resource, (start), (n), (name))
struct resource *__devm_request_region(struct device *dev, struct resource *parent,
        resource_size_t start, resource_size_t n, const char *name)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
type: 资源指针,这里特指I/O资源
start: 资源的起始地址
n: 资源的总长度
name: 使用资源的用户名称,用于内核标记
返回: NULL表示获取失败,其它返回resoure对应的指针地址

//例程
struct resource *res_gpi;
if (!devm_request_region(&pdev->dev, res_gpi->start, resource_size(res_gpi), MODULE_NAME "_gpi")) {
    dev_warn(&pdev->dev, "GPI I/O resource busy, probably claimed by ACPI\n");
}

devm_request_resource

//函数原型
struct resource *platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
type: 资源的类型, IORESOURCE_IO, IORESOURCE_MEM, IORESOURCE_REG, IORESOURCE_IRQ, IORESOURCE_DMA, IORESOURCE_BUS
name: 资源的名称
返回: NULL表示获取失败,其它返回resoure对应的指针地址

//例程
//interrupt-name指定中断的name,通过platform_get_resource_byname访问
interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
            <0 9 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "edma-tx", "edma-err";
fsl_edma->errirq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "edma-err")

irq

devm_free_irq

//函数原型
void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
irp: 被申请得中断线号
dev_id: 释放设备的标识指针

//例程
devm_free_irq(dev, priv->irq, priv);

devm_request_any_context_irq

//函数原型
int devm_request_any_context_irq(struct device *dev, unsigned int irq,
                            irq_handler_t handler, unsigned long irqflags,
                            const char *devname, void *dev_id)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
irp: 被申请得中断线号
handler: irq发生时执行的中断回调函数
irqflags: 申请的中断触发的标志位,其中边沿和电平要和设备树一致,如果为0,则使用设备树中的中断标志
devname: 设备名称
dev_id: 传递给回调函数得参数

//例程
static irqreturn_t max77650_charger_check_status(int irq, void *data)
{
}

rv = devm_request_any_context_irq(dev, chg_irq,
                    max77650_charger_check_status,
                    IRQF_ONESHOT, "chg", chg);

devm_request_irq

//函数原型
static inline int __must_check
devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
            unsigned long irqflags, const char *devname, void *dev_id)
{
    return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags, devname, dev_id);
}

//参数
dev: 管理资源的设备,一般为总线匹配的设备
irp: 被申请得中断线号
handler: irq发生时执行得回调函数
irqflags: 申请的中断触发的标志位,其中边沿和电平要和设备树一致,如果为0,则使用设备树中的中断标志
devname: 设备名称
dev_id: 传递给回调函数得参数

//例程
//priv为传递的数据rngc
static irqreturn_t imx_rngc_irq(int irq, void *priv)
{
    //中断回调函数
}

ret = devm_request_irq(&pdev->dev,
    irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);

devm_request_threaded_irq

//函数原型
int devm_request_threaded_irq(struct device *dev, unsigned int irq,
          irq_handler_t handler, irq_handler_t thread_fn,
          unsigned long irqflags, const char *devname,
          void *dev_id)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
irp: 被申请得中断线号
handler: irq发生时执行得回调函数(中断上半部)
thead_fn:线程化调用的中断函数,下半部,NULL则中断
irqflags: 申请的中断触发的标志位,其中边沿和电平要和设备树一致,如果为0,则使用设备树中的中断标志
devname: 设备名称
dev_id: 传递给回调函数得参数

//例程
//tegra为传递参数
static irqreturn_t actmon_thread_isr(int irq, void *data)
{
}

err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL,
                actmon_thread_isr, IRQF_ONESHOT,
                "tegra-devfreq", tegra);

devm_irq_alloc_descs

devm_irq_alloc_desc

devm_irq_alloc_desc_at

devm_irq_alloc_desc_from

devm_irq_alloc_descs_from

devm_irq_alloc_generic_chip

devm_irq_setup_generic_chip

devm_irq_domain_create_sim

irq_of_parse_and_map

//函数原型
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)

//参数
dev: 驱动匹配的设备节点
index: interrupt属性中的编号(interrupt属性支持多组)
返回: 在内核中所在控制器中的对应的中断编号

//例程
//设备树
key {
    interrupt-parent = <&gpio1>;
    interrupts = <18 IRQ_TYPE_EDGE_BOTH>;
};

chip->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);

irq_get_trigger_type

led

devm_led_classdev_register

等同于devm_led_classdev_register_ext, 格式如下所示。

static inline int devm_led_classdev_register(struct device *parent,
                        struct led_classdev *led_cdev)
{
    return devm_led_classdev_register_ext(parent, led_cdev, NULL);
}

devm_led_classdev_register_ext

//函数原型
int devm_led_classdev_register_ext(struct device *parent,
                struct led_classdev *led_cdev,
                struct led_init_data *init_data)

//参数
parent: LED设备的父设备总线
led_cdev: led控制类结构
led_init_data: led类初始化数据
返回: 0表示注册成功,负值表示注册失败

//例程
//设备树
led_dat->cdev.brightness_set = gpio_led_set;    //对应brightness
led_dat->cdev.blink_set = gpio_blink_set;
if (template->name) {
    led_dat->cdev.name = template->name;
    ret = devm_led_classdev_register(parent, &led_dat->cdev);
} else {
    init_data.fwnode = fwnode;
    ret = devm_led_classdev_register_ext(parent, &led_dat->cdev,
                            &init_data);
}

devm_led_classdev_unregister

mem

devm_free_pages

devm_get_free_pages

devm_kasprintf

devm_kcalloc

devm_kfree

devm_kmalloc

devm_kmalloc_array

devm_kmemdup

devm_krealloc

devm_kstrdup

devm_kvasprintf

devm_kzalloc

//函数原型
void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
size: 申请数据的长度
gfp: 申请数据的类型
/*
GFP_ATOMIC: GFP_ATOMIC标记是用在中断处理函数中的,
GFP_KERNEL: 内存不够,会等待内核释放内存,因此会发生堵塞,不能用在中断处理中
...
参考:https://blog.csdn.net/21cnbao/article/details/112210900
*/
返回: 获取的内存指针首地址

static struct led_data *chip;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);

pinctrl

devm_pinctrl_get

//函数原型
struct pinctrl *devm_pinctrl_get(struct device *dev)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
返回: 管理引脚资源的句柄
struct pinctrl {
  struct list_head node;      /* 管理资源的列表 */
  struct device *dev;         /* 使用此资源的设备 */
  struct list_head states;    /* 设备状态的列表 */
  struct pinctrl_state *state;  /* 资源的状态 */
  struct list_head dt_maps;   /* 从设备树种解析的映射表块 */
  struct kref users;          /* 资源被引用的次数 */
};

//例程
usr_led {
    //...
    pinctrl-names = "default", "improve";
    pinctrl-0 = <&pinctrl_gpio_led>;
    pinctrl-1 = <&pinctrl_led_improve>;
}
pinctrl_gpio_led: gpio-leds {
    fsl,pins = <
        MX6UL_PAD_GPIO1_IO03__GPIO1_IO03        0x17059
    >;
};
pinctrl_led_improve: led-improve {
    fsl,pins = <
        MX6UL_PAD_GPIO1_IO03__GPIO1_IO03  0x40017059
    >;
};

chip->led_pinctrl = devm_pinctrl_get(&pdev->dev);
if(IS_ERR_OR_NULL(chip->led_pinctrl))
{
    dev_info(&pdev->dev, "devm_pinctrl_get failed\n");
    return -EIO;
}

devm_pinctrl_put

//函数原型
void devm_pinctrl_put(struct pinctrl *p)

//参数
p: 申请的管理引脚资源的句柄

//例程
devm_pinctrl_put(chip->led_pinctrl);

pinctrl_lookup_state

//函数原型
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
            const char *name)

//参数
p: 申请的管理引脚资源的句柄
name: pinctrl-names中的名称,与<pinctrl-num>相对应
返回: 返回name对应的pinctrl状态

//例程
struct pinctrl_state *pState = pinctrl_lookup_state(chip->led_pinctrl, "improve");

pinctrl_select_state

//函数原型
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)

//参数
p: 申请的管理引脚资源的句柄
state: 获取的引脚状态的状态配置
返回: 0表示选择成功,其它则失败

//例程
int ret = pinctrl_select_state(chip->led_pinctrl, pState);

devm_pinctrl_get_select

//函数原型
static inline struct pinctrl * __must_check devm_pinctrl_get_select(struct device *dev, const char *name)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
name: pinctrl-names属性中的名称
返回: 管理引脚资源的句柄

//例程
chip->led_pinctrl = devm_pinctrl_get(&pdev->dev "default");

devm_pinctrl_get_select_default

devm_pinctrl_register

devm_pinctrl_register_and_init

devm_pinctrl_unregister

rtc

rtc_update_irq

devm_rtc_device_register

//函数原型
struct rtc_device *devm_rtc_device_register(struct device *dev,
      const char *name,
      const struct rtc_class_ops *ops,
      struct module *owner)

//参数
dev: 管理资源的设备,一般为总线匹配的设备
name: rtc设备名称
ops:  rtc设备用于上层访问调用的接口
struct rtc_class_ops {
  int (*ioctl)(struct device *, unsigned int, unsigned long);   
  int (*read_time)(struct device *, struct rtc_time *);         //读取当前时间
  int (*set_time)(struct device *, struct rtc_time *);          //写入当前时间
  int (*read_alarm)(struct device *, struct rtc_wkalrm *);      //读取当前定时时间    
  int (*set_alarm)(struct device *, struct rtc_wkalrm *);       //写入当前定时时间
  int (*proc)(struct device *, struct seq_file *);
  int (*alarm_irq_enable)(struct device *, unsigned int enabled);
  int (*read_offset)(struct device *, long *offset);
  int (*set_offset)(struct device *, long offset);
  int (*param_get)(struct device *, struct rtc_param *param);
  int (*param_set)(struct device *, struct rtc_param *param);
};
module: 设备归属用户,一般为THIS_MODULE

//例程
static const struct rtc_class_ops pcf8563_ops = {
    .ioctl = pcf8563_rtc_ioctl,
    .read_time = pcf8563_get_time,
    .set_time = pcf8563_set_time,
    .read_alarm = pcf8563_read_alarm,
    .set_alarm = pcf8563_set_alarm,
    .alarm_irq_enable = pcf8563_alarm_irq_enable,
};
priv->rtc = devm_rtc_device_register(&pdev->dev, "pcf8563", &pcf8563_ops, THIS_MODULE);

devm_rtc_allocate_device

//函数原型
struct rtc_device *devm_rtc_allocate_device(struct device *dev)

//参数
dev: 管理rtc设备的设备(一般为platform总线设备或i2c设备)

//例程
chip->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(chip->rtc)){
    dev_err(&client->dev, "rtc alloc device failed!\n");
    return PTR_ERR(chip->rtc);
}

devm_rtc_register_device

//函数原型
#define devm_rtc_register_device(device) \
    __devm_rtc_register_device(THIS_MODULE, device)

//参数
device: 指向rtc设备的结构指针

//例程
int err;

chip->rtc->owner = THIS_MODULE;
chip->rtc->ops = &pcf8563_ops;          //设置rtc支持的接口
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, chip->rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, chip->rtc->features);
chip->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
chip->rtc->range_max = RTC_TIMESTAMP_END_2099;
chip->rtc->set_start_time = true;

//5. register the rtc device.
err = devm_rtc_register_device(chip->rtc);

devm_rtc_nvmem_register

serdev

devm_serdev_device_open

slave_dma_engine

devm_acpi_dma_controller_register

spi

devm_spi_alloc_master

devm_spi_alloc_slave

devm_spi_register_master

other

devm_add_action_or_reset

//函数原型
static inline int devm_add_action_or_reset(struct device *dev,
            void (*action)(void *), void *data)

//参数
dev:指向要添加回调函数的设备的指针。
action:指向要添加的回调函数的指针。当设备被释放或发生某些错误时,这个回调函数将被调用。
data:传递给回调函数的参数。
返回: 0表示添加成功,其它则表示添加失败

//例程
ret = devm_add_action_or_reset(dev, imx2_wdt_action, wdev->clk);

next_chapter

返回目录

直接开始下一节说明: 内核扩展资源管理接口