diff options
Diffstat (limited to 'target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch')
-rw-r--r-- | target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch b/target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch deleted file mode 100644 index 0964da03a8..0000000000 --- a/target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch +++ /dev/null @@ -1,381 +0,0 @@ -From 9695375a3f4a604406f2e61f2b735eca1de931ed Mon Sep 17 00:00:00 2001 -From: Miquel Raynal <miquel.raynal@bootlin.com> -Date: Tue, 8 Jan 2019 17:31:20 +0100 -Subject: [PATCH] phy: add A3700 COMPHY support - -Add a driver to support COMPHY, a hardware block providing shared -serdes PHYs on Marvell Armada 3700. This driver uses SMC calls and -rely on having an up-to-date firmware. - -SATA, PCie and USB3 host mode have been tested successfully with an -ESPRESSObin. (HS)SGMII mode cannot be tested with this platform. - -Evan worked on the original driver structure and Grzegorz on the SMC -calls rework. The structure of this driver has been copied from -Antoine Tenart work on CP110 COMPHY driver. - -Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> -Co-developed-by: Evan Wang <xswang@marvell.com> -Signed-off-by: Evan Wang <xswang@marvell.com> -Co-developed-by: Grzegorz Jaszczyk <jaz@semihalf.com> -Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com> -Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> ---- - drivers/phy/marvell/Kconfig | 12 + - drivers/phy/marvell/Makefile | 1 + - drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 318 +++++++++++++++++++++++++++ - 3 files changed, 331 insertions(+) - create mode 100644 drivers/phy/marvell/phy-mvebu-a3700-comphy.c - ---- a/drivers/phy/marvell/Kconfig -+++ b/drivers/phy/marvell/Kconfig -@@ -21,6 +21,18 @@ config PHY_BERLIN_USB - help - Enable this to support the USB PHY on Marvell Berlin SoCs. - -+config PHY_MVEBU_A3700_COMPHY -+ tristate "Marvell A3700 comphy driver" -+ depends on ARCH_MVEBU || COMPILE_TEST -+ depends on OF -+ depends on HAVE_ARM_SMCCC -+ default y -+ select GENERIC_PHY -+ help -+ This driver allows to control the comphy, a hardware block providing -+ shared serdes PHYs on Marvell Armada 3700. Its serdes lanes can be -+ used by various controllers: Ethernet, SATA, USB3, PCIe. -+ - config PHY_MVEBU_CP110_COMPHY - tristate "Marvell CP110 comphy driver" - depends on ARCH_MVEBU || COMPILE_TEST ---- a/drivers/phy/marvell/Makefile -+++ b/drivers/phy/marvell/Makefile -@@ -2,6 +2,7 @@ - obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o - obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o - obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o -+obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o - obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o - obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o - obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o ---- /dev/null -+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -@@ -0,0 +1,318 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2018 Marvell -+ * -+ * Authors: -+ * Evan Wang <xswang@marvell.com> -+ * Miquèl Raynal <miquel.raynal@bootlin.com> -+ * -+ * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart. -+ * SMC call initial support done by Grzegorz Jaszczyk. -+ */ -+ -+#include <linux/arm-smccc.h> -+#include <linux/io.h> -+#include <linux/iopoll.h> -+#include <linux/mfd/syscon.h> -+#include <linux/module.h> -+#include <linux/phy.h> -+#include <linux/phy/phy.h> -+#include <linux/platform_device.h> -+ -+#define MVEBU_A3700_COMPHY_LANES 3 -+#define MVEBU_A3700_COMPHY_PORTS 2 -+ -+/* COMPHY Fast SMC function identifiers */ -+#define COMPHY_SIP_POWER_ON 0x82000001 -+#define COMPHY_SIP_POWER_OFF 0x82000002 -+#define COMPHY_SIP_PLL_LOCK 0x82000003 -+ -+#define COMPHY_FW_MODE_SATA 0x1 -+#define COMPHY_FW_MODE_SGMII 0x2 -+#define COMPHY_FW_MODE_HS_SGMII 0x3 -+#define COMPHY_FW_MODE_USB3H 0x4 -+#define COMPHY_FW_MODE_USB3D 0x5 -+#define COMPHY_FW_MODE_PCIE 0x6 -+#define COMPHY_FW_MODE_RXAUI 0x7 -+#define COMPHY_FW_MODE_XFI 0x8 -+#define COMPHY_FW_MODE_SFI 0x9 -+#define COMPHY_FW_MODE_USB3 0xa -+ -+#define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ -+#define COMPHY_FW_SPEED_2_5G 1 -+#define COMPHY_FW_SPEED_3_125G 2 /* SGMII 2.5G */ -+#define COMPHY_FW_SPEED_5G 3 -+#define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ -+#define COMPHY_FW_SPEED_6G 5 -+#define COMPHY_FW_SPEED_10_3125G 6 /* XFI 10G */ -+#define COMPHY_FW_SPEED_MAX 0x3F -+ -+#define COMPHY_FW_MODE(mode) ((mode) << 12) -+#define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ -+ ((idx) << 8) | \ -+ ((speed) << 2)) -+#define COMPHY_FW_PCIE(mode, idx, speed, width) (COMPHY_FW_NET(mode, idx, speed) | \ -+ ((width) << 18)) -+ -+struct mvebu_a3700_comphy_conf { -+ unsigned int lane; -+ enum phy_mode mode; -+ int submode; -+ unsigned int port; -+ u32 fw_mode; -+}; -+ -+#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw) \ -+ { \ -+ .lane = _lane, \ -+ .mode = _mode, \ -+ .submode = _smode, \ -+ .port = _port, \ -+ .fw_mode = _fw, \ -+ } -+ -+#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \ -+ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw) -+ -+#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \ -+ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw) -+ -+static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { -+ /* lane 0 */ -+ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0, -+ COMPHY_FW_MODE_USB3H), -+ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, -+ COMPHY_FW_MODE_SGMII), -+ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, -+ COMPHY_FW_MODE_HS_SGMII), -+ /* lane 1 */ -+ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, -+ COMPHY_FW_MODE_PCIE), -+ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, -+ COMPHY_FW_MODE_SGMII), -+ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, -+ COMPHY_FW_MODE_HS_SGMII), -+ /* lane 2 */ -+ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, -+ COMPHY_FW_MODE_SATA), -+ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0, -+ COMPHY_FW_MODE_USB3H), -+}; -+ -+struct mvebu_a3700_comphy_lane { -+ struct device *dev; -+ unsigned int id; -+ enum phy_mode mode; -+ int submode; -+ int port; -+}; -+ -+static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, -+ unsigned long mode) -+{ -+ struct arm_smccc_res res; -+ -+ arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res); -+ -+ return res.a0; -+} -+ -+static int mvebu_a3700_comphy_get_fw_mode(int lane, int port, -+ enum phy_mode mode, -+ int submode) -+{ -+ int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes); -+ -+ /* Unused PHY mux value is 0x0 */ -+ if (mode == PHY_MODE_INVALID) -+ return -EINVAL; -+ -+ for (i = 0; i < n; i++) { -+ if (mvebu_a3700_comphy_modes[i].lane == lane && -+ mvebu_a3700_comphy_modes[i].port == port && -+ mvebu_a3700_comphy_modes[i].mode == mode && -+ mvebu_a3700_comphy_modes[i].submode == submode) -+ break; -+ } -+ -+ if (i == n) -+ return -EINVAL; -+ -+ return mvebu_a3700_comphy_modes[i].fw_mode; -+} -+ -+static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode, -+ int submode) -+{ -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+ int fw_mode; -+ -+ if (submode == PHY_INTERFACE_MODE_1000BASEX) -+ submode = PHY_INTERFACE_MODE_SGMII; -+ -+ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode, -+ submode); -+ if (fw_mode < 0) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+ return fw_mode; -+ } -+ -+ /* Just remember the mode, ->power_on() will do the real setup */ -+ lane->mode = mode; -+ lane->submode = submode; -+ -+ return 0; -+} -+ -+static int mvebu_a3700_comphy_power_on(struct phy *phy) -+{ -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+ u32 fw_param; -+ int fw_mode; -+ -+ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, -+ lane->mode, lane->submode); -+ if (fw_mode < 0) { -+ dev_err(lane->dev, "invalid COMPHY mode\n"); -+ return fw_mode; -+ } -+ -+ switch (lane->mode) { -+ case PHY_MODE_USB_HOST_SS: -+ dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id); -+ fw_param = COMPHY_FW_MODE(fw_mode); -+ break; -+ case PHY_MODE_SATA: -+ dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id); -+ fw_param = COMPHY_FW_MODE(fw_mode); -+ break; -+ case PHY_MODE_ETHERNET: -+ switch (lane->submode) { -+ case PHY_INTERFACE_MODE_SGMII: -+ dev_dbg(lane->dev, "set lane %d to SGMII mode\n", -+ lane->id); -+ fw_param = COMPHY_FW_NET(fw_mode, lane->port, -+ COMPHY_FW_SPEED_1_25G); -+ break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n", -+ lane->id); -+ fw_param = COMPHY_FW_NET(fw_mode, lane->port, -+ COMPHY_FW_SPEED_3_125G); -+ break; -+ default: -+ dev_err(lane->dev, "unsupported PHY submode (%d)\n", -+ lane->submode); -+ return -ENOTSUPP; -+ } -+ break; -+ case PHY_MODE_PCIE: -+ dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); -+ fw_param = COMPHY_FW_PCIE(fw_mode, lane->port, -+ COMPHY_FW_SPEED_5G, -+ phy->attrs.bus_width); -+ break; -+ default: -+ dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode); -+ return -ENOTSUPP; -+ } -+ -+ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); -+} -+ -+static int mvebu_a3700_comphy_power_off(struct phy *phy) -+{ -+ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); -+ -+ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0); -+} -+ -+static const struct phy_ops mvebu_a3700_comphy_ops = { -+ .power_on = mvebu_a3700_comphy_power_on, -+ .power_off = mvebu_a3700_comphy_power_off, -+ .set_mode = mvebu_a3700_comphy_set_mode, -+ .owner = THIS_MODULE, -+}; -+ -+static struct phy *mvebu_a3700_comphy_xlate(struct device *dev, -+ struct of_phandle_args *args) -+{ -+ struct mvebu_a3700_comphy_lane *lane; -+ struct phy *phy; -+ -+ if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS)) -+ return ERR_PTR(-EINVAL); -+ -+ phy = of_phy_simple_xlate(dev, args); -+ if (IS_ERR(phy)) -+ return phy; -+ -+ lane = phy_get_drvdata(phy); -+ lane->port = args->args[0]; -+ -+ return phy; -+} -+ -+static int mvebu_a3700_comphy_probe(struct platform_device *pdev) -+{ -+ struct phy_provider *provider; -+ struct device_node *child; -+ -+ for_each_available_child_of_node(pdev->dev.of_node, child) { -+ struct mvebu_a3700_comphy_lane *lane; -+ struct phy *phy; -+ int ret; -+ u32 lane_id; -+ -+ ret = of_property_read_u32(child, "reg", &lane_id); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "missing 'reg' property (%d)\n", -+ ret); -+ continue; -+ } -+ -+ if (lane_id >= MVEBU_A3700_COMPHY_LANES) { -+ dev_err(&pdev->dev, "invalid 'reg' property\n"); -+ continue; -+ } -+ -+ lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL); -+ if (!lane) -+ return -ENOMEM; -+ -+ phy = devm_phy_create(&pdev->dev, child, -+ &mvebu_a3700_comphy_ops); -+ if (IS_ERR(phy)) -+ return PTR_ERR(phy); -+ -+ lane->dev = &pdev->dev; -+ lane->mode = PHY_MODE_INVALID; -+ lane->submode = PHY_INTERFACE_MODE_NA; -+ lane->id = lane_id; -+ lane->port = -1; -+ phy_set_drvdata(phy, lane); -+ } -+ -+ provider = devm_of_phy_provider_register(&pdev->dev, -+ mvebu_a3700_comphy_xlate); -+ return PTR_ERR_OR_ZERO(provider); -+} -+ -+static const struct of_device_id mvebu_a3700_comphy_of_match_table[] = { -+ { .compatible = "marvell,comphy-a3700" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, mvebu_a3700_comphy_of_match_table); -+ -+static struct platform_driver mvebu_a3700_comphy_driver = { -+ .probe = mvebu_a3700_comphy_probe, -+ .driver = { -+ .name = "mvebu-a3700-comphy", -+ .of_match_table = mvebu_a3700_comphy_of_match_table, -+ }, -+}; -+module_platform_driver(mvebu_a3700_comphy_driver); -+ -+MODULE_AUTHOR("Miquèl Raynal <miquel.raynal@bootlin.com>"); -+MODULE_DESCRIPTION("Common PHY driver for A3700"); -+MODULE_LICENSE("GPL v2"); |