1
0
Fork 0
alistair23-linux/drivers/clk/s32/s32v234/clk.c

110 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2015-2016 Freescale Semiconductor, Inc.
* Copyright 2017-2018 NXP
*/
#include <linux/of_address.h>
#include <linux/clk.h>
#include <dt-bindings/clock/s32v234-clock.h>
#include "clk.h"
static void __iomem *mc_cgm0_base;
static void __iomem *mc_me_base;
static void __iomem *src_base;
DEFINE_SPINLOCK(s32v234_lock);
/* sources for multiplexer clocks, this is used multiple times */
PNAME(osc_sels) = {"firc", "fxosc", };
static struct clk *clk[S32V234_CLK_END];
static struct clk_onecell_data clk_data;
static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node)
{
struct device_node *np;
clk[S32V234_CLK_DUMMY] = s32_clk_fixed("dummy", 0);
clk[S32V234_CLK_FXOSC] = s32_obtain_fixed_clock("fxosc", 0);
clk[S32V234_CLK_FIRC] = s32_obtain_fixed_clock("firc", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_me");
mc_me_base = of_iomap(np, 0);
if (WARN_ON(!mc_me_base))
return;
np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-src");
src_base = of_iomap(np, 0);
if (WARN_ON(!src_base))
return;
np = mc_cgm0_node;
mc_cgm0_base = of_iomap(np, 0);
if (WARN_ON(!mc_cgm0_base))
return;
enable_cpumodes_onperipheralconfig(mc_me_base, MC_ME_RUN_PCn_DRUN |
MC_ME_RUN_PCn_RUN0 |
MC_ME_RUN_PCn_RUN1 |
MC_ME_RUN_PCn_RUN2 |
MC_ME_RUN_PCn_RUN3,
0);
/* turn on XOSC and FIRC */
enable_clocks_sources(MC_ME_MODE_MC_MVRON, MC_ME_MODE_MC_XOSCON |
MC_ME_MODE_MC_FIRCON,
MC_ME_RUNn_MC(mc_me_base, 0));
/* transition the core to RUN0 mode */
entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0);
clk[S32V234_CLK_PERIPHPLL_SRC_SEL] = s32_clk_mux("periphpll_sel",
SRC_GPR1, SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET,
SRC_GPR1_XPLL_SRC_SEL_SIZE,
osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock);
/* PERIPH_PLL */
clk[S32V234_CLK_PERIPHPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_PERIPH,
"periphpll_vco", "periphpll_sel",
PERIPHPLL_PLLDIG(mc_cgm0_base),
PERIPHPLL_PLLDIG_PLLDV_MFD, PERIPHPLL_PLLDIG_PLLDV_MFN,
PERIPHPLL_PLLDIG_PLLDV_RFDPHI0,
PERIPHPLL_PLLDIG_PLLDV_RFDPHI1);
clk[S32V234_CLK_PERIPHPLL_PHI0] =
s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH,
"periphpll_phi0", "periphpll_vco",
PERIPHPLL_PLLDIG(mc_cgm0_base), 0);
clk[S32V234_CLK_PERIPHPLL_PHI1] =
s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH,
"periphpll_phi1", "periphpll_vco",
PERIPHPLL_PLLDIG(mc_cgm0_base), 1);
clk[S32V234_CLK_PERIPHPLL_PHI0_DIV3] = s32_clk_fixed_factor(
"periphpll_phi0_div3", "periphpll_phi0", 1, 3);
clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor(
"periphpll_phi0_div5", "periphpll_phi0", 1, 5);
/* enable PERIPHPLL */
enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL,
MC_ME_RUNn_MC(mc_me_base, 0));
/* set the system clock */
enable_sysclock(MC_ME_MODE_MC_SYSCLK(0x2),
MC_ME_RUNn_MC(mc_me_base, 0));
/* transition the core to RUN0 mode */
entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0);
/* Add the clocks to provider list */
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
CLK_OF_DECLARE(S32V234, "fsl,s32v234-mc_cgm0", s32v234_clocks_init);