linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] phy: amlogic: add MIPI DSI function to analog MIPI+PCIe PHY
@ 2020-09-15 13:03 Neil Armstrong
  2020-09-15 13:03 ` [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute Neil Armstrong
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Neil Armstrong @ 2020-09-15 13:03 UTC (permalink / raw)
  To: kishon, repk
  Cc: linux-amlogic, linux-arm-kernel, linux-kernel, Neil Armstrong

The AXG Analog MIPI-DSI PHY also provides functions to the PCIe PHY,
thus we need to have inclusive support for both interfaces at runtime.

This fixes the regmap get from parent node, removes cell param
to select a mode and implement runtime configuration & power on/off
for both functions since they are not exclusive.

Changes since v1 at [1]:
- added description to binding as requested parent
- updated commit log of patch 1
- also update example of patch 1

[1] https://lkml.kernel.org/r/20200907073402.26674-1-narmstrong@baylibre.com

Neil Armstrong (3):
  dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg
    attribute
  dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell
    parameter
  phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI
    analog

 .../amlogic,meson-axg-mipi-pcie-analog.yaml   |  21 +-
 drivers/phy/amlogic/Kconfig                   |   1 +
 .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 204 ++++++++++++------
 3 files changed, 149 insertions(+), 77 deletions(-)

-- 
2.22.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute
  2020-09-15 13:03 [PATCH v2 0/3] phy: amlogic: add MIPI DSI function to analog MIPI+PCIe PHY Neil Armstrong
@ 2020-09-15 13:03 ` Neil Armstrong
  2020-09-23  1:31   ` [PATCH v2 1/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: " Rob Herring
  2020-09-15 13:03 ` [PATCH v2 2/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell parameter Neil Armstrong
  2020-09-15 13:03 ` [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog Neil Armstrong
  2 siblings, 1 reply; 8+ messages in thread
From: Neil Armstrong @ 2020-09-15 13:03 UTC (permalink / raw)
  To: kishon, repk, devicetree
  Cc: linux-amlogic, linux-arm-kernel, linux-kernel, Neil Armstrong

The PHY registers happens to be at the beginning of a large zone containing
interleaved system registers (mainly clocks, power management, PHY control..),
found in all Amlogic SoC so far.

The goal is to model it the same way as the other "features" of this zone,
like Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
and Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
and have a coherent bindings scheme over the Amlogic SoCs.

This update the description, removed the reg attribute then updates the example
accordingly.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../phy/amlogic,meson-axg-mipi-pcie-analog.yaml | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
index 18c1ec5e19ad..702763a84dac 100644
--- a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
+++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
@@ -9,27 +9,32 @@ title: Amlogic AXG shared MIPI/PCIE analog PHY
 maintainers:
   - Remi Pommarel <repk@triplefau.lt>
 
+description: |+
+  The Everything-Else Power Domains node should be the child of a syscon
+  node with the required property:
+
+  - compatible: Should be the following:
+                "amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon"
+
+  Refer to the the bindings described in
+  Documentation/devicetree/bindings/mfd/syscon.yaml
+
 properties:
   compatible:
     const: amlogic,axg-mipi-pcie-analog-phy
 
-  reg:
-    maxItems: 1
-
   "#phy-cells":
     const: 1
 
 required:
   - compatible
-  - reg
   - "#phy-cells"
 
 additionalProperties: false
 
 examples:
   - |
-    mpphy: phy@0 {
+    mpphy: phy {
           compatible = "amlogic,axg-mipi-pcie-analog-phy";
-          reg = <0x0 0xc>;
           #phy-cells = <1>;
     };
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell parameter
  2020-09-15 13:03 [PATCH v2 0/3] phy: amlogic: add MIPI DSI function to analog MIPI+PCIe PHY Neil Armstrong
  2020-09-15 13:03 ` [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute Neil Armstrong
@ 2020-09-15 13:03 ` Neil Armstrong
  2020-09-22 19:35   ` [PATCH v2 2/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: " Rob Herring
  2020-09-15 13:03 ` [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog Neil Armstrong
  2 siblings, 1 reply; 8+ messages in thread
From: Neil Armstrong @ 2020-09-15 13:03 UTC (permalink / raw)
  To: kishon, repk, devicetree
  Cc: linux-amlogic, linux-arm-kernel, linux-kernel, Neil Armstrong

The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
MIPI DSI at the same time, and is not exclusive.

Thus remove the invalid phy cell parameter.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml      | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
index 702763a84dac..4d01f3124e1c 100644
--- a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
+++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml
@@ -24,7 +24,7 @@ properties:
     const: amlogic,axg-mipi-pcie-analog-phy
 
   "#phy-cells":
-    const: 1
+    const: 0
 
 required:
   - compatible
@@ -36,5 +36,5 @@ examples:
   - |
     mpphy: phy {
           compatible = "amlogic,axg-mipi-pcie-analog-phy";
-          #phy-cells = <1>;
+          #phy-cells = <0>;
     };
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog
  2020-09-15 13:03 [PATCH v2 0/3] phy: amlogic: add MIPI DSI function to analog MIPI+PCIe PHY Neil Armstrong
  2020-09-15 13:03 ` [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute Neil Armstrong
  2020-09-15 13:03 ` [PATCH v2 2/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell parameter Neil Armstrong
@ 2020-09-15 13:03 ` Neil Armstrong
  2020-09-29  9:25   ` Neil Armstrong
  2 siblings, 1 reply; 8+ messages in thread
From: Neil Armstrong @ 2020-09-15 13:03 UTC (permalink / raw)
  To: kishon, repk
  Cc: linux-amlogic, linux-arm-kernel, linux-kernel, Neil Armstrong

The AXG Analog MIPI-DSI PHY also provides functions to the PCIe PHY,
thus we need to have inclusive support for both interfaces at runtime.

This fixes the regmap get from parent node, removes cell param
to select a mode and implement runtime configuration & power on/off
for both functions since they are not exclusive.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Remi Pommarel <repk@triplefau.lt>
---
 drivers/phy/amlogic/Kconfig                   |   1 +
 .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 204 ++++++++++++------
 2 files changed, 136 insertions(+), 69 deletions(-)

diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
index 99e8a4c7f1f3..db5d0cd757e3 100644
--- a/drivers/phy/amlogic/Kconfig
+++ b/drivers/phy/amlogic/Kconfig
@@ -66,6 +66,7 @@ config PHY_MESON_AXG_MIPI_PCIE_ANALOG
 	depends on OF && (ARCH_MESON || COMPILE_TEST)
 	select GENERIC_PHY
 	select REGMAP_MMIO
+	select GENERIC_PHY_MIPI_DPHY
 	help
 	  Enable this to support the Meson MIPI + PCIE analog PHY
 	  found in Meson AXG SoCs.
diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
index 1431cbf885e1..6eb21551bdd9 100644
--- a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
+++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
@@ -4,9 +4,13 @@
  *
  * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
  */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
 #include <dt-bindings/phy/phy.h>
 
@@ -14,10 +18,10 @@
 #define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
 #define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
 #define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
-#define		HHI_MIPI_CNTL0_DECODE_TO_RTERM	GENMASK(15, 12)
-#define		HHI_MIPI_CNTL0_OUTPUT_EN	BIT(3)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL1	GENMASK(25, 16)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL0	GENMASK(15, 0)
 
-#define HHI_MIPI_CNTL1 0x01
+#define HHI_MIPI_CNTL1 0x04
 #define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
 #define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
 #define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
@@ -25,100 +29,170 @@
 #define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
 #define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
 
-#define HHI_MIPI_CNTL2 0x02
+#define HHI_MIPI_CNTL2 0x08
 #define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
 #define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
 #define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
 #define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
 #define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
-#define		HHI_MIPI_CNTL2_CH_EN(n)		BIT(15 - (n))
+#define		HHI_MIPI_CNTL2_CH_EN		GENMASK(15, 11)
 #define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
 
+#define DSI_LANE_0              (1 << 4)
+#define DSI_LANE_1              (1 << 3)
+#define DSI_LANE_CLK            (1 << 2)
+#define DSI_LANE_2              (1 << 1)
+#define DSI_LANE_3              (1 << 0)
+#define DSI_LANE_MASK		(0x1F)
+
 struct phy_axg_mipi_pcie_analog_priv {
 	struct phy *phy;
-	unsigned int mode;
 	struct regmap *regmap;
+	bool dsi_configured;
+	bool dsi_enabled;
+	bool powered;
+	struct phy_configure_opts_mipi_dphy config;
 };
 
-static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
-	.reg_bits = 8,
-	.val_bits = 32,
-	.reg_stride = 4,
-	.max_register = HHI_MIPI_CNTL2,
-};
+static void phy_bandgap_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
 
-static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
+}
+
+static void phy_bandgap_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
 {
-	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, 0);
+}
 
-	/* MIPI not supported yet */
-	if (priv->mode != PHY_TYPE_PCIE)
-		return -EINVAL;
+static void phy_dsi_analog_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
+	u32 reg;
 
 	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
-			   HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
+			   HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   BIT(31), BIT(31));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_DIF_REF_CTL0,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2,
+		     (0x26e0 << 16) | (0x459 << 0));
+
+	reg = DSI_LANE_CLK;
+	switch (priv->config.lanes) {
+	case 4:
+		reg |= DSI_LANE_3;
+		fallthrough;
+	case 3:
+		reg |= DSI_LANE_2;
+		fallthrough;
+	case 2:
+		reg |= DSI_LANE_1;
+		fallthrough;
+	case 1:
+		reg |= DSI_LANE_0;
+		break;
+	default:
+		reg = 0;
+	}
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
+			   HHI_MIPI_CNTL2_CH_EN,
+			   FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
+
+	priv->dsi_enabled = true;
+}
 
+static void phy_dsi_analog_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
 	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
-			   HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
-	return 0;
+			HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
+
+	priv->dsi_enabled = false;
 }
 
-static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_configure(struct phy *phy,
+					      union phy_configure_opts *opts)
 {
 	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+	int ret;
 
-	/* MIPI not supported yet */
-	if (priv->mode != PHY_TYPE_PCIE)
-		return -EINVAL;
+	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+	if (ret)
+		return ret;
+
+	memcpy(&priv->config, opts, sizeof(priv->config));
+
+	priv->dsi_configured = true;
+
+	/* If PHY was already powered on, setup the DSI analog part */
+	if (priv->powered) {
+		/* If reconfiguring, disable & reconfigure */
+		if (priv->dsi_enabled)
+			phy_dsi_analog_disable(priv);
+
+		usleep_range(100, 200);
+
+		phy_dsi_analog_enable(priv);
+	}
 
-	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
-			   HHI_MIPI_CNTL0_BANDGAP, 0);
-	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
-			   HHI_MIPI_CNTL0_ENABLE, 0);
 	return 0;
 }
 
-static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
 {
+	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+	phy_bandgap_enable(priv);
+
+	if (priv->dsi_configured)
+		phy_dsi_analog_enable(priv);
+
+	priv->powered = true;
+
 	return 0;
 }
 
-static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
 {
+	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+	phy_bandgap_disable(priv);
+
+	if (priv->dsi_enabled)
+		phy_dsi_analog_disable(priv);
+
+	priv->powered = false;
+
 	return 0;
 }
 
 static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
-	.init = phy_axg_mipi_pcie_analog_init,
-	.exit = phy_axg_mipi_pcie_analog_exit,
+	.configure = phy_axg_mipi_pcie_analog_configure,
 	.power_on = phy_axg_mipi_pcie_analog_power_on,
 	.power_off = phy_axg_mipi_pcie_analog_power_off,
 	.owner = THIS_MODULE,
 };
 
-static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
-						  struct of_phandle_args *args)
-{
-	struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
-	unsigned int mode;
-
-	if (args->args_count != 1) {
-		dev_err(dev, "invalid number of arguments\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	mode = args->args[0];
-
-	/* MIPI mode is not supported yet */
-	if (mode != PHY_TYPE_PCIE) {
-		dev_err(dev, "invalid phy mode select argument\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	priv->mode = mode;
-	return priv->phy;
-}
-
 static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
 {
 	struct phy_provider *phy;
@@ -126,27 +200,20 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
 	struct phy_axg_mipi_pcie_analog_priv *priv;
 	struct device_node *np = dev->of_node;
 	struct regmap *map;
-	struct resource *res;
-	void __iomem *base;
 	int ret;
 
 	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base)) {
-		dev_err(dev, "failed to get regmap base\n");
-		return PTR_ERR(base);
-	}
-
-	map = devm_regmap_init_mmio(dev, base,
-				    &phy_axg_mipi_pcie_analog_regmap_conf);
+	/* Get the hhi system controller node */
+	map = syscon_node_to_regmap(of_get_parent(dev->of_node));
 	if (IS_ERR(map)) {
-		dev_err(dev, "failed to get HHI regmap\n");
+		dev_err(dev,
+			"failed to get HHI regmap\n");
 		return PTR_ERR(map);
 	}
+
 	priv->regmap = map;
 
 	priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
@@ -160,8 +227,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
 	phy_set_drvdata(priv->phy, priv);
 	dev_set_drvdata(dev, priv);
 
-	phy = devm_of_phy_provider_register(dev,
-					    phy_axg_mipi_pcie_analog_xlate);
+	phy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 
 	return PTR_ERR_OR_ZERO(phy);
 }
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: remove phy cell parameter
  2020-09-15 13:03 ` [PATCH v2 2/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell parameter Neil Armstrong
@ 2020-09-22 19:35   ` Rob Herring
  0 siblings, 0 replies; 8+ messages in thread
From: Rob Herring @ 2020-09-22 19:35 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: repk, linux-kernel, linux-arm-kernel, linux-amlogic, kishon, devicetree

On Tue, 15 Sep 2020 15:03:38 +0200, Neil Armstrong wrote:
> The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
> MIPI DSI at the same time, and is not exclusive.
> 
> Thus remove the invalid phy cell parameter.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml      | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: remove reg attribute
  2020-09-15 13:03 ` [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute Neil Armstrong
@ 2020-09-23  1:31   ` Rob Herring
  0 siblings, 0 replies; 8+ messages in thread
From: Rob Herring @ 2020-09-23  1:31 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: devicetree, linux-arm-kernel, kishon, repk, linux-amlogic, linux-kernel

On Tue, 15 Sep 2020 15:03:37 +0200, Neil Armstrong wrote:
> The PHY registers happens to be at the beginning of a large zone containing
> interleaved system registers (mainly clocks, power management, PHY control..),
> found in all Amlogic SoC so far.
> 
> The goal is to model it the same way as the other "features" of this zone,
> like Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
> and Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
> and have a coherent bindings scheme over the Amlogic SoCs.
> 
> This update the description, removed the reg attribute then updates the example
> accordingly.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../phy/amlogic,meson-axg-mipi-pcie-analog.yaml | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog
  2020-09-15 13:03 ` [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog Neil Armstrong
@ 2020-09-29  9:25   ` Neil Armstrong
  2020-10-20 23:10     ` Kevin Hilman
  0 siblings, 1 reply; 8+ messages in thread
From: Neil Armstrong @ 2020-09-29  9:25 UTC (permalink / raw)
  To: kishon, repk; +Cc: linux-amlogic, linux-arm-kernel, linux-kernel

Hi Kishon,

Gentle ping.

Thanks,
Neil

On 15/09/2020 15:03, Neil Armstrong wrote:
> The AXG Analog MIPI-DSI PHY also provides functions to the PCIe PHY,
> thus we need to have inclusive support for both interfaces at runtime.
> 
> This fixes the regmap get from parent node, removes cell param
> to select a mode and implement runtime configuration & power on/off
> for both functions since they are not exclusive.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> Reviewed-by: Remi Pommarel <repk@triplefau.lt>
> ---
>  drivers/phy/amlogic/Kconfig                   |   1 +
>  .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 204 ++++++++++++------
>  2 files changed, 136 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
> index 99e8a4c7f1f3..db5d0cd757e3 100644
> --- a/drivers/phy/amlogic/Kconfig
> +++ b/drivers/phy/amlogic/Kconfig
> @@ -66,6 +66,7 @@ config PHY_MESON_AXG_MIPI_PCIE_ANALOG
>  	depends on OF && (ARCH_MESON || COMPILE_TEST)
>  	select GENERIC_PHY
>  	select REGMAP_MMIO
> +	select GENERIC_PHY_MIPI_DPHY
>  	help
>  	  Enable this to support the Meson MIPI + PCIE analog PHY
>  	  found in Meson AXG SoCs.
> diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
> index 1431cbf885e1..6eb21551bdd9 100644
> --- a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
> +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
> @@ -4,9 +4,13 @@
>   *
>   * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
>   */
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
>  #include <linux/module.h>
>  #include <linux/phy/phy.h>
>  #include <linux/regmap.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/syscon.h>
>  #include <linux/platform_device.h>
>  #include <dt-bindings/phy/phy.h>
>  
> @@ -14,10 +18,10 @@
>  #define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
>  #define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
>  #define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
> -#define		HHI_MIPI_CNTL0_DECODE_TO_RTERM	GENMASK(15, 12)
> -#define		HHI_MIPI_CNTL0_OUTPUT_EN	BIT(3)
> +#define		HHI_MIPI_CNTL0_DIF_REF_CTL1	GENMASK(25, 16)
> +#define		HHI_MIPI_CNTL0_DIF_REF_CTL0	GENMASK(15, 0)
>  
> -#define HHI_MIPI_CNTL1 0x01
> +#define HHI_MIPI_CNTL1 0x04
>  #define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
>  #define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
>  #define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
> @@ -25,100 +29,170 @@
>  #define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
>  #define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
>  
> -#define HHI_MIPI_CNTL2 0x02
> +#define HHI_MIPI_CNTL2 0x08
>  #define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
>  #define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
>  #define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
>  #define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
>  #define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
> -#define		HHI_MIPI_CNTL2_CH_EN(n)		BIT(15 - (n))
> +#define		HHI_MIPI_CNTL2_CH_EN		GENMASK(15, 11)
>  #define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
>  
> +#define DSI_LANE_0              (1 << 4)
> +#define DSI_LANE_1              (1 << 3)
> +#define DSI_LANE_CLK            (1 << 2)
> +#define DSI_LANE_2              (1 << 1)
> +#define DSI_LANE_3              (1 << 0)
> +#define DSI_LANE_MASK		(0x1F)
> +
>  struct phy_axg_mipi_pcie_analog_priv {
>  	struct phy *phy;
> -	unsigned int mode;
>  	struct regmap *regmap;
> +	bool dsi_configured;
> +	bool dsi_enabled;
> +	bool powered;
> +	struct phy_configure_opts_mipi_dphy config;
>  };
>  
> -static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
> -	.reg_bits = 8,
> -	.val_bits = 32,
> -	.reg_stride = 4,
> -	.max_register = HHI_MIPI_CNTL2,
> -};
> +static void phy_bandgap_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
> +{
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
>  
> -static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
> +}
> +
> +static void phy_bandgap_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
>  {
> -	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			HHI_MIPI_CNTL0_BANDGAP, 0);
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			HHI_MIPI_CNTL0_ENABLE, 0);
> +}
>  
> -	/* MIPI not supported yet */
> -	if (priv->mode != PHY_TYPE_PCIE)
> -		return -EINVAL;
> +static void phy_dsi_analog_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
> +{
> +	u32 reg;
>  
>  	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> -			   HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
> +			   HHI_MIPI_CNTL0_DIF_REF_CTL1,
> +			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   BIT(31), BIT(31));
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			   HHI_MIPI_CNTL0_DIF_REF_CTL0,
> +			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
> +
> +	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
> +
> +	regmap_write(priv->regmap, HHI_MIPI_CNTL2,
> +		     (0x26e0 << 16) | (0x459 << 0));
> +
> +	reg = DSI_LANE_CLK;
> +	switch (priv->config.lanes) {
> +	case 4:
> +		reg |= DSI_LANE_3;
> +		fallthrough;
> +	case 3:
> +		reg |= DSI_LANE_2;
> +		fallthrough;
> +	case 2:
> +		reg |= DSI_LANE_1;
> +		fallthrough;
> +	case 1:
> +		reg |= DSI_LANE_0;
> +		break;
> +	default:
> +		reg = 0;
> +	}
> +
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
> +			   HHI_MIPI_CNTL2_CH_EN,
> +			   FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
> +
> +	priv->dsi_enabled = true;
> +}
>  
> +static void phy_dsi_analog_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
> +{
>  	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> -			   HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
> -	return 0;
> +			HHI_MIPI_CNTL0_DIF_REF_CTL1,
> +			FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> +			HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
> +
> +	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
> +
> +	regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
> +
> +	priv->dsi_enabled = false;
>  }
>  
> -static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
> +static int phy_axg_mipi_pcie_analog_configure(struct phy *phy,
> +					      union phy_configure_opts *opts)
>  {
>  	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +	int ret;
>  
> -	/* MIPI not supported yet */
> -	if (priv->mode != PHY_TYPE_PCIE)
> -		return -EINVAL;
> +	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
> +	if (ret)
> +		return ret;
> +
> +	memcpy(&priv->config, opts, sizeof(priv->config));
> +
> +	priv->dsi_configured = true;
> +
> +	/* If PHY was already powered on, setup the DSI analog part */
> +	if (priv->powered) {
> +		/* If reconfiguring, disable & reconfigure */
> +		if (priv->dsi_enabled)
> +			phy_dsi_analog_disable(priv);
> +
> +		usleep_range(100, 200);
> +
> +		phy_dsi_analog_enable(priv);
> +	}
>  
> -	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> -			   HHI_MIPI_CNTL0_BANDGAP, 0);
> -	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
> -			   HHI_MIPI_CNTL0_ENABLE, 0);
>  	return 0;
>  }
>  
> -static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
> +static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
>  {
> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +
> +	phy_bandgap_enable(priv);
> +
> +	if (priv->dsi_configured)
> +		phy_dsi_analog_enable(priv);
> +
> +	priv->powered = true;
> +
>  	return 0;
>  }
>  
> -static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
> +static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
>  {
> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
> +
> +	phy_bandgap_disable(priv);
> +
> +	if (priv->dsi_enabled)
> +		phy_dsi_analog_disable(priv);
> +
> +	priv->powered = false;
> +
>  	return 0;
>  }
>  
>  static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
> -	.init = phy_axg_mipi_pcie_analog_init,
> -	.exit = phy_axg_mipi_pcie_analog_exit,
> +	.configure = phy_axg_mipi_pcie_analog_configure,
>  	.power_on = phy_axg_mipi_pcie_analog_power_on,
>  	.power_off = phy_axg_mipi_pcie_analog_power_off,
>  	.owner = THIS_MODULE,
>  };
>  
> -static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
> -						  struct of_phandle_args *args)
> -{
> -	struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
> -	unsigned int mode;
> -
> -	if (args->args_count != 1) {
> -		dev_err(dev, "invalid number of arguments\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	mode = args->args[0];
> -
> -	/* MIPI mode is not supported yet */
> -	if (mode != PHY_TYPE_PCIE) {
> -		dev_err(dev, "invalid phy mode select argument\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	priv->mode = mode;
> -	return priv->phy;
> -}
> -
>  static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>  {
>  	struct phy_provider *phy;
> @@ -126,27 +200,20 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>  	struct phy_axg_mipi_pcie_analog_priv *priv;
>  	struct device_node *np = dev->of_node;
>  	struct regmap *map;
> -	struct resource *res;
> -	void __iomem *base;
>  	int ret;
>  
>  	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
>  	if (!priv)
>  		return -ENOMEM;
>  
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	base = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(base)) {
> -		dev_err(dev, "failed to get regmap base\n");
> -		return PTR_ERR(base);
> -	}
> -
> -	map = devm_regmap_init_mmio(dev, base,
> -				    &phy_axg_mipi_pcie_analog_regmap_conf);
> +	/* Get the hhi system controller node */
> +	map = syscon_node_to_regmap(of_get_parent(dev->of_node));
>  	if (IS_ERR(map)) {
> -		dev_err(dev, "failed to get HHI regmap\n");
> +		dev_err(dev,
> +			"failed to get HHI regmap\n");
>  		return PTR_ERR(map);
>  	}
> +
>  	priv->regmap = map;
>  
>  	priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
> @@ -160,8 +227,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>  	phy_set_drvdata(priv->phy, priv);
>  	dev_set_drvdata(dev, priv);
>  
> -	phy = devm_of_phy_provider_register(dev,
> -					    phy_axg_mipi_pcie_analog_xlate);
> +	phy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>  
>  	return PTR_ERR_OR_ZERO(phy);
>  }
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog
  2020-09-29  9:25   ` Neil Armstrong
@ 2020-10-20 23:10     ` Kevin Hilman
  0 siblings, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2020-10-20 23:10 UTC (permalink / raw)
  To: Neil Armstrong, kishon, repk
  Cc: linux-amlogic, linux-arm-kernel, linux-kernel

Hi Kishon,

It's been another few weeks, so another slightly less gentle ping. :)

Kevin

Neil Armstrong <narmstrong@baylibre.com> writes:

> Hi Kishon,
>
> Gentle ping.
>
> Thanks,
> Neil
>
> On 15/09/2020 15:03, Neil Armstrong wrote:
>> The AXG Analog MIPI-DSI PHY also provides functions to the PCIe PHY,
>> thus we need to have inclusive support for both interfaces at runtime.
>> 
>> This fixes the regmap get from parent node, removes cell param
>> to select a mode and implement runtime configuration & power on/off
>> for both functions since they are not exclusive.
>> 
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> Reviewed-by: Remi Pommarel <repk@triplefau.lt>
>> ---
>>  drivers/phy/amlogic/Kconfig                   |   1 +
>>  .../amlogic/phy-meson-axg-mipi-pcie-analog.c  | 204 ++++++++++++------
>>  2 files changed, 136 insertions(+), 69 deletions(-)
>> 
>> diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
>> index 99e8a4c7f1f3..db5d0cd757e3 100644
>> --- a/drivers/phy/amlogic/Kconfig
>> +++ b/drivers/phy/amlogic/Kconfig
>> @@ -66,6 +66,7 @@ config PHY_MESON_AXG_MIPI_PCIE_ANALOG
>>  	depends on OF && (ARCH_MESON || COMPILE_TEST)
>>  	select GENERIC_PHY
>>  	select REGMAP_MMIO
>> +	select GENERIC_PHY_MIPI_DPHY
>>  	help
>>  	  Enable this to support the Meson MIPI + PCIE analog PHY
>>  	  found in Meson AXG SoCs.
>> diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
>> index 1431cbf885e1..6eb21551bdd9 100644
>> --- a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
>> +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
>> @@ -4,9 +4,13 @@
>>   *
>>   * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
>>   */
>> +#include <linux/bitfield.h>
>> +#include <linux/bitops.h>
>>  #include <linux/module.h>
>>  #include <linux/phy/phy.h>
>>  #include <linux/regmap.h>
>> +#include <linux/delay.h>
>> +#include <linux/mfd/syscon.h>
>>  #include <linux/platform_device.h>
>>  #include <dt-bindings/phy/phy.h>
>>  
>> @@ -14,10 +18,10 @@
>>  #define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
>>  #define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
>>  #define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
>> -#define		HHI_MIPI_CNTL0_DECODE_TO_RTERM	GENMASK(15, 12)
>> -#define		HHI_MIPI_CNTL0_OUTPUT_EN	BIT(3)
>> +#define		HHI_MIPI_CNTL0_DIF_REF_CTL1	GENMASK(25, 16)
>> +#define		HHI_MIPI_CNTL0_DIF_REF_CTL0	GENMASK(15, 0)
>>  
>> -#define HHI_MIPI_CNTL1 0x01
>> +#define HHI_MIPI_CNTL1 0x04
>>  #define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
>>  #define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
>>  #define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
>> @@ -25,100 +29,170 @@
>>  #define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
>>  #define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
>>  
>> -#define HHI_MIPI_CNTL2 0x02
>> +#define HHI_MIPI_CNTL2 0x08
>>  #define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
>>  #define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
>>  #define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
>>  #define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
>>  #define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
>> -#define		HHI_MIPI_CNTL2_CH_EN(n)		BIT(15 - (n))
>> +#define		HHI_MIPI_CNTL2_CH_EN		GENMASK(15, 11)
>>  #define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
>>  
>> +#define DSI_LANE_0              (1 << 4)
>> +#define DSI_LANE_1              (1 << 3)
>> +#define DSI_LANE_CLK            (1 << 2)
>> +#define DSI_LANE_2              (1 << 1)
>> +#define DSI_LANE_3              (1 << 0)
>> +#define DSI_LANE_MASK		(0x1F)
>> +
>>  struct phy_axg_mipi_pcie_analog_priv {
>>  	struct phy *phy;
>> -	unsigned int mode;
>>  	struct regmap *regmap;
>> +	bool dsi_configured;
>> +	bool dsi_enabled;
>> +	bool powered;
>> +	struct phy_configure_opts_mipi_dphy config;
>>  };
>>  
>> -static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
>> -	.reg_bits = 8,
>> -	.val_bits = 32,
>> -	.reg_stride = 4,
>> -	.max_register = HHI_MIPI_CNTL2,
>> -};
>> +static void phy_bandgap_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
>> +{
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
>>  
>> -static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
>> +}
>> +
>> +static void phy_bandgap_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
>>  {
>> -	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			HHI_MIPI_CNTL0_BANDGAP, 0);
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			HHI_MIPI_CNTL0_ENABLE, 0);
>> +}
>>  
>> -	/* MIPI not supported yet */
>> -	if (priv->mode != PHY_TYPE_PCIE)
>> -		return -EINVAL;
>> +static void phy_dsi_analog_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
>> +{
>> +	u32 reg;
>>  
>>  	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> -			   HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
>> +			   HHI_MIPI_CNTL0_DIF_REF_CTL1,
>> +			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			   BIT(31), BIT(31));
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			   HHI_MIPI_CNTL0_DIF_REF_CTL0,
>> +			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
>> +
>> +	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
>> +
>> +	regmap_write(priv->regmap, HHI_MIPI_CNTL2,
>> +		     (0x26e0 << 16) | (0x459 << 0));
>> +
>> +	reg = DSI_LANE_CLK;
>> +	switch (priv->config.lanes) {
>> +	case 4:
>> +		reg |= DSI_LANE_3;
>> +		fallthrough;
>> +	case 3:
>> +		reg |= DSI_LANE_2;
>> +		fallthrough;
>> +	case 2:
>> +		reg |= DSI_LANE_1;
>> +		fallthrough;
>> +	case 1:
>> +		reg |= DSI_LANE_0;
>> +		break;
>> +	default:
>> +		reg = 0;
>> +	}
>> +
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
>> +			   HHI_MIPI_CNTL2_CH_EN,
>> +			   FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
>> +
>> +	priv->dsi_enabled = true;
>> +}
>>  
>> +static void phy_dsi_analog_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
>> +{
>>  	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> -			   HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
>> -	return 0;
>> +			HHI_MIPI_CNTL0_DIF_REF_CTL1,
>> +			FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
>> +	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> +			HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
>> +
>> +	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
>> +
>> +	regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
>> +
>> +	priv->dsi_enabled = false;
>>  }
>>  
>> -static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
>> +static int phy_axg_mipi_pcie_analog_configure(struct phy *phy,
>> +					      union phy_configure_opts *opts)
>>  {
>>  	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
>> +	int ret;
>>  
>> -	/* MIPI not supported yet */
>> -	if (priv->mode != PHY_TYPE_PCIE)
>> -		return -EINVAL;
>> +	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
>> +	if (ret)
>> +		return ret;
>> +
>> +	memcpy(&priv->config, opts, sizeof(priv->config));
>> +
>> +	priv->dsi_configured = true;
>> +
>> +	/* If PHY was already powered on, setup the DSI analog part */
>> +	if (priv->powered) {
>> +		/* If reconfiguring, disable & reconfigure */
>> +		if (priv->dsi_enabled)
>> +			phy_dsi_analog_disable(priv);
>> +
>> +		usleep_range(100, 200);
>> +
>> +		phy_dsi_analog_enable(priv);
>> +	}
>>  
>> -	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> -			   HHI_MIPI_CNTL0_BANDGAP, 0);
>> -	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
>> -			   HHI_MIPI_CNTL0_ENABLE, 0);
>>  	return 0;
>>  }
>>  
>> -static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
>> +static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
>>  {
>> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
>> +
>> +	phy_bandgap_enable(priv);
>> +
>> +	if (priv->dsi_configured)
>> +		phy_dsi_analog_enable(priv);
>> +
>> +	priv->powered = true;
>> +
>>  	return 0;
>>  }
>>  
>> -static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
>> +static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
>>  {
>> +	struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
>> +
>> +	phy_bandgap_disable(priv);
>> +
>> +	if (priv->dsi_enabled)
>> +		phy_dsi_analog_disable(priv);
>> +
>> +	priv->powered = false;
>> +
>>  	return 0;
>>  }
>>  
>>  static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
>> -	.init = phy_axg_mipi_pcie_analog_init,
>> -	.exit = phy_axg_mipi_pcie_analog_exit,
>> +	.configure = phy_axg_mipi_pcie_analog_configure,
>>  	.power_on = phy_axg_mipi_pcie_analog_power_on,
>>  	.power_off = phy_axg_mipi_pcie_analog_power_off,
>>  	.owner = THIS_MODULE,
>>  };
>>  
>> -static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
>> -						  struct of_phandle_args *args)
>> -{
>> -	struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
>> -	unsigned int mode;
>> -
>> -	if (args->args_count != 1) {
>> -		dev_err(dev, "invalid number of arguments\n");
>> -		return ERR_PTR(-EINVAL);
>> -	}
>> -
>> -	mode = args->args[0];
>> -
>> -	/* MIPI mode is not supported yet */
>> -	if (mode != PHY_TYPE_PCIE) {
>> -		dev_err(dev, "invalid phy mode select argument\n");
>> -		return ERR_PTR(-EINVAL);
>> -	}
>> -
>> -	priv->mode = mode;
>> -	return priv->phy;
>> -}
>> -
>>  static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>>  {
>>  	struct phy_provider *phy;
>> @@ -126,27 +200,20 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>>  	struct phy_axg_mipi_pcie_analog_priv *priv;
>>  	struct device_node *np = dev->of_node;
>>  	struct regmap *map;
>> -	struct resource *res;
>> -	void __iomem *base;
>>  	int ret;
>>  
>>  	priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
>>  	if (!priv)
>>  		return -ENOMEM;
>>  
>> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -	base = devm_ioremap_resource(dev, res);
>> -	if (IS_ERR(base)) {
>> -		dev_err(dev, "failed to get regmap base\n");
>> -		return PTR_ERR(base);
>> -	}
>> -
>> -	map = devm_regmap_init_mmio(dev, base,
>> -				    &phy_axg_mipi_pcie_analog_regmap_conf);
>> +	/* Get the hhi system controller node */
>> +	map = syscon_node_to_regmap(of_get_parent(dev->of_node));
>>  	if (IS_ERR(map)) {
>> -		dev_err(dev, "failed to get HHI regmap\n");
>> +		dev_err(dev,
>> +			"failed to get HHI regmap\n");
>>  		return PTR_ERR(map);
>>  	}
>> +
>>  	priv->regmap = map;
>>  
>>  	priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
>> @@ -160,8 +227,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
>>  	phy_set_drvdata(priv->phy, priv);
>>  	dev_set_drvdata(dev, priv);
>>  
>> -	phy = devm_of_phy_provider_register(dev,
>> -					    phy_axg_mipi_pcie_analog_xlate);
>> +	phy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>>  
>>  	return PTR_ERR_OR_ZERO(phy);
>>  }
>> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-10-20 23:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-15 13:03 [PATCH v2 0/3] phy: amlogic: add MIPI DSI function to analog MIPI+PCIe PHY Neil Armstrong
2020-09-15 13:03 ` [PATCH v2 1/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove reg attribute Neil Armstrong
2020-09-23  1:31   ` [PATCH v2 1/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: " Rob Herring
2020-09-15 13:03 ` [PATCH v2 2/3] dt-bindings: phy: amlogic,meson-axg-mipi-pcie-analog: remove phy cell parameter Neil Armstrong
2020-09-22 19:35   ` [PATCH v2 2/3] dt-bindings: phy: amlogic, meson-axg-mipi-pcie-analog: " Rob Herring
2020-09-15 13:03 ` [PATCH v2 3/3] phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog Neil Armstrong
2020-09-29  9:25   ` Neil Armstrong
2020-10-20 23:10     ` Kevin Hilman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).