You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
561 lines
15 KiB
561 lines
15 KiB
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "%s: " fmt, __func__
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/err.h>
|
|
#include <linux/delay.h>
|
|
#include <dt-bindings/clock/mdss-28nm-pll-clk.h>
|
|
|
|
#include "mdss-pll.h"
|
|
#include "mdss-dsi-pll.h"
|
|
#include "mdss-dsi-pll-28nm.h"
|
|
|
|
#define VCO_DELAY_USEC 1000
|
|
|
|
enum {
|
|
DSI_PLL_0,
|
|
DSI_PLL_1,
|
|
DSI_PLL_MAX
|
|
};
|
|
|
|
static struct lpfr_cfg lpfr_lut_struct[] = {
|
|
{479500000, 8},
|
|
{480000000, 11},
|
|
{575500000, 8},
|
|
{576000000, 12},
|
|
{610500000, 8},
|
|
{659500000, 9},
|
|
{671500000, 10},
|
|
{672000000, 14},
|
|
{708500000, 10},
|
|
{750000000, 11},
|
|
};
|
|
|
|
static void dsi_pll_sw_reset(struct mdss_pll_resources *rsc)
|
|
{
|
|
/*
|
|
* DSI PLL software reset. Add HW recommended delays after toggling
|
|
* the software reset bit off and back on.
|
|
*/
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
|
|
ndelay(500);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
|
|
}
|
|
|
|
static void dsi_pll_toggle_lock_detect(
|
|
struct mdss_pll_resources *rsc)
|
|
{
|
|
/* DSI PLL toggle lock detect setting */
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04);
|
|
ndelay(500);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
|
|
udelay(512);
|
|
}
|
|
|
|
static int dsi_pll_check_lock_status(
|
|
struct mdss_pll_resources *rsc)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = dsi_pll_lock_status(rsc);
|
|
if (rc)
|
|
pr_debug("PLL Locked\n");
|
|
else
|
|
pr_err("PLL failed to lock\n");
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
static int dsi_pll_enable_seq_gf2(struct mdss_pll_resources *rsc)
|
|
{
|
|
int pll_locked = 0;
|
|
|
|
dsi_pll_sw_reset(rsc);
|
|
|
|
/*
|
|
* GF PART 2 PLL power up sequence.
|
|
* Add necessary delays recommended by hardware.
|
|
*/
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x04);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
|
|
udelay(3);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
|
|
udelay(500);
|
|
|
|
dsi_pll_toggle_lock_detect(rsc);
|
|
|
|
pll_locked = dsi_pll_check_lock_status(rsc);
|
|
return pll_locked ? 0 : -EINVAL;
|
|
}
|
|
|
|
static int dsi_pll_enable_seq_gf1(struct mdss_pll_resources *rsc)
|
|
{
|
|
int pll_locked = 0;
|
|
|
|
dsi_pll_sw_reset(rsc);
|
|
/*
|
|
* GF PART 1 PLL power up sequence.
|
|
* Add necessary delays recommended by hardware.
|
|
*/
|
|
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x14);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
|
|
udelay(3);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
|
|
udelay(500);
|
|
|
|
dsi_pll_toggle_lock_detect(rsc);
|
|
|
|
pll_locked = dsi_pll_check_lock_status(rsc);
|
|
return pll_locked ? 0 : -EINVAL;
|
|
}
|
|
|
|
static int dsi_pll_enable_seq_tsmc(struct mdss_pll_resources *rsc)
|
|
{
|
|
int pll_locked = 0;
|
|
|
|
dsi_pll_sw_reset(rsc);
|
|
/*
|
|
* TSMC PLL power up sequence.
|
|
* Add necessary delays recommended by hardware.
|
|
*/
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
|
|
MDSS_PLL_REG_W(rsc->pll_base,
|
|
DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
|
|
udelay(500);
|
|
|
|
dsi_pll_toggle_lock_detect(rsc);
|
|
|
|
pll_locked = dsi_pll_check_lock_status(rsc);
|
|
return pll_locked ? 0 : -EINVAL;
|
|
}
|
|
|
|
static struct regmap_config dsi_pll_28lpm_config = {
|
|
.reg_bits = 32,
|
|
.reg_stride = 4,
|
|
.val_bits = 32,
|
|
.max_register = 0xF4,
|
|
};
|
|
|
|
static struct regmap_bus analog_postdiv_regmap_bus = {
|
|
.reg_write = analog_postdiv_reg_write,
|
|
.reg_read = analog_postdiv_reg_read,
|
|
};
|
|
|
|
static struct regmap_bus byteclk_src_mux_regmap_bus = {
|
|
.reg_write = byteclk_mux_write_sel,
|
|
.reg_read = byteclk_mux_read_sel,
|
|
};
|
|
|
|
static struct regmap_bus pclk_src_regmap_bus = {
|
|
.reg_write = pixel_clk_set_div,
|
|
.reg_read = pixel_clk_get_div,
|
|
};
|
|
|
|
static const struct clk_ops clk_ops_vco_28lpm = {
|
|
.recalc_rate = vco_28nm_recalc_rate,
|
|
.set_rate = vco_28nm_set_rate,
|
|
.round_rate = vco_28nm_round_rate,
|
|
.prepare = vco_28nm_prepare,
|
|
.unprepare = vco_28nm_unprepare,
|
|
};
|
|
|
|
static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
|
|
.ref_clk_rate = 19200000UL,
|
|
.min_rate = 350000000UL,
|
|
.max_rate = 750000000UL,
|
|
.pll_en_seq_cnt = 9,
|
|
.pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[3] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[4] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[5] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[6] = dsi_pll_enable_seq_gf2,
|
|
.pll_enable_seqs[7] = dsi_pll_enable_seq_gf2,
|
|
.pll_enable_seqs[8] = dsi_pll_enable_seq_gf2,
|
|
.lpfr_lut_size = 10,
|
|
.lpfr_lut = lpfr_lut_struct,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_vco_clk",
|
|
.parent_names = (const char *[]){"cxo"},
|
|
.num_parents = 1,
|
|
.ops = &clk_ops_vco_28lpm,
|
|
.flags = CLK_GET_RATE_NOCACHE,
|
|
},
|
|
};
|
|
|
|
static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
|
|
.ref_clk_rate = 19200000UL,
|
|
.min_rate = 350000000UL,
|
|
.max_rate = 750000000UL,
|
|
.pll_en_seq_cnt = 9,
|
|
.pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc,
|
|
.pll_enable_seqs[3] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[4] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[5] = dsi_pll_enable_seq_gf1,
|
|
.pll_enable_seqs[6] = dsi_pll_enable_seq_gf2,
|
|
.pll_enable_seqs[7] = dsi_pll_enable_seq_gf2,
|
|
.pll_enable_seqs[8] = dsi_pll_enable_seq_gf2,
|
|
.lpfr_lut_size = 10,
|
|
.lpfr_lut = lpfr_lut_struct,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_vco_clk",
|
|
.parent_names = (const char *[]){"cxo"},
|
|
.num_parents = 1,
|
|
.ops = &clk_ops_vco_28lpm,
|
|
.flags = CLK_GET_RATE_NOCACHE,
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_div dsi0pll_analog_postdiv = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG,
|
|
.shift = 0,
|
|
.width = 4,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_analog_postdiv",
|
|
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_regmap_div_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_div dsi1pll_analog_postdiv = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG,
|
|
.shift = 0,
|
|
.width = 4,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_analog_postdiv",
|
|
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_regmap_div_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_fixed_factor dsi0pll_indirect_path_src = {
|
|
.div = 2,
|
|
.mult = 1,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_indirect_path_src",
|
|
.parent_names = (const char *[]){"dsi0pll_analog_postdiv"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_fixed_factor_ops,
|
|
},
|
|
};
|
|
|
|
static struct clk_fixed_factor dsi1pll_indirect_path_src = {
|
|
.div = 2,
|
|
.mult = 1,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_indirect_path_src",
|
|
.parent_names = (const char *[]){"dsi1pll_analog_postdiv"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_fixed_factor_ops,
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_mux dsi0pll_byteclk_src_mux = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG,
|
|
.shift = 1,
|
|
.width = 1,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_byteclk_src_mux",
|
|
.parent_names = (const char *[]){
|
|
"dsi0pll_vco_clk",
|
|
"dsi0pll_indirect_path_src"},
|
|
.num_parents = 2,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_regmap_mux_closest_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_mux dsi1pll_byteclk_src_mux = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG,
|
|
.shift = 1,
|
|
.width = 1,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_byteclk_src_mux",
|
|
.parent_names = (const char *[]){
|
|
"dsi1pll_vco_clk",
|
|
"dsi1pll_indirect_path_src"},
|
|
.num_parents = 2,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_regmap_mux_closest_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_fixed_factor dsi0pll_byteclk_src = {
|
|
.div = 4,
|
|
.mult = 1,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_byteclk_src",
|
|
.parent_names = (const char *[]){
|
|
"dsi0pll_byteclk_src_mux"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_fixed_factor_ops,
|
|
},
|
|
};
|
|
|
|
static struct clk_fixed_factor dsi1pll_byteclk_src = {
|
|
.div = 4,
|
|
.mult = 1,
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_byteclk_src",
|
|
.parent_names = (const char *[]){
|
|
"dsi1pll_byteclk_src_mux"},
|
|
.num_parents = 1,
|
|
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
|
|
.ops = &clk_fixed_factor_ops,
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_div dsi0pll_pclk_src = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG,
|
|
.shift = 0,
|
|
.width = 8,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi0pll_pclk_src",
|
|
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
|
|
.num_parents = 1,
|
|
.flags = CLK_GET_RATE_NOCACHE,
|
|
.ops = &clk_regmap_div_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_regmap_div dsi1pll_pclk_src = {
|
|
.reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG,
|
|
.shift = 0,
|
|
.width = 8,
|
|
.clkr = {
|
|
.hw.init = &(struct clk_init_data){
|
|
.name = "dsi1pll_pclk_src",
|
|
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
|
|
.num_parents = 1,
|
|
.flags = CLK_GET_RATE_NOCACHE,
|
|
.ops = &clk_regmap_div_ops,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct clk_hw *mdss_dsi_pllcc_28lpm[] = {
|
|
[VCO_CLK_0] = &dsi0pll_vco_clk.hw,
|
|
[ANALOG_POSTDIV_0_CLK] = &dsi0pll_analog_postdiv.clkr.hw,
|
|
[INDIRECT_PATH_SRC_0_CLK] = &dsi0pll_indirect_path_src.hw,
|
|
[BYTECLK_SRC_MUX_0_CLK] = &dsi0pll_byteclk_src_mux.clkr.hw,
|
|
[BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw,
|
|
[PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw,
|
|
[VCO_CLK_1] = &dsi1pll_vco_clk.hw,
|
|
[ANALOG_POSTDIV_1_CLK] = &dsi1pll_analog_postdiv.clkr.hw,
|
|
[INDIRECT_PATH_SRC_1_CLK] = &dsi1pll_indirect_path_src.hw,
|
|
[BYTECLK_SRC_MUX_1_CLK] = &dsi1pll_byteclk_src_mux.clkr.hw,
|
|
[BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw,
|
|
[PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw,
|
|
};
|
|
|
|
int dsi_pll_clock_register_28lpm(struct platform_device *pdev,
|
|
struct mdss_pll_resources *pll_res)
|
|
{
|
|
int rc = 0, ndx, i;
|
|
struct clk *clk;
|
|
struct clk_onecell_data *clk_data;
|
|
int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_28lpm);
|
|
struct regmap *rmap;
|
|
|
|
int const ssc_freq_min = 30000; /* min. recommended freq. value */
|
|
int const ssc_freq_max = 33000; /* max. recommended freq. value */
|
|
int const ssc_ppm_max = 5000; /* max. recommended ppm */
|
|
|
|
if (!pdev || !pdev->dev.of_node ||
|
|
!pll_res || !pll_res->pll_base) {
|
|
pr_err("Invalid params\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ndx = pll_res->index;
|
|
|
|
if (ndx >= DSI_PLL_MAX) {
|
|
pr_err("pll index(%d) NOT supported\n", ndx);
|
|
return -EINVAL;
|
|
}
|
|
|
|
pll_res->vco_delay = VCO_DELAY_USEC;
|
|
|
|
if (pll_res->ssc_en) {
|
|
if (!pll_res->ssc_freq || (pll_res->ssc_freq < ssc_freq_min) ||
|
|
(pll_res->ssc_freq > ssc_freq_max)) {
|
|
pll_res->ssc_freq = ssc_freq_min;
|
|
pr_debug("SSC frequency out of recommended range. Set to default=%d\n",
|
|
pll_res->ssc_freq);
|
|
}
|
|
|
|
if (!pll_res->ssc_ppm || (pll_res->ssc_ppm > ssc_ppm_max)) {
|
|
pll_res->ssc_ppm = ssc_ppm_max;
|
|
pr_debug("SSC PPM out of recommended range. Set to default=%d\n",
|
|
pll_res->ssc_ppm);
|
|
}
|
|
}
|
|
|
|
clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
|
|
GFP_KERNEL);
|
|
if (!clk_data)
|
|
return -ENOMEM;
|
|
|
|
clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks *
|
|
sizeof(struct clk *)), GFP_KERNEL);
|
|
if (!clk_data->clks) {
|
|
devm_kfree(&pdev->dev, clk_data);
|
|
return -ENOMEM;
|
|
}
|
|
clk_data->clk_num = num_clks;
|
|
|
|
/* Establish client data */
|
|
if (ndx == 0) {
|
|
rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi0pll_byteclk_src_mux.clkr.regmap = rmap;
|
|
|
|
rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi0pll_analog_postdiv.clkr.regmap = rmap;
|
|
|
|
rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi0pll_pclk_src.clkr.regmap = rmap;
|
|
|
|
dsi0pll_vco_clk.priv = pll_res;
|
|
for (i = VCO_CLK_0; i <= PCLK_SRC_0_CLK; i++) {
|
|
clk = devm_clk_register(&pdev->dev,
|
|
mdss_dsi_pllcc_28lpm[i]);
|
|
if (IS_ERR(clk)) {
|
|
pr_err("clk registration failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
rc = -EINVAL;
|
|
goto clk_register_fail;
|
|
}
|
|
clk_data->clks[i] = clk;
|
|
|
|
}
|
|
|
|
rc = of_clk_add_provider(pdev->dev.of_node,
|
|
of_clk_src_onecell_get, clk_data);
|
|
|
|
} else {
|
|
rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi1pll_byteclk_src_mux.clkr.regmap = rmap;
|
|
|
|
rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi1pll_analog_postdiv.clkr.regmap = rmap;
|
|
|
|
rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
|
|
pll_res, &dsi_pll_28lpm_config);
|
|
if (IS_ERR(rmap)) {
|
|
pr_err("regmap init failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
return -EINVAL;
|
|
}
|
|
dsi1pll_pclk_src.clkr.regmap = rmap;
|
|
|
|
dsi1pll_vco_clk.priv = pll_res;
|
|
for (i = VCO_CLK_1; i <= PCLK_SRC_1_CLK; i++) {
|
|
clk = devm_clk_register(&pdev->dev,
|
|
mdss_dsi_pllcc_28lpm[i]);
|
|
if (IS_ERR(clk)) {
|
|
pr_err("clk registration failed for DSI clock:%d\n",
|
|
pll_res->index);
|
|
rc = -EINVAL;
|
|
goto clk_register_fail;
|
|
}
|
|
clk_data->clks[i] = clk;
|
|
|
|
}
|
|
|
|
rc = of_clk_add_provider(pdev->dev.of_node,
|
|
of_clk_src_onecell_get, clk_data);
|
|
}
|
|
if (!rc) {
|
|
pr_info("Registered DSI PLL ndx=%d, clocks successfully", ndx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
clk_register_fail:
|
|
devm_kfree(&pdev->dev, clk_data->clks);
|
|
devm_kfree(&pdev->dev, clk_data);
|
|
return rc;
|
|
}
|
|
|