-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net: dsa: microchip: add DSA support for microchip LAN937x
Basic DSA driver support for lan937x and the device will be configured through SPI interface. It adds the lan937x_dev_ops in ksz_common.c file and tries to reuse the functionality of ksz9477 series switch. drivers/net/dsa/microchip/ path is already part of MAINTAINERS & the new files come under this path. Hence no update needed to the MAINTAINERS Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Arun Ramadoss
authored and
David S. Miller
committed
Jul 2, 2022
1 parent
457c182
commit 55ab6ff
Showing
6 changed files
with
333 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* Microchip lan937x dev ops headers | ||
* Copyright (C) 2019-2022 Microchip Technology Inc. | ||
*/ | ||
|
||
#ifndef __LAN937X_CFG_H | ||
#define __LAN937X_CFG_H | ||
|
||
int lan937x_reset_switch(struct ksz_device *dev); | ||
int lan937x_setup(struct dsa_switch *ds); | ||
void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port); | ||
void lan937x_config_cpu_port(struct dsa_switch *ds); | ||
int lan937x_switch_init(struct ksz_device *dev); | ||
void lan937x_switch_exit(struct ksz_device *dev); | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Microchip LAN937X switch driver main logic | ||
* Copyright (C) 2019-2022 Microchip Technology Inc. | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/iopoll.h> | ||
#include <linux/phy.h> | ||
#include <linux/of_net.h> | ||
#include <linux/if_bridge.h> | ||
#include <linux/math.h> | ||
#include <net/dsa.h> | ||
#include <net/switchdev.h> | ||
|
||
#include "lan937x_reg.h" | ||
#include "ksz_common.h" | ||
#include "lan937x.h" | ||
|
||
static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) | ||
{ | ||
return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); | ||
} | ||
|
||
static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset, | ||
u8 bits, bool set) | ||
{ | ||
return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), | ||
bits, set ? bits : 0); | ||
} | ||
|
||
int lan937x_reset_switch(struct ksz_device *dev) | ||
{ | ||
u32 data32; | ||
int ret; | ||
|
||
/* reset switch */ | ||
ret = lan937x_cfg(dev, REG_SW_OPERATION, SW_RESET, true); | ||
if (ret < 0) | ||
return ret; | ||
|
||
/* Enable Auto Aging */ | ||
ret = lan937x_cfg(dev, REG_SW_LUE_CTRL_1, SW_LINK_AUTO_AGING, true); | ||
if (ret < 0) | ||
return ret; | ||
|
||
/* disable interrupts */ | ||
ret = ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK); | ||
if (ret < 0) | ||
return ret; | ||
|
||
ret = ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0xFF); | ||
if (ret < 0) | ||
return ret; | ||
|
||
return ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32); | ||
} | ||
|
||
void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port) | ||
{ | ||
struct dsa_switch *ds = dev->ds; | ||
u8 member; | ||
|
||
/* enable tag tail for host port */ | ||
if (cpu_port) | ||
lan937x_port_cfg(dev, port, REG_PORT_CTRL_0, | ||
PORT_TAIL_TAG_ENABLE, true); | ||
|
||
/* disable frame check length field */ | ||
lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_0, PORT_CHECK_LENGTH, | ||
false); | ||
|
||
/* set back pressure for half duplex */ | ||
lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, | ||
true); | ||
|
||
/* enable 802.1p priority */ | ||
lan937x_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); | ||
|
||
if (!dev->info->internal_phy[port]) | ||
lan937x_port_cfg(dev, port, REG_PORT_XMII_CTRL_0, | ||
PORT_MII_TX_FLOW_CTRL | PORT_MII_RX_FLOW_CTRL, | ||
true); | ||
|
||
if (cpu_port) | ||
member = dsa_user_ports(ds); | ||
else | ||
member = BIT(dsa_upstream_port(ds, port)); | ||
|
||
dev->dev_ops->cfg_port_member(dev, port, member); | ||
} | ||
|
||
void lan937x_config_cpu_port(struct dsa_switch *ds) | ||
{ | ||
struct ksz_device *dev = ds->priv; | ||
struct dsa_port *dp; | ||
|
||
dsa_switch_for_each_cpu_port(dp, ds) { | ||
if (dev->info->cpu_ports & (1 << dp->index)) { | ||
dev->cpu_port = dp->index; | ||
|
||
/* enable cpu port */ | ||
lan937x_port_setup(dev, dp->index, true); | ||
} | ||
} | ||
|
||
dsa_switch_for_each_user_port(dp, ds) { | ||
ksz_port_stp_state_set(ds, dp->index, BR_STATE_DISABLED); | ||
} | ||
} | ||
|
||
int lan937x_setup(struct dsa_switch *ds) | ||
{ | ||
struct ksz_device *dev = ds->priv; | ||
|
||
/* The VLAN aware is a global setting. Mixed vlan | ||
* filterings are not supported. | ||
*/ | ||
ds->vlan_filtering_is_global = true; | ||
|
||
/* Enable aggressive back off for half duplex & UNH mode */ | ||
lan937x_cfg(dev, REG_SW_MAC_CTRL_0, | ||
(SW_PAUSE_UNH_MODE | SW_NEW_BACKOFF | SW_AGGR_BACKOFF), | ||
true); | ||
|
||
/* If NO_EXC_COLLISION_DROP bit is set, the switch will not drop | ||
* packets when 16 or more collisions occur | ||
*/ | ||
lan937x_cfg(dev, REG_SW_MAC_CTRL_1, NO_EXC_COLLISION_DROP, true); | ||
|
||
/* enable global MIB counter freeze function */ | ||
lan937x_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true); | ||
|
||
/* disable CLK125 & CLK25, 1: disable, 0: enable */ | ||
lan937x_cfg(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1, | ||
(SW_CLK125_ENB | SW_CLK25_ENB), true); | ||
|
||
return 0; | ||
} | ||
|
||
int lan937x_switch_init(struct ksz_device *dev) | ||
{ | ||
dev->port_mask = (1 << dev->info->port_cnt) - 1; | ||
|
||
return 0; | ||
} | ||
|
||
void lan937x_switch_exit(struct ksz_device *dev) | ||
{ | ||
lan937x_reset_switch(dev); | ||
} | ||
|
||
MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>"); | ||
MODULE_DESCRIPTION("Microchip LAN937x Series Switch DSA Driver"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* Microchip LAN937X switch register definitions | ||
* Copyright (C) 2019-2021 Microchip Technology Inc. | ||
*/ | ||
#ifndef __LAN937X_REG_H | ||
#define __LAN937X_REG_H | ||
|
||
#define PORT_CTRL_ADDR(port, addr) ((addr) | (((port) + 1) << 12)) | ||
|
||
/* 0 - Operation */ | ||
#define REG_SW_INT_STATUS__4 0x0010 | ||
#define REG_SW_INT_MASK__4 0x0014 | ||
|
||
#define LUE_INT BIT(31) | ||
#define TRIG_TS_INT BIT(30) | ||
#define APB_TIMEOUT_INT BIT(29) | ||
#define OVER_TEMP_INT BIT(28) | ||
#define HSR_INT BIT(27) | ||
#define PIO_INT BIT(26) | ||
#define POR_READY_INT BIT(25) | ||
|
||
#define SWITCH_INT_MASK \ | ||
(LUE_INT | TRIG_TS_INT | APB_TIMEOUT_INT | OVER_TEMP_INT | HSR_INT | \ | ||
PIO_INT | POR_READY_INT) | ||
|
||
#define REG_SW_PORT_INT_STATUS__4 0x0018 | ||
#define REG_SW_PORT_INT_MASK__4 0x001C | ||
|
||
/* 1 - Global */ | ||
#define REG_SW_GLOBAL_OUTPUT_CTRL__1 0x0103 | ||
#define SW_CLK125_ENB BIT(1) | ||
#define SW_CLK25_ENB BIT(0) | ||
|
||
/* 3 - Operation Control */ | ||
#define REG_SW_OPERATION 0x0300 | ||
|
||
#define SW_DOUBLE_TAG BIT(7) | ||
#define SW_OVER_TEMP_ENABLE BIT(2) | ||
#define SW_RESET BIT(1) | ||
|
||
#define REG_SW_LUE_CTRL_0 0x0310 | ||
|
||
#define SW_VLAN_ENABLE BIT(7) | ||
#define SW_DROP_INVALID_VID BIT(6) | ||
#define SW_AGE_CNT_M 0x7 | ||
#define SW_AGE_CNT_S 3 | ||
#define SW_RESV_MCAST_ENABLE BIT(2) | ||
|
||
#define REG_SW_LUE_CTRL_1 0x0311 | ||
|
||
#define UNICAST_LEARN_DISABLE BIT(7) | ||
#define SW_FLUSH_STP_TABLE BIT(5) | ||
#define SW_FLUSH_MSTP_TABLE BIT(4) | ||
#define SW_SRC_ADDR_FILTER BIT(3) | ||
#define SW_AGING_ENABLE BIT(2) | ||
#define SW_FAST_AGING BIT(1) | ||
#define SW_LINK_AUTO_AGING BIT(0) | ||
|
||
#define REG_SW_MAC_CTRL_0 0x0330 | ||
#define SW_NEW_BACKOFF BIT(7) | ||
#define SW_PAUSE_UNH_MODE BIT(1) | ||
#define SW_AGGR_BACKOFF BIT(0) | ||
|
||
#define REG_SW_MAC_CTRL_1 0x0331 | ||
#define SW_SHORT_IFG BIT(7) | ||
#define MULTICAST_STORM_DISABLE BIT(6) | ||
#define SW_BACK_PRESSURE BIT(5) | ||
#define FAIR_FLOW_CTRL BIT(4) | ||
#define NO_EXC_COLLISION_DROP BIT(3) | ||
#define SW_LEGAL_PACKET_DISABLE BIT(1) | ||
#define SW_PASS_SHORT_FRAME BIT(0) | ||
|
||
#define REG_SW_MAC_CTRL_6 0x0336 | ||
#define SW_MIB_COUNTER_FLUSH BIT(7) | ||
#define SW_MIB_COUNTER_FREEZE BIT(6) | ||
|
||
/* 4 - LUE */ | ||
#define REG_SW_ALU_STAT_CTRL__4 0x041C | ||
|
||
#define REG_SW_ALU_VAL_B 0x0424 | ||
#define ALU_V_OVERRIDE BIT(31) | ||
#define ALU_V_USE_FID BIT(30) | ||
#define ALU_V_PORT_MAP 0xFF | ||
|
||
/* Port Registers */ | ||
|
||
/* 0 - Operation */ | ||
#define REG_PORT_CTRL_0 0x0020 | ||
|
||
#define PORT_MAC_LOOPBACK BIT(7) | ||
#define PORT_MAC_REMOTE_LOOPBACK BIT(6) | ||
#define PORT_K2L_INSERT_ENABLE BIT(5) | ||
#define PORT_K2L_DEBUG_ENABLE BIT(4) | ||
#define PORT_TAIL_TAG_ENABLE BIT(2) | ||
#define PORT_QUEUE_SPLIT_ENABLE 0x3 | ||
|
||
/* 3 - xMII */ | ||
#define REG_PORT_XMII_CTRL_0 0x0300 | ||
#define PORT_SGMII_SEL BIT(7) | ||
#define PORT_MII_FULL_DUPLEX BIT(6) | ||
#define PORT_MII_TX_FLOW_CTRL BIT(5) | ||
#define PORT_MII_100MBIT BIT(4) | ||
#define PORT_MII_RX_FLOW_CTRL BIT(3) | ||
#define PORT_GRXC_ENABLE BIT(0) | ||
|
||
/* 4 - MAC */ | ||
#define REG_PORT_MAC_CTRL_0 0x0400 | ||
#define PORT_CHECK_LENGTH BIT(2) | ||
#define PORT_BROADCAST_STORM BIT(1) | ||
#define PORT_JUMBO_PACKET BIT(0) | ||
|
||
#define REG_PORT_MAC_CTRL_1 0x0401 | ||
#define PORT_BACK_PRESSURE BIT(3) | ||
#define PORT_PASS_ALL BIT(0) | ||
|
||
/* 8 - Classification and Policing */ | ||
#define REG_PORT_MRI_PRIO_CTRL 0x0801 | ||
#define PORT_HIGHEST_PRIO BIT(7) | ||
#define PORT_OR_PRIO BIT(6) | ||
#define PORT_MAC_PRIO_ENABLE BIT(4) | ||
#define PORT_VLAN_PRIO_ENABLE BIT(3) | ||
#define PORT_802_1P_PRIO_ENABLE BIT(2) | ||
#define PORT_DIFFSERV_PRIO_ENABLE BIT(1) | ||
#define PORT_ACL_PRIO_ENABLE BIT(0) | ||
|
||
#define P_PRIO_CTRL REG_PORT_MRI_PRIO_CTRL | ||
|
||
#endif |