Search code examples
linux-kernellinux-device-driverclockgpiodevice-tree

How to define a clock multiplexer in a linux kernel device tree


I am writing a linux device driver and need to define the following clock-tree in a device tree file:

linux, common clock framework, clock tree

Note: Selecting an oscillator in the multiplexer is done by pulling an gpio output high or low. The clock generator is programmed via I2C.

Here is an example of what I have so far:

clocks {
    /* fixed clock oscillators */
    osc22: oscillator22 {
        compatible = "fixed-clock";
        #clock-cells = <0>;
        clock-frequency = <22579200>;
    };

    osc24: oscillator24 {
        compatible = "fixed-clock";
        #clock-cells = <0>;
        clock-frequency = <24576000>;
    };

    /* clock multiplexer
     * I'm afraid the following is not going to work :( ?
     */
    mux: multiplexer {
        compatible = "mux-clock";     /* <-------- ??? */
        clocks = <&osc22>, <&osc24>;  /* parent clocks */
    };
};

i2c1 {
    /* clock generator */
    si5351: si5351c@60 {
        #address-cells = <1>;
        #size-cells = <0>;
        #clock-cells = <1>;
        compatible = "silabs,si5351c";
        reg = <0x60>;
        clocks = <0>, <&mux>;
        clock-names = "xtal", "clkin";
        status = "okay";

        clkout0 {
            reg = <0>;
            silabs,disable-state = <2>;
            silabs,clock-source = <3>;
        };
    };
};

References:

How do I define a simple gpio-controlled clock multiplexer in a device tree?


Solution

  • As correctly pointed out by @h3n, at the time of asking this question, the kernel did not provide support for gpio-controlled clock multiplexers. So, I had to add a common clock driver for such devices.

    This driver (drivers/clk/clk-gpio.c) is in the mainline since 4.3-rc1.

    A device tree binding for the above mentioned use-case could look like this:

    clocks {
        /* fixed clock oscillators */
        osc22: oscillator22 {
            compatible = "fixed-clock";
            #clock-cells = <0>;
            clock-frequency = <22579200>;
        };
    
        osc24: oscillator24 {
            compatible = "fixed-clock";
            #clock-cells = <0>;
            clock-frequency = <24576000>;
        };
    
        /* gpio-controlled clock multiplexer */
        mux: multiplexer {
            compatible = "gpio-mux-clock";
            clocks = <&osc22>, <&osc24>;  /* parent clocks */
            #clock-cells = <0>;
            select-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
        };
    };