11// SPDX-License-Identifier: GPL-2.0
22/*
33 * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
4+ * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
45 */
56
67#include <linux/kernel.h>
@@ -139,6 +140,20 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
139140 [PLL_OFF_OPMODE ] = 0x28 ,
140141 [PLL_OFF_STATUS ] = 0x38 ,
141142 },
143+ [CLK_ALPHA_PLL_TYPE_LUCID_EVO ] = {
144+ [PLL_OFF_OPMODE ] = 0x04 ,
145+ [PLL_OFF_STATUS ] = 0x0c ,
146+ [PLL_OFF_L_VAL ] = 0x10 ,
147+ [PLL_OFF_ALPHA_VAL ] = 0x14 ,
148+ [PLL_OFF_USER_CTL ] = 0x18 ,
149+ [PLL_OFF_USER_CTL_U ] = 0x1c ,
150+ [PLL_OFF_CONFIG_CTL ] = 0x20 ,
151+ [PLL_OFF_CONFIG_CTL_U ] = 0x24 ,
152+ [PLL_OFF_CONFIG_CTL_U1 ] = 0x28 ,
153+ [PLL_OFF_TEST_CTL ] = 0x2c ,
154+ [PLL_OFF_TEST_CTL_U ] = 0x30 ,
155+ [PLL_OFF_TEST_CTL_U1 ] = 0x34 ,
156+ },
142157};
143158EXPORT_SYMBOL_GPL (clk_alpha_pll_regs );
144159
@@ -175,6 +190,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
175190#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14)
176191#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21)
177192
193+ /* LUCID EVO PLL specific settings and offsets */
194+ #define LUCID_EVO_ENABLE_VOTE_RUN BIT(25)
195+ #define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
196+
178197/* ZONDA PLL specific */
179198#define ZONDA_PLL_OUT_MASK 0xf
180199#define ZONDA_STAY_IN_CFA BIT(16)
@@ -1741,24 +1760,32 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
17411760 LUCID_5LPE_ALPHA_PLL_ACK_LATCH );
17421761}
17431762
1744- static int clk_lucid_5lpe_pll_postdiv_set_rate (struct clk_hw * hw , unsigned long rate ,
1745- unsigned long parent_rate )
1763+ static int __clk_lucid_pll_postdiv_set_rate (struct clk_hw * hw , unsigned long rate ,
1764+ unsigned long parent_rate ,
1765+ unsigned long enable_vote_run )
17461766{
17471767 struct clk_alpha_pll_postdiv * pll = to_clk_alpha_pll_postdiv (hw );
1748- int i , val = 0 , div , ret ;
1768+ struct regmap * regmap = pll -> clkr .regmap ;
1769+ int i , val , div , ret ;
17491770 u32 mask ;
17501771
17511772 /*
17521773 * If the PLL is in FSM mode, then treat set_rate callback as a
17531774 * no-operation.
17541775 */
1755- ret = regmap_read (pll -> clkr . regmap , PLL_USER_CTL (pll ), & val );
1776+ ret = regmap_read (regmap , PLL_USER_CTL (pll ), & val );
17561777 if (ret )
17571778 return ret ;
17581779
1759- if (val & LUCID_5LPE_ENABLE_VOTE_RUN )
1780+ if (val & enable_vote_run )
17601781 return 0 ;
17611782
1783+ if (!pll -> post_div_table ) {
1784+ pr_err ("Missing the post_div_table for the %s PLL\n" ,
1785+ clk_hw_get_name (& pll -> clkr .hw ));
1786+ return - EINVAL ;
1787+ }
1788+
17621789 div = DIV_ROUND_UP_ULL ((u64 )parent_rate , rate );
17631790 for (i = 0 ; i < pll -> num_post_div ; i ++ ) {
17641791 if (pll -> post_div_table [i ].div == div ) {
@@ -1772,6 +1799,12 @@ static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long
17721799 mask , val << pll -> post_div_shift );
17731800}
17741801
1802+ static int clk_lucid_5lpe_pll_postdiv_set_rate (struct clk_hw * hw , unsigned long rate ,
1803+ unsigned long parent_rate )
1804+ {
1805+ return __clk_lucid_pll_postdiv_set_rate (hw , rate , parent_rate , LUCID_5LPE_ENABLE_VOTE_RUN );
1806+ }
1807+
17751808const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
17761809 .prepare = alpha_pll_lucid_5lpe_prepare ,
17771810 .enable = alpha_pll_lucid_5lpe_enable ,
@@ -1951,3 +1984,124 @@ const struct clk_ops clk_alpha_pll_zonda_ops = {
19511984 .set_rate = clk_zonda_pll_set_rate ,
19521985};
19531986EXPORT_SYMBOL (clk_alpha_pll_zonda_ops );
1987+
1988+ static int alpha_pll_lucid_evo_enable (struct clk_hw * hw )
1989+ {
1990+ struct clk_alpha_pll * pll = to_clk_alpha_pll (hw );
1991+ struct regmap * regmap = pll -> clkr .regmap ;
1992+ u32 val ;
1993+ int ret ;
1994+
1995+ ret = regmap_read (regmap , PLL_USER_CTL (pll ), & val );
1996+ if (ret )
1997+ return ret ;
1998+
1999+ /* If in FSM mode, just vote for it */
2000+ if (val & LUCID_EVO_ENABLE_VOTE_RUN ) {
2001+ ret = clk_enable_regmap (hw );
2002+ if (ret )
2003+ return ret ;
2004+ return wait_for_pll_enable_lock (pll );
2005+ }
2006+
2007+ /* Check if PLL is already enabled */
2008+ ret = trion_pll_is_enabled (pll , regmap );
2009+ if (ret < 0 ) {
2010+ return ret ;
2011+ } else if (ret ) {
2012+ pr_warn ("%s PLL is already enabled\n" , clk_hw_get_name (& pll -> clkr .hw ));
2013+ return 0 ;
2014+ }
2015+
2016+ ret = regmap_update_bits (regmap , PLL_MODE (pll ), PLL_RESET_N , PLL_RESET_N );
2017+ if (ret )
2018+ return ret ;
2019+
2020+ /* Set operation mode to RUN */
2021+ regmap_write (regmap , PLL_OPMODE (pll ), PLL_RUN );
2022+
2023+ ret = wait_for_pll_enable_lock (pll );
2024+ if (ret )
2025+ return ret ;
2026+
2027+ /* Enable the PLL outputs */
2028+ ret = regmap_update_bits (regmap , PLL_USER_CTL (pll ), PLL_OUT_MASK , PLL_OUT_MASK );
2029+ if (ret )
2030+ return ret ;
2031+
2032+ /* Enable the global PLL outputs */
2033+ ret = regmap_update_bits (regmap , PLL_MODE (pll ), PLL_OUTCTRL , PLL_OUTCTRL );
2034+ if (ret )
2035+ return ret ;
2036+
2037+ /* Ensure that the write above goes through before returning. */
2038+ mb ();
2039+ return ret ;
2040+ }
2041+
2042+ static void alpha_pll_lucid_evo_disable (struct clk_hw * hw )
2043+ {
2044+ struct clk_alpha_pll * pll = to_clk_alpha_pll (hw );
2045+ struct regmap * regmap = pll -> clkr .regmap ;
2046+ u32 val ;
2047+ int ret ;
2048+
2049+ ret = regmap_read (regmap , PLL_USER_CTL (pll ), & val );
2050+ if (ret )
2051+ return ;
2052+
2053+ /* If in FSM mode, just unvote it */
2054+ if (val & LUCID_EVO_ENABLE_VOTE_RUN ) {
2055+ clk_disable_regmap (hw );
2056+ return ;
2057+ }
2058+
2059+ /* Disable the global PLL output */
2060+ ret = regmap_update_bits (regmap , PLL_MODE (pll ), PLL_OUTCTRL , 0 );
2061+ if (ret )
2062+ return ;
2063+
2064+ /* Disable the PLL outputs */
2065+ ret = regmap_update_bits (regmap , PLL_USER_CTL (pll ), PLL_OUT_MASK , 0 );
2066+ if (ret )
2067+ return ;
2068+
2069+ /* Place the PLL mode in STANDBY */
2070+ regmap_write (regmap , PLL_OPMODE (pll ), PLL_STANDBY );
2071+ }
2072+
2073+ static unsigned long alpha_pll_lucid_evo_recalc_rate (struct clk_hw * hw ,
2074+ unsigned long parent_rate )
2075+ {
2076+ struct clk_alpha_pll * pll = to_clk_alpha_pll (hw );
2077+ struct regmap * regmap = pll -> clkr .regmap ;
2078+ u32 l , frac ;
2079+
2080+ regmap_read (regmap , PLL_L_VAL (pll ), & l );
2081+ l &= LUCID_EVO_PLL_L_VAL_MASK ;
2082+ regmap_read (regmap , PLL_ALPHA_VAL (pll ), & frac );
2083+
2084+ return alpha_pll_calc_rate (parent_rate , l , frac , pll_alpha_width (pll ));
2085+ }
2086+
2087+ static int clk_lucid_evo_pll_postdiv_set_rate (struct clk_hw * hw , unsigned long rate ,
2088+ unsigned long parent_rate )
2089+ {
2090+ return __clk_lucid_pll_postdiv_set_rate (hw , rate , parent_rate , LUCID_EVO_ENABLE_VOTE_RUN );
2091+ }
2092+
2093+ const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops = {
2094+ .enable = alpha_pll_lucid_evo_enable ,
2095+ .disable = alpha_pll_lucid_evo_disable ,
2096+ .is_enabled = clk_trion_pll_is_enabled ,
2097+ .recalc_rate = alpha_pll_lucid_evo_recalc_rate ,
2098+ .round_rate = clk_alpha_pll_round_rate ,
2099+ };
2100+ EXPORT_SYMBOL_GPL (clk_alpha_pll_fixed_lucid_evo_ops );
2101+
2102+ const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = {
2103+ .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate ,
2104+ .round_rate = clk_alpha_pll_postdiv_fabia_round_rate ,
2105+ .set_rate = clk_lucid_evo_pll_postdiv_set_rate ,
2106+ };
2107+ EXPORT_SYMBOL_GPL (clk_alpha_pll_postdiv_lucid_evo_ops );
0 commit comments