記錄一些Linux Device Drivers中經常使用的API。html
Linux官方提供的內核文檔:node
一、 最新版: https://www.kernel.org/doc/html/latest/linux
二、 4.10: https://www.kernel.org/doc/html/v4.10/ios
三、 Understanding the Linux Virtual Memory Manager 或者查看PDF版本ide
1、內存分配spa
1. void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)code
二、 void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)orm
三、 void devm_kfree(struct device *dev, void *p)htm
四、 struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num)
五、 int platform_get_irq(struct platform_device *dev, unsigned int num)
六、 struct resource *platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name)
七、 int platform_get_irq_byname(struct platform_device *dev, const char *name)
示例(四、五、六、7幾個API的調用):
blog
1 設備樹: 2 reg = <0x15240000 0x2c000>, 3 <0x15204000 0x20000>; 4 reg-names = "slimbus_physical", "slimbus_bam_physical"; 5 interrupts = <0 291 0>, <0 292 0>; 6 interrupt-names = "slimbus_irq", "slimbus_bam_irq"; 7 8 驅動: 9 10 struct resource *bam_mem; 11 struct resource *slim_mem; 12 struct resource *irq, *bam_irq; 13 14 15 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, 16 "slimbus_physical"); 17 等價於: platform_get_resource(pdev, IORESOURCE_MEM, 0) 18 19 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, 20 "slimbus_bam_physical"); 21 等價於: platform_get_resource(pdev, IORESOURCE_MEM, 1) 22 23 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 24 "slimbus_irq"); 25 等價於: platform_get_resource(pdev, IORESOURCE_IRQ, 0) 26 27 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 28 "slimbus_bam_irq"); 29 等價於: platform_get_resource(pdev, IORESOURCE_IRQ, 1)
八、 char *kstrdup(const char *s, gfp_t gfp);
功能: 分配一塊內存空間(kmalloc + gfp),而後將s指向的字符串拷貝到這塊內存中並返回該內存的首地址
九、void *kmemdup(const void *src, size_t len, gfp_t gfp);
功能:分配一塊長度爲len的內存(kmalloc+gfp),而後將src到(src + len)內存的內容copy到新分配的內存中,而後返回該內存的首地址
十、void *memdup_user(const void __user *src, size_t len);
功能: 分配一塊長度爲len的內存(kmalloc + gfp),而後將用戶空間的地址src到(src+len)範圍的內存使用copy_from_user的方式拷貝到
新分配的內存當中,最後返回新分配的內存的首地址
2、GPIO相關
一、static inline int of_get_named_gpio(struct device_node *np, const char *propname, int index)
得到GPIO號, 失敗的話,會返回負數, 能夠用gpio_is_valid來檢查解析到的gpio是否合法:
1 設備樹: 2 qcom,cdc-us-euro-gpios = <&tlmm 128 0>
3
4 驅動: 5 pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node, 6 "qcom,cdc-us-euro-gpios", 0);
二、 int of_get_gpio(struct device_node *np, int index)
從設備樹的gpios屬性中解析出第index個gpio資源:
1 設備樹: 2 gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>, <&gpf1 4 GPIO_ACTIVE_HIGH>; 3 驅動: 4 int sda_pin, scl_pin; 5 6 sda_pin = of_get_gpio(np, 0); 7 scl_pin = of_get_gpio(np, 1);
3、端口映射
一、void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
示例:
二、 void devm_iounmap(struct device *dev, void __iomem *addr)
三、 void __iomem *devm_ioremap(struct device *dev, resource_size_t offset, resource_size_t size)
四、 void __iomem *of_iomap(struct device_node *np, int index)
五、void __iomem *of_io_request_and_map(struct device_node *np, int index, const char *name)
4、設備樹相關
1. bool of_property_read_bool(const struct device_node *np, const char *propname)
若是存在該屬性,那麼返回true,不然返回false
2. int of_property_read_u8(const struct device_node *np, const char *propname, u8 *out_value)
讀取一個unsigned char, 成功返回0, 失敗的話返回負數
這裏須要注意的是: 設備樹中對應的屬性是 property_name = /bits/ 8 <0x50>
3. int of_property_read_u16(const struct device_node *np, const char *propname, u16 *out_value)
讀取一個unsigned short, 成功返回0, 失敗的話返回負數
這裏須要注意的是: 設備樹中對應的屬性是 property = /bits/ 16 <0x5000 0x6000 0x7000>
4. int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value)
讀取一個unsigned int, 成功返回0, 失敗的話返回負數
五、const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node)
返回matches中跟node相匹配的那一項, 如:
1 設備樹以下: 2 sound { 3 status = "okay"; 4 compatible = "qcom,sdm660-asoc-snd"; 5 ... ... 6 } 7
8 驅動以下: 9 static const struct of_device_id sdm660_asoc_machine_of_match[] = { 10 { .compatible = "qcom,sdm660-asoc-snd", 11 .data = "internal_codec"}, 12 { .compatible = "qcom,sdm660-asoc-snd-tasha", 13 .data = "tasha_codec"}, 14 { .compatible = "qcom,sdm660-asoc-snd-tavil", 15 .data = "tavil_codec"}, 16 {}, 17 }; 18
19 static int msm_asoc_machine_probe(struct platform_device *pdev) 20 { 21 const struct of_device_id *match; 22
23 match = of_match_node(sdm660_asoc_machine_of_match, 24 pdev->dev.of_node); 25 ... ... 26 } 27
28 static struct platform_driver sdm660_asoc_machine_driver = { 29 .driver = { 30 ...... 31 .of_match_table = sdm660_asoc_machine_of_match, 32 }, 33 ...... 34 }; 35 module_platform_driver(sdm660_asoc_machine_driver);
六、 struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index)
根據一個handle property解析獲得對應的device node, 如:
1 設備樹: 2
3 sound { 4 status = "okay"; 5 compatible = "qcom,sdm660-asoc-snd"; 6 ... ... 7 qcom,us-euro-gpios = <0x1b4>; 8 ... ... 9 }; 10
11 msm_cdc_pinctrl@75 { 12 compatible = "qcom,msm-cdc-pinctrl"; 13 ... ... 14 linux,phandle = <0x1b4>; 15 phandle = <0x1b4>; 16 }; 17
18
19
20 驅動: 21 struct device_node *node; 22 node = of_parse_phandle(pdev->dev.of_node, 23 "qcom,us-euro-gpios", 0);
5、中斷
內核中其餘一些不常見的用法示例:
完。