aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-5.4/542-phy-add-A3700-COMPHY-support.patch
diff options
context:
space:
mode:
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.patch381
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");