linux/drivers/clk/qcom/clk-alpha-pll.h

157 lines
3.9 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. */
#ifndef __QCOM_CLK_ALPHA_PLL_H__
#define __QCOM_CLK_ALPHA_PLL_H__
#include <linux/clk-provider.h>
#include "clk-regmap.h"
/* Alpha PLL types */
enum {
CLK_ALPHA_PLL_TYPE_DEFAULT,
CLK_ALPHA_PLL_TYPE_HUAYRA,
CLK_ALPHA_PLL_TYPE_BRAMMO,
CLK_ALPHA_PLL_TYPE_FABIA,
CLK_ALPHA_PLL_TYPE_TRION,
CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
CLK_ALPHA_PLL_TYPE_MAX,
};
enum {
PLL_OFF_L_VAL,
PLL_OFF_CAL_L_VAL,
PLL_OFF_ALPHA_VAL,
PLL_OFF_ALPHA_VAL_U,
PLL_OFF_USER_CTL,
PLL_OFF_USER_CTL_U,
PLL_OFF_USER_CTL_U1,
PLL_OFF_CONFIG_CTL,
PLL_OFF_CONFIG_CTL_U,
PLL_OFF_CONFIG_CTL_U1,
PLL_OFF_TEST_CTL,
PLL_OFF_TEST_CTL_U,
PLL_OFF_TEST_CTL_U1,
PLL_OFF_STATUS,
PLL_OFF_OPMODE,
PLL_OFF_FRAC,
PLL_OFF_CAL_VAL,
PLL_OFF_MAX_REGS
};
extern const u8 clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_MAX][PLL_OFF_MAX_REGS];
struct pll_vco {
unsigned long min_freq;
unsigned long max_freq;
u32 val;
};
clk: qcom: Add CPU clock driver for msm8996 Each of the CPU clusters (Power and Perf) on msm8996 are clocked via 2 PLLs, a primary and alternate. There are also 2 Mux'es, a primary and secondary all connected together as shown below +-------+ XO | | +------------------>0 | | | PLL/2 | SMUX +----+ +------->1 | | | | | | | +-------+ | +-------+ | +---->0 | | | | +---------------+ | +----------->1 | CPU clk |Primary PLL +----+ PLL_EARLY | | +------> | +------+-----------+ +------>2 PMUX | +---------------+ | | | | | +------+ | +-->3 | +--^+ ACD +-----+ | +-------+ +---------------+ +------+ | |Alt PLL | | | +---------------------------+ +---------------+ PLL_EARLY The primary PLL is what drives the CPU clk, except for times when we are reprogramming the PLL itself (for rate changes) when we temporarily switch to an alternate PLL. A subsequent patch adds support to switch between primary and alternate PLL during rate changes. The primary PLL operates on a single VCO range, between 600MHz and 3GHz. However the CPUs do support OPPs with frequencies between 300MHz and 600MHz. In order to support running the CPUs at those frequencies we end up having to lock the PLL at twice the rate and drive the CPU clk via the PLL/2 output and SMUX. So for frequencies above 600MHz we follow the following path Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk and for frequencies between 300MHz and 600MHz we follow Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk ACD stands for Adaptive Clock Distribution and is used to detect voltage droops. Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org> Rajendra Nayak: Initial RFC - https://lkml.org/lkml/2016/9/29/84 Signed-off-by: Ilia Lin <ilialin@codeaurora.org> Ilia Lin: - reworked clock registering - Added clock-tree diagram - non-builtin support - clock notifier on rate change - https://lkml.org/lkml/2018/5/24/123 Signed-off-by: Loic Poulain <loic.poulain@linaro.org> Loic Poulain: - fixed driver remove / clk deregistering - Removed useless memory barriers - devm usage when possible - Fixed Kconfig depends Link: https://lore.kernel.org/r/1593766185-16346-3-git-send-email-loic.poulain@linaro.org Signed-off-by: Stephen Boyd <sboyd@kernel.org>
2020-07-03 08:49:42 +00:00
#define VCO(a, b, c) { \
.val = a,\
.min_freq = b,\
.max_freq = c,\
}
/**
* struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers
* @vco_table: array of VCO settings
* @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @clkr: regmap clock handle
*/
struct clk_alpha_pll {
u32 offset;
const u8 *regs;
const struct pll_vco *vco_table;
size_t num_vco;
#define SUPPORTS_OFFLINE_REQ BIT(0)
#define SUPPORTS_FSM_MODE BIT(2)
#define SUPPORTS_DYNAMIC_UPDATE BIT(3)
u8 flags;
struct clk_regmap clkr;
};
/**
* struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
* @offset: base address of registers
* @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @width: width of post-divider
* @post_div_shift: shift to differentiate between odd & even post-divider
* @post_div_table: table with PLL odd and even post-divider settings
* @num_post_div: Number of PLL post-divider settings
*
* @clkr: regmap clock handle
*/
struct clk_alpha_pll_postdiv {
u32 offset;
u8 width;
const u8 *regs;
struct clk_regmap clkr;
int post_div_shift;
const struct clk_div_table *post_div_table;
size_t num_post_div;
};
struct alpha_pll_config {
u32 l;
u32 alpha;
u32 alpha_hi;
u32 config_ctl_val;
u32 config_ctl_hi_val;
u32 config_ctl_hi1_val;
u32 user_ctl_val;
u32 user_ctl_hi_val;
u32 user_ctl_hi1_val;
u32 test_ctl_val;
u32 test_ctl_hi_val;
u32 test_ctl_hi1_val;
u32 main_output_mask;
u32 aux_output_mask;
u32 aux2_output_mask;
u32 early_output_mask;
u32 alpha_en_mask;
u32 alpha_mode_mask;
u32 pre_div_val;
u32 pre_div_mask;
u32 post_div_val;
u32 post_div_mask;
u32 vco_val;
u32 vco_mask;
};
extern const struct clk_ops clk_alpha_pll_ops;
extern const struct clk_ops clk_alpha_pll_fixed_ops;
extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ops;
extern const struct clk_ops clk_alpha_pll_huayra_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ro_ops;
extern const struct clk_ops clk_alpha_pll_fabia_ops;
extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_fabia_ops;
extern const struct clk_ops clk_alpha_pll_trion_ops;
extern const struct clk_ops clk_alpha_pll_fixed_trion_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops;
extern const struct clk_ops clk_alpha_pll_lucid_ops;
#define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
#define clk_lucid_pll_configure(pll, regmap, config) \
clk_trion_pll_configure(pll, regmap, config)
#endif