162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/* Copyright (C) 2014 Broadcom Corporation */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#ifndef _CLK_IPROC_H
562306a36Sopenharmony_ci#define _CLK_IPROC_H
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/list.h>
962306a36Sopenharmony_ci#include <linux/spinlock.h>
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci#include <linux/device.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/clk-provider.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define IPROC_CLK_NAME_LEN 25
1662306a36Sopenharmony_ci#define IPROC_CLK_INVALID_OFFSET 0xffffffff
1762306a36Sopenharmony_ci#define bit_mask(width) ((1 << (width)) - 1)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* clocks that should not be disabled at runtime */
2062306a36Sopenharmony_ci#define IPROC_CLK_AON BIT(0)
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* PLL that requires gating through ASIU */
2362306a36Sopenharmony_ci#define IPROC_CLK_PLL_ASIU BIT(1)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* PLL that has fractional part of the NDIV */
2662306a36Sopenharmony_ci#define IPROC_CLK_PLL_HAS_NDIV_FRAC BIT(2)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Some of the iProc PLL/clocks may have an ASIC bug that requires read back
3062306a36Sopenharmony_ci * of the same register following the write to flush the write transaction into
3162306a36Sopenharmony_ci * the intended register
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci#define IPROC_CLK_NEEDS_READ_BACK BIT(3)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*
3662306a36Sopenharmony_ci * Some PLLs require the PLL SW override bit to be set before changes can be
3762306a36Sopenharmony_ci * applied to the PLL
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * Some PLLs use a different way to control clock power, via the PWRDWN bit in
4362306a36Sopenharmony_ci * the PLL control register
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_ci#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * Some PLLs have separate registers for Status and Control.  Identify this to
4962306a36Sopenharmony_ci * let the driver know if additional registers need to be used
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ci#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*
5462306a36Sopenharmony_ci * Some PLLs have an additional divide by 2 in master clock calculation;
5562306a36Sopenharmony_ci * MCLK = VCO_freq / (Mdiv * 2). Identify this to let the driver know
5662306a36Sopenharmony_ci * of modified calculations
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_ci#define IPROC_CLK_MCLK_DIV_BY_2 BIT(7)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * Some PLLs provide a look up table for the leaf clock frequencies and
6262306a36Sopenharmony_ci * auto calculates VCO frequency parameters based on the provided leaf
6362306a36Sopenharmony_ci * clock frequencies. They have a user mode that allows the divider
6462306a36Sopenharmony_ci * controls to be determined by the user
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_ci#define IPROC_CLK_PLL_USER_MODE_ON BIT(8)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * Some PLLs have an active low reset
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_ci#define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*
7462306a36Sopenharmony_ci * Calculate the PLL parameters are runtime, instead of using table
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_ci#define IPROC_CLK_PLL_CALC_PARAM BIT(10)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/*
7962306a36Sopenharmony_ci * Parameters for VCO frequency configuration
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * VCO frequency =
8262306a36Sopenharmony_ci * ((ndiv_int + ndiv_frac / 2^20) * (ref frequency  / pdiv)
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_cistruct iproc_pll_vco_param {
8562306a36Sopenharmony_ci	unsigned long rate;
8662306a36Sopenharmony_ci	unsigned int ndiv_int;
8762306a36Sopenharmony_ci	unsigned int ndiv_frac;
8862306a36Sopenharmony_ci	unsigned int pdiv;
8962306a36Sopenharmony_ci};
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct iproc_clk_reg_op {
9262306a36Sopenharmony_ci	unsigned int offset;
9362306a36Sopenharmony_ci	unsigned int shift;
9462306a36Sopenharmony_ci	unsigned int width;
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/*
9862306a36Sopenharmony_ci * Clock gating control at the top ASIU level
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_cistruct iproc_asiu_gate {
10162306a36Sopenharmony_ci	unsigned int offset;
10262306a36Sopenharmony_ci	unsigned int en_shift;
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/*
10662306a36Sopenharmony_ci * Control of powering on/off of a PLL
10762306a36Sopenharmony_ci *
10862306a36Sopenharmony_ci * Before powering off a PLL, input isolation (ISO) needs to be enabled
10962306a36Sopenharmony_ci */
11062306a36Sopenharmony_cistruct iproc_pll_aon_pwr_ctrl {
11162306a36Sopenharmony_ci	unsigned int offset;
11262306a36Sopenharmony_ci	unsigned int pwr_width;
11362306a36Sopenharmony_ci	unsigned int pwr_shift;
11462306a36Sopenharmony_ci	unsigned int iso_shift;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/*
11862306a36Sopenharmony_ci * Control of the PLL reset
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistruct iproc_pll_reset_ctrl {
12162306a36Sopenharmony_ci	unsigned int offset;
12262306a36Sopenharmony_ci	unsigned int reset_shift;
12362306a36Sopenharmony_ci	unsigned int p_reset_shift;
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * Control of the Ki, Kp, and Ka parameters
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_cistruct iproc_pll_dig_filter_ctrl {
13062306a36Sopenharmony_ci	unsigned int offset;
13162306a36Sopenharmony_ci	unsigned int ki_shift;
13262306a36Sopenharmony_ci	unsigned int ki_width;
13362306a36Sopenharmony_ci	unsigned int kp_shift;
13462306a36Sopenharmony_ci	unsigned int kp_width;
13562306a36Sopenharmony_ci	unsigned int ka_shift;
13662306a36Sopenharmony_ci	unsigned int ka_width;
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/*
14062306a36Sopenharmony_ci * To enable SW control of the PLL
14162306a36Sopenharmony_ci */
14262306a36Sopenharmony_cistruct iproc_pll_sw_ctrl {
14362306a36Sopenharmony_ci	unsigned int offset;
14462306a36Sopenharmony_ci	unsigned int shift;
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistruct iproc_pll_vco_ctrl {
14862306a36Sopenharmony_ci	unsigned int u_offset;
14962306a36Sopenharmony_ci	unsigned int l_offset;
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/*
15362306a36Sopenharmony_ci * Main PLL control parameters
15462306a36Sopenharmony_ci */
15562306a36Sopenharmony_cistruct iproc_pll_ctrl {
15662306a36Sopenharmony_ci	unsigned long flags;
15762306a36Sopenharmony_ci	struct iproc_pll_aon_pwr_ctrl aon;
15862306a36Sopenharmony_ci	struct iproc_asiu_gate asiu;
15962306a36Sopenharmony_ci	struct iproc_pll_reset_ctrl reset;
16062306a36Sopenharmony_ci	struct iproc_pll_dig_filter_ctrl dig_filter;
16162306a36Sopenharmony_ci	struct iproc_pll_sw_ctrl sw_ctrl;
16262306a36Sopenharmony_ci	struct iproc_clk_reg_op ndiv_int;
16362306a36Sopenharmony_ci	struct iproc_clk_reg_op ndiv_frac;
16462306a36Sopenharmony_ci	struct iproc_clk_reg_op pdiv;
16562306a36Sopenharmony_ci	struct iproc_pll_vco_ctrl vco_ctrl;
16662306a36Sopenharmony_ci	struct iproc_clk_reg_op status;
16762306a36Sopenharmony_ci	struct iproc_clk_reg_op macro_mode;
16862306a36Sopenharmony_ci};
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/*
17162306a36Sopenharmony_ci * Controls enabling/disabling a PLL derived clock
17262306a36Sopenharmony_ci */
17362306a36Sopenharmony_cistruct iproc_clk_enable_ctrl {
17462306a36Sopenharmony_ci	unsigned int offset;
17562306a36Sopenharmony_ci	unsigned int enable_shift;
17662306a36Sopenharmony_ci	unsigned int hold_shift;
17762306a36Sopenharmony_ci	unsigned int bypass_shift;
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/*
18162306a36Sopenharmony_ci * Main clock control parameters for clocks derived from the PLLs
18262306a36Sopenharmony_ci */
18362306a36Sopenharmony_cistruct iproc_clk_ctrl {
18462306a36Sopenharmony_ci	unsigned int channel;
18562306a36Sopenharmony_ci	unsigned long flags;
18662306a36Sopenharmony_ci	struct iproc_clk_enable_ctrl enable;
18762306a36Sopenharmony_ci	struct iproc_clk_reg_op mdiv;
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/*
19162306a36Sopenharmony_ci * Divisor of the ASIU clocks
19262306a36Sopenharmony_ci */
19362306a36Sopenharmony_cistruct iproc_asiu_div {
19462306a36Sopenharmony_ci	unsigned int offset;
19562306a36Sopenharmony_ci	unsigned int en_shift;
19662306a36Sopenharmony_ci	unsigned int high_shift;
19762306a36Sopenharmony_ci	unsigned int high_width;
19862306a36Sopenharmony_ci	unsigned int low_shift;
19962306a36Sopenharmony_ci	unsigned int low_width;
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_civoid iproc_armpll_setup(struct device_node *node);
20362306a36Sopenharmony_civoid iproc_pll_clk_setup(struct device_node *node,
20462306a36Sopenharmony_ci			 const struct iproc_pll_ctrl *pll_ctrl,
20562306a36Sopenharmony_ci			 const struct iproc_pll_vco_param *vco,
20662306a36Sopenharmony_ci			 unsigned int num_vco_entries,
20762306a36Sopenharmony_ci			 const struct iproc_clk_ctrl *clk_ctrl,
20862306a36Sopenharmony_ci			 unsigned int num_clks);
20962306a36Sopenharmony_civoid iproc_asiu_setup(struct device_node *node,
21062306a36Sopenharmony_ci		      const struct iproc_asiu_div *div,
21162306a36Sopenharmony_ci		      const struct iproc_asiu_gate *gate,
21262306a36Sopenharmony_ci		      unsigned int num_clks);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci#endif /* _CLK_IPROC_H */
215