All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
@ 2020-12-29 13:58 ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot

The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
panels, this adds the bindings.

This D-PHY depends on a separate analog PHY.

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

In order to configure the DSI PHY timings, a new "configure" PHY op is added to
permit dynamic (re)configuration of the PHY function.

Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
set of default D-PHY timings, timings struct and correct calculations.

Neil Armstrong (4):
  phy: dphy: Add configuration helpers
  generic-phy: add configure op
  phy: Add Amlogic AXG MIPI D-PHY driver
  phy: Add Amlogic AXG MIPI PCIe Analog PHY driver

 drivers/phy/Kconfig                      |  23 ++
 drivers/phy/Makefile                     |   3 +
 drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
 drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
 drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
 drivers/phy/phy-uclass.c                 |  11 +
 include/generic-phy.h                    |  23 ++
 include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
 8 files changed, 1131 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
 create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
 create mode 100644 drivers/phy/phy-core-mipi-dphy.c
 create mode 100644 include/phy-mipi-dphy.h

-- 
2.25.1

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

* [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
@ 2020-12-29 13:58 ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Neil Armstrong

The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
panels, this adds the bindings.

This D-PHY depends on a separate analog PHY.

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

In order to configure the DSI PHY timings, a new "configure" PHY op is added to
permit dynamic (re)configuration of the PHY function.

Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
set of default D-PHY timings, timings struct and correct calculations.

Neil Armstrong (4):
  phy: dphy: Add configuration helpers
  generic-phy: add configure op
  phy: Add Amlogic AXG MIPI D-PHY driver
  phy: Add Amlogic AXG MIPI PCIe Analog PHY driver

 drivers/phy/Kconfig                      |  23 ++
 drivers/phy/Makefile                     |   3 +
 drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
 drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
 drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
 drivers/phy/phy-uclass.c                 |  11 +
 include/generic-phy.h                    |  23 ++
 include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
 8 files changed, 1131 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
 create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
 create mode 100644 drivers/phy/phy-core-mipi-dphy.c
 create mode 100644 include/phy-mipi-dphy.h

-- 
2.25.1


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

* [PATCH 1/4] phy: dphy: Add configuration helpers
  2020-12-29 13:58 ` Neil Armstrong
@ 2020-12-29 13:58   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot

The MIPI D-PHY spec defines default values and boundaries for most of the
parameters it defines. Introduce helpers to help drivers get meaningful
values based on their current parameters, and validate the boundaries of
these parameters if needed.

These helpers and header are taken from Linux commit 9123e3a74ec7 ("Linux 5.9-rc1").

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig              |   5 +
 drivers/phy/Makefile             |   1 +
 drivers/phy/phy-core-mipi-dphy.c | 161 ++++++++++++++++++
 include/phy-mipi-dphy.h          | 284 +++++++++++++++++++++++++++++++
 4 files changed, 451 insertions(+)
 create mode 100644 drivers/phy/phy-core-mipi-dphy.c
 create mode 100644 include/phy-mipi-dphy.h

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index d12a6b02ad..8d9da17b53 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -59,6 +59,11 @@ config SPL_NOP_PHY
 	  This is useful when a driver uses the PHY framework but no real PHY
 	  hardware exists.
 
+config MIPI_DPHY_HELPERS
+	bool "MIPI D-PHY support helpers"
+	help
+	  Provides a number of helpers a core functions for MIPI D-PHY drivers.
+
 config BCM6318_USBH_PHY
 	bool "BCM6318 USBH PHY support"
 	depends on PHY && ARCH_BMIPS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 45a7fe5b56..9024002822 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
 obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o
+obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o
 obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
 obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
 obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
new file mode 100644
index 0000000000..ba5f648612
--- /dev/null
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ * Copyright (C) 2018 Cadence Design Systems Inc.
+ */
+
+#include <common.h>
+#include <div64.h>
+
+#include <phy-mipi-dphy.h>
+
+#define PSEC_PER_SEC	1000000000000LL
+
+/*
+ * Minimum D-PHY timings based on MIPI D-PHY specification. Derived
+ * from the valid ranges specified in Section 6.9, Table 14, Page 41
+ * of the D-PHY specification (v2.1).
+ */
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg)
+{
+	unsigned long long hs_clk_rate;
+	unsigned long long ui;
+
+	if (!cfg)
+		return -EINVAL;
+
+	hs_clk_rate = pixel_clock * bpp;
+	do_div(hs_clk_rate, lanes);
+
+	ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
+	do_div(ui, hs_clk_rate);
+
+	cfg->clk_miss = 0;
+	cfg->clk_post = 60000 + 52 * ui;
+	cfg->clk_pre = 8000;
+	cfg->clk_prepare = 38000;
+	cfg->clk_settle = 95000;
+	cfg->clk_term_en = 0;
+	cfg->clk_trail = 60000;
+	cfg->clk_zero = 262000;
+	cfg->d_term_en = 0;
+	cfg->eot = 0;
+	cfg->hs_exit = 100000;
+	cfg->hs_prepare = 40000 + 4 * ui;
+	cfg->hs_zero = 105000 + 6 * ui;
+	cfg->hs_settle = 85000 + 6 * ui;
+	cfg->hs_skip = 40000;
+
+	/*
+	 * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)
+	 * contains this formula as:
+	 *
+	 *     T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui)
+	 *
+	 * where n = 1 for forward-direction HS mode and n = 4 for reverse-
+	 * direction HS mode. There's only one setting and this function does
+	 * not parameterize on anything other that ui, so this code will
+	 * assumes that reverse-direction HS mode is supported and uses n = 4.
+	 */
+	cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
+
+	cfg->init = 100;
+	cfg->lpx = 60000;
+	cfg->ta_get = 5 * cfg->lpx;
+	cfg->ta_go = 4 * cfg->lpx;
+	cfg->ta_sure = 2 * cfg->lpx;
+	cfg->wakeup = 1000;
+
+	cfg->hs_clk_rate = hs_clk_rate;
+	cfg->lanes = lanes;
+
+	return 0;
+}
+
+/*
+ * Validate D-PHY configuration according to MIPI D-PHY specification
+ * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").
+ */
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
+{
+	unsigned long long ui;
+
+	if (!cfg)
+		return -EINVAL;
+
+	ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate);
+	do_div(ui, cfg->hs_clk_rate);
+
+	if (cfg->clk_miss > 60000)
+		return -EINVAL;
+
+	if (cfg->clk_post < (60000 + 52 * ui))
+		return -EINVAL;
+
+	if (cfg->clk_pre < 8000)
+		return -EINVAL;
+
+	if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000)
+		return -EINVAL;
+
+	if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000)
+		return -EINVAL;
+
+	if (cfg->clk_term_en > 38000)
+		return -EINVAL;
+
+	if (cfg->clk_trail < 60000)
+		return -EINVAL;
+
+	if ((cfg->clk_prepare + cfg->clk_zero) < 300000)
+		return -EINVAL;
+
+	if (cfg->d_term_en > (35000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->eot > (105000 + 12 * ui))
+		return -EINVAL;
+
+	if (cfg->hs_exit < 100000)
+		return -EINVAL;
+
+	if (cfg->hs_prepare < (40000 + 4 * ui) ||
+	    cfg->hs_prepare > (85000 + 6 * ui))
+		return -EINVAL;
+
+	if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui))
+		return -EINVAL;
+
+	if ((cfg->hs_settle < (85000 + 6 * ui)) ||
+	    (cfg->hs_settle > (145000 + 10 * ui)))
+		return -EINVAL;
+
+	if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->init < 100)
+		return -EINVAL;
+
+	if (cfg->lpx < 50000)
+		return -EINVAL;
+
+	if (cfg->ta_get != (5 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->ta_go != (4 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->wakeup < 1000)
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/include/phy-mipi-dphy.h b/include/phy-mipi-dphy.h
new file mode 100644
index 0000000000..a877ffee84
--- /dev/null
+++ b/include/phy-mipi-dphy.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Cadence Design Systems Inc.
+ */
+
+#ifndef __PHY_MIPI_DPHY_H_
+#define __PHY_MIPI_DPHY_H_
+
+/**
+ * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set
+ *
+ * This structure is used to represent the configuration state of a
+ * MIPI D-PHY phy.
+ */
+struct phy_configure_opts_mipi_dphy {
+	/**
+	 * @clk_miss:
+	 *
+	 * Timeout, in picoseconds, for receiver to detect absence of
+	 * Clock transitions and disable the Clock Lane HS-RX.
+	 *
+	 * Maximum value: 60000 ps
+	 */
+	unsigned int		clk_miss;
+
+	/**
+	 * @clk_post:
+	 *
+	 * Time, in picoseconds, that the transmitter continues to
+	 * send HS clock after the last associated Data Lane has
+	 * transitioned to LP Mode. Interval is defined as the period
+	 * from the end of @hs_trail to the beginning of @clk_trail.
+	 *
+	 * Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps
+	 */
+	unsigned int		clk_post;
+
+	/**
+	 * @clk_pre:
+	 *
+	 * Time, in UI, that the HS clock shall be driven by
+	 * the transmitter prior to any associated Data Lane beginning
+	 * the transition from LP to HS mode.
+	 *
+	 * Minimum value: 8 UI
+	 */
+	unsigned int		clk_pre;
+
+	/**
+	 * @clk_prepare:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the Clock
+	 * Lane LP-00 Line state immediately before the HS-0 Line
+	 * state starting the HS transmission.
+	 *
+	 * Minimum value: 38000 ps
+	 * Maximum value: 95000 ps
+	 */
+	unsigned int		clk_prepare;
+
+	/**
+	 * @clk_settle:
+	 *
+	 * Time interval, in picoseconds, during which the HS receiver
+	 * should ignore any Clock Lane HS transitions, starting from
+	 * the beginning of @clk_prepare.
+	 *
+	 * Minimum value: 95000 ps
+	 * Maximum value: 300000 ps
+	 */
+	unsigned int		clk_settle;
+
+	/**
+	 * @clk_term_en:
+	 *
+	 * Time, in picoseconds, for the Clock Lane receiver to enable
+	 * the HS line termination.
+	 *
+	 * Maximum value: 38000 ps
+	 */
+	unsigned int		clk_term_en;
+
+	/**
+	 * @clk_trail:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state after the last payload clock bit of a HS transmission
+	 * burst.
+	 *
+	 * Minimum value: 60000 ps
+	 */
+	unsigned int		clk_trail;
+
+	/**
+	 * @clk_zero:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state prior to starting the Clock.
+	 */
+	unsigned int		clk_zero;
+
+	/**
+	 * @d_term_en:
+	 *
+	 * Time, in picoseconds, for the Data Lane receiver to enable
+	 * the HS line termination.
+	 *
+	 * Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps
+	 */
+	unsigned int		d_term_en;
+
+	/**
+	 * @eot:
+	 *
+	 * Transmitted time interval, in picoseconds, from the start
+	 * of @hs_trail or @clk_trail, to the start of the LP- 11
+	 * state following a HS burst.
+	 *
+	 * Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps
+	 */
+	unsigned int		eot;
+
+	/**
+	 * @hs_exit:
+	 *
+	 * Time, in picoseconds, that the transmitter drives LP-11
+	 * following a HS burst.
+	 *
+	 * Minimum value: 100000 ps
+	 */
+	unsigned int		hs_exit;
+
+	/**
+	 * @hs_prepare:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the Data
+	 * Lane LP-00 Line state immediately before the HS-0 Line
+	 * state starting the HS transmission.
+	 *
+	 * Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps
+	 * Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_prepare;
+
+	/**
+	 * @hs_settle:
+	 *
+	 * Time interval, in picoseconds, during which the HS receiver
+	 * shall ignore any Data Lane HS transitions, starting from
+	 * the beginning of @hs_prepare.
+	 *
+	 * Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps
+	 * Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_settle;
+
+	/**
+	 * @hs_skip:
+	 *
+	 * Time interval, in picoseconds, during which the HS-RX
+	 * should ignore any transitions on the Data Lane, following a
+	 * HS burst. The end point of the interval is defined as the
+	 * beginning of the LP-11 state following the HS burst.
+	 *
+	 * Minimum value: 40000 ps
+	 * Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_skip;
+
+	/**
+	 * @hs_trail:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the
+	 * flipped differential state after last payload data bit of a
+	 * HS transmission burst
+	 *
+	 * Minimum value: max(8 * @hs_clk_rate period in ps,
+	 *		      60000 ps + 4 * @hs_clk_rate period in ps)
+	 */
+	unsigned int		hs_trail;
+
+	/**
+	 * @hs_zero:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state prior to transmitting the Sync sequence.
+	 */
+	unsigned int		hs_zero;
+
+	/**
+	 * @init:
+	 *
+	 * Time, in microseconds for the initialization period to
+	 * complete.
+	 *
+	 * Minimum value: 100 us
+	 */
+	unsigned int		init;
+
+	/**
+	 * @lpx:
+	 *
+	 * Transmitted length, in picoseconds, of any Low-Power state
+	 * period.
+	 *
+	 * Minimum value: 50000 ps
+	 */
+	unsigned int		lpx;
+
+	/**
+	 * @ta_get:
+	 *
+	 * Time, in picoseconds, that the new transmitter drives the
+	 * Bridge state (LP-00) after accepting control during a Link
+	 * Turnaround.
+	 *
+	 * Value: 5 * @lpx
+	 */
+	unsigned int		ta_get;
+
+	/**
+	 * @ta_go:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the
+	 * Bridge state (LP-00) before releasing control during a Link
+	 * Turnaround.
+	 *
+	 * Value: 4 * @lpx
+	 */
+	unsigned int		ta_go;
+
+	/**
+	 * @ta_sure:
+	 *
+	 * Time, in picoseconds, that the new transmitter waits after
+	 * the LP-10 state before transmitting the Bridge state
+	 * (LP-00) during a Link Turnaround.
+	 *
+	 * Minimum value: @lpx
+	 * Maximum value: 2 * @lpx
+	 */
+	unsigned int		ta_sure;
+
+	/**
+	 * @wakeup:
+	 *
+	 * Time, in microseconds, that a transmitter drives a Mark-1
+	 * state prior to a Stop state in order to initiate an exit
+	 * from ULPS.
+	 *
+	 * Minimum value: 1000 us
+	 */
+	unsigned int		wakeup;
+
+	/**
+	 * @hs_clk_rate:
+	 *
+	 * Clock rate, in Hertz, of the high-speed clock.
+	 */
+	unsigned long		hs_clk_rate;
+
+	/**
+	 * @lp_clk_rate:
+	 *
+	 * Clock rate, in Hertz, of the low-power clock.
+	 */
+	unsigned long		lp_clk_rate;
+
+	/**
+	 * @lanes:
+	 *
+	 * Number of active, consecutive, data lanes, starting from
+	 * lane 0, used for the transmissions.
+	 */
+	unsigned char		lanes;
+};
+
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg);
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg);
+
+#endif /* __PHY_MIPI_DPHY_H_ */
-- 
2.25.1

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

* [PATCH 1/4] phy: dphy: Add configuration helpers
@ 2020-12-29 13:58   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Neil Armstrong

The MIPI D-PHY spec defines default values and boundaries for most of the
parameters it defines. Introduce helpers to help drivers get meaningful
values based on their current parameters, and validate the boundaries of
these parameters if needed.

These helpers and header are taken from Linux commit 9123e3a74ec7 ("Linux 5.9-rc1").

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig              |   5 +
 drivers/phy/Makefile             |   1 +
 drivers/phy/phy-core-mipi-dphy.c | 161 ++++++++++++++++++
 include/phy-mipi-dphy.h          | 284 +++++++++++++++++++++++++++++++
 4 files changed, 451 insertions(+)
 create mode 100644 drivers/phy/phy-core-mipi-dphy.c
 create mode 100644 include/phy-mipi-dphy.h

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index d12a6b02ad..8d9da17b53 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -59,6 +59,11 @@ config SPL_NOP_PHY
 	  This is useful when a driver uses the PHY framework but no real PHY
 	  hardware exists.
 
+config MIPI_DPHY_HELPERS
+	bool "MIPI D-PHY support helpers"
+	help
+	  Provides a number of helpers a core functions for MIPI D-PHY drivers.
+
 config BCM6318_USBH_PHY
 	bool "BCM6318 USBH PHY support"
 	depends on PHY && ARCH_BMIPS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 45a7fe5b56..9024002822 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
 obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o
+obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o
 obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
 obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
 obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
new file mode 100644
index 0000000000..ba5f648612
--- /dev/null
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ * Copyright (C) 2018 Cadence Design Systems Inc.
+ */
+
+#include <common.h>
+#include <div64.h>
+
+#include <phy-mipi-dphy.h>
+
+#define PSEC_PER_SEC	1000000000000LL
+
+/*
+ * Minimum D-PHY timings based on MIPI D-PHY specification. Derived
+ * from the valid ranges specified in Section 6.9, Table 14, Page 41
+ * of the D-PHY specification (v2.1).
+ */
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg)
+{
+	unsigned long long hs_clk_rate;
+	unsigned long long ui;
+
+	if (!cfg)
+		return -EINVAL;
+
+	hs_clk_rate = pixel_clock * bpp;
+	do_div(hs_clk_rate, lanes);
+
+	ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
+	do_div(ui, hs_clk_rate);
+
+	cfg->clk_miss = 0;
+	cfg->clk_post = 60000 + 52 * ui;
+	cfg->clk_pre = 8000;
+	cfg->clk_prepare = 38000;
+	cfg->clk_settle = 95000;
+	cfg->clk_term_en = 0;
+	cfg->clk_trail = 60000;
+	cfg->clk_zero = 262000;
+	cfg->d_term_en = 0;
+	cfg->eot = 0;
+	cfg->hs_exit = 100000;
+	cfg->hs_prepare = 40000 + 4 * ui;
+	cfg->hs_zero = 105000 + 6 * ui;
+	cfg->hs_settle = 85000 + 6 * ui;
+	cfg->hs_skip = 40000;
+
+	/*
+	 * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)
+	 * contains this formula as:
+	 *
+	 *     T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui)
+	 *
+	 * where n = 1 for forward-direction HS mode and n = 4 for reverse-
+	 * direction HS mode. There's only one setting and this function does
+	 * not parameterize on anything other that ui, so this code will
+	 * assumes that reverse-direction HS mode is supported and uses n = 4.
+	 */
+	cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
+
+	cfg->init = 100;
+	cfg->lpx = 60000;
+	cfg->ta_get = 5 * cfg->lpx;
+	cfg->ta_go = 4 * cfg->lpx;
+	cfg->ta_sure = 2 * cfg->lpx;
+	cfg->wakeup = 1000;
+
+	cfg->hs_clk_rate = hs_clk_rate;
+	cfg->lanes = lanes;
+
+	return 0;
+}
+
+/*
+ * Validate D-PHY configuration according to MIPI D-PHY specification
+ * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").
+ */
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
+{
+	unsigned long long ui;
+
+	if (!cfg)
+		return -EINVAL;
+
+	ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate);
+	do_div(ui, cfg->hs_clk_rate);
+
+	if (cfg->clk_miss > 60000)
+		return -EINVAL;
+
+	if (cfg->clk_post < (60000 + 52 * ui))
+		return -EINVAL;
+
+	if (cfg->clk_pre < 8000)
+		return -EINVAL;
+
+	if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000)
+		return -EINVAL;
+
+	if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000)
+		return -EINVAL;
+
+	if (cfg->clk_term_en > 38000)
+		return -EINVAL;
+
+	if (cfg->clk_trail < 60000)
+		return -EINVAL;
+
+	if ((cfg->clk_prepare + cfg->clk_zero) < 300000)
+		return -EINVAL;
+
+	if (cfg->d_term_en > (35000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->eot > (105000 + 12 * ui))
+		return -EINVAL;
+
+	if (cfg->hs_exit < 100000)
+		return -EINVAL;
+
+	if (cfg->hs_prepare < (40000 + 4 * ui) ||
+	    cfg->hs_prepare > (85000 + 6 * ui))
+		return -EINVAL;
+
+	if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui))
+		return -EINVAL;
+
+	if ((cfg->hs_settle < (85000 + 6 * ui)) ||
+	    (cfg->hs_settle > (145000 + 10 * ui)))
+		return -EINVAL;
+
+	if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))
+		return -EINVAL;
+
+	if (cfg->init < 100)
+		return -EINVAL;
+
+	if (cfg->lpx < 50000)
+		return -EINVAL;
+
+	if (cfg->ta_get != (5 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->ta_go != (4 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))
+		return -EINVAL;
+
+	if (cfg->wakeup < 1000)
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/include/phy-mipi-dphy.h b/include/phy-mipi-dphy.h
new file mode 100644
index 0000000000..a877ffee84
--- /dev/null
+++ b/include/phy-mipi-dphy.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Cadence Design Systems Inc.
+ */
+
+#ifndef __PHY_MIPI_DPHY_H_
+#define __PHY_MIPI_DPHY_H_
+
+/**
+ * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set
+ *
+ * This structure is used to represent the configuration state of a
+ * MIPI D-PHY phy.
+ */
+struct phy_configure_opts_mipi_dphy {
+	/**
+	 * @clk_miss:
+	 *
+	 * Timeout, in picoseconds, for receiver to detect absence of
+	 * Clock transitions and disable the Clock Lane HS-RX.
+	 *
+	 * Maximum value: 60000 ps
+	 */
+	unsigned int		clk_miss;
+
+	/**
+	 * @clk_post:
+	 *
+	 * Time, in picoseconds, that the transmitter continues to
+	 * send HS clock after the last associated Data Lane has
+	 * transitioned to LP Mode. Interval is defined as the period
+	 * from the end of @hs_trail to the beginning of @clk_trail.
+	 *
+	 * Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps
+	 */
+	unsigned int		clk_post;
+
+	/**
+	 * @clk_pre:
+	 *
+	 * Time, in UI, that the HS clock shall be driven by
+	 * the transmitter prior to any associated Data Lane beginning
+	 * the transition from LP to HS mode.
+	 *
+	 * Minimum value: 8 UI
+	 */
+	unsigned int		clk_pre;
+
+	/**
+	 * @clk_prepare:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the Clock
+	 * Lane LP-00 Line state immediately before the HS-0 Line
+	 * state starting the HS transmission.
+	 *
+	 * Minimum value: 38000 ps
+	 * Maximum value: 95000 ps
+	 */
+	unsigned int		clk_prepare;
+
+	/**
+	 * @clk_settle:
+	 *
+	 * Time interval, in picoseconds, during which the HS receiver
+	 * should ignore any Clock Lane HS transitions, starting from
+	 * the beginning of @clk_prepare.
+	 *
+	 * Minimum value: 95000 ps
+	 * Maximum value: 300000 ps
+	 */
+	unsigned int		clk_settle;
+
+	/**
+	 * @clk_term_en:
+	 *
+	 * Time, in picoseconds, for the Clock Lane receiver to enable
+	 * the HS line termination.
+	 *
+	 * Maximum value: 38000 ps
+	 */
+	unsigned int		clk_term_en;
+
+	/**
+	 * @clk_trail:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state after the last payload clock bit of a HS transmission
+	 * burst.
+	 *
+	 * Minimum value: 60000 ps
+	 */
+	unsigned int		clk_trail;
+
+	/**
+	 * @clk_zero:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state prior to starting the Clock.
+	 */
+	unsigned int		clk_zero;
+
+	/**
+	 * @d_term_en:
+	 *
+	 * Time, in picoseconds, for the Data Lane receiver to enable
+	 * the HS line termination.
+	 *
+	 * Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps
+	 */
+	unsigned int		d_term_en;
+
+	/**
+	 * @eot:
+	 *
+	 * Transmitted time interval, in picoseconds, from the start
+	 * of @hs_trail or @clk_trail, to the start of the LP- 11
+	 * state following a HS burst.
+	 *
+	 * Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps
+	 */
+	unsigned int		eot;
+
+	/**
+	 * @hs_exit:
+	 *
+	 * Time, in picoseconds, that the transmitter drives LP-11
+	 * following a HS burst.
+	 *
+	 * Minimum value: 100000 ps
+	 */
+	unsigned int		hs_exit;
+
+	/**
+	 * @hs_prepare:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the Data
+	 * Lane LP-00 Line state immediately before the HS-0 Line
+	 * state starting the HS transmission.
+	 *
+	 * Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps
+	 * Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_prepare;
+
+	/**
+	 * @hs_settle:
+	 *
+	 * Time interval, in picoseconds, during which the HS receiver
+	 * shall ignore any Data Lane HS transitions, starting from
+	 * the beginning of @hs_prepare.
+	 *
+	 * Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps
+	 * Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_settle;
+
+	/**
+	 * @hs_skip:
+	 *
+	 * Time interval, in picoseconds, during which the HS-RX
+	 * should ignore any transitions on the Data Lane, following a
+	 * HS burst. The end point of the interval is defined as the
+	 * beginning of the LP-11 state following the HS burst.
+	 *
+	 * Minimum value: 40000 ps
+	 * Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps
+	 */
+	unsigned int		hs_skip;
+
+	/**
+	 * @hs_trail:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the
+	 * flipped differential state after last payload data bit of a
+	 * HS transmission burst
+	 *
+	 * Minimum value: max(8 * @hs_clk_rate period in ps,
+	 *		      60000 ps + 4 * @hs_clk_rate period in ps)
+	 */
+	unsigned int		hs_trail;
+
+	/**
+	 * @hs_zero:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the HS-0
+	 * state prior to transmitting the Sync sequence.
+	 */
+	unsigned int		hs_zero;
+
+	/**
+	 * @init:
+	 *
+	 * Time, in microseconds for the initialization period to
+	 * complete.
+	 *
+	 * Minimum value: 100 us
+	 */
+	unsigned int		init;
+
+	/**
+	 * @lpx:
+	 *
+	 * Transmitted length, in picoseconds, of any Low-Power state
+	 * period.
+	 *
+	 * Minimum value: 50000 ps
+	 */
+	unsigned int		lpx;
+
+	/**
+	 * @ta_get:
+	 *
+	 * Time, in picoseconds, that the new transmitter drives the
+	 * Bridge state (LP-00) after accepting control during a Link
+	 * Turnaround.
+	 *
+	 * Value: 5 * @lpx
+	 */
+	unsigned int		ta_get;
+
+	/**
+	 * @ta_go:
+	 *
+	 * Time, in picoseconds, that the transmitter drives the
+	 * Bridge state (LP-00) before releasing control during a Link
+	 * Turnaround.
+	 *
+	 * Value: 4 * @lpx
+	 */
+	unsigned int		ta_go;
+
+	/**
+	 * @ta_sure:
+	 *
+	 * Time, in picoseconds, that the new transmitter waits after
+	 * the LP-10 state before transmitting the Bridge state
+	 * (LP-00) during a Link Turnaround.
+	 *
+	 * Minimum value: @lpx
+	 * Maximum value: 2 * @lpx
+	 */
+	unsigned int		ta_sure;
+
+	/**
+	 * @wakeup:
+	 *
+	 * Time, in microseconds, that a transmitter drives a Mark-1
+	 * state prior to a Stop state in order to initiate an exit
+	 * from ULPS.
+	 *
+	 * Minimum value: 1000 us
+	 */
+	unsigned int		wakeup;
+
+	/**
+	 * @hs_clk_rate:
+	 *
+	 * Clock rate, in Hertz, of the high-speed clock.
+	 */
+	unsigned long		hs_clk_rate;
+
+	/**
+	 * @lp_clk_rate:
+	 *
+	 * Clock rate, in Hertz, of the low-power clock.
+	 */
+	unsigned long		lp_clk_rate;
+
+	/**
+	 * @lanes:
+	 *
+	 * Number of active, consecutive, data lanes, starting from
+	 * lane 0, used for the transmissions.
+	 */
+	unsigned char		lanes;
+};
+
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg);
+int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg);
+
+#endif /* __PHY_MIPI_DPHY_H_ */
-- 
2.25.1


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

* [PATCH 2/4] generic-phy: add configure op
  2020-12-29 13:58 ` Neil Armstrong
@ 2020-12-29 13:58   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot

Add the PHY configure op callback to the generic PHY uclass to permit
configuring the PHY.

It's useful for MIPI DSI PHYs to setup the link timings.

Signed-off-by:?Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/phy-uclass.c | 11 +++++++++++
 include/generic-phy.h    | 23 +++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index ef03e3a502..43ffbcee0f 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -204,6 +204,17 @@ int generic_phy_power_off(struct phy *phy)
 	return ret;
 }
 
+int generic_phy_configure(struct phy *phy, void *params)
+{
+	struct phy_ops const *ops;
+
+	if (!generic_phy_valid(phy))
+		return 0;
+	ops = phy_dev_ops(phy->dev);
+
+	return ops->configure ? ops->configure(phy, params) : 0;
+}
+
 int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
 {
 	int i, ret, count;
diff --git a/include/generic-phy.h b/include/generic-phy.h
index 5ab34cda03..a17d900e4b 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -122,6 +122,20 @@ struct phy_ops {
 	* @return 0 if OK, or a negative error code
 	*/
 	int	(*power_off)(struct phy *phy);
+
+	/**
+	* configure - configure a PHY device
+	*
+	* @phy:	PHY port to be configured
+	* @params: PHY Parameters, underlying data is specific to the PHY function
+	*
+	* During runtime, the PHY may need to be configured for it's main function.
+	* This function configures the PHY for it's main function following
+	* power_on/off() after beeing initialized.
+	*
+	* @return 0 if OK, or a negative error code
+	*/
+	int	(*configure)(struct phy *phy, void *params);
 };
 
 /**
@@ -183,6 +197,15 @@ int generic_phy_power_on(struct phy *phy);
  */
 int generic_phy_power_off(struct phy *phy);
 
+/**
+ * generic_phy_configure() - configure a PHY device
+ *
+ * @phy:	PHY port to be configured
+ * @params: 	PHY Parameters, underlying data is specific to the PHY function
+ * @return 0 if OK, or a negative error code
+ */
+int generic_phy_configure(struct phy *phy, void *params);
+
 
 /**
  * generic_phy_get_by_index() - Get a PHY device by integer index.
-- 
2.25.1

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

* [PATCH 2/4] generic-phy: add configure op
@ 2020-12-29 13:58   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:58 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Neil Armstrong

Add the PHY configure op callback to the generic PHY uclass to permit
configuring the PHY.

It's useful for MIPI DSI PHYs to setup the link timings.

Signed-off-by:Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/phy-uclass.c | 11 +++++++++++
 include/generic-phy.h    | 23 +++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index ef03e3a502..43ffbcee0f 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -204,6 +204,17 @@ int generic_phy_power_off(struct phy *phy)
 	return ret;
 }
 
+int generic_phy_configure(struct phy *phy, void *params)
+{
+	struct phy_ops const *ops;
+
+	if (!generic_phy_valid(phy))
+		return 0;
+	ops = phy_dev_ops(phy->dev);
+
+	return ops->configure ? ops->configure(phy, params) : 0;
+}
+
 int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
 {
 	int i, ret, count;
diff --git a/include/generic-phy.h b/include/generic-phy.h
index 5ab34cda03..a17d900e4b 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -122,6 +122,20 @@ struct phy_ops {
 	* @return 0 if OK, or a negative error code
 	*/
 	int	(*power_off)(struct phy *phy);
+
+	/**
+	* configure - configure a PHY device
+	*
+	* @phy:	PHY port to be configured
+	* @params: PHY Parameters, underlying data is specific to the PHY function
+	*
+	* During runtime, the PHY may need to be configured for it's main function.
+	* This function configures the PHY for it's main function following
+	* power_on/off() after beeing initialized.
+	*
+	* @return 0 if OK, or a negative error code
+	*/
+	int	(*configure)(struct phy *phy, void *params);
 };
 
 /**
@@ -183,6 +197,15 @@ int generic_phy_power_on(struct phy *phy);
  */
 int generic_phy_power_off(struct phy *phy);
 
+/**
+ * generic_phy_configure() - configure a PHY device
+ *
+ * @phy:	PHY port to be configured
+ * @params: 	PHY Parameters, underlying data is specific to the PHY function
+ * @return 0 if OK, or a negative error code
+ */
+int generic_phy_configure(struct phy *phy, void *params);
+
 
 /**
  * generic_phy_get_by_index() - Get a PHY device by integer index.
-- 
2.25.1


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

* [PATCH 3/4] phy: Add Amlogic AXG MIPI D-PHY driver
  2020-12-29 13:58 ` Neil Armstrong
@ 2020-12-29 13:59   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:59 UTC (permalink / raw)
  To: u-boot

The Amlogic AXG SoCs embeds a MIPI D-PHY used to communicate with DSI
panels.

This D-PHY depends on a separate analog PHY.

Signed-off-by:?Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig               |   9 +
 drivers/phy/Makefile              |   1 +
 drivers/phy/meson-axg-mipi-dphy.c | 393 ++++++++++++++++++++++++++++++
 3 files changed, 403 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-dphy.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d9da17b53..00d77eef08 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -196,6 +196,15 @@ config MESON_G12A_USB_PHY
 	  This is the generic phy driver for the Amlogic Meson G12A
 	  USB2 and USB3 PHYS.
 
+config MESON_AXG_MIPI_DPHY
+	bool "Amlogic Meson AXG MIPI D-PHY"
+	depends on PHY && ARCH_MESON && MESON_AXG
+	select MIPI_DPHY_HELPERS
+	imply REGMAP
+	help
+	  This is the generic phy driver for the Amlogic Meson AXG
+	  MIPI D-PHY.
+
 config MSM8916_USB_PHY
 	bool "Qualcomm MSM8916 USB PHY support"
 	depends on PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 9024002822..b2fd2d06f6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
+obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c
new file mode 100644
index 0000000000..8b2469793d
--- /dev/null
+++ b/drivers/phy/meson-axg-mipi-dphy.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Meson AXG MIPI DPHY driver
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <reset.h>
+#include <clk.h>
+#include <phy-mipi-dphy.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/bitfield.h>
+
+/* [31] soft reset for the phy.
+ *		1: reset. 0: dessert the reset.
+ * [30] clock lane soft reset.
+ * [29] data byte lane 3 soft reset.
+ * [28] data byte lane 2 soft reset.
+ * [27] data byte lane 1 soft reset.
+ * [26] data byte lane 0 soft reset.
+ * [25] mipi dsi pll clock selection.
+ *		1:  clock from fixed 850Mhz clock source. 0: from VID2 PLL.
+ * [12] mipi HSbyteclk enable.
+ * [11] mipi divider clk selection.
+ *		1: select the mipi DDRCLKHS from clock divider.
+ *		0: from PLL clock.
+ * [10] mipi clock divider control.
+ *		1: /4. 0: /2.
+ * [9]  mipi divider output enable.
+ * [8]  mipi divider counter enable.
+ * [7]  PLL clock enable.
+ * [5]  LPDT data endian.
+ *		1 = transfer the high bit first. 0 : transfer the low bit first.
+ * [4]  HS data endian.
+ * [3]  force data byte lane in stop mode.
+ * [2]  force data byte lane 0 in receiver mode.
+ * [1]  write 1 to sync the txclkesc input. the internal logic have to
+ *	use txclkesc to decide Txvalid and Txready.
+ * [0]  enalbe the MIPI DPHY TxDDRClk.
+ */
+#define MIPI_DSI_PHY_CTRL				0x0
+
+/* [31] clk lane tx_hs_en control selection.
+ *		1: from register. 0: use clk lane state machine.
+ * [30] register bit for clock lane tx_hs_en.
+ * [29] clk lane tx_lp_en contrl selection.
+ *		1: from register. 0: from clk lane state machine.
+ * [28] register bit for clock lane tx_lp_en.
+ * [27] chan0 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [26] register bit for chan0 tx_hs_en.
+ * [25] chan0 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [24] register bit from chan0 tx_lp_en.
+ * [23] chan0 rx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [22] register bit from chan0 rx_lp_en.
+ * [21] chan0 contention detection enable control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [20] register bit from chan0 contention dectection enable.
+ * [19] chan1 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [18] register bit for chan1 tx_hs_en.
+ * [17] chan1 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [16] register bit from chan1 tx_lp_en.
+ * [15] chan2 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [14] register bit for chan2 tx_hs_en.
+ * [13] chan2 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [12] register bit from chan2 tx_lp_en.
+ * [11] chan3 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [10] register bit for chan3 tx_hs_en.
+ * [9]  chan3 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [8]  register bit from chan3 tx_lp_en.
+ * [4]  clk chan power down. this bit is also used as the power down
+ *	of the whole MIPI_DSI_PHY.
+ * [3]  chan3 power down.
+ * [2]  chan2 power down.
+ * [1]  chan1 power down.
+ * [0]  chan0 power down.
+ */
+#define MIPI_DSI_CHAN_CTRL				0x4
+
+/* [24]   rx turn watch dog triggered.
+ * [23]   rx esc watchdog  triggered.
+ * [22]   mbias ready.
+ * [21]   txclkesc  synced and ready.
+ * [20:17] clk lane state. {mbias_ready, tx_stop, tx_ulps, tx_hs_active}
+ * [16:13] chan3 state{0, tx_stop, tx_ulps, tx_hs_active}
+ * [12:9]  chan2 state.{0, tx_stop, tx_ulps, tx_hs_active}
+ * [8:5]   chan1 state. {0, tx_stop, tx_ulps, tx_hs_active}
+ * [4:0]   chan0 state. {TX_STOP, tx_ULPS, hs_active, direction, rxulpsesc}
+ */
+#define MIPI_DSI_CHAN_STS				0x8
+
+/* [31:24] TCLK_PREPARE.
+ * [23:16] TCLK_ZERO.
+ * [15:8]  TCLK_POST.
+ * [7:0]   TCLK_TRAIL.
+ */
+#define MIPI_DSI_CLK_TIM				0xc
+
+/* [31:24] THS_PREPARE.
+ * [23:16] THS_ZERO.
+ * [15:8]  THS_TRAIL.
+ * [7:0]   THS_EXIT.
+ */
+#define MIPI_DSI_HS_TIM					0x10
+
+/* [31:24] tTA_GET.
+ * [23:16] tTA_GO.
+ * [15:8]  tTA_SURE.
+ * [7:0]   tLPX.
+ */
+#define MIPI_DSI_LP_TIM					0x14
+
+/* wait time to  MIPI DIS analog ready. */
+#define MIPI_DSI_ANA_UP_TIM				0x18
+
+/* TINIT. */
+#define MIPI_DSI_INIT_TIM				0x1c
+
+/* TWAKEUP. */
+#define MIPI_DSI_WAKEUP_TIM				0x20
+
+/* when in RxULPS check state, after the the logic enable the analog,
+ *	how long we should wait to check the lP state .
+ */
+#define MIPI_DSI_LPOK_TIM				0x24
+
+/* Watchdog for RX low power state no finished. */
+#define MIPI_DSI_LP_WCHDOG				0x28
+
+/* tMBIAS,  after send power up signals to analog,
+ *	how long we should wait for analog powered up.
+ */
+#define MIPI_DSI_ANA_CTRL				0x2c
+
+/* [31:8]  reserved for future.
+ * [7:0]   tCLK_PRE.
+ */
+#define MIPI_DSI_CLK_TIM1				0x30
+
+/* watchdog for turn around waiting time. */
+#define MIPI_DSI_TURN_WCHDOG				0x34
+
+/* When in RxULPS state, how frequency we should to check
+ *	if the TX side out of ULPS state.
+ */
+#define MIPI_DSI_ULPS_CHECK				0x38
+#define MIPI_DSI_TEST_CTRL0				0x3c
+#define MIPI_DSI_TEST_CTRL1				0x40
+
+#define NSEC_PER_MSEC	1000000L
+
+struct phy_meson_axg_mipi_dphy_priv {
+	struct regmap *regmap;
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk clk;
+#endif
+	struct reset_ctl reset;
+	struct phy analog;
+	struct phy_configure_opts_mipi_dphy config;
+};
+
+static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, void *params)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	struct phy_configure_opts_mipi_dphy *config = params;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(config);
+	if (ret)
+		return ret;
+
+	ret = generic_phy_configure(&priv->analog, config);
+	if (ret)
+		return ret;
+
+	memcpy(&priv->config, config, sizeof(priv->config));
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	unsigned long temp;
+	int ret;
+
+	ret = generic_phy_power_on(&priv->analog);
+	if (ret)
+		return ret;
+
+	/* enable phy clock */
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,  0x1);
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
+		     BIT(0) | /* enable the DSI PLL clock . */
+		     BIT(7) | /* enable pll clock which connected to DDR clock path */
+		     BIT(8)); /* enable the clock divider counter */
+
+	/* enable the divider clock out */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));
+
+	/* enable the byte clock generation. */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);
+
+	/* Calculate lanebyteclk period in ps */
+	temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
+	temp = temp * 8 * 10;
+
+	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
+		     DIV_ROUND_UP(priv->config.clk_trail, temp) |
+		     (DIV_ROUND_UP(priv->config.clk_post +
+				   priv->config.hs_trail, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
+	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
+		     DIV_ROUND_UP(priv->config.clk_pre, temp));
+
+	regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
+		     DIV_ROUND_UP(priv->config.hs_exit, temp) |
+		     (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24));
+
+	regmap_write(priv->regmap, MIPI_DSI_LP_TIM,
+		     DIV_ROUND_UP(priv->config.lpx, temp) |
+		     (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.ta_get, temp) << 24));
+
+	regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100);
+	regmap_write(priv->regmap, MIPI_DSI_INIT_TIM,
+		     DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp));
+	regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM,
+		     DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp));
+	regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C);
+	regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C);
+	regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000);
+	regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000);
+
+	/* Powerup the analog circuit */
+	switch (priv->config.lanes) {
+	case 1:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe);
+		break;
+	case 2:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc);
+		break;
+	case 3:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8);
+		break;
+	case 4:
+	default:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0);
+		break;
+	}
+
+	/* Trigger a sync active for esc_clk */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1));
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+
+	regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf);
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31));
+
+	return generic_phy_power_off(&priv->analog);
+}
+
+static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = generic_phy_init(&priv->analog);
+	if (ret)
+		return ret;
+
+	ret = reset_assert(&priv->reset);
+	udelay(1);
+	ret |= reset_deassert(&priv->reset);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_exit(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = generic_phy_exit(&priv->analog);
+	if (ret)
+		return ret;
+
+	return reset_assert(&priv->reset);
+}
+
+struct phy_ops meson_axg_mipi_dphy_ops = {
+	.init = phy_meson_axg_mipi_dphy_init,
+	.exit = phy_meson_axg_mipi_dphy_exit,
+	.power_on = phy_meson_axg_mipi_dphy_power_on,
+	.power_off = phy_meson_axg_mipi_dphy_power_off,
+	.configure = phy_meson_axg_mipi_dphy_configure,
+};
+
+int meson_axg_mipi_dphy_probe(struct udevice *dev)
+{
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+	if (ret)
+		return ret;
+
+	ret = generic_phy_get_by_index(dev, 0, &priv->analog);
+	if (ret)
+		return ret;
+
+	ret = reset_get_by_index(dev, 0, &priv->reset);
+	if (ret == -ENOTSUPP)
+		return 0;
+	else if (ret)
+		return ret;
+
+	ret = reset_deassert(&priv->reset);
+	if (ret) {
+		reset_release_all(&priv->reset, 1);
+		return ret;
+	}
+
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&priv->clk);
+	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+		pr_err("failed to enable PHY clock\n");
+		clk_free(&priv->clk);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id meson_axg_mipi_dphy_ids[] = {
+	{ .compatible = "amlogic,axg-mipi-dphy" },
+	{ }
+};
+
+U_BOOT_DRIVER(meson_axg_mipi_dphy) = {
+	.name = "meson_axg_mipi_dphy",
+	.id = UCLASS_PHY,
+	.of_match = meson_axg_mipi_dphy_ids,
+	.probe = meson_axg_mipi_dphy_probe,
+	.ops = &meson_axg_mipi_dphy_ops,
+	.priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_dphy_priv),
+};
-- 
2.25.1

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

* [PATCH 3/4] phy: Add Amlogic AXG MIPI D-PHY driver
@ 2020-12-29 13:59   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:59 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Neil Armstrong

The Amlogic AXG SoCs embeds a MIPI D-PHY used to communicate with DSI
panels.

This D-PHY depends on a separate analog PHY.

Signed-off-by:Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig               |   9 +
 drivers/phy/Makefile              |   1 +
 drivers/phy/meson-axg-mipi-dphy.c | 393 ++++++++++++++++++++++++++++++
 3 files changed, 403 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-dphy.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d9da17b53..00d77eef08 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -196,6 +196,15 @@ config MESON_G12A_USB_PHY
 	  This is the generic phy driver for the Amlogic Meson G12A
 	  USB2 and USB3 PHYS.
 
+config MESON_AXG_MIPI_DPHY
+	bool "Amlogic Meson AXG MIPI D-PHY"
+	depends on PHY && ARCH_MESON && MESON_AXG
+	select MIPI_DPHY_HELPERS
+	imply REGMAP
+	help
+	  This is the generic phy driver for the Amlogic Meson AXG
+	  MIPI D-PHY.
+
 config MSM8916_USB_PHY
 	bool "Qualcomm MSM8916 USB PHY support"
 	depends on PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 9024002822..b2fd2d06f6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
+obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c
new file mode 100644
index 0000000000..8b2469793d
--- /dev/null
+++ b/drivers/phy/meson-axg-mipi-dphy.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Meson AXG MIPI DPHY driver
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <reset.h>
+#include <clk.h>
+#include <phy-mipi-dphy.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/bitfield.h>
+
+/* [31] soft reset for the phy.
+ *		1: reset. 0: dessert the reset.
+ * [30] clock lane soft reset.
+ * [29] data byte lane 3 soft reset.
+ * [28] data byte lane 2 soft reset.
+ * [27] data byte lane 1 soft reset.
+ * [26] data byte lane 0 soft reset.
+ * [25] mipi dsi pll clock selection.
+ *		1:  clock from fixed 850Mhz clock source. 0: from VID2 PLL.
+ * [12] mipi HSbyteclk enable.
+ * [11] mipi divider clk selection.
+ *		1: select the mipi DDRCLKHS from clock divider.
+ *		0: from PLL clock.
+ * [10] mipi clock divider control.
+ *		1: /4. 0: /2.
+ * [9]  mipi divider output enable.
+ * [8]  mipi divider counter enable.
+ * [7]  PLL clock enable.
+ * [5]  LPDT data endian.
+ *		1 = transfer the high bit first. 0 : transfer the low bit first.
+ * [4]  HS data endian.
+ * [3]  force data byte lane in stop mode.
+ * [2]  force data byte lane 0 in receiver mode.
+ * [1]  write 1 to sync the txclkesc input. the internal logic have to
+ *	use txclkesc to decide Txvalid and Txready.
+ * [0]  enalbe the MIPI DPHY TxDDRClk.
+ */
+#define MIPI_DSI_PHY_CTRL				0x0
+
+/* [31] clk lane tx_hs_en control selection.
+ *		1: from register. 0: use clk lane state machine.
+ * [30] register bit for clock lane tx_hs_en.
+ * [29] clk lane tx_lp_en contrl selection.
+ *		1: from register. 0: from clk lane state machine.
+ * [28] register bit for clock lane tx_lp_en.
+ * [27] chan0 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [26] register bit for chan0 tx_hs_en.
+ * [25] chan0 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [24] register bit from chan0 tx_lp_en.
+ * [23] chan0 rx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [22] register bit from chan0 rx_lp_en.
+ * [21] chan0 contention detection enable control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [20] register bit from chan0 contention dectection enable.
+ * [19] chan1 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [18] register bit for chan1 tx_hs_en.
+ * [17] chan1 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [16] register bit from chan1 tx_lp_en.
+ * [15] chan2 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [14] register bit for chan2 tx_hs_en.
+ * [13] chan2 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [12] register bit from chan2 tx_lp_en.
+ * [11] chan3 tx_hs_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [10] register bit for chan3 tx_hs_en.
+ * [9]  chan3 tx_lp_en control selection.
+ *		1: from register. 0: from chan0 state machine.
+ * [8]  register bit from chan3 tx_lp_en.
+ * [4]  clk chan power down. this bit is also used as the power down
+ *	of the whole MIPI_DSI_PHY.
+ * [3]  chan3 power down.
+ * [2]  chan2 power down.
+ * [1]  chan1 power down.
+ * [0]  chan0 power down.
+ */
+#define MIPI_DSI_CHAN_CTRL				0x4
+
+/* [24]   rx turn watch dog triggered.
+ * [23]   rx esc watchdog  triggered.
+ * [22]   mbias ready.
+ * [21]   txclkesc  synced and ready.
+ * [20:17] clk lane state. {mbias_ready, tx_stop, tx_ulps, tx_hs_active}
+ * [16:13] chan3 state{0, tx_stop, tx_ulps, tx_hs_active}
+ * [12:9]  chan2 state.{0, tx_stop, tx_ulps, tx_hs_active}
+ * [8:5]   chan1 state. {0, tx_stop, tx_ulps, tx_hs_active}
+ * [4:0]   chan0 state. {TX_STOP, tx_ULPS, hs_active, direction, rxulpsesc}
+ */
+#define MIPI_DSI_CHAN_STS				0x8
+
+/* [31:24] TCLK_PREPARE.
+ * [23:16] TCLK_ZERO.
+ * [15:8]  TCLK_POST.
+ * [7:0]   TCLK_TRAIL.
+ */
+#define MIPI_DSI_CLK_TIM				0xc
+
+/* [31:24] THS_PREPARE.
+ * [23:16] THS_ZERO.
+ * [15:8]  THS_TRAIL.
+ * [7:0]   THS_EXIT.
+ */
+#define MIPI_DSI_HS_TIM					0x10
+
+/* [31:24] tTA_GET.
+ * [23:16] tTA_GO.
+ * [15:8]  tTA_SURE.
+ * [7:0]   tLPX.
+ */
+#define MIPI_DSI_LP_TIM					0x14
+
+/* wait time to  MIPI DIS analog ready. */
+#define MIPI_DSI_ANA_UP_TIM				0x18
+
+/* TINIT. */
+#define MIPI_DSI_INIT_TIM				0x1c
+
+/* TWAKEUP. */
+#define MIPI_DSI_WAKEUP_TIM				0x20
+
+/* when in RxULPS check state, after the the logic enable the analog,
+ *	how long we should wait to check the lP state .
+ */
+#define MIPI_DSI_LPOK_TIM				0x24
+
+/* Watchdog for RX low power state no finished. */
+#define MIPI_DSI_LP_WCHDOG				0x28
+
+/* tMBIAS,  after send power up signals to analog,
+ *	how long we should wait for analog powered up.
+ */
+#define MIPI_DSI_ANA_CTRL				0x2c
+
+/* [31:8]  reserved for future.
+ * [7:0]   tCLK_PRE.
+ */
+#define MIPI_DSI_CLK_TIM1				0x30
+
+/* watchdog for turn around waiting time. */
+#define MIPI_DSI_TURN_WCHDOG				0x34
+
+/* When in RxULPS state, how frequency we should to check
+ *	if the TX side out of ULPS state.
+ */
+#define MIPI_DSI_ULPS_CHECK				0x38
+#define MIPI_DSI_TEST_CTRL0				0x3c
+#define MIPI_DSI_TEST_CTRL1				0x40
+
+#define NSEC_PER_MSEC	1000000L
+
+struct phy_meson_axg_mipi_dphy_priv {
+	struct regmap *regmap;
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk clk;
+#endif
+	struct reset_ctl reset;
+	struct phy analog;
+	struct phy_configure_opts_mipi_dphy config;
+};
+
+static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, void *params)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	struct phy_configure_opts_mipi_dphy *config = params;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(config);
+	if (ret)
+		return ret;
+
+	ret = generic_phy_configure(&priv->analog, config);
+	if (ret)
+		return ret;
+
+	memcpy(&priv->config, config, sizeof(priv->config));
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	unsigned long temp;
+	int ret;
+
+	ret = generic_phy_power_on(&priv->analog);
+	if (ret)
+		return ret;
+
+	/* enable phy clock */
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,  0x1);
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
+		     BIT(0) | /* enable the DSI PLL clock . */
+		     BIT(7) | /* enable pll clock which connected to DDR clock path */
+		     BIT(8)); /* enable the clock divider counter */
+
+	/* enable the divider clock out */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));
+
+	/* enable the byte clock generation. */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);
+
+	/* Calculate lanebyteclk period in ps */
+	temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
+	temp = temp * 8 * 10;
+
+	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
+		     DIV_ROUND_UP(priv->config.clk_trail, temp) |
+		     (DIV_ROUND_UP(priv->config.clk_post +
+				   priv->config.hs_trail, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
+	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
+		     DIV_ROUND_UP(priv->config.clk_pre, temp));
+
+	regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
+		     DIV_ROUND_UP(priv->config.hs_exit, temp) |
+		     (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24));
+
+	regmap_write(priv->regmap, MIPI_DSI_LP_TIM,
+		     DIV_ROUND_UP(priv->config.lpx, temp) |
+		     (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) |
+		     (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) |
+		     (DIV_ROUND_UP(priv->config.ta_get, temp) << 24));
+
+	regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100);
+	regmap_write(priv->regmap, MIPI_DSI_INIT_TIM,
+		     DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp));
+	regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM,
+		     DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp));
+	regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C);
+	regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C);
+	regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000);
+	regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000);
+
+	/* Powerup the analog circuit */
+	switch (priv->config.lanes) {
+	case 1:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe);
+		break;
+	case 2:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc);
+		break;
+	case 3:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8);
+		break;
+	case 4:
+	default:
+		regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0);
+		break;
+	}
+
+	/* Trigger a sync active for esc_clk */
+	regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1));
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+
+	regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf);
+	regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31));
+
+	return generic_phy_power_off(&priv->analog);
+}
+
+static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = generic_phy_init(&priv->analog);
+	if (ret)
+		return ret;
+
+	ret = reset_assert(&priv->reset);
+	udelay(1);
+	ret |= reset_deassert(&priv->reset);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_exit(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = generic_phy_exit(&priv->analog);
+	if (ret)
+		return ret;
+
+	return reset_assert(&priv->reset);
+}
+
+struct phy_ops meson_axg_mipi_dphy_ops = {
+	.init = phy_meson_axg_mipi_dphy_init,
+	.exit = phy_meson_axg_mipi_dphy_exit,
+	.power_on = phy_meson_axg_mipi_dphy_power_on,
+	.power_off = phy_meson_axg_mipi_dphy_power_off,
+	.configure = phy_meson_axg_mipi_dphy_configure,
+};
+
+int meson_axg_mipi_dphy_probe(struct udevice *dev)
+{
+	struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+	if (ret)
+		return ret;
+
+	ret = generic_phy_get_by_index(dev, 0, &priv->analog);
+	if (ret)
+		return ret;
+
+	ret = reset_get_by_index(dev, 0, &priv->reset);
+	if (ret == -ENOTSUPP)
+		return 0;
+	else if (ret)
+		return ret;
+
+	ret = reset_deassert(&priv->reset);
+	if (ret) {
+		reset_release_all(&priv->reset, 1);
+		return ret;
+	}
+
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&priv->clk);
+	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+		pr_err("failed to enable PHY clock\n");
+		clk_free(&priv->clk);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id meson_axg_mipi_dphy_ids[] = {
+	{ .compatible = "amlogic,axg-mipi-dphy" },
+	{ }
+};
+
+U_BOOT_DRIVER(meson_axg_mipi_dphy) = {
+	.name = "meson_axg_mipi_dphy",
+	.id = UCLASS_PHY,
+	.of_match = meson_axg_mipi_dphy_ids,
+	.probe = meson_axg_mipi_dphy_probe,
+	.ops = &meson_axg_mipi_dphy_ops,
+	.priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_dphy_priv),
+};
-- 
2.25.1


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

* [PATCH 4/4] phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
  2020-12-29 13:58 ` Neil Armstrong
@ 2020-12-29 13:59   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:59 UTC (permalink / raw)
  To: u-boot

The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
MIPI DSI at the same time, and provides the Analog part of MIPI DSI transmission
and Analog part of the PCIe lines.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig                      |   9 +
 drivers/phy/Makefile                     |   1 +
 drivers/phy/meson-axg-mipi-pcie-analog.c | 233 +++++++++++++++++++++++
 3 files changed, 243 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 00d77eef08..e64802e8f3 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -205,6 +205,15 @@ config MESON_AXG_MIPI_DPHY
 	  This is the generic phy driver for the Amlogic Meson AXG
 	  MIPI D-PHY.
 
+config MESON_AXG_MIPI_PCIE_ANALOG_PHY
+	bool "Amlogic Meson AXG MIPI PCIe Analog PHY"
+	depends on PHY && ARCH_MESON && MESON_AXG
+	select MIPI_DPHY_HELPERS
+	imply REGMAP
+	help
+	  This is the generic phy driver for the Amlogic Meson AXG
+	  MIPI PCIe Analog PHY.
+
 config MSM8916_USB_PHY
 	bool "Qualcomm MSM8916 USB PHY support"
 	depends on PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b2fd2d06f6..8daf9f6089 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
 obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o
+obj-$(CONFIG_MESON_AXG_MIPI_PCIE_ANALOG_PHY) += meson-axg-mipi-pcie-analog.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
diff --git a/drivers/phy/meson-axg-mipi-pcie-analog.c b/drivers/phy/meson-axg-mipi-pcie-analog.c
new file mode 100644
index 0000000000..276e6004e5
--- /dev/null
+++ b/drivers/phy/meson-axg-mipi-pcie-analog.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic AXG MIPI + PCIE analog PHY driver
+ *
+ * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <reset.h>
+#include <clk.h>
+#include <phy-mipi-dphy.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/bitfield.h>
+
+#define HHI_MIPI_CNTL0 0x00
+#define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
+#define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
+#define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL1	GENMASK(25, 16)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL0	GENMASK(15, 0)
+
+#define HHI_MIPI_CNTL1 0x04
+#define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
+#define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
+#define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
+#define		HHI_MIPI_CNTL1_INPUT_SETTING	BIT(2)
+#define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
+#define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
+
+#define HHI_MIPI_CNTL2 0x08
+#define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
+#define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
+#define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
+#define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
+#define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
+#define		HHI_MIPI_CNTL2_CH_EN		GENMASK(15, 11)
+#define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
+
+#define DSI_LANE_0              (1 << 4)
+#define DSI_LANE_1              (1 << 3)
+#define DSI_LANE_CLK            (1 << 2)
+#define DSI_LANE_2              (1 << 1)
+#define DSI_LANE_3              (1 << 0)
+#define DSI_LANE_MASK		(0x1F)
+
+struct phy_meson_axg_mipi_pcie_analog_priv {
+	struct regmap *regmap;
+	struct phy_configure_opts_mipi_dphy config;
+	bool dsi_configured;
+	bool dsi_enabled;
+	bool powered;
+};
+
+static void phy_bandgap_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
+}
+
+static void phy_bandgap_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, 0);
+}
+
+static void phy_dsi_analog_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	u32 reg;
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   BIT(31), BIT(31));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_DIF_REF_CTL0,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2,
+		     (0x26e0 << 16) | (0x459 << 0));
+
+	reg = DSI_LANE_CLK;
+	switch (priv->config.lanes) {
+	case 4:
+		reg |= DSI_LANE_3;
+		fallthrough;
+	case 3:
+		reg |= DSI_LANE_2;
+		fallthrough;
+	case 2:
+		reg |= DSI_LANE_1;
+		fallthrough;
+	case 1:
+		reg |= DSI_LANE_0;
+		break;
+	default:
+		reg = 0;
+	}
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
+			   HHI_MIPI_CNTL2_CH_EN,
+			   FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
+
+	priv->dsi_enabled = true;
+}
+
+static void phy_dsi_analog_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
+
+	priv->dsi_enabled = false;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_configure(struct phy *phy, void *params)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+	struct phy_configure_opts_mipi_dphy *config = params;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(config);
+	if (ret)
+		return ret;
+
+	memcpy(&priv->config, config, sizeof(priv->config));
+
+	priv->dsi_configured = true;
+
+	/* If PHY was already powered on, setup the DSI analog part */
+	if (priv->powered) {
+		/* If reconfiguring, disable & reconfigure */
+		if (priv->dsi_enabled)
+			phy_dsi_analog_disable(priv);
+
+		udelay(100);
+
+		phy_dsi_analog_enable(priv);
+	}
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_power_on(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	phy_bandgap_enable(priv);
+
+	if (priv->dsi_configured)
+		phy_dsi_analog_enable(priv);
+
+	priv->powered = true;
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_power_off(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	phy_bandgap_disable(priv);
+
+	if (priv->dsi_enabled)
+		phy_dsi_analog_disable(priv);
+
+	priv->powered = false;
+
+	return 0;
+}
+
+struct phy_ops meson_axg_mipi_pcie_analog_ops = {
+	.power_on = phy_meson_axg_mipi_pcie_analog_power_on,
+	.power_off = phy_meson_axg_mipi_pcie_analog_power_off,
+	.configure = phy_meson_axg_mipi_pcie_analog_configure,
+};
+
+int meson_axg_mipi_pcie_analog_probe(struct udevice *dev)
+{
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	priv->regmap = syscon_node_to_regmap(dev_get_parent(dev)->node);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	return 0;
+}
+
+static const struct udevice_id meson_axg_mipi_pcie_analog_ids[] = {
+	{ .compatible = "amlogic,axg-mipi-pcie-analog-phy" },
+	{ }
+};
+
+U_BOOT_DRIVER(meson_axg_mipi_pcie_analog) = {
+	.name = "meson_axg_mipi_pcie_analog",
+	.id = UCLASS_PHY,
+	.of_match = meson_axg_mipi_pcie_analog_ids,
+	.probe = meson_axg_mipi_pcie_analog_probe,
+	.ops = &meson_axg_mipi_pcie_analog_ops,
+	.priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_pcie_analog_priv),
+};
-- 
2.25.1

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

* [PATCH 4/4] phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
@ 2020-12-29 13:59   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2020-12-29 13:59 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Neil Armstrong

The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
MIPI DSI at the same time, and provides the Analog part of MIPI DSI transmission
and Analog part of the PCIe lines.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/phy/Kconfig                      |   9 +
 drivers/phy/Makefile                     |   1 +
 drivers/phy/meson-axg-mipi-pcie-analog.c | 233 +++++++++++++++++++++++
 3 files changed, 243 insertions(+)
 create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 00d77eef08..e64802e8f3 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -205,6 +205,15 @@ config MESON_AXG_MIPI_DPHY
 	  This is the generic phy driver for the Amlogic Meson AXG
 	  MIPI D-PHY.
 
+config MESON_AXG_MIPI_PCIE_ANALOG_PHY
+	bool "Amlogic Meson AXG MIPI PCIe Analog PHY"
+	depends on PHY && ARCH_MESON && MESON_AXG
+	select MIPI_DPHY_HELPERS
+	imply REGMAP
+	help
+	  This is the generic phy driver for the Amlogic Meson AXG
+	  MIPI PCIe Analog PHY.
+
 config MSM8916_USB_PHY
 	bool "Qualcomm MSM8916 USB PHY support"
 	depends on PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b2fd2d06f6..8daf9f6089 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
 obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o
+obj-$(CONFIG_MESON_AXG_MIPI_PCIE_ANALOG_PHY) += meson-axg-mipi-pcie-analog.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
diff --git a/drivers/phy/meson-axg-mipi-pcie-analog.c b/drivers/phy/meson-axg-mipi-pcie-analog.c
new file mode 100644
index 0000000000..276e6004e5
--- /dev/null
+++ b/drivers/phy/meson-axg-mipi-pcie-analog.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic AXG MIPI + PCIE analog PHY driver
+ *
+ * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <reset.h>
+#include <clk.h>
+#include <phy-mipi-dphy.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/bitfield.h>
+
+#define HHI_MIPI_CNTL0 0x00
+#define		HHI_MIPI_CNTL0_COMMON_BLOCK	GENMASK(31, 28)
+#define		HHI_MIPI_CNTL0_ENABLE		BIT(29)
+#define		HHI_MIPI_CNTL0_BANDGAP		BIT(26)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL1	GENMASK(25, 16)
+#define		HHI_MIPI_CNTL0_DIF_REF_CTL0	GENMASK(15, 0)
+
+#define HHI_MIPI_CNTL1 0x04
+#define		HHI_MIPI_CNTL1_CH0_CML_PDR_EN	BIT(12)
+#define		HHI_MIPI_CNTL1_LP_ABILITY	GENMASK(5, 4)
+#define		HHI_MIPI_CNTL1_LP_RESISTER	BIT(3)
+#define		HHI_MIPI_CNTL1_INPUT_SETTING	BIT(2)
+#define		HHI_MIPI_CNTL1_INPUT_SEL	BIT(1)
+#define		HHI_MIPI_CNTL1_PRBS7_EN		BIT(0)
+
+#define HHI_MIPI_CNTL2 0x08
+#define		HHI_MIPI_CNTL2_CH_PU		GENMASK(31, 25)
+#define		HHI_MIPI_CNTL2_CH_CTL		GENMASK(24, 19)
+#define		HHI_MIPI_CNTL2_CH0_DIGDR_EN	BIT(18)
+#define		HHI_MIPI_CNTL2_CH_DIGDR_EN	BIT(17)
+#define		HHI_MIPI_CNTL2_LPULPS_EN	BIT(16)
+#define		HHI_MIPI_CNTL2_CH_EN		GENMASK(15, 11)
+#define		HHI_MIPI_CNTL2_CH0_LP_CTL	GENMASK(10, 1)
+
+#define DSI_LANE_0              (1 << 4)
+#define DSI_LANE_1              (1 << 3)
+#define DSI_LANE_CLK            (1 << 2)
+#define DSI_LANE_2              (1 << 1)
+#define DSI_LANE_3              (1 << 0)
+#define DSI_LANE_MASK		(0x1F)
+
+struct phy_meson_axg_mipi_pcie_analog_priv {
+	struct regmap *regmap;
+	struct phy_configure_opts_mipi_dphy config;
+	bool dsi_configured;
+	bool dsi_enabled;
+	bool powered;
+};
+
+static void phy_bandgap_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
+}
+
+static void phy_bandgap_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_BANDGAP, 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_ENABLE, 0);
+}
+
+static void phy_dsi_analog_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	u32 reg;
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   BIT(31), BIT(31));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			   HHI_MIPI_CNTL0_DIF_REF_CTL0,
+			   FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2,
+		     (0x26e0 << 16) | (0x459 << 0));
+
+	reg = DSI_LANE_CLK;
+	switch (priv->config.lanes) {
+	case 4:
+		reg |= DSI_LANE_3;
+		fallthrough;
+	case 3:
+		reg |= DSI_LANE_2;
+		fallthrough;
+	case 2:
+		reg |= DSI_LANE_1;
+		fallthrough;
+	case 1:
+		reg |= DSI_LANE_0;
+		break;
+	default:
+		reg = 0;
+	}
+
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
+			   HHI_MIPI_CNTL2_CH_EN,
+			   FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
+
+	priv->dsi_enabled = true;
+}
+
+static void phy_dsi_analog_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
+{
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_DIF_REF_CTL1,
+			FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
+	regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+			HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
+
+	regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
+
+	priv->dsi_enabled = false;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_configure(struct phy *phy, void *params)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+	struct phy_configure_opts_mipi_dphy *config = params;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(config);
+	if (ret)
+		return ret;
+
+	memcpy(&priv->config, config, sizeof(priv->config));
+
+	priv->dsi_configured = true;
+
+	/* If PHY was already powered on, setup the DSI analog part */
+	if (priv->powered) {
+		/* If reconfiguring, disable & reconfigure */
+		if (priv->dsi_enabled)
+			phy_dsi_analog_disable(priv);
+
+		udelay(100);
+
+		phy_dsi_analog_enable(priv);
+	}
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_power_on(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	phy_bandgap_enable(priv);
+
+	if (priv->dsi_configured)
+		phy_dsi_analog_enable(priv);
+
+	priv->powered = true;
+
+	return 0;
+}
+
+static int phy_meson_axg_mipi_pcie_analog_power_off(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	phy_bandgap_disable(priv);
+
+	if (priv->dsi_enabled)
+		phy_dsi_analog_disable(priv);
+
+	priv->powered = false;
+
+	return 0;
+}
+
+struct phy_ops meson_axg_mipi_pcie_analog_ops = {
+	.power_on = phy_meson_axg_mipi_pcie_analog_power_on,
+	.power_off = phy_meson_axg_mipi_pcie_analog_power_off,
+	.configure = phy_meson_axg_mipi_pcie_analog_configure,
+};
+
+int meson_axg_mipi_pcie_analog_probe(struct udevice *dev)
+{
+	struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
+
+	priv->regmap = syscon_node_to_regmap(dev_get_parent(dev)->node);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	return 0;
+}
+
+static const struct udevice_id meson_axg_mipi_pcie_analog_ids[] = {
+	{ .compatible = "amlogic,axg-mipi-pcie-analog-phy" },
+	{ }
+};
+
+U_BOOT_DRIVER(meson_axg_mipi_pcie_analog) = {
+	.name = "meson_axg_mipi_pcie_analog",
+	.id = UCLASS_PHY,
+	.of_match = meson_axg_mipi_pcie_analog_ids,
+	.probe = meson_axg_mipi_pcie_analog_probe,
+	.ops = &meson_axg_mipi_pcie_analog_ops,
+	.priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_pcie_analog_priv),
+};
-- 
2.25.1


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

* [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
  2020-12-29 13:58 ` Neil Armstrong
@ 2021-01-11  8:47   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2021-01-11  8:47 UTC (permalink / raw)
  To: u-boot

Hi Simon, Tom,

Could you review patches 1 & 2 of this serie ?

Thanks,
Neil

On 29/12/2020 14:58, Neil Armstrong wrote:
> The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
> panels, this adds the bindings.
> 
> This D-PHY depends on a separate analog PHY.
> 
> The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
> MIPI DSI at the same time.
> 
> In order to configure the DSI PHY timings, a new "configure" PHY op is added to
> permit dynamic (re)configuration of the PHY function.
> 
> Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
> set of default D-PHY timings, timings struct and correct calculations.
> 
> Neil Armstrong (4):
>   phy: dphy: Add configuration helpers
>   generic-phy: add configure op
>   phy: Add Amlogic AXG MIPI D-PHY driver
>   phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
> 
>  drivers/phy/Kconfig                      |  23 ++
>  drivers/phy/Makefile                     |   3 +
>  drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
>  drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
>  drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
>  drivers/phy/phy-uclass.c                 |  11 +
>  include/generic-phy.h                    |  23 ++
>  include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
>  8 files changed, 1131 insertions(+)
>  create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
>  create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
>  create mode 100644 drivers/phy/phy-core-mipi-dphy.c
>  create mode 100644 include/phy-mipi-dphy.h
> 

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

* Re: [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
@ 2021-01-11  8:47   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2021-01-11  8:47 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic, Tom Rini

Hi Simon, Tom,

Could you review patches 1 & 2 of this serie ?

Thanks,
Neil

On 29/12/2020 14:58, Neil Armstrong wrote:
> The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
> panels, this adds the bindings.
> 
> This D-PHY depends on a separate analog PHY.
> 
> The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
> MIPI DSI at the same time.
> 
> In order to configure the DSI PHY timings, a new "configure" PHY op is added to
> permit dynamic (re)configuration of the PHY function.
> 
> Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
> set of default D-PHY timings, timings struct and correct calculations.
> 
> Neil Armstrong (4):
>   phy: dphy: Add configuration helpers
>   generic-phy: add configure op
>   phy: Add Amlogic AXG MIPI D-PHY driver
>   phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
> 
>  drivers/phy/Kconfig                      |  23 ++
>  drivers/phy/Makefile                     |   3 +
>  drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
>  drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
>  drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
>  drivers/phy/phy-uclass.c                 |  11 +
>  include/generic-phy.h                    |  23 ++
>  include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
>  8 files changed, 1131 insertions(+)
>  create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
>  create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
>  create mode 100644 drivers/phy/phy-core-mipi-dphy.c
>  create mode 100644 include/phy-mipi-dphy.h
> 


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

* [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
  2021-01-11  8:47   ` Neil Armstrong
@ 2021-01-15 18:43     ` Tom Rini
  -1 siblings, 0 replies; 16+ messages in thread
From: Tom Rini @ 2021-01-15 18:43 UTC (permalink / raw)
  To: u-boot

On Mon, Jan 11, 2021 at 09:47:29AM +0100, Neil Armstrong wrote:

> Hi Simon, Tom,
> 
> Could you review patches 1 & 2 of this serie ?

Patches 1 and 2 look fine to me, FWIW.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20210115/0471da35/attachment.sig>

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

* Re: [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
@ 2021-01-15 18:43     ` Tom Rini
  0 siblings, 0 replies; 16+ messages in thread
From: Tom Rini @ 2021-01-15 18:43 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot, sjg, u-boot-amlogic

[-- Attachment #1: Type: text/plain, Size: 193 bytes --]

On Mon, Jan 11, 2021 at 09:47:29AM +0100, Neil Armstrong wrote:

> Hi Simon, Tom,
> 
> Could you review patches 1 & 2 of this serie ?

Patches 1 and 2 look fine to me, FWIW.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
  2020-12-29 13:58 ` Neil Armstrong
@ 2021-01-18 10:22   ` Neil Armstrong
  -1 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2021-01-18 10:22 UTC (permalink / raw)
  To: u-boot

On 29/12/2020 14:58, Neil Armstrong wrote:
> The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
> panels, this adds the bindings.
> 
> This D-PHY depends on a separate analog PHY.
> 
> The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
> MIPI DSI at the same time.
> 
> In order to configure the DSI PHY timings, a new "configure" PHY op is added to
> permit dynamic (re)configuration of the PHY function.
> 
> Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
> set of default D-PHY timings, timings struct and correct calculations.
> 
> Neil Armstrong (4):
>   phy: dphy: Add configuration helpers
>   generic-phy: add configure op
>   phy: Add Amlogic AXG MIPI D-PHY driver
>   phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
> 
>  drivers/phy/Kconfig                      |  23 ++
>  drivers/phy/Makefile                     |   3 +
>  drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
>  drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
>  drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
>  drivers/phy/phy-uclass.c                 |  11 +
>  include/generic-phy.h                    |  23 ++
>  include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
>  8 files changed, 1131 insertions(+)
>  create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
>  create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
>  create mode 100644 drivers/phy/phy-core-mipi-dphy.c
>  create mode 100644 include/phy-mipi-dphy.h
> 

Applied to u-boot-amlogic

Neil

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

* Re: [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function
@ 2021-01-18 10:22   ` Neil Armstrong
  0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2021-01-18 10:22 UTC (permalink / raw)
  To: u-boot, sjg; +Cc: u-boot-amlogic

On 29/12/2020 14:58, Neil Armstrong wrote:
> The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI
> panels, this adds the bindings.
> 
> This D-PHY depends on a separate analog PHY.
> 
> The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and
> MIPI DSI at the same time.
> 
> In order to configure the DSI PHY timings, a new "configure" PHY op is added to
> permit dynamic (re)configuration of the PHY function.
> 
> Finally, the Linux MIPI D-PHY configuration helpers are imported to provide a standard
> set of default D-PHY timings, timings struct and correct calculations.
> 
> Neil Armstrong (4):
>   phy: dphy: Add configuration helpers
>   generic-phy: add configure op
>   phy: Add Amlogic AXG MIPI D-PHY driver
>   phy: Add Amlogic AXG MIPI PCIe Analog PHY driver
> 
>  drivers/phy/Kconfig                      |  23 ++
>  drivers/phy/Makefile                     |   3 +
>  drivers/phy/meson-axg-mipi-dphy.c        | 393 +++++++++++++++++++++++
>  drivers/phy/meson-axg-mipi-pcie-analog.c | 233 ++++++++++++++
>  drivers/phy/phy-core-mipi-dphy.c         | 161 ++++++++++
>  drivers/phy/phy-uclass.c                 |  11 +
>  include/generic-phy.h                    |  23 ++
>  include/phy-mipi-dphy.h                  | 284 ++++++++++++++++
>  8 files changed, 1131 insertions(+)
>  create mode 100644 drivers/phy/meson-axg-mipi-dphy.c
>  create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c
>  create mode 100644 drivers/phy/phy-core-mipi-dphy.c
>  create mode 100644 include/phy-mipi-dphy.h
> 

Applied to u-boot-amlogic

Neil

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

end of thread, other threads:[~2021-01-18 10:22 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-29 13:58 [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function Neil Armstrong
2020-12-29 13:58 ` Neil Armstrong
2020-12-29 13:58 ` [PATCH 1/4] phy: dphy: Add configuration helpers Neil Armstrong
2020-12-29 13:58   ` Neil Armstrong
2020-12-29 13:58 ` [PATCH 2/4] generic-phy: add configure op Neil Armstrong
2020-12-29 13:58   ` Neil Armstrong
2020-12-29 13:59 ` [PATCH 3/4] phy: Add Amlogic AXG MIPI D-PHY driver Neil Armstrong
2020-12-29 13:59   ` Neil Armstrong
2020-12-29 13:59 ` [PATCH 4/4] phy: Add Amlogic AXG MIPI PCIe Analog PHY driver Neil Armstrong
2020-12-29 13:59   ` Neil Armstrong
2021-01-11  8:47 ` [PATCH 0/4] phy: add support for Amlogic Meson AXG MIPI-DSI PHY function Neil Armstrong
2021-01-11  8:47   ` Neil Armstrong
2021-01-15 18:43   ` Tom Rini
2021-01-15 18:43     ` Tom Rini
2021-01-18 10:22 ` Neil Armstrong
2021-01-18 10:22   ` Neil Armstrong

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.