Merge "defconfig: Enable CPU clock drivers for sdxnightjar"

This commit is contained in:
qctecmdr 2021-01-14 22:32:57 -08:00 • committed by Gerrit - the friendly Code Review server
commit f127889e20
3 changed files with 131 additions and 17 deletions

View file

@ -41,6 +41,7 @@ CONFIG_IIO=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_SDX_DEBUGCC_NIGHTJAR=y
CONFIG_COMMON_CLK_QCOM_DEBUG=y
CONFIG_CLOCK_CPU_SDXLEMUR=y
CONFIG_MSM_RPM_SMD=y
# CONFIG_GENERIC_ADC_BATTERY is not set
# CONFIG_BATTERY_LEGO_EV3 is not set

View file

@ -72,6 +72,7 @@ CONFIG_IIO=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_SDX_DEBUGCC_NIGHTJAR=y
CONFIG_COMMON_CLK_QCOM_DEBUG=y
CONFIG_CLOCK_CPU_SDXLEMUR=y
CONFIG_MSM_RPM_SMD=y
# CONFIG_GENERIC_ADC_BATTERY is not set
# CONFIG_BATTERY_LEGO_EV3 is not set

View file

@ -88,26 +88,50 @@ cpucc_calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
return tmp;
}
static int cpucc_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
static int cpucc_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
struct clk_hw *apcs_cpu_pll_hw;
struct clk_hw *xo_hw, *gpll0_hw;
struct clk_rate_request parent_req = { };
struct clk_regmap_mux_div *cpuclk = to_clk_regmap_mux_div(hw);
unsigned long rate = req->rate, rrate;
u32 div;
int ret;
apcs_cpu_pll_hw = clk_hw_get_parent_by_index(hw,
P_APCS_CPU_PLL);
parent_req.rate = req->rate;
parent_req.best_parent_hw = apcs_cpu_pll_hw;
req->best_parent_hw = apcs_cpu_pll_hw;
ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
if (ret)
return ret;
xo_hw = clk_hw_get_parent_by_index(hw, P_BI_TCXO);
if (rate == clk_hw_get_rate(xo_hw)) {
req->best_parent_hw = xo_hw;
req->best_parent_rate = rate;
cpuclk->div = 1;
cpuclk->src = cpuclk->parent_map[P_BI_TCXO].cfg;
return 0;
}
req->best_parent_rate = parent_req.rate;
cpuclk->src = cpuclk->parent_map[P_APCS_CPU_PLL].cfg;
cpuclk->div = 1;
gpll0_hw = clk_hw_get_parent_by_index(hw, P_GPLL0);
div = DIV_ROUND_UP((2 * (clk_hw_get_rate(gpll0_hw))), rate) - 1;
rrate = cpucc_calc_rate(clk_hw_get_rate(gpll0_hw), 0, 0, 0, div);
/* Use the GPLL0 source */
if (rate <= rrate) {
parent_req.best_parent_hw = gpll0_hw;
req->best_parent_hw = gpll0_hw;
req->best_parent_rate = clk_hw_get_rate(gpll0_hw);
req->rate = rrate;
cpuclk->src = cpuclk->parent_map[P_GPLL0].cfg;
} else { /* Use the APCS PLL source */
parent_req.rate = req->rate;
parent_req.best_parent_hw = clk_hw_get_parent_by_index(hw,
P_APCS_CPU_PLL);
req->best_parent_hw = parent_req.best_parent_hw;
ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
if (ret)
return ret;
req->best_parent_rate = parent_req.rate;
cpuclk->src = cpuclk->parent_map[P_APCS_CPU_PLL].cfg;
div = 1;
}
cpuclk->div = div;
return 0;
}
@ -187,6 +211,28 @@ static u8 cpucc_clk_get_parent(struct clk_hw *hw)
return clk_regmap_mux_div_ops.get_parent(hw);
}
/*
* We use the notifier function for switching to a temporary safe configuration
* (mux and divider), while the APSS pll is reconfigured.
*/
static int cpucc_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data)
{
struct clk_regmap_mux_div *cpuclk = container_of(nb,
struct clk_regmap_mux_div, clk_nb);
int ret = 0;
if (event == PRE_RATE_CHANGE)
/* set the mux to safe source(gpll0) & div */
ret = mux_div_set_src_div(cpuclk, cpuclk->safe_src, 1);
if (event == ABORT_RATE_CHANGE)
pr_err("Error in configuring PLL - stay at safe src only\n");
return notifier_from_errno(ret);
}
static const struct clk_ops cpucc_clk_ops = {
.enable = cpucc_clk_enable,
.disable = cpucc_clk_disable,
@ -204,6 +250,11 @@ static struct pll_vco lucid_5lpe_vco[] = {
{ 249600000, 2000000000, 0 },
};
static struct pll_vco alpha_pll_vco[] = {
{ 250000000, 500000000, 3 },
{ 750000000, 1500000000, 1 },
};
/* Initial configuration for 1094.4 */
static const struct alpha_pll_config apcs_cpu_pll_config = {
.l = 0x4E,
@ -220,6 +271,25 @@ static const struct alpha_pll_config apcs_cpu_pll_config = {
.user_ctl_hi1_val = 0x00000000,
};
/* Initial configuration for 1190.4 MHz */
static struct alpha_pll_config apcs_cpu_alpha_pll_config = {
.l = 0x3E,
.config_ctl_val = 0x4001055b,
.test_ctl_hi_val = 0x0,
.vco_val = BIT(20),
.vco_mask = 0x3 << 20,
.main_output_mask = BIT(0),
};
static struct clk_init_data apcs_cpu_pll_sdxnightjar = {
.name = "apcs_cpu_pll",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo_ao",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
};
static struct clk_alpha_pll apcs_cpu_pll = {
.offset = 0x0,
.vco_table = lucid_5lpe_vco,
@ -279,6 +349,7 @@ static struct clk_regmap_mux_div apcs_mux_clk = {
static const struct of_device_id match_table[] = {
{ .compatible = "qcom,sdxlemur-apsscc" },
{ .compatible = "qcom,sdxnightjar-apsscc" },
{}
};
@ -487,6 +558,28 @@ static void cpucc_clk_populate_opp_table(struct platform_device *pdev)
cpucc_clk_print_opp_table(final_cpu);
}
static void cpucc_sdxnightjar_fixup(void)
{
apcs_cpu_pll.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT];
apcs_cpu_pll.vco_table = alpha_pll_vco;
apcs_cpu_pll.num_vco = sizeof(alpha_pll_vco);
apcs_cpu_pll.clkr.hw.init = &apcs_cpu_pll_sdxnightjar;
apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_MIN] = 0;
apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_LOW] = 1000000000;
apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_LOW_L1] = 0;
apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_NOMINAL] = 2000000000;
/* GPLL0 as safe source Index */
apcs_mux_clk.safe_src = 1;
apcs_mux_clk.safe_div = 1;
apcs_mux_clk.clk_nb.notifier_call = cpucc_notifier_cb;
clk_alpha_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap,
&apcs_cpu_alpha_pll_config);
}
static int cpucc_get_and_parse_dt_resource(struct platform_device *pdev,
unsigned long *xo_rate)
{
@ -597,6 +690,7 @@ static int cpucc_driver_probe(struct platform_device *pdev)
struct clk_hw_onecell_data *data;
struct device *dev = &pdev->dev;
int i, ret, cpu;
bool is_sdxnightjar;
unsigned long xo_rate;
u32 l_val;
@ -604,9 +698,17 @@ static int cpucc_driver_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
l_val = apcs_cpu_pll_config.l;
clk_lucid_5lpe_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap,
&apcs_cpu_pll_config);
is_sdxnightjar = of_device_is_compatible(pdev->dev.of_node,
"qcom,sdxnightjar-apsscc");
if (is_sdxnightjar) {
l_val = apcs_cpu_alpha_pll_config.l;
cpucc_sdxnightjar_fixup();
} else {
l_val = apcs_cpu_pll_config.l;
clk_lucid_5lpe_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap,
&apcs_cpu_pll_config);
}
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@ -631,6 +733,16 @@ static int cpucc_driver_probe(struct platform_device *pdev)
return ret;
}
if (is_sdxnightjar) {
ret = clk_notifier_register(apcs_mux_clk.clkr.hw.clk,
&apcs_mux_clk.clk_nb);
if (ret) {
dev_err(&pdev->dev,
"failed to register clock notifier: %d\n", ret);
return ret;
}
}
/* Set to boot frequency */
ret = clk_set_rate(apcs_mux_clk.clkr.hw.clk, l_val * xo_rate);
if (ret) {