17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Raspberry Pi 3 のDevice Tree Sourceを読む

Posted at

Raspberry Pi 3 のdevice treeの設定がカーネル内のどこで処理されるのかを調べてみました。
とりあえず、分かったところの分だけを公開。

Raspberry Pi3 の device tree の設定

ヘッダ部分

  • /dts-v1/; はdeviece treeのバージョンを示す。
  • bcm2708.dtsiをインクルードしてデフォルト設定を読み込む。この行以降はデフォルト設定から変更を行うための記述となる。
  • / { ... } はルートノードです。
/dts-v1/;

#include "bcm2710.dtsi"

/ {
	compatible = "brcm,bcm2710","brcm,bcm2709";
	model = "Raspberry Pi 3 Model B";
};

&gpio

  • &gpioのノードでmultiplexされた端子の設定を行います。
&gpio {
	sdio_pins: sdio_pins {
		brcm,pins =     <34 35 36 37 38 39>;
		brcm,function = <7>; // alt3 = SD1
		brcm,pull =     <0 2 2 2 2 2>;
	};

	bt_pins: bt_pins {
		brcm,pins = <43>;
		brcm,function = <4>; /* alt0:GPCLK2 */
		brcm,pull = <0>;
	};

	uart0_pins: uart0_pins {
		brcm,pins = <32 33>;
		brcm,function = <7>; /* alt3=UART0 */
		brcm,pull = <0 2>;
	};
  • 34 35 36 37 38 39の番号の を sdio_pinsとして使う。 34はpull無し、36 37 28 29をpull upとする。
  • 43 を bt用のクロックとして使う。 43はpull無し。
  • 32 33 を BT用のuartとして使う。 32はpull無し、33をpull upとする。

&gpioを処理する部分

  • brcm,pinsとprcm,functions,とbrcm,pullはdrivers/pinctrl/bcm/pinctrl-bcm2835.c の bcm2835_pctl_dt_node_to_map()で処理します。
  • propetry構造体のポインタ pins と funcs と pulls を of_find_property()で取得
  • 要素数 num_pins と num_funcs と num_pullsを取得
  • pinctrl_map 構造体をアロケート
  • 各ピンに対して
  • of_property_read_u32_index()でpin番号を取得
  • of_property_read_u32_index()でfunc番号を取得して、bcm2835_pctl_dt_node_to_map_func()でpinにfuncを設定する。
  • of_property_read_u32_index()でpull プルアップ/プルダウン設定を取得して、bcm2835_pctl_dt_node_to_map_pull()でpinにプルアップ/プルダウン設定をおこなう。
static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
		struct device_node *np,
		struct pinctrl_map **map, unsigned *num_maps)
{
	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
	struct property *pins, *funcs, *pulls;
	int num_pins, num_funcs, num_pulls, maps_per_pin;
	struct pinctrl_map *maps, *cur_map;
	int i, err;
	u32 pin, func, pull;

	pins = of_find_property(np, "brcm,pins", NULL);
	if (!pins) {
		dev_err(pc->dev, "%s: missing brcm,pins property\n",
				of_node_full_name(np));
		return -EINVAL;
	}

	funcs = of_find_property(np, "brcm,function", NULL);
	pulls = of_find_property(np, "brcm,pull", NULL);

	if (!funcs && !pulls) {
		dev_err(pc->dev,
			"%s: neither brcm,function nor brcm,pull specified\n",
			of_node_full_name(np));
		return -EINVAL;
	}

	num_pins = pins->length / 4;
	num_funcs = funcs ? (funcs->length / 4) : 0;
	num_pulls = pulls ? (pulls->length / 4) : 0;

	if (num_funcs > 1 && num_funcs != num_pins) {
		dev_err(pc->dev,
			"%s: brcm,function must have 1 or %d entries\n",
			of_node_full_name(np), num_pins);
		return -EINVAL;
	}

	if (num_pulls > 1 && num_pulls != num_pins) {
		dev_err(pc->dev,
			"%s: brcm,pull must have 1 or %d entries\n",
			of_node_full_name(np), num_pins);
		return -EINVAL;
	}

	maps_per_pin = 0;
	if (num_funcs)
		maps_per_pin++;
	if (num_pulls)
		maps_per_pin++;
	cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
				GFP_KERNEL);
	if (!maps)
		return -ENOMEM;

	for (i = 0; i < num_pins; i++) {
		err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
		if (err)
			goto out;
		if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
			dev_err(pc->dev, "%s: invalid brcm,pins value %d\n",
				of_node_full_name(np), pin);
			err = -EINVAL;
			goto out;
		}

		if (num_funcs) {
			err = of_property_read_u32_index(np, "brcm,function",
					(num_funcs > 1) ? i : 0, &func);
			if (err)
				goto out;
			err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
							func, &cur_map);
			if (err)
				goto out;
		}
		if (num_pulls) {
			err = of_property_read_u32_index(np, "brcm,pull",
					(num_pulls > 1) ? i : 0, &pull);
			if (err)
				goto out;
			err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
							pull, &cur_map);
			if (err)
				goto out;
		}
	}

	*map = maps;
	*num_maps = num_pins * maps_per_pin;

	return 0;

out:
	kfree(maps);
	return err;
}

&mmc

  • &mmcではmmcドライバの設定を行います。
  • Raspberry Pi 3では、SDメモリスロットのつながっているホスト側をsdhostドライバ、Wi-FI/BTチップが繋がっているホスト側をmmcドライバとしています。
&mmc {
	pinctrl-names = "default";
	pinctrl-0 = <&sdio_pins>;
	non-removable;
	bus-width = <4>;
	status = "okay";
	brcm,overclock-50 = <0>;
};
  • 端子 sdio_poins
  • 取り外ししないデバイスを接続
  • バス幅 4bit
  • status はデフォルト(cm2708_common.dtsi)だとdisabledになっているのをokayにして有効にする。
  • SDCLK 50MHZにする機能:0 (多分無効という意味?)

&mmcを処理する部分

  • pinctrl-names と pinctrl-0 がどこで処理されるか不明。 driver/pinctlのどこか
  • non-removblable と bus-wideはdrivers/mmc/core/host.c の mmc_of_parse()で処理する。
  • status どこで処理しているか不明
  • brcm,overclock-50はdrivers/mmc/host/bcm2835-mmc.c の bcm2835_mmc_probe()で処理する。

&uart0

&uart0 {
	pinctrl-names = "default";
	pinctrl-0 = <&uart0_pins &bt_pins>;
	status = "okay";
};

  • uart0 の部分でUART0の設定をおこなう
  • 端子 uart0_pins bt_pins
  • status はデフォルト(cm2708_common.dtsi)だとdisabledになっているのをokayにして有効にする。

参考

17
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?