prci: register the DDR and GEMGX PLLs
The PRCI module exports three PLLs. Currently only the coreclk/corepll is registered, so add the logic to register the DDR (memory) and GEMGX (ethernet) clocks as well. These clocks are unused at the moment. Reviewed by: kp Differential Revision: https://reviews.freebsd.org/D23404
This commit is contained in:
parent
13ae20a8a1
commit
f6029f2bc9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357369
@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <gnu/dts/include/dt-bindings/clock/sifive-fu540-prci.h>
|
||||
|
||||
static struct resource_spec prci_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
RESOURCE_SPEC_END
|
||||
@ -68,6 +70,7 @@ struct prci_softc {
|
||||
|
||||
struct prci_clk_pll_sc {
|
||||
struct prci_softc *parent_sc;
|
||||
uint32_t reg;
|
||||
};
|
||||
|
||||
#define PRCI_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
@ -75,17 +78,40 @@ struct prci_clk_pll_sc {
|
||||
#define PRCI_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
|
||||
#define PRCI_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
|
||||
|
||||
#define PRCI_COREPLL 0x4
|
||||
#define PRCI_COREPLL_DIVR_MASK 0x3f
|
||||
#define PRCI_COREPLL_DIVR_SHIFT 0
|
||||
#define PRCI_COREPLL_DIVF_MASK 0x7fc0
|
||||
#define PRCI_COREPLL_DIVF_SHIFT 6
|
||||
#define PRCI_COREPLL_DIVQ_MASK 0x38000
|
||||
#define PRCI_COREPLL_DIVQ_SHIFT 15
|
||||
#define PRCI_COREPLL_CFG0 0x4
|
||||
#define PRCI_DDRPLL_CFG0 0xC
|
||||
#define PRCI_GEMGXLPLL_CFG0 0x1C
|
||||
|
||||
#define PRCI_PLL_DIVR_MASK 0x3f
|
||||
#define PRCI_PLL_DIVR_SHIFT 0
|
||||
#define PRCI_PLL_DIVF_MASK 0x7fc0
|
||||
#define PRCI_PLL_DIVF_SHIFT 6
|
||||
#define PRCI_PLL_DIVQ_MASK 0x38000
|
||||
#define PRCI_PLL_DIVQ_SHIFT 15
|
||||
|
||||
#define PRCI_READ(_sc, _reg) \
|
||||
bus_space_read_4((_sc)->bst, (_sc)->bsh, (_reg))
|
||||
|
||||
struct prci_pll_def {
|
||||
uint32_t id;
|
||||
const char *name;
|
||||
uint32_t reg;
|
||||
};
|
||||
|
||||
#define PLL(_id, _name, _base) \
|
||||
{ \
|
||||
.id = (_id), \
|
||||
.name = (_name), \
|
||||
.reg = (_base), \
|
||||
}
|
||||
|
||||
/* PLL Clocks */
|
||||
struct prci_pll_def pll_clks[] = {
|
||||
PLL(PRCI_CLK_COREPLL, "coreclk", PRCI_COREPLL_CFG0),
|
||||
PLL(PRCI_CLK_DDRPLL, "ddrclk", PRCI_DDRPLL_CFG0),
|
||||
PLL(PRCI_CLK_GEMGXLPLL, "gemgxclk", PRCI_GEMGXLPLL_CFG0),
|
||||
};
|
||||
|
||||
static int
|
||||
prci_clk_pll_init(struct clknode *clk, device_t dev)
|
||||
{
|
||||
@ -121,11 +147,11 @@ prci_clk_pll_recalc(struct clknode *clk, uint64_t *freq)
|
||||
}
|
||||
|
||||
/* Calculate the PLL output */
|
||||
val = PRCI_READ(sc->parent_sc, PRCI_COREPLL);
|
||||
val = PRCI_READ(sc->parent_sc, sc->reg);
|
||||
|
||||
divf = (val & PRCI_COREPLL_DIVF_MASK) >> PRCI_COREPLL_DIVF_SHIFT;
|
||||
divq = (val & PRCI_COREPLL_DIVQ_MASK) >> PRCI_COREPLL_DIVQ_SHIFT;
|
||||
divr = (val & PRCI_COREPLL_DIVR_MASK) >> PRCI_COREPLL_DIVR_SHIFT;
|
||||
divf = (val & PRCI_PLL_DIVF_MASK) >> PRCI_PLL_DIVF_SHIFT;
|
||||
divq = (val & PRCI_PLL_DIVQ_MASK) >> PRCI_PLL_DIVQ_SHIFT;
|
||||
divr = (val & PRCI_PLL_DIVR_MASK) >> PRCI_PLL_DIVR_SHIFT;
|
||||
|
||||
*freq = refclk / (divr + 1) * (2 * (divf + 1)) / (1 << divq);
|
||||
|
||||
@ -160,7 +186,8 @@ prci_probe(device_t dev)
|
||||
}
|
||||
|
||||
static void
|
||||
prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef)
|
||||
prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef,
|
||||
uint32_t reg)
|
||||
{
|
||||
struct clknode *clk;
|
||||
struct prci_clk_pll_sc *sc;
|
||||
@ -172,6 +199,7 @@ prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef)
|
||||
|
||||
sc = clknode_get_softc(clk);
|
||||
sc->parent_sc = parent_sc;
|
||||
sc->reg = reg;
|
||||
|
||||
clknode_register(parent_sc->clkdom, clk);
|
||||
}
|
||||
@ -207,8 +235,6 @@ prci_attach(device_t dev)
|
||||
}
|
||||
|
||||
bzero(&clkdef, sizeof(clkdef));
|
||||
clkdef.id = 0;
|
||||
clkdef.name = "coreclk";
|
||||
clkdef.parent_names = mallocarray(ncells, sizeof(char *), M_OFWPROP,
|
||||
M_WAITOK);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
@ -232,7 +258,11 @@ prci_attach(device_t dev)
|
||||
}
|
||||
|
||||
/* We can't free a clkdom, so from now on we cannot fail. */
|
||||
prci_pll_register(sc, &clkdef);
|
||||
for (i = 0; i < nitems(pll_clks); i++) {
|
||||
clkdef.id = pll_clks[i].id;
|
||||
clkdef.name = pll_clks[i].name;
|
||||
prci_pll_register(sc, &clkdef, pll_clks[i].reg);
|
||||
}
|
||||
|
||||
error = clkdom_finit(sc->clkdom);
|
||||
if (error)
|
||||
|
Loading…
Reference in New Issue
Block a user