prci: register tlclk as a fixed clock

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.

Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D23406
This commit is contained in:
Mitchell Horne 2020-02-01 17:13:52 +00:00
parent adec0ce785
commit 9e483eadd4

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <dev/extres/clk/clk.h>
#include <dev/extres/clk/clk_fixed.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@ -119,6 +120,17 @@ struct prci_pll_def pll_clks[] = {
PLL(PRCI_CLK_GEMGXLPLL, "gemgxclk", PRCI_GEMGXLPLL_CFG0),
};
/* Fixed divisor clock TLCLK. */
struct clk_fixed_def tlclk_def = {
.clkdef.id = PRCI_CLK_TLCLK,
.clkdef.name = "prci_tlclk",
.clkdef.parent_names = (const char *[]){"coreclk"},
.clkdef.parent_cnt = 1,
.clkdef.flags = CLK_NODE_STATIC_STRINGS,
.mult = 1,
.div = 2,
};
static int
prci_clk_pll_init(struct clknode *clk, device_t dev)
{
@ -271,6 +283,16 @@ prci_attach(device_t dev)
prci_pll_register(sc, &clkdef, pll_clks[i].reg);
}
/*
* Register the fixed clock "tlclk".
*
* If an older device tree is being used, tlclk may appear as its own
* entity in the device tree, under soc/tlclk. If this is the case it
* will be registered automatically by the fixed_clk driver, and the
* version we register here will be an unreferenced duplicate.
*/
clknode_fixed_register(sc->clkdom, &tlclk_def);
error = clkdom_finit(sc->clkdom);
if (error)
panic("Couldn't finalise clock domain");