Page MenuHomeFreeBSD

prci: register tlclk as a fixed clock
ClosedPublic

Authored by mhorne on Jan 28 2020, 8:19 PM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, May 5, 9:11 PM
Unknown Object (File)
Mar 16 2024, 8:08 AM
Unknown Object (File)
Mar 16 2024, 8:08 AM
Unknown Object (File)
Mar 16 2024, 8:08 AM
Unknown Object (File)
Mar 16 2024, 8:08 AM
Unknown Object (File)
Mar 16 2024, 7:56 AM
Unknown Object (File)
Jan 24 2024, 3:58 AM
Unknown Object (File)
Jan 16 2024, 5:55 PM
Subscribers

Details

Summary

The PRCI exports tlclk as a constant fixed divisor clock, defined as 1/2
of the coreclk frequency. In older FU540 device trees (such as the one
provided by SiFive), tlclk is represented as its own entity, and is
automatically registered as a fixed-divisor-clock. Unfortunately the
upstream FU540 device tree (that we have in our tree) represents tlclk
as an output of the PRCI block, and we must register it manually. At
worst, users of the old device tree will end up with an unreferenced
duplicate of tlclk.

This fixes device attachment for the SiFive UART on newer device trees,
since it references tlclk via the PRCI.

Test Plan

Sysctl output for tlclk:

hw.clock.tlclk.enable_cnt: 2
hw.clock.tlclk.childrens: 
hw.clock.tlclk.parents: coreclk 
hw.clock.tlclk.parent: coreclk
hw.clock.tlclk.frequency: 66666664

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Snippet from the older device tree, provided by SiFive's FSBL:

		prci: prci@10000000 {
			compatible = "sifive,aloeprci0", "sifive,ux00prci0";
			reg = <0x0 0x10000000 0x0 0x1000>;
			reg-names = "control";
			clocks = <&refclk>;
			#clock-cells = <1>;
		};
		tlclk: tlclk {
			compatible = "fixed-factor-clock";
			clocks = <&prci 0>;
			#clock-cells = <0>;
			clock-div = <2>;
			clock-mult = <1>;
		};

                ...

		L28: serial@10010000 {
			compatible = "sifive,uart0";
			interrupt-parent = <&L4>;
			interrupts = <4>;
			reg = <0x0 0x10010000 0x0 0x1000>;
			reg-names = "control";
			clocks = <&tlclk>;
		};

And here's what we have in Linux's device tree:

prci: clock-controller@10000000 {
        compatible = "sifive,fu540-c000-prci";
        reg = <0x0 0x10000000 0x0 0x1000>;
        clocks = <&hfclk>, <&rtcclk>;
        #clock-cells = <1>;
};
uart0: serial@10010000 {
        compatible = "sifive,fu540-c000-uart", "sifive,uart0";
        reg = <0x0 0x10010000 0x0 0x1000>;
        interrupt-parent = <&plic0>;
        interrupts = <4>;
        clocks = <&prci PRCI_CLK_TLCLK>;
        status = "disabled";
};

As you can see the method in which tlclk is reference by uart0 differs; in the newer device trees it is a member of the PRCI.

sys/riscv/sifive/fu540_prci.c
294 ↗(On Diff #67433)

This may be better achieved by using different configurations based on exact compat string of the PRCI. I'm not sure of what the preferred approach would be. Thoughts?

sys/riscv/sifive/fu540_prci.c
294 ↗(On Diff #67433)

I wonder if it's not better to just always register this clock (with a different name, maybe "prci_tlclk"). If there's a separate tlclk entry in the device tree it'll just use the PRCI coreclk, and no one will use prci_tlclk. If there's not users will reference the the prci_tlclk from the PRCI.

Worst case is that we have two instances of the tlclk, but that shouldn't really harm anything

Rename to prci_tlclk and register unconditionally.

This revision is now accepted and ready to land.Feb 1 2020, 8:05 AM
This revision was automatically updated to reflect the committed changes.