All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver
@ 2022-06-13  7:26 ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

This series display port phy drivers and separated from [1] which is
original from Guillaume.
The display port driver is [2].

Changes for v11:
1. Fix register definition.

[1]:https://lore.kernel.org/all/20220523104758.29531-1-granquet@baylibre.com/
[2]:https://lore.kernel.org/all/20220610105522.13449-1-rex-bc.chen@mediatek.com/

Markus Schneider-Pargmann (1):
  phy: phy-mtk-dp: Add driver for DP phy

 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

-- 
2.18.0


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

* [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver
@ 2022-06-13  7:26 ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: granquet, jitao.shi, linux-kernel, dri-devel, msp,
	Project_Global_Chrome_Upstream_Group, linux-phy, linux-mediatek,
	Bo-Chen Chen, wenst, linux-arm-kernel, angelogioacchino.delregno

This series display port phy drivers and separated from [1] which is
original from Guillaume.
The display port driver is [2].

Changes for v11:
1. Fix register definition.

[1]:https://lore.kernel.org/all/20220523104758.29531-1-granquet@baylibre.com/
[2]:https://lore.kernel.org/all/20220610105522.13449-1-rex-bc.chen@mediatek.com/

Markus Schneider-Pargmann (1):
  phy: phy-mtk-dp: Add driver for DP phy

 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

-- 
2.18.0


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

* [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver
@ 2022-06-13  7:26 ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

This series display port phy drivers and separated from [1] which is
original from Guillaume.
The display port driver is [2].

Changes for v11:
1. Fix register definition.

[1]:https://lore.kernel.org/all/20220523104758.29531-1-granquet@baylibre.com/
[2]:https://lore.kernel.org/all/20220610105522.13449-1-rex-bc.chen@mediatek.com/

Markus Schneider-Pargmann (1):
  phy: phy-mtk-dp: Add driver for DP phy

 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

-- 
2.18.0


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver
@ 2022-06-13  7:26 ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

This series display port phy drivers and separated from [1] which is
original from Guillaume.
The display port driver is [2].

Changes for v11:
1. Fix register definition.

[1]:https://lore.kernel.org/all/20220523104758.29531-1-granquet@baylibre.com/
[2]:https://lore.kernel.org/all/20220610105522.13449-1-rex-bc.chen@mediatek.com/

Markus Schneider-Pargmann (1):
  phy: phy-mtk-dp: Add driver for DP phy

 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

-- 
2.18.0


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver
@ 2022-06-13  7:26 ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

This series display port phy drivers and separated from [1] which is
original from Guillaume.
The display port driver is [2].

Changes for v11:
1. Fix register definition.

[1]:https://lore.kernel.org/all/20220523104758.29531-1-granquet@baylibre.com/
[2]:https://lore.kernel.org/all/20220610105522.13449-1-rex-bc.chen@mediatek.com/

Markus Schneider-Pargmann (1):
  phy: phy-mtk-dp: Add driver for DP phy

 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
  2022-06-13  7:26 ` Bo-Chen Chen
                     ` (2 preceding siblings ...)
  (?)
@ 2022-06-13  7:26   ` Bo-Chen Chen
  -1 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

From: Markus Schneider-Pargmann <msp@baylibre.com>

This is a new driver that supports the integrated DisplayPort phy for
mediatek SoCs, especially the mt8195. The phy is integrated into the
DisplayPort controller and will be created by the mtk-dp driver. This
driver expects a struct regmap to be able to work on the same registers
as the DisplayPort controller. It sets the device data to be the struct
phy so that the DisplayPort controller can easily work with it.

The driver does not have any devicetree bindings because the datasheet
does not list the controller and the phy as distinct units.

The interaction with the controller can be covered by the configure
callback of the phy framework and its displayport parameters.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
[Bo-Chen: Modify reviewers' comments.]
Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
---
 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..f1460ee9ce83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/display/mediatek/
 F:	drivers/gpu/drm/mediatek/
+F:	drivers/phy/mediatek/phy-mtk-dp.c
 F:	drivers/phy/mediatek/phy-mtk-hdmi*
 F:	drivers/phy/mediatek/phy-mtk-mipi*
 
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 55f8e6c048ab..d631525d12e1 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
 	select GENERIC_PHY
 	help
 	  Support MIPI DSI for Mediatek SoCs.
+
+config PHY_MTK_DP
+	tristate "MediaTek DP-PHY Driver"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support DisplayPort PHY for MediaTek SoCs.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ace660fbed3a..4ba1e0650434 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the phy drivers.
 #
 
+obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
 obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
new file mode 100644
index 000000000000..c4d5ca1719a4
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DisplayPort PHY driver
+ *
+ * Copyright (c) 2022 BayLibre
+ * Copyright (c) 2022 MediaTek
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_OFFSET			0x1000
+
+#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
+#define TPLL_SSC_EN			BIT(3)
+
+#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
+#define BIT_RATE_RBR			0
+#define BIT_RATE_HBR			1
+#define BIT_RATE_HBR2			2
+#define BIT_RATE_HBR3			3
+
+#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
+#define DP_GLB_SW_RST_PHYD		BIT(0)
+
+#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
+#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
+#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
+#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
+#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
+#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
+#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
+#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
+#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
+#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
+#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
+#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
+#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
+#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
+#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
+#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
+#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
+#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
+#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
+
+struct mtk_dp_phy {
+	struct regmap *regs;
+};
+
+static int mtk_dp_phy_init(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 driving_params[] = {
+		DRIVING_PARAM_3_DEFAULT,
+		DRIVING_PARAM_4_DEFAULT,
+		DRIVING_PARAM_5_DEFAULT,
+		DRIVING_PARAM_6_DEFAULT,
+		DRIVING_PARAM_7_DEFAULT,
+		DRIVING_PARAM_8_DEFAULT
+	};
+
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+
+	return 0;
+}
+
+static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	if (opts->dp.set_rate) {
+		switch (opts->dp.link_rate) {
+		default:
+			dev_err(&phy->dev,
+				"Implementation error, unknown linkrate %x\n",
+				opts->dp.link_rate);
+			return -EINVAL;
+		case 1620:
+			val = BIT_RATE_RBR;
+			break;
+		case 2700:
+			val = BIT_RATE_HBR;
+			break;
+		case 5400:
+			val = BIT_RATE_HBR2;
+			break;
+		case 8100:
+			val = BIT_RATE_HBR3;
+			break;
+		}
+		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
+	}
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
+			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
+
+	return 0;
+}
+
+static int mtk_dp_phy_reset(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 0);
+	usleep_range(50, 200);
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 1);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dp_phy_dev_ops = {
+	.init = mtk_dp_phy_init,
+	.configure = mtk_dp_phy_configure,
+	.reset = mtk_dp_phy_reset,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_dp_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dp_phy *dp_phy;
+	struct phy *phy;
+	struct regmap *regs;
+
+	regs = *(struct regmap **)dev->platform_data;
+	if (!regs)
+		return dev_err_probe(dev, EINVAL,
+				     "No data passed, requires struct regmap**\n");
+
+	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
+	if (!dp_phy)
+		return -ENOMEM;
+
+	dp_phy->regs = regs;
+	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "Failed to create DP PHY\n");
+
+	phy_set_drvdata(phy, dp_phy);
+	if (!dev->of_node)
+		phy_create_lookup(phy, "dp", dev_name(dev));
+
+	return 0;
+}
+
+struct platform_driver mtk_dp_phy_driver = {
+	.probe = mtk_dp_phy_probe,
+	.driver = {
+		.name = "mediatek-dp-phy",
+	},
+};
+module_platform_driver(mtk_dp_phy_driver);
+
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
+MODULE_DESCRIPTION("MediaTek DP PHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.18.0


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

* [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13  7:26   ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: granquet, jitao.shi, linux-kernel, dri-devel, msp,
	Project_Global_Chrome_Upstream_Group, linux-phy, linux-mediatek,
	Bo-Chen Chen, wenst, linux-arm-kernel, angelogioacchino.delregno

From: Markus Schneider-Pargmann <msp@baylibre.com>

This is a new driver that supports the integrated DisplayPort phy for
mediatek SoCs, especially the mt8195. The phy is integrated into the
DisplayPort controller and will be created by the mtk-dp driver. This
driver expects a struct regmap to be able to work on the same registers
as the DisplayPort controller. It sets the device data to be the struct
phy so that the DisplayPort controller can easily work with it.

The driver does not have any devicetree bindings because the datasheet
does not list the controller and the phy as distinct units.

The interaction with the controller can be covered by the configure
callback of the phy framework and its displayport parameters.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
[Bo-Chen: Modify reviewers' comments.]
Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
---
 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..f1460ee9ce83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/display/mediatek/
 F:	drivers/gpu/drm/mediatek/
+F:	drivers/phy/mediatek/phy-mtk-dp.c
 F:	drivers/phy/mediatek/phy-mtk-hdmi*
 F:	drivers/phy/mediatek/phy-mtk-mipi*
 
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 55f8e6c048ab..d631525d12e1 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
 	select GENERIC_PHY
 	help
 	  Support MIPI DSI for Mediatek SoCs.
+
+config PHY_MTK_DP
+	tristate "MediaTek DP-PHY Driver"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support DisplayPort PHY for MediaTek SoCs.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ace660fbed3a..4ba1e0650434 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the phy drivers.
 #
 
+obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
 obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
new file mode 100644
index 000000000000..c4d5ca1719a4
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DisplayPort PHY driver
+ *
+ * Copyright (c) 2022 BayLibre
+ * Copyright (c) 2022 MediaTek
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_OFFSET			0x1000
+
+#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
+#define TPLL_SSC_EN			BIT(3)
+
+#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
+#define BIT_RATE_RBR			0
+#define BIT_RATE_HBR			1
+#define BIT_RATE_HBR2			2
+#define BIT_RATE_HBR3			3
+
+#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
+#define DP_GLB_SW_RST_PHYD		BIT(0)
+
+#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
+#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
+#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
+#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
+#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
+#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
+#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
+#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
+#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
+#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
+#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
+#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
+#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
+#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
+#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
+#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
+#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
+#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
+#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
+
+struct mtk_dp_phy {
+	struct regmap *regs;
+};
+
+static int mtk_dp_phy_init(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 driving_params[] = {
+		DRIVING_PARAM_3_DEFAULT,
+		DRIVING_PARAM_4_DEFAULT,
+		DRIVING_PARAM_5_DEFAULT,
+		DRIVING_PARAM_6_DEFAULT,
+		DRIVING_PARAM_7_DEFAULT,
+		DRIVING_PARAM_8_DEFAULT
+	};
+
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+
+	return 0;
+}
+
+static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	if (opts->dp.set_rate) {
+		switch (opts->dp.link_rate) {
+		default:
+			dev_err(&phy->dev,
+				"Implementation error, unknown linkrate %x\n",
+				opts->dp.link_rate);
+			return -EINVAL;
+		case 1620:
+			val = BIT_RATE_RBR;
+			break;
+		case 2700:
+			val = BIT_RATE_HBR;
+			break;
+		case 5400:
+			val = BIT_RATE_HBR2;
+			break;
+		case 8100:
+			val = BIT_RATE_HBR3;
+			break;
+		}
+		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
+	}
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
+			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
+
+	return 0;
+}
+
+static int mtk_dp_phy_reset(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 0);
+	usleep_range(50, 200);
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 1);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dp_phy_dev_ops = {
+	.init = mtk_dp_phy_init,
+	.configure = mtk_dp_phy_configure,
+	.reset = mtk_dp_phy_reset,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_dp_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dp_phy *dp_phy;
+	struct phy *phy;
+	struct regmap *regs;
+
+	regs = *(struct regmap **)dev->platform_data;
+	if (!regs)
+		return dev_err_probe(dev, EINVAL,
+				     "No data passed, requires struct regmap**\n");
+
+	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
+	if (!dp_phy)
+		return -ENOMEM;
+
+	dp_phy->regs = regs;
+	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "Failed to create DP PHY\n");
+
+	phy_set_drvdata(phy, dp_phy);
+	if (!dev->of_node)
+		phy_create_lookup(phy, "dp", dev_name(dev));
+
+	return 0;
+}
+
+struct platform_driver mtk_dp_phy_driver = {
+	.probe = mtk_dp_phy_probe,
+	.driver = {
+		.name = "mediatek-dp-phy",
+	},
+};
+module_platform_driver(mtk_dp_phy_driver);
+
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
+MODULE_DESCRIPTION("MediaTek DP PHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.18.0


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

* [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13  7:26   ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

From: Markus Schneider-Pargmann <msp@baylibre.com>

This is a new driver that supports the integrated DisplayPort phy for
mediatek SoCs, especially the mt8195. The phy is integrated into the
DisplayPort controller and will be created by the mtk-dp driver. This
driver expects a struct regmap to be able to work on the same registers
as the DisplayPort controller. It sets the device data to be the struct
phy so that the DisplayPort controller can easily work with it.

The driver does not have any devicetree bindings because the datasheet
does not list the controller and the phy as distinct units.

The interaction with the controller can be covered by the configure
callback of the phy framework and its displayport parameters.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
[Bo-Chen: Modify reviewers' comments.]
Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
---
 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..f1460ee9ce83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/display/mediatek/
 F:	drivers/gpu/drm/mediatek/
+F:	drivers/phy/mediatek/phy-mtk-dp.c
 F:	drivers/phy/mediatek/phy-mtk-hdmi*
 F:	drivers/phy/mediatek/phy-mtk-mipi*
 
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 55f8e6c048ab..d631525d12e1 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
 	select GENERIC_PHY
 	help
 	  Support MIPI DSI for Mediatek SoCs.
+
+config PHY_MTK_DP
+	tristate "MediaTek DP-PHY Driver"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support DisplayPort PHY for MediaTek SoCs.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ace660fbed3a..4ba1e0650434 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the phy drivers.
 #
 
+obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
 obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
new file mode 100644
index 000000000000..c4d5ca1719a4
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DisplayPort PHY driver
+ *
+ * Copyright (c) 2022 BayLibre
+ * Copyright (c) 2022 MediaTek
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_OFFSET			0x1000
+
+#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
+#define TPLL_SSC_EN			BIT(3)
+
+#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
+#define BIT_RATE_RBR			0
+#define BIT_RATE_HBR			1
+#define BIT_RATE_HBR2			2
+#define BIT_RATE_HBR3			3
+
+#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
+#define DP_GLB_SW_RST_PHYD		BIT(0)
+
+#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
+#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
+#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
+#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
+#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
+#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
+#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
+#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
+#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
+#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
+#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
+#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
+#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
+#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
+#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
+#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
+#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
+#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
+#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
+
+struct mtk_dp_phy {
+	struct regmap *regs;
+};
+
+static int mtk_dp_phy_init(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 driving_params[] = {
+		DRIVING_PARAM_3_DEFAULT,
+		DRIVING_PARAM_4_DEFAULT,
+		DRIVING_PARAM_5_DEFAULT,
+		DRIVING_PARAM_6_DEFAULT,
+		DRIVING_PARAM_7_DEFAULT,
+		DRIVING_PARAM_8_DEFAULT
+	};
+
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+
+	return 0;
+}
+
+static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	if (opts->dp.set_rate) {
+		switch (opts->dp.link_rate) {
+		default:
+			dev_err(&phy->dev,
+				"Implementation error, unknown linkrate %x\n",
+				opts->dp.link_rate);
+			return -EINVAL;
+		case 1620:
+			val = BIT_RATE_RBR;
+			break;
+		case 2700:
+			val = BIT_RATE_HBR;
+			break;
+		case 5400:
+			val = BIT_RATE_HBR2;
+			break;
+		case 8100:
+			val = BIT_RATE_HBR3;
+			break;
+		}
+		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
+	}
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
+			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
+
+	return 0;
+}
+
+static int mtk_dp_phy_reset(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 0);
+	usleep_range(50, 200);
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 1);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dp_phy_dev_ops = {
+	.init = mtk_dp_phy_init,
+	.configure = mtk_dp_phy_configure,
+	.reset = mtk_dp_phy_reset,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_dp_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dp_phy *dp_phy;
+	struct phy *phy;
+	struct regmap *regs;
+
+	regs = *(struct regmap **)dev->platform_data;
+	if (!regs)
+		return dev_err_probe(dev, EINVAL,
+				     "No data passed, requires struct regmap**\n");
+
+	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
+	if (!dp_phy)
+		return -ENOMEM;
+
+	dp_phy->regs = regs;
+	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "Failed to create DP PHY\n");
+
+	phy_set_drvdata(phy, dp_phy);
+	if (!dev->of_node)
+		phy_create_lookup(phy, "dp", dev_name(dev));
+
+	return 0;
+}
+
+struct platform_driver mtk_dp_phy_driver = {
+	.probe = mtk_dp_phy_probe,
+	.driver = {
+		.name = "mediatek-dp-phy",
+	},
+};
+module_platform_driver(mtk_dp_phy_driver);
+
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
+MODULE_DESCRIPTION("MediaTek DP PHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.18.0


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13  7:26   ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

From: Markus Schneider-Pargmann <msp@baylibre.com>

This is a new driver that supports the integrated DisplayPort phy for
mediatek SoCs, especially the mt8195. The phy is integrated into the
DisplayPort controller and will be created by the mtk-dp driver. This
driver expects a struct regmap to be able to work on the same registers
as the DisplayPort controller. It sets the device data to be the struct
phy so that the DisplayPort controller can easily work with it.

The driver does not have any devicetree bindings because the datasheet
does not list the controller and the phy as distinct units.

The interaction with the controller can be covered by the configure
callback of the phy framework and its displayport parameters.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
[Bo-Chen: Modify reviewers' comments.]
Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
---
 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..f1460ee9ce83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/display/mediatek/
 F:	drivers/gpu/drm/mediatek/
+F:	drivers/phy/mediatek/phy-mtk-dp.c
 F:	drivers/phy/mediatek/phy-mtk-hdmi*
 F:	drivers/phy/mediatek/phy-mtk-mipi*
 
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 55f8e6c048ab..d631525d12e1 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
 	select GENERIC_PHY
 	help
 	  Support MIPI DSI for Mediatek SoCs.
+
+config PHY_MTK_DP
+	tristate "MediaTek DP-PHY Driver"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support DisplayPort PHY for MediaTek SoCs.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ace660fbed3a..4ba1e0650434 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the phy drivers.
 #
 
+obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
 obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
new file mode 100644
index 000000000000..c4d5ca1719a4
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DisplayPort PHY driver
+ *
+ * Copyright (c) 2022 BayLibre
+ * Copyright (c) 2022 MediaTek
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_OFFSET			0x1000
+
+#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
+#define TPLL_SSC_EN			BIT(3)
+
+#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
+#define BIT_RATE_RBR			0
+#define BIT_RATE_HBR			1
+#define BIT_RATE_HBR2			2
+#define BIT_RATE_HBR3			3
+
+#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
+#define DP_GLB_SW_RST_PHYD		BIT(0)
+
+#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
+#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
+#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
+#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
+#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
+#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
+#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
+#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
+#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
+#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
+#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
+#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
+#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
+#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
+#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
+#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
+#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
+#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
+#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
+
+struct mtk_dp_phy {
+	struct regmap *regs;
+};
+
+static int mtk_dp_phy_init(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 driving_params[] = {
+		DRIVING_PARAM_3_DEFAULT,
+		DRIVING_PARAM_4_DEFAULT,
+		DRIVING_PARAM_5_DEFAULT,
+		DRIVING_PARAM_6_DEFAULT,
+		DRIVING_PARAM_7_DEFAULT,
+		DRIVING_PARAM_8_DEFAULT
+	};
+
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+
+	return 0;
+}
+
+static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	if (opts->dp.set_rate) {
+		switch (opts->dp.link_rate) {
+		default:
+			dev_err(&phy->dev,
+				"Implementation error, unknown linkrate %x\n",
+				opts->dp.link_rate);
+			return -EINVAL;
+		case 1620:
+			val = BIT_RATE_RBR;
+			break;
+		case 2700:
+			val = BIT_RATE_HBR;
+			break;
+		case 5400:
+			val = BIT_RATE_HBR2;
+			break;
+		case 8100:
+			val = BIT_RATE_HBR3;
+			break;
+		}
+		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
+	}
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
+			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
+
+	return 0;
+}
+
+static int mtk_dp_phy_reset(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 0);
+	usleep_range(50, 200);
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 1);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dp_phy_dev_ops = {
+	.init = mtk_dp_phy_init,
+	.configure = mtk_dp_phy_configure,
+	.reset = mtk_dp_phy_reset,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_dp_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dp_phy *dp_phy;
+	struct phy *phy;
+	struct regmap *regs;
+
+	regs = *(struct regmap **)dev->platform_data;
+	if (!regs)
+		return dev_err_probe(dev, EINVAL,
+				     "No data passed, requires struct regmap**\n");
+
+	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
+	if (!dp_phy)
+		return -ENOMEM;
+
+	dp_phy->regs = regs;
+	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "Failed to create DP PHY\n");
+
+	phy_set_drvdata(phy, dp_phy);
+	if (!dev->of_node)
+		phy_create_lookup(phy, "dp", dev_name(dev));
+
+	return 0;
+}
+
+struct platform_driver mtk_dp_phy_driver = {
+	.probe = mtk_dp_phy_probe,
+	.driver = {
+		.name = "mediatek-dp-phy",
+	},
+};
+module_platform_driver(mtk_dp_phy_driver);
+
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
+MODULE_DESCRIPTION("MediaTek DP PHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.18.0


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13  7:26   ` Bo-Chen Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Bo-Chen Chen @ 2022-06-13  7:26 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul, matthias.bgg,
	airlied
  Cc: msp, granquet, jitao.shi, wenst, angelogioacchino.delregno,
	ck.hu, dri-devel, linux-mediatek, linux-phy, linux-kernel,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Bo-Chen Chen

From: Markus Schneider-Pargmann <msp@baylibre.com>

This is a new driver that supports the integrated DisplayPort phy for
mediatek SoCs, especially the mt8195. The phy is integrated into the
DisplayPort controller and will be created by the mtk-dp driver. This
driver expects a struct regmap to be able to work on the same registers
as the DisplayPort controller. It sets the device data to be the struct
phy so that the DisplayPort controller can easily work with it.

The driver does not have any devicetree bindings because the datasheet
does not list the controller and the phy as distinct units.

The interaction with the controller can be covered by the configure
callback of the phy framework and its displayport parameters.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
[Bo-Chen: Modify reviewers' comments.]
Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
---
 MAINTAINERS                       |   1 +
 drivers/phy/mediatek/Kconfig      |   8 ++
 drivers/phy/mediatek/Makefile     |   1 +
 drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..f1460ee9ce83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/display/mediatek/
 F:	drivers/gpu/drm/mediatek/
+F:	drivers/phy/mediatek/phy-mtk-dp.c
 F:	drivers/phy/mediatek/phy-mtk-hdmi*
 F:	drivers/phy/mediatek/phy-mtk-mipi*
 
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 55f8e6c048ab..d631525d12e1 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
 	select GENERIC_PHY
 	help
 	  Support MIPI DSI for Mediatek SoCs.
+
+config PHY_MTK_DP
+	tristate "MediaTek DP-PHY Driver"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support DisplayPort PHY for MediaTek SoCs.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ace660fbed3a..4ba1e0650434 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the phy drivers.
 #
 
+obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
 obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
 obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
 obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
new file mode 100644
index 000000000000..c4d5ca1719a4
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek DisplayPort PHY driver
+ *
+ * Copyright (c) 2022 BayLibre
+ * Copyright (c) 2022 MediaTek
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_OFFSET			0x1000
+
+#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
+#define TPLL_SSC_EN			BIT(3)
+
+#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
+#define BIT_RATE_RBR			0
+#define BIT_RATE_HBR			1
+#define BIT_RATE_HBR2			2
+#define BIT_RATE_HBR3			3
+
+#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
+#define DP_GLB_SW_RST_PHYD		BIT(0)
+
+#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
+#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
+#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
+#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
+#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
+#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
+#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
+#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
+#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
+#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
+#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
+#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
+#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
+#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
+#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
+#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
+#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
+#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
+#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
+#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
+
+#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
+#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
+#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
+				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
+
+struct mtk_dp_phy {
+	struct regmap *regs;
+};
+
+static int mtk_dp_phy_init(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 driving_params[] = {
+		DRIVING_PARAM_3_DEFAULT,
+		DRIVING_PARAM_4_DEFAULT,
+		DRIVING_PARAM_5_DEFAULT,
+		DRIVING_PARAM_6_DEFAULT,
+		DRIVING_PARAM_7_DEFAULT,
+		DRIVING_PARAM_8_DEFAULT
+	};
+
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
+			  driving_params, ARRAY_SIZE(driving_params));
+
+	return 0;
+}
+
+static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+	u32 val;
+
+	if (opts->dp.set_rate) {
+		switch (opts->dp.link_rate) {
+		default:
+			dev_err(&phy->dev,
+				"Implementation error, unknown linkrate %x\n",
+				opts->dp.link_rate);
+			return -EINVAL;
+		case 1620:
+			val = BIT_RATE_RBR;
+			break;
+		case 2700:
+			val = BIT_RATE_HBR;
+			break;
+		case 5400:
+			val = BIT_RATE_HBR2;
+			break;
+		case 8100:
+			val = BIT_RATE_HBR3;
+			break;
+		}
+		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
+	}
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
+			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
+
+	return 0;
+}
+
+static int mtk_dp_phy_reset(struct phy *phy)
+{
+	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
+
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 0);
+	usleep_range(50, 200);
+	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
+			   DP_GLB_SW_RST_PHYD, 1);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dp_phy_dev_ops = {
+	.init = mtk_dp_phy_init,
+	.configure = mtk_dp_phy_configure,
+	.reset = mtk_dp_phy_reset,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_dp_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dp_phy *dp_phy;
+	struct phy *phy;
+	struct regmap *regs;
+
+	regs = *(struct regmap **)dev->platform_data;
+	if (!regs)
+		return dev_err_probe(dev, EINVAL,
+				     "No data passed, requires struct regmap**\n");
+
+	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
+	if (!dp_phy)
+		return -ENOMEM;
+
+	dp_phy->regs = regs;
+	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "Failed to create DP PHY\n");
+
+	phy_set_drvdata(phy, dp_phy);
+	if (!dev->of_node)
+		phy_create_lookup(phy, "dp", dev_name(dev));
+
+	return 0;
+}
+
+struct platform_driver mtk_dp_phy_driver = {
+	.probe = mtk_dp_phy_probe,
+	.driver = {
+		.name = "mediatek-dp-phy",
+	},
+};
+module_platform_driver(mtk_dp_phy_driver);
+
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
+MODULE_DESCRIPTION("MediaTek DP PHY Driver");
+MODULE_LICENSE("GPL");
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
  2022-06-13  7:26   ` Bo-Chen Chen
                       ` (2 preceding siblings ...)
  (?)
@ 2022-06-13 10:39     ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 27+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-06-13 10:39 UTC (permalink / raw)
  To: Bo-Chen Chen, chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul,
	matthias.bgg, airlied
  Cc: granquet, jitao.shi, linux-kernel, dri-devel, msp,
	Project_Global_Chrome_Upstream_Group, linux-phy, linux-mediatek,
	wenst, linux-arm-kernel

Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>

There's no power_on()/power_off() callbacks and looks a bit weird, but it's
also right... the only thing that's missing, IMO, is a comment in the actual
file explaining that power for this PHY is always on when the DP block is on
and that no PHY specific power sequence has to be carried on (being managed
elsewhere and strongly tied to the specific DP IP).

Besides that,

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13 10:39     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 27+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-06-13 10:39 UTC (permalink / raw)
  To: Bo-Chen Chen, chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul,
	matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>

There's no power_on()/power_off() callbacks and looks a bit weird, but it's
also right... the only thing that's missing, IMO, is a comment in the actual
file explaining that power for this PHY is always on when the DP block is on
and that no PHY specific power sequence has to be carried on (being managed
elsewhere and strongly tied to the specific DP IP).

Besides that,

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13 10:39     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 27+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-06-13 10:39 UTC (permalink / raw)
  To: Bo-Chen Chen, chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul,
	matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>

There's no power_on()/power_off() callbacks and looks a bit weird, but it's
also right... the only thing that's missing, IMO, is a comment in the actual
file explaining that power for this PHY is always on when the DP block is on
and that no PHY specific power sequence has to be carried on (being managed
elsewhere and strongly tied to the specific DP IP).

Besides that,

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13 10:39     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 27+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-06-13 10:39 UTC (permalink / raw)
  To: Bo-Chen Chen, chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul,
	matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>

There's no power_on()/power_off() callbacks and looks a bit weird, but it's
also right... the only thing that's missing, IMO, is a comment in the actual
file explaining that power for this PHY is always on when the DP block is on
and that no PHY specific power sequence has to be carried on (being managed
elsewhere and strongly tied to the specific DP IP).

Besides that,

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-13 10:39     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 27+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-06-13 10:39 UTC (permalink / raw)
  To: Bo-Chen Chen, chunkuang.hu, p.zabel, chunfeng.yun, kishon, vkoul,
	matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>

There's no power_on()/power_off() callbacks and looks a bit weird, but it's
also right... the only thing that's missing, IMO, is a comment in the actual
file explaining that power for this PHY is always on when the DP block is on
and that no PHY specific power sequence has to be carried on (being managed
elsewhere and strongly tied to the specific DP IP).

Besides that,

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
  2022-06-13 10:39     ` AngeloGioacchino Del Regno
  (?)
  (?)
@ 2022-06-16  7:00       ` Rex-BC Chen
  -1 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-16  7:00 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu, p.zabel, chunfeng.yun,
	kishon, vkoul, matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Mon, 2022-06-13 at 12:39 +0200, AngeloGioacchino Del Regno wrote:
> Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> 
> There's no power_on()/power_off() callbacks and looks a bit weird,
> but it's
> also right... the only thing that's missing, IMO, is a comment in the
> actual
> file explaining that power for this PHY is always on when the DP
> block is on
> and that no PHY specific power sequence has to be carried on (being
> managed
> elsewhere and strongly tied to the specific DP IP).
> 
> Besides that,
> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> 

Hello Angelo,

there is no power-on/off setting register for dp-phy because of the
hardware design.

Therefore, we power-on/off using enable/disable power domain.
You can see the function mtk_dp_suspend/mtk_dp_resume in mtk-dp.c
"pm_runtime_get_sync/pm_runtime_put_sync".

When the power domain is disable, the phy is also diabled.

BRs,
Bo-Chen


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-16  7:00       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-16  7:00 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu, p.zabel, chunfeng.yun,
	kishon, vkoul, matthias.bgg, airlied
  Cc: granquet, jitao.shi, linux-kernel, dri-devel, msp,
	Project_Global_Chrome_Upstream_Group, linux-phy, linux-mediatek,
	wenst, linux-arm-kernel

On Mon, 2022-06-13 at 12:39 +0200, AngeloGioacchino Del Regno wrote:
> Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> 
> There's no power_on()/power_off() callbacks and looks a bit weird,
> but it's
> also right... the only thing that's missing, IMO, is a comment in the
> actual
> file explaining that power for this PHY is always on when the DP
> block is on
> and that no PHY specific power sequence has to be carried on (being
> managed
> elsewhere and strongly tied to the specific DP IP).
> 
> Besides that,
> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> 

Hello Angelo,

there is no power-on/off setting register for dp-phy because of the
hardware design.

Therefore, we power-on/off using enable/disable power domain.
You can see the function mtk_dp_suspend/mtk_dp_resume in mtk-dp.c
"pm_runtime_get_sync/pm_runtime_put_sync".

When the power domain is disable, the phy is also diabled.

BRs,
Bo-Chen


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-16  7:00       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-16  7:00 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu, p.zabel, chunfeng.yun,
	kishon, vkoul, matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Mon, 2022-06-13 at 12:39 +0200, AngeloGioacchino Del Regno wrote:
> Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> 
> There's no power_on()/power_off() callbacks and looks a bit weird,
> but it's
> also right... the only thing that's missing, IMO, is a comment in the
> actual
> file explaining that power for this PHY is always on when the DP
> block is on
> and that no PHY specific power sequence has to be carried on (being
> managed
> elsewhere and strongly tied to the specific DP IP).
> 
> Besides that,
> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> 

Hello Angelo,

there is no power-on/off setting register for dp-phy because of the
hardware design.

Therefore, we power-on/off using enable/disable power domain.
You can see the function mtk_dp_suspend/mtk_dp_resume in mtk-dp.c
"pm_runtime_get_sync/pm_runtime_put_sync".

When the power domain is disable, the phy is also diabled.

BRs,
Bo-Chen


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-16  7:00       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-16  7:00 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, chunkuang.hu, p.zabel, chunfeng.yun,
	kishon, vkoul, matthias.bgg, airlied
  Cc: msp, granquet, jitao.shi, wenst, ck.hu, dri-devel,
	linux-mediatek, linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Mon, 2022-06-13 at 12:39 +0200, AngeloGioacchino Del Regno wrote:
> Il 13/06/22 09:26, Bo-Chen Chen ha scritto:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> 
> There's no power_on()/power_off() callbacks and looks a bit weird,
> but it's
> also right... the only thing that's missing, IMO, is a comment in the
> actual
> file explaining that power for this PHY is always on when the DP
> block is on
> and that no PHY specific power sequence has to be carried on (being
> managed
> elsewhere and strongly tied to the specific DP IP).
> 
> Besides that,
> 
> Reviewed-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> 

Hello Angelo,

there is no power-on/off setting register for dp-phy because of the
hardware design.

Therefore, we power-on/off using enable/disable power domain.
You can see the function mtk_dp_suspend/mtk_dp_resume in mtk-dp.c
"pm_runtime_get_sync/pm_runtime_put_sync".

When the power domain is disable, the phy is also diabled.

BRs,
Bo-Chen


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
  2022-06-13  7:26   ` Bo-Chen Chen
  (?)
  (?)
@ 2022-06-17  0:47     ` Vinod Koul
  -1 siblings, 0 replies; 27+ messages in thread
From: Vinod Koul @ 2022-06-17  0:47 UTC (permalink / raw)
  To: Bo-Chen Chen
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On 13-06-22, 15:26, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> ---
>  MAINTAINERS                       |   1 +
>  drivers/phy/mediatek/Kconfig      |   8 ++
>  drivers/phy/mediatek/Makefile     |   1 +
>  drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
>  4 files changed, 212 insertions(+)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a6d3bd9d2a8d..f1460ee9ce83 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
>  S:	Supported
>  F:	Documentation/devicetree/bindings/display/mediatek/
>  F:	drivers/gpu/drm/mediatek/
> +F:	drivers/phy/mediatek/phy-mtk-dp.c
>  F:	drivers/phy/mediatek/phy-mtk-hdmi*
>  F:	drivers/phy/mediatek/phy-mtk-mipi*
>  
> diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
> index 55f8e6c048ab..d631525d12e1 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
>  	select GENERIC_PHY
>  	help
>  	  Support MIPI DSI for Mediatek SoCs.
> +
> +config PHY_MTK_DP
> +	tristate "MediaTek DP-PHY Driver"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Support DisplayPort PHY for MediaTek SoCs.
> diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
> index ace660fbed3a..4ba1e0650434 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -3,6 +3,7 @@
>  # Makefile for the phy drivers.
>  #
>  
> +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
>  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
>  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
>  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
> new file mode 100644
> index 000000000000..c4d5ca1719a4
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> @@ -0,0 +1,202 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek DisplayPort PHY driver
> + *
> + * Copyright (c) 2022 BayLibre
> + * Copyright (c) 2022 MediaTek

It should be proper name of companies (hint see other uses)

> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define PHY_OFFSET			0x1000
> +
> +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> +#define TPLL_SSC_EN			BIT(3)
> +
> +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> +#define BIT_RATE_RBR			0
> +#define BIT_RATE_HBR			1
> +#define BIT_RATE_HBR2			2
> +#define BIT_RATE_HBR3			3
> +
> +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> +#define DP_GLB_SW_RST_PHYD		BIT(0)
> +
> +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
> +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
> +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
> +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> +
> +struct mtk_dp_phy {
> +	struct regmap *regs;
> +};
> +
> +static int mtk_dp_phy_init(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 driving_params[] = {
> +		DRIVING_PARAM_3_DEFAULT,
> +		DRIVING_PARAM_4_DEFAULT,
> +		DRIVING_PARAM_5_DEFAULT,
> +		DRIVING_PARAM_6_DEFAULT,
> +		DRIVING_PARAM_7_DEFAULT,
> +		DRIVING_PARAM_8_DEFAULT
> +	};
> +
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 val;
> +
> +	if (opts->dp.set_rate) {
> +		switch (opts->dp.link_rate) {
> +		default:
> +			dev_err(&phy->dev,
> +				"Implementation error, unknown linkrate %x\n",
> +				opts->dp.link_rate);
> +			return -EINVAL;
> +		case 1620:
> +			val = BIT_RATE_RBR;
> +			break;
> +		case 2700:
> +			val = BIT_RATE_HBR;
> +			break;
> +		case 5400:
> +			val = BIT_RATE_HBR2;
> +			break;
> +		case 8100:
> +			val = BIT_RATE_HBR3;
> +			break;
> +		}
> +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
> +	}
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_reset(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 0);
> +	usleep_range(50, 200);
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 1);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mtk_dp_phy_dev_ops = {
> +	.init = mtk_dp_phy_init,
> +	.configure = mtk_dp_phy_configure,
> +	.reset = mtk_dp_phy_reset,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int mtk_dp_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_dp_phy *dp_phy;
> +	struct phy *phy;
> +	struct regmap *regs;
> +
> +	regs = *(struct regmap **)dev->platform_data;

why do you need this cast away from void?

> +	if (!regs)
> +		return dev_err_probe(dev, EINVAL,
> +				     "No data passed, requires struct regmap**\n");
> +
> +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> +	if (!dp_phy)
> +		return -ENOMEM;
> +
> +	dp_phy->regs = regs;
> +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> +	if (IS_ERR(phy))
> +		return dev_err_probe(dev, PTR_ERR(phy),
> +				     "Failed to create DP PHY\n");
> +
> +	phy_set_drvdata(phy, dp_phy);
> +	if (!dev->of_node)
> +		phy_create_lookup(phy, "dp", dev_name(dev));
> +
> +	return 0;
> +}
> +
> +struct platform_driver mtk_dp_phy_driver = {
> +	.probe = mtk_dp_phy_probe,
> +	.driver = {
> +		.name = "mediatek-dp-phy",
> +	},
> +};
> +module_platform_driver(mtk_dp_phy_driver);
> +
> +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.0

-- 
~Vinod

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  0:47     ` Vinod Koul
  0 siblings, 0 replies; 27+ messages in thread
From: Vinod Koul @ 2022-06-17  0:47 UTC (permalink / raw)
  To: Bo-Chen Chen
  Cc: chunkuang.hu, granquet, jitao.shi, airlied, linux-phy,
	linux-kernel, dri-devel, kishon,
	Project_Global_Chrome_Upstream_Group, matthias.bgg,
	linux-mediatek, wenst, chunfeng.yun, msp, linux-arm-kernel,
	angelogioacchino.delregno

On 13-06-22, 15:26, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> ---
>  MAINTAINERS                       |   1 +
>  drivers/phy/mediatek/Kconfig      |   8 ++
>  drivers/phy/mediatek/Makefile     |   1 +
>  drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
>  4 files changed, 212 insertions(+)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a6d3bd9d2a8d..f1460ee9ce83 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
>  S:	Supported
>  F:	Documentation/devicetree/bindings/display/mediatek/
>  F:	drivers/gpu/drm/mediatek/
> +F:	drivers/phy/mediatek/phy-mtk-dp.c
>  F:	drivers/phy/mediatek/phy-mtk-hdmi*
>  F:	drivers/phy/mediatek/phy-mtk-mipi*
>  
> diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
> index 55f8e6c048ab..d631525d12e1 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
>  	select GENERIC_PHY
>  	help
>  	  Support MIPI DSI for Mediatek SoCs.
> +
> +config PHY_MTK_DP
> +	tristate "MediaTek DP-PHY Driver"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Support DisplayPort PHY for MediaTek SoCs.
> diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
> index ace660fbed3a..4ba1e0650434 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -3,6 +3,7 @@
>  # Makefile for the phy drivers.
>  #
>  
> +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
>  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
>  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
>  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
> new file mode 100644
> index 000000000000..c4d5ca1719a4
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> @@ -0,0 +1,202 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek DisplayPort PHY driver
> + *
> + * Copyright (c) 2022 BayLibre
> + * Copyright (c) 2022 MediaTek

It should be proper name of companies (hint see other uses)

> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define PHY_OFFSET			0x1000
> +
> +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> +#define TPLL_SSC_EN			BIT(3)
> +
> +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> +#define BIT_RATE_RBR			0
> +#define BIT_RATE_HBR			1
> +#define BIT_RATE_HBR2			2
> +#define BIT_RATE_HBR3			3
> +
> +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> +#define DP_GLB_SW_RST_PHYD		BIT(0)
> +
> +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
> +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
> +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
> +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> +
> +struct mtk_dp_phy {
> +	struct regmap *regs;
> +};
> +
> +static int mtk_dp_phy_init(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 driving_params[] = {
> +		DRIVING_PARAM_3_DEFAULT,
> +		DRIVING_PARAM_4_DEFAULT,
> +		DRIVING_PARAM_5_DEFAULT,
> +		DRIVING_PARAM_6_DEFAULT,
> +		DRIVING_PARAM_7_DEFAULT,
> +		DRIVING_PARAM_8_DEFAULT
> +	};
> +
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 val;
> +
> +	if (opts->dp.set_rate) {
> +		switch (opts->dp.link_rate) {
> +		default:
> +			dev_err(&phy->dev,
> +				"Implementation error, unknown linkrate %x\n",
> +				opts->dp.link_rate);
> +			return -EINVAL;
> +		case 1620:
> +			val = BIT_RATE_RBR;
> +			break;
> +		case 2700:
> +			val = BIT_RATE_HBR;
> +			break;
> +		case 5400:
> +			val = BIT_RATE_HBR2;
> +			break;
> +		case 8100:
> +			val = BIT_RATE_HBR3;
> +			break;
> +		}
> +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
> +	}
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_reset(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 0);
> +	usleep_range(50, 200);
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 1);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mtk_dp_phy_dev_ops = {
> +	.init = mtk_dp_phy_init,
> +	.configure = mtk_dp_phy_configure,
> +	.reset = mtk_dp_phy_reset,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int mtk_dp_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_dp_phy *dp_phy;
> +	struct phy *phy;
> +	struct regmap *regs;
> +
> +	regs = *(struct regmap **)dev->platform_data;

why do you need this cast away from void?

> +	if (!regs)
> +		return dev_err_probe(dev, EINVAL,
> +				     "No data passed, requires struct regmap**\n");
> +
> +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> +	if (!dp_phy)
> +		return -ENOMEM;
> +
> +	dp_phy->regs = regs;
> +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> +	if (IS_ERR(phy))
> +		return dev_err_probe(dev, PTR_ERR(phy),
> +				     "Failed to create DP PHY\n");
> +
> +	phy_set_drvdata(phy, dp_phy);
> +	if (!dev->of_node)
> +		phy_create_lookup(phy, "dp", dev_name(dev));
> +
> +	return 0;
> +}
> +
> +struct platform_driver mtk_dp_phy_driver = {
> +	.probe = mtk_dp_phy_probe,
> +	.driver = {
> +		.name = "mediatek-dp-phy",
> +	},
> +};
> +module_platform_driver(mtk_dp_phy_driver);
> +
> +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.0

-- 
~Vinod

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  0:47     ` Vinod Koul
  0 siblings, 0 replies; 27+ messages in thread
From: Vinod Koul @ 2022-06-17  0:47 UTC (permalink / raw)
  To: Bo-Chen Chen
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On 13-06-22, 15:26, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> ---
>  MAINTAINERS                       |   1 +
>  drivers/phy/mediatek/Kconfig      |   8 ++
>  drivers/phy/mediatek/Makefile     |   1 +
>  drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
>  4 files changed, 212 insertions(+)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a6d3bd9d2a8d..f1460ee9ce83 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
>  S:	Supported
>  F:	Documentation/devicetree/bindings/display/mediatek/
>  F:	drivers/gpu/drm/mediatek/
> +F:	drivers/phy/mediatek/phy-mtk-dp.c
>  F:	drivers/phy/mediatek/phy-mtk-hdmi*
>  F:	drivers/phy/mediatek/phy-mtk-mipi*
>  
> diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
> index 55f8e6c048ab..d631525d12e1 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
>  	select GENERIC_PHY
>  	help
>  	  Support MIPI DSI for Mediatek SoCs.
> +
> +config PHY_MTK_DP
> +	tristate "MediaTek DP-PHY Driver"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Support DisplayPort PHY for MediaTek SoCs.
> diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
> index ace660fbed3a..4ba1e0650434 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -3,6 +3,7 @@
>  # Makefile for the phy drivers.
>  #
>  
> +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
>  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
>  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
>  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
> new file mode 100644
> index 000000000000..c4d5ca1719a4
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> @@ -0,0 +1,202 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek DisplayPort PHY driver
> + *
> + * Copyright (c) 2022 BayLibre
> + * Copyright (c) 2022 MediaTek

It should be proper name of companies (hint see other uses)

> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define PHY_OFFSET			0x1000
> +
> +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> +#define TPLL_SSC_EN			BIT(3)
> +
> +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> +#define BIT_RATE_RBR			0
> +#define BIT_RATE_HBR			1
> +#define BIT_RATE_HBR2			2
> +#define BIT_RATE_HBR3			3
> +
> +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> +#define DP_GLB_SW_RST_PHYD		BIT(0)
> +
> +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
> +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
> +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
> +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> +
> +struct mtk_dp_phy {
> +	struct regmap *regs;
> +};
> +
> +static int mtk_dp_phy_init(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 driving_params[] = {
> +		DRIVING_PARAM_3_DEFAULT,
> +		DRIVING_PARAM_4_DEFAULT,
> +		DRIVING_PARAM_5_DEFAULT,
> +		DRIVING_PARAM_6_DEFAULT,
> +		DRIVING_PARAM_7_DEFAULT,
> +		DRIVING_PARAM_8_DEFAULT
> +	};
> +
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 val;
> +
> +	if (opts->dp.set_rate) {
> +		switch (opts->dp.link_rate) {
> +		default:
> +			dev_err(&phy->dev,
> +				"Implementation error, unknown linkrate %x\n",
> +				opts->dp.link_rate);
> +			return -EINVAL;
> +		case 1620:
> +			val = BIT_RATE_RBR;
> +			break;
> +		case 2700:
> +			val = BIT_RATE_HBR;
> +			break;
> +		case 5400:
> +			val = BIT_RATE_HBR2;
> +			break;
> +		case 8100:
> +			val = BIT_RATE_HBR3;
> +			break;
> +		}
> +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
> +	}
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_reset(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 0);
> +	usleep_range(50, 200);
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 1);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mtk_dp_phy_dev_ops = {
> +	.init = mtk_dp_phy_init,
> +	.configure = mtk_dp_phy_configure,
> +	.reset = mtk_dp_phy_reset,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int mtk_dp_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_dp_phy *dp_phy;
> +	struct phy *phy;
> +	struct regmap *regs;
> +
> +	regs = *(struct regmap **)dev->platform_data;

why do you need this cast away from void?

> +	if (!regs)
> +		return dev_err_probe(dev, EINVAL,
> +				     "No data passed, requires struct regmap**\n");
> +
> +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> +	if (!dp_phy)
> +		return -ENOMEM;
> +
> +	dp_phy->regs = regs;
> +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> +	if (IS_ERR(phy))
> +		return dev_err_probe(dev, PTR_ERR(phy),
> +				     "Failed to create DP PHY\n");
> +
> +	phy_set_drvdata(phy, dp_phy);
> +	if (!dev->of_node)
> +		phy_create_lookup(phy, "dp", dev_name(dev));
> +
> +	return 0;
> +}
> +
> +struct platform_driver mtk_dp_phy_driver = {
> +	.probe = mtk_dp_phy_probe,
> +	.driver = {
> +		.name = "mediatek-dp-phy",
> +	},
> +};
> +module_platform_driver(mtk_dp_phy_driver);
> +
> +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.0

-- 
~Vinod

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  0:47     ` Vinod Koul
  0 siblings, 0 replies; 27+ messages in thread
From: Vinod Koul @ 2022-06-17  0:47 UTC (permalink / raw)
  To: Bo-Chen Chen
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On 13-06-22, 15:26, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann <msp@baylibre.com>
> 
> This is a new driver that supports the integrated DisplayPort phy for
> mediatek SoCs, especially the mt8195. The phy is integrated into the
> DisplayPort controller and will be created by the mtk-dp driver. This
> driver expects a struct regmap to be able to work on the same registers
> as the DisplayPort controller. It sets the device data to be the struct
> phy so that the DisplayPort controller can easily work with it.
> 
> The driver does not have any devicetree bindings because the datasheet
> does not list the controller and the phy as distinct units.
> 
> The interaction with the controller can be covered by the configure
> callback of the phy framework and its displayport parameters.
> 
> Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> [Bo-Chen: Modify reviewers' comments.]
> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> ---
>  MAINTAINERS                       |   1 +
>  drivers/phy/mediatek/Kconfig      |   8 ++
>  drivers/phy/mediatek/Makefile     |   1 +
>  drivers/phy/mediatek/phy-mtk-dp.c | 202 ++++++++++++++++++++++++++++++
>  4 files changed, 212 insertions(+)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a6d3bd9d2a8d..f1460ee9ce83 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
>  S:	Supported
>  F:	Documentation/devicetree/bindings/display/mediatek/
>  F:	drivers/gpu/drm/mediatek/
> +F:	drivers/phy/mediatek/phy-mtk-dp.c
>  F:	drivers/phy/mediatek/phy-mtk-hdmi*
>  F:	drivers/phy/mediatek/phy-mtk-mipi*
>  
> diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
> index 55f8e6c048ab..d631525d12e1 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
>  	select GENERIC_PHY
>  	help
>  	  Support MIPI DSI for Mediatek SoCs.
> +
> +config PHY_MTK_DP
> +	tristate "MediaTek DP-PHY Driver"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Support DisplayPort PHY for MediaTek SoCs.
> diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
> index ace660fbed3a..4ba1e0650434 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -3,6 +3,7 @@
>  # Makefile for the phy drivers.
>  #
>  
> +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
>  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
>  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
>  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
> new file mode 100644
> index 000000000000..c4d5ca1719a4
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> @@ -0,0 +1,202 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MediaTek DisplayPort PHY driver
> + *
> + * Copyright (c) 2022 BayLibre
> + * Copyright (c) 2022 MediaTek

It should be proper name of companies (hint see other uses)

> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define PHY_OFFSET			0x1000
> +
> +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> +#define TPLL_SSC_EN			BIT(3)
> +
> +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> +#define BIT_RATE_RBR			0
> +#define BIT_RATE_HBR			1
> +#define BIT_RATE_HBR2			2
> +#define BIT_RATE_HBR3			3
> +
> +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> +#define DP_GLB_SW_RST_PHYD		BIT(0)
> +
> +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET + 0x138)
> +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET + 0x238)
> +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET + 0x338)
> +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET + 0x438)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> +
> +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
> +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> +
> +struct mtk_dp_phy {
> +	struct regmap *regs;
> +};
> +
> +static int mtk_dp_phy_init(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 driving_params[] = {
> +		DRIVING_PARAM_3_DEFAULT,
> +		DRIVING_PARAM_4_DEFAULT,
> +		DRIVING_PARAM_5_DEFAULT,
> +		DRIVING_PARAM_6_DEFAULT,
> +		DRIVING_PARAM_7_DEFAULT,
> +		DRIVING_PARAM_8_DEFAULT
> +	};
> +
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> +			  driving_params, ARRAY_SIZE(driving_params));
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +	u32 val;
> +
> +	if (opts->dp.set_rate) {
> +		switch (opts->dp.link_rate) {
> +		default:
> +			dev_err(&phy->dev,
> +				"Implementation error, unknown linkrate %x\n",
> +				opts->dp.link_rate);
> +			return -EINVAL;
> +		case 1620:
> +			val = BIT_RATE_RBR;
> +			break;
> +		case 2700:
> +			val = BIT_RATE_HBR;
> +			break;
> +		case 5400:
> +			val = BIT_RATE_HBR2;
> +			break;
> +		case 8100:
> +			val = BIT_RATE_HBR3;
> +			break;
> +		}
> +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
> +	}
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
> +
> +	return 0;
> +}
> +
> +static int mtk_dp_phy_reset(struct phy *phy)
> +{
> +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> +
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 0);
> +	usleep_range(50, 200);
> +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> +			   DP_GLB_SW_RST_PHYD, 1);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mtk_dp_phy_dev_ops = {
> +	.init = mtk_dp_phy_init,
> +	.configure = mtk_dp_phy_configure,
> +	.reset = mtk_dp_phy_reset,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int mtk_dp_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_dp_phy *dp_phy;
> +	struct phy *phy;
> +	struct regmap *regs;
> +
> +	regs = *(struct regmap **)dev->platform_data;

why do you need this cast away from void?

> +	if (!regs)
> +		return dev_err_probe(dev, EINVAL,
> +				     "No data passed, requires struct regmap**\n");
> +
> +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> +	if (!dp_phy)
> +		return -ENOMEM;
> +
> +	dp_phy->regs = regs;
> +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> +	if (IS_ERR(phy))
> +		return dev_err_probe(dev, PTR_ERR(phy),
> +				     "Failed to create DP PHY\n");
> +
> +	phy_set_drvdata(phy, dp_phy);
> +	if (!dev->of_node)
> +		phy_create_lookup(phy, "dp", dev_name(dev));
> +
> +	return 0;
> +}
> +
> +struct platform_driver mtk_dp_phy_driver = {
> +	.probe = mtk_dp_phy_probe,
> +	.driver = {
> +		.name = "mediatek-dp-phy",
> +	},
> +};
> +module_platform_driver(mtk_dp_phy_driver);
> +
> +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.0

-- 
~Vinod

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
  2022-06-17  0:47     ` Vinod Koul
  (?)
  (?)
@ 2022-06-17  8:25       ` Rex-BC Chen
  -1 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-17  8:25 UTC (permalink / raw)
  To: Vinod Koul
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Thu, 2022-06-16 at 17:47 -0700, Vinod Koul wrote:
> On 13-06-22, 15:26, Bo-Chen Chen wrote:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> > ---
> >  MAINTAINERS                       |   1 +
> >  drivers/phy/mediatek/Kconfig      |   8 ++
> >  drivers/phy/mediatek/Makefile     |   1 +
> >  drivers/phy/mediatek/phy-mtk-dp.c | 202
> > ++++++++++++++++++++++++++++++
> >  4 files changed, 212 insertions(+)
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a6d3bd9d2a8d..f1460ee9ce83 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org
> > (moderated for non-subscribers)
> >  S:	Supported
> >  F:	Documentation/devicetree/bindings/display/mediatek/
> >  F:	drivers/gpu/drm/mediatek/
> > +F:	drivers/phy/mediatek/phy-mtk-dp.c
> >  F:	drivers/phy/mediatek/phy-mtk-hdmi*
> >  F:	drivers/phy/mediatek/phy-mtk-mipi*
> >  
> > diff --git a/drivers/phy/mediatek/Kconfig
> > b/drivers/phy/mediatek/Kconfig
> > index 55f8e6c048ab..d631525d12e1 100644
> > --- a/drivers/phy/mediatek/Kconfig
> > +++ b/drivers/phy/mediatek/Kconfig
> > @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
> >  	select GENERIC_PHY
> >  	help
> >  	  Support MIPI DSI for Mediatek SoCs.
> > +
> > +config PHY_MTK_DP
> > +	tristate "MediaTek DP-PHY Driver"
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	depends on OF
> > +	select GENERIC_PHY
> > +	help
> > +	  Support DisplayPort PHY for MediaTek SoCs.
> > diff --git a/drivers/phy/mediatek/Makefile
> > b/drivers/phy/mediatek/Makefile
> > index ace660fbed3a..4ba1e0650434 100644
> > --- a/drivers/phy/mediatek/Makefile
> > +++ b/drivers/phy/mediatek/Makefile
> > @@ -3,6 +3,7 @@
> >  # Makefile for the phy drivers.
> >  #
> >  
> > +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
> >  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
> >  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
> >  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> > diff --git a/drivers/phy/mediatek/phy-mtk-dp.c
> > b/drivers/phy/mediatek/phy-mtk-dp.c
> > new file mode 100644
> > index 000000000000..c4d5ca1719a4
> > --- /dev/null
> > +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> > @@ -0,0 +1,202 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * MediaTek DisplayPort PHY driver
> > + *
> > + * Copyright (c) 2022 BayLibre
> > + * Copyright (c) 2022 MediaTek
> 
> It should be proper name of companies (hint see other uses)
> 

Hello Vinod,

Thanks for review.
I will modify like this:
 /*
  * MediaTek DisplayPort PHY driver
  *
  * Copyright (c) 2022 BayLibre Inc.
  * Copyright (c) 2022 MediaTek Inc.
  */
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#define PHY_OFFSET			0x1000
> > +
> > +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> > +#define TPLL_SSC_EN			BIT(3)
> > +
> > +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> > +#define BIT_RATE_RBR			0
> > +#define BIT_RATE_HBR			1
> > +#define BIT_RATE_HBR2			2
> > +#define BIT_RATE_HBR3			3
> > +
> > +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> > +#define DP_GLB_SW_RST_PHYD		BIT(0)
> > +
> > +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x138)
> > +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x238)
> > +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x338)
> > +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x438)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> > +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> > +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> > +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> > +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> > +
> > +struct mtk_dp_phy {
> > +	struct regmap *regs;
> > +};
> > +
> > +static int mtk_dp_phy_init(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 driving_params[] = {
> > +		DRIVING_PARAM_3_DEFAULT,
> > +		DRIVING_PARAM_4_DEFAULT,
> > +		DRIVING_PARAM_5_DEFAULT,
> > +		DRIVING_PARAM_6_DEFAULT,
> > +		DRIVING_PARAM_7_DEFAULT,
> > +		DRIVING_PARAM_8_DEFAULT
> > +	};
> > +
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_configure(struct phy *phy, union
> > phy_configure_opts *opts)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 val;
> > +
> > +	if (opts->dp.set_rate) {
> > +		switch (opts->dp.link_rate) {
> > +		default:
> > +			dev_err(&phy->dev,
> > +				"Implementation error, unknown linkrate
> > %x\n",
> > +				opts->dp.link_rate);
> > +			return -EINVAL;
> > +		case 1620:
> > +			val = BIT_RATE_RBR;
> > +			break;
> > +		case 2700:
> > +			val = BIT_RATE_HBR;
> > +			break;
> > +		case 5400:
> > +			val = BIT_RATE_HBR2;
> > +			break;
> > +		case 8100:
> > +			val = BIT_RATE_HBR3;
> > +			break;
> > +		}
> > +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE,
> > val);
> > +	}
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> > +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN :
> > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_reset(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 0);
> > +	usleep_range(50, 200);
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 1);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops mtk_dp_phy_dev_ops = {
> > +	.init = mtk_dp_phy_init,
> > +	.configure = mtk_dp_phy_configure,
> > +	.reset = mtk_dp_phy_reset,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int mtk_dp_phy_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct mtk_dp_phy *dp_phy;
> > +	struct phy *phy;
> > +	struct regmap *regs;
> > +
> > +	regs = *(struct regmap **)dev->platform_data;
> 
> why do you need this cast away from void?
> 

When register platform data (in mtk_dp.c prober)
we do this where "struct regmap *regs;":

mtk_dp->phy_dev = platform_device_register_data(
			dev, "mediatek-dp-phy",
			PLATFORM_DEVID_AUTO, &mtk_dp->regs,
			sizeof(struct regmap *));

refer to [1].

[1]: 
https://lore.kernel.org/all/20220610105522.13449-6-rex-bc.chen@mediatek.com/

BRs,
Bo-Chen
> > +	if (!regs)
> > +		return dev_err_probe(dev, EINVAL,
> > +				     "No data passed, requires struct
> > regmap**\n");
> > +
> > +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> > +	if (!dp_phy)
> > +		return -ENOMEM;
> > +
> > +	dp_phy->regs = regs;
> > +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> > +	if (IS_ERR(phy))
> > +		return dev_err_probe(dev, PTR_ERR(phy),
> > +				     "Failed to create DP PHY\n");
> > +
> > +	phy_set_drvdata(phy, dp_phy);
> > +	if (!dev->of_node)
> > +		phy_create_lookup(phy, "dp", dev_name(dev));
> > +
> > +	return 0;
> > +}
> > +
> > +struct platform_driver mtk_dp_phy_driver = {
> > +	.probe = mtk_dp_phy_probe,
> > +	.driver = {
> > +		.name = "mediatek-dp-phy",
> > +	},
> > +};
> > +module_platform_driver(mtk_dp_phy_driver);
> > +
> > +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> > +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.18.0
> 
> 


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  8:25       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-17  8:25 UTC (permalink / raw)
  To: Vinod Koul
  Cc: chunkuang.hu, granquet, jitao.shi, airlied, linux-phy,
	linux-kernel, dri-devel, kishon,
	Project_Global_Chrome_Upstream_Group, matthias.bgg,
	linux-mediatek, wenst, chunfeng.yun, msp, linux-arm-kernel,
	angelogioacchino.delregno

On Thu, 2022-06-16 at 17:47 -0700, Vinod Koul wrote:
> On 13-06-22, 15:26, Bo-Chen Chen wrote:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> > ---
> >  MAINTAINERS                       |   1 +
> >  drivers/phy/mediatek/Kconfig      |   8 ++
> >  drivers/phy/mediatek/Makefile     |   1 +
> >  drivers/phy/mediatek/phy-mtk-dp.c | 202
> > ++++++++++++++++++++++++++++++
> >  4 files changed, 212 insertions(+)
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a6d3bd9d2a8d..f1460ee9ce83 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org
> > (moderated for non-subscribers)
> >  S:	Supported
> >  F:	Documentation/devicetree/bindings/display/mediatek/
> >  F:	drivers/gpu/drm/mediatek/
> > +F:	drivers/phy/mediatek/phy-mtk-dp.c
> >  F:	drivers/phy/mediatek/phy-mtk-hdmi*
> >  F:	drivers/phy/mediatek/phy-mtk-mipi*
> >  
> > diff --git a/drivers/phy/mediatek/Kconfig
> > b/drivers/phy/mediatek/Kconfig
> > index 55f8e6c048ab..d631525d12e1 100644
> > --- a/drivers/phy/mediatek/Kconfig
> > +++ b/drivers/phy/mediatek/Kconfig
> > @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
> >  	select GENERIC_PHY
> >  	help
> >  	  Support MIPI DSI for Mediatek SoCs.
> > +
> > +config PHY_MTK_DP
> > +	tristate "MediaTek DP-PHY Driver"
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	depends on OF
> > +	select GENERIC_PHY
> > +	help
> > +	  Support DisplayPort PHY for MediaTek SoCs.
> > diff --git a/drivers/phy/mediatek/Makefile
> > b/drivers/phy/mediatek/Makefile
> > index ace660fbed3a..4ba1e0650434 100644
> > --- a/drivers/phy/mediatek/Makefile
> > +++ b/drivers/phy/mediatek/Makefile
> > @@ -3,6 +3,7 @@
> >  # Makefile for the phy drivers.
> >  #
> >  
> > +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
> >  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
> >  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
> >  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> > diff --git a/drivers/phy/mediatek/phy-mtk-dp.c
> > b/drivers/phy/mediatek/phy-mtk-dp.c
> > new file mode 100644
> > index 000000000000..c4d5ca1719a4
> > --- /dev/null
> > +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> > @@ -0,0 +1,202 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * MediaTek DisplayPort PHY driver
> > + *
> > + * Copyright (c) 2022 BayLibre
> > + * Copyright (c) 2022 MediaTek
> 
> It should be proper name of companies (hint see other uses)
> 

Hello Vinod,

Thanks for review.
I will modify like this:
 /*
  * MediaTek DisplayPort PHY driver
  *
  * Copyright (c) 2022 BayLibre Inc.
  * Copyright (c) 2022 MediaTek Inc.
  */
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#define PHY_OFFSET			0x1000
> > +
> > +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> > +#define TPLL_SSC_EN			BIT(3)
> > +
> > +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> > +#define BIT_RATE_RBR			0
> > +#define BIT_RATE_HBR			1
> > +#define BIT_RATE_HBR2			2
> > +#define BIT_RATE_HBR3			3
> > +
> > +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> > +#define DP_GLB_SW_RST_PHYD		BIT(0)
> > +
> > +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x138)
> > +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x238)
> > +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x338)
> > +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x438)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> > +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> > +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> > +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> > +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> > +
> > +struct mtk_dp_phy {
> > +	struct regmap *regs;
> > +};
> > +
> > +static int mtk_dp_phy_init(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 driving_params[] = {
> > +		DRIVING_PARAM_3_DEFAULT,
> > +		DRIVING_PARAM_4_DEFAULT,
> > +		DRIVING_PARAM_5_DEFAULT,
> > +		DRIVING_PARAM_6_DEFAULT,
> > +		DRIVING_PARAM_7_DEFAULT,
> > +		DRIVING_PARAM_8_DEFAULT
> > +	};
> > +
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_configure(struct phy *phy, union
> > phy_configure_opts *opts)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 val;
> > +
> > +	if (opts->dp.set_rate) {
> > +		switch (opts->dp.link_rate) {
> > +		default:
> > +			dev_err(&phy->dev,
> > +				"Implementation error, unknown linkrate
> > %x\n",
> > +				opts->dp.link_rate);
> > +			return -EINVAL;
> > +		case 1620:
> > +			val = BIT_RATE_RBR;
> > +			break;
> > +		case 2700:
> > +			val = BIT_RATE_HBR;
> > +			break;
> > +		case 5400:
> > +			val = BIT_RATE_HBR2;
> > +			break;
> > +		case 8100:
> > +			val = BIT_RATE_HBR3;
> > +			break;
> > +		}
> > +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE,
> > val);
> > +	}
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> > +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN :
> > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_reset(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 0);
> > +	usleep_range(50, 200);
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 1);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops mtk_dp_phy_dev_ops = {
> > +	.init = mtk_dp_phy_init,
> > +	.configure = mtk_dp_phy_configure,
> > +	.reset = mtk_dp_phy_reset,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int mtk_dp_phy_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct mtk_dp_phy *dp_phy;
> > +	struct phy *phy;
> > +	struct regmap *regs;
> > +
> > +	regs = *(struct regmap **)dev->platform_data;
> 
> why do you need this cast away from void?
> 

When register platform data (in mtk_dp.c prober)
we do this where "struct regmap *regs;":

mtk_dp->phy_dev = platform_device_register_data(
			dev, "mediatek-dp-phy",
			PLATFORM_DEVID_AUTO, &mtk_dp->regs,
			sizeof(struct regmap *));

refer to [1].

[1]: 
https://lore.kernel.org/all/20220610105522.13449-6-rex-bc.chen@mediatek.com/

BRs,
Bo-Chen
> > +	if (!regs)
> > +		return dev_err_probe(dev, EINVAL,
> > +				     "No data passed, requires struct
> > regmap**\n");
> > +
> > +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> > +	if (!dp_phy)
> > +		return -ENOMEM;
> > +
> > +	dp_phy->regs = regs;
> > +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> > +	if (IS_ERR(phy))
> > +		return dev_err_probe(dev, PTR_ERR(phy),
> > +				     "Failed to create DP PHY\n");
> > +
> > +	phy_set_drvdata(phy, dp_phy);
> > +	if (!dev->of_node)
> > +		phy_create_lookup(phy, "dp", dev_name(dev));
> > +
> > +	return 0;
> > +}
> > +
> > +struct platform_driver mtk_dp_phy_driver = {
> > +	.probe = mtk_dp_phy_probe,
> > +	.driver = {
> > +		.name = "mediatek-dp-phy",
> > +	},
> > +};
> > +module_platform_driver(mtk_dp_phy_driver);
> > +
> > +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> > +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.18.0
> 
> 


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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  8:25       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-17  8:25 UTC (permalink / raw)
  To: Vinod Koul
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Thu, 2022-06-16 at 17:47 -0700, Vinod Koul wrote:
> On 13-06-22, 15:26, Bo-Chen Chen wrote:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> > ---
> >  MAINTAINERS                       |   1 +
> >  drivers/phy/mediatek/Kconfig      |   8 ++
> >  drivers/phy/mediatek/Makefile     |   1 +
> >  drivers/phy/mediatek/phy-mtk-dp.c | 202
> > ++++++++++++++++++++++++++++++
> >  4 files changed, 212 insertions(+)
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a6d3bd9d2a8d..f1460ee9ce83 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org
> > (moderated for non-subscribers)
> >  S:	Supported
> >  F:	Documentation/devicetree/bindings/display/mediatek/
> >  F:	drivers/gpu/drm/mediatek/
> > +F:	drivers/phy/mediatek/phy-mtk-dp.c
> >  F:	drivers/phy/mediatek/phy-mtk-hdmi*
> >  F:	drivers/phy/mediatek/phy-mtk-mipi*
> >  
> > diff --git a/drivers/phy/mediatek/Kconfig
> > b/drivers/phy/mediatek/Kconfig
> > index 55f8e6c048ab..d631525d12e1 100644
> > --- a/drivers/phy/mediatek/Kconfig
> > +++ b/drivers/phy/mediatek/Kconfig
> > @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
> >  	select GENERIC_PHY
> >  	help
> >  	  Support MIPI DSI for Mediatek SoCs.
> > +
> > +config PHY_MTK_DP
> > +	tristate "MediaTek DP-PHY Driver"
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	depends on OF
> > +	select GENERIC_PHY
> > +	help
> > +	  Support DisplayPort PHY for MediaTek SoCs.
> > diff --git a/drivers/phy/mediatek/Makefile
> > b/drivers/phy/mediatek/Makefile
> > index ace660fbed3a..4ba1e0650434 100644
> > --- a/drivers/phy/mediatek/Makefile
> > +++ b/drivers/phy/mediatek/Makefile
> > @@ -3,6 +3,7 @@
> >  # Makefile for the phy drivers.
> >  #
> >  
> > +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
> >  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
> >  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
> >  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> > diff --git a/drivers/phy/mediatek/phy-mtk-dp.c
> > b/drivers/phy/mediatek/phy-mtk-dp.c
> > new file mode 100644
> > index 000000000000..c4d5ca1719a4
> > --- /dev/null
> > +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> > @@ -0,0 +1,202 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * MediaTek DisplayPort PHY driver
> > + *
> > + * Copyright (c) 2022 BayLibre
> > + * Copyright (c) 2022 MediaTek
> 
> It should be proper name of companies (hint see other uses)
> 

Hello Vinod,

Thanks for review.
I will modify like this:
 /*
  * MediaTek DisplayPort PHY driver
  *
  * Copyright (c) 2022 BayLibre Inc.
  * Copyright (c) 2022 MediaTek Inc.
  */
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#define PHY_OFFSET			0x1000
> > +
> > +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> > +#define TPLL_SSC_EN			BIT(3)
> > +
> > +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> > +#define BIT_RATE_RBR			0
> > +#define BIT_RATE_HBR			1
> > +#define BIT_RATE_HBR2			2
> > +#define BIT_RATE_HBR3			3
> > +
> > +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> > +#define DP_GLB_SW_RST_PHYD		BIT(0)
> > +
> > +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x138)
> > +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x238)
> > +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x338)
> > +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x438)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> > +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> > +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> > +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> > +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> > +
> > +struct mtk_dp_phy {
> > +	struct regmap *regs;
> > +};
> > +
> > +static int mtk_dp_phy_init(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 driving_params[] = {
> > +		DRIVING_PARAM_3_DEFAULT,
> > +		DRIVING_PARAM_4_DEFAULT,
> > +		DRIVING_PARAM_5_DEFAULT,
> > +		DRIVING_PARAM_6_DEFAULT,
> > +		DRIVING_PARAM_7_DEFAULT,
> > +		DRIVING_PARAM_8_DEFAULT
> > +	};
> > +
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_configure(struct phy *phy, union
> > phy_configure_opts *opts)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 val;
> > +
> > +	if (opts->dp.set_rate) {
> > +		switch (opts->dp.link_rate) {
> > +		default:
> > +			dev_err(&phy->dev,
> > +				"Implementation error, unknown linkrate
> > %x\n",
> > +				opts->dp.link_rate);
> > +			return -EINVAL;
> > +		case 1620:
> > +			val = BIT_RATE_RBR;
> > +			break;
> > +		case 2700:
> > +			val = BIT_RATE_HBR;
> > +			break;
> > +		case 5400:
> > +			val = BIT_RATE_HBR2;
> > +			break;
> > +		case 8100:
> > +			val = BIT_RATE_HBR3;
> > +			break;
> > +		}
> > +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE,
> > val);
> > +	}
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> > +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN :
> > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_reset(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 0);
> > +	usleep_range(50, 200);
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 1);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops mtk_dp_phy_dev_ops = {
> > +	.init = mtk_dp_phy_init,
> > +	.configure = mtk_dp_phy_configure,
> > +	.reset = mtk_dp_phy_reset,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int mtk_dp_phy_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct mtk_dp_phy *dp_phy;
> > +	struct phy *phy;
> > +	struct regmap *regs;
> > +
> > +	regs = *(struct regmap **)dev->platform_data;
> 
> why do you need this cast away from void?
> 

When register platform data (in mtk_dp.c prober)
we do this where "struct regmap *regs;":

mtk_dp->phy_dev = platform_device_register_data(
			dev, "mediatek-dp-phy",
			PLATFORM_DEVID_AUTO, &mtk_dp->regs,
			sizeof(struct regmap *));

refer to [1].

[1]: 
https://lore.kernel.org/all/20220610105522.13449-6-rex-bc.chen@mediatek.com/

BRs,
Bo-Chen
> > +	if (!regs)
> > +		return dev_err_probe(dev, EINVAL,
> > +				     "No data passed, requires struct
> > regmap**\n");
> > +
> > +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> > +	if (!dp_phy)
> > +		return -ENOMEM;
> > +
> > +	dp_phy->regs = regs;
> > +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> > +	if (IS_ERR(phy))
> > +		return dev_err_probe(dev, PTR_ERR(phy),
> > +				     "Failed to create DP PHY\n");
> > +
> > +	phy_set_drvdata(phy, dp_phy);
> > +	if (!dev->of_node)
> > +		phy_create_lookup(phy, "dp", dev_name(dev));
> > +
> > +	return 0;
> > +}
> > +
> > +struct platform_driver mtk_dp_phy_driver = {
> > +	.probe = mtk_dp_phy_probe,
> > +	.driver = {
> > +		.name = "mediatek-dp-phy",
> > +	},
> > +};
> > +module_platform_driver(mtk_dp_phy_driver);
> > +
> > +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> > +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.18.0
> 
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy
@ 2022-06-17  8:25       ` Rex-BC Chen
  0 siblings, 0 replies; 27+ messages in thread
From: Rex-BC Chen @ 2022-06-17  8:25 UTC (permalink / raw)
  To: Vinod Koul
  Cc: chunkuang.hu, p.zabel, chunfeng.yun, kishon, matthias.bgg,
	airlied, msp, granquet, jitao.shi, wenst,
	angelogioacchino.delregno, ck.hu, dri-devel, linux-mediatek,
	linux-phy, linux-kernel, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

On Thu, 2022-06-16 at 17:47 -0700, Vinod Koul wrote:
> On 13-06-22, 15:26, Bo-Chen Chen wrote:
> > From: Markus Schneider-Pargmann <msp@baylibre.com>
> > 
> > This is a new driver that supports the integrated DisplayPort phy
> > for
> > mediatek SoCs, especially the mt8195. The phy is integrated into
> > the
> > DisplayPort controller and will be created by the mtk-dp driver.
> > This
> > driver expects a struct regmap to be able to work on the same
> > registers
> > as the DisplayPort controller. It sets the device data to be the
> > struct
> > phy so that the DisplayPort controller can easily work with it.
> > 
> > The driver does not have any devicetree bindings because the
> > datasheet
> > does not list the controller and the phy as distinct units.
> > 
> > The interaction with the controller can be covered by the configure
> > callback of the phy framework and its displayport parameters.
> > 
> > Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
> > Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
> > [Bo-Chen: Modify reviewers' comments.]
> > Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
> > ---
> >  MAINTAINERS                       |   1 +
> >  drivers/phy/mediatek/Kconfig      |   8 ++
> >  drivers/phy/mediatek/Makefile     |   1 +
> >  drivers/phy/mediatek/phy-mtk-dp.c | 202
> > ++++++++++++++++++++++++++++++
> >  4 files changed, 212 insertions(+)
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a6d3bd9d2a8d..f1460ee9ce83 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -6698,6 +6698,7 @@ L:	linux-mediatek@lists.infradead.org
> > (moderated for non-subscribers)
> >  S:	Supported
> >  F:	Documentation/devicetree/bindings/display/mediatek/
> >  F:	drivers/gpu/drm/mediatek/
> > +F:	drivers/phy/mediatek/phy-mtk-dp.c
> >  F:	drivers/phy/mediatek/phy-mtk-hdmi*
> >  F:	drivers/phy/mediatek/phy-mtk-mipi*
> >  
> > diff --git a/drivers/phy/mediatek/Kconfig
> > b/drivers/phy/mediatek/Kconfig
> > index 55f8e6c048ab..d631525d12e1 100644
> > --- a/drivers/phy/mediatek/Kconfig
> > +++ b/drivers/phy/mediatek/Kconfig
> > @@ -55,3 +55,11 @@ config PHY_MTK_MIPI_DSI
> >  	select GENERIC_PHY
> >  	help
> >  	  Support MIPI DSI for Mediatek SoCs.
> > +
> > +config PHY_MTK_DP
> > +	tristate "MediaTek DP-PHY Driver"
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	depends on OF
> > +	select GENERIC_PHY
> > +	help
> > +	  Support DisplayPort PHY for MediaTek SoCs.
> > diff --git a/drivers/phy/mediatek/Makefile
> > b/drivers/phy/mediatek/Makefile
> > index ace660fbed3a..4ba1e0650434 100644
> > --- a/drivers/phy/mediatek/Makefile
> > +++ b/drivers/phy/mediatek/Makefile
> > @@ -3,6 +3,7 @@
> >  # Makefile for the phy drivers.
> >  #
> >  
> > +obj-$(CONFIG_PHY_MTK_DP)		+= phy-mtk-dp.o
> >  obj-$(CONFIG_PHY_MTK_TPHY)		+= phy-mtk-tphy.o
> >  obj-$(CONFIG_PHY_MTK_UFS)		+= phy-mtk-ufs.o
> >  obj-$(CONFIG_PHY_MTK_XSPHY)		+= phy-mtk-xsphy.o
> > diff --git a/drivers/phy/mediatek/phy-mtk-dp.c
> > b/drivers/phy/mediatek/phy-mtk-dp.c
> > new file mode 100644
> > index 000000000000..c4d5ca1719a4
> > --- /dev/null
> > +++ b/drivers/phy/mediatek/phy-mtk-dp.c
> > @@ -0,0 +1,202 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * MediaTek DisplayPort PHY driver
> > + *
> > + * Copyright (c) 2022 BayLibre
> > + * Copyright (c) 2022 MediaTek
> 
> It should be proper name of companies (hint see other uses)
> 

Hello Vinod,

Thanks for review.
I will modify like this:
 /*
  * MediaTek DisplayPort PHY driver
  *
  * Copyright (c) 2022 BayLibre Inc.
  * Copyright (c) 2022 MediaTek Inc.
  */
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#define PHY_OFFSET			0x1000
> > +
> > +#define MTK_DP_PHY_DIG_PLL_CTL_1	(PHY_OFFSET + 0x14)
> > +#define TPLL_SSC_EN			BIT(3)
> > +
> > +#define MTK_DP_PHY_DIG_BIT_RATE		(PHY_OFFSET + 0x3C)
> > +#define BIT_RATE_RBR			0
> > +#define BIT_RATE_HBR			1
> > +#define BIT_RATE_HBR2			2
> > +#define BIT_RATE_HBR3			3
> > +
> > +#define MTK_DP_PHY_DIG_SW_RST		(PHY_OFFSET + 0x38)
> > +#define DP_GLB_SW_RST_PHYD		BIT(0)
> > +
> > +#define MTK_DP_LANE0_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x138)
> > +#define MTK_DP_LANE1_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x238)
> > +#define MTK_DP_LANE2_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x338)
> > +#define MTK_DP_LANE3_DRIVING_PARAM_3		(PHY_OFFSET +
> > 0x438)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT	BIT(4)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT	(BIT(10) | BIT(12))
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT	GENMASK(20, 19)
> > +#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_3_DEFAULT	(XTP_LN_TX_LCTXC0_SW0_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT	GENMASK(4, 3)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT	GENMASK(12, 9)
> > +#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT	(BIT(18) | BIT(21))
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT	GENMASK(29, 29)
> > +#define DRIVING_PARAM_4_DEFAULT	(XTP_LN_TX_LCTXC0_SW1_PRE0_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT	(BIT(3) | BIT(5))
> > +#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT	GENMASK(13, 12)
> > +#define DRIVING_PARAM_5_DEFAULT	(XTP_LN_TX_LCTXC0_SW2_PRE1_DEFA
> > ULT | \
> > +				 XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT	GENMASK(10, 10)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT	GENMASK(19, 19)
> > +#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT	GENMASK(28, 28)
> > +#define DRIVING_PARAM_6_DEFAULT	(XTP_LN_TX_LCTXCP1_SW0_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT	0
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT	GENMASK(10, 9)
> > +#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT	GENMASK(19, 18)
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_7_DEFAULT	(XTP_LN_TX_LCTXCP1_SW1_PRE0_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
> > +
> > +#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT	GENMASK(3, 3)
> > +#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT	0
> > +#define DRIVING_PARAM_8_DEFAULT	(XTP_LN_TX_LCTXCP1_SW2_PRE1_DEF
> > AULT | \
> > +				 XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
> > +
> > +struct mtk_dp_phy {
> > +	struct regmap *regs;
> > +};
> > +
> > +static int mtk_dp_phy_init(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 driving_params[] = {
> > +		DRIVING_PARAM_3_DEFAULT,
> > +		DRIVING_PARAM_4_DEFAULT,
> > +		DRIVING_PARAM_5_DEFAULT,
> > +		DRIVING_PARAM_6_DEFAULT,
> > +		DRIVING_PARAM_7_DEFAULT,
> > +		DRIVING_PARAM_8_DEFAULT
> > +	};
> > +
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +	regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
> > +			  driving_params, ARRAY_SIZE(driving_params));
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_configure(struct phy *phy, union
> > phy_configure_opts *opts)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +	u32 val;
> > +
> > +	if (opts->dp.set_rate) {
> > +		switch (opts->dp.link_rate) {
> > +		default:
> > +			dev_err(&phy->dev,
> > +				"Implementation error, unknown linkrate
> > %x\n",
> > +				opts->dp.link_rate);
> > +			return -EINVAL;
> > +		case 1620:
> > +			val = BIT_RATE_RBR;
> > +			break;
> > +		case 2700:
> > +			val = BIT_RATE_HBR;
> > +			break;
> > +		case 5400:
> > +			val = BIT_RATE_HBR2;
> > +			break;
> > +		case 8100:
> > +			val = BIT_RATE_HBR3;
> > +			break;
> > +		}
> > +		regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE,
> > val);
> > +	}
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
> > +			   TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN :
> > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_dp_phy_reset(struct phy *phy)
> > +{
> > +	struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
> > +
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 0);
> > +	usleep_range(50, 200);
> > +	regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
> > +			   DP_GLB_SW_RST_PHYD, 1);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops mtk_dp_phy_dev_ops = {
> > +	.init = mtk_dp_phy_init,
> > +	.configure = mtk_dp_phy_configure,
> > +	.reset = mtk_dp_phy_reset,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int mtk_dp_phy_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct mtk_dp_phy *dp_phy;
> > +	struct phy *phy;
> > +	struct regmap *regs;
> > +
> > +	regs = *(struct regmap **)dev->platform_data;
> 
> why do you need this cast away from void?
> 

When register platform data (in mtk_dp.c prober)
we do this where "struct regmap *regs;":

mtk_dp->phy_dev = platform_device_register_data(
			dev, "mediatek-dp-phy",
			PLATFORM_DEVID_AUTO, &mtk_dp->regs,
			sizeof(struct regmap *));

refer to [1].

[1]: 
https://lore.kernel.org/all/20220610105522.13449-6-rex-bc.chen@mediatek.com/

BRs,
Bo-Chen
> > +	if (!regs)
> > +		return dev_err_probe(dev, EINVAL,
> > +				     "No data passed, requires struct
> > regmap**\n");
> > +
> > +	dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
> > +	if (!dp_phy)
> > +		return -ENOMEM;
> > +
> > +	dp_phy->regs = regs;
> > +	phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
> > +	if (IS_ERR(phy))
> > +		return dev_err_probe(dev, PTR_ERR(phy),
> > +				     "Failed to create DP PHY\n");
> > +
> > +	phy_set_drvdata(phy, dp_phy);
> > +	if (!dev->of_node)
> > +		phy_create_lookup(phy, "dp", dev_name(dev));
> > +
> > +	return 0;
> > +}
> > +
> > +struct platform_driver mtk_dp_phy_driver = {
> > +	.probe = mtk_dp_phy_probe,
> > +	.driver = {
> > +		.name = "mediatek-dp-phy",
> > +	},
> > +};
> > +module_platform_driver(mtk_dp_phy_driver);
> > +
> > +MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
> > +MODULE_DESCRIPTION("MediaTek DP PHY Driver");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.18.0
> 
> 


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

end of thread, other threads:[~2022-06-17  8:30 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-13  7:26 [PATCH v11 0/1] drm/mediatek: Add MT8195 DisplayPort PHY driver Bo-Chen Chen
2022-06-13  7:26 ` Bo-Chen Chen
2022-06-13  7:26 ` Bo-Chen Chen
2022-06-13  7:26 ` Bo-Chen Chen
2022-06-13  7:26 ` Bo-Chen Chen
2022-06-13  7:26 ` [PATCH v11 1/1] phy: phy-mtk-dp: Add driver for DP phy Bo-Chen Chen
2022-06-13  7:26   ` Bo-Chen Chen
2022-06-13  7:26   ` Bo-Chen Chen
2022-06-13  7:26   ` Bo-Chen Chen
2022-06-13  7:26   ` Bo-Chen Chen
2022-06-13 10:39   ` AngeloGioacchino Del Regno
2022-06-13 10:39     ` AngeloGioacchino Del Regno
2022-06-13 10:39     ` AngeloGioacchino Del Regno
2022-06-13 10:39     ` AngeloGioacchino Del Regno
2022-06-13 10:39     ` AngeloGioacchino Del Regno
2022-06-16  7:00     ` Rex-BC Chen
2022-06-16  7:00       ` Rex-BC Chen
2022-06-16  7:00       ` Rex-BC Chen
2022-06-16  7:00       ` Rex-BC Chen
2022-06-17  0:47   ` Vinod Koul
2022-06-17  0:47     ` Vinod Koul
2022-06-17  0:47     ` Vinod Koul
2022-06-17  0:47     ` Vinod Koul
2022-06-17  8:25     ` Rex-BC Chen
2022-06-17  8:25       ` Rex-BC Chen
2022-06-17  8:25       ` Rex-BC Chen
2022-06-17  8:25       ` Rex-BC Chen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.