net: usb: asix: ax88772: move embedded PHY detection as early as possible
Some HW revisions need additional MAC configuration before the embedded PHY
can be enabled. If this is not done, we won't be able to get response
from the internal PHY.
This issue was detected on chipcode == AX_AX88772_CHIPCODE variant,
where ax88772_hw_reset() was executed with missing embd_phy flag.
Fixes: e532a096be
("net: usb: asix: ax88772: add phylib support")
Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
359f4cdd7d
commit
7a141e64cf
|
@ -184,6 +184,7 @@ struct asix_common_private {
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
u16 phy_addr;
|
u16 phy_addr;
|
||||||
char phy_name[20];
|
char phy_name[20];
|
||||||
|
bool embd_phy;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct driver_info ax88172a_info;
|
extern const struct driver_info ax88172a_info;
|
||||||
|
|
|
@ -354,24 +354,23 @@ out:
|
||||||
static int ax88772_hw_reset(struct usbnet *dev, int in_pm)
|
static int ax88772_hw_reset(struct usbnet *dev, int in_pm)
|
||||||
{
|
{
|
||||||
struct asix_data *data = (struct asix_data *)&dev->data;
|
struct asix_data *data = (struct asix_data *)&dev->data;
|
||||||
int ret, embd_phy;
|
struct asix_common_private *priv = dev->driver_priv;
|
||||||
u16 rx_ctl;
|
u16 rx_ctl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 |
|
ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 |
|
||||||
AX_GPIO_GPO2EN, 5, in_pm);
|
AX_GPIO_GPO2EN, 5, in_pm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
|
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy,
|
||||||
|
|
||||||
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy,
|
|
||||||
0, 0, NULL, in_pm);
|
0, 0, NULL, in_pm);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embd_phy) {
|
if (priv->embd_phy) {
|
||||||
ret = asix_sw_reset(dev, AX_SWRESET_IPPD, in_pm);
|
ret = asix_sw_reset(dev, AX_SWRESET_IPPD, in_pm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -449,17 +448,16 @@ out:
|
||||||
static int ax88772a_hw_reset(struct usbnet *dev, int in_pm)
|
static int ax88772a_hw_reset(struct usbnet *dev, int in_pm)
|
||||||
{
|
{
|
||||||
struct asix_data *data = (struct asix_data *)&dev->data;
|
struct asix_data *data = (struct asix_data *)&dev->data;
|
||||||
int ret, embd_phy;
|
struct asix_common_private *priv = dev->driver_priv;
|
||||||
u16 rx_ctl, phy14h, phy15h, phy16h;
|
u16 rx_ctl, phy14h, phy15h, phy16h;
|
||||||
u8 chipcode = 0;
|
u8 chipcode = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
ret = asix_write_gpio(dev, AX_GPIO_RSE, 5, in_pm);
|
ret = asix_write_gpio(dev, AX_GPIO_RSE, 5, in_pm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
|
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy |
|
||||||
|
|
||||||
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy |
|
|
||||||
AX_PHYSEL_SSEN, 0, 0, NULL, in_pm);
|
AX_PHYSEL_SSEN, 0, 0, NULL, in_pm);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
|
||||||
|
@ -683,12 +681,6 @@ static int ax88772_init_phy(struct usbnet *dev)
|
||||||
struct asix_common_private *priv = dev->driver_priv;
|
struct asix_common_private *priv = dev->driver_priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = asix_read_phy_addr(dev, true);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->phy_addr = ret;
|
|
||||||
|
|
||||||
snprintf(priv->phy_name, sizeof(priv->phy_name), PHY_ID_FMT,
|
snprintf(priv->phy_name, sizeof(priv->phy_name), PHY_ID_FMT,
|
||||||
priv->mdio->id, priv->phy_addr);
|
priv->mdio->id, priv->phy_addr);
|
||||||
|
|
||||||
|
@ -716,6 +708,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
int ret, i;
|
int ret, i;
|
||||||
u32 phyid;
|
u32 phyid;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->driver_priv = priv;
|
||||||
|
|
||||||
usbnet_get_endpoints(dev, intf);
|
usbnet_get_endpoints(dev, intf);
|
||||||
|
|
||||||
/* Maybe the boot loader passed the MAC address via device tree */
|
/* Maybe the boot loader passed the MAC address via device tree */
|
||||||
|
@ -751,6 +749,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */
|
dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */
|
||||||
dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */
|
dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */
|
||||||
|
|
||||||
|
ret = asix_read_phy_addr(dev, true);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->phy_addr = ret;
|
||||||
|
priv->embd_phy = ((priv->phy_addr & 0x1f) == 0x10 ? true : false);
|
||||||
|
|
||||||
asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
|
asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
|
||||||
chipcode &= AX_CHIPCODE_MASK;
|
chipcode &= AX_CHIPCODE_MASK;
|
||||||
|
|
||||||
|
@ -773,12 +778,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
dev->rx_urb_size = 2048;
|
dev->rx_urb_size = 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL);
|
|
||||||
if (!priv)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
dev->driver_priv = priv;
|
|
||||||
|
|
||||||
priv->presvd_phy_bmcr = 0;
|
priv->presvd_phy_bmcr = 0;
|
||||||
priv->presvd_phy_advertise = 0;
|
priv->presvd_phy_advertise = 0;
|
||||||
if (chipcode == AX_AX88772_CHIPCODE) {
|
if (chipcode == AX_AX88772_CHIPCODE) {
|
||||||
|
|
Loading…
Reference in New Issue