mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-05 19:10:13 +00:00
c13fe7c034
Add a DM clock driver for StarFive JH7110 SoC. Signed-off-by: Yanhong Wang <yanhong.wang@starfivetech.com> Tested-by: Conor Dooley <conor.dooley@microchip.com>
603 lines
18 KiB
C
603 lines
18 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2022-23 StarFive Technology Co., Ltd.
|
|
*
|
|
* Author: Yanhong Wang <yanhong.wang@starfivetech.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <clk.h>
|
|
#include <clk-uclass.h>
|
|
#include <dm.h>
|
|
#include <dm/device.h>
|
|
#include <dm/devres.h>
|
|
#include <dm/lists.h>
|
|
#include <dt-bindings/clock/starfive,jh7110-crg.h>
|
|
#include <log.h>
|
|
#include <linux/clk-provider.h>
|
|
|
|
#include "clk.h"
|
|
|
|
#define STARFIVE_CLK_ENABLE_SHIFT 31 /* [31] */
|
|
#define STARFIVE_CLK_INVERT_SHIFT 30 /* [30] */
|
|
#define STARFIVE_CLK_MUX_SHIFT 24 /* [29:24] */
|
|
#define STARFIVE_CLK_DIV_SHIFT 0 /* [23:0] */
|
|
|
|
#define OFFSET(id) ((id) * 4)
|
|
#define AONOFFSET(id) (((id) - JH7110_SYSCLK_END) * 4)
|
|
#define STGOFFSET(id) (((id) - JH7110_AONCLK_END) * 4)
|
|
|
|
typedef int (*jh1710_init_fn)(struct udevice *dev);
|
|
|
|
struct jh7110_clk_priv {
|
|
void __iomem *reg;
|
|
jh1710_init_fn init;
|
|
};
|
|
|
|
static const char *cpu_root_sels[2] = {
|
|
[0] = "oscillator",
|
|
[1] = "pll0_out",
|
|
};
|
|
|
|
static const char *perh_root_sels[2] = {
|
|
[0] = "pll0_out",
|
|
[1] = "pll2_out",
|
|
};
|
|
|
|
static const char *bus_root_sels[2] = {
|
|
[0] = "oscillator",
|
|
[1] = "pll2_out",
|
|
};
|
|
|
|
static const char *qspi_ref_sels[2] = {
|
|
[0] = "oscillator",
|
|
[1] = "qspi_ref_src",
|
|
};
|
|
|
|
static const char *gmac1_tx_sels[2] = {
|
|
[0] = "gmac1_gtxclk",
|
|
[1] = "gmac1_rmii_rtx",
|
|
};
|
|
|
|
static const char *gmac0_tx_sels[2] = {
|
|
[0] = "gmac0_gtxclk",
|
|
[1] = "gmac0_rmii_rtx",
|
|
};
|
|
|
|
static const char *apb_func_sels[2] = {
|
|
[0] = "osc_div4",
|
|
[1] = "oscillator",
|
|
};
|
|
|
|
static const char *gmac1_rx_sels[2] = {
|
|
[0] = "gmac1-rgmii-rxin-clock",
|
|
[1] = "gmac1_rmii_rtx",
|
|
};
|
|
|
|
static struct clk *starfive_clk_mux(void __iomem *reg,
|
|
const char *name,
|
|
unsigned int offset,
|
|
u8 width,
|
|
const char * const *parent_names,
|
|
u8 num_parents)
|
|
{
|
|
return clk_register_mux(NULL, name, parent_names, num_parents, 0,
|
|
reg + offset, STARFIVE_CLK_MUX_SHIFT,
|
|
width, 0);
|
|
}
|
|
|
|
static struct clk *starfive_clk_gate(void __iomem *reg,
|
|
const char *name,
|
|
const char *parent_name,
|
|
unsigned int offset)
|
|
{
|
|
return clk_register_gate(NULL, name, parent_name, 0, reg + offset,
|
|
STARFIVE_CLK_ENABLE_SHIFT, 0, NULL);
|
|
}
|
|
|
|
static struct clk *starfive_clk_inv(void __iomem *reg,
|
|
const char *name,
|
|
const char *parent_name,
|
|
unsigned int offset)
|
|
{
|
|
return clk_register_gate(NULL, name, parent_name, 0, reg + offset,
|
|
STARFIVE_CLK_INVERT_SHIFT, 0, NULL);
|
|
}
|
|
|
|
static struct clk *starfive_clk_divider(void __iomem *reg,
|
|
const char *name,
|
|
const char *parent_name,
|
|
unsigned int offset,
|
|
u8 width)
|
|
{
|
|
return clk_register_divider(NULL, name, parent_name, 0, reg + offset,
|
|
0, width, CLK_DIVIDER_ONE_BASED);
|
|
}
|
|
|
|
static struct clk *starfive_clk_composite(void __iomem *reg,
|
|
const char *name,
|
|
const char * const *parent_names,
|
|
unsigned int num_parents,
|
|
unsigned int offset,
|
|
unsigned int mux_width,
|
|
unsigned int gate_width,
|
|
unsigned int div_width)
|
|
{
|
|
struct clk *clk = ERR_PTR(-ENOMEM);
|
|
struct clk_divider *div = NULL;
|
|
struct clk_gate *gate = NULL;
|
|
struct clk_mux *mux = NULL;
|
|
int mask_arry[4] = {0x1, 0x3, 0x7, 0xF};
|
|
int mask;
|
|
|
|
if (mux_width) {
|
|
if (mux_width > 4)
|
|
goto fail;
|
|
else
|
|
mask = mask_arry[mux_width - 1];
|
|
|
|
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
|
if (!mux)
|
|
goto fail;
|
|
|
|
mux->reg = reg + offset;
|
|
mux->mask = mask;
|
|
mux->shift = STARFIVE_CLK_MUX_SHIFT;
|
|
mux->num_parents = num_parents;
|
|
mux->flags = 0;
|
|
mux->parent_names = parent_names;
|
|
}
|
|
|
|
if (gate_width) {
|
|
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
|
|
|
if (!gate)
|
|
goto fail;
|
|
|
|
gate->reg = reg + offset;
|
|
gate->bit_idx = STARFIVE_CLK_ENABLE_SHIFT;
|
|
gate->flags = 0;
|
|
}
|
|
|
|
if (div_width) {
|
|
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
|
if (!div)
|
|
goto fail;
|
|
|
|
div->reg = reg + offset;
|
|
|
|
if (offset == OFFSET(JH7110_SYSCLK_UART3_CORE) ||
|
|
offset == OFFSET(JH7110_SYSCLK_UART4_CORE) ||
|
|
offset == OFFSET(JH7110_SYSCLK_UART5_CORE)) {
|
|
div->shift = 8;
|
|
div->width = 8;
|
|
} else {
|
|
div->shift = STARFIVE_CLK_DIV_SHIFT;
|
|
div->width = div_width;
|
|
}
|
|
div->flags = CLK_DIVIDER_ONE_BASED;
|
|
div->table = NULL;
|
|
}
|
|
|
|
clk = clk_register_composite(NULL, name,
|
|
parent_names, num_parents,
|
|
&mux->clk, &clk_mux_ops,
|
|
&div->clk, &clk_divider_ops,
|
|
&gate->clk, &clk_gate_ops, 0);
|
|
|
|
if (IS_ERR(clk))
|
|
goto fail;
|
|
|
|
return clk;
|
|
|
|
fail:
|
|
kfree(gate);
|
|
kfree(div);
|
|
kfree(mux);
|
|
return ERR_CAST(clk);
|
|
}
|
|
|
|
static struct clk *starfive_clk_fix_parent_composite(void __iomem *reg,
|
|
const char *name,
|
|
const char *parent_names,
|
|
unsigned int offset,
|
|
unsigned int mux_width,
|
|
unsigned int gate_width,
|
|
unsigned int div_width)
|
|
{
|
|
const char * const *parents;
|
|
|
|
parents = &parent_names;
|
|
|
|
return starfive_clk_composite(reg, name, parents, 1, offset,
|
|
mux_width, gate_width, div_width);
|
|
}
|
|
|
|
static struct clk *starfive_clk_gate_divider(void __iomem *reg,
|
|
const char *name,
|
|
const char *parent,
|
|
unsigned int offset,
|
|
unsigned int width)
|
|
{
|
|
const char * const *parent_names;
|
|
|
|
parent_names = &parent;
|
|
|
|
return starfive_clk_composite(reg, name, parent_names, 1,
|
|
offset, 0, 1, width);
|
|
}
|
|
|
|
static int jh7110_syscrg_init(struct udevice *dev)
|
|
{
|
|
struct jh7110_clk_priv *priv = dev_get_priv(dev);
|
|
struct ofnode_phandle_args args;
|
|
fdt_addr_t addr;
|
|
struct clk *pclk;
|
|
int ret;
|
|
|
|
ret = ofnode_parse_phandle_with_args(dev->node_, "starfive,sys-syscon", NULL, 0, 0, &args);
|
|
if (ret)
|
|
return ret;
|
|
|
|
addr = ofnode_get_addr(args.node);
|
|
if (addr == FDT_ADDR_T_NONE)
|
|
return -EINVAL;
|
|
|
|
clk_dm(JH7110_SYSCLK_PLL0_OUT,
|
|
starfive_jh7110_pll("pll0_out", "oscillator", (void __iomem *)addr,
|
|
priv->reg, &starfive_jh7110_pll0));
|
|
clk_dm(JH7110_SYSCLK_PLL1_OUT,
|
|
starfive_jh7110_pll("pll1_out", "oscillator", (void __iomem *)addr,
|
|
priv->reg, &starfive_jh7110_pll1));
|
|
clk_dm(JH7110_SYSCLK_PLL2_OUT,
|
|
starfive_jh7110_pll("pll2_out", "oscillator", (void __iomem *)addr,
|
|
priv->reg, &starfive_jh7110_pll2));
|
|
clk_dm(JH7110_SYSCLK_CPU_ROOT,
|
|
starfive_clk_mux(priv->reg, "cpu_root",
|
|
OFFSET(JH7110_SYSCLK_CPU_ROOT), 1,
|
|
cpu_root_sels, ARRAY_SIZE(cpu_root_sels)));
|
|
clk_dm(JH7110_SYSCLK_CPU_CORE,
|
|
starfive_clk_divider(priv->reg,
|
|
"cpu_core", "cpu_root",
|
|
OFFSET(JH7110_SYSCLK_CPU_CORE), 3));
|
|
clk_dm(JH7110_SYSCLK_CPU_BUS,
|
|
starfive_clk_divider(priv->reg,
|
|
"cpu_bus", "cpu_core",
|
|
OFFSET(JH7110_SYSCLK_CPU_BUS), 2));
|
|
clk_dm(JH7110_SYSCLK_PERH_ROOT,
|
|
starfive_clk_composite(priv->reg,
|
|
"perh_root",
|
|
perh_root_sels, ARRAY_SIZE(perh_root_sels),
|
|
OFFSET(JH7110_SYSCLK_PERH_ROOT), 1, 0, 2));
|
|
clk_dm(JH7110_SYSCLK_BUS_ROOT,
|
|
starfive_clk_mux(priv->reg, "bus_root",
|
|
OFFSET(JH7110_SYSCLK_BUS_ROOT), 1,
|
|
bus_root_sels, ARRAY_SIZE(bus_root_sels)));
|
|
clk_dm(JH7110_SYSCLK_NOCSTG_BUS,
|
|
starfive_clk_divider(priv->reg,
|
|
"nocstg_bus", "bus_root",
|
|
OFFSET(JH7110_SYSCLK_NOCSTG_BUS), 3));
|
|
clk_dm(JH7110_SYSCLK_AXI_CFG0,
|
|
starfive_clk_divider(priv->reg,
|
|
"axi_cfg0", "bus_root",
|
|
OFFSET(JH7110_SYSCLK_AXI_CFG0), 2));
|
|
clk_dm(JH7110_SYSCLK_STG_AXIAHB,
|
|
starfive_clk_divider(priv->reg,
|
|
"stg_axiahb", "axi_cfg0",
|
|
OFFSET(JH7110_SYSCLK_STG_AXIAHB), 2));
|
|
clk_dm(JH7110_SYSCLK_AHB0,
|
|
starfive_clk_gate(priv->reg,
|
|
"ahb0", "stg_axiahb",
|
|
OFFSET(JH7110_SYSCLK_AHB0)));
|
|
clk_dm(JH7110_SYSCLK_AHB1,
|
|
starfive_clk_gate(priv->reg,
|
|
"ahb1", "stg_axiahb",
|
|
OFFSET(JH7110_SYSCLK_AHB1)));
|
|
clk_dm(JH7110_SYSCLK_APB_BUS,
|
|
starfive_clk_divider(priv->reg,
|
|
"apb_bus", "stg_axiahb",
|
|
OFFSET(JH7110_SYSCLK_APB_BUS), 4));
|
|
clk_dm(JH7110_SYSCLK_APB0,
|
|
starfive_clk_gate(priv->reg,
|
|
"apb0", "apb_bus",
|
|
OFFSET(JH7110_SYSCLK_APB0)));
|
|
clk_dm(JH7110_SYSCLK_QSPI_AHB,
|
|
starfive_clk_gate(priv->reg,
|
|
"qspi_ahb", "ahb1",
|
|
OFFSET(JH7110_SYSCLK_QSPI_AHB)));
|
|
clk_dm(JH7110_SYSCLK_QSPI_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"qspi_apb", "apb_bus",
|
|
OFFSET(JH7110_SYSCLK_QSPI_APB)));
|
|
clk_dm(JH7110_SYSCLK_QSPI_REF_SRC,
|
|
starfive_clk_divider(priv->reg,
|
|
"qspi_ref_src", "pll0_out",
|
|
OFFSET(JH7110_SYSCLK_QSPI_REF_SRC), 5));
|
|
clk_dm(JH7110_SYSCLK_QSPI_REF,
|
|
starfive_clk_composite(priv->reg,
|
|
"qspi_ref",
|
|
qspi_ref_sels, ARRAY_SIZE(qspi_ref_sels),
|
|
OFFSET(JH7110_SYSCLK_QSPI_REF), 1, 1, 0));
|
|
clk_dm(JH7110_SYSCLK_SDIO0_AHB,
|
|
starfive_clk_gate(priv->reg,
|
|
"sdio0_ahb", "ahb0",
|
|
OFFSET(JH7110_SYSCLK_SDIO0_AHB)));
|
|
clk_dm(JH7110_SYSCLK_SDIO1_AHB,
|
|
starfive_clk_gate(priv->reg,
|
|
"sdio1_ahb", "ahb0",
|
|
OFFSET(JH7110_SYSCLK_SDIO1_AHB)));
|
|
clk_dm(JH7110_SYSCLK_SDIO0_SDCARD,
|
|
starfive_clk_fix_parent_composite(priv->reg,
|
|
"sdio0_sdcard", "axi_cfg0",
|
|
OFFSET(JH7110_SYSCLK_SDIO0_SDCARD), 0, 1, 4));
|
|
clk_dm(JH7110_SYSCLK_SDIO1_SDCARD,
|
|
starfive_clk_fix_parent_composite(priv->reg,
|
|
"sdio1_sdcard", "axi_cfg0",
|
|
OFFSET(JH7110_SYSCLK_SDIO1_SDCARD), 0, 1, 4));
|
|
clk_dm(JH7110_SYSCLK_USB_125M,
|
|
starfive_clk_divider(priv->reg,
|
|
"usb_125m", "pll0_out",
|
|
OFFSET(JH7110_SYSCLK_USB_125M), 4));
|
|
clk_dm(JH7110_SYSCLK_NOC_BUS_STG_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"noc_bus_stg_axi", "nocstg_bus",
|
|
OFFSET(JH7110_SYSCLK_NOC_BUS_STG_AXI)));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_AHB,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac1_ahb", "ahb0",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_AHB)));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac1_axi", "stg_axiahb",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_AXI)));
|
|
clk_dm(JH7110_SYSCLK_GMAC_SRC,
|
|
starfive_clk_divider(priv->reg,
|
|
"gmac_src", "pll0_out",
|
|
OFFSET(JH7110_SYSCLK_GMAC_SRC), 3));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_GTXCLK,
|
|
starfive_clk_divider(priv->reg,
|
|
"gmac1_gtxclk", "pll0_out",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_GTXCLK), 4));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_GTXC,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac1_gtxc", "gmac1_gtxclk",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_GTXC)));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_RMII_RTX,
|
|
starfive_clk_divider(priv->reg,
|
|
"gmac1_rmii_rtx", "gmac1-rmii-refin-clock",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_RMII_RTX), 5));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_PTP,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"gmac1_ptp", "gmac_src",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_PTP), 5));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_RX,
|
|
starfive_clk_mux(priv->reg, "gmac1_rx",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_RX), 1,
|
|
gmac1_rx_sels, ARRAY_SIZE(gmac1_rx_sels)));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_TX,
|
|
starfive_clk_composite(priv->reg,
|
|
"gmac1_tx",
|
|
gmac1_tx_sels, ARRAY_SIZE(gmac1_tx_sels),
|
|
OFFSET(JH7110_SYSCLK_GMAC1_TX), 1, 1, 0));
|
|
clk_dm(JH7110_SYSCLK_GMAC1_TX_INV,
|
|
starfive_clk_inv(priv->reg,
|
|
"gmac1_tx_inv", "gmac1_tx",
|
|
OFFSET(JH7110_SYSCLK_GMAC1_TX_INV)));
|
|
clk_dm(JH7110_SYSCLK_GMAC0_GTXCLK,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"gmac0_gtxclk", "pll0_out",
|
|
OFFSET(JH7110_SYSCLK_GMAC0_GTXCLK), 4));
|
|
clk_dm(JH7110_SYSCLK_GMAC0_PTP,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"gmac0_ptp", "gmac_src",
|
|
OFFSET(JH7110_SYSCLK_GMAC0_PTP), 5));
|
|
clk_dm(JH7110_SYSCLK_GMAC0_GTXC,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac0_gtxc", "gmac0_gtxclk",
|
|
OFFSET(JH7110_SYSCLK_GMAC0_GTXC)));
|
|
clk_dm(JH7110_SYSCLK_UART0_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart0_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART0_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART0_CORE,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart0_core", "oscillator",
|
|
OFFSET(JH7110_SYSCLK_UART0_CORE)));
|
|
clk_dm(JH7110_SYSCLK_UART1_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart1_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART1_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART1_CORE,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart1_core", "oscillator",
|
|
OFFSET(JH7110_SYSCLK_UART1_CORE)));
|
|
clk_dm(JH7110_SYSCLK_UART2_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart2_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART2_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART2_CORE,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart2_core", "oscillator",
|
|
OFFSET(JH7110_SYSCLK_UART2_CORE)));
|
|
clk_dm(JH7110_SYSCLK_UART3_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart3_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART3_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART3_CORE,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"uart3_core", "perh_root",
|
|
OFFSET(JH7110_SYSCLK_UART3_CORE), 8));
|
|
clk_dm(JH7110_SYSCLK_UART4_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart4_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART4_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART4_CORE,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"uart4_core", "perh_root",
|
|
OFFSET(JH7110_SYSCLK_UART4_CORE), 8));
|
|
clk_dm(JH7110_SYSCLK_UART5_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"uart5_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_UART5_APB)));
|
|
clk_dm(JH7110_SYSCLK_UART5_CORE,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"uart5_core", "perh_root",
|
|
OFFSET(JH7110_SYSCLK_UART5_CORE), 8));
|
|
clk_dm(JH7110_SYSCLK_I2C2_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"i2c2_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_I2C2_APB)));
|
|
clk_dm(JH7110_SYSCLK_I2C5_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"i2c5_apb", "apb0",
|
|
OFFSET(JH7110_SYSCLK_I2C5_APB)));
|
|
|
|
/* enable noc_bus_stg_axi clock */
|
|
if (!clk_get_by_id(JH7110_SYSCLK_NOC_BUS_STG_AXI, &pclk))
|
|
clk_enable(pclk);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jh7110_aoncrg_init(struct udevice *dev)
|
|
{
|
|
struct jh7110_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
clk_dm(JH7110_AONCLK_OSC_DIV4,
|
|
starfive_clk_divider(priv->reg,
|
|
"osc_div4", "oscillator",
|
|
AONOFFSET(JH7110_AONCLK_OSC_DIV4), 5));
|
|
clk_dm(JH7110_AONCLK_APB_FUNC,
|
|
starfive_clk_mux(priv->reg, "apb_func",
|
|
AONOFFSET(JH7110_AONCLK_APB_FUNC), 1,
|
|
apb_func_sels, ARRAY_SIZE(apb_func_sels)));
|
|
clk_dm(JH7110_AONCLK_GMAC0_AHB,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac0_ahb", "stg_axiahb",
|
|
AONOFFSET(JH7110_AONCLK_GMAC0_AHB)));
|
|
clk_dm(JH7110_AONCLK_GMAC0_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"gmac0_axi", "stg_axiahb",
|
|
AONOFFSET(JH7110_AONCLK_GMAC0_AXI)));
|
|
clk_dm(JH7110_AONCLK_GMAC0_RMII_RTX,
|
|
starfive_clk_divider(priv->reg,
|
|
"gmac0_rmii_rtx", "gmac0-rmii-refin-clock",
|
|
AONOFFSET(JH7110_AONCLK_GMAC0_RMII_RTX), 5));
|
|
clk_dm(JH7110_AONCLK_GMAC0_TX,
|
|
starfive_clk_composite(priv->reg,
|
|
"gmac0_tx", gmac0_tx_sels,
|
|
ARRAY_SIZE(gmac0_tx_sels),
|
|
AONOFFSET(JH7110_AONCLK_GMAC0_TX), 1, 1, 0));
|
|
clk_dm(JH7110_AONCLK_GMAC0_TX_INV,
|
|
starfive_clk_inv(priv->reg,
|
|
"gmac0_tx_inv", "gmac0_tx",
|
|
AONOFFSET(JH7110_AONCLK_GMAC0_TX_INV)));
|
|
clk_dm(JH7110_AONCLK_OTPC_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"otpc_apb", "apb_bus",
|
|
AONOFFSET(JH7110_AONCLK_OTPC_APB)));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jh7110_stgcrg_init(struct udevice *dev)
|
|
{
|
|
struct jh7110_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
clk_dm(JH7110_STGCLK_USB_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"usb_apb", "apb_bus",
|
|
STGOFFSET(JH7110_STGCLK_USB_APB)));
|
|
clk_dm(JH7110_STGCLK_USB_UTMI_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"usb_utmi_apb", "apb_bus",
|
|
STGOFFSET(JH7110_STGCLK_USB_UTMI_APB)));
|
|
clk_dm(JH7110_STGCLK_USB_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"usb_axi", "stg_axiahb",
|
|
STGOFFSET(JH7110_STGCLK_USB_AXI)));
|
|
clk_dm(JH7110_STGCLK_USB_LPM,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"usb_lpm", "oscillator",
|
|
STGOFFSET(JH7110_STGCLK_USB_LPM), 2));
|
|
clk_dm(JH7110_STGCLK_USB_STB,
|
|
starfive_clk_gate_divider(priv->reg,
|
|
"usb_stb", "oscillator",
|
|
STGOFFSET(JH7110_STGCLK_USB_STB), 3));
|
|
clk_dm(JH7110_STGCLK_USB_APP_125,
|
|
starfive_clk_gate(priv->reg,
|
|
"usb_app_125", "usb_125m",
|
|
STGOFFSET(JH7110_STGCLK_USB_APP_125)));
|
|
clk_dm(JH7110_STGCLK_USB_REFCLK,
|
|
starfive_clk_divider(priv->reg, "usb_refclk", "oscillator",
|
|
STGOFFSET(JH7110_STGCLK_USB_REFCLK), 2));
|
|
clk_dm(JH7110_STGCLK_PCIE0_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie0_axi", "stg_axiahb",
|
|
STGOFFSET(JH7110_STGCLK_PCIE0_AXI)));
|
|
clk_dm(JH7110_STGCLK_PCIE0_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie0_apb", "apb_bus",
|
|
STGOFFSET(JH7110_STGCLK_PCIE0_APB)));
|
|
clk_dm(JH7110_STGCLK_PCIE0_TL,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie0_tl", "stg_axiahb",
|
|
STGOFFSET(JH7110_STGCLK_PCIE0_TL)));
|
|
clk_dm(JH7110_STGCLK_PCIE1_AXI,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie1_axi", "stg_axiahb",
|
|
STGOFFSET(JH7110_STGCLK_PCIE1_AXI)));
|
|
clk_dm(JH7110_STGCLK_PCIE1_APB,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie1_apb", "apb_bus",
|
|
STGOFFSET(JH7110_STGCLK_PCIE1_APB)));
|
|
clk_dm(JH7110_STGCLK_PCIE1_TL,
|
|
starfive_clk_gate(priv->reg,
|
|
"pcie1_tl", "stg_axiahb",
|
|
STGOFFSET(JH7110_STGCLK_PCIE1_TL)));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jh7110_clk_probe(struct udevice *dev)
|
|
{
|
|
struct jh7110_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
priv->init = (jh1710_init_fn)dev_get_driver_data(dev);
|
|
priv->reg = (void __iomem *)dev_read_addr_ptr(dev);
|
|
|
|
if (priv->init)
|
|
return priv->init(dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jh7110_clk_bind(struct udevice *dev)
|
|
{
|
|
/* The reset driver does not have a device node, so bind it here */
|
|
return device_bind_driver_to_node(dev, "jh7110_reset", dev->name,
|
|
dev_ofnode(dev), NULL);
|
|
}
|
|
|
|
static const struct udevice_id jh7110_clk_of_match[] = {
|
|
{ .compatible = "starfive,jh7110-syscrg",
|
|
.data = (ulong)&jh7110_syscrg_init
|
|
},
|
|
{ .compatible = "starfive,jh7110-stgcrg",
|
|
.data = (ulong)&jh7110_stgcrg_init
|
|
},
|
|
{ .compatible = "starfive,jh7110-aoncrg",
|
|
.data = (ulong)&jh7110_aoncrg_init
|
|
},
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(jh7110_clk) = {
|
|
.name = "jh7110_clk",
|
|
.id = UCLASS_CLK,
|
|
.of_match = jh7110_clk_of_match,
|
|
.probe = jh7110_clk_probe,
|
|
.ops = &ccf_clk_ops,
|
|
.priv_auto = sizeof(struct jh7110_clk_priv),
|
|
.bind = jh7110_clk_bind,
|
|
};
|