diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-11-28 13:58:23 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-11-28 13:58:23 +1100 |
commit | 8b19d905faf6d7f2f9b7e19329aa49b7661551b4 (patch) | |
tree | b2b58b850c78562a129692548d355c98c593e1b0 | |
parent | 8388e9a33764254e5d2ec135134b62a9882e5076 (diff) | |
parent | 9b28b23a7a12cb07536da93100a907f772f00fea (diff) |
Merge remote-tracking branch 'phy-next/next'
23 files changed, 545 insertions, 101 deletions
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt index 07ca4ec4a745..f2e120af17f0 100644 --- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt @@ -14,13 +14,14 @@ Required properties: * allwinner,sun8i-r40-usb-phy * allwinner,sun8i-v3s-usb-phy * allwinner,sun50i-a64-usb-phy + * allwinner,sun50i-h6-usb-phy - reg : a list of offset + length pairs - reg-names : * "phy_ctrl" - * "pmu0" for H3, V3s and A64 + * "pmu0" for H3, V3s, A64 or H6 * "pmu1" * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 - * "pmu3" for sun8i-h3 + * "pmu3" for sun8i-h3 or sun50i-h6 - #phy-cells : from the generic phy bindings, must be 1 - clocks : phandle + clock specifier for the phy clocks - clock-names : @@ -29,12 +30,13 @@ Required properties: * "usb0_phy", "usb1_phy" for sun8i * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 + * "usb0_phy" and "usb3_phy" for sun50i-h6 - resets : a list of phandle + reset specifier pairs - reset-names : * "usb0_reset" * "usb1_reset" * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 - * "usb3_reset" for sun8i-h3 + * "usb3_reset" for sun8i-h3 and sun50i-h6 Optional properties: - usb0_id_det-gpios : gpio phandle for reading the otg id pin value diff --git a/MAINTAINERS b/MAINTAINERS index 9ec2a9bade05..e74267f5b923 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6276,6 +6276,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git S: Supported F: drivers/phy/ F: include/linux/phy/ +F: Documentation/devicetree/bindings/phy/ GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER M: Wolfram Sang <wsa+renesas@sang-engineering.com> diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 7a37a37e3fb3..731793a87e43 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1165,28 +1165,13 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) */ static int mvpp22_comphy_init(struct mvpp2_port *port) { - enum phy_mode mode; int ret; if (!port->comphy) return 0; - switch (port->phy_interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - mode = PHY_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_2500BASEX: - mode = PHY_MODE_2500SGMII; - break; - case PHY_INTERFACE_MODE_10GKR: - mode = PHY_MODE_10GKR; - break; - default: - return -EINVAL; - } - - ret = phy_set_mode(port->comphy, mode); + ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, + port->phy_interface); if (ret) return ret; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 7f8da8873a96..c2e564b21dc6 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -472,7 +472,6 @@ static int ocelot_port_open(struct net_device *dev) { struct ocelot_port *port = netdev_priv(dev); struct ocelot *ocelot = port->ocelot; - enum phy_mode phy_mode; int err; /* Enable receiving frames on the port, and activate auto-learning of @@ -484,12 +483,8 @@ static int ocelot_port_open(struct net_device *dev) ANA_PORT_PORT_CFG, port->chip_port); if (port->serdes) { - if (port->phy_mode == PHY_INTERFACE_MODE_SGMII) - phy_mode = PHY_MODE_SGMII; - else - phy_mode = PHY_MODE_QSGMII; - - err = phy_set_mode(port->serdes, phy_mode); + err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, + port->phy_mode); if (err) { netdev_err(dev, "Could not set mode of SerDes\n"); return err; diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index d4dcd39b8d76..5163097b43df 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -115,6 +115,7 @@ enum sun4i_usb_phy_type { sun8i_r40_phy, sun8i_v3s_phy, sun50i_a64_phy, + sun50i_h6_phy, }; struct sun4i_usb_phy_cfg { @@ -126,6 +127,7 @@ struct sun4i_usb_phy_cfg { bool dedicated_clocks; bool enable_pmu_unk1; bool phy0_dual_route; + int missing_phys; }; struct sun4i_usb_phy_data { @@ -294,7 +296,8 @@ static int sun4i_usb_phy_init(struct phy *_phy) return ret; } - if (data->cfg->type == sun8i_a83t_phy) { + if (data->cfg->type == sun8i_a83t_phy || + data->cfg->type == sun50i_h6_phy) { if (phy->index == 0) { val = readl(data->base + data->cfg->phyctl_offset); val |= PHY_CTL_VBUSVLDEXT; @@ -343,7 +346,8 @@ static int sun4i_usb_phy_exit(struct phy *_phy) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); if (phy->index == 0) { - if (data->cfg->type == sun8i_a83t_phy) { + if (data->cfg->type == sun8i_a83t_phy || + data->cfg->type == sun50i_h6_phy) { void __iomem *phyctl = data->base + data->cfg->phyctl_offset; @@ -474,7 +478,8 @@ static int sun4i_usb_phy_power_off(struct phy *_phy) return 0; } -static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode) +static int sun4i_usb_phy_set_mode(struct phy *_phy, + enum phy_mode mode, int submode) { struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); @@ -646,6 +651,9 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, if (args->args[0] >= data->cfg->num_phys) return ERR_PTR(-ENODEV); + if (data->cfg->missing_phys & BIT(args->args[0])) + return ERR_PTR(-ENODEV); + return data->phys[args->args[0]].phy; } @@ -741,6 +749,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) struct sun4i_usb_phy *phy = data->phys + i; char name[16]; + if (data->cfg->missing_phys & BIT(i)) + continue; + snprintf(name, sizeof(name), "usb%d_vbus", i); phy->vbus = devm_regulator_get_optional(dev, name); if (IS_ERR(phy->vbus)) { @@ -952,6 +963,17 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .phy0_dual_route = true, }; +static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { + .num_phys = 4, + .type = sun50i_h6_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, + .enable_pmu_unk1 = true, + .phy0_dual_route = true, + .missing_phys = BIT(1) | BIT(2), +}; + static const struct of_device_id sun4i_usb_phy_of_match[] = { { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, @@ -965,6 +987,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = &sun50i_a64_cfg}, + { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, { }, }; MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c index 9f9b5414b97a..148ef0bdb9c1 100644 --- a/drivers/phy/amlogic/phy-meson-gxl-usb2.c +++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c @@ -152,7 +152,8 @@ static int phy_meson_gxl_usb2_reset(struct phy *phy) return 0; } -static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode) +static int phy_meson_gxl_usb2_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); @@ -209,7 +210,7 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy) /* power on the PHY by taking it out of reset mode */ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); - ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode); + ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode, 0); if (ret) { phy_meson_gxl_usb2_power_off(phy); diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb3.c b/drivers/phy/amlogic/phy-meson-gxl-usb3.c index d37d94ddf9c0..c0e9e4c16149 100644 --- a/drivers/phy/amlogic/phy-meson-gxl-usb3.c +++ b/drivers/phy/amlogic/phy-meson-gxl-usb3.c @@ -119,7 +119,8 @@ static int phy_meson_gxl_usb3_power_off(struct phy *phy) return 0; } -static int phy_meson_gxl_usb3_set_mode(struct phy *phy, enum phy_mode mode) +static int phy_meson_gxl_usb3_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); @@ -164,7 +165,7 @@ static int phy_meson_gxl_usb3_init(struct phy *phy) if (ret) goto err_disable_clk_phy; - ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode); + ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode, 0); if (ret) goto err_disable_clk_peripheral; diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig index 57fff7de4031..2b8c0851ff33 100644 --- a/drivers/phy/cadence/Kconfig +++ b/drivers/phy/cadence/Kconfig @@ -1,5 +1,5 @@ # -# Phy driver for Cadence MHDP DisplayPort controller +# Phy drivers for Cadence PHYs # config PHY_CADENCE_DP tristate "Cadence MHDP DisplayPort PHY driver" @@ -8,3 +8,10 @@ config PHY_CADENCE_DP select GENERIC_PHY help Support for Cadence MHDP DisplayPort PHY. + +config PHY_CADENCE_SIERRA + tristate "Cadence Sierra PHY Driver" + depends on OF && HAS_IOMEM && RESET_CONTROLLER + select GENERIC_PHY + help + Enable this to support the Cadence Sierra PHY driver
\ No newline at end of file diff --git a/drivers/phy/cadence/Makefile b/drivers/phy/cadence/Makefile index e5b0a11cf28a..412349af0492 100644 --- a/drivers/phy/cadence/Makefile +++ b/drivers/phy/cadence/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o +obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c new file mode 100644 index 000000000000..de10402f2931 --- /dev/null +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cadence Sierra PHY Driver + * + * Copyright (c) 2018 Cadence Design Systems + * Author: Alan Douglas <adouglas@cadence.com> + * + */ +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/reset.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <dt-bindings/phy/phy.h> + +/* PHY register offsets */ +#define SIERRA_PHY_PLL_CFG (0xc00e << 2) +#define SIERRA_DET_STANDEC_A (0x4000 << 2) +#define SIERRA_DET_STANDEC_B (0x4001 << 2) +#define SIERRA_DET_STANDEC_C (0x4002 << 2) +#define SIERRA_DET_STANDEC_D (0x4003 << 2) +#define SIERRA_DET_STANDEC_E (0x4004 << 2) +#define SIERRA_PSM_LANECAL (0x4008 << 2) +#define SIERRA_PSM_DIAG (0x4015 << 2) +#define SIERRA_PSC_TX_A0 (0x4028 << 2) +#define SIERRA_PSC_TX_A1 (0x4029 << 2) +#define SIERRA_PSC_TX_A2 (0x402A << 2) +#define SIERRA_PSC_TX_A3 (0x402B << 2) +#define SIERRA_PSC_RX_A0 (0x4030 << 2) +#define SIERRA_PSC_RX_A1 (0x4031 << 2) +#define SIERRA_PSC_RX_A2 (0x4032 << 2) +#define SIERRA_PSC_RX_A3 (0x4033 << 2) +#define SIERRA_PLLCTRL_SUBRATE (0x403A << 2) +#define SIERRA_PLLCTRL_GEN_D (0x403E << 2) +#define SIERRA_DRVCTRL_ATTEN (0x406A << 2) +#define SIERRA_CLKPATHCTRL_TMR (0x4081 << 2) +#define SIERRA_RX_CREQ_FLTR_A_MODE1 (0x4087 << 2) +#define SIERRA_RX_CREQ_FLTR_A_MODE0 (0x4088 << 2) +#define SIERRA_CREQ_CCLKDET_MODE01 (0x408E << 2) +#define SIERRA_RX_CTLE_MAINTENANCE (0x4091 << 2) +#define SIERRA_CREQ_FSMCLK_SEL (0x4092 << 2) +#define SIERRA_CTLELUT_CTRL (0x4098 << 2) +#define SIERRA_DFE_ECMP_RATESEL (0x40C0 << 2) +#define SIERRA_DFE_SMP_RATESEL (0x40C1 << 2) +#define SIERRA_DEQ_VGATUNE_CTRL (0x40E1 << 2) +#define SIERRA_TMRVAL_MODE3 (0x416E << 2) +#define SIERRA_TMRVAL_MODE2 (0x416F << 2) +#define SIERRA_TMRVAL_MODE1 (0x4170 << 2) +#define SIERRA_TMRVAL_MODE0 (0x4171 << 2) +#define SIERRA_PICNT_MODE1 (0x4174 << 2) +#define SIERRA_CPI_OUTBUF_RATESEL (0x417C << 2) +#define SIERRA_LFPSFILT_NS (0x418A << 2) +#define SIERRA_LFPSFILT_RD (0x418B << 2) +#define SIERRA_LFPSFILT_MP (0x418C << 2) +#define SIERRA_SDFILT_H2L_A (0x4191 << 2) + +#define SIERRA_MACRO_ID 0x00007364 +#define SIERRA_MAX_LANES 4 + +struct cdns_sierra_inst { + struct phy *phy; + u32 phy_type; + u32 num_lanes; + u32 mlane; + struct reset_control *lnk_rst; +}; + +struct cdns_reg_pairs { + u16 val; + u32 off; +}; + +struct cdns_sierra_data { + u32 id_value; + u32 pcie_regs; + u32 usb_regs; + struct cdns_reg_pairs *pcie_vals; + struct cdns_reg_pairs *usb_vals; +}; + +struct cdns_sierra_phy { + struct device *dev; + void __iomem *base; + struct cdns_sierra_data *init_data; + struct cdns_sierra_inst phys[SIERRA_MAX_LANES]; + struct reset_control *phy_rst; + struct reset_control *apb_rst; + struct clk *clk; + int nsubnodes; + bool autoconf; +}; + +static void cdns_sierra_phy_init(struct phy *gphy) +{ + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); + struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent); + int i, j; + struct cdns_reg_pairs *vals; + u32 num_regs; + + if (ins->phy_type == PHY_TYPE_PCIE) { + num_regs = phy->init_data->pcie_regs; + vals = phy->init_data->pcie_vals; + } else if (ins->phy_type == PHY_TYPE_USB3) { + num_regs = phy->init_data->usb_regs; + vals = phy->init_data->usb_vals; + } else { + return; + } + for (i = 0; i < ins->num_lanes; i++) + for (j = 0; j < num_regs ; j++) + writel(vals[j].val, phy->base + + vals[j].off + (i + ins->mlane) * 0x800); +} + +static int cdns_sierra_phy_on(struct phy *gphy) +{ + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); + + /* Take the PHY lane group out of reset */ + return reset_control_deassert(ins->lnk_rst); +} + +static int cdns_sierra_phy_off(struct phy *gphy) +{ + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); + + return reset_control_assert(ins->lnk_rst); +} + +static const struct phy_ops ops = { + .power_on = cdns_sierra_phy_on, + .power_off = cdns_sierra_phy_off, + .owner = THIS_MODULE, +}; + +static int cdns_sierra_get_optional(struct cdns_sierra_inst *inst, + struct device_node *child) +{ + if (of_property_read_u32(child, "reg", &inst->mlane)) + return -EINVAL; + + if (of_property_read_u32(child, "cdns,num-lanes", &inst->num_lanes)) + return -EINVAL; + + if (of_property_read_u32(child, "cdns,phy-type", &inst->phy_type)) + return -EINVAL; + + return 0; +} + +static const struct of_device_id cdns_sierra_id_table[]; + +static int cdns_sierra_phy_probe(struct platform_device *pdev) +{ + struct cdns_sierra_phy *sp; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + struct resource *res; + int i, ret, node = 0; + struct device_node *dn = dev->of_node, *child; + + if (of_get_child_count(dn) == 0) + return -ENODEV; + + sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); + if (!sp) + return -ENOMEM; + dev_set_drvdata(dev, sp); + sp->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + sp->base = devm_ioremap_resource(dev, res); + if (IS_ERR(sp->base)) { + dev_err(dev, "missing \"reg\"\n"); + return PTR_ERR(sp->base); + } + + /* Get init data for this PHY */ + match = of_match_device(cdns_sierra_id_table, dev); + if (!match) + return -EINVAL; + sp->init_data = (struct cdns_sierra_data *)match->data; + + platform_set_drvdata(pdev, sp); + + sp->clk = devm_clk_get(dev, "phy_clk"); + if (IS_ERR(sp->clk)) { + dev_err(dev, "failed to get clock phy_clk\n"); + return PTR_ERR(sp->clk); + } + + sp->phy_rst = devm_reset_control_get(dev, "sierra_reset"); + if (IS_ERR(sp->phy_rst)) { + dev_err(dev, "failed to get reset\n"); + return PTR_ERR(sp->phy_rst); + } + + sp->apb_rst = devm_reset_control_get(dev, "sierra_apb"); + if (IS_ERR(sp->apb_rst)) { + dev_err(dev, "failed to get apb reset\n"); + return PTR_ERR(sp->apb_rst); + } + + ret = clk_prepare_enable(sp->clk); + if (ret) + return ret; + + /* Enable APB */ + reset_control_deassert(sp->apb_rst); + + /* Check that PHY is present */ + if (sp->init_data->id_value != readl(sp->base)) { + ret = -EINVAL; + goto clk_disable; + } + + sp->autoconf = of_property_read_bool(dn, "cdns,autoconf"); + + for_each_available_child_of_node(dn, child) { + struct phy *gphy; + + sp->phys[node].lnk_rst = + of_reset_control_get_exclusive_by_index(child, 0); + + if (IS_ERR(sp->phys[node].lnk_rst)) { + dev_err(dev, "failed to get reset %s\n", + child->full_name); + ret = PTR_ERR(sp->phys[node].lnk_rst); + goto put_child2; + } + + if (!sp->autoconf) { + ret = cdns_sierra_get_optional(&sp->phys[node], child); + if (ret) { + dev_err(dev, "missing property in node %s\n", + child->name); + goto put_child; + } + } + + gphy = devm_phy_create(dev, child, &ops); + + if (IS_ERR(gphy)) { + ret = PTR_ERR(gphy); + goto put_child; + } + sp->phys[node].phy = gphy; + phy_set_drvdata(gphy, &sp->phys[node]); + + /* Initialise the PHY registers, unless auto configured */ + if (!sp->autoconf) + cdns_sierra_phy_init(gphy); + + node++; + } + sp->nsubnodes = node; + + /* If more than one subnode, configure the PHY as multilink */ + if (!sp->autoconf && sp->nsubnodes > 1) + writel(2, sp->base + SIERRA_PHY_PLL_CFG); + + pm_runtime_enable(dev); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + reset_control_deassert(sp->phy_rst); + return PTR_ERR_OR_ZERO(phy_provider); + +put_child: + node++; +put_child2: + for (i = 0; i < node; i++) + reset_control_put(sp->phys[i].lnk_rst); + of_node_put(child); +clk_disable: + clk_disable_unprepare(sp->clk); + reset_control_assert(sp->apb_rst); + return ret; +} + +static int cdns_sierra_phy_remove(struct platform_device *pdev) +{ + struct cdns_sierra_phy *phy = dev_get_drvdata(pdev->dev.parent); + int i; + + reset_control_assert(phy->phy_rst); + reset_control_assert(phy->apb_rst); + pm_runtime_disable(&pdev->dev); + + /* + * The device level resets will be put automatically. + * Need to put the subnode resets here though. + */ + for (i = 0; i < phy->nsubnodes; i++) { + reset_control_assert(phy->phys[i].lnk_rst); + reset_control_put(phy->phys[i].lnk_rst); + } + return 0; +} + +static struct cdns_reg_pairs cdns_usb_regs[] = { + /* + * Write USB configuration parameters to the PHY. + * These values are specific to this specific hardware + * configuration. + */ + {0xFE0A, SIERRA_DET_STANDEC_A}, + {0x000F, SIERRA_DET_STANDEC_B}, + {0x55A5, SIERRA_DET_STANDEC_C}, + {0x69AD, SIERRA_DET_STANDEC_D}, + {0x0241, SIERRA_DET_STANDEC_E}, + {0x0110, SIERRA_PSM_LANECAL}, + {0xCF00, SIERRA_PSM_DIAG}, + {0x001F, SIERRA_PSC_TX_A0}, + {0x0007, SIERRA_PSC_TX_A1}, + {0x0003, SIERRA_PSC_TX_A2}, + {0x0003, SIERRA_PSC_TX_A3}, + {0x0FFF, SIERRA_PSC_RX_A0}, + {0x0003, SIERRA_PSC_RX_A1}, + {0x0003, SIERRA_PSC_RX_A2}, + {0x0001, SIERRA_PSC_RX_A3}, + {0x0001, SIERRA_PLLCTRL_SUBRATE}, + {0x0406, SIERRA_PLLCTRL_GEN_D}, + {0x0000, SIERRA_DRVCTRL_ATTEN}, + {0x823E, SIERRA_CLKPATHCTRL_TMR}, + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1}, + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0}, + {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01}, + {0x023C, SIERRA_RX_CTLE_MAINTENANCE}, + {0x3232, SIERRA_CREQ_FSMCLK_SEL}, + {0x8452, SIERRA_CTLELUT_CTRL}, + {0x4121, SIERRA_DFE_ECMP_RATESEL}, + {0x4121, SIERRA_DFE_SMP_RATESEL}, + {0x9999, SIERRA_DEQ_VGATUNE_CTRL}, + {0x0330, SIERRA_TMRVAL_MODE0}, + {0x01FF, SIERRA_PICNT_MODE1}, + {0x0009, SIERRA_CPI_OUTBUF_RATESEL}, + {0x000F, SIERRA_LFPSFILT_NS}, + {0x0009, SIERRA_LFPSFILT_RD}, + {0x0001, SIERRA_LFPSFILT_MP}, + {0x8013, SIERRA_SDFILT_H2L_A}, + {0x0400, SIERRA_TMRVAL_MODE1}, +}; + +static struct cdns_reg_pairs cdns_pcie_regs[] = { + /* + * Write PCIe configuration parameters to the PHY. + * These values are specific to this specific hardware + * configuration. + */ + {0x891f, SIERRA_DET_STANDEC_D}, + {0x0053, SIERRA_DET_STANDEC_E}, + {0x0400, SIERRA_TMRVAL_MODE2}, + {0x0200, SIERRA_TMRVAL_MODE3}, +}; + +static const struct cdns_sierra_data cdns_map_sierra = { + SIERRA_MACRO_ID, + ARRAY_SIZE(cdns_pcie_regs), + ARRAY_SIZE(cdns_usb_regs), + cdns_pcie_regs, + cdns_usb_regs +}; + +static const struct of_device_id cdns_sierra_id_table[] = { + { + .compatible = "cdns,sierra-phy-t0", + .data = &cdns_map_sierra, + }, + {} +}; +MODULE_DEVICE_TABLE(of, cdns_sierra_id_table); + +static struct platform_driver cdns_sierra_driver = { + .probe = cdns_sierra_phy_probe, + .remove = cdns_sierra_phy_remove, + .driver = { + .name = "cdns-sierra-phy", + .of_match_table = cdns_sierra_id_table, + }, +}; +module_platform_driver(cdns_sierra_driver); + +MODULE_ALIAS("platform:cdns_sierra"); +MODULE_AUTHOR("Cadence Design Systems"); +MODULE_DESCRIPTION("CDNS sierra phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c index 86a5f7b9448b..2b4462a28a58 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c @@ -9,6 +9,7 @@ #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> #include <linux/regmap.h> @@ -116,41 +117,43 @@ struct mvebu_comhy_conf { enum phy_mode mode; + int submode; unsigned lane; unsigned port; u32 mux; }; -#define MVEBU_COMPHY_CONF(_lane, _port, _mode, _mux) \ +#define MVEBU_COMPHY_CONF(_lane, _port, _submode, _mux) \ { \ .lane = _lane, \ .port = _port, \ - .mode = _mode, \ + .mode = PHY_MODE_ETHERNET, \ + .submode = _submode, \ .mux = _mux, \ } static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = { /* lane 0 */ - MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1), - MVEBU_COMPHY_CONF(0, 1, PHY_MODE_2500SGMII, 0x1), + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1), + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1), /* lane 1 */ - MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1), - MVEBU_COMPHY_CONF(1, 2, PHY_MODE_2500SGMII, 0x1), + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1), + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), /* lane 2 */ - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1), - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_2500SGMII, 0x1), - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1), + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1), + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1), + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1), /* lane 3 */ - MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2), - MVEBU_COMPHY_CONF(3, 1, PHY_MODE_2500SGMII, 0x2), + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2), + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2), /* lane 4 */ - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2), - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_2500SGMII, 0x2), - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2), - MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1), + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2), + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2), + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2), + MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1), /* lane 5 */ - MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1), - MVEBU_COMPHY_CONF(5, 2, PHY_MODE_2500SGMII, 0x1), + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1), + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), }; struct mvebu_comphy_priv { @@ -163,10 +166,12 @@ struct mvebu_comphy_lane { struct mvebu_comphy_priv *priv; unsigned id; enum phy_mode mode; + int submode; int port; }; -static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) +static int mvebu_comphy_get_mux(int lane, int port, + enum phy_mode mode, int submode) { int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); @@ -177,7 +182,8 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) for (i = 0; i < n; i++) { if (mvebu_comphy_cp110_modes[i].lane == lane && mvebu_comphy_cp110_modes[i].port == port && - mvebu_comphy_cp110_modes[i].mode == mode) + mvebu_comphy_cp110_modes[i].mode == mode && + mvebu_comphy_cp110_modes[i].submode == submode) break; } @@ -187,8 +193,7 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) return mvebu_comphy_cp110_modes[i].mux; } -static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, - enum phy_mode mode) +static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane) { struct mvebu_comphy_priv *priv = lane->priv; u32 val; @@ -206,14 +211,14 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, MVEBU_COMPHY_SERDES_CFG0_HALF_BUS | MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf)); - if (mode == PHY_MODE_10GKR) + if (lane->submode == PHY_INTERFACE_MODE_10GKR) val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe); - else if (mode == PHY_MODE_2500SGMII) + else if (lane->submode == PHY_INTERFACE_MODE_2500BASEX) val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; - else if (mode == PHY_MODE_SGMII) + else if (lane->submode == PHY_INTERFACE_MODE_SGMII) val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; @@ -243,7 +248,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, /* refclk selection */ val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL; - if (mode == PHY_MODE_10GKR) + if (lane->submode == PHY_INTERFACE_MODE_10GKR) val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE; writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); @@ -261,8 +266,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id)); } -static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane, - enum phy_mode mode) +static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane) { struct mvebu_comphy_priv *priv = lane->priv; u32 val; @@ -303,13 +307,13 @@ static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane, return 0; } -static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode) +static int mvebu_comphy_set_mode_sgmii(struct phy *phy) { struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); struct mvebu_comphy_priv *priv = lane->priv; u32 val; - mvebu_comphy_ethernet_init_reset(lane, mode); + mvebu_comphy_ethernet_init_reset(lane); val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN; @@ -330,7 +334,7 @@ static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode) val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1); writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id)); - return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII); + return mvebu_comphy_init_plls(lane); } static int mvebu_comphy_set_mode_10gkr(struct phy *phy) @@ -339,7 +343,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy) struct mvebu_comphy_priv *priv = lane->priv; u32 val; - mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR); + mvebu_comphy_ethernet_init_reset(lane); val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL | @@ -469,7 +473,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy) val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a); writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id)); - return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR); + return mvebu_comphy_init_plls(lane); } static int mvebu_comphy_power_on(struct phy *phy) @@ -479,7 +483,8 @@ static int mvebu_comphy_power_on(struct phy *phy) int ret, mux; u32 val; - mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode); + mux = mvebu_comphy_get_mux(lane->id, lane->port, + lane->mode, lane->submode); if (mux < 0) return -ENOTSUPP; @@ -492,12 +497,12 @@ static int mvebu_comphy_power_on(struct phy *phy) val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); - switch (lane->mode) { - case PHY_MODE_SGMII: - case PHY_MODE_2500SGMII: - ret = mvebu_comphy_set_mode_sgmii(phy, lane->mode); + switch (lane->submode) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + ret = mvebu_comphy_set_mode_sgmii(phy); break; - case PHY_MODE_10GKR: + case PHY_INTERFACE_MODE_10GKR: ret = mvebu_comphy_set_mode_10gkr(phy); break; default: @@ -512,14 +517,22 @@ static int mvebu_comphy_power_on(struct phy *phy) return ret; } -static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode) +static int mvebu_comphy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); - if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0) + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + if (submode == PHY_INTERFACE_MODE_1000BASEX) + submode = PHY_INTERFACE_MODE_SGMII; + + if (mvebu_comphy_get_mux(lane->id, lane->port, mode, submode) < 0) return -EINVAL; lane->mode = mode; + lane->submode = submode; return 0; } diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 3eb8e1bd7b78..5b6a470ca145 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -971,7 +971,7 @@ static int mtk_phy_exit(struct phy *phy) return 0; } -static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct mtk_phy_instance *instance = phy_get_drvdata(phy); struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c index 020cd0227397..8c51131945c0 100644 --- a/drivers/phy/mediatek/phy-mtk-xsphy.c +++ b/drivers/phy/mediatek/phy-mtk-xsphy.c @@ -426,7 +426,7 @@ static int mtk_phy_exit(struct phy *phy) return 0; } -static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct xsphy_instance *inst = phy_get_drvdata(phy); struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c index cbb49d9da6f9..77c46f639fbf 100644 --- a/drivers/phy/mscc/phy-ocelot-serdes.c +++ b/drivers/phy/mscc/phy-ocelot-serdes.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/phy.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -104,20 +105,24 @@ struct serdes_mux { u8 idx; u8 port; enum phy_mode mode; + int submode; u32 mask; u32 mux; }; -#define SERDES_MUX(_idx, _port, _mode, _mask, _mux) { \ +#define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \ .idx = _idx, \ .port = _port, \ .mode = _mode, \ + .submode = _submode, \ .mask = _mask, \ .mux = _mux, \ } -#define SERDES_MUX_SGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_SGMII, m, c) -#define SERDES_MUX_QSGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_QSGMII, m, c) +#define SERDES_MUX_SGMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c) +#define SERDES_MUX_QSGMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c) static const struct serdes_mux ocelot_serdes_muxes[] = { SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0), @@ -154,22 +159,27 @@ static const struct serdes_mux ocelot_serdes_muxes[] = { SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0), SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA | HSIO_HW_CFG_DEV2G5_10_MODE, 0), - SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, HSIO_HW_CFG_PCIE_ENA, + SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, 0, HSIO_HW_CFG_PCIE_ENA, HSIO_HW_CFG_PCIE_ENA), }; -static int serdes_set_mode(struct phy *phy, enum phy_mode mode) +static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct serdes_macro *macro = phy_get_drvdata(phy); unsigned int i; int ret; + /* As of now only PHY_MODE_ETHERNET is supported */ + if (mode != PHY_MODE_ETHERNET) + return -EOPNOTSUPP; + for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) { if (macro->idx != ocelot_serdes_muxes[i].idx || - mode != ocelot_serdes_muxes[i].mode) + mode != ocelot_serdes_muxes[i].mode || + submode != ocelot_serdes_muxes[i].submode) continue; - if (mode != PHY_MODE_QSGMII && + if (submode != PHY_INTERFACE_MODE_QSGMII && macro->port != ocelot_serdes_muxes[i].port) continue; diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 35fd38c5a4a1..df3d4ba516ab 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -360,7 +360,7 @@ int phy_power_off(struct phy *phy) } EXPORT_SYMBOL_GPL(phy_power_off); -int phy_set_mode(struct phy *phy, enum phy_mode mode) +int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) { int ret; @@ -368,14 +368,14 @@ int phy_set_mode(struct phy *phy, enum phy_mode mode) return 0; mutex_lock(&phy->mutex); - ret = phy->ops->set_mode(phy, mode); + ret = phy->ops->set_mode(phy, mode, submode); if (!ret) phy->attrs.mode = mode; mutex_unlock(&phy->mutex); return ret; } -EXPORT_SYMBOL_GPL(phy_set_mode); +EXPORT_SYMBOL_GPL(phy_set_mode_ext); int phy_reset(struct phy *phy) { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index a83332411026..514db7248a5d 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -1365,7 +1365,8 @@ static int qcom_qmp_phy_poweron(struct phy *phy) return ret; } -static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int qcom_qmp_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct qmp_phy *qphy = phy_get_drvdata(phy); struct qcom_qmp *qmp = qphy->qmp; diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 6d4b44b569bc..9177989f22d1 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -425,7 +425,8 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) HSTX_TRIM_MASK); } -static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int qusb2_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct qusb2_phy *qphy = phy_get_drvdata(phy); diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c index ba1895b76a5d..1e0d4f2046a4 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c @@ -65,7 +65,8 @@ static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy) } static -int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, enum phy_mode mode) +int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, + enum phy_mode mode, int submode) { struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c index 49f435c71147..aef40f7a41d4 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c @@ -84,7 +84,8 @@ static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy) } static -int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, enum phy_mode mode) +int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, + enum phy_mode mode, int submode) { struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index abbbe75070da..04934f8dac91 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -42,7 +42,8 @@ struct qcom_usb_hs_phy { struct notifier_block vbus_notify; }; -static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int qcom_usb_hs_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); u8 addr; diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c index befb886ff121..d5f4fbc32b52 100644 --- a/drivers/phy/ti/phy-da8xx-usb.c +++ b/drivers/phy/ti/phy-da8xx-usb.c @@ -93,7 +93,8 @@ static int da8xx_usb20_phy_power_off(struct phy *phy) return 0; } -static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode) +static int da8xx_usb20_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) { struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); u32 val; diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c index b8ec39ac4dfc..329fb938099a 100644 --- a/drivers/phy/ti/phy-tusb1210.c +++ b/drivers/phy/ti/phy-tusb1210.c @@ -53,7 +53,7 @@ static int tusb1210_power_off(struct phy *phy) return 0; } -static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode) +static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) { struct tusb1210 *tusb = phy_get_drvdata(phy); int ret; diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 03b319f89a34..79da05a3e28d 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -35,13 +35,10 @@ enum phy_mode { PHY_MODE_USB_DEVICE_HS, PHY_MODE_USB_DEVICE_SS, PHY_MODE_USB_OTG, - PHY_MODE_SGMII, - PHY_MODE_2500SGMII, - PHY_MODE_QSGMII, - PHY_MODE_10GKR, PHY_MODE_UFS_HS_A, PHY_MODE_UFS_HS_B, PHY_MODE_PCIE, + PHY_MODE_ETHERNET, }; /** @@ -60,7 +57,7 @@ struct phy_ops { int (*exit)(struct phy *phy); int (*power_on)(struct phy *phy); int (*power_off)(struct phy *phy); - int (*set_mode)(struct phy *phy, enum phy_mode mode); + int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode); int (*reset)(struct phy *phy); int (*calibrate)(struct phy *phy); struct module *owner; @@ -164,7 +161,10 @@ int phy_init(struct phy *phy); int phy_exit(struct phy *phy); int phy_power_on(struct phy *phy); int phy_power_off(struct phy *phy); -int phy_set_mode(struct phy *phy, enum phy_mode mode); +int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode); +#define phy_set_mode(phy, mode) \ + phy_set_mode_ext(phy, mode, 0) + static inline enum phy_mode phy_get_mode(struct phy *phy) { return phy->attrs.mode; @@ -278,13 +278,17 @@ static inline int phy_power_off(struct phy *phy) return -ENOSYS; } -static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) +static inline int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, + int submode) { if (!phy) return 0; return -ENOSYS; } +#define phy_set_mode(phy, mode) \ + phy_set_mode_ext(phy, mode, 0) + static inline enum phy_mode phy_get_mode(struct phy *phy) { return PHY_MODE_INVALID; |