lan743x: Added fixed link and RGMII support
Microchip lan7431 is frequently connected to a phy. However, it can also be directly connected to a MII remote peer without any phy in between. For supporting such a phyless hardware setup in Linux we utilized phylib, which supports a fixed-link configuration via the device tree. And we added support for defining the connection type R/GMII in the device tree. New behavior: ------------- . The automatic speed and duplex detection of the lan743x silicon between mac and phy is disabled. Instead phylib is used like in other typical Linux drivers. The usage of phylib allows to specify fixed-link parameters in the device tree. . The device tree entry phy-connection-type is supported now with the modes RGMII or (G)MII (default). Development state: ------------------ . Tested with fixed-phy configurations. Not yet tested in normal configurations with phy. Microchip kindly offered testing as soon as the Corona measures allow this. . All review findings of Andrew Lunn are included Example: -------- &pcie { status = "okay"; host@0 { reg = <0 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; ethernet@0 { compatible = "weyland-yutani,noscom1", "microchip,lan743x"; status = "okay"; reg = <0 0 0 0 0>; phy-connection-type = "rgmii"; fixed-link { speed = <100>; full-duplex; }; }; }; }; Signed-off-by: Roelof Berg <rberg@berg-solutions.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ff0f638329
commit
6f197fb638
|
@ -2,11 +2,11 @@
|
||||||
/* Copyright (C) 2018 Microchip Technology Inc. */
|
/* Copyright (C) 2018 Microchip Technology Inc. */
|
||||||
|
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include "lan743x_main.h"
|
|
||||||
#include "lan743x_ethtool.h"
|
|
||||||
#include <linux/net_tstamp.h>
|
#include <linux/net_tstamp.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
|
#include "lan743x_main.h"
|
||||||
|
#include "lan743x_ethtool.h"
|
||||||
|
|
||||||
/* eeprom */
|
/* eeprom */
|
||||||
#define LAN743X_EEPROM_MAGIC (0x74A5)
|
#define LAN743X_EEPROM_MAGIC (0x74A5)
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <linux/microchipphy.h>
|
#include <linux/microchipphy.h>
|
||||||
#include <linux/net_tstamp.h>
|
#include <linux/net_tstamp.h>
|
||||||
|
#include <linux/of_mdio.h>
|
||||||
|
#include <linux/of_net.h>
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
|
#include <linux/phy_fixed.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/crc16.h>
|
#include <linux/crc16.h>
|
||||||
|
@ -798,9 +801,9 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
|
||||||
|
|
||||||
netdev = adapter->netdev;
|
netdev = adapter->netdev;
|
||||||
|
|
||||||
/* setup auto duplex, and speed detection */
|
/* disable auto duplex, and speed detection. Phylib does that */
|
||||||
data = lan743x_csr_read(adapter, MAC_CR);
|
data = lan743x_csr_read(adapter, MAC_CR);
|
||||||
data |= MAC_CR_ADD_ | MAC_CR_ASD_;
|
data &= ~(MAC_CR_ADD_ | MAC_CR_ASD_);
|
||||||
data |= MAC_CR_CNTR_RST_;
|
data |= MAC_CR_CNTR_RST_;
|
||||||
lan743x_csr_write(adapter, MAC_CR, data);
|
lan743x_csr_write(adapter, MAC_CR, data);
|
||||||
|
|
||||||
|
@ -946,6 +949,7 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct lan743x_adapter *adapter = netdev_priv(netdev);
|
struct lan743x_adapter *adapter = netdev_priv(netdev);
|
||||||
struct phy_device *phydev = netdev->phydev;
|
struct phy_device *phydev = netdev->phydev;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
phy_print_status(phydev);
|
phy_print_status(phydev);
|
||||||
if (phydev->state == PHY_RUNNING) {
|
if (phydev->state == PHY_RUNNING) {
|
||||||
|
@ -953,6 +957,39 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
|
||||||
int remote_advertisement = 0;
|
int remote_advertisement = 0;
|
||||||
int local_advertisement = 0;
|
int local_advertisement = 0;
|
||||||
|
|
||||||
|
data = lan743x_csr_read(adapter, MAC_CR);
|
||||||
|
|
||||||
|
/* set interface mode */
|
||||||
|
if (phy_interface_mode_is_rgmii(adapter->phy_mode))
|
||||||
|
/* RGMII */
|
||||||
|
data &= ~MAC_CR_MII_EN_;
|
||||||
|
else
|
||||||
|
/* GMII */
|
||||||
|
data |= MAC_CR_MII_EN_;
|
||||||
|
|
||||||
|
/* set duplex mode */
|
||||||
|
if (phydev->duplex)
|
||||||
|
data |= MAC_CR_DPX_;
|
||||||
|
else
|
||||||
|
data &= ~MAC_CR_DPX_;
|
||||||
|
|
||||||
|
/* set bus speed */
|
||||||
|
switch (phydev->speed) {
|
||||||
|
case SPEED_10:
|
||||||
|
data &= ~MAC_CR_CFG_H_;
|
||||||
|
data &= ~MAC_CR_CFG_L_;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
data &= ~MAC_CR_CFG_H_;
|
||||||
|
data |= MAC_CR_CFG_L_;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
data |= MAC_CR_CFG_H_;
|
||||||
|
data |= MAC_CR_CFG_L_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lan743x_csr_write(adapter, MAC_CR, data);
|
||||||
|
|
||||||
memset(&ksettings, 0, sizeof(ksettings));
|
memset(&ksettings, 0, sizeof(ksettings));
|
||||||
phy_ethtool_get_link_ksettings(netdev, &ksettings);
|
phy_ethtool_get_link_ksettings(netdev, &ksettings);
|
||||||
local_advertisement =
|
local_advertisement =
|
||||||
|
@ -980,20 +1017,44 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter)
|
||||||
static int lan743x_phy_open(struct lan743x_adapter *adapter)
|
static int lan743x_phy_open(struct lan743x_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct lan743x_phy *phy = &adapter->phy;
|
struct lan743x_phy *phy = &adapter->phy;
|
||||||
|
struct device_node *phynode;
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
|
||||||
netdev = adapter->netdev;
|
netdev = adapter->netdev;
|
||||||
phydev = phy_find_first(adapter->mdiobus);
|
phynode = of_node_get(adapter->pdev->dev.of_node);
|
||||||
if (!phydev)
|
adapter->phy_mode = PHY_INTERFACE_MODE_GMII;
|
||||||
goto return_error;
|
|
||||||
|
|
||||||
ret = phy_connect_direct(netdev, phydev,
|
if (phynode) {
|
||||||
lan743x_phy_link_status_change,
|
of_get_phy_mode(phynode, &adapter->phy_mode);
|
||||||
PHY_INTERFACE_MODE_GMII);
|
|
||||||
if (ret)
|
if (of_phy_is_fixed_link(phynode)) {
|
||||||
goto return_error;
|
ret = of_phy_register_fixed_link(phynode);
|
||||||
|
if (ret) {
|
||||||
|
netdev_err(netdev,
|
||||||
|
"cannot register fixed PHY\n");
|
||||||
|
of_node_put(phynode);
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phydev = of_phy_connect(netdev, phynode,
|
||||||
|
lan743x_phy_link_status_change, 0,
|
||||||
|
adapter->phy_mode);
|
||||||
|
of_node_put(phynode);
|
||||||
|
if (!phydev)
|
||||||
|
goto return_error;
|
||||||
|
} else {
|
||||||
|
phydev = phy_find_first(adapter->mdiobus);
|
||||||
|
if (!phydev)
|
||||||
|
goto return_error;
|
||||||
|
|
||||||
|
ret = phy_connect_direct(netdev, phydev,
|
||||||
|
lan743x_phy_link_status_change,
|
||||||
|
adapter->phy_mode);
|
||||||
|
if (ret)
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
/* MAC doesn't support 1000T Half */
|
/* MAC doesn't support 1000T Half */
|
||||||
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
|
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#ifndef _LAN743X_H
|
#ifndef _LAN743X_H
|
||||||
#define _LAN743X_H
|
#define _LAN743X_H
|
||||||
|
|
||||||
|
#include <linux/phy.h>
|
||||||
#include "lan743x_ptp.h"
|
#include "lan743x_ptp.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
|
#define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
|
||||||
|
@ -104,10 +105,14 @@
|
||||||
((value << 0) & FCT_FLOW_CTL_ON_THRESHOLD_)
|
((value << 0) & FCT_FLOW_CTL_ON_THRESHOLD_)
|
||||||
|
|
||||||
#define MAC_CR (0x100)
|
#define MAC_CR (0x100)
|
||||||
|
#define MAC_CR_MII_EN_ BIT(19)
|
||||||
#define MAC_CR_EEE_EN_ BIT(17)
|
#define MAC_CR_EEE_EN_ BIT(17)
|
||||||
#define MAC_CR_ADD_ BIT(12)
|
#define MAC_CR_ADD_ BIT(12)
|
||||||
#define MAC_CR_ASD_ BIT(11)
|
#define MAC_CR_ASD_ BIT(11)
|
||||||
#define MAC_CR_CNTR_RST_ BIT(5)
|
#define MAC_CR_CNTR_RST_ BIT(5)
|
||||||
|
#define MAC_CR_DPX_ BIT(3)
|
||||||
|
#define MAC_CR_CFG_H_ BIT(2)
|
||||||
|
#define MAC_CR_CFG_L_ BIT(1)
|
||||||
#define MAC_CR_RST_ BIT(0)
|
#define MAC_CR_RST_ BIT(0)
|
||||||
|
|
||||||
#define MAC_RX (0x104)
|
#define MAC_RX (0x104)
|
||||||
|
@ -698,6 +703,7 @@ struct lan743x_rx {
|
||||||
struct lan743x_adapter {
|
struct lan743x_adapter {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct mii_bus *mdiobus;
|
struct mii_bus *mdiobus;
|
||||||
|
phy_interface_t phy_mode;
|
||||||
int msg_enable;
|
int msg_enable;
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
u32 wolopts;
|
u32 wolopts;
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
/* Copyright (C) 2018 Microchip Technology Inc. */
|
/* Copyright (C) 2018 Microchip Technology Inc. */
|
||||||
|
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include "lan743x_main.h"
|
|
||||||
|
|
||||||
#include <linux/ptp_clock_kernel.h>
|
#include <linux/ptp_clock_kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/net_tstamp.h>
|
#include <linux/net_tstamp.h>
|
||||||
|
#include "lan743x_main.h"
|
||||||
|
|
||||||
#include "lan743x_ptp.h"
|
#include "lan743x_ptp.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue