300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > linux kernel --- dts的相关操作函数

linux kernel --- dts的相关操作函数

时间:2022-01-05 13:58:35

相关推荐

linux kernel --- dts的相关操作函数

一、compatible匹配

1、dts 中写法

compatible = “aaa,bbb”

当一个驱动支持多个设备的时候,在每个设备的dts中,都会配置各自的compatible,当与driver中的compatible匹配后,会取各自的data。在 __of_match_node中有match++。

2、example

static const struct of_device_id plat_drv_match[] = {{.compatible = "aaa,bbb", .data = &bbb_hw_data},{.compatible = "aaa,ccc", .data = &ccc_hw_data},{}};data = of_device_get_match_data(dev);

在bbb.dts中,匹配到第1条,data就用第1条

在ccc.dts中,匹配到第2条,data就用第2条

3、源码

以下函数位于 //kernel4.14/drivers/of/device.c

const void *of_device_get_match_data(const struct device *dev){const struct of_device_id *match;match = of_match_device(dev->driver->of_match_table, dev);if (!match)return NULL;return match->data;}EXPORT_SYMBOL(of_device_get_match_data);

判断dts中的compatible属性是否包含driver中指定的compatible,

实际上返回的是dev->driver->of_match_table->data。

data是void *类型,自己如果想取到data里的值,就可以自己定义类型,里面可以放一些自己需要的参数。

二、根据dts中的reg-names得到dts中配置的reg

1、dts 中写法

reg的参数:第一个是地址,第二个是映射长度。

如果是32位,reg = <0x80000000 0x1000>;

如果是64位,reg = <0 0x80000000 0 0x1000>;

reg-names = “bbb”;

2、example

resource = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bbb");addr = resource->start; //为reg中的起始地址size = resource_size(resource); //为reg中的内存大小virt_addr = devm_ioremap_nocache(&pdev->dev, addr, size); //物理地址和虚拟地址的映射

3、源码

以下函数位于 //kernel4.14/drivers/base/platform.c

/*** platform_get_resource_byname - get a resource for a device by name* @dev: platform device* @type: resource type* @name: resource name*/struct resource *platform_get_resource_byname(struct platform_device *dev,unsigned int type,const char *name){u32 i;for (i = 0; i < dev->num_resources; i++) {struct resource *r = &dev->resource[i];if (unlikely(!r->name))continue;if (type == resource_type(r) && !strcmp(r->name, name))return r;}return NULL;}EXPORT_SYMBOL_GPL(platform_get_resource_byname);

因为linux 会通过dts进行设备(platform_device)的注册和初始化信息。其中就会有将dts中的reg,reg-names匹配到dev->resource等参数,struct resource结构体里就定义了设备的资源信息:所占内存的起始地址和结束地址,flag 是IORESOURCE_MEM还是IORESOURCE_IRQ等。所以这里通过这个函数platform_get_resource_byname就可以得到所占内存空间的物理地址resource->start。

以下函数位于 //kernel4.14/lib/devres.c

/*** devm_ioremap_nocache - Managed ioremap_nocache()* @dev: Generic device to remap IO address for* @offset: Resource address to map* @size: Size of map** Managed ioremap_nocache(). Map is automatically unmapped on driver* detach.*/void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,resource_size_t size){void __iomem **ptr, *addr;ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);if (!ptr)return NULL;addr = ioremap_nocache(offset, size);if (addr) {*ptr = addr;devres_add(dev, ptr);} elsedevres_free(ptr);return addr;}EXPORT_SYMBOL(devm_ioremap_nocache);

将物理地址映射到虚拟地址,不过cache,DMA可以和cpu直接交互。

三、通过dts中irq的name得到irq_num中断号

1、dts 中写法

interrupts = <GIC_SPI 12 IRQ_TYPE>;

interrupt-names = “irq_name”;

解释:

GIC_SPI:共享中断;GIC_PPI:每个处理器拥有独立中断

12 硬件中断号

IRQ_TYPE:电平触发还是上下沿触发(IRQ_TYPE_LEVEL_HIGH…)

2、example

irq_num = platform_get_irq_byname(dev, "irq_name");

得到的irq_num 就是中断号

3、源码

以下函数位于 //kernel4.14/drivers/base/platform.c

/*** platform_get_irq_byname - get an IRQ for a device by name* @dev: platform device* @name: IRQ name*/int platform_get_irq_byname(struct platform_device *dev, const char *name){struct resource *r;if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) {int ret; ret = of_irq_get_byname(dev->dev.of_node, name);if (ret > 0 || ret == -EPROBE_DEFER)return ret; }r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);return r ? r->start : -ENXIO;}EXPORT_SYMBOL_GPL(platform_get_irq_byname);

of_irq_get_byname:在interrupt-names这个属性中查找name这个名字。如果成功会返回linux irq number。

四、通过syscon(system control)中name得到配置的regmap

syscon这个属性自我理解是:对这个外设系统的一些控制。

regmap这个机制只要目的是减少慢速I/O驱动上的重复逻辑,提供一种通用的接口来操作底层硬件上的寄存器。regmap 除了能做到统一的I/O接口,还可以在驱动和硬件IC之间做一层缓存,从而减少底层I/O的操作次数。

1、dts 中写法

syscons = <&aaa_regs0x8000000000x1>syscon-names = "thatsok";

解释:&代表引用节点,说明aaa_regs在其他地方有定义

2、example

syscon_regmap_lookup_by_name(dev.of_node, "thatsok");syscon_get_args_by_name(dev.of_node, "thatsok", 2, reg_info);

3、源码

以下函数位于 //kernel4.14/drivers/mfd/syscon.c

struct regmap *syscon_regmap_lookup_by_name(struct device_node *np,const char *name){struct device_node *syscon_np;struct of_phandle_args args;struct regmap *regmap;int index = 0;int rc; if (name)index = of_property_match_string(np, "syscon-names", name);if (index < 0)return ERR_PTR(-EINVAL);rc = of_parse_phandle_with_args(np, "syscons", "#syscon-cells", index,&args);if (rc)return ERR_PTR(rc);syscon_np = args.np;if (!syscon_np)return ERR_PTR(-ENODEV);regmap = syscon_node_to_regmap(syscon_np);of_node_put(syscon_np);return regmap;}EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_name);

在syscon-names这个属性中找到name这个名字,找到regmap,也就是dts中的第一个参数aaa_regs对应的regmap

int syscon_get_args_by_name(struct device_node *np,const char *name,int arg_count,unsigned int *out_args){struct of_phandle_args args;int index = 0;int rc;if (name)index = of_property_match_string(np, "syscon-names", name);if (index < 0)return -EINVAL;rc = of_parse_phandle_with_args(np, "syscons", "#syscon-cells", index,&args);if (rc)return rc;if (arg_count > args.args_count)arg_count = args.args_count;for (index = 0; index < arg_count; index++)out_args[index] = args.args[index];of_node_put(args.np);return arg_count;}EXPORT_SYMBOL_GPL(syscon_get_args_by_name);

在syscon-names这个属性中找到name这个名字,找到arg_count个参数,分别放在out_args中,即dts中的reg_info[0], reg_info[1]…

五、of相关函数

主要介绍常用函数 位于kernel4.14/include/linux/of.h 会调用到kernel4.14/drivers/of/property.c中

1、解析字节

dts中写法:

bbb-property = <1>;

example:

u32 num;of_property_read_u32(np, "bbb-property", &num);

找到bbb-property这个属性,取出里面的值放到num中去

static inline int of_property_read_u32(const struct device_node *np,const char *propname,u32 *out_value)

2、解析数组

dts中写法 :bbb-property = <1, 2, 3, 4>

也可以写 bbb-property = <1, 2>, < 3, 4>

of_property_read_u32_array

example

u32 *buf_info;of_property_read_u32_array(np, "bbb-property", buf_info, 4);

在dts中查找"bbb-property"这个属性,读出4个数据,依次放在buf[0]…buf[3]中.

int of_property_read_u32_array(const struct device_node *np,const char *propname,u32 *out_values, size_t sz)

3、解析字符串list

dts中写法:

bbb-names = "aaa", "bbb", "ccc", "ddd"

example

int count;char *name;count = of_property_count_strings(dev.of_node, "bbb-names");for (i = 0; i < count; i++)of_property_read_string_index(np, "bbb-names", i, &name);

通过在dts中找到bbb-names这个属性,调用of_property_count_strings,得到有count个字符串

通过i作为index索引,取出每个字符串,这里要注意,每次取出来的都是放在首地址处的,用数组来表示的话,每一个索引,都是放在name[0]处。

static inline int of_property_read_string_index(const struct device_node *np,const char *propname,int index, const char **output)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。