UART4 与 Pandaboard 和 Arch Linux

UART4 with Pandaboard and Arch Linux

我正在尝试在我的带有 Arch Linux 的 Pandaboard 中使用 UART4。我使用的是最新的内核 (4.2.0-2-ARCH),所以我无法使用 omap_mux 以旧方式配置 MUX,我必须使用设备树覆盖来完成。这对我来说是新的,所以很难,我以前从未做过。我一直在阅读一些 post 关于如何在 this and this. So I downloaded the OMAP4 Technical Reference Manual (download here 等网站的 Beaglebone 板上使用它们的文章。 Table 18-504表示UART4控制寄存器。基于此和上面的 url,我创建并编译了以下设备树覆盖,用 0 填充寄存器,这应该为 UART4 功能设置 MUX:

// Util: http://lxr.free-electrons.com/source/arch/arm/boot/dts/omap4-panda-es.dts
//       http://www.valvers.com/embedded-linux/beaglebone-black/step04-gpio/


/dts-v1/;
/plugin/;


/ {
        model = "TI OMAP4 PandaBoard-ES";
        compatible = "ti,omap4-panda-es", "ti,omap4460";


        part-number = "ANDRES-IO";


        fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        uart4_pins: pinmux_uart4_pins {
                                pinctrl-single,pins = <
                                                        0x15C 0x00  // kernel pin 142 (uart4 tx y rx - address 0x4A10 015C)
                                                      >;
                        };
                };
        };


        fragment@1 {
                target = <&ocp>;
                __overlay__ {
                        uart4_pins_helper {
                                compatible = "panda-pinmux-helper";
                                pinctrl-names = "default";
                                pinctrl-0 = <&uart4_pins>;
                                status = "okay";
                        };
                };
        };
};

我将编译后的文件复制到/lib/firmware/,但之后我不知道如何使用或启用它。 Beaglebone 板有 bone_capemgr 但我在 Pandaboard 中看不到这样的东西。

其他 OS 如 Ubuntu 已配置 UART4,我尝试寻找他们使用的设备树覆盖,但找不到任何东西。

我解决了!!!!!也许是微不足道的事情,但对我来说真的很难,我学到了很多东西。没有太多关于如何在 Pandaboard 中执行此操作的信息,仅适用于 Beagleboards。所以首先,Device Tree Overlay 文件只在启动时加载,我们不能像 Beagleboard 那样动态加载它,因为我们没有 bone_capemgr。编译后的 .dtb 文件位于 /boot/dtbs(至少在 Arch Linux 中),那里有很多 .dtb 文件,但只有一个在启动时加载,具体取决于板,你可以看到启动时加载了哪个,例如,在我的情况下是:

U-Boot 2015.04 (Jun 07 2015 - 19:26:06) Arch Linux ARM
CPU  : OMAP4460 ES1.1
Board: OMAP4 Panda
I2C:   ready
DRAM:  1 GiB
MMC:   OMAP SD/MMC: 0
** Unable to use mmc 0:1 for loading the env **
Using default environment
Net:   No ethernet found.
Hit any key to stop autoboot:  0 
starting USB...
USB0:   USB EHCI 1.00
scanning bus 0 for devices... 3 USB Device(s) found
       scanning usb for storage devices... 0 Storage Device(s) found
       scanning usb for ethernet devices... 1 Ethernet Device(s) found
switch to partitions #0, OK
mmc0 is current device
mmc found on device 0
Checking for: /boot/uEnv.txt ...
74 bytes read in 13 ms (4.9 KiB/s)
Loaded environment from /boot/uEnv.txt
Checking if uenvcmd is set ...
4984312 bytes read in 244 ms (19.5 MiB/s)
loading /boot/dtbs/omap4-panda-es.dtb ...
100695 bytes read in 380 ms (257.8 KiB/s)
** File not found /boot/initramfs-linux.img **
Kernel image @ 0x82000000 [ 0x000000 - 0x4c0df8 ]
## Flattened Device Tree blob at 88000000
   Booting using the fdt blob at 0x88000000
   Loading Device Tree to 8ffe4000, end 8ffff956 ... OK
Starting kernel ...

我有一个 Pandaboard ES,所以加载的文件是 /boot/dtbs/omap4-panda-es.dtb。我反编译了文件,所以我可以使用 dtc -I dtb -O dts omap4-panda-es.dtb > omap4-panda-es.dts 添加 UART4 MUX 设置(取自 here). So now we have a omap4-panda-es.dts which is the complete Device Tree Overlays that sets everything up, I just need to add the UART4 MUX settings. We have to use the pinctrl-single,pins property. Here 是关于 pinctrl-single,pins:

的一个很好的解释

The pin configuration nodes for pinctrl-single are specified as pinctrl register offset and value pairs using pinctrl-single,pins. Only the bits specified in pinctrl-single,function-mask are updated. For example, setting a pin for a device could be done with: pinctrl-single,pins = <0xdc 0x118>; Where 0xdc is the offset from the pinctrl register base address for the device pinctrl register, and 0x118 contains the desired value of the pinctrl register.

这是我一开始的误解,我虽然 pinctrl 地址是绝对地址,但它是相对于树中的基地址的。例如,在我的例子中,有很多 pinmux_tfp410_pinspinmux_dss_hdmi_pinspinmux_i2c1_pins 等。所有这些 pinmux_* 都在名为 pinmux@40 的父项下,这意味着pinctrl 中指定的地址是相对于 0x40 的,但是这个 pinmux@40 在另一个名为 scm@100000 的节点下,该节点位于另一个名为 l4@4a000000 的节点内,所以pinmux@40里面的地址是相对于所有这些地址之和的结点的基地址,即0x4a000000 + 0x100000 + 0x40 = 0x4a100040,所以0xa100040是基地址,所有在[中指定的地址=28=] 相对于 0xa100040。所以,根据Table18-504中的OMAP4 Technical Reference Manual(下载可用here) the address for the UART4 control register that control the MUX and some other things is 0x4A10015C. The base address of pinctrl is 0x4a100040 so the address we must specify in pinctrl is 0x11c because 0x4a100040 + 0x11c = 0x4A10015C. All the Device Tree Overlays I found of other linux distros that support Pandaboard use the same base address 0x4a100040 (here为例)。所以我在节点pinmux@40下添加了这个:

// Set the UART4 MUX, it doesn't come by default so I had to add it
//  "linux,phandle" has the same value aas "phandle", it's just a reference number, just make sure
//  it is not being used in another part of the tree (it will refuse to compile if you do it wrong)
// The phandle is used for reference in "serial@4806e000" at "pinctrl-0"
pinmux_uart4_pins {
    pinctrl-single,pins = <
        0x11c 0x100       // uart4_rx.uart4_rx INPUT | MODE0
        0x11e 0           // uart4_tx.uart4_tx OUTPUT | MODE0
    >;
    linux,phandle = <0xfff>;
    phandle = <0xfff>;
};

我从 here 中获取了此设置,但只需更改 0x1000 就会更改寄存器中的设置。就我而言,我还必须添加:

linux,phandle = <0xfff>;
phandle = <0xfff>;

例如,我在 Ubuntu 中看不到这个 (https://github.com/Canonical-kernel/Ubuntu-kernel/blob/master/arch/arm/boot/dts/omap4.dtsi),但我不知道为什么或这个 phandle 的目的是什么,我只知道是否它们用作参考,我需要将参考放在设备树中的其他位置,只需确保它是唯一的,它可以是任何 32 位值,但在树内必须是唯一的。在我的例子中,有另一个节点引用 UART4:

serial@4806e000 {
     compatible = "ti,omap4-uart";
     reg = <0x4806e000 0x100>;
     interrupts = <0x0 0x46 0x4>;
     ti,hwmods = "uart4";
     clock-frequency = <0x2dc6c00>;
     interrupts-extended = <0x1 0x0 0x46 0x4 0x82 0x11c>;
     linux,phandle = <0x121>;
      phandle = <0x121>;
 };

所以我必须使用 phandle 否则 MUX 设置将不会应用:

 serial@4806e000 {
     compatible = "ti,omap4-uart";
     reg = <0x4806e000 0x100>;
     interrupts = <0x0 0x46 0x4>;
     ti,hwmods = "uart4";
     pinctrl-names = "default";
     pinctrl-0 = <0xfff>;
     clock-frequency = <0x2dc6c00>;
     interrupts-extended = <0x1 0x0 0x46 0x4 0x82 0x11c>;
     linux,phandle = <0x121>;
     phandle = <0x121>;
 };

最后,在文件末尾有很多定义,每个节点一个,例如

i2c1_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_i2c1_pins";
i2c2_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_i2c2_pins";
i2c3_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_i2c3_pins";
i2c4_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_i2c4_pins";
wl12xx_gpio = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_wl12xx_gpio";
wl12xx_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_wl12xx_pins";
twl6030_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_twl6030_pins";

他们只是描述了每个节点所在的位置,在这里我们可以清楚地看到基地址是什么。所以我在这里添加了这个:

uart4_pins = "/ocp/l4@4a000000/scm@100000/pinmux@40/pinmux_uart4_pins";

现在我们有一个完整的 .dts 文件,应该可以让 UART4 正常工作。我们必须使用 dtc -O dtb -o omap4-panda-es.dtb -b O -@ omap4-panda-es.dts 编译它,这将生成一个 .dtb 文件来替换 /boot/dtbs 中的文件,所以替换它并重新启动!重新启动 运行 cat /sys/kernel/debug/pinctrl/4a100040.pinmux/pinmux-functions 后,它应该显示如下内容:

function: pinmux_dss_dpi_pins, groups = [ pinmux_dss_dpi_pins ]
function: pinmux_tfp410_pins, groups = [ pinmux_tfp410_pins ]
function: pinmux_dss_hdmi_pins, groups = [ pinmux_dss_hdmi_pins ]
function: pinmux_tpd12s015_pins, groups = [ pinmux_tpd12s015_pins ]
function: pinmux_hsusbb1_pins, groups = [ pinmux_hsusbb1_pins ]
function: pinmux_uart4_pins, groups = [ pinmux_uart4_pins ]
function: pinmux_wl12xx_pins, groups = [ pinmux_wl12xx_pins ]
function: gpio_led_pmx, groups = [ gpio_led_pmx ]
function: pinmux_wl12xx_gpio, groups = [ pinmux_wl12xx_gpio ]
function: pinmux_i2c1_pins, groups = [ pinmux_i2c1_pins ]
function: pinmux_twl6030_pins, groups = [ pinmux_twl6030_pins ]
function: pinmux_twl6040_pins, groups = [ pinmux_twl6040_pins ]
function: pinmux_i2c2_pins, groups = [ pinmux_i2c2_pins ]
function: pinmux_i2c3_pins, groups = [ pinmux_i2c3_pins ]
function: pinmux_i2c4_pins, groups = [ pinmux_i2c4_pins ]
function: pinmux_wl12xx_pins, groups = [ pinmux_wl12xx_pins ]
function: pinmux_mcpdm_pins, groups = [ pinmux_mcpdm_pins ]
function: pinmux_mcbsp1_pins, groups = [ pinmux_mcbsp1_pins ]

如果我们看到 uart4 一切正常,应该可以正常工作!否则 .dts 文件有问题。我们可以通过 运行ning 测试 uart 是否工作,例如 echo -e "AT" > /dev/ttyO3,记住 /dev/ttyO3UART4。我希望这对某人有用!

仅供参考,这里是完整的 .dts 和已编译的 .dtb 文件,带有工作的 UART4:https://gist.github.com/dragondgold/1aaabf93279006b703f3