RE: [PATCH v6 12/13] phy: cadence: phy-cadence-sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks)

2021-03-14 Thread Swapnil Kashinath Jakhade



> -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)

2021-03-10 Thread Kishon Vijay Abraham I
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