RE: [PATCH v6 12/13] phy: cadence: phy-cadence-sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks)
> -Original Message- > From: Kishon Vijay Abraham I > Sent: Wednesday, March 10, 2021 9:16 PM > To: Kishon Vijay Abraham I ; Vinod Koul > ; Rob Herring ; Philipp Zabel > ; Swapnil Kashinath Jakhade > > Cc: linux-kernel@vger.kernel.org; devicet...@vger.kernel.org; Lokesh Vutla > > Subject: [PATCH v6 12/13] phy: cadence: phy-cadence-sierra: Model > PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks) > > EXTERNAL MAIL > > > Sierra has two PLLs, PLL_CMNLC and PLL_CMNLC1 and each of these PLLs has > two inputs, plllc_refclk (input from pll0_refclk) and refrcv (input from > pll1_refclk). Model PLL_CMNLC and PLL_CMNLC1 as clocks so that it's > possible to select one of these two inputs from device tree. > > Signed-off-by: Kishon Vijay Abraham I > --- > drivers/phy/cadence/Kconfig | 1 + > drivers/phy/cadence/phy-cadence-sierra.c | 267 ++- > 2 files changed, 265 insertions(+), 3 deletions(-) > Reviewed-by: Swapnil Jakhade Thanks & regards, Swapnil > diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig > index 27e9d6c377e5..a62910ff5591 100644 > --- a/drivers/phy/cadence/Kconfig > +++ b/drivers/phy/cadence/Kconfig > @@ -25,6 +25,7 @@ config PHY_CADENCE_DPHY > config PHY_CADENCE_SIERRA > tristate "Cadence Sierra PHY Driver" > depends on OF && HAS_IOMEM && RESET_CONTROLLER > + depends on COMMON_CLK > select GENERIC_PHY > help > Enable this to support the Cadence Sierra PHY driver > diff --git a/drivers/phy/cadence/phy-cadence-sierra.c > b/drivers/phy/cadence/phy-cadence-sierra.c > index ac32b7b0289f..039ca10db59d 100644 > --- a/drivers/phy/cadence/phy-cadence-sierra.c > +++ b/drivers/phy/cadence/phy-cadence-sierra.c > @@ -7,6 +7,7 @@ > * > */ > #include > +#include > #include > #include > #include > @@ -20,10 +21,12 @@ > #include > #include > #include > +#include > > /* PHY register offsets */ > #define SIERRA_COMMON_CDB_OFFSET 0x0 > #define SIERRA_MACRO_ID_REG 0x0 > +#define SIERRA_CMN_PLLLC_GEN_PREG0x42 > #define SIERRA_CMN_PLLLC_MODE_PREG 0x48 > #define SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG 0x49 > #define SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG 0x4A > @@ -31,6 +34,9 @@ > #define SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG0x4F > #define SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG0x50 > #define SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG 0x62 > +#define SIERRA_CMN_REFRCV_PREG 0x98 > +#define SIERRA_CMN_REFRCV1_PREG 0xB8 > +#define SIERRA_CMN_PLLLC1_GEN_PREG 0xC2 > > #define SIERRA_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ > ((0x4000 << (block_offset)) + \ > @@ -144,13 +150,19 @@ > #define SIERRA_MAX_LANES 16 > #define PLL_LOCK_TIME10 > > -#define CDNS_SIERRA_INPUT_CLOCKS 3 > +#define CDNS_SIERRA_OUTPUT_CLOCKS2 > +#define CDNS_SIERRA_INPUT_CLOCKS 5 > enum cdns_sierra_clock_input { > PHY_CLK, > CMN_REFCLK_DIG_DIV, > CMN_REFCLK1_DIG_DIV, > + PLL0_REFCLK, > + PLL1_REFCLK, > }; > > +#define SIERRA_NUM_CMN_PLLC 2 > +#define SIERRA_NUM_CMN_PLLC_PARENTS 2 > + > static const struct reg_field macro_id_type = > REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15); > static const struct reg_field phy_pll_cfg_1 = > @@ -158,6 +170,53 @@ static const struct reg_field phy_pll_cfg_1 = > static const struct reg_field pllctrl_lock = > REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG, 0, > 0); > > +static const char * const clk_names[] = { > + [CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc", > + [CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1", > +}; > + > +enum cdns_sierra_cmn_plllc { > + CMN_PLLLC, > + CMN_PLLLC1, > +}; > + > +struct cdns_sierra_pll_mux_reg_fields { > + struct reg_fieldpfdclk_sel_preg; > + struct reg_fieldplllc1en_field; > + struct reg_fieldtermen_field; > +}; > + > +static const struct cdns_sierra_pll_mux_reg_fields > cmn_plllc_pfdclk1_sel_preg[] = { > + [CMN_PLLLC] = { > + .pfdclk_sel_preg = > REG_FIELD(SIERRA_CMN_PLLLC_GEN_PREG, 1, 1), > + .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 8, > 8), > + .termen_field = REG_FIELD(SIERRA
[PATCH v6 12/13] phy: cadence: phy-cadence-sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks)
Sierra has two PLLs, PLL_CMNLC and PLL_CMNLC1 and each of these PLLs has two inputs, plllc_refclk (input from pll0_refclk) and refrcv (input from pll1_refclk). Model PLL_CMNLC and PLL_CMNLC1 as clocks so that it's possible to select one of these two inputs from device tree. Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/cadence/Kconfig | 1 + drivers/phy/cadence/phy-cadence-sierra.c | 267 ++- 2 files changed, 265 insertions(+), 3 deletions(-) diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig index 27e9d6c377e5..a62910ff5591 100644 --- a/drivers/phy/cadence/Kconfig +++ b/drivers/phy/cadence/Kconfig @@ -25,6 +25,7 @@ config PHY_CADENCE_DPHY config PHY_CADENCE_SIERRA tristate "Cadence Sierra PHY Driver" depends on OF && HAS_IOMEM && RESET_CONTROLLER + depends on COMMON_CLK select GENERIC_PHY help Enable this to support the Cadence Sierra PHY driver diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index ac32b7b0289f..039ca10db59d 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -7,6 +7,7 @@ * */ #include +#include #include #include #include @@ -20,10 +21,12 @@ #include #include #include +#include /* PHY register offsets */ #define SIERRA_COMMON_CDB_OFFSET 0x0 #define SIERRA_MACRO_ID_REG0x0 +#define SIERRA_CMN_PLLLC_GEN_PREG 0x42 #define SIERRA_CMN_PLLLC_MODE_PREG 0x48 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG 0x49 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG 0x4A @@ -31,6 +34,9 @@ #define SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG 0x4F #define SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG 0x50 #define SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG0x62 +#define SIERRA_CMN_REFRCV_PREG 0x98 +#define SIERRA_CMN_REFRCV1_PREG0xB8 +#define SIERRA_CMN_PLLLC1_GEN_PREG 0xC2 #define SIERRA_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ ((0x4000 << (block_offset)) + \ @@ -144,13 +150,19 @@ #define SIERRA_MAX_LANES 16 #define PLL_LOCK_TIME 10 -#define CDNS_SIERRA_INPUT_CLOCKS 3 +#define CDNS_SIERRA_OUTPUT_CLOCKS 2 +#define CDNS_SIERRA_INPUT_CLOCKS 5 enum cdns_sierra_clock_input { PHY_CLK, CMN_REFCLK_DIG_DIV, CMN_REFCLK1_DIG_DIV, + PLL0_REFCLK, + PLL1_REFCLK, }; +#define SIERRA_NUM_CMN_PLLC2 +#define SIERRA_NUM_CMN_PLLC_PARENTS2 + static const struct reg_field macro_id_type = REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15); static const struct reg_field phy_pll_cfg_1 = @@ -158,6 +170,53 @@ static const struct reg_field phy_pll_cfg_1 = static const struct reg_field pllctrl_lock = REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG, 0, 0); +static const char * const clk_names[] = { + [CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc", + [CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1", +}; + +enum cdns_sierra_cmn_plllc { + CMN_PLLLC, + CMN_PLLLC1, +}; + +struct cdns_sierra_pll_mux_reg_fields { + struct reg_fieldpfdclk_sel_preg; + struct reg_fieldplllc1en_field; + struct reg_fieldtermen_field; +}; + +static const struct cdns_sierra_pll_mux_reg_fields cmn_plllc_pfdclk1_sel_preg[] = { + [CMN_PLLLC] = { + .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC_GEN_PREG, 1, 1), + .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 8, 8), + .termen_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 0, 0), + }, + [CMN_PLLLC1] = { + .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC1_GEN_PREG, 1, 1), + .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 8, 8), + .termen_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 0, 0), + }, +}; + +struct cdns_sierra_pll_mux { + struct clk_hw hw; + struct regmap_field *pfdclk_sel_preg; + struct regmap_field *plllc1en_field; + struct regmap_field *termen_field; + struct clk_init_dataclk_data; +}; + +#define to_cdns_sierra_pll_mux(_hw)\ + container_of(_hw, struct cdns_sierra_pll_mux, hw) + +static const int pll_mux_parent_index[][SIERRA_NUM_CMN_PLLC_PARENTS] = { + [CMN_PLLLC] = { PLL0_REFCLK, PLL1_REFCLK }, + [CMN_PLLLC1] = { PLL1_REFCLK, PLL0_REFCLK }, +}; + +static u32 cdns_sierra_pll_mux_table[] = { 0, 1 }; + struct cdns_sierra_inst { struct phy *phy; u32 phy_type; @@ -204,10 +263,15 @@ struct cdns_sierra_phy { struc