cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spl2sw_mac.c (8954B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright Sunplus Technology Co., Ltd.
      3 *       All rights reserved.
      4 */
      5
      6#include <linux/platform_device.h>
      7#include <linux/netdevice.h>
      8#include <linux/bitfield.h>
      9#include <linux/of_mdio.h>
     10
     11#include "spl2sw_register.h"
     12#include "spl2sw_define.h"
     13#include "spl2sw_desc.h"
     14#include "spl2sw_mac.h"
     15
     16void spl2sw_mac_hw_stop(struct spl2sw_common *comm)
     17{
     18	u32 reg;
     19
     20	if (comm->enable == 0) {
     21		/* Mask and clear all interrupts. */
     22		writel(0xffffffff, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
     23		writel(0xffffffff, comm->l2sw_reg_base + L2SW_SW_INT_STATUS_0);
     24
     25		/* Disable cpu 0 and cpu 1. */
     26		reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
     27		reg |= MAC_DIS_SOC1_CPU | MAC_DIS_SOC0_CPU;
     28		writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);
     29	}
     30
     31	/* Disable LAN ports. */
     32	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL0);
     33	reg |= FIELD_PREP(MAC_DIS_PORT, ~comm->enable);
     34	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL0);
     35}
     36
     37void spl2sw_mac_hw_start(struct spl2sw_common *comm)
     38{
     39	u32 reg;
     40
     41	/* Enable cpu port 0 (6) & CRC padding (8) */
     42	reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
     43	reg &= ~MAC_DIS_SOC0_CPU;
     44	reg |= MAC_EN_CRC_SOC0;
     45	writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);
     46
     47	/* Enable port 0 & port 1 */
     48	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL0);
     49	reg &= FIELD_PREP(MAC_DIS_PORT, ~comm->enable) | ~MAC_DIS_PORT;
     50	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL0);
     51}
     52
     53int spl2sw_mac_addr_add(struct spl2sw_mac *mac)
     54{
     55	struct spl2sw_common *comm = mac->comm;
     56	u32 reg;
     57	int ret;
     58
     59	/* Write 6-octet MAC address. */
     60	writel((mac->mac_addr[0] << 0) + (mac->mac_addr[1] << 8),
     61	       comm->l2sw_reg_base + L2SW_W_MAC_15_0);
     62	writel((mac->mac_addr[2] << 0) + (mac->mac_addr[3] << 8) +
     63	       (mac->mac_addr[4] << 16) + (mac->mac_addr[5] << 24),
     64	       comm->l2sw_reg_base + L2SW_W_MAC_47_16);
     65
     66	/* Set learn port = cpu_port, aging = 1 */
     67	reg = MAC_W_CPU_PORT_0 | FIELD_PREP(MAC_W_VID, mac->vlan_id) |
     68	      FIELD_PREP(MAC_W_AGE, 1) | MAC_W_MAC_CMD;
     69	writel(reg, comm->l2sw_reg_base + L2SW_WT_MAC_AD0);
     70
     71	/* Wait for completing. */
     72	ret = read_poll_timeout(readl, reg, reg & MAC_W_MAC_DONE, 1, 200, true,
     73				comm->l2sw_reg_base + L2SW_WT_MAC_AD0);
     74	if (ret) {
     75		netdev_err(mac->ndev, "Failed to add address to table!\n");
     76		return ret;
     77	}
     78
     79	netdev_dbg(mac->ndev, "mac_ad0 = %08x, mac_ad = %08x%04x\n",
     80		   readl(comm->l2sw_reg_base + L2SW_WT_MAC_AD0),
     81		   (u32)FIELD_GET(MAC_W_MAC_47_16,
     82		   readl(comm->l2sw_reg_base + L2SW_W_MAC_47_16)),
     83		   (u32)FIELD_GET(MAC_W_MAC_15_0,
     84		   readl(comm->l2sw_reg_base + L2SW_W_MAC_15_0)));
     85	return 0;
     86}
     87
     88int spl2sw_mac_addr_del(struct spl2sw_mac *mac)
     89{
     90	struct spl2sw_common *comm = mac->comm;
     91	u32 reg;
     92	int ret;
     93
     94	/* Write 6-octet MAC address. */
     95	writel((mac->mac_addr[0] << 0) + (mac->mac_addr[1] << 8),
     96	       comm->l2sw_reg_base + L2SW_W_MAC_15_0);
     97	writel((mac->mac_addr[2] << 0) + (mac->mac_addr[3] << 8) +
     98	       (mac->mac_addr[4] << 16) + (mac->mac_addr[5] << 24),
     99	       comm->l2sw_reg_base + L2SW_W_MAC_47_16);
    100
    101	/* Set learn port = lan_port0 and aging = 0
    102	 * to wipe (age) out the entry.
    103	 */
    104	reg = MAC_W_LAN_PORT_0 | FIELD_PREP(MAC_W_VID, mac->vlan_id) | MAC_W_MAC_CMD;
    105	writel(reg, comm->l2sw_reg_base + L2SW_WT_MAC_AD0);
    106
    107	/* Wait for completing. */
    108	ret = read_poll_timeout(readl, reg, reg & MAC_W_MAC_DONE, 1, 200, true,
    109				comm->l2sw_reg_base + L2SW_WT_MAC_AD0);
    110	if (ret) {
    111		netdev_err(mac->ndev, "Failed to delete address from table!\n");
    112		return ret;
    113	}
    114
    115	netdev_dbg(mac->ndev, "mac_ad0 = %08x, mac_ad = %08x%04x\n",
    116		   readl(comm->l2sw_reg_base + L2SW_WT_MAC_AD0),
    117		   (u32)FIELD_GET(MAC_W_MAC_47_16,
    118		   readl(comm->l2sw_reg_base + L2SW_W_MAC_47_16)),
    119		   (u32)FIELD_GET(MAC_W_MAC_15_0,
    120		   readl(comm->l2sw_reg_base + L2SW_W_MAC_15_0)));
    121	return 0;
    122}
    123
    124void spl2sw_mac_hw_init(struct spl2sw_common *comm)
    125{
    126	u32 reg;
    127
    128	/* Disable cpu0 and cpu 1 port. */
    129	reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
    130	reg |= MAC_DIS_SOC1_CPU | MAC_DIS_SOC0_CPU;
    131	writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);
    132
    133	/* Set base addresses of TX and RX queues. */
    134	writel(comm->desc_dma, comm->l2sw_reg_base + L2SW_TX_LBASE_ADDR_0);
    135	writel(comm->desc_dma + sizeof(struct spl2sw_mac_desc) * TX_DESC_NUM,
    136	       comm->l2sw_reg_base + L2SW_TX_HBASE_ADDR_0);
    137	writel(comm->desc_dma + sizeof(struct spl2sw_mac_desc) * (TX_DESC_NUM +
    138	       MAC_GUARD_DESC_NUM), comm->l2sw_reg_base + L2SW_RX_HBASE_ADDR_0);
    139	writel(comm->desc_dma + sizeof(struct spl2sw_mac_desc) * (TX_DESC_NUM +
    140	       MAC_GUARD_DESC_NUM + RX_QUEUE0_DESC_NUM),
    141	       comm->l2sw_reg_base + L2SW_RX_LBASE_ADDR_0);
    142
    143	/* Fc_rls_th=0x4a, Fc_set_th=0x3a, Drop_rls_th=0x2d, Drop_set_th=0x1d */
    144	writel(0x4a3a2d1d, comm->l2sw_reg_base + L2SW_FL_CNTL_TH);
    145
    146	/* Cpu_rls_th=0x4a, Cpu_set_th=0x3a, Cpu_th=0x12, Port_th=0x12 */
    147	writel(0x4a3a1212, comm->l2sw_reg_base + L2SW_CPU_FL_CNTL_TH);
    148
    149	/* mtcc_lmt=0xf, Pri_th_l=6, Pri_th_h=6, weigh_8x_en=1 */
    150	writel(0xf6680000, comm->l2sw_reg_base + L2SW_PRI_FL_CNTL);
    151
    152	/* High-active LED */
    153	reg = readl(comm->l2sw_reg_base + L2SW_LED_PORT0);
    154	reg |= MAC_LED_ACT_HI;
    155	writel(reg, comm->l2sw_reg_base + L2SW_LED_PORT0);
    156
    157	/* Disable aging of cpu port 0 & 1.
    158	 * Disable SA learning of cpu port 0 & 1.
    159	 * Enable UC and MC packets
    160	 */
    161	reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
    162	reg &= ~(MAC_EN_SOC1_AGING | MAC_EN_SOC0_AGING |
    163		 MAC_DIS_BC2CPU_P1 | MAC_DIS_BC2CPU_P0 |
    164		 MAC_DIS_MC2CPU_P1 | MAC_DIS_MC2CPU_P0);
    165	reg |= MAC_DIS_LRN_SOC1 | MAC_DIS_LRN_SOC0;
    166	writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);
    167
    168	/* Enable RMC2CPU for port 0 & 1
    169	 * Enable Flow control for port 0 & 1
    170	 * Enable Back pressure for port 0 & 1
    171	 */
    172	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL0);
    173	reg &= ~(MAC_DIS_RMC2CPU_P1 | MAC_DIS_RMC2CPU_P0);
    174	reg |= MAC_EN_FLOW_CTL_P1 | MAC_EN_FLOW_CTL_P0 |
    175	       MAC_EN_BACK_PRESS_P1 | MAC_EN_BACK_PRESS_P0;
    176	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL0);
    177
    178	/* Disable LAN port SA learning. */
    179	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL1);
    180	reg |= MAC_DIS_SA_LRN_P1 | MAC_DIS_SA_LRN_P0;
    181	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL1);
    182
    183	/* Enable rmii force mode and
    184	 * set both external phy-address to 31.
    185	 */
    186	reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
    187	reg &= ~(MAC_EXT_PHY1_ADDR | MAC_EXT_PHY0_ADDR);
    188	reg |= FIELD_PREP(MAC_EXT_PHY1_ADDR, 31) | FIELD_PREP(MAC_EXT_PHY0_ADDR, 31);
    189	reg |= MAC_FORCE_RMII_EN_1 | MAC_FORCE_RMII_EN_0;
    190	writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
    191
    192	/* Port 0: VLAN group 0
    193	 * Port 1: VLAN group 1
    194	 */
    195	reg = FIELD_PREP(MAC_P1_PVID, 1) | FIELD_PREP(MAC_P0_PVID, 0);
    196	writel(reg, comm->l2sw_reg_base + L2SW_PVID_CONFIG0);
    197
    198	/* VLAN group 0: cpu0 (bit3) + port0 (bit0) = 1001 = 0x9
    199	 * VLAN group 1: cpu0 (bit3) + port1 (bit1) = 1010 = 0xa
    200	 */
    201	reg = FIELD_PREP(MAC_VLAN_MEMSET_1, 0xa) | FIELD_PREP(MAC_VLAN_MEMSET_0, 9);
    202	writel(reg, comm->l2sw_reg_base + L2SW_VLAN_MEMSET_CONFIG0);
    203
    204	/* RMC forward: to_cpu (1)
    205	 * LED: 60mS (1)
    206	 * BC storm prev: 31 BC (1)
    207	 */
    208	reg = readl(comm->l2sw_reg_base + L2SW_SW_GLB_CNTL);
    209	reg &= ~(MAC_RMC_TB_FAULT_RULE | MAC_LED_FLASH_TIME | MAC_BC_STORM_PREV);
    210	reg |= FIELD_PREP(MAC_RMC_TB_FAULT_RULE, 1) |
    211	       FIELD_PREP(MAC_LED_FLASH_TIME, 1) |
    212	       FIELD_PREP(MAC_BC_STORM_PREV, 1);
    213	writel(reg, comm->l2sw_reg_base + L2SW_SW_GLB_CNTL);
    214
    215	writel(MAC_INT_MASK_DEF, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
    216}
    217
    218void spl2sw_mac_rx_mode_set(struct spl2sw_mac *mac)
    219{
    220	struct spl2sw_common *comm = mac->comm;
    221	struct net_device *ndev = mac->ndev;
    222	u32 mask, reg, rx_mode;
    223
    224	netdev_dbg(ndev, "ndev->flags = %08x\n", ndev->flags);
    225	mask = FIELD_PREP(MAC_DIS_MC2CPU, mac->lan_port) |
    226	       FIELD_PREP(MAC_DIS_UN2CPU, mac->lan_port);
    227	reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
    228
    229	if (ndev->flags & IFF_PROMISC) {
    230		/* Allow MC and unknown UC packets */
    231		rx_mode = FIELD_PREP(MAC_DIS_MC2CPU, mac->lan_port) |
    232			  FIELD_PREP(MAC_DIS_UN2CPU, mac->lan_port);
    233	} else if ((!netdev_mc_empty(ndev) && (ndev->flags & IFF_MULTICAST)) ||
    234		   (ndev->flags & IFF_ALLMULTI)) {
    235		/* Allow MC packets */
    236		rx_mode = FIELD_PREP(MAC_DIS_MC2CPU, mac->lan_port);
    237	} else {
    238		/* Disable MC and unknown UC packets */
    239		rx_mode = 0;
    240	}
    241
    242	writel((reg & (~mask)) | ((~rx_mode) & mask), comm->l2sw_reg_base + L2SW_CPU_CNTL);
    243	netdev_dbg(ndev, "cpu_cntl = %08x\n", readl(comm->l2sw_reg_base + L2SW_CPU_CNTL));
    244}
    245
    246void spl2sw_mac_init(struct spl2sw_common *comm)
    247{
    248	u32 i;
    249
    250	for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
    251		comm->rx_pos[i] = 0;
    252	mb();	/* make sure settings are effective. */
    253
    254	spl2sw_mac_hw_init(comm);
    255}
    256
    257void spl2sw_mac_soft_reset(struct spl2sw_common *comm)
    258{
    259	u32 i;
    260
    261	spl2sw_mac_hw_stop(comm);
    262
    263	spl2sw_rx_descs_flush(comm);
    264	comm->tx_pos = 0;
    265	comm->tx_done_pos = 0;
    266	comm->tx_desc_full = 0;
    267
    268	for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
    269		comm->rx_pos[i] = 0;
    270	mb();	/* make sure settings are effective. */
    271
    272	spl2sw_mac_hw_init(comm);
    273	spl2sw_mac_hw_start(comm);
    274}