All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver
@ 2019-01-04  7:08 Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Sergio Paracuellos
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, driverdev-devel

There is a lot of code related with PHY part of the mt7621 PCI driver
that can be extracted to a new PHY generic driver to do the same function.

This patch series add a new 'mt7621-pci-phy' driver to handle those
and updates the mt7621-pci driver code to use generic kernel's PHY
API. This makes the code much better and readable.

Device tree has been also updated with new related bindinds for the
PCI PHY part.

This changes are only compile-tested.

Changes in v3:
    - Change '#phy-cells' to be zero instead of one avoiding to implement
      custom 'xlate' function in phy's driver. All of phy types  for the
      phy driver are 'PHY_TYPE_PCIE' which is for that the '#phy-cells'
      was using for. There is no sense to check the type in a custom 'xlate' function.
      Phy's driver 'mt7621_pci_phy_xlate' has been deleted and now the generic
      'of_phy_simple_xlate' is being used.
    - Update MODULE_LICENSE to use 'GPL v2' instead of 'GPL'.
    - Add kernel doc for phy's driver data structures.
    - Add a PATCH with DT bindings documentation.

Changes in v2:
    - PATCH 1: remap registers first and assign virtual address after
        for each port because they share the same address space.

Hope this helps.

Thanks in advance.

Best regards,
     Sergio Paracuellos


Sergio Paracuellos (4):
  staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci
  staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy'
    driver
  staging: mt7621-dts: add pci-phy related bindings to board's device
    tree
  staging: mt7621-pci-phy: dt-bindings: add bindings for Mediatek MT7621
    Pcie PHY

 drivers/staging/Kconfig                       |   2 +
 drivers/staging/Makefile                      |   1 +
 drivers/staging/mt7621-dts/mt7621.dtsi        |  31 ++
 drivers/staging/mt7621-pci-phy/Kconfig        |   7 +
 drivers/staging/mt7621-pci-phy/Makefile       |   1 +
 drivers/staging/mt7621-pci-phy/TODO           |   4 +
 .../mediatek,mt7621-pci-phy.txt               |  54 +++
 .../staging/mt7621-pci-phy/pci-mt7621-phy.c   | 387 ++++++++++++++++++
 drivers/staging/mt7621-pci/pci-mt7621.c       | 250 ++---------
 9 files changed, 519 insertions(+), 218 deletions(-)
 create mode 100644 drivers/staging/mt7621-pci-phy/Kconfig
 create mode 100644 drivers/staging/mt7621-pci-phy/Makefile
 create mode 100644 drivers/staging/mt7621-pci-phy/TODO
 create mode 100644 drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
 create mode 100644 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c

-- 
2.19.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci
  2019-01-04  7:08 [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver Sergio Paracuellos
@ 2019-01-04  7:08 ` Sergio Paracuellos
  2019-02-15  5:44   ` NeilBrown
  2019-01-04  7:08 ` [PATCH v3 2/4] staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver Sergio Paracuellos
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, driverdev-devel

Phy part of the pci for this SoC can be handled using a generic phy
driver. This commit extracts phy part of the mt7621-pci into a new
'mt7621-pci-phy' driver.

Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
---
 drivers/staging/Kconfig                       |   2 +
 drivers/staging/Makefile                      |   1 +
 drivers/staging/mt7621-pci-phy/Kconfig        |   7 +
 drivers/staging/mt7621-pci-phy/Makefile       |   1 +
 drivers/staging/mt7621-pci-phy/TODO           |   4 +
 .../staging/mt7621-pci-phy/pci-mt7621-phy.c   | 387 ++++++++++++++++++
 6 files changed, 402 insertions(+)
 create mode 100644 drivers/staging/mt7621-pci-phy/Kconfig
 create mode 100644 drivers/staging/mt7621-pci-phy/Makefile
 create mode 100644 drivers/staging/mt7621-pci-phy/TODO
 create mode 100644 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index e4f608815c05..4a3d6e00f7cb 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -104,6 +104,8 @@ source "drivers/staging/pi433/Kconfig"
 
 source "drivers/staging/mt7621-pci/Kconfig"
 
+source "drivers/staging/mt7621-pci-phy/Kconfig"
+
 source "drivers/staging/mt7621-pinctrl/Kconfig"
 
 source "drivers/staging/mt7621-spi/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 5868631e8f1b..413890dd5a14 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_BCM2835_VCHIQ)	+= vc04_services/
 obj-$(CONFIG_DRM_VBOXVIDEO)	+= vboxvideo/
 obj-$(CONFIG_PI433)		+= pi433/
 obj-$(CONFIG_SOC_MT7621)	+= mt7621-pci/
+obj-$(CONFIG_SOC_MT7621)	+= mt7621-pci-phy/
 obj-$(CONFIG_SOC_MT7621)	+= mt7621-pinctrl/
 obj-$(CONFIG_SOC_MT7621)	+= mt7621-spi/
 obj-$(CONFIG_SOC_MT7621)	+= mt7621-dma/
diff --git a/drivers/staging/mt7621-pci-phy/Kconfig b/drivers/staging/mt7621-pci-phy/Kconfig
new file mode 100644
index 000000000000..b9f6ab784ee8
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/Kconfig
@@ -0,0 +1,7 @@
+config PCI_MT7621_PHY
+	tristate "MediaTek MT7621 PCI PHY Driver"
+	depends on RALINK && OF
+	select GENERIC_PHY
+	help
+	  Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver,
+
diff --git a/drivers/staging/mt7621-pci-phy/Makefile b/drivers/staging/mt7621-pci-phy/Makefile
new file mode 100644
index 000000000000..2b82ccfc28c6
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SOC_MT7621)       += pci-mt7621-phy.o
diff --git a/drivers/staging/mt7621-pci-phy/TODO b/drivers/staging/mt7621-pci-phy/TODO
new file mode 100644
index 000000000000..a255e8f753eb
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/TODO
@@ -0,0 +1,4 @@
+
+- general code review and cleanup
+
+Cc:  NeilBrown <neil@brown.name> and Sergio Paracuellos <sergio.paracuellos@gmail.com>
diff --git a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
new file mode 100644
index 000000000000..3d16716cfebc
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Mediatek MT7621 PCI PHY Driver
+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <mt7621.h>
+#include <ralink_regs.h>
+
+#define RALINK_CLKCFG1			0x30
+#define CHIP_REV_MT7621_E2		0x0101
+
+#define PCIE_PORT_CLK_EN(x)		BIT(24 + (x))
+
+#define RG_PE1_PIPE_REG			0x02c
+#define RG_PE1_PIPE_RST			BIT(12)
+#define RG_PE1_PIPE_CMD_FRC		BIT(4)
+
+#define RG_P0_TO_P1_WIDTH		0x100
+#define RG_PE1_H_LCDDS_REG		0x49c
+#define RG_PE1_H_LCDDS_PCW		GENMASK(30, 0)
+#define RG_PE1_H_LCDDS_PCW_VAL(x)	((0x7fffffff & (x)) << 0)
+
+#define RG_PE1_FRC_H_XTAL_REG		0x400
+#define RG_PE1_FRC_H_XTAL_TYPE          BIT(8)
+#define RG_PE1_H_XTAL_TYPE              GENMASK(10, 9)
+#define RG_PE1_H_XTAL_TYPE_VAL(x)       ((0x3 & (x)) << 9)
+
+#define RG_PE1_FRC_PHY_REG		0x000
+#define RG_PE1_FRC_PHY_EN               BIT(4)
+#define RG_PE1_PHY_EN                   BIT(5)
+
+#define RG_PE1_H_PLL_REG		0x490
+#define RG_PE1_H_PLL_BC			GENMASK(23, 22)
+#define RG_PE1_H_PLL_BC_VAL(x)		((0x3 & (x)) << 22)
+#define RG_PE1_H_PLL_BP			GENMASK(21, 18)
+#define RG_PE1_H_PLL_BP_VAL(x)		((0xf & (x)) << 18)
+#define RG_PE1_H_PLL_IR			GENMASK(15, 12)
+#define RG_PE1_H_PLL_IR_VAL(x)		((0xf & (x)) << 12)
+#define RG_PE1_H_PLL_IC			GENMASK(11, 8)
+#define RG_PE1_H_PLL_IC_VAL(x)		((0xf & (x)) << 8)
+#define RG_PE1_H_PLL_PREDIV             GENMASK(7, 6)
+#define RG_PE1_H_PLL_PREDIV_VAL(x)      ((0x3 & (x)) << 6)
+#define RG_PE1_PLL_DIVEN		GENMASK(3, 1)
+#define RG_PE1_PLL_DIVEN_VAL(x)		((0x7 & (x)) << 1)
+
+#define RG_PE1_H_PLL_FBKSEL_REG		0x4bc
+#define RG_PE1_H_PLL_FBKSEL             GENMASK(5, 4)
+#define RG_PE1_H_PLL_FBKSEL_VAL(x)      ((0x3 & (x)) << 4)
+
+#define	RG_PE1_H_LCDDS_SSC_PRD_REG	0x4a4
+#define RG_PE1_H_LCDDS_SSC_PRD          GENMASK(15, 0)
+#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x)   ((0xffff & (x)) << 0)
+
+#define RG_PE1_H_LCDDS_SSC_DELTA_REG	0x4a8
+#define RG_PE1_H_LCDDS_SSC_DELTA        GENMASK(11, 0)
+#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
+#define RG_PE1_H_LCDDS_SSC_DELTA1       GENMASK(27, 16)
+#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
+
+#define RG_PE1_LCDDS_CLK_PH_INV_REG	0x4a0
+#define RG_PE1_LCDDS_CLK_PH_INV		BIT(5)
+
+#define RG_PE1_H_PLL_BR_REG		0x4ac
+#define RG_PE1_H_PLL_BR			GENMASK(18, 16)
+#define RG_PE1_H_PLL_BR_VAL(x)		((0x7 & (x)) << 16)
+
+#define	RG_PE1_MSTCKDIV_REG		0x414
+#define RG_PE1_MSTCKDIV			GENMASK(7, 6)
+#define RG_PE1_MSTCKDIV_VAL(x)		((0x3 & (x)) << 6)
+
+#define RG_PE1_FRC_MSTCKDIV		BIT(5)
+
+/**
+ * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
+ * @phy: pointer to the kernel PHY device
+ * @port_base: base register
+ * @index: internal ID to identify the Mt7621 PCIe PHY
+ */
+struct mt7621_pci_phy_instance {
+	struct phy *phy;
+	void __iomem *port_base;
+	u32 index;
+};
+
+/**
+ * struct mt7621_pci_phy - Mt7621 Pcie PHY core
+ * @dev: pointer to device
+ * @phys: pointer to Mt7621 PHY device
+ * @nphys: number of PHY devices for this core
+ */
+struct mt7621_pci_phy {
+	struct device *dev;
+	struct mt7621_pci_phy_instance **phys;
+	int nphys;
+};
+
+static inline u32 phy_read(struct mt7621_pci_phy_instance *instance, u32 reg)
+{
+	return readl(instance->port_base + reg);
+}
+
+static inline void phy_write(struct mt7621_pci_phy_instance *instance,
+			     u32 val, u32 reg)
+{
+	writel(val, instance->port_base + reg);
+}
+
+static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy,
+				   struct mt7621_pci_phy_instance *instance)
+{
+	u32 offset = (instance->index != 1) ?
+		RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
+	u32 reg;
+
+	reg = phy_read(instance, offset);
+	reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
+	reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
+	phy_write(instance, reg, offset);
+}
+
+static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy,
+				   struct mt7621_pci_phy_instance *instance)
+{
+	struct device *dev = phy->dev;
+	u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
+	u32 offset;
+	u32 val;
+
+	reg = (reg >> 6) & 0x7;
+	/* Set PCIe Port PHY to disable SSC */
+	/* Debug Xtal Type */
+	val = phy_read(instance, RG_PE1_FRC_H_XTAL_REG);
+	val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
+	val |= RG_PE1_FRC_H_XTAL_TYPE;
+	val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
+	phy_write(instance, val, RG_PE1_FRC_H_XTAL_REG);
+
+	/* disable port */
+	offset = (instance->index != 1) ?
+		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+	val = phy_read(instance, offset);
+	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+	val |= RG_PE1_FRC_PHY_EN;
+	phy_write(instance, val, offset);
+
+	/* Set Pre-divider ratio (for host mode) */
+	val = phy_read(instance, RG_PE1_H_PLL_REG);
+	val &= ~(RG_PE1_H_PLL_PREDIV);
+
+	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
+		val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
+		phy_write(instance, val, RG_PE1_H_PLL_REG);
+		dev_info(dev, "Xtal is 40MHz\n");
+	} else { /* 25MHz | 20MHz Xtal */
+		val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
+		phy_write(instance, val, RG_PE1_H_PLL_REG);
+		if (reg >= 6) {
+			dev_info(dev, "Xtal is 25MHz\n");
+
+			/* Select feedback clock */
+			val = phy_read(instance, RG_PE1_H_PLL_FBKSEL_REG);
+			val &= ~(RG_PE1_H_PLL_FBKSEL);
+			val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
+			phy_write(instance, val, RG_PE1_H_PLL_FBKSEL_REG);
+
+			/* DDS NCPO PCW (for host mode) */
+			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
+			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
+			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
+			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
+
+			/* DDS SSC dither period control */
+			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
+			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
+			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
+			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
+
+			/* DDS SSC dither amplitude control */
+			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_DELTA_REG);
+			val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
+				 RG_PE1_H_LCDDS_SSC_DELTA1);
+			val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
+			val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
+			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_DELTA_REG);
+		} else {
+			dev_info(dev, "Xtal is 20MHz\n");
+		}
+	}
+
+	/* DDS clock inversion */
+	val = phy_read(instance, RG_PE1_LCDDS_CLK_PH_INV_REG);
+	val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
+	val |= RG_PE1_LCDDS_CLK_PH_INV;
+	phy_write(instance, val, RG_PE1_LCDDS_CLK_PH_INV_REG);
+
+	/* Set PLL bits */
+	val = phy_read(instance, RG_PE1_H_PLL_REG);
+	val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
+		 RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
+	val |= RG_PE1_H_PLL_BC_VAL(0x02);
+	val |= RG_PE1_H_PLL_BP_VAL(0x06);
+	val |= RG_PE1_H_PLL_IR_VAL(0x02);
+	val |= RG_PE1_H_PLL_IC_VAL(0x01);
+	val |= RG_PE1_PLL_DIVEN_VAL(0x02);
+	phy_write(instance, val, RG_PE1_H_PLL_REG);
+
+	val = phy_read(instance, RG_PE1_H_PLL_BR_REG);
+	val &= ~(RG_PE1_H_PLL_BR);
+	val |= RG_PE1_H_PLL_BR_VAL(0x00);
+	phy_write(instance, val, RG_PE1_H_PLL_BR_REG);
+
+	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
+		/* set force mode enable of da_pe1_mstckdiv */
+		val = phy_read(instance, RG_PE1_MSTCKDIV_REG);
+		val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
+		val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
+		phy_write(instance, val, RG_PE1_MSTCKDIV_REG);
+	}
+}
+
+static int mt7621_pci_phy_init(struct phy *phy)
+{
+	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+	struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
+	u32 chip_rev_id = rt_sysc_r32(SYSC_REG_CHIP_REV);
+
+	if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
+		mt7621_bypass_pipe_rst(mphy, instance);
+
+	mt7621_set_phy_for_ssc(mphy, instance);
+
+	return 0;
+}
+
+static int mt7621_pci_phy_power_on(struct phy *phy)
+{
+	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+	u32 offset = (instance->index != 1) ?
+		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+	u32 val;
+
+	/* Enable PHY and disable force mode */
+	val = phy_read(instance, offset);
+	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+	val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+	phy_write(instance, val, offset);
+
+	return 0;
+}
+
+static int mt7621_pci_phy_power_off(struct phy *phy)
+{
+	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+	u32 offset = (instance->index != 1) ?
+		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
+	u32 val;
+
+	/* Disable PHY */
+	val = phy_read(instance, offset);
+	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
+	val |= RG_PE1_FRC_PHY_EN;
+	phy_write(instance, val, offset);
+
+	return 0;
+}
+
+static int mt7621_pci_phy_exit(struct phy *phy)
+{
+	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
+
+	rt_sysc_m32(PCIE_PORT_CLK_EN(instance->index), 0, RALINK_CLKCFG1);
+
+	return 0;
+}
+
+static const struct phy_ops mt7621_pci_phy_ops = {
+	.init		= mt7621_pci_phy_init,
+	.exit		= mt7621_pci_phy_exit,
+	.power_on	= mt7621_pci_phy_power_on,
+	.power_off	= mt7621_pci_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int mt7621_pci_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *child_np;
+	struct phy_provider *provider;
+	struct mt7621_pci_phy *phy;
+	struct resource res;
+	int port, ret;
+	void __iomem *port_base;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	phy->nphys = of_get_child_count(np);
+	phy->phys = devm_kcalloc(dev, phy->nphys,
+				 sizeof(*phy->phys), GFP_KERNEL);
+	if (!phy->phys)
+		return -ENOMEM;
+
+	phy->dev = dev;
+	platform_set_drvdata(pdev, phy);
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret) {
+		dev_err(dev, "failed to get address resource(id-%d)\n", port);
+		return ret;
+	}
+
+	port_base = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(port_base)) {
+		dev_err(dev, "failed to remap phy regs\n");
+		return PTR_ERR(port_base);
+	}
+
+	port = 0;
+	for_each_child_of_node(np, child_np) {
+		struct mt7621_pci_phy_instance *instance;
+		struct phy *pphy;
+
+		instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+		if (!instance) {
+			ret = -ENOMEM;
+			goto put_child;
+		}
+
+		phy->phys[port] = instance;
+
+		pphy = devm_phy_create(dev, child_np, &mt7621_pci_phy_ops);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create phy\n");
+			ret = PTR_ERR(phy);
+			goto put_child;
+		}
+
+		instance->port_base = port_base;
+		instance->phy = pphy;
+		instance->index = port;
+		phy_set_drvdata(pphy, instance);
+		port++;
+	}
+
+	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(provider);
+
+put_child:
+	of_node_put(child_np);
+	return ret;
+}
+
+static const struct of_device_id mt7621_pci_phy_ids[] = {
+	{ .compatible = "mediatek,mt7621-pci-phy" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
+
+static struct platform_driver mt7621_pci_phy_driver = {
+	.probe = mt7621_pci_phy_probe,
+	.driver = {
+		.name = "mt7621-pci-phy",
+		.of_match_table = of_match_ptr(mt7621_pci_phy_ids),
+	},
+};
+
+static int __init mt7621_pci_phy_drv_init(void)
+{
+	return platform_driver_register(&mt7621_pci_phy_driver);
+}
+
+arch_initcall(mt7621_pci_phy_drv_init);
+
+MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.19.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v3 2/4] staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver
  2019-01-04  7:08 [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Sergio Paracuellos
@ 2019-01-04  7:08 ` Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree Sergio Paracuellos
  2019-01-04  7:08   ` Sergio Paracuellos
  3 siblings, 0 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, driverdev-devel

Phy part of this driver has been moved to a new 'pci-mt7621-phy' driver.
Change code to use kernel's generic phy API removing also no more need
moved code.

Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
---
 drivers/staging/mt7621-pci/pci-mt7621.c | 250 +++---------------------
 1 file changed, 32 insertions(+), 218 deletions(-)

diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index e720524ba5a3..507b8c68d20b 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -25,6 +25,7 @@
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/pci.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
 #include <mt7621.h>
@@ -95,76 +96,12 @@
 #define RALINK_PCI_IO_MAP_BASE		0x1e160000
 #define MEMORY_BASE			0x0
 
-/* pcie phy related macros */
-#define RALINK_PCIEPHY_P0P1_CTL_OFFSET	0x9000
-#define RALINK_PCIEPHY_P2_CTL_OFFSET	0xA000
-
-#define RG_P0_TO_P1_WIDTH		0x100
-
-#define RG_PE1_PIPE_REG			0x02c
-#define RG_PE1_PIPE_RST			BIT(12)
-#define RG_PE1_PIPE_CMD_FRC		BIT(4)
-
-#define RG_PE1_H_LCDDS_REG		0x49c
-#define RG_PE1_H_LCDDS_PCW		GENMASK(30, 0)
-#define RG_PE1_H_LCDDS_PCW_VAL(x)	((0x7fffffff & (x)) << 0)
-
-#define RG_PE1_FRC_H_XTAL_REG		0x400
-#define RG_PE1_FRC_H_XTAL_TYPE          BIT(8)
-#define RG_PE1_H_XTAL_TYPE              GENMASK(10, 9)
-#define RG_PE1_H_XTAL_TYPE_VAL(x)       ((0x3 & (x)) << 9)
-
-#define RG_PE1_FRC_PHY_REG		0x000
-#define RG_PE1_FRC_PHY_EN               BIT(4)
-#define RG_PE1_PHY_EN                   BIT(5)
-
-#define RG_PE1_H_PLL_REG		0x490
-#define RG_PE1_H_PLL_BC			GENMASK(23, 22)
-#define RG_PE1_H_PLL_BC_VAL(x)		((0x3 & (x)) << 22)
-#define RG_PE1_H_PLL_BP			GENMASK(21, 18)
-#define RG_PE1_H_PLL_BP_VAL(x)		((0xf & (x)) << 18)
-#define RG_PE1_H_PLL_IR			GENMASK(15, 12)
-#define RG_PE1_H_PLL_IR_VAL(x)		((0xf & (x)) << 12)
-#define RG_PE1_H_PLL_IC			GENMASK(11, 8)
-#define RG_PE1_H_PLL_IC_VAL(x)		((0xf & (x)) << 8)
-#define RG_PE1_H_PLL_PREDIV             GENMASK(7, 6)
-#define RG_PE1_H_PLL_PREDIV_VAL(x)      ((0x3 & (x)) << 6)
-#define RG_PE1_PLL_DIVEN		GENMASK(3, 1)
-#define RG_PE1_PLL_DIVEN_VAL(x)		((0x7 & (x)) << 1)
-
-#define RG_PE1_H_PLL_FBKSEL_REG		0x4bc
-#define RG_PE1_H_PLL_FBKSEL             GENMASK(5, 4)
-#define RG_PE1_H_PLL_FBKSEL_VAL(x)      ((0x3 & (x)) << 4)
-
-#define	RG_PE1_H_LCDDS_SSC_PRD_REG	0x4a4
-#define RG_PE1_H_LCDDS_SSC_PRD          GENMASK(15, 0)
-#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x)   ((0xffff & (x)) << 0)
-
-#define RG_PE1_H_LCDDS_SSC_DELTA_REG	0x4a8
-#define RG_PE1_H_LCDDS_SSC_DELTA        GENMASK(11, 0)
-#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
-#define RG_PE1_H_LCDDS_SSC_DELTA1       GENMASK(27, 16)
-#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
-
-#define RG_PE1_LCDDS_CLK_PH_INV_REG	0x4a0
-#define RG_PE1_LCDDS_CLK_PH_INV		BIT(5)
-
-#define RG_PE1_H_PLL_BR_REG		0x4ac
-#define RG_PE1_H_PLL_BR			GENMASK(18, 16)
-#define RG_PE1_H_PLL_BR_VAL(x)		((0x7 & (x)) << 16)
-
-#define	RG_PE1_MSTCKDIV_REG		0x414
-#define RG_PE1_MSTCKDIV			GENMASK(7, 6)
-#define RG_PE1_MSTCKDIV_VAL(x)		((0x3 & (x)) << 6)
-
-#define RG_PE1_FRC_MSTCKDIV		BIT(5)
-
 /**
  * struct mt7621_pcie_port - PCIe port information
  * @base: I/O mapped register base
  * @list: port list
  * @pcie: pointer to PCIe host info
- * @phy_reg_offset: offset to related phy registers
+ * @phy: pointer to PHY control block
  * @pcie_rst: pointer to port reset control
  * @slot: port slot
  * @enabled: indicates if port is enabled
@@ -173,7 +110,7 @@ struct mt7621_pcie_port {
 	void __iomem *base;
 	struct list_head list;
 	struct mt7621_pcie *pcie;
-	u32 phy_reg_offset;
+	struct phy *phy;
 	struct reset_control *pcie_rst;
 	u32 slot;
 	bool enabled;
@@ -265,150 +202,6 @@ static void write_config(struct mt7621_pcie *pcie, unsigned int dev,
 	pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA);
 }
 
-static void bypass_pipe_rst(struct mt7621_pcie_port *port)
-{
-	struct mt7621_pcie *pcie = port->pcie;
-	u32 phy_offset = port->phy_reg_offset;
-	u32 offset = (port->slot != 1) ?
-		phy_offset + RG_PE1_PIPE_REG :
-		phy_offset + RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
-	u32 reg = pcie_read(pcie, offset);
-
-	reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
-	reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
-	pcie_write(pcie, reg, offset);
-}
-
-static void set_phy_for_ssc(struct mt7621_pcie_port *port)
-{
-	struct mt7621_pcie *pcie = port->pcie;
-	struct device *dev = pcie->dev;
-	u32 phy_offset = port->phy_reg_offset;
-	u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
-	u32 offset;
-	u32 val;
-
-	reg = (reg >> 6) & 0x7;
-	/* Set PCIe Port PHY to disable SSC */
-	/* Debug Xtal Type */
-	offset = phy_offset + RG_PE1_FRC_H_XTAL_REG;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
-	val |= RG_PE1_FRC_H_XTAL_TYPE;
-	val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
-	pcie_write(pcie, val, offset);
-
-	/* disable port */
-	offset = (port->slot != 1) ?
-		phy_offset + RG_PE1_FRC_PHY_REG :
-		phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
-	val |= RG_PE1_FRC_PHY_EN;
-	pcie_write(pcie, val, offset);
-
-	/* Set Pre-divider ratio (for host mode) */
-	offset =  phy_offset + RG_PE1_H_PLL_REG;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_H_PLL_PREDIV);
-
-	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
-		val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
-		pcie_write(pcie, val, offset);
-		dev_info(dev, "Xtal is 40MHz\n");
-	} else { /* 25MHz | 20MHz Xtal */
-		val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
-		pcie_write(pcie, val, offset);
-		if (reg >= 6) {
-			dev_info(dev, "Xtal is 25MHz\n");
-
-			/* Select feedback clock */
-			offset = phy_offset + RG_PE1_H_PLL_FBKSEL_REG;
-			val = pcie_read(pcie, offset);
-			val &= ~(RG_PE1_H_PLL_FBKSEL);
-			val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
-			pcie_write(pcie, val, offset);
-
-			/* DDS NCPO PCW (for host mode) */
-			offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG;
-			val = pcie_read(pcie, offset);
-			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
-			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
-			pcie_write(pcie, val, offset);
-
-			/* DDS SSC dither period control */
-			offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG;
-			val = pcie_read(pcie, offset);
-			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
-			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
-			pcie_write(pcie, val, offset);
-
-			/* DDS SSC dither amplitude control */
-			offset = phy_offset + RG_PE1_H_LCDDS_SSC_DELTA_REG;
-			val = pcie_read(pcie, offset);
-			val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
-				 RG_PE1_H_LCDDS_SSC_DELTA1);
-			val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
-			val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
-			pcie_write(pcie, val, offset);
-		} else {
-			dev_info(dev, "Xtal is 20MHz\n");
-		}
-	}
-
-	/* DDS clock inversion */
-	offset = phy_offset + RG_PE1_LCDDS_CLK_PH_INV_REG;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
-	val |= RG_PE1_LCDDS_CLK_PH_INV;
-	pcie_write(pcie, val, offset);
-
-	/* Set PLL bits */
-	offset = phy_offset + RG_PE1_H_PLL_REG;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
-		 RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
-	val |= RG_PE1_H_PLL_BC_VAL(0x02);
-	val |= RG_PE1_H_PLL_BP_VAL(0x06);
-	val |= RG_PE1_H_PLL_IR_VAL(0x02);
-	val |= RG_PE1_H_PLL_IC_VAL(0x01);
-	val |= RG_PE1_PLL_DIVEN_VAL(0x02);
-	pcie_write(pcie, val, offset);
-
-	offset = phy_offset + RG_PE1_H_PLL_BR_REG;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_H_PLL_BR);
-	val |= RG_PE1_H_PLL_BR_VAL(0x00);
-	pcie_write(pcie, val, offset);
-
-	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
-		/* set force mode enable of da_pe1_mstckdiv */
-		offset = phy_offset + RG_PE1_MSTCKDIV_REG;
-		val = pcie_read(pcie, offset);
-		val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
-		val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
-		pcie_write(pcie, val, offset);
-	}
-
-	/* Enable PHY and disable force mode */
-	offset = (port->slot != 1) ?
-		phy_offset + RG_PE1_FRC_PHY_REG :
-		phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
-	val = pcie_read(pcie, offset);
-	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
-	val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
-	pcie_write(pcie, val, offset);
-}
-
-static void mt7621_enable_phy(struct mt7621_pcie_port *port)
-{
-	u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
-
-	if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
-		bypass_pipe_rst(port);
-	set_phy_for_ssc(port);
-}
-
 static inline void mt7621_control_assert(struct mt7621_pcie_port *port)
 {
 	u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID);
@@ -510,7 +303,7 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
 	struct device *dev = pcie->dev;
 	struct device_node *pnode = dev->of_node;
 	struct resource regs;
-	char name[6];
+	char name[10];
 	int err;
 
 	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
@@ -534,11 +327,13 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie,
 		return PTR_ERR(port->pcie_rst);
 	}
 
+	snprintf(name, sizeof(name), "pcie-phy%d", slot);
+	port->phy = devm_phy_get(dev, name);
+	if (IS_ERR(port->phy))
+		return PTR_ERR(port->phy);
+
 	port->slot = slot;
 	port->pcie = pcie;
-	port->phy_reg_offset = (slot != 2) ?
-				RALINK_PCIEPHY_P0P1_CTL_OFFSET :
-				RALINK_PCIEPHY_P2_CTL_OFFSET;
 
 	INIT_LIST_HEAD(&port->list);
 	list_add_tail(&port->list, &pcie->ports);
@@ -588,6 +383,7 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
 	struct device *dev = pcie->dev;
 	u32 slot = port->slot;
 	u32 val = 0;
+	int err;
 
 	/*
 	 * Any MT7621 Ralink pcie controller that doesn't have 0x0101 at
@@ -598,18 +394,36 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port)
 	val = read_config(pcie, slot, PCIE_FTS_NUM);
 	dev_info(dev, "Port %d N_FTS = %x\n", (unsigned int)val, slot);
 
+	err = phy_init(port->phy);
+	if (err) {
+		dev_err(dev, "failed to initialize port%d phy\n", slot);
+		goto err_phy_init;
+	}
+
+	err = phy_power_on(port->phy);
+	if (err) {
+		dev_err(dev, "failed to power on port%d phy\n", slot);
+		goto err_phy_on;
+	}
+
 	if ((pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) == 0) {
 		dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot);
 		mt7621_control_assert(port);
-		rt_sysc_m32(PCIE_PORT_CLK_EN(slot), 0, RALINK_CLKCFG1);
 		port->enabled = false;
-	} else {
-		port->enabled = true;
+		err = -ENODEV;
+		goto err_no_link_up;
 	}
 
-	mt7621_enable_phy(port);
+	port->enabled = true;
 
 	return 0;
+
+err_no_link_up:
+	phy_power_off(port->phy);
+err_phy_on:
+	phy_exit(port->phy);
+err_phy_init:
+	return err;
 }
 
 static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
-- 
2.19.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree
  2019-01-04  7:08 [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 2/4] staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver Sergio Paracuellos
@ 2019-01-04  7:08 ` Sergio Paracuellos
  2019-02-15  5:42   ` NeilBrown
  2019-01-04  7:08   ` Sergio Paracuellos
  3 siblings, 1 reply; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, driverdev-devel

New driver for pci phy has been added, as well as. pci driver has been
changed to use kernel's generic PHY API. Add related PCI PHY bindings
accordly.

Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
---
 drivers/staging/mt7621-dts/mt7621.dtsi | 31 ++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
index 71f069d59ad8..0cbc298ed457 100644
--- a/drivers/staging/mt7621-dts/mt7621.dtsi
+++ b/drivers/staging/mt7621-dts/mt7621.dtsi
@@ -424,6 +424,8 @@
 		reset-names = "pcie0", "pcie1", "pcie2";
 		clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>;
 		clock-names = "pcie0", "pcie1", "pcie2";
+		phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
+		phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
 
 		pcie@0,0 {
 			reg = <0x0000 0 0 0 0>;
@@ -449,4 +451,33 @@
 			bus-range = <0x00 0xff>;
 		};
 	};
+
+	pcie0_phy: pcie-phy@1a149000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a149000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie0_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+
+		pcie1_port: pcie-phy@1 {
+			reg = <1>;
+			#phy-cells = <0>;
+		};
+	};
+
+	pcie1_phy: pcie-phy@1a14a000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a14a000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie2_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+	};
 };
-- 
2.19.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v3 4/4] staging: mt7621-pci-phy: dt-bindings: add bindings for Mediatek MT7621 Pcie PHY
  2019-01-04  7:08 [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver Sergio Paracuellos
@ 2019-01-04  7:08   ` Sergio Paracuellos
  2019-01-04  7:08 ` [PATCH v3 2/4] staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver Sergio Paracuellos
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, Device Tree mailing list, driverdev-devel

Add bindings documentation for PCie PHY of Mediatek MT7621.
This file will be moved into its appropiate documentation bindings'place
when this driver is mainlined.

CC: Device Tree mailing list <devicetree@vger.kernel.org>
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
---
 .../mediatek,mt7621-pci-phy.txt               | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt

diff --git a/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
new file mode 100644
index 000000000000..33a8a698bdd0
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
@@ -0,0 +1,54 @@
+Mediatek Mt7621 PCIe PHY
+
+Required properties:
+- compatible: must be "mediatek,mt7621-pci-phy"
+- reg: base address and length of the PCIe PHY block
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Each PCIe PHY should be represented by a child node
+
+Required properties For the child node:
+- reg: the PHY ID
+0 - PCIe RC 0
+1 - PCIe RC 1
+- #phy-cells: must be 0
+
+Example:
+	pcie0_phy: pcie-phy@1a149000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a149000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie0_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+
+		pcie1_port: pcie-phy@1 {
+			reg = <1>;
+			#phy-cells = <0>;
+		};
+	};
+
+	pcie1_phy: pcie-phy@1a14a000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a14a000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie2_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+	};
+
+	/* users of the PCIe phy */
+
+	pcie: pcie@1e140000 {
+		...
+		...
+		phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
+		phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
+	};
\ No newline at end of file
-- 
2.19.1

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

* [PATCH v3 4/4] staging: mt7621-pci-phy: dt-bindings: add bindings for Mediatek MT7621 Pcie PHY
@ 2019-01-04  7:08   ` Sergio Paracuellos
  0 siblings, 0 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-01-04  7:08 UTC (permalink / raw)
  To: gregkh; +Cc: neil, Device Tree mailing list, driverdev-devel

Add bindings documentation for PCie PHY of Mediatek MT7621.
This file will be moved into its appropiate documentation bindings'place
when this driver is mainlined.

CC: Device Tree mailing list <devicetree@vger.kernel.org>
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
---
 .../mediatek,mt7621-pci-phy.txt               | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt

diff --git a/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
new file mode 100644
index 000000000000..33a8a698bdd0
--- /dev/null
+++ b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt
@@ -0,0 +1,54 @@
+Mediatek Mt7621 PCIe PHY
+
+Required properties:
+- compatible: must be "mediatek,mt7621-pci-phy"
+- reg: base address and length of the PCIe PHY block
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Each PCIe PHY should be represented by a child node
+
+Required properties For the child node:
+- reg: the PHY ID
+0 - PCIe RC 0
+1 - PCIe RC 1
+- #phy-cells: must be 0
+
+Example:
+	pcie0_phy: pcie-phy@1a149000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a149000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie0_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+
+		pcie1_port: pcie-phy@1 {
+			reg = <1>;
+			#phy-cells = <0>;
+		};
+	};
+
+	pcie1_phy: pcie-phy@1a14a000 {
+		compatible = "mediatek,mt7621-pci-phy";
+		reg = <0x1a14a000 0x0700>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pcie2_port: pcie-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+	};
+
+	/* users of the PCIe phy */
+
+	pcie: pcie@1e140000 {
+		...
+		...
+		phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
+		phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
+	};
\ No newline at end of file
-- 
2.19.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree
  2019-01-04  7:08 ` [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree Sergio Paracuellos
@ 2019-02-15  5:42   ` NeilBrown
  2019-02-15  5:57     ` Sergio Paracuellos
  0 siblings, 1 reply; 10+ messages in thread
From: NeilBrown @ 2019-02-15  5:42 UTC (permalink / raw)
  To: Sergio Paracuellos, gregkh; +Cc: driverdev-devel


[-- Attachment #1.1: Type: text/plain, Size: 1824 bytes --]

On Fri, Jan 04 2019, Sergio Paracuellos wrote:

> New driver for pci phy has been added, as well as. pci driver has been
> changed to use kernel's generic PHY API. Add related PCI PHY bindings
> accordly.
>
> Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> ---
>  drivers/staging/mt7621-dts/mt7621.dtsi | 31 ++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>
> diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
> index 71f069d59ad8..0cbc298ed457 100644
> --- a/drivers/staging/mt7621-dts/mt7621.dtsi
> +++ b/drivers/staging/mt7621-dts/mt7621.dtsi
> @@ -424,6 +424,8 @@
>  		reset-names = "pcie0", "pcie1", "pcie2";
>  		clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>;
>  		clock-names = "pcie0", "pcie1", "pcie2";
> +		phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
> +		phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
>  
>  		pcie@0,0 {
>  			reg = <0x0000 0 0 0 0>;
> @@ -449,4 +451,33 @@
>  			bus-range = <0x00 0xff>;
>  		};
>  	};
> +
> +	pcie0_phy: pcie-phy@1a149000 {

Sorry for the late testing...
This should be "1e149000", 'e', not 'a'.

Same for pcie1_phy.

Thanks,
NeilBrown


> +		compatible = "mediatek,mt7621-pci-phy";
> +		reg = <0x1a149000 0x0700>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		pcie0_port: pcie-phy@0 {
> +			reg = <0>;
> +			#phy-cells = <0>;
> +		};
> +
> +		pcie1_port: pcie-phy@1 {
> +			reg = <1>;
> +			#phy-cells = <0>;
> +		};
> +	};
> +
> +	pcie1_phy: pcie-phy@1a14a000 {
> +		compatible = "mediatek,mt7621-pci-phy";
> +		reg = <0x1a14a000 0x0700>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		pcie2_port: pcie-phy@0 {
> +			reg = <0>;
> +			#phy-cells = <0>;
> +		};
> +	};
>  };
> -- 
> 2.19.1

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

[-- Attachment #2: Type: text/plain, Size: 169 bytes --]

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci
  2019-01-04  7:08 ` [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Sergio Paracuellos
@ 2019-02-15  5:44   ` NeilBrown
  2019-02-15  5:59     ` Sergio Paracuellos
  0 siblings, 1 reply; 10+ messages in thread
From: NeilBrown @ 2019-02-15  5:44 UTC (permalink / raw)
  To: Sergio Paracuellos, gregkh; +Cc: driverdev-devel


[-- Attachment #1.1: Type: text/plain, Size: 16429 bytes --]

On Fri, Jan 04 2019, Sergio Paracuellos wrote:

> Phy part of the pci for this SoC can be handled using a generic phy
> driver. This commit extracts phy part of the mt7621-pci into a new
> 'mt7621-pci-phy' driver.
>
> Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> ---
>  drivers/staging/Kconfig                       |   2 +
>  drivers/staging/Makefile                      |   1 +
>  drivers/staging/mt7621-pci-phy/Kconfig        |   7 +
>  drivers/staging/mt7621-pci-phy/Makefile       |   1 +
>  drivers/staging/mt7621-pci-phy/TODO           |   4 +
>  .../staging/mt7621-pci-phy/pci-mt7621-phy.c   | 387 ++++++++++++++++++
>  6 files changed, 402 insertions(+)
>  create mode 100644 drivers/staging/mt7621-pci-phy/Kconfig
>  create mode 100644 drivers/staging/mt7621-pci-phy/Makefile
>  create mode 100644 drivers/staging/mt7621-pci-phy/TODO
>  create mode 100644 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
>
> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
> index e4f608815c05..4a3d6e00f7cb 100644
> --- a/drivers/staging/Kconfig
> +++ b/drivers/staging/Kconfig
> @@ -104,6 +104,8 @@ source "drivers/staging/pi433/Kconfig"
>  
>  source "drivers/staging/mt7621-pci/Kconfig"
>  
> +source "drivers/staging/mt7621-pci-phy/Kconfig"
> +
>  source "drivers/staging/mt7621-pinctrl/Kconfig"
>  
>  source "drivers/staging/mt7621-spi/Kconfig"
> diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
> index 5868631e8f1b..413890dd5a14 100644
> --- a/drivers/staging/Makefile
> +++ b/drivers/staging/Makefile
> @@ -42,6 +42,7 @@ obj-$(CONFIG_BCM2835_VCHIQ)	+= vc04_services/
>  obj-$(CONFIG_DRM_VBOXVIDEO)	+= vboxvideo/
>  obj-$(CONFIG_PI433)		+= pi433/
>  obj-$(CONFIG_SOC_MT7621)	+= mt7621-pci/
> +obj-$(CONFIG_SOC_MT7621)	+= mt7621-pci-phy/
>  obj-$(CONFIG_SOC_MT7621)	+= mt7621-pinctrl/
>  obj-$(CONFIG_SOC_MT7621)	+= mt7621-spi/
>  obj-$(CONFIG_SOC_MT7621)	+= mt7621-dma/
> diff --git a/drivers/staging/mt7621-pci-phy/Kconfig b/drivers/staging/mt7621-pci-phy/Kconfig
> new file mode 100644
> index 000000000000..b9f6ab784ee8
> --- /dev/null
> +++ b/drivers/staging/mt7621-pci-phy/Kconfig
> @@ -0,0 +1,7 @@
> +config PCI_MT7621_PHY
> +	tristate "MediaTek MT7621 PCI PHY Driver"
> +	depends on RALINK && OF
> +	select GENERIC_PHY
> +	help
> +	  Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver,
> +
> diff --git a/drivers/staging/mt7621-pci-phy/Makefile b/drivers/staging/mt7621-pci-phy/Makefile
> new file mode 100644
> index 000000000000..2b82ccfc28c6
> --- /dev/null
> +++ b/drivers/staging/mt7621-pci-phy/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_SOC_MT7621)       += pci-mt7621-phy.o
> diff --git a/drivers/staging/mt7621-pci-phy/TODO b/drivers/staging/mt7621-pci-phy/TODO
> new file mode 100644
> index 000000000000..a255e8f753eb
> --- /dev/null
> +++ b/drivers/staging/mt7621-pci-phy/TODO
> @@ -0,0 +1,4 @@
> +
> +- general code review and cleanup
> +
> +Cc:  NeilBrown <neil@brown.name> and Sergio Paracuellos <sergio.paracuellos@gmail.com>
> diff --git a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
> new file mode 100644
> index 000000000000..3d16716cfebc
> --- /dev/null
> +++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
> @@ -0,0 +1,387 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Mediatek MT7621 PCI PHY Driver
> + * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> + */
> +
> +#include <dt-bindings/phy/phy.h>
> +#include <linux/bitops.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <mt7621.h>
> +#include <ralink_regs.h>
> +
> +#define RALINK_CLKCFG1			0x30
> +#define CHIP_REV_MT7621_E2		0x0101
> +
> +#define PCIE_PORT_CLK_EN(x)		BIT(24 + (x))
> +
> +#define RG_PE1_PIPE_REG			0x02c
> +#define RG_PE1_PIPE_RST			BIT(12)
> +#define RG_PE1_PIPE_CMD_FRC		BIT(4)
> +
> +#define RG_P0_TO_P1_WIDTH		0x100
> +#define RG_PE1_H_LCDDS_REG		0x49c
> +#define RG_PE1_H_LCDDS_PCW		GENMASK(30, 0)
> +#define RG_PE1_H_LCDDS_PCW_VAL(x)	((0x7fffffff & (x)) << 0)
> +
> +#define RG_PE1_FRC_H_XTAL_REG		0x400
> +#define RG_PE1_FRC_H_XTAL_TYPE          BIT(8)
> +#define RG_PE1_H_XTAL_TYPE              GENMASK(10, 9)
> +#define RG_PE1_H_XTAL_TYPE_VAL(x)       ((0x3 & (x)) << 9)
> +
> +#define RG_PE1_FRC_PHY_REG		0x000
> +#define RG_PE1_FRC_PHY_EN               BIT(4)
> +#define RG_PE1_PHY_EN                   BIT(5)
> +
> +#define RG_PE1_H_PLL_REG		0x490
> +#define RG_PE1_H_PLL_BC			GENMASK(23, 22)
> +#define RG_PE1_H_PLL_BC_VAL(x)		((0x3 & (x)) << 22)
> +#define RG_PE1_H_PLL_BP			GENMASK(21, 18)
> +#define RG_PE1_H_PLL_BP_VAL(x)		((0xf & (x)) << 18)
> +#define RG_PE1_H_PLL_IR			GENMASK(15, 12)
> +#define RG_PE1_H_PLL_IR_VAL(x)		((0xf & (x)) << 12)
> +#define RG_PE1_H_PLL_IC			GENMASK(11, 8)
> +#define RG_PE1_H_PLL_IC_VAL(x)		((0xf & (x)) << 8)
> +#define RG_PE1_H_PLL_PREDIV             GENMASK(7, 6)
> +#define RG_PE1_H_PLL_PREDIV_VAL(x)      ((0x3 & (x)) << 6)
> +#define RG_PE1_PLL_DIVEN		GENMASK(3, 1)
> +#define RG_PE1_PLL_DIVEN_VAL(x)		((0x7 & (x)) << 1)
> +
> +#define RG_PE1_H_PLL_FBKSEL_REG		0x4bc
> +#define RG_PE1_H_PLL_FBKSEL             GENMASK(5, 4)
> +#define RG_PE1_H_PLL_FBKSEL_VAL(x)      ((0x3 & (x)) << 4)
> +
> +#define	RG_PE1_H_LCDDS_SSC_PRD_REG	0x4a4
> +#define RG_PE1_H_LCDDS_SSC_PRD          GENMASK(15, 0)
> +#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x)   ((0xffff & (x)) << 0)
> +
> +#define RG_PE1_H_LCDDS_SSC_DELTA_REG	0x4a8
> +#define RG_PE1_H_LCDDS_SSC_DELTA        GENMASK(11, 0)
> +#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
> +#define RG_PE1_H_LCDDS_SSC_DELTA1       GENMASK(27, 16)
> +#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
> +
> +#define RG_PE1_LCDDS_CLK_PH_INV_REG	0x4a0
> +#define RG_PE1_LCDDS_CLK_PH_INV		BIT(5)
> +
> +#define RG_PE1_H_PLL_BR_REG		0x4ac
> +#define RG_PE1_H_PLL_BR			GENMASK(18, 16)
> +#define RG_PE1_H_PLL_BR_VAL(x)		((0x7 & (x)) << 16)
> +
> +#define	RG_PE1_MSTCKDIV_REG		0x414
> +#define RG_PE1_MSTCKDIV			GENMASK(7, 6)
> +#define RG_PE1_MSTCKDIV_VAL(x)		((0x3 & (x)) << 6)
> +
> +#define RG_PE1_FRC_MSTCKDIV		BIT(5)
> +
> +/**
> + * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
> + * @phy: pointer to the kernel PHY device
> + * @port_base: base register
> + * @index: internal ID to identify the Mt7621 PCIe PHY
> + */
> +struct mt7621_pci_phy_instance {
> +	struct phy *phy;
> +	void __iomem *port_base;
> +	u32 index;
> +};
> +
> +/**
> + * struct mt7621_pci_phy - Mt7621 Pcie PHY core
> + * @dev: pointer to device
> + * @phys: pointer to Mt7621 PHY device
> + * @nphys: number of PHY devices for this core
> + */
> +struct mt7621_pci_phy {
> +	struct device *dev;
> +	struct mt7621_pci_phy_instance **phys;
> +	int nphys;
> +};
> +
> +static inline u32 phy_read(struct mt7621_pci_phy_instance *instance, u32 reg)
> +{
> +	return readl(instance->port_base + reg);
> +}
> +
> +static inline void phy_write(struct mt7621_pci_phy_instance *instance,
> +			     u32 val, u32 reg)
> +{
> +	writel(val, instance->port_base + reg);
> +}
> +
> +static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy,
> +				   struct mt7621_pci_phy_instance *instance)
> +{
> +	u32 offset = (instance->index != 1) ?
> +		RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
> +	u32 reg;
> +
> +	reg = phy_read(instance, offset);
> +	reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
> +	reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
> +	phy_write(instance, reg, offset);
> +}
> +
> +static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy,
> +				   struct mt7621_pci_phy_instance *instance)
> +{
> +	struct device *dev = phy->dev;
> +	u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
> +	u32 offset;
> +	u32 val;
> +
> +	reg = (reg >> 6) & 0x7;
> +	/* Set PCIe Port PHY to disable SSC */
> +	/* Debug Xtal Type */
> +	val = phy_read(instance, RG_PE1_FRC_H_XTAL_REG);
> +	val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
> +	val |= RG_PE1_FRC_H_XTAL_TYPE;
> +	val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
> +	phy_write(instance, val, RG_PE1_FRC_H_XTAL_REG);
> +
> +	/* disable port */
> +	offset = (instance->index != 1) ?
> +		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> +	val = phy_read(instance, offset);
> +	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> +	val |= RG_PE1_FRC_PHY_EN;
> +	phy_write(instance, val, offset);
> +
> +	/* Set Pre-divider ratio (for host mode) */
> +	val = phy_read(instance, RG_PE1_H_PLL_REG);
> +	val &= ~(RG_PE1_H_PLL_PREDIV);
> +
> +	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
> +		val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
> +		phy_write(instance, val, RG_PE1_H_PLL_REG);
> +		dev_info(dev, "Xtal is 40MHz\n");
> +	} else { /* 25MHz | 20MHz Xtal */
> +		val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
> +		phy_write(instance, val, RG_PE1_H_PLL_REG);
> +		if (reg >= 6) {
> +			dev_info(dev, "Xtal is 25MHz\n");
> +
> +			/* Select feedback clock */
> +			val = phy_read(instance, RG_PE1_H_PLL_FBKSEL_REG);
> +			val &= ~(RG_PE1_H_PLL_FBKSEL);
> +			val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
> +			phy_write(instance, val, RG_PE1_H_PLL_FBKSEL_REG);
> +
> +			/* DDS NCPO PCW (for host mode) */
> +			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
> +			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
> +			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
> +			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
> +
> +			/* DDS SSC dither period control */
> +			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
> +			val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
> +			val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
> +			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
> +
> +			/* DDS SSC dither amplitude control */
> +			val = phy_read(instance, RG_PE1_H_LCDDS_SSC_DELTA_REG);
> +			val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
> +				 RG_PE1_H_LCDDS_SSC_DELTA1);
> +			val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
> +			val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
> +			phy_write(instance, val, RG_PE1_H_LCDDS_SSC_DELTA_REG);
> +		} else {
> +			dev_info(dev, "Xtal is 20MHz\n");
> +		}
> +	}
> +
> +	/* DDS clock inversion */
> +	val = phy_read(instance, RG_PE1_LCDDS_CLK_PH_INV_REG);
> +	val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
> +	val |= RG_PE1_LCDDS_CLK_PH_INV;
> +	phy_write(instance, val, RG_PE1_LCDDS_CLK_PH_INV_REG);
> +
> +	/* Set PLL bits */
> +	val = phy_read(instance, RG_PE1_H_PLL_REG);
> +	val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
> +		 RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
> +	val |= RG_PE1_H_PLL_BC_VAL(0x02);
> +	val |= RG_PE1_H_PLL_BP_VAL(0x06);
> +	val |= RG_PE1_H_PLL_IR_VAL(0x02);
> +	val |= RG_PE1_H_PLL_IC_VAL(0x01);
> +	val |= RG_PE1_PLL_DIVEN_VAL(0x02);
> +	phy_write(instance, val, RG_PE1_H_PLL_REG);
> +
> +	val = phy_read(instance, RG_PE1_H_PLL_BR_REG);
> +	val &= ~(RG_PE1_H_PLL_BR);
> +	val |= RG_PE1_H_PLL_BR_VAL(0x00);
> +	phy_write(instance, val, RG_PE1_H_PLL_BR_REG);
> +
> +	if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
> +		/* set force mode enable of da_pe1_mstckdiv */
> +		val = phy_read(instance, RG_PE1_MSTCKDIV_REG);
> +		val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
> +		val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
> +		phy_write(instance, val, RG_PE1_MSTCKDIV_REG);
> +	}
> +}
> +
> +static int mt7621_pci_phy_init(struct phy *phy)
> +{
> +	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> +	struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
> +	u32 chip_rev_id = rt_sysc_r32(SYSC_REG_CHIP_REV);
> +
> +	if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
> +		mt7621_bypass_pipe_rst(mphy, instance);
> +
> +	mt7621_set_phy_for_ssc(mphy, instance);
> +
> +	return 0;
> +}
> +
> +static int mt7621_pci_phy_power_on(struct phy *phy)
> +{
> +	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> +	u32 offset = (instance->index != 1) ?
> +		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> +	u32 val;
> +
> +	/* Enable PHY and disable force mode */
> +	val = phy_read(instance, offset);
> +	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> +	val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> +	phy_write(instance, val, offset);
> +
> +	return 0;
> +}
> +
> +static int mt7621_pci_phy_power_off(struct phy *phy)
> +{
> +	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> +	u32 offset = (instance->index != 1) ?
> +		RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> +	u32 val;
> +
> +	/* Disable PHY */
> +	val = phy_read(instance, offset);
> +	val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> +	val |= RG_PE1_FRC_PHY_EN;
> +	phy_write(instance, val, offset);
> +
> +	return 0;
> +}
> +
> +static int mt7621_pci_phy_exit(struct phy *phy)
> +{
> +	struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> +
> +	rt_sysc_m32(PCIE_PORT_CLK_EN(instance->index), 0, RALINK_CLKCFG1);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mt7621_pci_phy_ops = {
> +	.init		= mt7621_pci_phy_init,
> +	.exit		= mt7621_pci_phy_exit,
> +	.power_on	= mt7621_pci_phy_power_on,
> +	.power_off	= mt7621_pci_phy_power_off,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int mt7621_pci_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct device_node *child_np;
> +	struct phy_provider *provider;
> +	struct mt7621_pci_phy *phy;
> +	struct resource res;
> +	int port, ret;
> +	void __iomem *port_base;
> +
> +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> +	if (!phy)
> +		return -ENOMEM;
> +
> +	phy->nphys = of_get_child_count(np);
> +	phy->phys = devm_kcalloc(dev, phy->nphys,
> +				 sizeof(*phy->phys), GFP_KERNEL);
> +	if (!phy->phys)
> +		return -ENOMEM;
> +
> +	phy->dev = dev;
> +	platform_set_drvdata(pdev, phy);
> +
> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret) {
> +		dev_err(dev, "failed to get address resource(id-%d)\n", port);
> +		return ret;
> +	}
> +
> +	port_base = devm_ioremap_resource(dev, &res);
> +	if (IS_ERR(port_base)) {
> +		dev_err(dev, "failed to remap phy regs\n");
> +		return PTR_ERR(port_base);
> +	}
> +
> +	port = 0;
> +	for_each_child_of_node(np, child_np) {
> +		struct mt7621_pci_phy_instance *instance;
> +		struct phy *pphy;
> +
> +		instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
> +		if (!instance) {
> +			ret = -ENOMEM;
> +			goto put_child;
> +		}
> +
> +		phy->phys[port] = instance;
> +
> +		pphy = devm_phy_create(dev, child_np, &mt7621_pci_phy_ops);
> +		if (IS_ERR(phy)) {
> +			dev_err(dev, "failed to create phy\n");
> +			ret = PTR_ERR(phy);
> +			goto put_child;
> +		}
> +
> +		instance->port_base = port_base;
> +		instance->phy = pphy;
> +		instance->index = port;
> +		phy_set_drvdata(pphy, instance);
> +		port++;
> +	}
> +
> +	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(provider);
> +
> +put_child:
> +	of_node_put(child_np);
> +	return ret;
> +}
> +
> +static const struct of_device_id mt7621_pci_phy_ids[] = {
> +	{ .compatible = "mediatek,mt7621-pci-phy" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
> +
> +static struct platform_driver mt7621_pci_phy_driver = {
> +	.probe = mt7621_pci_phy_probe,
> +	.driver = {
> +		.name = "mt7621-pci-phy",
> +		.of_match_table = of_match_ptr(mt7621_pci_phy_ids),
> +	},
> +};
> +
> +static int __init mt7621_pci_phy_drv_init(void)
> +{
> +	return platform_driver_register(&mt7621_pci_phy_driver);
> +}
> +
> +arch_initcall(mt7621_pci_phy_drv_init);

This doesn't work as arch_initcall().  It causes phy_create() to be
called before the phy module is initialized, so 'phy_class' is NULL, the
new phy isn't placed in the right class, and it cannot be found.

I changed to module_init() and it works.

Thanks,
NeilBrown


> +
> +MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
> +MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.19.1

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

[-- Attachment #2: Type: text/plain, Size: 169 bytes --]

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree
  2019-02-15  5:42   ` NeilBrown
@ 2019-02-15  5:57     ` Sergio Paracuellos
  0 siblings, 0 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-02-15  5:57 UTC (permalink / raw)
  To: NeilBrown; +Cc: Greg KH, driverdev-devel

Hi Neil,

On Fri, Feb 15, 2019 at 6:42 AM NeilBrown <neil@brown.name> wrote:
>
> On Fri, Jan 04 2019, Sergio Paracuellos wrote:
>
> > New driver for pci phy has been added, as well as. pci driver has been
> > changed to use kernel's generic PHY API. Add related PCI PHY bindings
> > accordly.
> >
> > Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> > ---
> >  drivers/staging/mt7621-dts/mt7621.dtsi | 31 ++++++++++++++++++++++++++
> >  1 file changed, 31 insertions(+)
> >
> > diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
> > index 71f069d59ad8..0cbc298ed457 100644
> > --- a/drivers/staging/mt7621-dts/mt7621.dtsi
> > +++ b/drivers/staging/mt7621-dts/mt7621.dtsi
> > @@ -424,6 +424,8 @@
> >               reset-names = "pcie0", "pcie1", "pcie2";
> >               clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>;
> >               clock-names = "pcie0", "pcie1", "pcie2";
> > +             phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>;
> > +             phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
> >
> >               pcie@0,0 {
> >                       reg = <0x0000 0 0 0 0>;
> > @@ -449,4 +451,33 @@
> >                       bus-range = <0x00 0xff>;
> >               };
> >       };
> > +
> > +     pcie0_phy: pcie-phy@1a149000 {
>
> Sorry for the late testing...
> This should be "1e149000", 'e', not 'a'.
>
> Same for pcie1_phy.

You are totally right. My bad here. I will fix this and send changes
as a fix patch.

>
> Thanks,
> NeilBrown

Thanks for testing and let me know.

Best regards,
    Sergio Paracuellos
>
>
> > +             compatible = "mediatek,mt7621-pci-phy";
> > +             reg = <0x1a149000 0x0700>;
> > +             #address-cells = <1>;
> > +             #size-cells = <0>;
> > +
> > +             pcie0_port: pcie-phy@0 {
> > +                     reg = <0>;
> > +                     #phy-cells = <0>;
> > +             };
> > +
> > +             pcie1_port: pcie-phy@1 {
> > +                     reg = <1>;
> > +                     #phy-cells = <0>;
> > +             };
> > +     };
> > +
> > +     pcie1_phy: pcie-phy@1a14a000 {
> > +             compatible = "mediatek,mt7621-pci-phy";
> > +             reg = <0x1a14a000 0x0700>;
> > +             #address-cells = <1>;
> > +             #size-cells = <0>;
> > +
> > +             pcie2_port: pcie-phy@0 {
> > +                     reg = <0>;
> > +                     #phy-cells = <0>;
> > +             };
> > +     };
> >  };
> > --
> > 2.19.1
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci
  2019-02-15  5:44   ` NeilBrown
@ 2019-02-15  5:59     ` Sergio Paracuellos
  0 siblings, 0 replies; 10+ messages in thread
From: Sergio Paracuellos @ 2019-02-15  5:59 UTC (permalink / raw)
  To: NeilBrown; +Cc: Greg KH, driverdev-devel

On Fri, Feb 15, 2019 at 6:44 AM NeilBrown <neil@brown.name> wrote:
>
> On Fri, Jan 04 2019, Sergio Paracuellos wrote:
>
> > Phy part of the pci for this SoC can be handled using a generic phy
> > driver. This commit extracts phy part of the mt7621-pci into a new
> > 'mt7621-pci-phy' driver.
> >
> > Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> > ---
> >  drivers/staging/Kconfig                       |   2 +
> >  drivers/staging/Makefile                      |   1 +
> >  drivers/staging/mt7621-pci-phy/Kconfig        |   7 +
> >  drivers/staging/mt7621-pci-phy/Makefile       |   1 +
> >  drivers/staging/mt7621-pci-phy/TODO           |   4 +
> >  .../staging/mt7621-pci-phy/pci-mt7621-phy.c   | 387 ++++++++++++++++++
> >  6 files changed, 402 insertions(+)
> >  create mode 100644 drivers/staging/mt7621-pci-phy/Kconfig
> >  create mode 100644 drivers/staging/mt7621-pci-phy/Makefile
> >  create mode 100644 drivers/staging/mt7621-pci-phy/TODO
> >  create mode 100644 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
> >
> > diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
> > index e4f608815c05..4a3d6e00f7cb 100644
> > --- a/drivers/staging/Kconfig
> > +++ b/drivers/staging/Kconfig
> > @@ -104,6 +104,8 @@ source "drivers/staging/pi433/Kconfig"
> >
> >  source "drivers/staging/mt7621-pci/Kconfig"
> >
> > +source "drivers/staging/mt7621-pci-phy/Kconfig"
> > +
> >  source "drivers/staging/mt7621-pinctrl/Kconfig"
> >
> >  source "drivers/staging/mt7621-spi/Kconfig"
> > diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
> > index 5868631e8f1b..413890dd5a14 100644
> > --- a/drivers/staging/Makefile
> > +++ b/drivers/staging/Makefile
> > @@ -42,6 +42,7 @@ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
> >  obj-$(CONFIG_DRM_VBOXVIDEO)  += vboxvideo/
> >  obj-$(CONFIG_PI433)          += pi433/
> >  obj-$(CONFIG_SOC_MT7621)     += mt7621-pci/
> > +obj-$(CONFIG_SOC_MT7621)     += mt7621-pci-phy/
> >  obj-$(CONFIG_SOC_MT7621)     += mt7621-pinctrl/
> >  obj-$(CONFIG_SOC_MT7621)     += mt7621-spi/
> >  obj-$(CONFIG_SOC_MT7621)     += mt7621-dma/
> > diff --git a/drivers/staging/mt7621-pci-phy/Kconfig b/drivers/staging/mt7621-pci-phy/Kconfig
> > new file mode 100644
> > index 000000000000..b9f6ab784ee8
> > --- /dev/null
> > +++ b/drivers/staging/mt7621-pci-phy/Kconfig
> > @@ -0,0 +1,7 @@
> > +config PCI_MT7621_PHY
> > +     tristate "MediaTek MT7621 PCI PHY Driver"
> > +     depends on RALINK && OF
> > +     select GENERIC_PHY
> > +     help
> > +       Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver,
> > +
> > diff --git a/drivers/staging/mt7621-pci-phy/Makefile b/drivers/staging/mt7621-pci-phy/Makefile
> > new file mode 100644
> > index 000000000000..2b82ccfc28c6
> > --- /dev/null
> > +++ b/drivers/staging/mt7621-pci-phy/Makefile
> > @@ -0,0 +1 @@
> > +obj-$(CONFIG_SOC_MT7621)       += pci-mt7621-phy.o
> > diff --git a/drivers/staging/mt7621-pci-phy/TODO b/drivers/staging/mt7621-pci-phy/TODO
> > new file mode 100644
> > index 000000000000..a255e8f753eb
> > --- /dev/null
> > +++ b/drivers/staging/mt7621-pci-phy/TODO
> > @@ -0,0 +1,4 @@
> > +
> > +- general code review and cleanup
> > +
> > +Cc:  NeilBrown <neil@brown.name> and Sergio Paracuellos <sergio.paracuellos@gmail.com>
> > diff --git a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
> > new file mode 100644
> > index 000000000000..3d16716cfebc
> > --- /dev/null
> > +++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
> > @@ -0,0 +1,387 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Mediatek MT7621 PCI PHY Driver
> > + * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> > + */
> > +
> > +#include <dt-bindings/phy/phy.h>
> > +#include <linux/bitops.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <mt7621.h>
> > +#include <ralink_regs.h>
> > +
> > +#define RALINK_CLKCFG1                       0x30
> > +#define CHIP_REV_MT7621_E2           0x0101
> > +
> > +#define PCIE_PORT_CLK_EN(x)          BIT(24 + (x))
> > +
> > +#define RG_PE1_PIPE_REG                      0x02c
> > +#define RG_PE1_PIPE_RST                      BIT(12)
> > +#define RG_PE1_PIPE_CMD_FRC          BIT(4)
> > +
> > +#define RG_P0_TO_P1_WIDTH            0x100
> > +#define RG_PE1_H_LCDDS_REG           0x49c
> > +#define RG_PE1_H_LCDDS_PCW           GENMASK(30, 0)
> > +#define RG_PE1_H_LCDDS_PCW_VAL(x)    ((0x7fffffff & (x)) << 0)
> > +
> > +#define RG_PE1_FRC_H_XTAL_REG                0x400
> > +#define RG_PE1_FRC_H_XTAL_TYPE          BIT(8)
> > +#define RG_PE1_H_XTAL_TYPE              GENMASK(10, 9)
> > +#define RG_PE1_H_XTAL_TYPE_VAL(x)       ((0x3 & (x)) << 9)
> > +
> > +#define RG_PE1_FRC_PHY_REG           0x000
> > +#define RG_PE1_FRC_PHY_EN               BIT(4)
> > +#define RG_PE1_PHY_EN                   BIT(5)
> > +
> > +#define RG_PE1_H_PLL_REG             0x490
> > +#define RG_PE1_H_PLL_BC                      GENMASK(23, 22)
> > +#define RG_PE1_H_PLL_BC_VAL(x)               ((0x3 & (x)) << 22)
> > +#define RG_PE1_H_PLL_BP                      GENMASK(21, 18)
> > +#define RG_PE1_H_PLL_BP_VAL(x)               ((0xf & (x)) << 18)
> > +#define RG_PE1_H_PLL_IR                      GENMASK(15, 12)
> > +#define RG_PE1_H_PLL_IR_VAL(x)               ((0xf & (x)) << 12)
> > +#define RG_PE1_H_PLL_IC                      GENMASK(11, 8)
> > +#define RG_PE1_H_PLL_IC_VAL(x)               ((0xf & (x)) << 8)
> > +#define RG_PE1_H_PLL_PREDIV             GENMASK(7, 6)
> > +#define RG_PE1_H_PLL_PREDIV_VAL(x)      ((0x3 & (x)) << 6)
> > +#define RG_PE1_PLL_DIVEN             GENMASK(3, 1)
> > +#define RG_PE1_PLL_DIVEN_VAL(x)              ((0x7 & (x)) << 1)
> > +
> > +#define RG_PE1_H_PLL_FBKSEL_REG              0x4bc
> > +#define RG_PE1_H_PLL_FBKSEL             GENMASK(5, 4)
> > +#define RG_PE1_H_PLL_FBKSEL_VAL(x)      ((0x3 & (x)) << 4)
> > +
> > +#define      RG_PE1_H_LCDDS_SSC_PRD_REG      0x4a4
> > +#define RG_PE1_H_LCDDS_SSC_PRD          GENMASK(15, 0)
> > +#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x)   ((0xffff & (x)) << 0)
> > +
> > +#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8
> > +#define RG_PE1_H_LCDDS_SSC_DELTA        GENMASK(11, 0)
> > +#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
> > +#define RG_PE1_H_LCDDS_SSC_DELTA1       GENMASK(27, 16)
> > +#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
> > +
> > +#define RG_PE1_LCDDS_CLK_PH_INV_REG  0x4a0
> > +#define RG_PE1_LCDDS_CLK_PH_INV              BIT(5)
> > +
> > +#define RG_PE1_H_PLL_BR_REG          0x4ac
> > +#define RG_PE1_H_PLL_BR                      GENMASK(18, 16)
> > +#define RG_PE1_H_PLL_BR_VAL(x)               ((0x7 & (x)) << 16)
> > +
> > +#define      RG_PE1_MSTCKDIV_REG             0x414
> > +#define RG_PE1_MSTCKDIV                      GENMASK(7, 6)
> > +#define RG_PE1_MSTCKDIV_VAL(x)               ((0x3 & (x)) << 6)
> > +
> > +#define RG_PE1_FRC_MSTCKDIV          BIT(5)
> > +
> > +/**
> > + * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
> > + * @phy: pointer to the kernel PHY device
> > + * @port_base: base register
> > + * @index: internal ID to identify the Mt7621 PCIe PHY
> > + */
> > +struct mt7621_pci_phy_instance {
> > +     struct phy *phy;
> > +     void __iomem *port_base;
> > +     u32 index;
> > +};
> > +
> > +/**
> > + * struct mt7621_pci_phy - Mt7621 Pcie PHY core
> > + * @dev: pointer to device
> > + * @phys: pointer to Mt7621 PHY device
> > + * @nphys: number of PHY devices for this core
> > + */
> > +struct mt7621_pci_phy {
> > +     struct device *dev;
> > +     struct mt7621_pci_phy_instance **phys;
> > +     int nphys;
> > +};
> > +
> > +static inline u32 phy_read(struct mt7621_pci_phy_instance *instance, u32 reg)
> > +{
> > +     return readl(instance->port_base + reg);
> > +}
> > +
> > +static inline void phy_write(struct mt7621_pci_phy_instance *instance,
> > +                          u32 val, u32 reg)
> > +{
> > +     writel(val, instance->port_base + reg);
> > +}
> > +
> > +static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy,
> > +                                struct mt7621_pci_phy_instance *instance)
> > +{
> > +     u32 offset = (instance->index != 1) ?
> > +             RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
> > +     u32 reg;
> > +
> > +     reg = phy_read(instance, offset);
> > +     reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
> > +     reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
> > +     phy_write(instance, reg, offset);
> > +}
> > +
> > +static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy,
> > +                                struct mt7621_pci_phy_instance *instance)
> > +{
> > +     struct device *dev = phy->dev;
> > +     u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
> > +     u32 offset;
> > +     u32 val;
> > +
> > +     reg = (reg >> 6) & 0x7;
> > +     /* Set PCIe Port PHY to disable SSC */
> > +     /* Debug Xtal Type */
> > +     val = phy_read(instance, RG_PE1_FRC_H_XTAL_REG);
> > +     val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE);
> > +     val |= RG_PE1_FRC_H_XTAL_TYPE;
> > +     val |= RG_PE1_H_XTAL_TYPE_VAL(0x00);
> > +     phy_write(instance, val, RG_PE1_FRC_H_XTAL_REG);
> > +
> > +     /* disable port */
> > +     offset = (instance->index != 1) ?
> > +             RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> > +     val = phy_read(instance, offset);
> > +     val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> > +     val |= RG_PE1_FRC_PHY_EN;
> > +     phy_write(instance, val, offset);
> > +
> > +     /* Set Pre-divider ratio (for host mode) */
> > +     val = phy_read(instance, RG_PE1_H_PLL_REG);
> > +     val &= ~(RG_PE1_H_PLL_PREDIV);
> > +
> > +     if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
> > +             val |= RG_PE1_H_PLL_PREDIV_VAL(0x01);
> > +             phy_write(instance, val, RG_PE1_H_PLL_REG);
> > +             dev_info(dev, "Xtal is 40MHz\n");
> > +     } else { /* 25MHz | 20MHz Xtal */
> > +             val |= RG_PE1_H_PLL_PREDIV_VAL(0x00);
> > +             phy_write(instance, val, RG_PE1_H_PLL_REG);
> > +             if (reg >= 6) {
> > +                     dev_info(dev, "Xtal is 25MHz\n");
> > +
> > +                     /* Select feedback clock */
> > +                     val = phy_read(instance, RG_PE1_H_PLL_FBKSEL_REG);
> > +                     val &= ~(RG_PE1_H_PLL_FBKSEL);
> > +                     val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
> > +                     phy_write(instance, val, RG_PE1_H_PLL_FBKSEL_REG);
> > +
> > +                     /* DDS NCPO PCW (for host mode) */
> > +                     val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
> > +                     val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
> > +                     val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
> > +                     phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
> > +
> > +                     /* DDS SSC dither period control */
> > +                     val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG);
> > +                     val &= ~(RG_PE1_H_LCDDS_SSC_PRD);
> > +                     val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
> > +                     phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG);
> > +
> > +                     /* DDS SSC dither amplitude control */
> > +                     val = phy_read(instance, RG_PE1_H_LCDDS_SSC_DELTA_REG);
> > +                     val &= ~(RG_PE1_H_LCDDS_SSC_DELTA |
> > +                              RG_PE1_H_LCDDS_SSC_DELTA1);
> > +                     val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
> > +                     val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
> > +                     phy_write(instance, val, RG_PE1_H_LCDDS_SSC_DELTA_REG);
> > +             } else {
> > +                     dev_info(dev, "Xtal is 20MHz\n");
> > +             }
> > +     }
> > +
> > +     /* DDS clock inversion */
> > +     val = phy_read(instance, RG_PE1_LCDDS_CLK_PH_INV_REG);
> > +     val &= ~(RG_PE1_LCDDS_CLK_PH_INV);
> > +     val |= RG_PE1_LCDDS_CLK_PH_INV;
> > +     phy_write(instance, val, RG_PE1_LCDDS_CLK_PH_INV_REG);
> > +
> > +     /* Set PLL bits */
> > +     val = phy_read(instance, RG_PE1_H_PLL_REG);
> > +     val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
> > +              RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN);
> > +     val |= RG_PE1_H_PLL_BC_VAL(0x02);
> > +     val |= RG_PE1_H_PLL_BP_VAL(0x06);
> > +     val |= RG_PE1_H_PLL_IR_VAL(0x02);
> > +     val |= RG_PE1_H_PLL_IC_VAL(0x01);
> > +     val |= RG_PE1_PLL_DIVEN_VAL(0x02);
> > +     phy_write(instance, val, RG_PE1_H_PLL_REG);
> > +
> > +     val = phy_read(instance, RG_PE1_H_PLL_BR_REG);
> > +     val &= ~(RG_PE1_H_PLL_BR);
> > +     val |= RG_PE1_H_PLL_BR_VAL(0x00);
> > +     phy_write(instance, val, RG_PE1_H_PLL_BR_REG);
> > +
> > +     if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
> > +             /* set force mode enable of da_pe1_mstckdiv */
> > +             val = phy_read(instance, RG_PE1_MSTCKDIV_REG);
> > +             val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV);
> > +             val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV);
> > +             phy_write(instance, val, RG_PE1_MSTCKDIV_REG);
> > +     }
> > +}
> > +
> > +static int mt7621_pci_phy_init(struct phy *phy)
> > +{
> > +     struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> > +     struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
> > +     u32 chip_rev_id = rt_sysc_r32(SYSC_REG_CHIP_REV);
> > +
> > +     if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2)
> > +             mt7621_bypass_pipe_rst(mphy, instance);
> > +
> > +     mt7621_set_phy_for_ssc(mphy, instance);
> > +
> > +     return 0;
> > +}
> > +
> > +static int mt7621_pci_phy_power_on(struct phy *phy)
> > +{
> > +     struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> > +     u32 offset = (instance->index != 1) ?
> > +             RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> > +     u32 val;
> > +
> > +     /* Enable PHY and disable force mode */
> > +     val = phy_read(instance, offset);
> > +     val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> > +     val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> > +     phy_write(instance, val, offset);
> > +
> > +     return 0;
> > +}
> > +
> > +static int mt7621_pci_phy_power_off(struct phy *phy)
> > +{
> > +     struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> > +     u32 offset = (instance->index != 1) ?
> > +             RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
> > +     u32 val;
> > +
> > +     /* Disable PHY */
> > +     val = phy_read(instance, offset);
> > +     val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
> > +     val |= RG_PE1_FRC_PHY_EN;
> > +     phy_write(instance, val, offset);
> > +
> > +     return 0;
> > +}
> > +
> > +static int mt7621_pci_phy_exit(struct phy *phy)
> > +{
> > +     struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
> > +
> > +     rt_sysc_m32(PCIE_PORT_CLK_EN(instance->index), 0, RALINK_CLKCFG1);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct phy_ops mt7621_pci_phy_ops = {
> > +     .init           = mt7621_pci_phy_init,
> > +     .exit           = mt7621_pci_phy_exit,
> > +     .power_on       = mt7621_pci_phy_power_on,
> > +     .power_off      = mt7621_pci_phy_power_off,
> > +     .owner          = THIS_MODULE,
> > +};
> > +
> > +static int mt7621_pci_phy_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct device_node *np = dev->of_node;
> > +     struct device_node *child_np;
> > +     struct phy_provider *provider;
> > +     struct mt7621_pci_phy *phy;
> > +     struct resource res;
> > +     int port, ret;
> > +     void __iomem *port_base;
> > +
> > +     phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> > +     if (!phy)
> > +             return -ENOMEM;
> > +
> > +     phy->nphys = of_get_child_count(np);
> > +     phy->phys = devm_kcalloc(dev, phy->nphys,
> > +                              sizeof(*phy->phys), GFP_KERNEL);
> > +     if (!phy->phys)
> > +             return -ENOMEM;
> > +
> > +     phy->dev = dev;
> > +     platform_set_drvdata(pdev, phy);
> > +
> > +     ret = of_address_to_resource(np, 0, &res);
> > +     if (ret) {
> > +             dev_err(dev, "failed to get address resource(id-%d)\n", port);
> > +             return ret;
> > +     }
> > +
> > +     port_base = devm_ioremap_resource(dev, &res);
> > +     if (IS_ERR(port_base)) {
> > +             dev_err(dev, "failed to remap phy regs\n");
> > +             return PTR_ERR(port_base);
> > +     }
> > +
> > +     port = 0;
> > +     for_each_child_of_node(np, child_np) {
> > +             struct mt7621_pci_phy_instance *instance;
> > +             struct phy *pphy;
> > +
> > +             instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
> > +             if (!instance) {
> > +                     ret = -ENOMEM;
> > +                     goto put_child;
> > +             }
> > +
> > +             phy->phys[port] = instance;
> > +
> > +             pphy = devm_phy_create(dev, child_np, &mt7621_pci_phy_ops);
> > +             if (IS_ERR(phy)) {
> > +                     dev_err(dev, "failed to create phy\n");
> > +                     ret = PTR_ERR(phy);
> > +                     goto put_child;
> > +             }
> > +
> > +             instance->port_base = port_base;
> > +             instance->phy = pphy;
> > +             instance->index = port;
> > +             phy_set_drvdata(pphy, instance);
> > +             port++;
> > +     }
> > +
> > +     provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > +
> > +     return PTR_ERR_OR_ZERO(provider);
> > +
> > +put_child:
> > +     of_node_put(child_np);
> > +     return ret;
> > +}
> > +
> > +static const struct of_device_id mt7621_pci_phy_ids[] = {
> > +     { .compatible = "mediatek,mt7621-pci-phy" },
> > +     {},
> > +};
> > +MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
> > +
> > +static struct platform_driver mt7621_pci_phy_driver = {
> > +     .probe = mt7621_pci_phy_probe,
> > +     .driver = {
> > +             .name = "mt7621-pci-phy",
> > +             .of_match_table = of_match_ptr(mt7621_pci_phy_ids),
> > +     },
> > +};
> > +
> > +static int __init mt7621_pci_phy_drv_init(void)
> > +{
> > +     return platform_driver_register(&mt7621_pci_phy_driver);
> > +}
> > +
> > +arch_initcall(mt7621_pci_phy_drv_init);
>
> This doesn't work as arch_initcall().  It causes phy_create() to be
> called before the phy module is initialized, so 'phy_class' is NULL, the
> new phy isn't placed in the right class, and it cannot be found.
>
> I changed to module_init() and it works.

I see. Thanks for letting me know. I will fix and send this minor
change as a fix patch.
Thanks for your effort in testing this.

>
> Thanks,
> NeilBrown

Best regards,
    Sergio Paracuellos
>
>
> > +
> > +MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
> > +MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.19.1
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

end of thread, other threads:[~2019-02-15  6:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-04  7:08 [PATCH v3 0/4] staging: mt7621-pci: extract PCI PHY part into a new 'pci-mt7621-phy' driver Sergio Paracuellos
2019-01-04  7:08 ` [PATCH v3 1/4] staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Sergio Paracuellos
2019-02-15  5:44   ` NeilBrown
2019-02-15  5:59     ` Sergio Paracuellos
2019-01-04  7:08 ` [PATCH v3 2/4] staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver Sergio Paracuellos
2019-01-04  7:08 ` [PATCH v3 3/4] staging: mt7621-dts: add pci-phy related bindings to board's device tree Sergio Paracuellos
2019-02-15  5:42   ` NeilBrown
2019-02-15  5:57     ` Sergio Paracuellos
2019-01-04  7:08 ` [PATCH v3 4/4] staging: mt7621-pci-phy: dt-bindings: add bindings for Mediatek MT7621 Pcie PHY Sergio Paracuellos
2019-01-04  7:08   ` Sergio Paracuellos

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.