了解设备树API(2)

1 内核中的设备树API

作用函数
遍历节点下的所有子节点for_each_child_of_node(dev)
判断具体的设备匹配int of_device_is_compatible(const struct device_node* device, const char *compat)
展开platform_deviceof_platform_bus_probe(NULL, xxx_of_bus_ids, NULL)
找到匹配节点,返回数据of_find_matching_node(NULL, 12x0_ids); 例子
匹配节点of_match_node(12x0_ids, np); 例子
不关心名字,获取gpioof_get_gpio(struct device_node *np, int index)
关心gpio名字的情况of_get_named_gpio(np, “cd-gpios”, 0); 例子
获取platform中断int platform_get_irq(struct platform_device *dev, unsigned int num)
被命名了的platform中断获取platform_get_irq_byname(pdev, “dema-tx”); 例子
获取时钟devm_clk_get(&pdev->dev, “general”); 例子

2 常用的OF API

序号作用函数参数作用
1寻找节点struct device_node *
of_find_compatible_node();
1)struct device_node *from,
2)const char *type,
3)const char *compatible
根据兼容属性,获取设备节点;
在大多数情况下,from,type 为NULL, 则表示遍历了所有节点。
2读取属性int
of_property_read_u8/16/32/u64_array();
1)const struct device_node *np,
2)const char *propname,
3)u8/16/32/64 *out_values,
4)size_t sz
读取设备节点np的属性名,常用的是u32
3字符串属性int
of_property_read_string();
1)struct device_node *np,
2)const char *propname,
3)const char **out_string.
读取字符串
3-1-int
of_property_read_string_index();
1)struct device_node *np,
2)const char *propname,
3)int index,
4)const char**output
读取字符串数组属性中的第index个字符串
4读取bool型属性static inline bool
of_property_read_bool();
1)const struct device_node *np,
2)const char *propname
如果设备节点np有propname属性,返回true,否则返回false.
一般用于检查空属性是否存在
5内存映射void __iomem *
of_iomap();
1)struct device_node *node,
2) int index
可以通过设备节点进行设备内存区间的ioremap(),index是内存段的索引。
若设备节点的reg属性有多段,可以通过index标示要ioremap()的是哪一段。 只有1段的情况下,index为0。
6通过设备节点获取与它对应的内存资源的resource结构体int
of_address_to_resource();
1)struct device_node *dev,
2)int index,
3)struct resource *r
本质是分析reg属性以获取内存基地址、大小等信息并填充到struct resource *r参数指向的结构体中。
7解析中断unsigned int
irq_of_parse_and_map();
1)struct device_node *dev,
2)int index
通过设备树获取设备的中断号,
实际上是从.dts中的interrupts属性里解析出中断号。 若设备使用了多个中断,index指定中断的索引号。
8获取与节点对应的platform_devicestruct platform_device *
of_find_device_by_node();
1)struct device_node *np在可以拿到device_node的情况下,如果想反向获取对应的platform_device,可使用该API;
反之,则可以使用:
**device_node *dn = op->dev.of_node;**获取。注:op 为 platform_device *op 类型。
9根据路径找到节点struct device_node *
of_find_node_by_path();
1)struct device_node *from,
2)const char *path
from:开始查找的节点,NULL表示从根节点开始查找;
path:查找的节点名
10根据“device_type“属性来查找节点struct device_node *
of_find_node_by_type();
1)struct device_node *from,
2)const char *type
不建议使用, 建议使用1
11节点属性名struct property *
of_find_property();
1)const struct device_node *np,
2)const char *name,
3)int *lenp
查找节点中的属性
试读一个设备树相关的代码
#linux-4.9.88\drivers\gpio\gpio_ath79.c
static int ath79_gpio_probe(struct platform_device *pdev)
{
	struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct device_node *np = pdev->dev.of_node;
	struct ath79_gpio_ctrl *ctrl;
	struct resource *res;
	u32 ath79_gpio_count;
	bool oe_inverted;
	int err;

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

	if (np) {
		err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
		if (err) {
			dev_err(&pdev->dev, "ngpios property is not valid\n");
			return err;
		}
		oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
	} else if (pdata) {
		ath79_gpio_count = pdata->ngpios;
		oe_inverted = pdata->oe_inverted;
	} else {
		dev_err(&pdev->dev, "No DT node or platform data found\n");
		return -EINVAL;
	}

	if (ath79_gpio_count >= 32) {
		dev_err(&pdev->dev, "ngpios must be less than 32\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	ctrl->base = devm_ioremap_nocache(
		&pdev->dev, res->start, resource_size(res));
	if (!ctrl->base)
		return -ENOMEM;

	spin_lock_init(&ctrl->lock);
	err = bgpio_init(&ctrl->gc, &pdev->dev, 4,
			ctrl->base + AR71XX_GPIO_REG_IN,
			ctrl->base + AR71XX_GPIO_REG_SET,
			ctrl->base + AR71XX_GPIO_REG_CLEAR,
			oe_inverted ? NULL : ctrl->base + AR71XX_GPIO_REG_OE,
			oe_inverted ? ctrl->base + AR71XX_GPIO_REG_OE : NULL,
			0);
	if (err) {
		dev_err(&pdev->dev, "bgpio_init failed\n");
		return err;
	}
	/* Use base 0 to stay compatible with legacy platforms */
	ctrl->gc.base = 0;

	err = gpiochip_add_data(&ctrl->gc, ctrl);
	if (err) {
		dev_err(&pdev->dev,
			"cannot add AR71xx GPIO chip, error=%d", err);
		return err;
	}

	if (np && !of_property_read_bool(np, "interrupt-controller"))
		return 0;

	err = gpiochip_irqchip_add(&ctrl->gc, &ath79_gpio_irqchip, 0,
				handle_simple_irq, IRQ_TYPE_NONE);
	if (err) {
		dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n");
		goto gpiochip_remove;
	}

	gpiochip_set_chained_irqchip(&ctrl->gc, &ath79_gpio_irqchip,
				platform_get_irq(pdev, 0),
				ath79_gpio_irq_handler);

	return 0;

gpiochip_remove:
	gpiochip_remove(&ctrl->gc);
	return err;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值