linux 设备树视频教程,设备树教程

# 设备树组成

## 文件类型

```

.dts 是ASCII的文本格式的设备树描述,一个.dts对应一个ARM设备,一般放在arch/arm/boot/dts下

.dtsi 类似c .h文件 是所有公用部分的提炼

dtb 被编译后的文件能够被linux识别 uboot也能识别

dtc是编译 .dts为.dtb的工具

dtc源码在 scripts/dtc/Makefile hostprogs-y:=dtc

ubuntu安装dtc sudo apt-get install device-tree-complier

soc被选中 dtc会被编译

arch/arm/boot/dts/Makefile 列举要编译的设备树

例如:

dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frdm.dtb

dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-qds.dtb

dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-rdb.dtb

dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb

```

## 绑定

```

在 Documentation/devicetree/bindings下有绑定有设备绑定信息介绍

```

```

UBoot支持设备树 使能: #define CONFIG_OF_LIBFDT

```

# 根节点兼容

```

compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

static const char * const imx6ul_dt_compat[] __initconst = {

"fsl,imx6ul",

"fsl,imx6ull",

"fsl,imx6ulz",

NULL,

};

DT_MACHINE_START(IMX6UL, "Freescale i.MX6 UltraLite (Device Tree)")

.map_io = imx6ul_map_io,

.init_irq = imx6ul_init_irq,

.init_machine = imx6ul_init_machine,

.init_late = imx6ul_init_late,

.dt_compat = imx6ul_dt_compat,

MACHINE_END

int of_machine_is_compatible(const char *compat); 判断具体电路板

```

# 设备节点兼容

```

int of_device_is_compatible(const struct device_node *device, const char *); 判断节点属性是否包含

static const struct of_device_id a1234_i2c_of_match[] = {

{.compatible = "acme,a1234-i2c-bus", .data = (void *)&fns}, // .data附加数据

{},

}

MODULE_DEVICE_TABLE(of, a1234_i2c_of_match); 热插拔设备自动加载驱动 usb pcie platform

static struct platform_driver i2c_a1234_driver = {

.driver = {

.name = "a1234-i2c-bus",

.owner = THIS_MODULE,

.of_match_table = a1234_i2c_of_match

}

.probe = i2c_probe

.remove = i2c_remove

}

module_platfrom_driver(i2c_a123_driver) 注册驱动到内核

```

## 一个驱动兼容多个设备

```

1. int of_device_is_compatible(const struct device_node *device, const char *compat)

查看设备兼容属性

2. 设备驱动附加数据 .data

static const struct of_device_id a1234_i2c_of_match[] = {

{.compatible = "acme,a1234-i2c-bus", .data = (void *)&fns}, // .data附加数据

{},

}

```

#

# 设备树常用OF操作函数

## 查找节点的 OF 函数

```

struct device_node *of_find_node_by_name(struct device_node *from, const char *name);

struct device_node *of_find_node_by_type(struct device_node *from, const char *type)

struct device_node *of_find_compatible_node(struct device_node *from,const char *type,const char *compatible)

struct device_node *of_find_matching_node_and_match(struct device_node *from,

const struct of_device_id *matches,

const struct of_device_id **match)

inline struct device_node *of_find_node_by_path(const char *path)

//!

struct device_node *of_get_parent(const struct device_node *node)

struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev)

```

# 设备树使用和语法

## **status属性**

```

值 值 描述

“okay” 表明设备是可操作的。

“disabled”

表明设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备

插入以后。至于 disabled 的具体含义还要看设备的绑定文档。

“fail”

表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可

操作。

“fail-sss” 含义和“fail”相同,后面的 sss 部分是检测到的错误内容。

```

## **获取匹配入口 of\_device\_id表**

```

const struct of_device_id *of_id =

of_match_device(mxs_auart_dt_ids, &pdev->dev);

if (of_id) {

/* Use of_id->data here */

[...]

}

const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev);

```

## **获取时钟(clocks )**

```

clocks =

clocks = , ;

clock-names = "nbclk", "fixed";

s->clk = clk_get(&pdev->dev, NULL);

struct clk *clk_get(struct device *dev, const char *id);

clk_prepare(clk);

clk_enable(clk);

clk_disable(clk);

Main kernel clock API

devm_get_clk(): looks up and obtains from the device tree a managed reference to a clock producer, to a root clock or to a clock node.

clk_prepare_enable(): selects a parent clock, configures the corresponding multiplexor and dividor, and enables the clock gating.

clk_disable_unprepare(): unprepares and gate a clock.

clk_get_rate(): obtains the current frequency (in Hz) for a given clock.

clk_set_rate(): sets the frequency for a given clock. If a clock has several parents, the clock framework can change the parent in order to obtain a better frequency.

clk_get_parent(): gets the parent clock source for a given clock

clk_set_parent(): sets the parent clock source for a given clock

foo: foo@abcdefgh {

compatible = "foo-driver";

clocks = , ;

clock-names = "foo1", "foo2";

};

static int foo_probe(struct platform_device *pdev)

{

priv->foo1clk = devm_clk_get(&pdev->dev, "foo1");

if (IS_ERR(priv->foo1clk)) {

ret = PTR_ERR(priv->foo1clk);

if (ret != -ENOENT) {

dev_err(&pdev->dev, "Can't get 'foo1' clock\n");

return ret;

}

}

priv->foo2clk = devm_clk_get(&pdev->dev, "foo2")';

if (IS_ERR(priv->foo2clk)) {

ret = PTR_ERR(priv->foo2clk);

if (ret != -ENOENT) {

dev_err(&pdev->dev, "Can't get 'foo2' clock\n");

return ret;

}

}

}

ret = clk_prepare_enable(priv->foo1clk);

if (ret < 0) {

dev_err(dev, "foo1 clk enable failed\n");

goto err_bclk_disable;

}

```

## **获取IO 寄存器资源(reg)**

```

reg = <0x8006a000 0x2000>

iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);

port->base = devm_ioremap_resource(&pdev->dev, iores);

struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);

struct resource *platform_get_resource_byname(struct platform_device* *dev*, unsigned int* type*, const char* *name*)

//!映射

void __iomem *devm_platform_ioremap_resource(struct platform_device* pdev, unsigned int *index)

void __iomem *devm_platform_ioremap_resource_byname(struct platform_device* *pdev*, const char* *name*)

```

## **获取中断(interrupts)**

```

interrupts = ,

;

interrupt-parent = ;

interrupts = <18 IRQ_TYPE_EDGE_BOTH>;

int irq = platform_get_irq(pdev, 0);

if (irq < 0)

return irq;

int platform_get_irq(struct platform_device *, unsigned int);

int platform_get_irq_byname(struct platform_device* *dev*, const char* *name*)

//非 platform 获取和映射中断

unsigned int irq_of_parse_and_map(struct device_node *node, int index);

```

*****

## **获取DMA channel (dmas )**

```

dmas = ,

dma-names = "rx", "tx"

s->rx_dma_chan = dma_request_slave_channel(s->dev, "rx");

s->tx_dma_chan = dma_request_slave_channel(s->dev, "tx");

struct dma_chan * __deprecated dma_request_slave_channel(struct device *dev, const char *name);

```

## **pinctrl 子系统**

```

pinctrl_usdhc1: usdhc-1 {

fsl,pins = <

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */

......

>;

};

&usdhc1 {

pinctrl-names = "default", "state_100mhz", "state_200mhz";

pinctrl-0 = ;

pinctrl-1 = ;

pinctrl-2 = ;

}

如果 pinctrl-names 为 “default”,那么这种功能状态将设置为默认的引脚状态,代码中无需处理

处理

pctrl = devm_pinctrl_get(dev);

pstate = pinctrl_lookup_state(pctrl, "state_100mhz");

pinctrl_select_state(pctrl, pstate);//设置为输出模式

```

## **gpio子系统**

```

1. 首先设置 pinctrl gpio引脚复用为gpio

pinctrl_led: ledgrp {

fsl,pins = <

MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */

>;

};

2. 定义gpio

gpioled {

#address-cells = <1>;

#size-cells = <1>;

compatible = "atkalpha-gpioled";

pinctrl-names = "default";

pinctrl-0 = ;

led-gpio = ;

status = "okay";

}

3. 驱动使用

//从设备树获取

int of_gpio_named_count(struct device_node *np, const char *propname)

int of_gpio_count(struct device_node *np)

int of_get_named_gpio(struct device_node *np, const char *propname, int index)

//!设置gpio状态

int gpio_request(unsigned gpio, const char *label)

void gpio_free(unsigned gpio)

int gpio_direction_input(unsigned gpio)

int gpio_direction_output(unsigned gpio, int value)

int gpio_get_value(unsigned gpio)

void gpio_set_value(unsigned gpio, int value)

//获取中断

int gpio_to_irq(unsigned int gpio)

```

#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值