162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright 2011-2012 Calxeda, Inc.
462306a36Sopenharmony_ci *  Copyright (C) 2012-2013 Altera Corporation <www.altera.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Based from clk-highbank.c
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/slab.h>
962306a36Sopenharmony_ci#include <linux/clk-provider.h>
1062306a36Sopenharmony_ci#include <linux/io.h>
1162306a36Sopenharmony_ci#include <linux/of.h>
1262306a36Sopenharmony_ci#include <linux/of_address.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "clk.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* Clock bypass bits */
1762306a36Sopenharmony_ci#define MAINPLL_BYPASS		(1<<0)
1862306a36Sopenharmony_ci#define SDRAMPLL_BYPASS		(1<<1)
1962306a36Sopenharmony_ci#define SDRAMPLL_SRC_BYPASS	(1<<2)
2062306a36Sopenharmony_ci#define PERPLL_BYPASS		(1<<3)
2162306a36Sopenharmony_ci#define PERPLL_SRC_BYPASS	(1<<4)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define SOCFPGA_PLL_BG_PWRDWN		0
2462306a36Sopenharmony_ci#define SOCFPGA_PLL_EXT_ENA		1
2562306a36Sopenharmony_ci#define SOCFPGA_PLL_PWR_DOWN		2
2662306a36Sopenharmony_ci#define SOCFPGA_PLL_DIVF_MASK		0x0000FFF8
2762306a36Sopenharmony_ci#define SOCFPGA_PLL_DIVF_SHIFT		3
2862306a36Sopenharmony_ci#define SOCFPGA_PLL_DIVQ_MASK		0x003F0000
2962306a36Sopenharmony_ci#define SOCFPGA_PLL_DIVQ_SHIFT		16
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define CLK_MGR_PLL_CLK_SRC_SHIFT	22
3262306a36Sopenharmony_ci#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_civoid __iomem *clk_mgr_base_addr;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
3962306a36Sopenharmony_ci					 unsigned long parent_rate)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
4262306a36Sopenharmony_ci	unsigned long divf, divq, reg;
4362306a36Sopenharmony_ci	unsigned long long vco_freq;
4462306a36Sopenharmony_ci	unsigned long bypass;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	reg = readl(socfpgaclk->hw.reg);
4762306a36Sopenharmony_ci	bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
4862306a36Sopenharmony_ci	if (bypass & MAINPLL_BYPASS)
4962306a36Sopenharmony_ci		return parent_rate;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
5262306a36Sopenharmony_ci	divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
5362306a36Sopenharmony_ci	vco_freq = (unsigned long long)parent_rate * (divf + 1);
5462306a36Sopenharmony_ci	do_div(vco_freq, (1 + divq));
5562306a36Sopenharmony_ci	return (unsigned long)vco_freq;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic u8 clk_pll_get_parent(struct clk_hw *hwclk)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	u32 pll_src;
6162306a36Sopenharmony_ci	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	pll_src = readl(socfpgaclk->hw.reg);
6462306a36Sopenharmony_ci	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
6562306a36Sopenharmony_ci			CLK_MGR_PLL_CLK_SRC_MASK;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic const struct clk_ops clk_pll_ops = {
6962306a36Sopenharmony_ci	.recalc_rate = clk_pll_recalc_rate,
7062306a36Sopenharmony_ci	.get_parent = clk_pll_get_parent,
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic void __init __socfpga_pll_init(struct device_node *node,
7462306a36Sopenharmony_ci				      const struct clk_ops *ops)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	u32 reg;
7762306a36Sopenharmony_ci	struct clk_hw *hw_clk;
7862306a36Sopenharmony_ci	struct socfpga_pll *pll_clk;
7962306a36Sopenharmony_ci	const char *clk_name = node->name;
8062306a36Sopenharmony_ci	const char *parent_name[SOCFPGA_MAX_PARENTS];
8162306a36Sopenharmony_ci	struct clk_init_data init;
8262306a36Sopenharmony_ci	struct device_node *clkmgr_np;
8362306a36Sopenharmony_ci	int rc;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	of_property_read_u32(node, "reg", &reg);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
8862306a36Sopenharmony_ci	if (WARN_ON(!pll_clk))
8962306a36Sopenharmony_ci		return;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
9262306a36Sopenharmony_ci	clk_mgr_base_addr = of_iomap(clkmgr_np, 0);
9362306a36Sopenharmony_ci	of_node_put(clkmgr_np);
9462306a36Sopenharmony_ci	BUG_ON(!clk_mgr_base_addr);
9562306a36Sopenharmony_ci	pll_clk->hw.reg = clk_mgr_base_addr + reg;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	of_property_read_string(node, "clock-output-names", &clk_name);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	init.name = clk_name;
10062306a36Sopenharmony_ci	init.ops = ops;
10162306a36Sopenharmony_ci	init.flags = 0;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
10462306a36Sopenharmony_ci	init.parent_names = parent_name;
10562306a36Sopenharmony_ci	pll_clk->hw.hw.init = &init;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	hw_clk = &pll_clk->hw.hw;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	rc = clk_hw_register(NULL, hw_clk);
11262306a36Sopenharmony_ci	if (rc) {
11362306a36Sopenharmony_ci		pr_err("Could not register clock:%s\n", clk_name);
11462306a36Sopenharmony_ci		goto err_clk_hw_register;
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	rc = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw_clk);
11862306a36Sopenharmony_ci	if (rc) {
11962306a36Sopenharmony_ci		pr_err("Could not register clock provider for node:%s\n",
12062306a36Sopenharmony_ci		       clk_name);
12162306a36Sopenharmony_ci		goto err_of_clk_add_hw_provider;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cierr_of_clk_add_hw_provider:
12762306a36Sopenharmony_ci	clk_hw_unregister(hw_clk);
12862306a36Sopenharmony_cierr_clk_hw_register:
12962306a36Sopenharmony_ci	kfree(pll_clk);
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_civoid __init socfpga_pll_init(struct device_node *node)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	__socfpga_pll_init(node, &clk_pll_ops);
13562306a36Sopenharmony_ci}
136