diff --git a/msm/dsi/dsi_pll_5nm.c b/msm/dsi/dsi_pll_5nm.c index aeb4b19118..dcfbda5a9e 100644 --- a/msm/dsi/dsi_pll_5nm.c +++ b/msm/dsi/dsi_pll_5nm.c @@ -181,6 +181,7 @@ /* Register Offsets from PHY base address */ #define PHY_CMN_CLK_CFG0 0x010 #define PHY_CMN_CLK_CFG1 0x014 +#define PHY_CMN_GLBL_CTRL 0x018 #define PHY_CMN_RBUF_CTRL 0x01C #define PHY_CMN_CTRL_0 0x024 #define PHY_CMN_CTRL_2 0x02C @@ -280,6 +281,7 @@ struct dsi_pll_5nm { struct dsi_pll_resource *rsc; struct dsi_pll_config pll_configuration; struct dsi_pll_regs reg_setup; + bool cphy_enabled; }; static inline bool dsi_pll_5nm_is_hw_revision( @@ -397,7 +399,10 @@ static inline int pclk_mux_write_sel(void *context, unsigned int reg, { int rc = 0; struct dsi_pll_resource *rsc = context; + struct dsi_pll_5nm *pll = rsc->priv; + if (pll->cphy_enabled) + WARN_ON("PHY is in CPHY mode. PLL config is incorrect\n"); rc = pclk_mux_write_sel_sub(rsc, reg, val); if (!rc && rsc->slave) rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); @@ -414,6 +419,42 @@ static inline int pclk_mux_write_sel(void *context, unsigned int reg, return rc; } +static inline int cphy_pclk_mux_read_sel(void *context, unsigned int reg, + unsigned int *val) +{ + struct dsi_pll_resource *rsc = context; + + *val = (DSI_PLL_REG_R(rsc->phy_base, reg) & 0x3); + + return 0; +} + +static inline int cphy_pclk_mux_write_sel(void *context, unsigned int reg, + unsigned int val) +{ + int rc = 0; + struct dsi_pll_resource *rsc = context; + struct dsi_pll_5nm *pll = rsc->priv; + + if (!pll->cphy_enabled) + WARN_ON("PHY-> not in CPHY mode. PLL config is incorrect\n"); + /* For Cphy configuration, val should always be 3 */ + val = 3; + rc = pclk_mux_write_sel_sub(rsc, reg, val); + if (!rc && rsc->slave) + rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); + + /* + * cache the current parent index for cases where parent + * is not changing but rate is changing. In that case + * clock framework won't call parent_set and hence dsiclk_sel + * bit won't be programmed. e.g. dfps update use case. + */ + rsc->cached_cfg1 = val; + + return rc; +} + static int dsi_pll_5nm_get_gdsc_status(struct dsi_pll_resource *rsc) { u32 reg = 0; @@ -806,6 +847,15 @@ static void dsi_pll_init_val(struct dsi_pll_resource *rsc) } +static void dsi_pll_detect_phy_mode(struct dsi_pll_5nm *pll, + struct dsi_pll_resource *rsc) +{ + u32 reg_val; + + reg_val = DSI_PLL_REG_R(rsc->phy_base, PHY_CMN_GLBL_CTRL); + pll->cphy_enabled = (reg_val & BIT(6)) ? true : false; +} + static void dsi_pll_commit(struct dsi_pll_5nm *pll, struct dsi_pll_resource *rsc) { @@ -823,7 +873,8 @@ static void dsi_pll_commit(struct dsi_pll_5nm *pll, reg->frac_div_start_high); DSI_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40); DSI_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06); - DSI_PLL_REG_W(pll_base, PLL_CMODE_1, 0x10); + DSI_PLL_REG_W(pll_base, PLL_CMODE_1, + pll->cphy_enabled ? 0x00 : 0x10); DSI_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS_1, reg->pll_clock_inverters); } @@ -857,6 +908,8 @@ static int vco_5nm_set_rate(struct clk_hw *hw, unsigned long rate, dsi_pll_init_val(rsc); + dsi_pll_detect_phy_mode(pll, rsc); + dsi_pll_setup_config(pll, rsc); dsi_pll_calc_dec_frac(pll, rsc); @@ -1221,11 +1274,19 @@ static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) { int rc; struct dsi_pll_resource *rsc = vco->priv; + struct dsi_pll_5nm *pll = rsc->priv; dsi_pll_enable_pll_bias(rsc); if (rsc->slave) dsi_pll_enable_pll_bias(rsc->slave); + /* For Cphy configuration, pclk_mux is always set to 3 divider */ + if (pll->cphy_enabled) { + rsc->cached_cfg1 |= 0x3; + if (rsc->slave) + rsc->slave->cached_cfg1 |= 0x3; + } + phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1); if (rsc->slave) phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1, @@ -1550,6 +1611,11 @@ static struct regmap_bus pclk_src_mux_regmap_bus = { .reg_write = pclk_mux_write_sel, }; +static struct regmap_bus cphy_pclk_src_mux_regmap_bus = { + .reg_read = cphy_pclk_mux_read_sel, + .reg_write = cphy_pclk_mux_write_sel, +}; + static struct regmap_bus pclk_src_regmap_bus = { .reg_write = pixel_clk_set_div, .reg_read = pixel_clk_get_div, @@ -1593,45 +1659,44 @@ static struct regmap_bus dsi_mux_regmap_bus = { * | DIV(1,2,4,8) | * +-------+-------+ * | - * +-----------------------------+--------+ - * | | | - * +-------v-------+ | | - * | bitclk_src | - * | DIV(1..15) | Not supported for DPHY - * +-------+-------+ - * | | | - * +----------+---------+ | | - * Shadow Path | | | | | - * + +-------v-------+ | +------v------+ | +------v-------+ - * | | byteclk_src | | |post_bit_div | | |post_vco_div | - * | | DIV(8) | | |DIV (2) | | |DIV(4) | - * | +-------+-------+ | +------+------+ | +------+-------+ - * | | | | | | | - * | | | +------+ | | - * | | +-------------+ | | +----+ - * | +--------+ | | | | - * | | +-v--v-v---v------+ - * +-v---------v----+ \ pclk_src_mux / - * \ byteclk_mux / \ / - * \ / +-----+-----+ - * +----+-----+ | Shadow Path - * | | + - * v +-----v------+ | - * dsi_byte_clk | pclk_src | | - * | DIV(1..15) | | - * +-----+------+ | - * | | - * | | - * +--------+ | - * | | - * +---v----v----+ - * \ pclk_mux / - * \ / - * +---+---+ - * | - * | - * v - * dsi_pclk + * +-----------------------------+-------+---------------+ + * | | | | + * +-------v-------+ | | | + * | bitclk_src | | + * | DIV(1..15) | Not supported for DPHY | + * +-------+-------+ | + * | | | | + * +-------------v+---------+---------+ | | | + * | | | | | | | + * +-----v-----+ +-----v-----+ | +------v------+ | +-----v------+ +-----v------+ + * |byteclk_src| |byteclk_src| | |post_bit_div | | |post_vco_div| |post_vco_div| + * | DIV(8) | | DIV(7) | | | DIV (2) | | | DIV(4) | | DIV(3.5) | + * +-----+-----+ +-----+-----+ | +------+------+ | +-----+------+ +------+-----+ + * | | | | | | | + *Shadow Path | CPHY Path | | | | +----v + * + | | +------+ | | +---+ | + * +---+ | +-----+ | | | | | + * | | | +-v--v----v---v---+ +--------v--------+ + * +---v--v--------v---+ \ pclk_src_mux / \ cphy_pclk_src / + * \ byteclk_mux / \ / \ mux / + * \ / +-----+-----+ +-----+-----+ + * +------+------+ | Shadow Path | + * | | + | + * v +-----v------+ | +------v------+ + * dsi_byte_clk | pclk_src | | |cphy_pclk_src| + * | DIV(1..15) | | | DIV(1..15) | + * +-----+------+ | +------+------+ + * | | | + * | | CPHY Path + * | | | + * +-------+ | +-------+ + * | | | + * +---v---v----v------+ + * \ pclk_mux / + * +------+------+ + * | + * v + * dsi_pclk * */ @@ -1844,6 +1909,28 @@ static struct clk_fixed_factor dsi1pll_post_vco_div = { }, }; +static struct clk_fixed_factor dsi0pll_post_vco_div3_5 = { + .div = 7, + .mult = 2, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_post_vco_div3_5", + .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_post_vco_div3_5 = { + .div = 7, + .mult = 2, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_post_vco_div3_5", + .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + static struct clk_fixed_factor dsi1pll_shadow_post_vco_div = { .div = 4, .mult = 1, @@ -1891,6 +1978,30 @@ static struct clk_fixed_factor dsi1pll_byteclk_src = { }, }; +static struct clk_fixed_factor dsi0pll_cphy_byteclk_src = { + .div = 7, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_cphy_byteclk_src", + .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_cphy_byteclk_src = { + .div = 7, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_cphy_byteclk_src", + .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + static struct clk_fixed_factor dsi1pll_shadow_byteclk_src = { .div = 8, .mult = 1, @@ -1954,8 +2065,9 @@ static struct clk_regmap_mux dsi0pll_byteclk_mux = { .hw.init = &(struct clk_init_data){ .name = "dsi0_phy_pll_out_byteclk", .parent_names = (const char *[]){"dsi0pll_byteclk_src", - "dsi0pll_shadow_byteclk_src"}, - .num_parents = 2, + "dsi0pll_shadow_byteclk_src", + "dsi0pll_cphy_byteclk_src"}, + .num_parents = 3, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, @@ -1970,8 +2082,9 @@ static struct clk_regmap_mux dsi1pll_byteclk_mux = { .hw.init = &(struct clk_init_data){ .name = "dsi1_phy_pll_out_byteclk", .parent_names = (const char *[]){"dsi1pll_byteclk_src", - "dsi1pll_shadow_byteclk_src"}, - .num_parents = 2, + "dsi1pll_shadow_byteclk_src", + "dsi1pll_cphy_byteclk_src"}, + .num_parents = 3, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, @@ -2010,6 +2123,21 @@ static struct clk_regmap_mux dsi0pll_shadow_pclk_src_mux = { }, }; +static struct clk_regmap_mux dsi0pll_cphy_pclk_src_mux = { + .reg = PHY_CMN_CLK_CFG1, + .shift = 0, + .width = 2, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_cphy_pclk_src_mux", + .parent_names = + (const char *[]){"dsi0pll_post_vco_div3_5"}, + .num_parents = 1, + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + static struct clk_regmap_mux dsi1pll_pclk_src_mux = { .reg = PHY_CMN_CLK_CFG1, .shift = 0, @@ -2041,6 +2169,21 @@ static struct clk_regmap_mux dsi1pll_shadow_pclk_src_mux = { }, }; +static struct clk_regmap_mux dsi1pll_cphy_pclk_src_mux = { + .reg = PHY_CMN_CLK_CFG1, + .shift = 0, + .width = 2, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_cphy_pclk_src_mux", + .parent_names = + (const char *[]){"dsi1pll_post_vco_div3_5"}, + .num_parents = 1, + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + static struct clk_regmap_div dsi0pll_pclk_src = { .shift = 0, .width = 4, @@ -2073,6 +2216,22 @@ static struct clk_regmap_div dsi0pll_shadow_pclk_src = { }, }; +static struct clk_regmap_div dsi0pll_cphy_pclk_src = { + .shift = 0, + .width = 4, + .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_cphy_pclk_src", + .parent_names = (const char *[]){ + "dsi0pll_cphy_pclk_src_mux"}, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, + }, +}; + static struct clk_regmap_div dsi1pll_pclk_src = { .shift = 0, .width = 4, @@ -2105,6 +2264,22 @@ static struct clk_regmap_div dsi1pll_shadow_pclk_src = { }, }; +static struct clk_regmap_div dsi1pll_cphy_pclk_src = { + .shift = 0, + .width = 4, + .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_cphy_pclk_src", + .parent_names = (const char *[]){ + "dsi1pll_cphy_pclk_src_mux"}, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ops, + }, + }, +}; + static struct clk_regmap_mux dsi0pll_pclk_mux = { .shift = 0, .width = 1, @@ -2112,8 +2287,9 @@ static struct clk_regmap_mux dsi0pll_pclk_mux = { .hw.init = &(struct clk_init_data){ .name = "dsi0_phy_pll_out_dsiclk", .parent_names = (const char *[]){"dsi0pll_pclk_src", - "dsi0pll_shadow_pclk_src"}, - .num_parents = 2, + "dsi0pll_shadow_pclk_src", + "dsi0pll_cphy_pclk_src"}, + .num_parents = 3, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, @@ -2128,8 +2304,9 @@ static struct clk_regmap_mux dsi1pll_pclk_mux = { .hw.init = &(struct clk_init_data){ .name = "dsi1_phy_pll_out_dsiclk", .parent_names = (const char *[]){"dsi1pll_pclk_src", - "dsi1pll_shadow_pclk_src"}, - .num_parents = 2, + "dsi1pll_shadow_pclk_src", + "dsi1pll_cphy_pclk_src"}, + .num_parents = 3, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_mux_closest_ops, @@ -2142,12 +2319,16 @@ static struct clk_hw *dsi_pllcc_5nm[] = { [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw, [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw, [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, + [CPHY_BYTECLK_SRC_0_CLK] = &dsi0pll_cphy_byteclk_src.hw, [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw, [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw, + [POST_VCO_DIV3_5_0_CLK] = &dsi0pll_post_vco_div3_5.hw, [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw, [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw, [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw, + [CPHY_PCLK_SRC_MUX_0_CLK] = &dsi0pll_cphy_pclk_src_mux.clkr.hw, + [CPHY_PCLK_SRC_0_CLK] = &dsi0pll_cphy_pclk_src.clkr.hw, [SHADOW_VCO_CLK_0] = &dsi0pll_shadow_vco_clk.hw, [SHADOW_PLL_OUT_DIV_0_CLK] = &dsi0pll_shadow_pll_out_div.clkr.hw, [SHADOW_BITCLK_SRC_0_CLK] = &dsi0pll_shadow_bitclk_src.clkr.hw, @@ -2160,12 +2341,16 @@ static struct clk_hw *dsi_pllcc_5nm[] = { [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw, [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw, [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, + [CPHY_BYTECLK_SRC_1_CLK] = &dsi1pll_cphy_byteclk_src.hw, [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw, [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw, + [POST_VCO_DIV3_5_1_CLK] = &dsi1pll_post_vco_div3_5.hw, [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw, [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw, [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw, + [CPHY_PCLK_SRC_MUX_1_CLK] = &dsi1pll_cphy_pclk_src_mux.clkr.hw, + [CPHY_PCLK_SRC_1_CLK] = &dsi1pll_cphy_pclk_src.clkr.hw, [SHADOW_VCO_CLK_1] = &dsi1pll_shadow_vco_clk.hw, [SHADOW_PLL_OUT_DIV_1_CLK] = &dsi1pll_shadow_pll_out_div.clkr.hw, [SHADOW_BITCLK_SRC_1_CLK] = &dsi1pll_shadow_bitclk_src.clkr.hw, @@ -2239,6 +2424,7 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, pll_res, rmap_config); dsi0pll_pclk_src.clkr.regmap = rmap; + dsi0pll_cphy_pclk_src.clkr.regmap = rmap; dsi0pll_shadow_pclk_src.clkr.regmap = rmap; rmap_config->name = "pclk_mux"; @@ -2252,6 +2438,12 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, dsi0pll_pclk_src_mux.clkr.regmap = rmap; dsi0pll_shadow_pclk_src_mux.clkr.regmap = rmap; + rmap_config->name = "cphy_pclk_src_mux"; + rmap = devm_regmap_init(&pdev->dev, + &cphy_pclk_src_mux_regmap_bus, + pll_res, rmap_config); + dsi0pll_cphy_pclk_src_mux.clkr.regmap = rmap; + rmap_config->name = "byteclk_mux"; rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, pll_res, rmap_config); @@ -2267,7 +2459,7 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, dsi0pll_shadow_vco_clk.max_rate = 5000000000; } - for (i = VCO_CLK_0; i <= SHADOW_PCLK_SRC_0_CLK; i++) { + for (i = VCO_CLK_0; i <= CPHY_PCLK_SRC_0_CLK; i++) { clk = devm_clk_register(&pdev->dev, dsi_pllcc_5nm[i]); if (IS_ERR(clk)) { @@ -2299,6 +2491,7 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, pll_res, rmap_config); dsi1pll_pclk_src.clkr.regmap = rmap; + dsi1pll_cphy_pclk_src.clkr.regmap = rmap; dsi1pll_shadow_pclk_src.clkr.regmap = rmap; rmap_config->name = "pclk_mux"; @@ -2312,6 +2505,12 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, dsi1pll_pclk_src_mux.clkr.regmap = rmap; dsi1pll_shadow_pclk_src_mux.clkr.regmap = rmap; + rmap_config->name = "cphy_pclk_src_mux"; + rmap = devm_regmap_init(&pdev->dev, + &cphy_pclk_src_mux_regmap_bus, + pll_res, rmap_config); + dsi1pll_cphy_pclk_src_mux.clkr.regmap = rmap; + rmap_config->name = "byteclk_mut"; rmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, pll_res, rmap_config); @@ -2327,7 +2526,7 @@ int dsi_pll_clock_register_5nm(struct platform_device *pdev, dsi1pll_shadow_vco_clk.max_rate = 5000000000; } - for (i = VCO_CLK_1; i <= SHADOW_PCLK_SRC_1_CLK; i++) { + for (i = VCO_CLK_1; i <= CPHY_PCLK_SRC_1_CLK; i++) { clk = devm_clk_register(&pdev->dev, dsi_pllcc_5nm[i]); if (IS_ERR(clk)) {