Commit ca2b6fae authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'phy-for-4.8-rc1' of...

Merge tag 'phy-for-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-testing

Kishon writes:

phy: for 4.8 -rc1

*) Add a new phy_ops for setting the phy mode
*) Add a new phy driver for DA8xx SoC USB PHY
*) Minor fixes and cleanups
Signed-off-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parents 25b1f9ac c14f8a40
TI DA8xx/OMAP-L1xx/AM18xx USB PHY
Required properties:
- compatible: must be "ti,da830-usb-phy".
- #phy-cells: must be 1.
This device controls the PHY for both the USB 1.1 OHCI and USB 2.0 OTG
controllers on DA8xx SoCs. Consumers of this device should use index 0 for
the USB 2.0 phy device and index 1 for the USB 1.1 phy device.
It also requires a "syscon" node with compatible = "ti,da830-cfgchip", "syscon"
to access the CFGCHIP2 register.
Example:
cfgchip: cfgchip@1417c {
compatible = "ti,da830-cfgchip", "syscon";
reg = <0x1417c 0x14>;
};
usb_phy: usb-phy {
compatible = "ti,da830-usb-phy";
#phy-cells = <1>;
};
usb20: usb@200000 {
compatible = "ti,da830-musb";
reg = <0x200000 0x1000>;
interrupts = <58>;
phys = <&usb_phy 0>;
phy-names = "usb-phy";
};
usb11: usb@225000 {
compatible = "ti,da830-ohci";
reg = <0x225000 0x1000>;
interrupts = <59>;
phys = <&usb_phy 1>;
phy-names = "usb-phy";
};
......@@ -5,11 +5,13 @@ Required properties:
"rockchip,rk3066a-usb-phy"
"rockchip,rk3188-usb-phy"
"rockchip,rk3288-usb-phy"
- rockchip,grf : phandle to the syscon managing the "general
register files"
- #address-cells: should be 1
- #size-cells: should be 0
Deprecated properties:
- rockchip,grf : phandle to the syscon managing the "general
register files" - phy should be a child of the GRF instead
Sub-nodes:
Each PHY should be represented as a sub-node.
......@@ -28,14 +30,19 @@ Optional Properties:
Example:
usbphy: phy {
compatible = "rockchip,rk3288-usb-phy";
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <0>;
grf: syscon@ff770000 {
compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
...
usbphy: phy {
compatible = "rockchip,rk3288-usb-phy";
#address-cells = <1>;
#size-cells = <0>;
usbphy0: usb-phy0 {
#phy-cells = <0>;
reg = <0x320>;
usbphy0: usb-phy0 {
#phy-cells = <0>;
reg = <0x320>;
};
};
};
......@@ -44,6 +44,16 @@ config ARMADA375_USBCLUSTER_PHY
depends on OF && HAS_IOMEM
select GENERIC_PHY
config PHY_DA8XX_USB
tristate "TI DA8xx USB PHY Driver"
depends on ARCH_DAVINCI_DA8XX
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the USB PHY on DA8xx SoCs.
This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
config PHY_DM816X_USB
tristate "TI dm816x USB PHY driver"
depends on ARCH_OMAP2PLUS
......
......@@ -6,6 +6,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
......
......@@ -342,6 +342,21 @@ 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 ret;
if (!phy || !phy->ops->set_mode)
return 0;
mutex_lock(&phy->mutex);
ret = phy->ops->set_mode(phy, mode);
mutex_unlock(&phy->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(phy_set_mode);
/**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy
......
/*
* phy-da8xx-usb - TI DaVinci DA8xx USB PHY driver
*
* Copyright (C) 2016 David Lechner <david@lechnology.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
struct da8xx_usb_phy {
struct phy_provider *phy_provider;
struct phy *usb11_phy;
struct phy *usb20_phy;
struct clk *usb11_clk;
struct clk *usb20_clk;
struct regmap *regmap;
};
static int da8xx_usb11_phy_power_on(struct phy *phy)
{
struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
int ret;
ret = clk_prepare_enable(d_phy->usb11_clk);
if (ret)
return ret;
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM,
CFGCHIP2_USB1SUSPENDM);
return 0;
}
static int da8xx_usb11_phy_power_off(struct phy *phy)
{
struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0);
clk_disable_unprepare(d_phy->usb11_clk);
return 0;
}
static const struct phy_ops da8xx_usb11_phy_ops = {
.power_on = da8xx_usb11_phy_power_on,
.power_off = da8xx_usb11_phy_power_off,
.owner = THIS_MODULE,
};
static int da8xx_usb20_phy_power_on(struct phy *phy)
{
struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
int ret;
ret = clk_prepare_enable(d_phy->usb20_clk);
if (ret)
return ret;
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN, 0);
return 0;
}
static int da8xx_usb20_phy_power_off(struct phy *phy)
{
struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN,
CFGCHIP2_OTGPWRDN);
clk_disable_unprepare(d_phy->usb20_clk);
return 0;
}
static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode)
{
struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
u32 val;
switch (mode) {
case PHY_MODE_USB_HOST: /* Force VBUS valid, ID = 0 */
val = CFGCHIP2_OTGMODE_FORCE_HOST;
break;
case PHY_MODE_USB_DEVICE: /* Force VBUS valid, ID = 1 */
val = CFGCHIP2_OTGMODE_FORCE_DEVICE;
break;
case PHY_MODE_USB_OTG: /* Don't override the VBUS/ID comparators */
val = CFGCHIP2_OTGMODE_NO_OVERRIDE;
break;
default:
return -EINVAL;
}
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGMODE_MASK,
val);
return 0;
}
static const struct phy_ops da8xx_usb20_phy_ops = {
.power_on = da8xx_usb20_phy_power_on,
.power_off = da8xx_usb20_phy_power_off,
.set_mode = da8xx_usb20_phy_set_mode,
.owner = THIS_MODULE,
};
static struct phy *da8xx_usb_phy_of_xlate(struct device *dev,
struct of_phandle_args *args)
{
struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
if (!d_phy)
return ERR_PTR(-ENODEV);
switch (args->args[0]) {
case 0:
return d_phy->usb20_phy;
case 1:
return d_phy->usb11_phy;
default:
return ERR_PTR(-EINVAL);
}
}
static int da8xx_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct da8xx_usb_phy *d_phy;
d_phy = devm_kzalloc(dev, sizeof(*d_phy), GFP_KERNEL);
if (!d_phy)
return -ENOMEM;
if (node)
d_phy->regmap = syscon_regmap_lookup_by_compatible(
"ti,da830-cfgchip");
else
d_phy->regmap = syscon_regmap_lookup_by_pdevname("syscon.0");
if (IS_ERR(d_phy->regmap)) {
dev_err(dev, "Failed to get syscon\n");
return PTR_ERR(d_phy->regmap);
}
d_phy->usb11_clk = devm_clk_get(dev, "usb11_phy");
if (IS_ERR(d_phy->usb11_clk)) {
dev_err(dev, "Failed to get usb11_phy clock\n");
return PTR_ERR(d_phy->usb11_clk);
}
d_phy->usb20_clk = devm_clk_get(dev, "usb20_phy");
if (IS_ERR(d_phy->usb20_clk)) {
dev_err(dev, "Failed to get usb20_phy clock\n");
return PTR_ERR(d_phy->usb20_clk);
}
d_phy->usb11_phy = devm_phy_create(dev, node, &da8xx_usb11_phy_ops);
if (IS_ERR(d_phy->usb11_phy)) {
dev_err(dev, "Failed to create usb11 phy\n");
return PTR_ERR(d_phy->usb11_phy);
}
d_phy->usb20_phy = devm_phy_create(dev, node, &da8xx_usb20_phy_ops);
if (IS_ERR(d_phy->usb20_phy)) {
dev_err(dev, "Failed to create usb20 phy\n");
return PTR_ERR(d_phy->usb20_phy);
}
platform_set_drvdata(pdev, d_phy);
phy_set_drvdata(d_phy->usb11_phy, d_phy);
phy_set_drvdata(d_phy->usb20_phy, d_phy);
if (node) {
d_phy->phy_provider = devm_of_phy_provider_register(dev,
da8xx_usb_phy_of_xlate);
if (IS_ERR(d_phy->phy_provider)) {
dev_err(dev, "Failed to create phy provider\n");
return PTR_ERR(d_phy->phy_provider);
}
} else {
int ret;
ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
if (ret)
dev_warn(dev, "Failed to create usb11 phy lookup\n");
ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy",
"musb-da8xx");
if (ret)
dev_warn(dev, "Failed to create usb20 phy lookup\n");
}
return 0;
}
static int da8xx_usb_phy_remove(struct platform_device *pdev)
{
struct da8xx_usb_phy *d_phy = platform_get_drvdata(pdev);
if (!pdev->dev.of_node) {
phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx");
phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
}
return 0;
}
static const struct of_device_id da8xx_usb_phy_ids[] = {
{ .compatible = "ti,da830-usb-phy" },
{ }
};
MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
static struct platform_driver da8xx_usb_phy_driver = {
.probe = da8xx_usb_phy_probe,
.remove = da8xx_usb_phy_remove,
.driver = {
.name = "da8xx-usb-phy",
.of_match_table = da8xx_usb_phy_ids,
},
};
module_platform_driver(da8xx_usb_phy_driver);
MODULE_ALIAS("platform:da8xx-usb-phy");
MODULE_AUTHOR("David Lechner <david@lechnology.com>");
MODULE_DESCRIPTION("TI DA8xx USB PHY driver");
MODULE_LICENSE("GPL v2");
......@@ -140,7 +140,6 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
dev_err(dev, "%s: failed to allocate phy\n", __func__);
err = -ENOMEM;
goto out;
}
......
......@@ -196,7 +196,6 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
dev_err(dev, "%s: failed to allocate phy\n", __func__);
err = -ENOMEM;
goto out;
}
......
......@@ -21,6 +21,7 @@
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/workqueue.h>
/******* USB2.0 Host registers (original offset is +0x200) *******/
#define USB2_INT_ENABLE 0x000
......@@ -81,9 +82,25 @@ struct rcar_gen3_chan {
struct extcon_dev *extcon;
struct phy *phy;
struct regulator *vbus;
struct work_struct work;
bool extcon_host;
bool has_otg;
};
static void rcar_gen3_phy_usb2_work(struct work_struct *work)
{
struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
work);
if (ch->extcon_host) {
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, false);
} else {
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, true);
}
}
static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
{
void __iomem *usb2_base = ch->base;
......@@ -130,8 +147,8 @@ static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
rcar_gen3_set_host_mode(ch, 1);
rcar_gen3_enable_vbus_ctrl(ch, 1);
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, false);
ch->extcon_host = true;
schedule_work(&ch->work);
}
static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
......@@ -140,8 +157,8 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
rcar_gen3_set_host_mode(ch, 0);
rcar_gen3_enable_vbus_ctrl(ch, 0);
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, true);
ch->extcon_host = false;
schedule_work(&ch->work);
}
static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
......@@ -301,6 +318,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
if (irq >= 0) {
int ret;
INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
IRQF_SHARED, dev_name(dev), channel);
if (irq < 0)
......
......@@ -236,9 +236,10 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
goto err_clk_prov;
}
err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action,
rk_phy);
if (err)
goto err_devm_action;
return err;
rk_phy->phy = devm_phy_create(base->dev, child, &ops);
if (IS_ERR(rk_phy->phy)) {
......@@ -256,9 +257,6 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
else
return rockchip_usb_phy_power(rk_phy, 1);
err_devm_action:
if (!rk_phy->uart_enabled)
of_clk_del_provider(child);
err_clk_prov:
if (!rk_phy->uart_enabled)
clk_unregister(rk_phy->clk480m);
......@@ -397,8 +395,13 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
phy_base->pdata = match->data;
phy_base->dev = dev;
phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,grf");
phy_base->reg_base = ERR_PTR(-ENODEV);
if (dev->parent && dev->parent->of_node)
phy_base->reg_base = syscon_node_to_regmap(
dev->parent->of_node);
if (IS_ERR(phy_base->reg_base))
phy_base->reg_base = syscon_regmap_lookup_by_phandle(
dev->of_node, "rockchip,grf");
if (IS_ERR(phy_base->reg_base)) {
dev_err(&pdev->dev, "Missing rockchip,grf property\n");
return PTR_ERR(phy_base->reg_base);
......@@ -463,7 +466,11 @@ static int __init rockchip_init_usb_uart(void)
return -ENOTSUPP;
}
grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
grf = ERR_PTR(-ENODEV);
if (np->parent)
grf = syscon_node_to_regmap(np->parent);
if (IS_ERR(grf))
grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(grf)) {
pr_err("%s: Missing rockchip,grf property, %lu\n",
__func__, PTR_ERR(grf));
......
......@@ -94,6 +94,7 @@
enum sun4i_usb_phy_type {
sun4i_a10_phy,
sun6i_a31_phy,
sun8i_a33_phy,
sun8i_h3_phy,
};
......@@ -122,7 +123,6 @@ struct sun4i_usb_phy_data {
/* phy0 / otg related variables */
struct extcon_dev *extcon;
bool phy0_init;
bool phy0_poll;
struct gpio_desc *id_det_gpio;
struct gpio_desc *vbus_det_gpio;
struct power_supply *vbus_power_supply;
......@@ -343,6 +343,24 @@ static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
return data->vbus_det_gpio || data->vbus_power_supply;
}
static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
{
if ((data->id_det_gpio && data->id_det_irq <= 0) ||
(data->vbus_det_gpio && data->vbus_det_irq <= 0))
return true;
/*
* The A31 companion pmic (axp221) does not generate vbus change
* interrupts when the board is driving vbus, so we must poll
* when using the pmic for vbus-det _and_ we're driving vbus.
*/
if (data->cfg->type == sun6i_a31_phy &&
data->vbus_power_supply && data->phys[0].regulator_on)
return true;
return false;
}
static int sun4i_usb_phy_power_on(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
......@@ -364,7 +382,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy)
phy->regulator_on = true;
/* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll)
if (phy->index == 0 && sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
return 0;
......@@ -385,7 +403,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy)
* phy0 vbus typically slowly discharges, sometimes this causes the
* Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
*/
if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll)
if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, POLL_TIME);
return 0;
......@@ -468,7 +486,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
if (vbus_notify)
extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
if (data->phy0_poll)
if (sun4i_usb_phy0_poll(data))
queue_delayed_work(system_wq, &data->detect, POLL_TIME);
}
......@@ -644,11 +662,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
if ((data->id_det_gpio && data->id_det_irq <= 0) ||
(data->vbus_det_gpio && data->vbus_det_irq <= 0))
data->phy0_poll = true;
if (data->id_det_irq > 0) {
ret = devm_request_irq(dev, data->id_det_irq,
sun4i_usb_phy0_id_vbus_det_irq,
......@@ -660,6 +673,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
}
data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
if (data->vbus_det_irq > 0) {
ret = devm_request_irq(dev, data->vbus_det_irq,
sun4i_usb_phy0_id_vbus_det_irq,
......@@ -711,7 +725,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
.num_phys = 3,
.type = sun4i_a10_phy,
.type = sun6i_a31_phy,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
......
......@@ -518,7 +518,7 @@ enum clk_type_t {
CLK_INT_SING = 2, /* Internal single ended */
};
enum phy_mode {
enum xgene_phy_mode {
MODE_SATA = 0, /* List them for simple reference */
MODE_SGMII = 1,
MODE_PCIE = 2,
......@@ -542,7 +542,7 @@ struct xgene_sata_override_param {
struct xgene_phy_ctx {
struct device *dev;
struct phy *phy;
enum phy_mode mode; /* Mode of operation */
enum xgene_phy_mode mode; /* Mode of operation */
enum clk_type_t clk_type; /* Input clock selection */
void __iomem *sds_base; /* PHY CSR base addr */
struct clk *clk; /* Optional clock */
......
......@@ -22,12 +22,20 @@
struct phy;
enum phy_mode {
PHY_MODE_INVALID,
PHY_MODE_USB_HOST,
PHY_MODE_USB_DEVICE,
PHY_MODE_USB_OTG,
};
/**
* struct phy_ops - set of function pointers for performing phy operations
* @init: operation to be performed for initializing phy
* @exit: operation to be performed while exiting
* @power_on: powering on the phy
* @power_off: powering off the phy
* @set_mode: set the mode of the phy
* @owner: the module owner containing the ops
*/
struct phy_ops {
......@@ -35,6 +43,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);
struct module *owner;
};
......@@ -126,6 +135,7 @@ 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);
static inline int phy_get_bus_width(struct phy *phy)
{
return phy->attrs.bus_width;
......@@ -233,6 +243,13 @@ static inline int phy_power_off(struct phy *phy)
return -ENOSYS;
}
static inline int phy_set_mode(struct phy *phy, enum phy_mode mode)
{
if (!phy)
return 0;
return -ENOSYS;
}
static inline int phy_get_bus_width(struct phy *phy)
{
return -ENOSYS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment