162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PLL clock driver for Keystone devices
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013 Texas Instruments Inc.
662306a36Sopenharmony_ci *	Murali Karicheri <m-karicheri2@ti.com>
762306a36Sopenharmony_ci *	Santosh Shilimkar <santosh.shilimkar@ti.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/clk-provider.h>
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/io.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/of_address.h>
1462306a36Sopenharmony_ci#include <linux/of.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define PLLM_LOW_MASK		0x3f
1862306a36Sopenharmony_ci#define PLLM_HIGH_MASK		0x7ffc0
1962306a36Sopenharmony_ci#define MAIN_PLLM_HIGH_MASK	0x7f000
2062306a36Sopenharmony_ci#define PLLM_HIGH_SHIFT		6
2162306a36Sopenharmony_ci#define PLLD_MASK		0x3f
2262306a36Sopenharmony_ci#define CLKOD_MASK		0x780000
2362306a36Sopenharmony_ci#define CLKOD_SHIFT		19
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/**
2662306a36Sopenharmony_ci * struct clk_pll_data - pll data structure
2762306a36Sopenharmony_ci * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm
2862306a36Sopenharmony_ci *	register of pll controller, else it is in the pll_ctrl0((bit 11-6)
2962306a36Sopenharmony_ci * @phy_pllm: Physical address of PLLM in pll controller. Used when
3062306a36Sopenharmony_ci *	has_pllctrl is non zero.
3162306a36Sopenharmony_ci * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of
3262306a36Sopenharmony_ci *	Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL
3362306a36Sopenharmony_ci *	or PA PLL available on keystone2. These PLLs are controlled by
3462306a36Sopenharmony_ci *	this register. Main PLL is controlled by a PLL controller.
3562306a36Sopenharmony_ci * @pllm: PLL register map address for multiplier bits
3662306a36Sopenharmony_ci * @pllod: PLL register map address for post divider bits
3762306a36Sopenharmony_ci * @pll_ctl0: PLL controller map address
3862306a36Sopenharmony_ci * @pllm_lower_mask: multiplier lower mask
3962306a36Sopenharmony_ci * @pllm_upper_mask: multiplier upper mask
4062306a36Sopenharmony_ci * @pllm_upper_shift: multiplier upper shift
4162306a36Sopenharmony_ci * @plld_mask: divider mask
4262306a36Sopenharmony_ci * @clkod_mask: output divider mask
4362306a36Sopenharmony_ci * @clkod_shift: output divider shift
4462306a36Sopenharmony_ci * @plld_mask: divider mask
4562306a36Sopenharmony_ci * @postdiv: Fixed post divider
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_cistruct clk_pll_data {
4862306a36Sopenharmony_ci	bool has_pllctrl;
4962306a36Sopenharmony_ci	u32 phy_pllm;
5062306a36Sopenharmony_ci	u32 phy_pll_ctl0;
5162306a36Sopenharmony_ci	void __iomem *pllm;
5262306a36Sopenharmony_ci	void __iomem *pllod;
5362306a36Sopenharmony_ci	void __iomem *pll_ctl0;
5462306a36Sopenharmony_ci	u32 pllm_lower_mask;
5562306a36Sopenharmony_ci	u32 pllm_upper_mask;
5662306a36Sopenharmony_ci	u32 pllm_upper_shift;
5762306a36Sopenharmony_ci	u32 plld_mask;
5862306a36Sopenharmony_ci	u32 clkod_mask;
5962306a36Sopenharmony_ci	u32 clkod_shift;
6062306a36Sopenharmony_ci	u32 postdiv;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/**
6462306a36Sopenharmony_ci * struct clk_pll - Main pll clock
6562306a36Sopenharmony_ci * @hw: clk_hw for the pll
6662306a36Sopenharmony_ci * @pll_data: PLL driver specific data
6762306a36Sopenharmony_ci */
6862306a36Sopenharmony_cistruct clk_pll {
6962306a36Sopenharmony_ci	struct clk_hw hw;
7062306a36Sopenharmony_ci	struct clk_pll_data *pll_data;
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic unsigned long clk_pllclk_recalc(struct clk_hw *hw,
7662306a36Sopenharmony_ci					unsigned long parent_rate)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	struct clk_pll *pll = to_clk_pll(hw);
7962306a36Sopenharmony_ci	struct clk_pll_data *pll_data = pll->pll_data;
8062306a36Sopenharmony_ci	unsigned long rate = parent_rate;
8162306a36Sopenharmony_ci	u32  mult = 0, prediv, postdiv, val;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * get bits 0-5 of multiplier from pllctrl PLLM register
8562306a36Sopenharmony_ci	 * if has_pllctrl is non zero
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	if (pll_data->has_pllctrl) {
8862306a36Sopenharmony_ci		val = readl(pll_data->pllm);
8962306a36Sopenharmony_ci		mult = (val & pll_data->pllm_lower_mask);
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/* bit6-12 of PLLM is in Main PLL control register */
9362306a36Sopenharmony_ci	val = readl(pll_data->pll_ctl0);
9462306a36Sopenharmony_ci	mult |= ((val & pll_data->pllm_upper_mask)
9562306a36Sopenharmony_ci			>> pll_data->pllm_upper_shift);
9662306a36Sopenharmony_ci	prediv = (val & pll_data->plld_mask);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (!pll_data->has_pllctrl)
9962306a36Sopenharmony_ci		/* read post divider from od bits*/
10062306a36Sopenharmony_ci		postdiv = ((val & pll_data->clkod_mask) >>
10162306a36Sopenharmony_ci				 pll_data->clkod_shift) + 1;
10262306a36Sopenharmony_ci	else if (pll_data->pllod) {
10362306a36Sopenharmony_ci		postdiv = readl(pll_data->pllod);
10462306a36Sopenharmony_ci		postdiv = ((postdiv & pll_data->clkod_mask) >>
10562306a36Sopenharmony_ci				pll_data->clkod_shift) + 1;
10662306a36Sopenharmony_ci	} else
10762306a36Sopenharmony_ci		postdiv = pll_data->postdiv;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	rate /= (prediv + 1);
11062306a36Sopenharmony_ci	rate = (rate * (mult + 1));
11162306a36Sopenharmony_ci	rate /= postdiv;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return rate;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic const struct clk_ops clk_pll_ops = {
11762306a36Sopenharmony_ci	.recalc_rate = clk_pllclk_recalc,
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic struct clk *clk_register_pll(struct device *dev,
12162306a36Sopenharmony_ci			const char *name,
12262306a36Sopenharmony_ci			const char *parent_name,
12362306a36Sopenharmony_ci			struct clk_pll_data *pll_data)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	struct clk_init_data init;
12662306a36Sopenharmony_ci	struct clk_pll *pll;
12762306a36Sopenharmony_ci	struct clk *clk;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
13062306a36Sopenharmony_ci	if (!pll)
13162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	init.name = name;
13462306a36Sopenharmony_ci	init.ops = &clk_pll_ops;
13562306a36Sopenharmony_ci	init.flags = 0;
13662306a36Sopenharmony_ci	init.parent_names = (parent_name ? &parent_name : NULL);
13762306a36Sopenharmony_ci	init.num_parents = (parent_name ? 1 : 0);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	pll->pll_data	= pll_data;
14062306a36Sopenharmony_ci	pll->hw.init = &init;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	clk = clk_register(NULL, &pll->hw);
14362306a36Sopenharmony_ci	if (IS_ERR(clk))
14462306a36Sopenharmony_ci		goto out;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return clk;
14762306a36Sopenharmony_ciout:
14862306a36Sopenharmony_ci	kfree(pll);
14962306a36Sopenharmony_ci	return NULL;
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/**
15362306a36Sopenharmony_ci * _of_pll_clk_init - PLL initialisation via DT
15462306a36Sopenharmony_ci * @node: device tree node for this clock
15562306a36Sopenharmony_ci * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
15662306a36Sopenharmony_ci *		pll controller, else it is in the control register0(bit 11-6)
15762306a36Sopenharmony_ci */
15862306a36Sopenharmony_cistatic void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct clk_pll_data *pll_data;
16162306a36Sopenharmony_ci	const char *parent_name;
16262306a36Sopenharmony_ci	struct clk *clk;
16362306a36Sopenharmony_ci	int i;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL);
16662306a36Sopenharmony_ci	if (!pll_data) {
16762306a36Sopenharmony_ci		pr_err("%s: Out of memory\n", __func__);
16862306a36Sopenharmony_ci		return;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	parent_name = of_clk_get_parent_name(node, 0);
17262306a36Sopenharmony_ci	if (of_property_read_u32(node, "fixed-postdiv",	&pll_data->postdiv)) {
17362306a36Sopenharmony_ci		/* assume the PLL has output divider register bits */
17462306a36Sopenharmony_ci		pll_data->clkod_mask = CLKOD_MASK;
17562306a36Sopenharmony_ci		pll_data->clkod_shift = CLKOD_SHIFT;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci		/*
17862306a36Sopenharmony_ci		 * Check if there is an post-divider register. If not
17962306a36Sopenharmony_ci		 * assume od bits are part of control register.
18062306a36Sopenharmony_ci		 */
18162306a36Sopenharmony_ci		i = of_property_match_string(node, "reg-names",
18262306a36Sopenharmony_ci					     "post-divider");
18362306a36Sopenharmony_ci		pll_data->pllod = of_iomap(node, i);
18462306a36Sopenharmony_ci	}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	i = of_property_match_string(node, "reg-names", "control");
18762306a36Sopenharmony_ci	pll_data->pll_ctl0 = of_iomap(node, i);
18862306a36Sopenharmony_ci	if (!pll_data->pll_ctl0) {
18962306a36Sopenharmony_ci		pr_err("%s: ioremap failed\n", __func__);
19062306a36Sopenharmony_ci		iounmap(pll_data->pllod);
19162306a36Sopenharmony_ci		goto out;
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	pll_data->pllm_lower_mask = PLLM_LOW_MASK;
19562306a36Sopenharmony_ci	pll_data->pllm_upper_shift = PLLM_HIGH_SHIFT;
19662306a36Sopenharmony_ci	pll_data->plld_mask = PLLD_MASK;
19762306a36Sopenharmony_ci	pll_data->has_pllctrl = pllctrl;
19862306a36Sopenharmony_ci	if (!pll_data->has_pllctrl) {
19962306a36Sopenharmony_ci		pll_data->pllm_upper_mask = PLLM_HIGH_MASK;
20062306a36Sopenharmony_ci	} else {
20162306a36Sopenharmony_ci		pll_data->pllm_upper_mask = MAIN_PLLM_HIGH_MASK;
20262306a36Sopenharmony_ci		i = of_property_match_string(node, "reg-names", "multiplier");
20362306a36Sopenharmony_ci		pll_data->pllm = of_iomap(node, i);
20462306a36Sopenharmony_ci		if (!pll_data->pllm) {
20562306a36Sopenharmony_ci			iounmap(pll_data->pll_ctl0);
20662306a36Sopenharmony_ci			iounmap(pll_data->pllod);
20762306a36Sopenharmony_ci			goto out;
20862306a36Sopenharmony_ci		}
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	clk = clk_register_pll(NULL, node->name, parent_name, pll_data);
21262306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(clk)) {
21362306a36Sopenharmony_ci		of_clk_add_provider(node, of_clk_src_simple_get, clk);
21462306a36Sopenharmony_ci		return;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ciout:
21862306a36Sopenharmony_ci	pr_err("%s: error initializing pll %pOFn\n", __func__, node);
21962306a36Sopenharmony_ci	kfree(pll_data);
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci/**
22362306a36Sopenharmony_ci * of_keystone_pll_clk_init - PLL initialisation DT wrapper
22462306a36Sopenharmony_ci * @node: device tree node for this clock
22562306a36Sopenharmony_ci */
22662306a36Sopenharmony_cistatic void __init of_keystone_pll_clk_init(struct device_node *node)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	_of_pll_clk_init(node, false);
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ciCLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock",
23162306a36Sopenharmony_ci					of_keystone_pll_clk_init);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci/**
23462306a36Sopenharmony_ci * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper
23562306a36Sopenharmony_ci * @node: device tree node for this clock
23662306a36Sopenharmony_ci */
23762306a36Sopenharmony_cistatic void __init of_keystone_main_pll_clk_init(struct device_node *node)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	_of_pll_clk_init(node, true);
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ciCLK_OF_DECLARE(keystone_main_pll_clock, "ti,keystone,main-pll-clock",
24262306a36Sopenharmony_ci						of_keystone_main_pll_clk_init);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci/**
24562306a36Sopenharmony_ci * of_pll_div_clk_init - PLL divider setup function
24662306a36Sopenharmony_ci * @node: device tree node for this clock
24762306a36Sopenharmony_ci */
24862306a36Sopenharmony_cistatic void __init of_pll_div_clk_init(struct device_node *node)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	const char *parent_name;
25162306a36Sopenharmony_ci	void __iomem *reg;
25262306a36Sopenharmony_ci	u32 shift, mask;
25362306a36Sopenharmony_ci	struct clk *clk;
25462306a36Sopenharmony_ci	const char *clk_name = node->name;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	of_property_read_string(node, "clock-output-names", &clk_name);
25762306a36Sopenharmony_ci	reg = of_iomap(node, 0);
25862306a36Sopenharmony_ci	if (!reg) {
25962306a36Sopenharmony_ci		pr_err("%s: ioremap failed\n", __func__);
26062306a36Sopenharmony_ci		return;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	parent_name = of_clk_get_parent_name(node, 0);
26462306a36Sopenharmony_ci	if (!parent_name) {
26562306a36Sopenharmony_ci		pr_err("%s: missing parent clock\n", __func__);
26662306a36Sopenharmony_ci		iounmap(reg);
26762306a36Sopenharmony_ci		return;
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	if (of_property_read_u32(node, "bit-shift", &shift)) {
27162306a36Sopenharmony_ci		pr_err("%s: missing 'shift' property\n", __func__);
27262306a36Sopenharmony_ci		iounmap(reg);
27362306a36Sopenharmony_ci		return;
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (of_property_read_u32(node, "bit-mask", &mask)) {
27762306a36Sopenharmony_ci		pr_err("%s: missing 'bit-mask' property\n", __func__);
27862306a36Sopenharmony_ci		iounmap(reg);
27962306a36Sopenharmony_ci		return;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
28362306a36Sopenharmony_ci				 mask, 0, NULL);
28462306a36Sopenharmony_ci	if (IS_ERR(clk)) {
28562306a36Sopenharmony_ci		pr_err("%s: error registering divider %s\n", __func__, clk_name);
28662306a36Sopenharmony_ci		iounmap(reg);
28762306a36Sopenharmony_ci		return;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	of_clk_add_provider(node, of_clk_src_simple_get, clk);
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ciCLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/**
29562306a36Sopenharmony_ci * of_pll_mux_clk_init - PLL mux setup function
29662306a36Sopenharmony_ci * @node: device tree node for this clock
29762306a36Sopenharmony_ci */
29862306a36Sopenharmony_cistatic void __init of_pll_mux_clk_init(struct device_node *node)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	void __iomem *reg;
30162306a36Sopenharmony_ci	u32 shift, mask;
30262306a36Sopenharmony_ci	struct clk *clk;
30362306a36Sopenharmony_ci	const char *parents[2];
30462306a36Sopenharmony_ci	const char *clk_name = node->name;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	of_property_read_string(node, "clock-output-names", &clk_name);
30762306a36Sopenharmony_ci	reg = of_iomap(node, 0);
30862306a36Sopenharmony_ci	if (!reg) {
30962306a36Sopenharmony_ci		pr_err("%s: ioremap failed\n", __func__);
31062306a36Sopenharmony_ci		return;
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	of_clk_parent_fill(node, parents, 2);
31462306a36Sopenharmony_ci	if (!parents[0] || !parents[1]) {
31562306a36Sopenharmony_ci		pr_err("%s: missing parent clocks\n", __func__);
31662306a36Sopenharmony_ci		return;
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	if (of_property_read_u32(node, "bit-shift", &shift)) {
32062306a36Sopenharmony_ci		pr_err("%s: missing 'shift' property\n", __func__);
32162306a36Sopenharmony_ci		return;
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if (of_property_read_u32(node, "bit-mask", &mask)) {
32562306a36Sopenharmony_ci		pr_err("%s: missing 'bit-mask' property\n", __func__);
32662306a36Sopenharmony_ci		return;
32762306a36Sopenharmony_ci	}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
33062306a36Sopenharmony_ci				ARRAY_SIZE(parents) , 0, reg, shift, mask,
33162306a36Sopenharmony_ci				0, NULL);
33262306a36Sopenharmony_ci	if (IS_ERR(clk)) {
33362306a36Sopenharmony_ci		pr_err("%s: error registering mux %s\n", __func__, clk_name);
33462306a36Sopenharmony_ci		return;
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	of_clk_add_provider(node, of_clk_src_simple_get, clk);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ciCLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
34262306a36Sopenharmony_ciMODULE_DESCRIPTION("PLL clock driver for Keystone devices");
34362306a36Sopenharmony_ciMODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
34462306a36Sopenharmony_ciMODULE_AUTHOR("Santosh Shilimkar <santosh.shilimkar@ti.com>");
345