* [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-08-06 11:11 ` Paul Kocialkowski
2021-06-24 18:41 ` [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support Pratyush Yadav
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Kishon Vijay Abraham I, linux-kernel, linux-phy
From: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
As some D-PHY controllers support both Rx and Tx mode, we need a way for
users to explicitly request one or the other. For instance, Rx mode can
be used along with MIPI CSI-2 while Tx mode can be used with MIPI DSI.
Introduce new MIPI D-PHY PHY submodes to use with PHY_MODE_MIPI_DPHY.
The default (zero value) is kept to Tx so only the rkisp1 driver, which
uses D-PHY in Rx mode, needs to be adapted.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
---
(no changes since v1)
include/linux/phy/phy-mipi-dphy.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h
index a877ffee845d..0f57ef46a8b5 100644
--- a/include/linux/phy/phy-mipi-dphy.h
+++ b/include/linux/phy/phy-mipi-dphy.h
@@ -6,6 +6,19 @@
#ifndef __PHY_MIPI_DPHY_H_
#define __PHY_MIPI_DPHY_H_
+/**
+ * enum phy_mipi_dphy_submode - MIPI D-PHY sub-mode
+ *
+ * A MIPI D-PHY can be used to transmit or receive data.
+ * Since some controllers can support both, the direction to enable is specified
+ * with the PHY sub-mode. Transmit is assumed by default with phy_set_mode.
+ */
+
+enum phy_mipi_dphy_submode {
+ PHY_MIPI_DPHY_SUBMODE_TX = 0,
+ PHY_MIPI_DPHY_SUBMODE_RX,
+};
+
/**
* struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set
*
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes
2021-06-24 18:41 ` [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes Pratyush Yadav
@ 2021-08-06 11:11 ` Paul Kocialkowski
2021-08-11 17:36 ` Pratyush Yadav
0 siblings, 1 reply; 14+ messages in thread
From: Paul Kocialkowski @ 2021-08-06 11:11 UTC (permalink / raw)
To: Pratyush Yadav
Cc: Vinod Koul, Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Vignesh Raghavendra, Kishon Vijay Abraham I, linux-kernel,
linux-phy
[-- Attachment #1: Type: text/plain, Size: 2359 bytes --]
Hi,
On Fri 25 Jun 21, 00:11, Pratyush Yadav wrote:
> From: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>
> As some D-PHY controllers support both Rx and Tx mode, we need a way for
> users to explicitly request one or the other. For instance, Rx mode can
> be used along with MIPI CSI-2 while Tx mode can be used with MIPI DSI.
>
> Introduce new MIPI D-PHY PHY submodes to use with PHY_MODE_MIPI_DPHY.
> The default (zero value) is kept to Tx so only the rkisp1 driver, which
> uses D-PHY in Rx mode, needs to be adapted.
After some thinking and discussions, it appears that using the submode is
probably not the best way to distinguish between rx and tx. This is because
rx/tx is more of a specification of the hardware component than a run-time
descision. Indeed the D-PHY blocks are usually dedicated to an associated
controller (DSI or CSI-2) and thus each instance is either meant for tx or
rx use.
As a result I will be using the allwinner,direction string property in
device-tree instead of the submode, with values of either "rx" or "tx".
I suppose you can do something similar if you agree it makes more sense.
Cheers,
Paul
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> ---
>
> (no changes since v1)
>
> include/linux/phy/phy-mipi-dphy.h | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h
> index a877ffee845d..0f57ef46a8b5 100644
> --- a/include/linux/phy/phy-mipi-dphy.h
> +++ b/include/linux/phy/phy-mipi-dphy.h
> @@ -6,6 +6,19 @@
> #ifndef __PHY_MIPI_DPHY_H_
> #define __PHY_MIPI_DPHY_H_
>
> +/**
> + * enum phy_mipi_dphy_submode - MIPI D-PHY sub-mode
> + *
> + * A MIPI D-PHY can be used to transmit or receive data.
> + * Since some controllers can support both, the direction to enable is specified
> + * with the PHY sub-mode. Transmit is assumed by default with phy_set_mode.
> + */
> +
> +enum phy_mipi_dphy_submode {
> + PHY_MIPI_DPHY_SUBMODE_TX = 0,
> + PHY_MIPI_DPHY_SUBMODE_RX,
> +};
> +
> /**
> * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set
> *
> --
> 2.30.0
>
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes
2021-08-06 11:11 ` Paul Kocialkowski
@ 2021-08-11 17:36 ` Pratyush Yadav
0 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-08-11 17:36 UTC (permalink / raw)
To: Paul Kocialkowski
Cc: Vinod Koul, Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Vignesh Raghavendra, Kishon Vijay Abraham I, linux-kernel,
linux-phy
On 06/08/21 01:11PM, Paul Kocialkowski wrote:
> Hi,
>
> On Fri 25 Jun 21, 00:11, Pratyush Yadav wrote:
> > From: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> >
> > As some D-PHY controllers support both Rx and Tx mode, we need a way for
> > users to explicitly request one or the other. For instance, Rx mode can
> > be used along with MIPI CSI-2 while Tx mode can be used with MIPI DSI.
> >
> > Introduce new MIPI D-PHY PHY submodes to use with PHY_MODE_MIPI_DPHY.
> > The default (zero value) is kept to Tx so only the rkisp1 driver, which
> > uses D-PHY in Rx mode, needs to be adapted.
>
> After some thinking and discussions, it appears that using the submode is
> probably not the best way to distinguish between rx and tx. This is because
> rx/tx is more of a specification of the hardware component than a run-time
> descision. Indeed the D-PHY blocks are usually dedicated to an associated
> controller (DSI or CSI-2) and thus each instance is either meant for tx or
> rx use.
Ok. IIRC Laurent also brought this point up earlier as well. At that
time I took the allwinner DPHY as an example of a DPHY that can run in
both modes.
The Cadence DPHY also supports both Rx and Tx modes but I don't know if
both can be implemented at the same time, if that would even make any
sense.
>
> As a result I will be using the allwinner,direction string property in
> device-tree instead of the submode, with values of either "rx" or "tx".
> I suppose you can do something similar if you agree it makes more sense.
Wouldn't a different compatible a better idea?
>
> Cheers,
>
> Paul
>
> > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > ---
> >
> > (no changes since v1)
> >
> > include/linux/phy/phy-mipi-dphy.h | 13 +++++++++++++
> > 1 file changed, 13 insertions(+)
> >
> > diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h
> > index a877ffee845d..0f57ef46a8b5 100644
> > --- a/include/linux/phy/phy-mipi-dphy.h
> > +++ b/include/linux/phy/phy-mipi-dphy.h
> > @@ -6,6 +6,19 @@
> > #ifndef __PHY_MIPI_DPHY_H_
> > #define __PHY_MIPI_DPHY_H_
> >
> > +/**
> > + * enum phy_mipi_dphy_submode - MIPI D-PHY sub-mode
> > + *
> > + * A MIPI D-PHY can be used to transmit or receive data.
> > + * Since some controllers can support both, the direction to enable is specified
> > + * with the PHY sub-mode. Transmit is assumed by default with phy_set_mode.
> > + */
> > +
> > +enum phy_mipi_dphy_submode {
> > + PHY_MIPI_DPHY_SUBMODE_TX = 0,
> > + PHY_MIPI_DPHY_SUBMODE_RX,
> > +};
> > +
> > /**
> > * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set
> > *
> > --
> > 2.30.0
> >
>
> --
> Paul Kocialkowski, Bootlin
> Embedded Linux and kernel engineering
> https://bootlin.com
--
Regards,
Pratyush Yadav
Texas Instruments Inc.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-08-06 10:18 ` Vinod Koul
2021-06-24 18:41 ` [PATCH v3 3/7] phy: cdns-dphy: Allow setting mode Pratyush Yadav
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Chunfeng Yun, Kishon Vijay Abraham I, Peter Chen, linux-kernel,
linux-phy
The Rx programming sequence differs from the Tx programming sequence.
Currently only Tx mode is supported. Move all the Tx related parts into
a set of Tx-specific hooks that are then called by the main PHY
framework hooks. This way when Rx support is added all that is needed to
be done is to plug in the Rx hooks.
The clocks "psm" and "pll_ref" are not used by the Rx path so make them
optional in the probe and then check if they exist in the power_on()
hook.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
---
(no changes since v1)
drivers/phy/cadence/cdns-dphy.c | 140 ++++++++++++++++++++++++--------
1 file changed, 104 insertions(+), 36 deletions(-)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index ba042e39cfaf..8656f2102a91 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -75,6 +75,11 @@ struct cdns_dphy;
struct cdns_dphy_ops {
int (*probe)(struct cdns_dphy *dphy);
void (*remove)(struct cdns_dphy *dphy);
+ int (*power_on)(struct cdns_dphy *dphy);
+ int (*power_off)(struct cdns_dphy *dphy);
+ int (*validate)(struct cdns_dphy *dphy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts);
+ int (*configure)(struct cdns_dphy *dphy, union phy_configure_opts *opts);
void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
enum cdns_dphy_clk_lane_cfg cfg);
@@ -86,12 +91,18 @@ struct cdns_dphy_ops {
struct cdns_dphy {
struct cdns_dphy_cfg cfg;
void __iomem *regs;
+ struct device *dev;
struct clk *psm_clk;
struct clk *pll_ref_clk;
const struct cdns_dphy_ops *ops;
struct phy *phy;
};
+struct cdns_dphy_driver_data {
+ const struct cdns_dphy_ops *tx;
+ const struct cdns_dphy_ops *rx;
+};
+
static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
struct cdns_dphy_cfg *cfg,
struct phy_configure_opts_mipi_dphy *opts,
@@ -199,20 +210,9 @@ static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
dphy->regs + DPHY_PSM_CFG);
}
-/*
- * This is the reference implementation of DPHY hooks. Specific integration of
- * this IP may have to re-implement some of them depending on how they decided
- * to wire things in the SoC.
- */
-static const struct cdns_dphy_ops ref_dphy_ops = {
- .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
- .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
- .set_psm_div = cdns_dphy_ref_set_psm_div,
-};
-
-static int cdns_dphy_config_from_opts(struct phy *phy,
- struct phy_configure_opts_mipi_dphy *opts,
- struct cdns_dphy_cfg *cfg)
+static int cdns_dphy_tx_config_from_opts(struct phy *phy,
+ struct phy_configure_opts_mipi_dphy *opts,
+ struct cdns_dphy_cfg *cfg)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
unsigned int dsi_hfp_ext = 0;
@@ -232,24 +232,13 @@ static int cdns_dphy_config_from_opts(struct phy *phy,
return 0;
}
-static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
- union phy_configure_opts *opts)
+static int cdns_dphy_tx_configure(struct cdns_dphy *dphy,
+ union phy_configure_opts *opts)
{
struct cdns_dphy_cfg cfg = { 0 };
-
- if (mode != PHY_MODE_MIPI_DPHY)
- return -EINVAL;
-
- return cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
-}
-
-static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
-{
- struct cdns_dphy *dphy = phy_get_drvdata(phy);
- struct cdns_dphy_cfg cfg = { 0 };
int ret;
- ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
+ ret = cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
if (ret)
return ret;
@@ -279,9 +268,21 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
return 0;
}
-static int cdns_dphy_power_on(struct phy *phy)
+static int cdns_dphy_tx_validate(struct cdns_dphy *dphy, enum phy_mode mode,
+ int submode, union phy_configure_opts *opts)
{
- struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ struct cdns_dphy_cfg cfg = { 0 };
+
+ if (submode != PHY_MIPI_DPHY_SUBMODE_TX)
+ return -EINVAL;
+
+ return cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
+}
+
+static int cdns_dphy_tx_power_on(struct cdns_dphy *dphy)
+{
+ if (!dphy->psm_clk || !dphy->pll_ref_clk)
+ return -EINVAL;
clk_prepare_enable(dphy->psm_clk);
clk_prepare_enable(dphy->pll_ref_clk);
@@ -293,16 +294,77 @@ static int cdns_dphy_power_on(struct phy *phy)
return 0;
}
-static int cdns_dphy_power_off(struct phy *phy)
+static int cdns_dphy_tx_power_off(struct cdns_dphy *dphy)
{
- struct cdns_dphy *dphy = phy_get_drvdata(phy);
-
clk_disable_unprepare(dphy->pll_ref_clk);
clk_disable_unprepare(dphy->psm_clk);
return 0;
}
+static const struct cdns_dphy_ops tx_ref_dphy_ops = {
+ .power_on = cdns_dphy_tx_power_on,
+ .power_off = cdns_dphy_tx_power_off,
+ .validate = cdns_dphy_tx_validate,
+ .configure = cdns_dphy_tx_configure,
+ .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
+ .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
+ .set_psm_div = cdns_dphy_ref_set_psm_div,
+};
+
+/*
+ * This is the reference implementation of DPHY hooks. Specific integration of
+ * this IP may have to re-implement some of them depending on how they decided
+ * to wire things in the SoC.
+ */
+static const struct cdns_dphy_driver_data ref_dphy_ops = {
+ .tx = &tx_ref_dphy_ops,
+};
+
+static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ if (mode != PHY_MODE_MIPI_DPHY)
+ return -EINVAL;
+
+ if (dphy->ops->validate)
+ return dphy->ops->validate(dphy, mode, submode, opts);
+
+ return 0;
+}
+
+static int cdns_dphy_power_on(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ if (dphy->ops->power_on)
+ return dphy->ops->power_on(dphy);
+
+ return 0;
+}
+
+static int cdns_dphy_power_off(struct phy *phy)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ if (dphy->ops->power_off)
+ return dphy->ops->power_off(dphy);
+
+ return 0;
+}
+
+static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+
+ if (dphy->ops->configure)
+ return dphy->ops->configure(dphy, opts);
+
+ return 0;
+}
+
static const struct phy_ops cdns_dphy_ops = {
.configure = cdns_dphy_configure,
.validate = cdns_dphy_validate,
@@ -314,14 +376,20 @@ static int cdns_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct cdns_dphy *dphy;
+ const struct cdns_dphy_driver_data *ddata;
int ret;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, dphy);
+ dphy->dev = &pdev->dev;
- dphy->ops = of_device_get_match_data(&pdev->dev);
+ ddata = of_device_get_match_data(&pdev->dev);
+ if (!ddata)
+ return -EINVAL;
+
+ dphy->ops = ddata->tx;
if (!dphy->ops)
return -EINVAL;
@@ -329,11 +397,11 @@ static int cdns_dphy_probe(struct platform_device *pdev)
if (IS_ERR(dphy->regs))
return PTR_ERR(dphy->regs);
- dphy->psm_clk = devm_clk_get(&pdev->dev, "psm");
+ dphy->psm_clk = devm_clk_get_optional(dphy->dev, "psm");
if (IS_ERR(dphy->psm_clk))
return PTR_ERR(dphy->psm_clk);
- dphy->pll_ref_clk = devm_clk_get(&pdev->dev, "pll_ref");
+ dphy->pll_ref_clk = devm_clk_get_optional(dphy->dev, "pll_ref");
if (IS_ERR(dphy->pll_ref_clk))
return PTR_ERR(dphy->pll_ref_clk);
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support
2021-06-24 18:41 ` [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support Pratyush Yadav
@ 2021-08-06 10:18 ` Vinod Koul
2021-08-11 17:39 ` Pratyush Yadav
0 siblings, 1 reply; 14+ messages in thread
From: Vinod Koul @ 2021-08-06 10:18 UTC (permalink / raw)
To: Pratyush Yadav
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Chunfeng Yun,
Kishon Vijay Abraham I, Peter Chen, linux-kernel, linux-phy
On 25-06-21, 00:11, Pratyush Yadav wrote:
> The Rx programming sequence differs from the Tx programming sequence.
> Currently only Tx mode is supported. Move all the Tx related parts into
> a set of Tx-specific hooks that are then called by the main PHY
> framework hooks. This way when Rx support is added all that is needed to
> be done is to plug in the Rx hooks.
>
> The clocks "psm" and "pll_ref" are not used by the Rx path so make them
> optional in the probe and then check if they exist in the power_on()
> hook.
>
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> ---
>
> (no changes since v1)
>
> drivers/phy/cadence/cdns-dphy.c | 140 ++++++++++++++++++++++++--------
> 1 file changed, 104 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
> index ba042e39cfaf..8656f2102a91 100644
> --- a/drivers/phy/cadence/cdns-dphy.c
> +++ b/drivers/phy/cadence/cdns-dphy.c
> @@ -75,6 +75,11 @@ struct cdns_dphy;
> struct cdns_dphy_ops {
> int (*probe)(struct cdns_dphy *dphy);
> void (*remove)(struct cdns_dphy *dphy);
> + int (*power_on)(struct cdns_dphy *dphy);
> + int (*power_off)(struct cdns_dphy *dphy);
> + int (*validate)(struct cdns_dphy *dphy, enum phy_mode mode, int submode,
> + union phy_configure_opts *opts);
> + int (*configure)(struct cdns_dphy *dphy, union phy_configure_opts *opts);
> void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
> void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
> enum cdns_dphy_clk_lane_cfg cfg);
> @@ -86,12 +91,18 @@ struct cdns_dphy_ops {
> struct cdns_dphy {
> struct cdns_dphy_cfg cfg;
> void __iomem *regs;
> + struct device *dev;
> struct clk *psm_clk;
> struct clk *pll_ref_clk;
> const struct cdns_dphy_ops *ops;
> struct phy *phy;
> };
>
> +struct cdns_dphy_driver_data {
> + const struct cdns_dphy_ops *tx;
> + const struct cdns_dphy_ops *rx;
> +};
> +
> static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
> struct cdns_dphy_cfg *cfg,
> struct phy_configure_opts_mipi_dphy *opts,
> @@ -199,20 +210,9 @@ static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
> dphy->regs + DPHY_PSM_CFG);
> }
>
> -/*
> - * This is the reference implementation of DPHY hooks. Specific integration of
> - * this IP may have to re-implement some of them depending on how they decided
> - * to wire things in the SoC.
> - */
> -static const struct cdns_dphy_ops ref_dphy_ops = {
> - .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
> - .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
> - .set_psm_div = cdns_dphy_ref_set_psm_div,
> -};
> -
> -static int cdns_dphy_config_from_opts(struct phy *phy,
> - struct phy_configure_opts_mipi_dphy *opts,
> - struct cdns_dphy_cfg *cfg)
> +static int cdns_dphy_tx_config_from_opts(struct phy *phy,
> + struct phy_configure_opts_mipi_dphy *opts,
> + struct cdns_dphy_cfg *cfg)
> {
> struct cdns_dphy *dphy = phy_get_drvdata(phy);
> unsigned int dsi_hfp_ext = 0;
> @@ -232,24 +232,13 @@ static int cdns_dphy_config_from_opts(struct phy *phy,
> return 0;
> }
>
> -static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
> - union phy_configure_opts *opts)
> +static int cdns_dphy_tx_configure(struct cdns_dphy *dphy,
> + union phy_configure_opts *opts)
> {
> struct cdns_dphy_cfg cfg = { 0 };
> -
> - if (mode != PHY_MODE_MIPI_DPHY)
> - return -EINVAL;
> -
> - return cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
> -}
> -
> -static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
> -{
> - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> - struct cdns_dphy_cfg cfg = { 0 };
> int ret;
>
> - ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
> + ret = cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
> if (ret)
> return ret;
>
> @@ -279,9 +268,21 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
> return 0;
> }
>
> -static int cdns_dphy_power_on(struct phy *phy)
> +static int cdns_dphy_tx_validate(struct cdns_dphy *dphy, enum phy_mode mode,
> + int submode, union phy_configure_opts *opts)
> {
> - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> + struct cdns_dphy_cfg cfg = { 0 };
> +
> + if (submode != PHY_MIPI_DPHY_SUBMODE_TX)
> + return -EINVAL;
> +
> + return cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
> +}
> +
> +static int cdns_dphy_tx_power_on(struct cdns_dphy *dphy)
> +{
> + if (!dphy->psm_clk || !dphy->pll_ref_clk)
> + return -EINVAL;
>
> clk_prepare_enable(dphy->psm_clk);
> clk_prepare_enable(dphy->pll_ref_clk);
> @@ -293,16 +294,77 @@ static int cdns_dphy_power_on(struct phy *phy)
> return 0;
> }
>
> -static int cdns_dphy_power_off(struct phy *phy)
> +static int cdns_dphy_tx_power_off(struct cdns_dphy *dphy)
> {
> - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> -
> clk_disable_unprepare(dphy->pll_ref_clk);
> clk_disable_unprepare(dphy->psm_clk);
>
> return 0;
> }
>
> +static const struct cdns_dphy_ops tx_ref_dphy_ops = {
> + .power_on = cdns_dphy_tx_power_on,
> + .power_off = cdns_dphy_tx_power_off,
> + .validate = cdns_dphy_tx_validate,
> + .configure = cdns_dphy_tx_configure,
> + .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
> + .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
> + .set_psm_div = cdns_dphy_ref_set_psm_div,
> +};
> +
> +/*
> + * This is the reference implementation of DPHY hooks. Specific integration of
> + * this IP may have to re-implement some of them depending on how they decided
> + * to wire things in the SoC.
> + */
> +static const struct cdns_dphy_driver_data ref_dphy_ops = {
> + .tx = &tx_ref_dphy_ops,
> +};
> +
> +static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
> + union phy_configure_opts *opts)
> +{
> + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> +
> + if (mode != PHY_MODE_MIPI_DPHY)
> + return -EINVAL;
> +
> + if (dphy->ops->validate)
> + return dphy->ops->validate(dphy, mode, submode, opts);
> +
> + return 0;
> +}
> +
> +static int cdns_dphy_power_on(struct phy *phy)
> +{
> + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> +
> + if (dphy->ops->power_on)
> + return dphy->ops->power_on(dphy);
> +
> + return 0;
> +}
> +
> +static int cdns_dphy_power_off(struct phy *phy)
> +{
> + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> +
> + if (dphy->ops->power_off)
> + return dphy->ops->power_off(dphy);
> +
> + return 0;
> +}
why do you need a dphy specific power_on/off only to call internal
ops..? If there is no additional logic lets drop this and continue the
phy ops for this
--
~Vinod
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support
2021-08-06 10:18 ` Vinod Koul
@ 2021-08-11 17:39 ` Pratyush Yadav
0 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-08-11 17:39 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Chunfeng Yun,
Kishon Vijay Abraham I, Peter Chen, linux-kernel, linux-phy
On 06/08/21 03:48PM, Vinod Koul wrote:
> On 25-06-21, 00:11, Pratyush Yadav wrote:
> > The Rx programming sequence differs from the Tx programming sequence.
> > Currently only Tx mode is supported. Move all the Tx related parts into
> > a set of Tx-specific hooks that are then called by the main PHY
> > framework hooks. This way when Rx support is added all that is needed to
> > be done is to plug in the Rx hooks.
> >
> > The clocks "psm" and "pll_ref" are not used by the Rx path so make them
> > optional in the probe and then check if they exist in the power_on()
> > hook.
> >
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > ---
> >
> > (no changes since v1)
> >
> > drivers/phy/cadence/cdns-dphy.c | 140 ++++++++++++++++++++++++--------
> > 1 file changed, 104 insertions(+), 36 deletions(-)
> >
> > diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
> > index ba042e39cfaf..8656f2102a91 100644
> > --- a/drivers/phy/cadence/cdns-dphy.c
> > +++ b/drivers/phy/cadence/cdns-dphy.c
> > @@ -75,6 +75,11 @@ struct cdns_dphy;
> > struct cdns_dphy_ops {
> > int (*probe)(struct cdns_dphy *dphy);
> > void (*remove)(struct cdns_dphy *dphy);
> > + int (*power_on)(struct cdns_dphy *dphy);
> > + int (*power_off)(struct cdns_dphy *dphy);
> > + int (*validate)(struct cdns_dphy *dphy, enum phy_mode mode, int submode,
> > + union phy_configure_opts *opts);
> > + int (*configure)(struct cdns_dphy *dphy, union phy_configure_opts *opts);
> > void (*set_psm_div)(struct cdns_dphy *dphy, u8 div);
> > void (*set_clk_lane_cfg)(struct cdns_dphy *dphy,
> > enum cdns_dphy_clk_lane_cfg cfg);
> > @@ -86,12 +91,18 @@ struct cdns_dphy_ops {
> > struct cdns_dphy {
> > struct cdns_dphy_cfg cfg;
> > void __iomem *regs;
> > + struct device *dev;
> > struct clk *psm_clk;
> > struct clk *pll_ref_clk;
> > const struct cdns_dphy_ops *ops;
> > struct phy *phy;
> > };
> >
> > +struct cdns_dphy_driver_data {
> > + const struct cdns_dphy_ops *tx;
> > + const struct cdns_dphy_ops *rx;
> > +};
> > +
> > static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
> > struct cdns_dphy_cfg *cfg,
> > struct phy_configure_opts_mipi_dphy *opts,
> > @@ -199,20 +210,9 @@ static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div)
> > dphy->regs + DPHY_PSM_CFG);
> > }
> >
> > -/*
> > - * This is the reference implementation of DPHY hooks. Specific integration of
> > - * this IP may have to re-implement some of them depending on how they decided
> > - * to wire things in the SoC.
> > - */
> > -static const struct cdns_dphy_ops ref_dphy_ops = {
> > - .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
> > - .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
> > - .set_psm_div = cdns_dphy_ref_set_psm_div,
> > -};
> > -
> > -static int cdns_dphy_config_from_opts(struct phy *phy,
> > - struct phy_configure_opts_mipi_dphy *opts,
> > - struct cdns_dphy_cfg *cfg)
> > +static int cdns_dphy_tx_config_from_opts(struct phy *phy,
> > + struct phy_configure_opts_mipi_dphy *opts,
> > + struct cdns_dphy_cfg *cfg)
> > {
> > struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > unsigned int dsi_hfp_ext = 0;
> > @@ -232,24 +232,13 @@ static int cdns_dphy_config_from_opts(struct phy *phy,
> > return 0;
> > }
> >
> > -static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
> > - union phy_configure_opts *opts)
> > +static int cdns_dphy_tx_configure(struct cdns_dphy *dphy,
> > + union phy_configure_opts *opts)
> > {
> > struct cdns_dphy_cfg cfg = { 0 };
> > -
> > - if (mode != PHY_MODE_MIPI_DPHY)
> > - return -EINVAL;
> > -
> > - return cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
> > -}
> > -
> > -static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
> > -{
> > - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > - struct cdns_dphy_cfg cfg = { 0 };
> > int ret;
> >
> > - ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
> > + ret = cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
> > if (ret)
> > return ret;
> >
> > @@ -279,9 +268,21 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
> > return 0;
> > }
> >
> > -static int cdns_dphy_power_on(struct phy *phy)
> > +static int cdns_dphy_tx_validate(struct cdns_dphy *dphy, enum phy_mode mode,
> > + int submode, union phy_configure_opts *opts)
> > {
> > - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > + struct cdns_dphy_cfg cfg = { 0 };
> > +
> > + if (submode != PHY_MIPI_DPHY_SUBMODE_TX)
> > + return -EINVAL;
> > +
> > + return cdns_dphy_tx_config_from_opts(dphy->phy, &opts->mipi_dphy, &cfg);
> > +}
> > +
> > +static int cdns_dphy_tx_power_on(struct cdns_dphy *dphy)
> > +{
> > + if (!dphy->psm_clk || !dphy->pll_ref_clk)
> > + return -EINVAL;
> >
> > clk_prepare_enable(dphy->psm_clk);
> > clk_prepare_enable(dphy->pll_ref_clk);
> > @@ -293,16 +294,77 @@ static int cdns_dphy_power_on(struct phy *phy)
> > return 0;
> > }
> >
> > -static int cdns_dphy_power_off(struct phy *phy)
> > +static int cdns_dphy_tx_power_off(struct cdns_dphy *dphy)
> > {
> > - struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > -
> > clk_disable_unprepare(dphy->pll_ref_clk);
> > clk_disable_unprepare(dphy->psm_clk);
> >
> > return 0;
> > }
> >
> > +static const struct cdns_dphy_ops tx_ref_dphy_ops = {
> > + .power_on = cdns_dphy_tx_power_on,
> > + .power_off = cdns_dphy_tx_power_off,
> > + .validate = cdns_dphy_tx_validate,
> > + .configure = cdns_dphy_tx_configure,
> > + .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns,
> > + .set_pll_cfg = cdns_dphy_ref_set_pll_cfg,
> > + .set_psm_div = cdns_dphy_ref_set_psm_div,
> > +};
> > +
> > +/*
> > + * This is the reference implementation of DPHY hooks. Specific integration of
> > + * this IP may have to re-implement some of them depending on how they decided
> > + * to wire things in the SoC.
> > + */
> > +static const struct cdns_dphy_driver_data ref_dphy_ops = {
> > + .tx = &tx_ref_dphy_ops,
> > +};
> > +
> > +static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
> > + union phy_configure_opts *opts)
> > +{
> > + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > +
> > + if (mode != PHY_MODE_MIPI_DPHY)
> > + return -EINVAL;
> > +
> > + if (dphy->ops->validate)
> > + return dphy->ops->validate(dphy, mode, submode, opts);
> > +
> > + return 0;
> > +}
> > +
> > +static int cdns_dphy_power_on(struct phy *phy)
> > +{
> > + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > +
> > + if (dphy->ops->power_on)
> > + return dphy->ops->power_on(dphy);
> > +
> > + return 0;
> > +}
> > +
> > +static int cdns_dphy_power_off(struct phy *phy)
> > +{
> > + struct cdns_dphy *dphy = phy_get_drvdata(phy);
> > +
> > + if (dphy->ops->power_off)
> > + return dphy->ops->power_off(dphy);
> > +
> > + return 0;
> > +}
>
> why do you need a dphy specific power_on/off only to call internal
> ops..? If there is no additional logic lets drop this and continue the
> phy ops for this
I don't clearly understand what you are trying to say. The internal ops
(dphy->ops) are DPHY-specific. So for example, you might have different
power on/off sequences for Rx and Tx mode DPHYs. You would then
implement different power_on() and power_off() hooks for those and store
them in dphy->ops. How else would you handle this?
>
> --
> ~Vinod
--
Regards,
Pratyush Yadav
Texas Instruments Inc.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 3/7] phy: cdns-dphy: Allow setting mode
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 1/7] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 2/7] phy: cdns-dphy: Prepare for Rx support Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 4/7] phy: cdns-dphy: Add Rx support Pratyush Yadav
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Chunfeng Yun, Kishon Vijay Abraham I, Peter Chen, linux-kernel,
linux-phy
Allow callers to set the PHY mode. The main mode should always be
PHY_MODE_MIPI_DPHY but the submode can either be
PHY_MIPI_DPHY_SUBMODE_RX or PHY_MIPI_DPHY_SUBMODE_TX. Update the ops
based on the requested submode.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
---
(no changes since v1)
drivers/phy/cadence/cdns-dphy.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index 8656f2102a91..7d5f7b333893 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -365,11 +365,41 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
return 0;
}
+static int cdns_dphy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct cdns_dphy *dphy = phy_get_drvdata(phy);
+ const struct cdns_dphy_driver_data *ddata;
+
+ ddata = of_device_get_match_data(dphy->dev);
+ if (!ddata)
+ return -EINVAL;
+
+ if (mode != PHY_MODE_MIPI_DPHY)
+ return -EINVAL;
+
+ if (submode == PHY_MIPI_DPHY_SUBMODE_TX) {
+ if (!ddata->tx)
+ return -EOPNOTSUPP;
+
+ dphy->ops = ddata->tx;
+ } else if (submode == PHY_MIPI_DPHY_SUBMODE_RX) {
+ if (!ddata->rx)
+ return -EOPNOTSUPP;
+
+ dphy->ops = ddata->rx;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static const struct phy_ops cdns_dphy_ops = {
.configure = cdns_dphy_configure,
.validate = cdns_dphy_validate,
.power_on = cdns_dphy_power_on,
.power_off = cdns_dphy_power_off,
+ .set_mode = cdns_dphy_set_mode,
};
static int cdns_dphy_probe(struct platform_device *pdev)
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 4/7] phy: cdns-dphy: Add Rx support
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
` (2 preceding siblings ...)
2021-06-24 18:41 ` [PATCH v3 3/7] phy: cdns-dphy: Allow setting mode Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-08-06 11:15 ` Vinod Koul
2021-06-24 18:41 ` [PATCH v3 5/7] phy: dt-bindings: Convert Cadence DPHY binding to YAML Pratyush Yadav
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Chunfeng Yun, Kishon Vijay Abraham I, Peter Chen, linux-kernel,
linux-phy
The Cadence DPHY can be used to receive image data over the CSI-2
protocol. Add support for Rx mode. The programming sequence differs from
the Tx mode so it is added as a separate set of hooks to isolate the two
paths.
The PHY is in Tx mode by default and it needs to be set in Rx mode by
setting the submode to PHY_MIPI_DPHY_SUBMODE_RX in the set_mode()
callback.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
---
Changes in v3:
- Use a table to select the band.
- Use a table to poll the data lane ready bits.
- Multiply the DPHY HS clock rate by 2 to get the bit rate since the
clock is DDR.
drivers/phy/cadence/cdns-dphy.c | 174 ++++++++++++++++++++++++++++++++
1 file changed, 174 insertions(+)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index 7d5f7b333893..7534ec957dc5 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -1,11 +1,14 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright: 2017-2018 Cadence Design Systems, Inc.
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
*/
#include <linux/bitops.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@@ -25,10 +28,14 @@
#define DPHY_PMA_RCLK(reg) (0x600 + (reg))
#define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
#define DPHY_PCS(reg) (0xb00 + (reg))
+#define DPHY_ISO(reg) (0xc00 + (reg))
#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
#define DPHY_CMN_SSM_EN BIT(0)
+#define DPHY_CMN_RX_BANDGAP_TIMER_MASK GENMASK(8, 1)
#define DPHY_CMN_TX_MODE_EN BIT(9)
+#define DPHY_CMN_RX_MODE_EN BIT(10)
+#define DPHY_CMN_RX_BANDGAP_TIMER 0x14
#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
#define DPHY_CMN_PWM_DIV(x) ((x) << 20)
@@ -45,10 +52,27 @@
#define DPHY_CMN_OPDIV_FROM_REG BIT(6)
#define DPHY_CMN_OPDIV(x) ((x) << 7)
+#define DPHY_BAND_CFG DPHY_PCS(0x0)
+#define DPHY_BAND_CFG_LEFT_BAND GENMASK(4, 0)
+#define DPHY_BAND_CFG_RIGHT_BAND GENMASK(9, 5)
+
#define DPHY_PSM_CFG DPHY_PCS(0x4)
#define DPHY_PSM_CFG_FROM_REG BIT(0)
#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
+#define DPHY_POWER_ISLAND_EN_DATA DPHY_PCS(0x8)
+#define DPHY_POWER_ISLAND_EN_DATA_VAL 0xaaaaaaaa
+#define DPHY_POWER_ISLAND_EN_CLK DPHY_PCS(0xc)
+#define DPHY_POWER_ISLAND_EN_CLK_VAL 0xaa
+
+#define DPHY_ISO_CL_CTRL_L DPHY_ISO(0x10)
+#define DPHY_ISO_DL_CTRL_L0 DPHY_ISO(0x14)
+#define DPHY_ISO_DL_CTRL_L1 DPHY_ISO(0x20)
+#define DPHY_ISO_DL_CTRL_L2 DPHY_ISO(0x30)
+#define DPHY_ISO_DL_CTRL_L3 DPHY_ISO(0x3c)
+#define DPHY_ISO_LANE_READY_BIT 0
+#define DPHY_ISO_LANE_READY_TIMEOUT_MS 100UL
+
#define DSI_HBP_FRAME_OVERHEAD 12
#define DSI_HSA_FRAME_OVERHEAD 14
#define DSI_HFP_FRAME_OVERHEAD 6
@@ -57,6 +81,9 @@
#define DSI_NULL_FRAME_OVERHEAD 6
#define DSI_EOT_PKT_SIZE 4
+#define DPHY_LANES_MIN 1
+#define DPHY_LANES_MAX 4
+
struct cdns_dphy_cfg {
u8 pll_ipdiv;
u8 pll_opdiv;
@@ -103,6 +130,22 @@ struct cdns_dphy_driver_data {
const struct cdns_dphy_ops *rx;
};
+struct cdns_dphy_rx_band {
+ unsigned int min_rate;
+ unsigned int max_rate;
+};
+
+/* Order of bands is important since the index is the band number. */
+struct cdns_dphy_rx_band bands[] = {
+ {80, 100}, {100, 120}, {120, 160}, {160, 200}, {200, 240},
+ {240, 280}, {280, 320}, {320, 360}, {360, 400}, {400, 480},
+ {480, 560}, {560, 640}, {640, 720}, {720, 800}, {800, 880},
+ {880, 1040}, {1040, 1200}, {1200, 1350}, {1350, 1500}, {1500, 1750},
+ {1750, 2000}, {2000, 2250}, {2250, 2500}
+};
+
+int num_bands = ARRAY_SIZE(bands);
+
static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
struct cdns_dphy_cfg *cfg,
struct phy_configure_opts_mipi_dphy *opts,
@@ -312,6 +355,135 @@ static const struct cdns_dphy_ops tx_ref_dphy_ops = {
.set_psm_div = cdns_dphy_ref_set_psm_div,
};
+static int cdns_dphy_rx_power_on(struct cdns_dphy *dphy)
+{
+ /* Start RX state machine. */
+ writel(DPHY_CMN_SSM_EN | DPHY_CMN_RX_MODE_EN |
+ FIELD_PREP(DPHY_CMN_RX_BANDGAP_TIMER_MASK,
+ DPHY_CMN_RX_BANDGAP_TIMER),
+ dphy->regs + DPHY_CMN_SSM);
+
+ return 0;
+}
+
+static int cdns_dphy_rx_power_off(struct cdns_dphy *dphy)
+{
+ writel(0, dphy->regs + DPHY_CMN_SSM);
+
+ return 0;
+}
+
+static int cdns_dphy_rx_get_band_ctrl(unsigned long hs_clk_rate)
+{
+ unsigned int rate;
+ int i;
+
+ rate = hs_clk_rate / 1000000UL;
+ /* Since CSI-2 clock is DDR, the bit rate is twice the clock rate. */
+ rate *= 2;
+
+ if (rate < bands[0].min_rate || rate >= bands[num_bands - 1].max_rate)
+ return -EOPNOTSUPP;
+
+ for (i = 0; i < num_bands; i++) {
+ if (rate >= bands[i].min_rate && rate < bands[i].max_rate)
+ return i;
+ }
+
+ /* Unreachable. */
+ WARN(1, "Reached unreachable code.");
+ return -EINVAL;
+}
+
+static int cdns_dphy_rx_wait_for_bit(void __iomem *addr, unsigned int bit)
+{
+ u32 val;
+
+ return readl_relaxed_poll_timeout(addr, val, val & BIT(bit), 10,
+ DPHY_ISO_LANE_READY_TIMEOUT_MS * 1000);
+}
+
+static int cdns_dphy_rx_wait_lane_ready(struct cdns_dphy *dphy, int lanes)
+{
+ void __iomem *reg = dphy->regs;
+ u32 data_lane_ctrl[] = {DPHY_ISO_DL_CTRL_L0, DPHY_ISO_DL_CTRL_L1,
+ DPHY_ISO_DL_CTRL_L2, DPHY_ISO_DL_CTRL_L3};
+ int ret, i;
+
+ /* Data lanes. Minimum one lane is mandatory. */
+ if (lanes < DPHY_LANES_MIN || lanes > DPHY_LANES_MAX)
+ return -EINVAL;
+
+ /* Clock lane */
+ ret = cdns_dphy_rx_wait_for_bit(reg + DPHY_ISO_CL_CTRL_L,
+ DPHY_ISO_LANE_READY_BIT);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < lanes; i++) {
+ ret = cdns_dphy_rx_wait_for_bit(reg + data_lane_ctrl[i],
+ DPHY_ISO_LANE_READY_BIT);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cdns_dphy_rx_configure(struct cdns_dphy *dphy,
+ union phy_configure_opts *opts)
+{
+ unsigned int reg;
+ int band_ctrl, ret;
+
+ band_ctrl = cdns_dphy_rx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate);
+ if (band_ctrl < 0)
+ return band_ctrl;
+
+ reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, band_ctrl) |
+ FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, band_ctrl);
+ writel(reg, dphy->regs + DPHY_BAND_CFG);
+
+ /*
+ * Set the required power island phase 2 time. This is mandated by DPHY
+ * specs.
+ */
+ reg = DPHY_POWER_ISLAND_EN_DATA_VAL;
+ writel(reg, dphy->regs + DPHY_POWER_ISLAND_EN_DATA);
+ reg = DPHY_POWER_ISLAND_EN_CLK_VAL;
+ writel(reg, dphy->regs + DPHY_POWER_ISLAND_EN_CLK);
+
+ ret = cdns_dphy_rx_wait_lane_ready(dphy, opts->mipi_dphy.lanes);
+ if (ret) {
+ dev_err(dphy->dev, "DPHY wait for lane ready timeout\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cdns_dphy_rx_validate(struct cdns_dphy *dphy, enum phy_mode mode,
+ int submode, union phy_configure_opts *opts)
+{
+ int ret;
+
+ if (submode != PHY_MIPI_DPHY_SUBMODE_RX)
+ return -EINVAL;
+
+ ret = cdns_dphy_rx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate);
+ if (ret < 0)
+ return ret;
+
+ return phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+}
+
+static const struct cdns_dphy_ops rx_ref_dphy_ops = {
+ .power_on = cdns_dphy_rx_power_on,
+ .power_off = cdns_dphy_rx_power_off,
+ .configure = cdns_dphy_rx_configure,
+ .validate = cdns_dphy_rx_validate,
+};
+
/*
* This is the reference implementation of DPHY hooks. Specific integration of
* this IP may have to re-implement some of them depending on how they decided
@@ -319,6 +491,7 @@ static const struct cdns_dphy_ops tx_ref_dphy_ops = {
*/
static const struct cdns_dphy_driver_data ref_dphy_ops = {
.tx = &tx_ref_dphy_ops,
+ .rx = &rx_ref_dphy_ops,
};
static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
@@ -483,5 +656,6 @@ static struct platform_driver cdns_dphy_platform_driver = {
module_platform_driver(cdns_dphy_platform_driver);
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
+MODULE_AUTHOR("Pratyush Yadav <p.yadav@ti.com>");
MODULE_DESCRIPTION("Cadence MIPI D-PHY Driver");
MODULE_LICENSE("GPL");
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 4/7] phy: cdns-dphy: Add Rx support
2021-06-24 18:41 ` [PATCH v3 4/7] phy: cdns-dphy: Add Rx support Pratyush Yadav
@ 2021-08-06 11:15 ` Vinod Koul
2021-08-11 17:33 ` Pratyush Yadav
0 siblings, 1 reply; 14+ messages in thread
From: Vinod Koul @ 2021-08-06 11:15 UTC (permalink / raw)
To: Pratyush Yadav
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Chunfeng Yun,
Kishon Vijay Abraham I, Peter Chen, linux-kernel, linux-phy
On 25-06-21, 00:11, Pratyush Yadav wrote:
> The Cadence DPHY can be used to receive image data over the CSI-2
> protocol. Add support for Rx mode. The programming sequence differs from
> the Tx mode so it is added as a separate set of hooks to isolate the two
> paths.
>
> The PHY is in Tx mode by default and it needs to be set in Rx mode by
> setting the submode to PHY_MIPI_DPHY_SUBMODE_RX in the set_mode()
> callback.
>
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
>
> ---
>
> Changes in v3:
> - Use a table to select the band.
> - Use a table to poll the data lane ready bits.
> - Multiply the DPHY HS clock rate by 2 to get the bit rate since the
> clock is DDR.
>
> drivers/phy/cadence/cdns-dphy.c | 174 ++++++++++++++++++++++++++++++++
> 1 file changed, 174 insertions(+)
>
> diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
> index 7d5f7b333893..7534ec957dc5 100644
> --- a/drivers/phy/cadence/cdns-dphy.c
> +++ b/drivers/phy/cadence/cdns-dphy.c
> @@ -1,11 +1,14 @@
> // SPDX-License-Identifier: GPL-2.0+
> /*
> * Copyright: 2017-2018 Cadence Design Systems, Inc.
> + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
> */
>
> #include <linux/bitops.h>
> +#include <linux/bitfield.h>
> #include <linux/clk.h>
> #include <linux/io.h>
> +#include <linux/iopoll.h>
> #include <linux/module.h>
> #include <linux/of_address.h>
> #include <linux/of_device.h>
> @@ -25,10 +28,14 @@
> #define DPHY_PMA_RCLK(reg) (0x600 + (reg))
> #define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
> #define DPHY_PCS(reg) (0xb00 + (reg))
> +#define DPHY_ISO(reg) (0xc00 + (reg))
>
> #define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
> #define DPHY_CMN_SSM_EN BIT(0)
> +#define DPHY_CMN_RX_BANDGAP_TIMER_MASK GENMASK(8, 1)
> #define DPHY_CMN_TX_MODE_EN BIT(9)
> +#define DPHY_CMN_RX_MODE_EN BIT(10)
> +#define DPHY_CMN_RX_BANDGAP_TIMER 0x14
>
> #define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
> #define DPHY_CMN_PWM_DIV(x) ((x) << 20)
> @@ -45,10 +52,27 @@
> #define DPHY_CMN_OPDIV_FROM_REG BIT(6)
> #define DPHY_CMN_OPDIV(x) ((x) << 7)
>
> +#define DPHY_BAND_CFG DPHY_PCS(0x0)
> +#define DPHY_BAND_CFG_LEFT_BAND GENMASK(4, 0)
> +#define DPHY_BAND_CFG_RIGHT_BAND GENMASK(9, 5)
> +
> #define DPHY_PSM_CFG DPHY_PCS(0x4)
> #define DPHY_PSM_CFG_FROM_REG BIT(0)
> #define DPHY_PSM_CLK_DIV(x) ((x) << 1)
>
> +#define DPHY_POWER_ISLAND_EN_DATA DPHY_PCS(0x8)
> +#define DPHY_POWER_ISLAND_EN_DATA_VAL 0xaaaaaaaa
> +#define DPHY_POWER_ISLAND_EN_CLK DPHY_PCS(0xc)
> +#define DPHY_POWER_ISLAND_EN_CLK_VAL 0xaa
> +
> +#define DPHY_ISO_CL_CTRL_L DPHY_ISO(0x10)
> +#define DPHY_ISO_DL_CTRL_L0 DPHY_ISO(0x14)
> +#define DPHY_ISO_DL_CTRL_L1 DPHY_ISO(0x20)
> +#define DPHY_ISO_DL_CTRL_L2 DPHY_ISO(0x30)
> +#define DPHY_ISO_DL_CTRL_L3 DPHY_ISO(0x3c)
> +#define DPHY_ISO_LANE_READY_BIT 0
> +#define DPHY_ISO_LANE_READY_TIMEOUT_MS 100UL
> +
> #define DSI_HBP_FRAME_OVERHEAD 12
> #define DSI_HSA_FRAME_OVERHEAD 14
> #define DSI_HFP_FRAME_OVERHEAD 6
> @@ -57,6 +81,9 @@
> #define DSI_NULL_FRAME_OVERHEAD 6
> #define DSI_EOT_PKT_SIZE 4
>
> +#define DPHY_LANES_MIN 1
> +#define DPHY_LANES_MAX 4
> +
> struct cdns_dphy_cfg {
> u8 pll_ipdiv;
> u8 pll_opdiv;
> @@ -103,6 +130,22 @@ struct cdns_dphy_driver_data {
> const struct cdns_dphy_ops *rx;
> };
>
> +struct cdns_dphy_rx_band {
> + unsigned int min_rate;
> + unsigned int max_rate;
> +};
> +
> +/* Order of bands is important since the index is the band number. */
> +struct cdns_dphy_rx_band bands[] = {
> + {80, 100}, {100, 120}, {120, 160}, {160, 200}, {200, 240},
> + {240, 280}, {280, 320}, {320, 360}, {360, 400}, {400, 480},
> + {480, 560}, {560, 640}, {640, 720}, {720, 800}, {800, 880},
> + {880, 1040}, {1040, 1200}, {1200, 1350}, {1350, 1500}, {1500, 1750},
> + {1750, 2000}, {2000, 2250}, {2250, 2500}
> +};
> +
> +int num_bands = ARRAY_SIZE(bands);
> +
> static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
> struct cdns_dphy_cfg *cfg,
> struct phy_configure_opts_mipi_dphy *opts,
> @@ -312,6 +355,135 @@ static const struct cdns_dphy_ops tx_ref_dphy_ops = {
> .set_psm_div = cdns_dphy_ref_set_psm_div,
> };
>
> +static int cdns_dphy_rx_power_on(struct cdns_dphy *dphy)
> +{
> + /* Start RX state machine. */
> + writel(DPHY_CMN_SSM_EN | DPHY_CMN_RX_MODE_EN |
> + FIELD_PREP(DPHY_CMN_RX_BANDGAP_TIMER_MASK,
> + DPHY_CMN_RX_BANDGAP_TIMER),
> + dphy->regs + DPHY_CMN_SSM);
> +
> + return 0;
> +}
> +
> +static int cdns_dphy_rx_power_off(struct cdns_dphy *dphy)
> +{
> + writel(0, dphy->regs + DPHY_CMN_SSM);
> +
> + return 0;
> +}
> +
> +static int cdns_dphy_rx_get_band_ctrl(unsigned long hs_clk_rate)
> +{
> + unsigned int rate;
> + int i;
> +
> + rate = hs_clk_rate / 1000000UL;
> + /* Since CSI-2 clock is DDR, the bit rate is twice the clock rate. */
> + rate *= 2;
> +
> + if (rate < bands[0].min_rate || rate >= bands[num_bands - 1].max_rate)
> + return -EOPNOTSUPP;
> +
> + for (i = 0; i < num_bands; i++) {
> + if (rate >= bands[i].min_rate && rate < bands[i].max_rate)
> + return i;
> + }
> +
> + /* Unreachable. */
> + WARN(1, "Reached unreachable code.");
> + return -EINVAL;
> +}
> +
> +static int cdns_dphy_rx_wait_for_bit(void __iomem *addr, unsigned int bit)
> +{
> + u32 val;
> +
> + return readl_relaxed_poll_timeout(addr, val, val & BIT(bit), 10,
> + DPHY_ISO_LANE_READY_TIMEOUT_MS * 1000);
this looks wrong, val is not initialized, so what/when is condition to
be met..?
--
~Vinod
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 4/7] phy: cdns-dphy: Add Rx support
2021-08-06 11:15 ` Vinod Koul
@ 2021-08-11 17:33 ` Pratyush Yadav
0 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-08-11 17:33 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Chunfeng Yun,
Kishon Vijay Abraham I, Peter Chen, linux-kernel, linux-phy
On 06/08/21 04:45PM, Vinod Koul wrote:
> On 25-06-21, 00:11, Pratyush Yadav wrote:
> > The Cadence DPHY can be used to receive image data over the CSI-2
> > protocol. Add support for Rx mode. The programming sequence differs from
> > the Tx mode so it is added as a separate set of hooks to isolate the two
> > paths.
> >
> > The PHY is in Tx mode by default and it needs to be set in Rx mode by
> > setting the submode to PHY_MIPI_DPHY_SUBMODE_RX in the set_mode()
> > callback.
> >
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> >
> > ---
> >
> > Changes in v3:
> > - Use a table to select the band.
> > - Use a table to poll the data lane ready bits.
> > - Multiply the DPHY HS clock rate by 2 to get the bit rate since the
> > clock is DDR.
> >
> > drivers/phy/cadence/cdns-dphy.c | 174 ++++++++++++++++++++++++++++++++
> > 1 file changed, 174 insertions(+)
> >
> > diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
> > index 7d5f7b333893..7534ec957dc5 100644
> > --- a/drivers/phy/cadence/cdns-dphy.c
> > +++ b/drivers/phy/cadence/cdns-dphy.c
> > @@ -1,11 +1,14 @@
> > // SPDX-License-Identifier: GPL-2.0+
> > /*
> > * Copyright: 2017-2018 Cadence Design Systems, Inc.
> > + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
> > */
> >
> > #include <linux/bitops.h>
> > +#include <linux/bitfield.h>
> > #include <linux/clk.h>
> > #include <linux/io.h>
> > +#include <linux/iopoll.h>
> > #include <linux/module.h>
> > #include <linux/of_address.h>
> > #include <linux/of_device.h>
> > @@ -25,10 +28,14 @@
> > #define DPHY_PMA_RCLK(reg) (0x600 + (reg))
> > #define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg))
> > #define DPHY_PCS(reg) (0xb00 + (reg))
> > +#define DPHY_ISO(reg) (0xc00 + (reg))
> >
> > #define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
> > #define DPHY_CMN_SSM_EN BIT(0)
> > +#define DPHY_CMN_RX_BANDGAP_TIMER_MASK GENMASK(8, 1)
> > #define DPHY_CMN_TX_MODE_EN BIT(9)
> > +#define DPHY_CMN_RX_MODE_EN BIT(10)
> > +#define DPHY_CMN_RX_BANDGAP_TIMER 0x14
> >
> > #define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
> > #define DPHY_CMN_PWM_DIV(x) ((x) << 20)
> > @@ -45,10 +52,27 @@
> > #define DPHY_CMN_OPDIV_FROM_REG BIT(6)
> > #define DPHY_CMN_OPDIV(x) ((x) << 7)
> >
> > +#define DPHY_BAND_CFG DPHY_PCS(0x0)
> > +#define DPHY_BAND_CFG_LEFT_BAND GENMASK(4, 0)
> > +#define DPHY_BAND_CFG_RIGHT_BAND GENMASK(9, 5)
> > +
> > #define DPHY_PSM_CFG DPHY_PCS(0x4)
> > #define DPHY_PSM_CFG_FROM_REG BIT(0)
> > #define DPHY_PSM_CLK_DIV(x) ((x) << 1)
> >
> > +#define DPHY_POWER_ISLAND_EN_DATA DPHY_PCS(0x8)
> > +#define DPHY_POWER_ISLAND_EN_DATA_VAL 0xaaaaaaaa
> > +#define DPHY_POWER_ISLAND_EN_CLK DPHY_PCS(0xc)
> > +#define DPHY_POWER_ISLAND_EN_CLK_VAL 0xaa
> > +
> > +#define DPHY_ISO_CL_CTRL_L DPHY_ISO(0x10)
> > +#define DPHY_ISO_DL_CTRL_L0 DPHY_ISO(0x14)
> > +#define DPHY_ISO_DL_CTRL_L1 DPHY_ISO(0x20)
> > +#define DPHY_ISO_DL_CTRL_L2 DPHY_ISO(0x30)
> > +#define DPHY_ISO_DL_CTRL_L3 DPHY_ISO(0x3c)
> > +#define DPHY_ISO_LANE_READY_BIT 0
> > +#define DPHY_ISO_LANE_READY_TIMEOUT_MS 100UL
> > +
> > #define DSI_HBP_FRAME_OVERHEAD 12
> > #define DSI_HSA_FRAME_OVERHEAD 14
> > #define DSI_HFP_FRAME_OVERHEAD 6
> > @@ -57,6 +81,9 @@
> > #define DSI_NULL_FRAME_OVERHEAD 6
> > #define DSI_EOT_PKT_SIZE 4
> >
> > +#define DPHY_LANES_MIN 1
> > +#define DPHY_LANES_MAX 4
> > +
> > struct cdns_dphy_cfg {
> > u8 pll_ipdiv;
> > u8 pll_opdiv;
> > @@ -103,6 +130,22 @@ struct cdns_dphy_driver_data {
> > const struct cdns_dphy_ops *rx;
> > };
> >
> > +struct cdns_dphy_rx_band {
> > + unsigned int min_rate;
> > + unsigned int max_rate;
> > +};
> > +
> > +/* Order of bands is important since the index is the band number. */
> > +struct cdns_dphy_rx_band bands[] = {
> > + {80, 100}, {100, 120}, {120, 160}, {160, 200}, {200, 240},
> > + {240, 280}, {280, 320}, {320, 360}, {360, 400}, {400, 480},
> > + {480, 560}, {560, 640}, {640, 720}, {720, 800}, {800, 880},
> > + {880, 1040}, {1040, 1200}, {1200, 1350}, {1350, 1500}, {1500, 1750},
> > + {1750, 2000}, {2000, 2250}, {2250, 2500}
> > +};
> > +
> > +int num_bands = ARRAY_SIZE(bands);
> > +
> > static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
> > struct cdns_dphy_cfg *cfg,
> > struct phy_configure_opts_mipi_dphy *opts,
> > @@ -312,6 +355,135 @@ static const struct cdns_dphy_ops tx_ref_dphy_ops = {
> > .set_psm_div = cdns_dphy_ref_set_psm_div,
> > };
> >
> > +static int cdns_dphy_rx_power_on(struct cdns_dphy *dphy)
> > +{
> > + /* Start RX state machine. */
> > + writel(DPHY_CMN_SSM_EN | DPHY_CMN_RX_MODE_EN |
> > + FIELD_PREP(DPHY_CMN_RX_BANDGAP_TIMER_MASK,
> > + DPHY_CMN_RX_BANDGAP_TIMER),
> > + dphy->regs + DPHY_CMN_SSM);
> > +
> > + return 0;
> > +}
> > +
> > +static int cdns_dphy_rx_power_off(struct cdns_dphy *dphy)
> > +{
> > + writel(0, dphy->regs + DPHY_CMN_SSM);
> > +
> > + return 0;
> > +}
> > +
> > +static int cdns_dphy_rx_get_band_ctrl(unsigned long hs_clk_rate)
> > +{
> > + unsigned int rate;
> > + int i;
> > +
> > + rate = hs_clk_rate / 1000000UL;
> > + /* Since CSI-2 clock is DDR, the bit rate is twice the clock rate. */
> > + rate *= 2;
> > +
> > + if (rate < bands[0].min_rate || rate >= bands[num_bands - 1].max_rate)
> > + return -EOPNOTSUPP;
> > +
> > + for (i = 0; i < num_bands; i++) {
> > + if (rate >= bands[i].min_rate && rate < bands[i].max_rate)
> > + return i;
> > + }
> > +
> > + /* Unreachable. */
> > + WARN(1, "Reached unreachable code.");
> > + return -EINVAL;
> > +}
> > +
> > +static int cdns_dphy_rx_wait_for_bit(void __iomem *addr, unsigned int bit)
> > +{
> > + u32 val;
> > +
> > + return readl_relaxed_poll_timeout(addr, val, val & BIT(bit), 10,
> > + DPHY_ISO_LANE_READY_TIMEOUT_MS * 1000);
>
> this looks wrong, val is not initialized, so what/when is condition to
> be met..?
The readl_relaxed_poll_timeout() macro puts the value returned by
readl() into val. That value is then used for testing the condition. See
read_poll_timeout() in iopoll.h to see what the macro eventually expands
to.
> --
> ~Vinod
--
Regards,
Pratyush Yadav
Texas Instruments Inc.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 5/7] phy: dt-bindings: Convert Cadence DPHY binding to YAML
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
` (3 preceding siblings ...)
2021-06-24 18:41 ` [PATCH v3 4/7] phy: cdns-dphy: Add Rx support Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 6/7] phy: dt-bindings: cdns,dphy: make clocks optional Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 7/7] phy: dt-bindings: cdns,dphy: add power-domains property Pratyush Yadav
6 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Kishon Vijay Abraham I, Rob Herring, devicetree, linux-kernel,
linux-phy
Convert Cadence DPHY binding to YAML.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v3:
- Add Rob's R-by.
Changes in v2:
- Drop reg description.
- Add a description for each DPHY clock.
- Rename dphy@... to phy@... in example.
- Add Laurent's R-by.
- Re-order subject prefixes.
.../devicetree/bindings/phy/cdns,dphy.txt | 20 --------
.../devicetree/bindings/phy/cdns,dphy.yaml | 51 +++++++++++++++++++
2 files changed, 51 insertions(+), 20 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/phy/cdns,dphy.txt
create mode 100644 Documentation/devicetree/bindings/phy/cdns,dphy.yaml
diff --git a/Documentation/devicetree/bindings/phy/cdns,dphy.txt b/Documentation/devicetree/bindings/phy/cdns,dphy.txt
deleted file mode 100644
index 1095bc4e72d9..000000000000
--- a/Documentation/devicetree/bindings/phy/cdns,dphy.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Cadence DPHY
-============
-
-Cadence DPHY block.
-
-Required properties:
-- compatible: should be set to "cdns,dphy".
-- reg: physical base address and length of the DPHY registers.
-- clocks: DPHY reference clocks.
-- clock-names: must contain "psm" and "pll_ref".
-- #phy-cells: must be set to 0.
-
-Example:
- dphy0: dphy@fd0e0000{
- compatible = "cdns,dphy";
- reg = <0x0 0xfd0e0000 0x0 0x1000>;
- clocks = <&psm_clk>, <&pll_ref_clk>;
- clock-names = "psm", "pll_ref";
- #phy-cells = <0>;
- };
diff --git a/Documentation/devicetree/bindings/phy/cdns,dphy.yaml b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
new file mode 100644
index 000000000000..b90a58773bf2
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/cdns,dphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cadence DPHY Device Tree Bindings
+
+maintainers:
+ - Pratyush Yadav <p.yadav@ti.com>
+
+properties:
+ compatible:
+ items:
+ - const: cdns,dphy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: PMA state machine clock
+ - description: PLL reference clock
+
+ clock-names:
+ items:
+ - const: psm
+ - const: pll_ref
+
+ "#phy-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+
+ dphy0: phy@fd0e0000{
+ compatible = "cdns,dphy";
+ reg = <0xfd0e0000 0x1000>;
+ clocks = <&psm_clk>, <&pll_ref_clk>;
+ clock-names = "psm", "pll_ref";
+ #phy-cells = <0>;
+ };
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 6/7] phy: dt-bindings: cdns,dphy: make clocks optional
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
` (4 preceding siblings ...)
2021-06-24 18:41 ` [PATCH v3 5/7] phy: dt-bindings: Convert Cadence DPHY binding to YAML Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
2021-06-24 18:41 ` [PATCH v3 7/7] phy: dt-bindings: cdns,dphy: add power-domains property Pratyush Yadav
6 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Kishon Vijay Abraham I, Rob Herring, devicetree, linux-kernel,
linux-phy
The clocks are not used by the DPHY when used in Rx mode so make them
optional.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes in v3:
- Add Rob's Ack.
Changes in v2:
- Re-order subject prefixes.
Documentation/devicetree/bindings/phy/cdns,dphy.yaml | 2 --
1 file changed, 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/cdns,dphy.yaml b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
index b90a58773bf2..3bb5be05e825 100644
--- a/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
+++ b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
@@ -33,8 +33,6 @@ properties:
required:
- compatible
- reg
- - clocks
- - clock-names
- "#phy-cells"
additionalProperties: false
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 7/7] phy: dt-bindings: cdns,dphy: add power-domains property
2021-06-24 18:41 [PATCH v3 0/7] Rx mode support for Cadence DPHY Pratyush Yadav
` (5 preceding siblings ...)
2021-06-24 18:41 ` [PATCH v3 6/7] phy: dt-bindings: cdns,dphy: make clocks optional Pratyush Yadav
@ 2021-06-24 18:41 ` Pratyush Yadav
6 siblings, 0 replies; 14+ messages in thread
From: Pratyush Yadav @ 2021-06-24 18:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Nikhil Devshatwar, Tomi Valkeinen, Laurent Pinchart,
Paul Kocialkowski, Vignesh Raghavendra, Pratyush Yadav,
Kishon Vijay Abraham I, Rob Herring, devicetree, linux-kernel,
linux-phy
This property is needed on TI platforms to enable the PD of the DPHY
before it can be used.
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes in v3:
- Add Rob's Ack.
Changes in v2:
- Add power-domain to the example.
- Add Laurent's R-by.
- Re-order subject prefixes.
Documentation/devicetree/bindings/phy/cdns,dphy.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/cdns,dphy.yaml b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
index 3bb5be05e825..d5a5e1f0b671 100644
--- a/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
+++ b/Documentation/devicetree/bindings/phy/cdns,dphy.yaml
@@ -30,6 +30,9 @@ properties:
"#phy-cells":
const: 0
+ power-domains:
+ maxItems: 1
+
required:
- compatible
- reg
@@ -39,11 +42,13 @@ additionalProperties: false
examples:
- |
+ #include <dt-bindings/soc/ti,sci_pm_domain.h>
dphy0: phy@fd0e0000{
compatible = "cdns,dphy";
reg = <0xfd0e0000 0x1000>;
clocks = <&psm_clk>, <&pll_ref_clk>;
clock-names = "psm", "pll_ref";
+ power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
#phy-cells = <0>;
};
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread