1
votes

I was wondering how some specific details in the device relate to the hardware and where to find this information(like schematic, datasheet etc).

An example of a usb node is given below: enter image description here

In the picture above I was wondering how do you find CLK_BUS_OHCI2 or RST_BUS_EHCI2 on the hardware. If you go to the include files you get a value (CLK_BUS_OHCI2 = 39), but I am not sure how that relates to actual hardware. Like which register or which pin etc.

2

2 Answers

3
votes

Nowadays I'm working with a similar platform, Allwinner A64 and I'm trying to understand how DTS, clocks, resets work. Fortunately your question came up in the search engine results. Gaurav Pathak's answer clarified most of the things for me and I want to extend a little bit from his point to help those who are trying to fill in the gap about bridging DTS and hardware.

I will refer to Linux kernel 5.7 and Allwinner A64 User Manual (v1.1).

There's a resemblance between uart4 and ehci2 in the means of node definition; for instance, we have property of clocks and resets in both of them. But ccu clock output usage were implemented different.

Let's take a closer look at uart4 node.

uart4: serial@1c29000 {
        compatible = "snps,dw-apb-uart";
        reg = <0x01c29000 0x400>;
        interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
        reg-shift = <2>;
        reg-io-width = <4>;
        clocks = <&ccu CLK_BUS_UART4>;
        resets = <&ccu RST_BUS_UART4>;
        status = "disabled";
    };

Now we already know that CLK_BUS_UART4 is included from include/dt-bindings/clock/sun50i-a64-ccu.h.

<&ccu CLK_BUS_UART4>

A further search for CLK_BUS_UART4 reveals that include/dt-bindings/clock/sun50i-a64-ccu.h is also indirectly (through drivers/clk/sunxi-ng/ccu-sun50i-a64.h) included from drivers/clk/sunxi-ng/ccu-sun50i-a64.c.

Then it was possible to refer to CLK_BUS_UART4 like below (L807 @ ccu-sun50i-a64.c)

    [CLK_BUS_UART4] = &bus_uart4_clk.common.hw

But what is bus_uart4_clk? Let's see.

It is defined at L381 @ ccu-sun50i-a64.c. This is how it looks:

    static SUNXI_CCU_GATE(bus_uart4_clk,    "bus-uart4",    "apb2",
              0x06c, BIT(20), 0);

SUNXI_CCU_GATE is a macro to manage gating register of Clock Control Unit. 4th argument, 0x06c refers to the register offset and 5th argument BIT(20) implies the Nth bit (20, in this case) at the offset of 0x06c is adjusted to drive bus_uart4_clk.

Allwinner A64 UART4 CCU Gating Register Description

Same thing applies for the resets property. To give a specific example; just search for RST_BUS_UART4 and 0x2d8 at Linux kernel source then look at the bottom of Page 142 of the A64 User Manual.

I hope there were not too much nonsense... Please correct me if I'm wrong.

2
votes

Well, as far as I know in the below structure

ehci2: usb@01c1c000 {
            compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
            reg = <0x01c1c000 0x100>;
            interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
            clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
            resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
            phys = <&usbphy 2>;
            phy-names = "usb";
            status = "disabled";
        };

clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>; represents consumer clocks i.e. input clocks and is called "phandle + clock specifier pairs". As you mentioned CLK_BUS_OHCI2 has value 39, that means USB controller will take input clock from the output 39 of ccu clock source.

In the dtsi file from where you posted the above screenshot, there should be a structure that defines the ccu for example like this below:

ccu: clk@01c20060 {
            #clock-cells = <1>;
            compatible = "allwinner,sun7i-a20-ahb-gates-clk";
            reg = <0x01c20060 0x8>;
            clocks = <&ahb>;
            clock-output-names = "ahb_usb0", "ahb_ehci0",
                "ahb_ohci0", "ahb_ehci1", "ahb_ohci1",
                "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0",
                "ahb_mmc1", "ahb_mmc2", "ahb_mmc3", "ahb_ms",
                "ahb_nand", "ahb_sdram", "ahb_ace",
                "ahb_emac", "ahb_ts", "ahb_spi0", "ahb_spi1",
                "ahb_spi2", "ahb_spi3", "ahb_sata",
                "ahb_hstimer", "ahb_ve", "ahb_tvd", "ahb_tve0",
                "ahb_tve1", "ahb_lcd0", "ahb_lcd1", "ahb_csi0",
                "ahb_csi1", "ahb_hdmi1", "ahb_hdmi0",
                "ahb_de_be0", "ahb_de_be1", "ahb_de_fe0",
                "ahb_de_fe1", "ahb_gmac", "ahb_ehci2",
                "ahb_mali";
        };

In the above structure there are multiple clock source outputs, so clock source 39 should be utilised by the above USB controller for taking clock input, note that #clock-cells = <1>; represents multiple clock output and #clock-cells = <0>; is for single clock output.
The ccu structure is just an example.