Commit 77a31246 authored by David S. Miller's avatar David S. Miller

Merge branch 'lan966x-driver'

Horatiu Vultur says:

====================
net: lan966x: Add lan966x switch driver

This patch series add support for Microchip lan966x driver

The lan966x switch is a multi-port Gigabit AVB/TSN Ethernet Switch with
two integrated 10/100/1000Base-T PHYs. In addition to the integrated PHYs,
it supports up to 2RGMII/RMII, up to 3BASE-X/SERDES/2.5GBASE-X and up to
2 Quad-SGMII/Quad-USGMII interfaces.

Initially it adds support only for the ports to behave as simple
NIC cards. In the future patches it would be extended with other
functionality like Switchdev, PTP, Frame DMA, VCAP, etc.

v4->v5:
- more fixes to the reset of the switch, require all resources before
  activating the hardware
- fix to lan966x-switch binding
- implement get/set_pauseparam in ethtool_ops
- stop calling lan966x_port_link_down when calling lan966x_port_pcs_set and
  call it in lan966x_phylink_mac_link_down

v3->v4:
- add timeouts when injecting/extracting frames, in case the HW breaks
- simplify the creation of the IFH
- fix the order of operations in lan966x_cleanup_ports
- fixes to phylink based on Russel review

v2->v3:
- fix compiling issues for x86
- fix resource management in first patch

v1->v2:
- add new patch for MAINTAINERS
- add functions lan966x_mac_cpu_learn/forget
- fix build issues with second patch
- fix the reset of the switch, return error if there is no reset controller
- start to use phylink_mii_c22_pcs_decode_state and
  phylink_mii_c22_pcs_encode_advertisement to remove duplicate code
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 35aefaad 813f38bf
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/microchip,lan966x-switch.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip Lan966x Ethernet switch controller
maintainers:
- Horatiu Vultur <horatiu.vultur@microchip.com>
description: |
The lan966x switch is a multi-port Gigabit AVB/TSN Ethernet Switch with
two integrated 10/100/1000Base-T PHYs. In addition to the integrated PHYs,
it supports up to 2RGMII/RMII, up to 3BASE-X/SERDES/2.5GBASE-X and up to
2 Quad-SGMII/Quad-USGMII interfaces.
properties:
$nodename:
pattern: "^switch@[0-9a-f]+$"
compatible:
const: microchip,lan966x-switch
reg:
items:
- description: cpu target
- description: general control block target
reg-names:
items:
- const: cpu
- const: gcb
interrupts:
minItems: 1
items:
- description: register based extraction
- description: frame dma based extraction
interrupt-names:
minItems: 1
items:
- const: xtr
- const: fdma
resets:
items:
- description: Reset controller used for switch core reset (soft reset)
- description: Reset controller used for releasing the phy from reset
reset-names:
items:
- const: switch
- const: phy
ethernet-ports:
type: object
patternProperties:
"^port@[0-9a-f]+$":
type: object
allOf:
- $ref: "http://devicetree.org/schemas/net/ethernet-controller.yaml#"
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
reg:
description:
Switch port number
phys:
description:
Phandle of a Ethernet SerDes PHY
phy-mode:
description:
This specifies the interface used by the Ethernet SerDes towards
the PHY or SFP.
enum:
- gmii
- sgmii
- qsgmii
- 1000base-x
- 2500base-x
phy-handle:
description:
Phandle of a Ethernet PHY.
sfp:
description:
Phandle of an SFP.
managed: true
required:
- reg
- phys
- phy-mode
oneOf:
- required:
- phy-handle
- required:
- sfp
- managed
required:
- compatible
- reg
- reg-names
- interrupts
- interrupt-names
- resets
- reset-names
- ethernet-ports
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
switch: switch@e0000000 {
compatible = "microchip,lan966x-switch";
reg = <0xe0000000 0x0100000>,
<0xe2000000 0x0800000>;
reg-names = "cpu", "gcb";
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "xtr";
resets = <&switch_reset 0>, <&phy_reset 0>;
reset-names = "switch", "phy";
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port0: port@0 {
reg = <0>;
phy-handle = <&phy0>;
phys = <&serdes 0 0>;
phy-mode = "gmii";
};
port1: port@1 {
reg = <1>;
sfp = <&sfp_eth1>;
managed = "in-band-status";
phys = <&serdes 2 4>;
phy-mode = "sgmii";
};
};
};
...
...@@ -12524,6 +12524,13 @@ L: netdev@vger.kernel.org ...@@ -12524,6 +12524,13 @@ L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ethernet/microchip/lan743x_* F: drivers/net/ethernet/microchip/lan743x_*
MICROCHIP LAN966X ETHERNET DRIVER
M: Horatiu Vultur <horatiu.vultur@microchip.com>
M: UNGLinuxDriver@microchip.com
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/microchip/lan966x/*
MICROCHIP LCDFB DRIVER MICROCHIP LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com> M: Nicolas Ferre <nicolas.ferre@microchip.com>
L: linux-fbdev@vger.kernel.org L: linux-fbdev@vger.kernel.org
......
...@@ -55,6 +55,7 @@ config LAN743X ...@@ -55,6 +55,7 @@ config LAN743X
To compile this driver as a module, choose M here. The module will be To compile this driver as a module, choose M here. The module will be
called lan743x. called lan743x.
source "drivers/net/ethernet/microchip/lan966x/Kconfig"
source "drivers/net/ethernet/microchip/sparx5/Kconfig" source "drivers/net/ethernet/microchip/sparx5/Kconfig"
endif # NET_VENDOR_MICROCHIP endif # NET_VENDOR_MICROCHIP
...@@ -9,4 +9,5 @@ obj-$(CONFIG_LAN743X) += lan743x.o ...@@ -9,4 +9,5 @@ obj-$(CONFIG_LAN743X) += lan743x.o
lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
obj-$(CONFIG_LAN966X_SWITCH) += lan966x/
obj-$(CONFIG_SPARX5_SWITCH) += sparx5/ obj-$(CONFIG_SPARX5_SWITCH) += sparx5/
config LAN966X_SWITCH
tristate "Lan966x switch driver"
depends on HAS_IOMEM
depends on OF
select PHYLINK
help
This driver supports the Lan966x network switch device.
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for the Microchip Lan966x network device drivers.
#
obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
lan966x_mac.o lan966x_ethtool.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __LAN966X_IFH_H__
#define __LAN966X_IFH_H__
/* Fields with description (*) should just be cleared upon injection
* IFH is transmitted MSByte first (Highest bit pos sent as MSB of first byte)
*/
#define IFH_LEN 7
/* Timestamp for frame */
#define IFH_POS_TIMESTAMP 192
/* Bypass analyzer with a prefilled IFH */
#define IFH_POS_BYPASS 191
/* Masqueraded injection with masq_port defining logical source port */
#define IFH_POS_MASQ 190
/* Masqueraded port number for injection */
#define IFH_POS_MASQ_PORT 186
/* Frame length (*) */
#define IFH_POS_LEN 178
/* Cell filling mode. Full(0),Etype(1), LlctOpt(2), Llct(3) */
#define IFH_POS_WRDMODE 176
/* Frame has 16 bits rtag removed compared to line data */
#define IFH_POS_RTAG48 175
/* Frame has a redundancy tag */
#define IFH_POS_HAS_RED_TAG 174
/* Frame has been cut through forwarded (*) */
#define IFH_POS_CUTTHRU 173
/* Rewriter command */
#define IFH_POS_REW_CMD 163
/* Enable OAM-related rewriting. PDU_TYPE encodes OAM type. */
#define IFH_POS_REW_OAM 162
/* PDU type. Encoding: (0-NONE, 1-Y1731_CCM, 2-MRP_TST, 3-MRP_ITST, 4-DLR_BCN,
* 5-DLR_ADV, 6-RTE_NULL_INJ, 7-IPV4, 8-IPV6, 9-Y1731_NON_CCM).
*/
#define IFH_POS_PDU_TYPE 158
/* Update FCS before transmission */
#define IFH_POS_FCS_UPD 157
/* Classified DSCP value of frame */
#define IFH_POS_DSCP 151
/* Yellow indication */
#define IFH_POS_DP 150
/* Process in RTE/inbound */
#define IFH_POS_RTE_INB_UPDATE 149
/* Number of tags to pop from frame */
#define IFH_POS_POP_CNT 147
/* Number of tags in front of the ethertype */
#define IFH_POS_ETYPE_OFS 145
/* Logical source port of frame (*) */
#define IFH_POS_SRCPORT 141
/* Sequence number in redundancy tag */
#define IFH_POS_SEQ_NUM 120
/* Stagd flag and classified TCI of frame (PCP/DEI/VID) */
#define IFH_POS_TCI 103
/* Classified internal priority for queuing */
#define IFH_POS_QOS_CLASS 100
/* Bit mask with eight cpu copy classses */
#define IFH_POS_CPUQ 92
/* Relearn + learn flags (*) */
#define IFH_POS_LEARN_FLAGS 90
/* SFLOW identifier for frame (0-8: Tx port, 9: Rx sampling, 15: No sampling) */
#define IFH_POS_SFLOW_ID 86
/* Set if an ACL/S2 rule was hit (*).
* Super priority: acl_hit=0 and acl_hit(4)=1.
*/
#define IFH_POS_ACL_HIT 85
/* S2 rule index hit (*) */
#define IFH_POS_ACL_IDX 79
/* ISDX as classified by S1 */
#define IFH_POS_ISDX 71
/* Destination ports for frame */
#define IFH_POS_DSTS 62
/* Storm policer to be applied: None/Uni/Multi/Broad (*) */
#define IFH_POS_FLOOD 60
/* Redundancy tag operation */
#define IFH_POS_SEQ_OP 58
/* Classified internal priority for resourcemgt, tagging etc */
#define IFH_POS_IPV 55
/* Frame is for AFI use */
#define IFH_POS_AFI 54
/* Internal aging value (*) */
#define IFH_POS_AGED 52
/* RTP Identifier */
#define IFH_POS_RTP_ID 42
/* RTP MRPD flow */
#define IFH_POS_RTP_SUBID 41
/* Profinet DataStatus or opcua GroupVersion MSB */
#define IFH_POS_PN_DATA_STATUS 33
/* Profinet transfer status (1 iff the status is 0) */
#define IFH_POS_PN_TRANSF_STATUS_ZERO 32
/* Profinet cycle counter or opcua NetworkMessageNumber */
#define IFH_POS_PN_CC 16
#define IFH_WID_TIMESTAMP 32
#define IFH_WID_BYPASS 1
#define IFH_WID_MASQ 1
#define IFH_WID_MASQ_PORT 4
#define IFH_WID_LEN 14
#define IFH_WID_WRDMODE 2
#define IFH_WID_RTAG48 1
#define IFH_WID_HAS_RED_TAG 1
#define IFH_WID_CUTTHRU 1
#define IFH_WID_REW_CMD 10
#define IFH_WID_REW_OAM 1
#define IFH_WID_PDU_TYPE 4
#define IFH_WID_FCS_UPD 1
#define IFH_WID_DSCP 6
#define IFH_WID_DP 1
#define IFH_WID_RTE_INB_UPDATE 1
#define IFH_WID_POP_CNT 2
#define IFH_WID_ETYPE_OFS 2
#define IFH_WID_SRCPORT 4
#define IFH_WID_SEQ_NUM 16
#define IFH_WID_TCI 17
#define IFH_WID_QOS_CLASS 3
#define IFH_WID_CPUQ 8
#define IFH_WID_LEARN_FLAGS 2
#define IFH_WID_SFLOW_ID 4
#define IFH_WID_ACL_HIT 1
#define IFH_WID_ACL_IDX 6
#define IFH_WID_ISDX 8
#define IFH_WID_DSTS 9
#define IFH_WID_FLOOD 2
#define IFH_WID_SEQ_OP 2
#define IFH_WID_IPV 3
#define IFH_WID_AFI 1
#define IFH_WID_AGED 2
#define IFH_WID_RTP_ID 10
#define IFH_WID_RTP_SUBID 1
#define IFH_WID_PN_DATA_STATUS 8
#define IFH_WID_PN_TRANSF_STATUS_ZERO 1
#define IFH_WID_PN_CC 16
#endif /* __LAN966X_IFH_H__ */
// SPDX-License-Identifier: GPL-2.0+
#include "lan966x_main.h"
#define LAN966X_MAC_COLUMNS 4
#define MACACCESS_CMD_IDLE 0
#define MACACCESS_CMD_LEARN 1
#define MACACCESS_CMD_FORGET 2
#define MACACCESS_CMD_AGE 3
#define MACACCESS_CMD_GET_NEXT 4
#define MACACCESS_CMD_INIT 5
#define MACACCESS_CMD_READ 6
#define MACACCESS_CMD_WRITE 7
#define MACACCESS_CMD_SYNC_GET_NEXT 8
static int lan966x_mac_get_status(struct lan966x *lan966x)
{
return lan_rd(lan966x, ANA_MACACCESS);
}
static int lan966x_mac_wait_for_completion(struct lan966x *lan966x)
{
u32 val;
return readx_poll_timeout(lan966x_mac_get_status,
lan966x, val,
(ANA_MACACCESS_MAC_TABLE_CMD_GET(val)) ==
MACACCESS_CMD_IDLE,
TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
}
static void lan966x_mac_select(struct lan966x *lan966x,
const unsigned char mac[ETH_ALEN],
unsigned int vid)
{
u32 macl = 0, mach = 0;
/* Set the MAC address to handle and the vlan associated in a format
* understood by the hardware.
*/
mach |= vid << 16;
mach |= mac[0] << 8;
mach |= mac[1] << 0;
macl |= mac[2] << 24;
macl |= mac[3] << 16;
macl |= mac[4] << 8;
macl |= mac[5] << 0;
lan_wr(macl, lan966x, ANA_MACLDATA);
lan_wr(mach, lan966x, ANA_MACHDATA);
}
int lan966x_mac_learn(struct lan966x *lan966x, int port,
const unsigned char mac[ETH_ALEN],
unsigned int vid,
enum macaccess_entry_type type)
{
lan966x_mac_select(lan966x, mac, vid);
/* Issue a write command */
lan_wr(ANA_MACACCESS_VALID_SET(1) |
ANA_MACACCESS_CHANGE2SW_SET(0) |
ANA_MACACCESS_DEST_IDX_SET(port) |
ANA_MACACCESS_ENTRYTYPE_SET(type) |
ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_LEARN),
lan966x, ANA_MACACCESS);
return lan966x_mac_wait_for_completion(lan966x);
}
int lan966x_mac_forget(struct lan966x *lan966x,
const unsigned char mac[ETH_ALEN],
unsigned int vid,
enum macaccess_entry_type type)
{
lan966x_mac_select(lan966x, mac, vid);
/* Issue a forget command */
lan_wr(ANA_MACACCESS_ENTRYTYPE_SET(type) |
ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_FORGET),
lan966x, ANA_MACACCESS);
return lan966x_mac_wait_for_completion(lan966x);
}
int lan966x_mac_cpu_learn(struct lan966x *lan966x, const char *addr, u16 vid)
{
return lan966x_mac_learn(lan966x, PGID_CPU, addr, vid, ENTRYTYPE_LOCKED);
}
int lan966x_mac_cpu_forget(struct lan966x *lan966x, const char *addr, u16 vid)
{
return lan966x_mac_forget(lan966x, addr, vid, ENTRYTYPE_LOCKED);
}
void lan966x_mac_init(struct lan966x *lan966x)
{
/* Clear the MAC table */
lan_wr(MACACCESS_CMD_INIT, lan966x, ANA_MACACCESS);
lan966x_mac_wait_for_completion(lan966x);
}
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __LAN966X_MAIN_H__
#define __LAN966X_MAIN_H__
#include <linux/etherdevice.h>
#include <linux/jiffies.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include "lan966x_regs.h"
#include "lan966x_ifh.h"
#define TABLE_UPDATE_SLEEP_US 10
#define TABLE_UPDATE_TIMEOUT_US 100000
#define LAN966X_BUFFER_CELL_SZ 64
#define LAN966X_BUFFER_MEMORY (160 * 1024)
#define LAN966X_BUFFER_MIN_SZ 60
#define PGID_AGGR 64
#define PGID_SRC 80
#define PGID_ENTRIES 89
#define PORT_PVID 0
/* Reserved amount for (SRC, PRIO) at index 8*SRC + PRIO */
#define QSYS_Q_RSRV 95
/* Reserved PGIDs */
#define PGID_CPU (PGID_AGGR - 6)
#define PGID_UC (PGID_AGGR - 5)
#define PGID_BC (PGID_AGGR - 4)
#define PGID_MC (PGID_AGGR - 3)
#define PGID_MCIPV4 (PGID_AGGR - 2)
#define PGID_MCIPV6 (PGID_AGGR - 1)
#define LAN966X_SPEED_NONE 0
#define LAN966X_SPEED_2500 1
#define LAN966X_SPEED_1000 1
#define LAN966X_SPEED_100 2
#define LAN966X_SPEED_10 3
#define CPU_PORT 8
/* MAC table entry types.
* ENTRYTYPE_NORMAL is subject to aging.
* ENTRYTYPE_LOCKED is not subject to aging.
* ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast.
* ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast.
*/
enum macaccess_entry_type {
ENTRYTYPE_NORMAL = 0,
ENTRYTYPE_LOCKED,
ENTRYTYPE_MACV4,
ENTRYTYPE_MACV6,
};
struct lan966x_port;
struct lan966x_stat_layout {
u32 offset;
char name[ETH_GSTRING_LEN];
};
struct lan966x {
struct device *dev;
u8 num_phys_ports;
struct lan966x_port **ports;
void __iomem *regs[NUM_TARGETS];
int shared_queue_sz;
u8 base_mac[ETH_ALEN];
/* stats */
const struct lan966x_stat_layout *stats_layout;
u32 num_stats;
/* workqueue for reading stats */
struct mutex stats_lock;
u64 *stats;
struct delayed_work stats_work;
struct workqueue_struct *stats_queue;
/* interrupts */
int xtr_irq;
};
struct lan966x_port_config {
phy_interface_t portmode;
const unsigned long *advertising;
int speed;
int duplex;
u32 pause;
bool inband;
bool autoneg;
};
struct lan966x_port {
struct net_device *dev;
struct lan966x *lan966x;
u8 chip_port;
u16 pvid;
struct phylink_config phylink_config;
struct phylink_pcs phylink_pcs;
struct lan966x_port_config config;
struct phylink *phylink;
struct phy *serdes;
struct fwnode_handle *fwnode;
};
extern const struct phylink_mac_ops lan966x_phylink_mac_ops;
extern const struct phylink_pcs_ops lan966x_phylink_pcs_ops;
extern const struct ethtool_ops lan966x_ethtool_ops;
void lan966x_stats_get(struct net_device *dev,
struct rtnl_link_stats64 *stats);
int lan966x_stats_init(struct lan966x *lan966x);
void lan966x_port_config_down(struct lan966x_port *port);
void lan966x_port_config_up(struct lan966x_port *port);
void lan966x_port_status_get(struct lan966x_port *port,
struct phylink_link_state *state);
int lan966x_port_pcs_set(struct lan966x_port *port,
struct lan966x_port_config *config);
void lan966x_port_init(struct lan966x_port *port);
int lan966x_mac_learn(struct lan966x *lan966x, int port,
const unsigned char mac[ETH_ALEN],
unsigned int vid,
enum macaccess_entry_type type);
int lan966x_mac_forget(struct lan966x *lan966x,
const unsigned char mac[ETH_ALEN],
unsigned int vid,
enum macaccess_entry_type type);
int lan966x_mac_cpu_learn(struct lan966x *lan966x, const char *addr, u16 vid);
int lan966x_mac_cpu_forget(struct lan966x *lan966x, const char *addr, u16 vid);
void lan966x_mac_init(struct lan966x *lan966x);
static inline void __iomem *lan_addr(void __iomem *base[],
int id, int tinst, int tcnt,
int gbase, int ginst,
int gcnt, int gwidth,
int raddr, int rinst,
int rcnt, int rwidth)
{
WARN_ON((tinst) >= tcnt);
WARN_ON((ginst) >= gcnt);
WARN_ON((rinst) >= rcnt);
return base[id + (tinst)] +
gbase + ((ginst) * gwidth) +
raddr + ((rinst) * rwidth);
}
static inline u32 lan_rd(struct lan966x *lan966x, int id, int tinst, int tcnt,
int gbase, int ginst, int gcnt, int gwidth,
int raddr, int rinst, int rcnt, int rwidth)
{
return readl(lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst,
gcnt, gwidth, raddr, rinst, rcnt, rwidth));
}
static inline void lan_wr(u32 val, struct lan966x *lan966x,
int id, int tinst, int tcnt,
int gbase, int ginst, int gcnt, int gwidth,
int raddr, int rinst, int rcnt, int rwidth)
{
writel(val, lan_addr(lan966x->regs, id, tinst, tcnt,
gbase, ginst, gcnt, gwidth,
raddr, rinst, rcnt, rwidth));
}
static inline void lan_rmw(u32 val, u32 mask, struct lan966x *lan966x,
int id, int tinst, int tcnt,
int gbase, int ginst, int gcnt, int gwidth,
int raddr, int rinst, int rcnt, int rwidth)
{
u32 nval;
nval = readl(lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst,
gcnt, gwidth, raddr, rinst, rcnt, rwidth));
nval = (nval & ~mask) | (val & mask);
writel(nval, lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst,
gcnt, gwidth, raddr, rinst, rcnt, rwidth));
}
#endif /* __LAN966X_MAIN_H__ */
// SPDX-License-Identifier: GPL-2.0+
#include <linux/module.h>
#include <linux/phylink.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/phy/phy.h>
#include <linux/sfp.h>
#include "lan966x_main.h"
static void lan966x_phylink_mac_config(struct phylink_config *config,
unsigned int mode,
const struct phylink_link_state *state)
{
}
static int lan966x_phylink_mac_prepare(struct phylink_config *config,
unsigned int mode,
phy_interface_t iface)
{
struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
int err;
if (port->serdes) {
err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
iface);
if (err) {
netdev_err(to_net_dev(config->dev),
"Could not set mode of SerDes\n");
return err;
}
}
return 0;
}
static void lan966x_phylink_mac_link_up(struct phylink_config *config,
struct phy_device *phy,
unsigned int mode,
phy_interface_t interface,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
struct lan966x_port_config *port_config = &port->config;
port_config->duplex = duplex;
port_config->speed = speed;
port_config->pause = 0;
port_config->pause |= tx_pause ? MLO_PAUSE_TX : 0;
port_config->pause |= rx_pause ? MLO_PAUSE_RX : 0;
lan966x_port_config_up(port);
}
static void lan966x_phylink_mac_link_down(struct phylink_config *config,
unsigned int mode,
phy_interface_t interface)
{
struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
struct lan966x *lan966x = port->lan966x;
lan966x_port_config_down(port);
/* Take PCS out of reset */
lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
DEV_CLOCK_CFG_PCS_TX_RST_SET(0),
DEV_CLOCK_CFG_PCS_RX_RST |
DEV_CLOCK_CFG_PCS_TX_RST,
lan966x, DEV_CLOCK_CFG(port->chip_port));
}
static struct lan966x_port *lan966x_pcs_to_port(struct phylink_pcs *pcs)
{
return container_of(pcs, struct lan966x_port, phylink_pcs);
}
static void lan966x_pcs_get_state(struct phylink_pcs *pcs,
struct phylink_link_state *state)
{
struct lan966x_port *port = lan966x_pcs_to_port(pcs);
lan966x_port_status_get(port, state);
}
static int lan966x_pcs_config(struct phylink_pcs *pcs,
unsigned int mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct lan966x_port *port = lan966x_pcs_to_port(pcs);
struct lan966x_port_config config;
int ret;
config = port->config;
config.portmode = interface;
config.inband = phylink_autoneg_inband(mode);
config.autoneg = phylink_test(advertising, Autoneg);
config.advertising = advertising;
ret = lan966x_port_pcs_set(port, &config);
if (ret)
netdev_err(port->dev, "port PCS config failed: %d\n", ret);
return ret;
}
static void lan966x_pcs_aneg_restart(struct phylink_pcs *pcs)
{
/* Currently not used */
}
const struct phylink_mac_ops lan966x_phylink_mac_ops = {
.validate = phylink_generic_validate,
.mac_config = lan966x_phylink_mac_config,
.mac_prepare = lan966x_phylink_mac_prepare,
.mac_link_down = lan966x_phylink_mac_link_down,
.mac_link_up = lan966x_phylink_mac_link_up,
};
const struct phylink_pcs_ops lan966x_phylink_pcs_ops = {
.pcs_get_state = lan966x_pcs_get_state,
.pcs_config = lan966x_pcs_config,
.pcs_an_restart = lan966x_pcs_aneg_restart,
};
This diff is collapsed.
This diff is collapsed.
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