Commit 34775209 authored by Neil Armstrong's avatar Neil Armstrong
Browse files

clk: meson-g12a: add PCIE PLL clocks



Add the PCIe reference clock feeding the USB3 + PCIE combo PHY.

This PLL needs a very precise register sequence to permit to be locked,
thus using the specific clk-pll pcie ops.

The PLL is then followed by :
- a fixed /2 divider
- a 5-bit 1-based divider
- a final /2 divider

This reference clock is fixed to 100MHz, thus only a single PLL setup
is added.

Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Acked-by: default avatarJerome Brunet <jbrunet@baylibre.com>
Link: https://lkml.kernel.org/r/20190307141455.23879-4-narmstrong@baylibre.com
parent 39b85002
Loading
Loading
Loading
Loading
+118 −0
Original line number Diff line number Diff line
@@ -614,6 +614,118 @@ static struct clk_regmap g12a_hifi_pll = {
	},
};

/*
 * The Meson G12A PCIE PLL is fined tuned to deliver a very precise
 * 100MHz reference clock for the PCIe Analog PHY, and thus requires
 * a strict register sequence to enable the PLL.
 */
static const struct reg_sequence g12a_pcie_pll_init_regs[] = {
	{ .reg = HHI_PCIE_PLL_CNTL0,	.def = 0x20090496 },
	{ .reg = HHI_PCIE_PLL_CNTL0,	.def = 0x30090496 },
	{ .reg = HHI_PCIE_PLL_CNTL1,	.def = 0x00000000 },
	{ .reg = HHI_PCIE_PLL_CNTL2,	.def = 0x00001100 },
	{ .reg = HHI_PCIE_PLL_CNTL3,	.def = 0x10058e00 },
	{ .reg = HHI_PCIE_PLL_CNTL4,	.def = 0x000100c0 },
	{ .reg = HHI_PCIE_PLL_CNTL5,	.def = 0x68000048 },
	{ .reg = HHI_PCIE_PLL_CNTL5,	.def = 0x68000068, .delay_us = 20 },
	{ .reg = HHI_PCIE_PLL_CNTL4,	.def = 0x008100c0, .delay_us = 10 },
	{ .reg = HHI_PCIE_PLL_CNTL0,	.def = 0x34090496 },
	{ .reg = HHI_PCIE_PLL_CNTL0,	.def = 0x14090496, .delay_us = 10 },
	{ .reg = HHI_PCIE_PLL_CNTL2,	.def = 0x00001000 },
};

/* Keep a single entry table for recalc/round_rate() ops */
static const struct pll_params_table g12a_pcie_pll_table[] = {
	PLL_PARAMS(150, 1),
	{0, 0},
};

static struct clk_regmap g12a_pcie_pll_dco = {
	.data = &(struct meson_clk_pll_data){
		.en = {
			.reg_off = HHI_PCIE_PLL_CNTL0,
			.shift   = 28,
			.width   = 1,
		},
		.m = {
			.reg_off = HHI_PCIE_PLL_CNTL0,
			.shift   = 0,
			.width   = 8,
		},
		.n = {
			.reg_off = HHI_PCIE_PLL_CNTL0,
			.shift   = 10,
			.width   = 5,
		},
		.frac = {
			.reg_off = HHI_PCIE_PLL_CNTL1,
			.shift   = 0,
			.width   = 12,
		},
		.l = {
			.reg_off = HHI_PCIE_PLL_CNTL0,
			.shift   = 31,
			.width   = 1,
		},
		.rst = {
			.reg_off = HHI_PCIE_PLL_CNTL0,
			.shift   = 29,
			.width   = 1,
		},
		.table = g12a_pcie_pll_table,
		.init_regs = g12a_pcie_pll_init_regs,
		.init_count = ARRAY_SIZE(g12a_pcie_pll_init_regs),
	},
	.hw.init = &(struct clk_init_data){
		.name = "pcie_pll_dco",
		.ops = &meson_clk_pcie_pll_ops,
		.parent_names = (const char *[]){ IN_PREFIX "xtal" },
		.num_parents = 1,
	},
};

static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = {
	.mult = 1,
	.div = 2,
	.hw.init = &(struct clk_init_data){
		.name = "pcie_pll_dco_div2",
		.ops = &clk_fixed_factor_ops,
		.parent_names = (const char *[]){ "pcie_pll_dco" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap g12a_pcie_pll_od = {
	.data = &(struct clk_regmap_div_data){
		.offset = HHI_PCIE_PLL_CNTL0,
		.shift = 16,
		.width = 5,
		.flags = CLK_DIVIDER_ROUND_CLOSEST |
			 CLK_DIVIDER_ONE_BASED |
			 CLK_DIVIDER_ALLOW_ZERO,
	},
	.hw.init = &(struct clk_init_data){
		.name = "pcie_pll_od",
		.ops = &clk_regmap_divider_ops,
		.parent_names = (const char *[]){ "pcie_pll_dco_div2" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_fixed_factor g12a_pcie_pll = {
	.mult = 1,
	.div = 2,
	.hw.init = &(struct clk_init_data){
		.name = "pcie_pll_pll",
		.ops = &clk_fixed_factor_ops,
		.parent_names = (const char *[]){ "pcie_pll_od" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap g12a_hdmi_pll_dco = {
	.data = &(struct meson_clk_pll_data){
		.en = {
@@ -2499,6 +2611,10 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = {
		[CLKID_CPU_CLK_AXI]		= &g12a_cpu_clk_axi.hw,
		[CLKID_CPU_CLK_TRACE_DIV]	= &g12a_cpu_clk_trace_div.hw,
		[CLKID_CPU_CLK_TRACE]		= &g12a_cpu_clk_trace.hw,
		[CLKID_PCIE_PLL_DCO]		= &g12a_pcie_pll_dco.hw,
		[CLKID_PCIE_PLL_DCO_DIV2]	= &g12a_pcie_pll_dco_div2.hw,
		[CLKID_PCIE_PLL_OD]		= &g12a_pcie_pll_od.hw,
		[CLKID_PCIE_PLL]		= &g12a_pcie_pll.hw,
		[NR_CLKS]			= NULL,
	},
	.num = NR_CLKS,
@@ -2685,6 +2801,8 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
	&g12a_cpu_clk_axi,
	&g12a_cpu_clk_trace_div,
	&g12a_cpu_clk_trace,
	&g12a_pcie_pll_od,
	&g12a_pcie_pll_dco,
};

static const struct meson_eeclkc_data g12a_clkc_data = {
+4 −1
Original line number Diff line number Diff line
@@ -186,8 +186,11 @@
#define CLKID_CPU_CLK_AXI			195
#define CLKID_CPU_CLK_TRACE_DIV			196
#define CLKID_CPU_CLK_TRACE			197
#define CLKID_PCIE_PLL_DCO			198
#define CLKID_PCIE_PLL_DCO_DIV2			199
#define CLKID_PCIE_PLL_OD			200

#define NR_CLKS					198
#define NR_CLKS					202

/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/g12a-clkc.h>