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