amalcolm
Posts: 13
Joined: Sun Feb 21, 2016 9:31 am

Set up GPIO clock from device tree

Sun Feb 21, 2016 9:46 am

I am trying to setup a GPIO clock from a device tree to support a device driver for a hardware codec.

There is a section in:

https://www.raspberrypi.org/documentati ... uration.md

labelled CLOCK CONFIGURATION

which shows the following:

clock_routing {
vco@PLLA { freq = <1966080000>; };
chan@APER { div = <4>; };
clock@GPCLK0 { pll = "PLLA"; chan = "APER"; };
};

clock_setup {
clock@PWM { freq = <2400000>; };
clock@GPCLK0 { freq = <12288000>; };
clock@GPCLK1 { freq = <25000000>; };
};

I have tried to put this in a device tree fragment in order to set up CLK0 on GPIO4 (I can do this programatically, by the way, so I know my hardware is good).

Is this all that is required to start the clock? (I have also add a fragment to set GPIO4 to alternate mode, and I believe that is working:

/ {
compatible = "brcm,bcm2708";


fragment@0 {
target-path = "/clocks";
__overlay__ {
clock_routing {
vco@PLLA { freq = <1966080000>; };
chan@APER { div = <4>; };
clock@GPCLK0 { pll = "PLLA"; chan = "APER"; };
};

clock_setup {
clock@GPCLK0 { freq = <12288000>; };
};
};
};

fragment@1 {
target = <&gpio>;
__overlay__ {
clock_pin: clock_pin {
brcm,pins = <4>;
brcm,function = <4>;
};
};
};
etc .....

I have checked the output of vcdbg and my dtb file is loaded correctly:

001610.109: Loaded overlay 'max9860'
001610.148: dtdebug: Found fragment 0 (offset 36)
001612.541: dtdebug: merge_fragment(/clocks,/fragment@0/__overlay__)
001614.601: dtdebug: merge_fragment(/clocks/clock_routing,/fragment@0/__overlay__/clock_routing)
001616.358: dtdebug: merge_fragment(/clocks/clock_routing/vco@PLLA,/fragment@0/__overlay__/clock$
001616.383: dtdebug: +prop(freq)
001616.811: dtdebug: merge_fragment() end
001618.608: dtdebug: merge_fragment(/clocks/clock_routing/chan@APER,/fragment@0/__overlay__/cloc$
001618.631: dtdebug: +prop(div)
001619.044: dtdebug: merge_fragment() end
001620.895: dtdebug: merge_fragment(/clocks/clock_routing/clock@GPCLK0,/fragment@0/__overlay__/c$
001620.918: dtdebug: +prop(pll)
001621.412: dtdebug: +prop(chan)
001621.913: dtdebug: merge_fragment() end
001621.938: dtdebug: merge_fragment() end
001624.230: dtdebug: merge_fragment(/clocks/clock_setup,/fragment@0/__overlay__/clock_setup)
001626.069: dtdebug: merge_fragment(/clocks/clock_setup/clock@GPCLK0,/fragment@0/__overlay__/clo$
001626.095: dtdebug: +prop(freq)
001626.538: dtdebug: merge_fragment() end
001626.562: dtdebug: merge_fragment() end
001626.595: dtdebug: merge_fragment() end
001626.712: dtdebug: Found fragment 1 (offset 316)
001628.533: dtdebug: merge_fragment(/soc/gpio@7e200000,/fragment@1/__overlay__)
001630.012: dtdebug: merge_fragment(/soc/gpio@7e200000/clock_pin,/fragment@1/__overlay__/clock_p$
001630.037: dtdebug: +prop(brcm,pins)
001630.659: dtdebug: +prop(brcm,function)
001631.293: dtdebug: +prop(linux,phandle)
001631.904: dtdebug: +prop(phandle)
001632.532: dtdebug: merge_fragment() end
001632.556: dtdebug: merge_fragment() end
001632.620: dtdebug: Found fragment 2 (offset 456)
001633.647: dtdebug: merge_fragment(/sound,/fragment@2/__overlay__)
001633.670: dtdebug: +prop(compatible)
001634.324: dtdebug: +prop(i2s-controller)
001635.172: dtdebug: +prop(status)
001635.878: dtdebug: merge_fragment() end
001635.931: dtdebug: Found fragment 3 (offset 572)
001638.745: dtdebug: merge_fragment(/soc/i2s@7e203000,/fragment@3/__overlay__)
001638.769: dtdebug: +prop(status)
001639.279: dtdebug: merge_fragment() end
001639.327: dtdebug: Found fragment 4 (offset 648)
001643.380: dtdebug: merge_fragment(/soc/i2c@7e804000,/fragment@4/__overlay__)
001643.405: dtdebug: +prop(#address-cells)
001643.819: dtdebug: +prop(#size-cells)
001644.236: dtdebug: +prop(status)
001646.521: dtdebug: merge_fragment(/soc/i2c@7e804000/max9860_codec@20,/fragment@4/__overlay__/m$
001646.546: dtdebug: +prop(#sound-dai-cells)
001647.022: dtdebug: +prop(compatible)
001647.425: dtdebug: +prop(reg)
001647.862: dtdebug: +prop(pinctrl-names)
001648.355: dtdebug: +prop(pinctrl-0)

However, I get no clock output.

If anyone can shed light on this I would be very grateful.

Thanks in advance

Andrew

f5oeo
Posts: 14
Joined: Sun Oct 12, 2014 10:16 am

Re: Set up GPIO clock from device tree

Sun Mar 27, 2016 1:10 pm

Try also to experiment with clock in device tree overlay without success.
Any update or extra documentation in PLL and clock ?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1317
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Set up GPIO clock from device tree

Tue Mar 29, 2016 8:01 am

The "Device Tree" that is used to generate the dt-blob.bin isn't Device Tree that would be recognised by anything else; it uses the same syntax, but the semantics are completely different.

What you are trying to do isn't possible at the moment. Although the RPi DTBs contain clock definitions, they are only describing clocks that the firmware has initialised (except for clk_uart1/clock@5 which is a multiple of a clock set up by the firmware). There are efforts upstream to create an ARM-side clock driver that can actually configure and control the BCM2835 PLLs and clock dividers - see drivers/clk/bcm/clk-bcm2835.c for how far Eric Anholt has got - but we aren't using that in Raspberry Pi builds yet.

Currently the only way to create a clock on RPi (short of using a kernel with a different clock driver) is to ask the firmware to do it using a custom dt-blob.bin, which is horrible - sorry. I would like to see the firmware making more use of the main DTB file to avoid duplication, and this is one area where it would be beneficial.

amalcolm
Posts: 13
Joined: Sun Feb 21, 2016 9:31 am

Re: Set up GPIO clock from device tree

Tue Mar 29, 2016 8:22 am

OK, thanks for that. I currently have a user-space program to initialize the clock via /dev/mem. I will integrate this into my driver.

Regards

Andrew Malcolm

tecmec
Posts: 4
Joined: Sun May 07, 2017 9:36 pm

Re: Set up GPIO clock from device tree

Sun May 07, 2017 10:11 pm

PhilE wrote:The "Device Tree" that is used to generate the dt-blob.bin isn't Device Tree that would be recognised by anything else; it uses the same syntax, but the semantics are completely different.

What you are trying to do isn't possible at the moment. Although the RPi DTBs contain clock definitions, they are only describing clocks that the firmware has initialised (except for clk_uart1/clock@5 which is a multiple of a clock set up by the firmware). There are efforts upstream to create an ARM-side clock driver that can actually configure and control the BCM2835 PLLs and clock dividers - see drivers/clk/bcm/clk-bcm2835.c for how far Eric Anholt has got - but we aren't using that in Raspberry Pi builds yet.

Currently the only way to create a clock on RPi (short of using a kernel with a different clock driver) is to ask the firmware to do it using a custom dt-blob.bin, which is horrible - sorry. I would like to see the firmware making more use of the main DTB file to avoid duplication, and this is one area where it would be beneficial.
Is this information still correct? I am trying to set up an external peripheral using the device tree, and I think I have everything working right now, except the clock. While I really wanted to set up the clock in the device tree (so that everything is nicely contained), I have come to accept that I might have to do so elsewhere. However, I can't find this "dt-blob.bin" anywhere. Also, it does seem like clk-bcm2835.c is in fact being used by the RPi builds now.

How would I go about setting up GPCLK0 at boot time (so that my downstream peripheral can be properly detected and initialized during boot)? So far I have the following in my overlay dts, but I'm missing the actual setup of the GPCLK0 frequency.

Code: Select all

...

/* set GPIO4 to ALT0 (GPCLK0) */
    fragment@1 {
        target = <&gpio>;
        __overlay__ {
            can_osc_pin {
                brcm,pins = <4>;
                brcm,function = <4>;
            };
        };
    };
 
    fragment@2 {
        target = <&spi0>;
        __overlay__ {
            /* needed to avoid dtc warning */
            #address-cells = <1>;
            #size-cells = <0>;
            cs-gpios = <0>, <0>;
            status = "okay";
 
            can0: mcp2515@0 {
                compatible = "microchip,mcp2515";
                reg = <0>;
                clocks = <&clocks 38>; /* BCM2835_CLOCK_GP0 */
                interrupt-parent = <&tca9539_74>;
                interrupts = <2 0x2>;
                vdd-supply = <&vdd_3v3_reg>;
                xceiver-supply = <&vdd_5v0_reg>;
                spi-max-frequency = <10000000>;
            };
        };
    };

...

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1317
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Set up GPIO clock from device tree

Mon May 08, 2017 10:26 am

I believe my comment still applies. Although the bcm2835-cprman driver is being used as of rpi-4.9.y onwards, as far as I know it doesn't allow you to initialise a clock to have specific clock rate unless it is requested by the consumer of the clock, i.e. the driver for the hardware that needs the clock. Fixed clocks support the "clock-frequency" property, but they are meant to be used with oscillators or other clocks that have been pre-configured - see the mcp2515-can0 overlay source here for a relevant example.

If you google "dt-blob.bin", the first result is our documentation of the dt-blob.bin configuration file. The source to our current dt-blob.bin, which is compiled into the start*.elf images but overridable by a file in the boot partition, can be found at: https://github.com/raspberrypi/firmware ... t-blob.dts

tecmec
Posts: 4
Joined: Sun May 07, 2017 9:36 pm

Re: Set up GPIO clock from device tree

Mon May 08, 2017 2:19 pm

Thanks. I missed the part where the file was an override (and so wouldn't exist out of the box).

I suppose the other option may be to see if I can modify the device driver to request a clock through that interface. Right now I see where it queries for the clock rate. I wonder how hard it would be to extend it to be more proactive if it fails.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1317
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Set up GPIO clock from device tree

Mon May 08, 2017 2:38 pm

It shouldn't be very difficult. You can use Eric Anholt's VC4 driver as an example: https://github.com/raspberrypi/linux/bl ... /vc4_dsi.c

Look for all occurrences of "pixel_clock" to show you what to do.

tecmec
Posts: 4
Joined: Sun May 07, 2017 9:36 pm

Re: Set up GPIO clock from device tree

Sun Jun 18, 2017 9:48 pm

I got the clock to work by doing two things. First, I modified driver of the device that consumes the clock to request a specific frequency (like the DSI driver you linked does), by calling clk_set_rate() during initialization. The second thing I had to do though, was to create a custom dt-blob.dtb that includes pin@p4 { function = "gp_clk"; termination = "pull_down"; };. I don't entirely understand why I had to do that though, because my dto (for linux, not the bootloader) includes:

Code: Select all

    fragment@1 {
        target = <&gpio>;
        __overlay__ {
            can_osc_pin {
                brcm,pins = <4>;
                brcm,function = <4>;
            };
        };
    };
From what I can tell, this should do the exact same thing - configure the GPIO4 pin for the ALT0 functionality (GP_CLK, in this case). I don't know why it doesn't work in the linux dto though. Thoughts?

tecmec
Posts: 4
Joined: Sun May 07, 2017 9:36 pm

Re: Set up GPIO clock from device tree

Mon Jun 19, 2017 12:33 am

To answer my own question, my pinctrl overlay under &gpio doesn't do anything all by itself. The pinctrl needs to be referenced by some other node so that it is actually applied. I changed my device tree overlay to have my device reference the pinctrl, and now everything works without using a custom dt-blob.bin.

Code: Select all

/* set GPIO4 to ALT0 (GPCLK0) */
    fragment@1 {
        target = <&gpio>;
        __overlay__ {
            can_clk_pin: can_clk_pin {
                brcm,pins = <4>;
                brcm,function = <4>;
                brcm,pull = <1>;
            };
        };
    };
 
    fragment@2 {
        target = <&spi0>;
        __overlay__ {
            /* needed to avoid dtc warning */
            #address-cells = <1>;
            #size-cells = <0>;
            cs-gpios = <0>, <0>;
            status = "okay";
 
            can0: mcp2515@0 {
                compatible = "microchip,mcp2515";
                reg = <0>;
                clocks = <&clocks 38>; /* BCM2835_CLOCK_GP0 */
                interrupt-parent = <&tca9539_74>;
                interrupts = <2 0x2>;
                vdd-supply = <&vdd_3v3_reg>;
                xceiver-supply = <&vdd_5v0_reg>;
                spi-max-frequency = <10000000>;
                pinctrl-names = "default";
                pinctrl-0 = <&can_clk_pin>;
            };
        };
    };
Last edited by tecmec on Mon Jun 19, 2017 2:04 pm, edited 1 time in total.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1317
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Set up GPIO clock from device tree

Mon Jun 19, 2017 8:41 am

Nice one - you found the answer before I saw the question. As you found, the groups of pin settings within the gpio node are only applied when an active node refers to them through a pinctrl-0 property.

Return to “Device Tree”

Who is online

Users browsing this forum: No registered users and 2 guests