18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2014 Broadcom Corporation
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or
58c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License as
68c2ecf20Sopenharmony_ci * published by the Free Software Foundation version 2.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This program is distributed "as is" WITHOUT ANY WARRANTY of any
98c2ecf20Sopenharmony_ci * kind, whether express or implied; without even the implied warranty
108c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
118c2ecf20Sopenharmony_ci * GNU General Public License for more details.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#ifndef _CLK_IPROC_H
158c2ecf20Sopenharmony_ci#define _CLK_IPROC_H
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/kernel.h>
188c2ecf20Sopenharmony_ci#include <linux/list.h>
198c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci#include <linux/device.h>
228c2ecf20Sopenharmony_ci#include <linux/of.h>
238c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define IPROC_CLK_NAME_LEN 25
268c2ecf20Sopenharmony_ci#define IPROC_CLK_INVALID_OFFSET 0xffffffff
278c2ecf20Sopenharmony_ci#define bit_mask(width) ((1 << (width)) - 1)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/* clocks that should not be disabled at runtime */
308c2ecf20Sopenharmony_ci#define IPROC_CLK_AON BIT(0)
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* PLL that requires gating through ASIU */
338c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_ASIU BIT(1)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* PLL that has fractional part of the NDIV */
368c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_HAS_NDIV_FRAC BIT(2)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Some of the iProc PLL/clocks may have an ASIC bug that requires read back
408c2ecf20Sopenharmony_ci * of the same register following the write to flush the write transaction into
418c2ecf20Sopenharmony_ci * the intended register
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ci#define IPROC_CLK_NEEDS_READ_BACK BIT(3)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * Some PLLs require the PLL SW override bit to be set before changes can be
478c2ecf20Sopenharmony_ci * applied to the PLL
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/*
528c2ecf20Sopenharmony_ci * Some PLLs use a different way to control clock power, via the PWRDWN bit in
538c2ecf20Sopenharmony_ci * the PLL control register
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_ci#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * Some PLLs have separate registers for Status and Control.  Identify this to
598c2ecf20Sopenharmony_ci * let the driver know if additional registers need to be used
608c2ecf20Sopenharmony_ci */
618c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/*
648c2ecf20Sopenharmony_ci * Some PLLs have an additional divide by 2 in master clock calculation;
658c2ecf20Sopenharmony_ci * MCLK = VCO_freq / (Mdiv * 2). Identify this to let the driver know
668c2ecf20Sopenharmony_ci * of modified calculations
678c2ecf20Sopenharmony_ci */
688c2ecf20Sopenharmony_ci#define IPROC_CLK_MCLK_DIV_BY_2 BIT(7)
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/*
718c2ecf20Sopenharmony_ci * Some PLLs provide a look up table for the leaf clock frequencies and
728c2ecf20Sopenharmony_ci * auto calculates VCO frequency parameters based on the provided leaf
738c2ecf20Sopenharmony_ci * clock frequencies. They have a user mode that allows the divider
748c2ecf20Sopenharmony_ci * controls to be determined by the user
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_USER_MODE_ON BIT(8)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/*
798c2ecf20Sopenharmony_ci * Some PLLs have an active low reset
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/*
848c2ecf20Sopenharmony_ci * Calculate the PLL parameters are runtime, instead of using table
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_ci#define IPROC_CLK_PLL_CALC_PARAM BIT(10)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/*
898c2ecf20Sopenharmony_ci * Parameters for VCO frequency configuration
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * VCO frequency =
928c2ecf20Sopenharmony_ci * ((ndiv_int + ndiv_frac / 2^20) * (ref freqeuncy  / pdiv)
938c2ecf20Sopenharmony_ci */
948c2ecf20Sopenharmony_cistruct iproc_pll_vco_param {
958c2ecf20Sopenharmony_ci	unsigned long rate;
968c2ecf20Sopenharmony_ci	unsigned int ndiv_int;
978c2ecf20Sopenharmony_ci	unsigned int ndiv_frac;
988c2ecf20Sopenharmony_ci	unsigned int pdiv;
998c2ecf20Sopenharmony_ci};
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistruct iproc_clk_reg_op {
1028c2ecf20Sopenharmony_ci	unsigned int offset;
1038c2ecf20Sopenharmony_ci	unsigned int shift;
1048c2ecf20Sopenharmony_ci	unsigned int width;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/*
1088c2ecf20Sopenharmony_ci * Clock gating control at the top ASIU level
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_cistruct iproc_asiu_gate {
1118c2ecf20Sopenharmony_ci	unsigned int offset;
1128c2ecf20Sopenharmony_ci	unsigned int en_shift;
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/*
1168c2ecf20Sopenharmony_ci * Control of powering on/off of a PLL
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci * Before powering off a PLL, input isolation (ISO) needs to be enabled
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_cistruct iproc_pll_aon_pwr_ctrl {
1218c2ecf20Sopenharmony_ci	unsigned int offset;
1228c2ecf20Sopenharmony_ci	unsigned int pwr_width;
1238c2ecf20Sopenharmony_ci	unsigned int pwr_shift;
1248c2ecf20Sopenharmony_ci	unsigned int iso_shift;
1258c2ecf20Sopenharmony_ci};
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci/*
1288c2ecf20Sopenharmony_ci * Control of the PLL reset
1298c2ecf20Sopenharmony_ci */
1308c2ecf20Sopenharmony_cistruct iproc_pll_reset_ctrl {
1318c2ecf20Sopenharmony_ci	unsigned int offset;
1328c2ecf20Sopenharmony_ci	unsigned int reset_shift;
1338c2ecf20Sopenharmony_ci	unsigned int p_reset_shift;
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/*
1378c2ecf20Sopenharmony_ci * Control of the Ki, Kp, and Ka parameters
1388c2ecf20Sopenharmony_ci */
1398c2ecf20Sopenharmony_cistruct iproc_pll_dig_filter_ctrl {
1408c2ecf20Sopenharmony_ci	unsigned int offset;
1418c2ecf20Sopenharmony_ci	unsigned int ki_shift;
1428c2ecf20Sopenharmony_ci	unsigned int ki_width;
1438c2ecf20Sopenharmony_ci	unsigned int kp_shift;
1448c2ecf20Sopenharmony_ci	unsigned int kp_width;
1458c2ecf20Sopenharmony_ci	unsigned int ka_shift;
1468c2ecf20Sopenharmony_ci	unsigned int ka_width;
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/*
1508c2ecf20Sopenharmony_ci * To enable SW control of the PLL
1518c2ecf20Sopenharmony_ci */
1528c2ecf20Sopenharmony_cistruct iproc_pll_sw_ctrl {
1538c2ecf20Sopenharmony_ci	unsigned int offset;
1548c2ecf20Sopenharmony_ci	unsigned int shift;
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistruct iproc_pll_vco_ctrl {
1588c2ecf20Sopenharmony_ci	unsigned int u_offset;
1598c2ecf20Sopenharmony_ci	unsigned int l_offset;
1608c2ecf20Sopenharmony_ci};
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * Main PLL control parameters
1648c2ecf20Sopenharmony_ci */
1658c2ecf20Sopenharmony_cistruct iproc_pll_ctrl {
1668c2ecf20Sopenharmony_ci	unsigned long flags;
1678c2ecf20Sopenharmony_ci	struct iproc_pll_aon_pwr_ctrl aon;
1688c2ecf20Sopenharmony_ci	struct iproc_asiu_gate asiu;
1698c2ecf20Sopenharmony_ci	struct iproc_pll_reset_ctrl reset;
1708c2ecf20Sopenharmony_ci	struct iproc_pll_dig_filter_ctrl dig_filter;
1718c2ecf20Sopenharmony_ci	struct iproc_pll_sw_ctrl sw_ctrl;
1728c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op ndiv_int;
1738c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op ndiv_frac;
1748c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op pdiv;
1758c2ecf20Sopenharmony_ci	struct iproc_pll_vco_ctrl vco_ctrl;
1768c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op status;
1778c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op macro_mode;
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/*
1818c2ecf20Sopenharmony_ci * Controls enabling/disabling a PLL derived clock
1828c2ecf20Sopenharmony_ci */
1838c2ecf20Sopenharmony_cistruct iproc_clk_enable_ctrl {
1848c2ecf20Sopenharmony_ci	unsigned int offset;
1858c2ecf20Sopenharmony_ci	unsigned int enable_shift;
1868c2ecf20Sopenharmony_ci	unsigned int hold_shift;
1878c2ecf20Sopenharmony_ci	unsigned int bypass_shift;
1888c2ecf20Sopenharmony_ci};
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/*
1918c2ecf20Sopenharmony_ci * Main clock control parameters for clocks derived from the PLLs
1928c2ecf20Sopenharmony_ci */
1938c2ecf20Sopenharmony_cistruct iproc_clk_ctrl {
1948c2ecf20Sopenharmony_ci	unsigned int channel;
1958c2ecf20Sopenharmony_ci	unsigned long flags;
1968c2ecf20Sopenharmony_ci	struct iproc_clk_enable_ctrl enable;
1978c2ecf20Sopenharmony_ci	struct iproc_clk_reg_op mdiv;
1988c2ecf20Sopenharmony_ci};
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci/*
2018c2ecf20Sopenharmony_ci * Divisor of the ASIU clocks
2028c2ecf20Sopenharmony_ci */
2038c2ecf20Sopenharmony_cistruct iproc_asiu_div {
2048c2ecf20Sopenharmony_ci	unsigned int offset;
2058c2ecf20Sopenharmony_ci	unsigned int en_shift;
2068c2ecf20Sopenharmony_ci	unsigned int high_shift;
2078c2ecf20Sopenharmony_ci	unsigned int high_width;
2088c2ecf20Sopenharmony_ci	unsigned int low_shift;
2098c2ecf20Sopenharmony_ci	unsigned int low_width;
2108c2ecf20Sopenharmony_ci};
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_civoid iproc_armpll_setup(struct device_node *node);
2138c2ecf20Sopenharmony_civoid iproc_pll_clk_setup(struct device_node *node,
2148c2ecf20Sopenharmony_ci			 const struct iproc_pll_ctrl *pll_ctrl,
2158c2ecf20Sopenharmony_ci			 const struct iproc_pll_vco_param *vco,
2168c2ecf20Sopenharmony_ci			 unsigned int num_vco_entries,
2178c2ecf20Sopenharmony_ci			 const struct iproc_clk_ctrl *clk_ctrl,
2188c2ecf20Sopenharmony_ci			 unsigned int num_clks);
2198c2ecf20Sopenharmony_civoid iproc_asiu_setup(struct device_node *node,
2208c2ecf20Sopenharmony_ci		      const struct iproc_asiu_div *div,
2218c2ecf20Sopenharmony_ci		      const struct iproc_asiu_gate *gate,
2228c2ecf20Sopenharmony_ci		      unsigned int num_clks);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci#endif /* _CLK_IPROC_H */
225