brintos

brintos / linux-shallow public Read only

0
0
Text · 80.0 KiB · 0102a82 Raw
2749 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/* Copyright 2017 Microsemi Corporation3 * Copyright 2018-2019 NXP4 */5#include <linux/fsl/enetc_mdio.h>6#include <soc/mscc/ocelot_qsys.h>7#include <soc/mscc/ocelot_vcap.h>8#include <soc/mscc/ocelot_ana.h>9#include <soc/mscc/ocelot_dev.h>10#include <soc/mscc/ocelot_ptp.h>11#include <soc/mscc/ocelot_sys.h>12#include <net/tc_act/tc_gate.h>13#include <soc/mscc/ocelot.h>14#include <linux/dsa/ocelot.h>15#include <linux/pcs-lynx.h>16#include <net/pkt_sched.h>17#include <linux/iopoll.h>18#include <linux/mdio.h>19#include <linux/of.h>20#include <linux/pci.h>21#include <linux/time.h>22#include "felix.h"23 24#define VSC9959_NUM_PORTS		625 26#define VSC9959_TAS_GCL_ENTRY_MAX	6327#define VSC9959_TAS_MIN_GATE_LEN_NS	3328#define VSC9959_VCAP_POLICER_BASE	6329#define VSC9959_VCAP_POLICER_MAX	38330#define VSC9959_SWITCH_PCI_BAR		431#define VSC9959_IMDIO_PCI_BAR		032 33#define VSC9959_PORT_MODE_SERDES	(OCELOT_PORT_MODE_SGMII | \34					 OCELOT_PORT_MODE_QSGMII | \35					 OCELOT_PORT_MODE_1000BASEX | \36					 OCELOT_PORT_MODE_2500BASEX | \37					 OCELOT_PORT_MODE_USXGMII)38 39static const u32 vsc9959_port_modes[VSC9959_NUM_PORTS] = {40	VSC9959_PORT_MODE_SERDES,41	VSC9959_PORT_MODE_SERDES,42	VSC9959_PORT_MODE_SERDES,43	VSC9959_PORT_MODE_SERDES,44	OCELOT_PORT_MODE_INTERNAL,45	OCELOT_PORT_MODE_INTERNAL,46};47 48static const u32 vsc9959_ana_regmap[] = {49	REG(ANA_ADVLEARN,			0x0089a0),50	REG(ANA_VLANMASK,			0x0089a4),51	REG_RESERVED(ANA_PORT_B_DOMAIN),52	REG(ANA_ANAGEFIL,			0x0089ac),53	REG(ANA_ANEVENTS,			0x0089b0),54	REG(ANA_STORMLIMIT_BURST,		0x0089b4),55	REG(ANA_STORMLIMIT_CFG,			0x0089b8),56	REG(ANA_ISOLATED_PORTS,			0x0089c8),57	REG(ANA_COMMUNITY_PORTS,		0x0089cc),58	REG(ANA_AUTOAGE,			0x0089d0),59	REG(ANA_MACTOPTIONS,			0x0089d4),60	REG(ANA_LEARNDISC,			0x0089d8),61	REG(ANA_AGENCTRL,			0x0089dc),62	REG(ANA_MIRRORPORTS,			0x0089e0),63	REG(ANA_EMIRRORPORTS,			0x0089e4),64	REG(ANA_FLOODING,			0x0089e8),65	REG(ANA_FLOODING_IPMC,			0x008a08),66	REG(ANA_SFLOW_CFG,			0x008a0c),67	REG(ANA_PORT_MODE,			0x008a28),68	REG(ANA_CUT_THRU_CFG,			0x008a48),69	REG(ANA_PGID_PGID,			0x008400),70	REG(ANA_TABLES_ANMOVED,			0x007f1c),71	REG(ANA_TABLES_MACHDATA,		0x007f20),72	REG(ANA_TABLES_MACLDATA,		0x007f24),73	REG(ANA_TABLES_STREAMDATA,		0x007f28),74	REG(ANA_TABLES_MACACCESS,		0x007f2c),75	REG(ANA_TABLES_MACTINDX,		0x007f30),76	REG(ANA_TABLES_VLANACCESS,		0x007f34),77	REG(ANA_TABLES_VLANTIDX,		0x007f38),78	REG(ANA_TABLES_ISDXACCESS,		0x007f3c),79	REG(ANA_TABLES_ISDXTIDX,		0x007f40),80	REG(ANA_TABLES_ENTRYLIM,		0x007f00),81	REG(ANA_TABLES_PTP_ID_HIGH,		0x007f44),82	REG(ANA_TABLES_PTP_ID_LOW,		0x007f48),83	REG(ANA_TABLES_STREAMACCESS,		0x007f4c),84	REG(ANA_TABLES_STREAMTIDX,		0x007f50),85	REG(ANA_TABLES_SEQ_HISTORY,		0x007f54),86	REG(ANA_TABLES_SEQ_MASK,		0x007f58),87	REG(ANA_TABLES_SFID_MASK,		0x007f5c),88	REG(ANA_TABLES_SFIDACCESS,		0x007f60),89	REG(ANA_TABLES_SFIDTIDX,		0x007f64),90	REG(ANA_MSTI_STATE,			0x008600),91	REG(ANA_OAM_UPM_LM_CNT,			0x008000),92	REG(ANA_SG_ACCESS_CTRL,			0x008a64),93	REG(ANA_SG_CONFIG_REG_1,		0x007fb0),94	REG(ANA_SG_CONFIG_REG_2,		0x007fb4),95	REG(ANA_SG_CONFIG_REG_3,		0x007fb8),96	REG(ANA_SG_CONFIG_REG_4,		0x007fbc),97	REG(ANA_SG_CONFIG_REG_5,		0x007fc0),98	REG(ANA_SG_GCL_GS_CONFIG,		0x007f80),99	REG(ANA_SG_GCL_TI_CONFIG,		0x007f90),100	REG(ANA_SG_STATUS_REG_1,		0x008980),101	REG(ANA_SG_STATUS_REG_2,		0x008984),102	REG(ANA_SG_STATUS_REG_3,		0x008988),103	REG(ANA_PORT_VLAN_CFG,			0x007800),104	REG(ANA_PORT_DROP_CFG,			0x007804),105	REG(ANA_PORT_QOS_CFG,			0x007808),106	REG(ANA_PORT_VCAP_CFG,			0x00780c),107	REG(ANA_PORT_VCAP_S1_KEY_CFG,		0x007810),108	REG(ANA_PORT_VCAP_S2_CFG,		0x00781c),109	REG(ANA_PORT_PCP_DEI_MAP,		0x007820),110	REG(ANA_PORT_CPU_FWD_CFG,		0x007860),111	REG(ANA_PORT_CPU_FWD_BPDU_CFG,		0x007864),112	REG(ANA_PORT_CPU_FWD_GARP_CFG,		0x007868),113	REG(ANA_PORT_CPU_FWD_CCM_CFG,		0x00786c),114	REG(ANA_PORT_PORT_CFG,			0x007870),115	REG(ANA_PORT_POL_CFG,			0x007874),116	REG(ANA_PORT_PTP_CFG,			0x007878),117	REG(ANA_PORT_PTP_DLY1_CFG,		0x00787c),118	REG(ANA_PORT_PTP_DLY2_CFG,		0x007880),119	REG(ANA_PORT_SFID_CFG,			0x007884),120	REG(ANA_PFC_PFC_CFG,			0x008800),121	REG_RESERVED(ANA_PFC_PFC_TIMER),122	REG_RESERVED(ANA_IPT_OAM_MEP_CFG),123	REG_RESERVED(ANA_IPT_IPT),124	REG_RESERVED(ANA_PPT_PPT),125	REG_RESERVED(ANA_FID_MAP_FID_MAP),126	REG(ANA_AGGR_CFG,			0x008a68),127	REG(ANA_CPUQ_CFG,			0x008a6c),128	REG_RESERVED(ANA_CPUQ_CFG2),129	REG(ANA_CPUQ_8021_CFG,			0x008a74),130	REG(ANA_DSCP_CFG,			0x008ab4),131	REG(ANA_DSCP_REWR_CFG,			0x008bb4),132	REG(ANA_VCAP_RNG_TYPE_CFG,		0x008bf4),133	REG(ANA_VCAP_RNG_VAL_CFG,		0x008c14),134	REG_RESERVED(ANA_VRAP_CFG),135	REG_RESERVED(ANA_VRAP_HDR_DATA),136	REG_RESERVED(ANA_VRAP_HDR_MASK),137	REG(ANA_DISCARD_CFG,			0x008c40),138	REG(ANA_FID_CFG,			0x008c44),139	REG(ANA_POL_PIR_CFG,			0x004000),140	REG(ANA_POL_CIR_CFG,			0x004004),141	REG(ANA_POL_MODE_CFG,			0x004008),142	REG(ANA_POL_PIR_STATE,			0x00400c),143	REG(ANA_POL_CIR_STATE,			0x004010),144	REG_RESERVED(ANA_POL_STATE),145	REG(ANA_POL_FLOWC,			0x008c48),146	REG(ANA_POL_HYST,			0x008cb4),147	REG_RESERVED(ANA_POL_MISC_CFG),148};149 150static const u32 vsc9959_qs_regmap[] = {151	REG(QS_XTR_GRP_CFG,			0x000000),152	REG(QS_XTR_RD,				0x000008),153	REG(QS_XTR_FRM_PRUNING,			0x000010),154	REG(QS_XTR_FLUSH,			0x000018),155	REG(QS_XTR_DATA_PRESENT,		0x00001c),156	REG(QS_XTR_CFG,				0x000020),157	REG(QS_INJ_GRP_CFG,			0x000024),158	REG(QS_INJ_WR,				0x00002c),159	REG(QS_INJ_CTRL,			0x000034),160	REG(QS_INJ_STATUS,			0x00003c),161	REG(QS_INJ_ERR,				0x000040),162	REG_RESERVED(QS_INH_DBG),163};164 165static const u32 vsc9959_vcap_regmap[] = {166	/* VCAP_CORE_CFG */167	REG(VCAP_CORE_UPDATE_CTRL,		0x000000),168	REG(VCAP_CORE_MV_CFG,			0x000004),169	/* VCAP_CORE_CACHE */170	REG(VCAP_CACHE_ENTRY_DAT,		0x000008),171	REG(VCAP_CACHE_MASK_DAT,		0x000108),172	REG(VCAP_CACHE_ACTION_DAT,		0x000208),173	REG(VCAP_CACHE_CNT_DAT,			0x000308),174	REG(VCAP_CACHE_TG_DAT,			0x000388),175	/* VCAP_CONST */176	REG(VCAP_CONST_VCAP_VER,		0x000398),177	REG(VCAP_CONST_ENTRY_WIDTH,		0x00039c),178	REG(VCAP_CONST_ENTRY_CNT,		0x0003a0),179	REG(VCAP_CONST_ENTRY_SWCNT,		0x0003a4),180	REG(VCAP_CONST_ENTRY_TG_WIDTH,		0x0003a8),181	REG(VCAP_CONST_ACTION_DEF_CNT,		0x0003ac),182	REG(VCAP_CONST_ACTION_WIDTH,		0x0003b0),183	REG(VCAP_CONST_CNT_WIDTH,		0x0003b4),184	REG(VCAP_CONST_CORE_CNT,		0x0003b8),185	REG(VCAP_CONST_IF_CNT,			0x0003bc),186};187 188static const u32 vsc9959_qsys_regmap[] = {189	REG(QSYS_PORT_MODE,			0x00f460),190	REG(QSYS_SWITCH_PORT_MODE,		0x00f480),191	REG(QSYS_STAT_CNT_CFG,			0x00f49c),192	REG(QSYS_EEE_CFG,			0x00f4a0),193	REG(QSYS_EEE_THRES,			0x00f4b8),194	REG(QSYS_IGR_NO_SHARING,		0x00f4bc),195	REG(QSYS_EGR_NO_SHARING,		0x00f4c0),196	REG(QSYS_SW_STATUS,			0x00f4c4),197	REG(QSYS_EXT_CPU_CFG,			0x00f4e0),198	REG_RESERVED(QSYS_PAD_CFG),199	REG(QSYS_CPU_GROUP_MAP,			0x00f4e8),200	REG_RESERVED(QSYS_QMAP),201	REG_RESERVED(QSYS_ISDX_SGRP),202	REG_RESERVED(QSYS_TIMED_FRAME_ENTRY),203	REG(QSYS_TFRM_MISC,			0x00f50c),204	REG(QSYS_TFRM_PORT_DLY,			0x00f510),205	REG(QSYS_TFRM_TIMER_CFG_1,		0x00f514),206	REG(QSYS_TFRM_TIMER_CFG_2,		0x00f518),207	REG(QSYS_TFRM_TIMER_CFG_3,		0x00f51c),208	REG(QSYS_TFRM_TIMER_CFG_4,		0x00f520),209	REG(QSYS_TFRM_TIMER_CFG_5,		0x00f524),210	REG(QSYS_TFRM_TIMER_CFG_6,		0x00f528),211	REG(QSYS_TFRM_TIMER_CFG_7,		0x00f52c),212	REG(QSYS_TFRM_TIMER_CFG_8,		0x00f530),213	REG(QSYS_RED_PROFILE,			0x00f534),214	REG(QSYS_RES_QOS_MODE,			0x00f574),215	REG(QSYS_RES_CFG,			0x00c000),216	REG(QSYS_RES_STAT,			0x00c004),217	REG(QSYS_EGR_DROP_MODE,			0x00f578),218	REG(QSYS_EQ_CTRL,			0x00f57c),219	REG_RESERVED(QSYS_EVENTS_CORE),220	REG(QSYS_QMAXSDU_CFG_0,			0x00f584),221	REG(QSYS_QMAXSDU_CFG_1,			0x00f5a0),222	REG(QSYS_QMAXSDU_CFG_2,			0x00f5bc),223	REG(QSYS_QMAXSDU_CFG_3,			0x00f5d8),224	REG(QSYS_QMAXSDU_CFG_4,			0x00f5f4),225	REG(QSYS_QMAXSDU_CFG_5,			0x00f610),226	REG(QSYS_QMAXSDU_CFG_6,			0x00f62c),227	REG(QSYS_QMAXSDU_CFG_7,			0x00f648),228	REG(QSYS_PREEMPTION_CFG,		0x00f664),229	REG(QSYS_CIR_CFG,			0x000000),230	REG(QSYS_EIR_CFG,			0x000004),231	REG(QSYS_SE_CFG,			0x000008),232	REG(QSYS_SE_DWRR_CFG,			0x00000c),233	REG_RESERVED(QSYS_SE_CONNECT),234	REG(QSYS_SE_DLB_SENSE,			0x000040),235	REG(QSYS_CIR_STATE,			0x000044),236	REG(QSYS_EIR_STATE,			0x000048),237	REG_RESERVED(QSYS_SE_STATE),238	REG(QSYS_HSCH_MISC_CFG,			0x00f67c),239	REG(QSYS_TAG_CONFIG,			0x00f680),240	REG(QSYS_TAS_PARAM_CFG_CTRL,		0x00f698),241	REG(QSYS_PORT_MAX_SDU,			0x00f69c),242	REG(QSYS_PARAM_CFG_REG_1,		0x00f440),243	REG(QSYS_PARAM_CFG_REG_2,		0x00f444),244	REG(QSYS_PARAM_CFG_REG_3,		0x00f448),245	REG(QSYS_PARAM_CFG_REG_4,		0x00f44c),246	REG(QSYS_PARAM_CFG_REG_5,		0x00f450),247	REG(QSYS_GCL_CFG_REG_1,			0x00f454),248	REG(QSYS_GCL_CFG_REG_2,			0x00f458),249	REG(QSYS_PARAM_STATUS_REG_1,		0x00f400),250	REG(QSYS_PARAM_STATUS_REG_2,		0x00f404),251	REG(QSYS_PARAM_STATUS_REG_3,		0x00f408),252	REG(QSYS_PARAM_STATUS_REG_4,		0x00f40c),253	REG(QSYS_PARAM_STATUS_REG_5,		0x00f410),254	REG(QSYS_PARAM_STATUS_REG_6,		0x00f414),255	REG(QSYS_PARAM_STATUS_REG_7,		0x00f418),256	REG(QSYS_PARAM_STATUS_REG_8,		0x00f41c),257	REG(QSYS_PARAM_STATUS_REG_9,		0x00f420),258	REG(QSYS_GCL_STATUS_REG_1,		0x00f424),259	REG(QSYS_GCL_STATUS_REG_2,		0x00f428),260};261 262static const u32 vsc9959_rew_regmap[] = {263	REG(REW_PORT_VLAN_CFG,			0x000000),264	REG(REW_TAG_CFG,			0x000004),265	REG(REW_PORT_CFG,			0x000008),266	REG(REW_DSCP_CFG,			0x00000c),267	REG(REW_PCP_DEI_QOS_MAP_CFG,		0x000010),268	REG(REW_PTP_CFG,			0x000050),269	REG(REW_PTP_DLY1_CFG,			0x000054),270	REG(REW_RED_TAG_CFG,			0x000058),271	REG(REW_DSCP_REMAP_DP1_CFG,		0x000410),272	REG(REW_DSCP_REMAP_CFG,			0x000510),273	REG_RESERVED(REW_STAT_CFG),274	REG_RESERVED(REW_REW_STICKY),275	REG_RESERVED(REW_PPT),276};277 278static const u32 vsc9959_sys_regmap[] = {279	REG(SYS_COUNT_RX_OCTETS,		0x000000),280	REG(SYS_COUNT_RX_UNICAST,		0x000004),281	REG(SYS_COUNT_RX_MULTICAST,		0x000008),282	REG(SYS_COUNT_RX_BROADCAST,		0x00000c),283	REG(SYS_COUNT_RX_SHORTS,		0x000010),284	REG(SYS_COUNT_RX_FRAGMENTS,		0x000014),285	REG(SYS_COUNT_RX_JABBERS,		0x000018),286	REG(SYS_COUNT_RX_CRC_ALIGN_ERRS,	0x00001c),287	REG(SYS_COUNT_RX_SYM_ERRS,		0x000020),288	REG(SYS_COUNT_RX_64,			0x000024),289	REG(SYS_COUNT_RX_65_127,		0x000028),290	REG(SYS_COUNT_RX_128_255,		0x00002c),291	REG(SYS_COUNT_RX_256_511,		0x000030),292	REG(SYS_COUNT_RX_512_1023,		0x000034),293	REG(SYS_COUNT_RX_1024_1526,		0x000038),294	REG(SYS_COUNT_RX_1527_MAX,		0x00003c),295	REG(SYS_COUNT_RX_PAUSE,			0x000040),296	REG(SYS_COUNT_RX_CONTROL,		0x000044),297	REG(SYS_COUNT_RX_LONGS,			0x000048),298	REG(SYS_COUNT_RX_CLASSIFIED_DROPS,	0x00004c),299	REG(SYS_COUNT_RX_RED_PRIO_0,		0x000050),300	REG(SYS_COUNT_RX_RED_PRIO_1,		0x000054),301	REG(SYS_COUNT_RX_RED_PRIO_2,		0x000058),302	REG(SYS_COUNT_RX_RED_PRIO_3,		0x00005c),303	REG(SYS_COUNT_RX_RED_PRIO_4,		0x000060),304	REG(SYS_COUNT_RX_RED_PRIO_5,		0x000064),305	REG(SYS_COUNT_RX_RED_PRIO_6,		0x000068),306	REG(SYS_COUNT_RX_RED_PRIO_7,		0x00006c),307	REG(SYS_COUNT_RX_YELLOW_PRIO_0,		0x000070),308	REG(SYS_COUNT_RX_YELLOW_PRIO_1,		0x000074),309	REG(SYS_COUNT_RX_YELLOW_PRIO_2,		0x000078),310	REG(SYS_COUNT_RX_YELLOW_PRIO_3,		0x00007c),311	REG(SYS_COUNT_RX_YELLOW_PRIO_4,		0x000080),312	REG(SYS_COUNT_RX_YELLOW_PRIO_5,		0x000084),313	REG(SYS_COUNT_RX_YELLOW_PRIO_6,		0x000088),314	REG(SYS_COUNT_RX_YELLOW_PRIO_7,		0x00008c),315	REG(SYS_COUNT_RX_GREEN_PRIO_0,		0x000090),316	REG(SYS_COUNT_RX_GREEN_PRIO_1,		0x000094),317	REG(SYS_COUNT_RX_GREEN_PRIO_2,		0x000098),318	REG(SYS_COUNT_RX_GREEN_PRIO_3,		0x00009c),319	REG(SYS_COUNT_RX_GREEN_PRIO_4,		0x0000a0),320	REG(SYS_COUNT_RX_GREEN_PRIO_5,		0x0000a4),321	REG(SYS_COUNT_RX_GREEN_PRIO_6,		0x0000a8),322	REG(SYS_COUNT_RX_GREEN_PRIO_7,		0x0000ac),323	REG(SYS_COUNT_RX_ASSEMBLY_ERRS,		0x0000b0),324	REG(SYS_COUNT_RX_SMD_ERRS,		0x0000b4),325	REG(SYS_COUNT_RX_ASSEMBLY_OK,		0x0000b8),326	REG(SYS_COUNT_RX_MERGE_FRAGMENTS,	0x0000bc),327	REG(SYS_COUNT_RX_PMAC_OCTETS,		0x0000c0),328	REG(SYS_COUNT_RX_PMAC_UNICAST,		0x0000c4),329	REG(SYS_COUNT_RX_PMAC_MULTICAST,	0x0000c8),330	REG(SYS_COUNT_RX_PMAC_BROADCAST,	0x0000cc),331	REG(SYS_COUNT_RX_PMAC_SHORTS,		0x0000d0),332	REG(SYS_COUNT_RX_PMAC_FRAGMENTS,	0x0000d4),333	REG(SYS_COUNT_RX_PMAC_JABBERS,		0x0000d8),334	REG(SYS_COUNT_RX_PMAC_CRC_ALIGN_ERRS,	0x0000dc),335	REG(SYS_COUNT_RX_PMAC_SYM_ERRS,		0x0000e0),336	REG(SYS_COUNT_RX_PMAC_64,		0x0000e4),337	REG(SYS_COUNT_RX_PMAC_65_127,		0x0000e8),338	REG(SYS_COUNT_RX_PMAC_128_255,		0x0000ec),339	REG(SYS_COUNT_RX_PMAC_256_511,		0x0000f0),340	REG(SYS_COUNT_RX_PMAC_512_1023,		0x0000f4),341	REG(SYS_COUNT_RX_PMAC_1024_1526,	0x0000f8),342	REG(SYS_COUNT_RX_PMAC_1527_MAX,		0x0000fc),343	REG(SYS_COUNT_RX_PMAC_PAUSE,		0x000100),344	REG(SYS_COUNT_RX_PMAC_CONTROL,		0x000104),345	REG(SYS_COUNT_RX_PMAC_LONGS,		0x000108),346	REG(SYS_COUNT_TX_OCTETS,		0x000200),347	REG(SYS_COUNT_TX_UNICAST,		0x000204),348	REG(SYS_COUNT_TX_MULTICAST,		0x000208),349	REG(SYS_COUNT_TX_BROADCAST,		0x00020c),350	REG(SYS_COUNT_TX_COLLISION,		0x000210),351	REG(SYS_COUNT_TX_DROPS,			0x000214),352	REG(SYS_COUNT_TX_PAUSE,			0x000218),353	REG(SYS_COUNT_TX_64,			0x00021c),354	REG(SYS_COUNT_TX_65_127,		0x000220),355	REG(SYS_COUNT_TX_128_255,		0x000224),356	REG(SYS_COUNT_TX_256_511,		0x000228),357	REG(SYS_COUNT_TX_512_1023,		0x00022c),358	REG(SYS_COUNT_TX_1024_1526,		0x000230),359	REG(SYS_COUNT_TX_1527_MAX,		0x000234),360	REG(SYS_COUNT_TX_YELLOW_PRIO_0,		0x000238),361	REG(SYS_COUNT_TX_YELLOW_PRIO_1,		0x00023c),362	REG(SYS_COUNT_TX_YELLOW_PRIO_2,		0x000240),363	REG(SYS_COUNT_TX_YELLOW_PRIO_3,		0x000244),364	REG(SYS_COUNT_TX_YELLOW_PRIO_4,		0x000248),365	REG(SYS_COUNT_TX_YELLOW_PRIO_5,		0x00024c),366	REG(SYS_COUNT_TX_YELLOW_PRIO_6,		0x000250),367	REG(SYS_COUNT_TX_YELLOW_PRIO_7,		0x000254),368	REG(SYS_COUNT_TX_GREEN_PRIO_0,		0x000258),369	REG(SYS_COUNT_TX_GREEN_PRIO_1,		0x00025c),370	REG(SYS_COUNT_TX_GREEN_PRIO_2,		0x000260),371	REG(SYS_COUNT_TX_GREEN_PRIO_3,		0x000264),372	REG(SYS_COUNT_TX_GREEN_PRIO_4,		0x000268),373	REG(SYS_COUNT_TX_GREEN_PRIO_5,		0x00026c),374	REG(SYS_COUNT_TX_GREEN_PRIO_6,		0x000270),375	REG(SYS_COUNT_TX_GREEN_PRIO_7,		0x000274),376	REG(SYS_COUNT_TX_AGED,			0x000278),377	REG(SYS_COUNT_TX_MM_HOLD,		0x00027c),378	REG(SYS_COUNT_TX_MERGE_FRAGMENTS,	0x000280),379	REG(SYS_COUNT_TX_PMAC_OCTETS,		0x000284),380	REG(SYS_COUNT_TX_PMAC_UNICAST,		0x000288),381	REG(SYS_COUNT_TX_PMAC_MULTICAST,	0x00028c),382	REG(SYS_COUNT_TX_PMAC_BROADCAST,	0x000290),383	REG(SYS_COUNT_TX_PMAC_PAUSE,		0x000294),384	REG(SYS_COUNT_TX_PMAC_64,		0x000298),385	REG(SYS_COUNT_TX_PMAC_65_127,		0x00029c),386	REG(SYS_COUNT_TX_PMAC_128_255,		0x0002a0),387	REG(SYS_COUNT_TX_PMAC_256_511,		0x0002a4),388	REG(SYS_COUNT_TX_PMAC_512_1023,		0x0002a8),389	REG(SYS_COUNT_TX_PMAC_1024_1526,	0x0002ac),390	REG(SYS_COUNT_TX_PMAC_1527_MAX,		0x0002b0),391	REG(SYS_COUNT_DROP_LOCAL,		0x000400),392	REG(SYS_COUNT_DROP_TAIL,		0x000404),393	REG(SYS_COUNT_DROP_YELLOW_PRIO_0,	0x000408),394	REG(SYS_COUNT_DROP_YELLOW_PRIO_1,	0x00040c),395	REG(SYS_COUNT_DROP_YELLOW_PRIO_2,	0x000410),396	REG(SYS_COUNT_DROP_YELLOW_PRIO_3,	0x000414),397	REG(SYS_COUNT_DROP_YELLOW_PRIO_4,	0x000418),398	REG(SYS_COUNT_DROP_YELLOW_PRIO_5,	0x00041c),399	REG(SYS_COUNT_DROP_YELLOW_PRIO_6,	0x000420),400	REG(SYS_COUNT_DROP_YELLOW_PRIO_7,	0x000424),401	REG(SYS_COUNT_DROP_GREEN_PRIO_0,	0x000428),402	REG(SYS_COUNT_DROP_GREEN_PRIO_1,	0x00042c),403	REG(SYS_COUNT_DROP_GREEN_PRIO_2,	0x000430),404	REG(SYS_COUNT_DROP_GREEN_PRIO_3,	0x000434),405	REG(SYS_COUNT_DROP_GREEN_PRIO_4,	0x000438),406	REG(SYS_COUNT_DROP_GREEN_PRIO_5,	0x00043c),407	REG(SYS_COUNT_DROP_GREEN_PRIO_6,	0x000440),408	REG(SYS_COUNT_DROP_GREEN_PRIO_7,	0x000444),409	REG(SYS_COUNT_SF_MATCHING_FRAMES,	0x000800),410	REG(SYS_COUNT_SF_NOT_PASSING_FRAMES,	0x000804),411	REG(SYS_COUNT_SF_NOT_PASSING_SDU,	0x000808),412	REG(SYS_COUNT_SF_RED_FRAMES,		0x00080c),413	REG(SYS_RESET_CFG,			0x000e00),414	REG(SYS_SR_ETYPE_CFG,			0x000e04),415	REG(SYS_VLAN_ETYPE_CFG,			0x000e08),416	REG(SYS_PORT_MODE,			0x000e0c),417	REG(SYS_FRONT_PORT_MODE,		0x000e2c),418	REG(SYS_FRM_AGING,			0x000e44),419	REG(SYS_STAT_CFG,			0x000e48),420	REG(SYS_SW_STATUS,			0x000e4c),421	REG_RESERVED(SYS_MISC_CFG),422	REG(SYS_REW_MAC_HIGH_CFG,		0x000e6c),423	REG(SYS_REW_MAC_LOW_CFG,		0x000e84),424	REG(SYS_TIMESTAMP_OFFSET,		0x000e9c),425	REG(SYS_PAUSE_CFG,			0x000ea0),426	REG(SYS_PAUSE_TOT_CFG,			0x000ebc),427	REG(SYS_ATOP,				0x000ec0),428	REG(SYS_ATOP_TOT_CFG,			0x000edc),429	REG(SYS_MAC_FC_CFG,			0x000ee0),430	REG(SYS_MMGT,				0x000ef8),431	REG_RESERVED(SYS_MMGT_FAST),432	REG_RESERVED(SYS_EVENTS_DIF),433	REG_RESERVED(SYS_EVENTS_CORE),434	REG(SYS_PTP_STATUS,			0x000f14),435	REG(SYS_PTP_TXSTAMP,			0x000f18),436	REG(SYS_PTP_NXT,			0x000f1c),437	REG(SYS_PTP_CFG,			0x000f20),438	REG(SYS_RAM_INIT,			0x000f24),439	REG_RESERVED(SYS_CM_ADDR),440	REG_RESERVED(SYS_CM_DATA_WR),441	REG_RESERVED(SYS_CM_DATA_RD),442	REG_RESERVED(SYS_CM_OP),443	REG_RESERVED(SYS_CM_DATA),444};445 446static const u32 vsc9959_ptp_regmap[] = {447	REG(PTP_PIN_CFG,			0x000000),448	REG(PTP_PIN_TOD_SEC_MSB,		0x000004),449	REG(PTP_PIN_TOD_SEC_LSB,		0x000008),450	REG(PTP_PIN_TOD_NSEC,			0x00000c),451	REG(PTP_PIN_WF_HIGH_PERIOD,		0x000014),452	REG(PTP_PIN_WF_LOW_PERIOD,		0x000018),453	REG(PTP_CFG_MISC,			0x0000a0),454	REG(PTP_CLK_CFG_ADJ_CFG,		0x0000a4),455	REG(PTP_CLK_CFG_ADJ_FREQ,		0x0000a8),456};457 458static const u32 vsc9959_gcb_regmap[] = {459	REG(GCB_SOFT_RST,			0x000004),460};461 462static const u32 vsc9959_dev_gmii_regmap[] = {463	REG(DEV_CLOCK_CFG,			0x0),464	REG(DEV_PORT_MISC,			0x4),465	REG(DEV_EVENTS,				0x8),466	REG(DEV_EEE_CFG,			0xc),467	REG(DEV_RX_PATH_DELAY,			0x10),468	REG(DEV_TX_PATH_DELAY,			0x14),469	REG(DEV_PTP_PREDICT_CFG,		0x18),470	REG(DEV_MAC_ENA_CFG,			0x1c),471	REG(DEV_MAC_MODE_CFG,			0x20),472	REG(DEV_MAC_MAXLEN_CFG,			0x24),473	REG(DEV_MAC_TAGS_CFG,			0x28),474	REG(DEV_MAC_ADV_CHK_CFG,		0x2c),475	REG(DEV_MAC_IFG_CFG,			0x30),476	REG(DEV_MAC_HDX_CFG,			0x34),477	REG(DEV_MAC_DBG_CFG,			0x38),478	REG(DEV_MAC_FC_MAC_LOW_CFG,		0x3c),479	REG(DEV_MAC_FC_MAC_HIGH_CFG,		0x40),480	REG(DEV_MAC_STICKY,			0x44),481	REG(DEV_MM_ENABLE_CONFIG,		0x48),482	REG(DEV_MM_VERIF_CONFIG,		0x4C),483	REG(DEV_MM_STATUS,			0x50),484	REG_RESERVED(PCS1G_CFG),485	REG_RESERVED(PCS1G_MODE_CFG),486	REG_RESERVED(PCS1G_SD_CFG),487	REG_RESERVED(PCS1G_ANEG_CFG),488	REG_RESERVED(PCS1G_ANEG_NP_CFG),489	REG_RESERVED(PCS1G_LB_CFG),490	REG_RESERVED(PCS1G_DBG_CFG),491	REG_RESERVED(PCS1G_CDET_CFG),492	REG_RESERVED(PCS1G_ANEG_STATUS),493	REG_RESERVED(PCS1G_ANEG_NP_STATUS),494	REG_RESERVED(PCS1G_LINK_STATUS),495	REG_RESERVED(PCS1G_LINK_DOWN_CNT),496	REG_RESERVED(PCS1G_STICKY),497	REG_RESERVED(PCS1G_DEBUG_STATUS),498	REG_RESERVED(PCS1G_LPI_CFG),499	REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT),500	REG_RESERVED(PCS1G_LPI_STATUS),501	REG_RESERVED(PCS1G_TSTPAT_MODE_CFG),502	REG_RESERVED(PCS1G_TSTPAT_STATUS),503	REG_RESERVED(DEV_PCS_FX100_CFG),504	REG_RESERVED(DEV_PCS_FX100_STATUS),505};506 507static const u32 *vsc9959_regmap[TARGET_MAX] = {508	[ANA]	= vsc9959_ana_regmap,509	[QS]	= vsc9959_qs_regmap,510	[QSYS]	= vsc9959_qsys_regmap,511	[REW]	= vsc9959_rew_regmap,512	[SYS]	= vsc9959_sys_regmap,513	[S0]	= vsc9959_vcap_regmap,514	[S1]	= vsc9959_vcap_regmap,515	[S2]	= vsc9959_vcap_regmap,516	[PTP]	= vsc9959_ptp_regmap,517	[GCB]	= vsc9959_gcb_regmap,518	[DEV_GMII] = vsc9959_dev_gmii_regmap,519};520 521/* Addresses are relative to the PCI device's base address */522static const struct resource vsc9959_resources[] = {523	DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),524	DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),525	DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),526	DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),527	DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),528	DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),529	DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),530	DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),531	DEFINE_RES_MEM_NAMED(0x0100000, 0x0010000, "port0"),532	DEFINE_RES_MEM_NAMED(0x0110000, 0x0010000, "port1"),533	DEFINE_RES_MEM_NAMED(0x0120000, 0x0010000, "port2"),534	DEFINE_RES_MEM_NAMED(0x0130000, 0x0010000, "port3"),535	DEFINE_RES_MEM_NAMED(0x0140000, 0x0010000, "port4"),536	DEFINE_RES_MEM_NAMED(0x0150000, 0x0010000, "port5"),537	DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),538	DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),539};540 541static const char * const vsc9959_resource_names[TARGET_MAX] = {542	[SYS] = "sys",543	[REW] = "rew",544	[S0] = "s0",545	[S1] = "s1",546	[S2] = "s2",547	[GCB] = "devcpu_gcb",548	[QS] = "qs",549	[PTP] = "ptp",550	[QSYS] = "qsys",551	[ANA] = "ana",552};553 554/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an555 * SGMII/QSGMII MAC PCS can be found.556 */557static const struct resource vsc9959_imdio_res =558	DEFINE_RES_MEM_NAMED(0x8030, 0x10, "imdio");559 560static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {561	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),562	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),563	[ANA_ANEVENTS_FLOOD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 30, 30),564	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 26, 26),565	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 24, 24),566	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 23, 23),567	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 22, 22),568	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 21, 21),569	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 20, 20),570	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 19, 19),571	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 18, 18),572	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 17, 17),573	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 15, 15),574	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 14, 14),575	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 13, 13),576	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 12, 12),577	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 11, 11),578	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 10, 10),579	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 9, 9),580	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 8, 8),581	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 7, 7),582	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),583	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),584	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 4, 4),585	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 3, 3),586	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 2, 2),587	[ANA_ANEVENTS_SEQ_GEN_ERR_0] = REG_FIELD(ANA_ANEVENTS, 1, 1),588	[ANA_ANEVENTS_SEQ_GEN_ERR_1] = REG_FIELD(ANA_ANEVENTS, 0, 0),589	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 16, 16),590	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 11, 12),591	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10),592	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 0, 0),593	[GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),594	/* Replicated per number of ports (7), register size 4 per port */595	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 7, 4),596	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 7, 4),597	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 7, 4),598	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 7, 4),599	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 7, 4),600	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 7, 4),601	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 7, 4),602	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4),603	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4),604	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4),605	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 7, 4),606	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 7, 4),607	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4),608};609 610static const struct vcap_field vsc9959_vcap_es0_keys[] = {611	[VCAP_ES0_EGR_PORT]			= {  0,  3},612	[VCAP_ES0_IGR_PORT]			= {  3,  3},613	[VCAP_ES0_RSV]				= {  6,  2},614	[VCAP_ES0_L2_MC]			= {  8,  1},615	[VCAP_ES0_L2_BC]			= {  9,  1},616	[VCAP_ES0_VID]				= { 10, 12},617	[VCAP_ES0_DP]				= { 22,  1},618	[VCAP_ES0_PCP]				= { 23,  3},619};620 621static const struct vcap_field vsc9959_vcap_es0_actions[] = {622	[VCAP_ES0_ACT_PUSH_OUTER_TAG]		= {  0,  2},623	[VCAP_ES0_ACT_PUSH_INNER_TAG]		= {  2,  1},624	[VCAP_ES0_ACT_TAG_A_TPID_SEL]		= {  3,  2},625	[VCAP_ES0_ACT_TAG_A_VID_SEL]		= {  5,  1},626	[VCAP_ES0_ACT_TAG_A_PCP_SEL]		= {  6,  2},627	[VCAP_ES0_ACT_TAG_A_DEI_SEL]		= {  8,  2},628	[VCAP_ES0_ACT_TAG_B_TPID_SEL]		= { 10,  2},629	[VCAP_ES0_ACT_TAG_B_VID_SEL]		= { 12,  1},630	[VCAP_ES0_ACT_TAG_B_PCP_SEL]		= { 13,  2},631	[VCAP_ES0_ACT_TAG_B_DEI_SEL]		= { 15,  2},632	[VCAP_ES0_ACT_VID_A_VAL]		= { 17, 12},633	[VCAP_ES0_ACT_PCP_A_VAL]		= { 29,  3},634	[VCAP_ES0_ACT_DEI_A_VAL]		= { 32,  1},635	[VCAP_ES0_ACT_VID_B_VAL]		= { 33, 12},636	[VCAP_ES0_ACT_PCP_B_VAL]		= { 45,  3},637	[VCAP_ES0_ACT_DEI_B_VAL]		= { 48,  1},638	[VCAP_ES0_ACT_RSV]			= { 49, 23},639	[VCAP_ES0_ACT_HIT_STICKY]		= { 72,  1},640};641 642static const struct vcap_field vsc9959_vcap_is1_keys[] = {643	[VCAP_IS1_HK_TYPE]			= {  0,   1},644	[VCAP_IS1_HK_LOOKUP]			= {  1,   2},645	[VCAP_IS1_HK_IGR_PORT_MASK]		= {  3,   7},646	[VCAP_IS1_HK_RSV]			= { 10,   9},647	[VCAP_IS1_HK_OAM_Y1731]			= { 19,   1},648	[VCAP_IS1_HK_L2_MC]			= { 20,   1},649	[VCAP_IS1_HK_L2_BC]			= { 21,   1},650	[VCAP_IS1_HK_IP_MC]			= { 22,   1},651	[VCAP_IS1_HK_VLAN_TAGGED]		= { 23,   1},652	[VCAP_IS1_HK_VLAN_DBL_TAGGED]		= { 24,   1},653	[VCAP_IS1_HK_TPID]			= { 25,   1},654	[VCAP_IS1_HK_VID]			= { 26,  12},655	[VCAP_IS1_HK_DEI]			= { 38,   1},656	[VCAP_IS1_HK_PCP]			= { 39,   3},657	/* Specific Fields for IS1 Half Key S1_NORMAL */658	[VCAP_IS1_HK_L2_SMAC]			= { 42,  48},659	[VCAP_IS1_HK_ETYPE_LEN]			= { 90,   1},660	[VCAP_IS1_HK_ETYPE]			= { 91,  16},661	[VCAP_IS1_HK_IP_SNAP]			= {107,   1},662	[VCAP_IS1_HK_IP4]			= {108,   1},663	/* Layer-3 Information */664	[VCAP_IS1_HK_L3_FRAGMENT]		= {109,   1},665	[VCAP_IS1_HK_L3_FRAG_OFS_GT0]		= {110,   1},666	[VCAP_IS1_HK_L3_OPTIONS]		= {111,   1},667	[VCAP_IS1_HK_L3_DSCP]			= {112,   6},668	[VCAP_IS1_HK_L3_IP4_SIP]		= {118,  32},669	/* Layer-4 Information */670	[VCAP_IS1_HK_TCP_UDP]			= {150,   1},671	[VCAP_IS1_HK_TCP]			= {151,   1},672	[VCAP_IS1_HK_L4_SPORT]			= {152,  16},673	[VCAP_IS1_HK_L4_RNG]			= {168,   8},674	/* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */675	[VCAP_IS1_HK_IP4_INNER_TPID]            = { 42,   1},676	[VCAP_IS1_HK_IP4_INNER_VID]		= { 43,  12},677	[VCAP_IS1_HK_IP4_INNER_DEI]		= { 55,   1},678	[VCAP_IS1_HK_IP4_INNER_PCP]		= { 56,   3},679	[VCAP_IS1_HK_IP4_IP4]			= { 59,   1},680	[VCAP_IS1_HK_IP4_L3_FRAGMENT]		= { 60,   1},681	[VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0]	= { 61,   1},682	[VCAP_IS1_HK_IP4_L3_OPTIONS]		= { 62,   1},683	[VCAP_IS1_HK_IP4_L3_DSCP]		= { 63,   6},684	[VCAP_IS1_HK_IP4_L3_IP4_DIP]		= { 69,  32},685	[VCAP_IS1_HK_IP4_L3_IP4_SIP]		= {101,  32},686	[VCAP_IS1_HK_IP4_L3_PROTO]		= {133,   8},687	[VCAP_IS1_HK_IP4_TCP_UDP]		= {141,   1},688	[VCAP_IS1_HK_IP4_TCP]			= {142,   1},689	[VCAP_IS1_HK_IP4_L4_RNG]		= {143,   8},690	[VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE]	= {151,  32},691};692 693static const struct vcap_field vsc9959_vcap_is1_actions[] = {694	[VCAP_IS1_ACT_DSCP_ENA]			= {  0,  1},695	[VCAP_IS1_ACT_DSCP_VAL]			= {  1,  6},696	[VCAP_IS1_ACT_QOS_ENA]			= {  7,  1},697	[VCAP_IS1_ACT_QOS_VAL]			= {  8,  3},698	[VCAP_IS1_ACT_DP_ENA]			= { 11,  1},699	[VCAP_IS1_ACT_DP_VAL]			= { 12,  1},700	[VCAP_IS1_ACT_PAG_OVERRIDE_MASK]	= { 13,  8},701	[VCAP_IS1_ACT_PAG_VAL]			= { 21,  8},702	[VCAP_IS1_ACT_RSV]			= { 29,  9},703	/* The fields below are incorrectly shifted by 2 in the manual */704	[VCAP_IS1_ACT_VID_REPLACE_ENA]		= { 38,  1},705	[VCAP_IS1_ACT_VID_ADD_VAL]		= { 39, 12},706	[VCAP_IS1_ACT_FID_SEL]			= { 51,  2},707	[VCAP_IS1_ACT_FID_VAL]			= { 53, 13},708	[VCAP_IS1_ACT_PCP_DEI_ENA]		= { 66,  1},709	[VCAP_IS1_ACT_PCP_VAL]			= { 67,  3},710	[VCAP_IS1_ACT_DEI_VAL]			= { 70,  1},711	[VCAP_IS1_ACT_VLAN_POP_CNT_ENA]		= { 71,  1},712	[VCAP_IS1_ACT_VLAN_POP_CNT]		= { 72,  2},713	[VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA]	= { 74,  4},714	[VCAP_IS1_ACT_HIT_STICKY]		= { 78,  1},715};716 717static struct vcap_field vsc9959_vcap_is2_keys[] = {718	/* Common: 41 bits */719	[VCAP_IS2_TYPE]				= {  0,   4},720	[VCAP_IS2_HK_FIRST]			= {  4,   1},721	[VCAP_IS2_HK_PAG]			= {  5,   8},722	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,   7},723	[VCAP_IS2_HK_RSV2]			= { 20,   1},724	[VCAP_IS2_HK_HOST_MATCH]		= { 21,   1},725	[VCAP_IS2_HK_L2_MC]			= { 22,   1},726	[VCAP_IS2_HK_L2_BC]			= { 23,   1},727	[VCAP_IS2_HK_VLAN_TAGGED]		= { 24,   1},728	[VCAP_IS2_HK_VID]			= { 25,  12},729	[VCAP_IS2_HK_DEI]			= { 37,   1},730	[VCAP_IS2_HK_PCP]			= { 38,   3},731	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */732	[VCAP_IS2_HK_L2_DMAC]			= { 41,  48},733	[VCAP_IS2_HK_L2_SMAC]			= { 89,  48},734	/* MAC_ETYPE (TYPE=000) */735	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {137,  16},736	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {153,  16},737	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {169,   8},738	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {177,   3},739	/* MAC_LLC (TYPE=001) */740	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {137,  40},741	/* MAC_SNAP (TYPE=010) */742	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {137,  40},743	/* MAC_ARP (TYPE=011) */744	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 41,  48},745	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 89,   1},746	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 90,   1},747	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 91,   1},748	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 92,   1},749	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 93,   1},750	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 94,   1},751	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= { 95,   2},752	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= { 97,  32},753	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {129,  32},754	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {161,   1},755	/* IP4_TCP_UDP / IP4_OTHER common */756	[VCAP_IS2_HK_IP4]			= { 41,   1},757	[VCAP_IS2_HK_L3_FRAGMENT]		= { 42,   1},758	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 43,   1},759	[VCAP_IS2_HK_L3_OPTIONS]		= { 44,   1},760	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 45,   1},761	[VCAP_IS2_HK_L3_TOS]			= { 46,   8},762	[VCAP_IS2_HK_L3_IP4_DIP]		= { 54,  32},763	[VCAP_IS2_HK_L3_IP4_SIP]		= { 86,  32},764	[VCAP_IS2_HK_DIP_EQ_SIP]		= {118,   1},765	/* IP4_TCP_UDP (TYPE=100) */766	[VCAP_IS2_HK_TCP]			= {119,   1},767	[VCAP_IS2_HK_L4_DPORT]			= {120,  16},768	[VCAP_IS2_HK_L4_SPORT]			= {136,  16},769	[VCAP_IS2_HK_L4_RNG]			= {152,   8},770	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {160,   1},771	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {161,   1},772	[VCAP_IS2_HK_L4_FIN]			= {162,   1},773	[VCAP_IS2_HK_L4_SYN]			= {163,   1},774	[VCAP_IS2_HK_L4_RST]			= {164,   1},775	[VCAP_IS2_HK_L4_PSH]			= {165,   1},776	[VCAP_IS2_HK_L4_ACK]			= {166,   1},777	[VCAP_IS2_HK_L4_URG]			= {167,   1},778	[VCAP_IS2_HK_L4_1588_DOM]		= {168,   8},779	[VCAP_IS2_HK_L4_1588_VER]		= {176,   4},780	/* IP4_OTHER (TYPE=101) */781	[VCAP_IS2_HK_IP4_L3_PROTO]		= {119,   8},782	[VCAP_IS2_HK_L3_PAYLOAD]		= {127,  56},783	/* IP6_STD (TYPE=110) */784	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 41,   1},785	[VCAP_IS2_HK_L3_IP6_SIP]		= { 42, 128},786	[VCAP_IS2_HK_IP6_L3_PROTO]		= {170,   8},787	/* OAM (TYPE=111) */788	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= {137,   7},789	[VCAP_IS2_HK_OAM_VER]			= {144,   5},790	[VCAP_IS2_HK_OAM_OPCODE]		= {149,   8},791	[VCAP_IS2_HK_OAM_FLAGS]			= {157,   8},792	[VCAP_IS2_HK_OAM_MEPID]			= {165,  16},793	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= {181,   1},794	[VCAP_IS2_HK_OAM_IS_Y1731]		= {182,   1},795};796 797static struct vcap_field vsc9959_vcap_is2_actions[] = {798	[VCAP_IS2_ACT_HIT_ME_ONCE]		= {  0,  1},799	[VCAP_IS2_ACT_CPU_COPY_ENA]		= {  1,  1},800	[VCAP_IS2_ACT_CPU_QU_NUM]		= {  2,  3},801	[VCAP_IS2_ACT_MASK_MODE]		= {  5,  2},802	[VCAP_IS2_ACT_MIRROR_ENA]		= {  7,  1},803	[VCAP_IS2_ACT_LRN_DIS]			= {  8,  1},804	[VCAP_IS2_ACT_POLICE_ENA]		= {  9,  1},805	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9},806	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1},807	[VCAP_IS2_ACT_PORT_MASK]		= { 20,  6},808	[VCAP_IS2_ACT_REW_OP]			= { 26,  9},809	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 35,  1},810	[VCAP_IS2_ACT_RSV]			= { 36,  2},811	[VCAP_IS2_ACT_ACL_ID]			= { 38,  6},812	[VCAP_IS2_ACT_HIT_CNT]			= { 44, 32},813};814 815static struct vcap_props vsc9959_vcap_props[] = {816	[VCAP_ES0] = {817		.action_type_width = 0,818		.action_table = {819			[ES0_ACTION_TYPE_NORMAL] = {820				.width = 72, /* HIT_STICKY not included */821				.count = 1,822			},823		},824		.target = S0,825		.keys = vsc9959_vcap_es0_keys,826		.actions = vsc9959_vcap_es0_actions,827	},828	[VCAP_IS1] = {829		.action_type_width = 0,830		.action_table = {831			[IS1_ACTION_TYPE_NORMAL] = {832				.width = 78, /* HIT_STICKY not included */833				.count = 4,834			},835		},836		.target = S1,837		.keys = vsc9959_vcap_is1_keys,838		.actions = vsc9959_vcap_is1_actions,839	},840	[VCAP_IS2] = {841		.action_type_width = 1,842		.action_table = {843			[IS2_ACTION_TYPE_NORMAL] = {844				.width = 44,845				.count = 2846			},847			[IS2_ACTION_TYPE_SMAC_SIP] = {848				.width = 6,849				.count = 4850			},851		},852		.target = S2,853		.keys = vsc9959_vcap_is2_keys,854		.actions = vsc9959_vcap_is2_actions,855	},856};857 858static const struct ptp_clock_info vsc9959_ptp_caps = {859	.owner		= THIS_MODULE,860	.name		= "felix ptp",861	.max_adj	= 0x7fffffff,862	.n_alarm	= 0,863	.n_ext_ts	= 0,864	.n_per_out	= OCELOT_PTP_PINS_NUM,865	.n_pins		= OCELOT_PTP_PINS_NUM,866	.pps		= 0,867	.gettime64	= ocelot_ptp_gettime64,868	.settime64	= ocelot_ptp_settime64,869	.adjtime	= ocelot_ptp_adjtime,870	.adjfine	= ocelot_ptp_adjfine,871	.verify		= ocelot_ptp_verify,872	.enable		= ocelot_ptp_enable,873};874 875#define VSC9959_INIT_TIMEOUT			50000876#define VSC9959_GCB_RST_SLEEP			100877#define VSC9959_SYS_RAMINIT_SLEEP		80878 879static int vsc9959_gcb_soft_rst_status(struct ocelot *ocelot)880{881	int val;882 883	ocelot_field_read(ocelot, GCB_SOFT_RST_SWC_RST, &val);884 885	return val;886}887 888static int vsc9959_sys_ram_init_status(struct ocelot *ocelot)889{890	return ocelot_read(ocelot, SYS_RAM_INIT);891}892 893/* CORE_ENA is in SYS:SYSTEM:RESET_CFG894 * RAM_INIT is in SYS:RAM_CTRL:RAM_INIT895 */896static int vsc9959_reset(struct ocelot *ocelot)897{898	int val, err;899 900	/* soft-reset the switch core */901	ocelot_field_write(ocelot, GCB_SOFT_RST_SWC_RST, 1);902 903	err = readx_poll_timeout(vsc9959_gcb_soft_rst_status, ocelot, val, !val,904				 VSC9959_GCB_RST_SLEEP, VSC9959_INIT_TIMEOUT);905	if (err) {906		dev_err(ocelot->dev, "timeout: switch core reset\n");907		return err;908	}909 910	/* initialize switch mem ~40us */911	ocelot_write(ocelot, SYS_RAM_INIT_RAM_INIT, SYS_RAM_INIT);912	err = readx_poll_timeout(vsc9959_sys_ram_init_status, ocelot, val, !val,913				 VSC9959_SYS_RAMINIT_SLEEP,914				 VSC9959_INIT_TIMEOUT);915	if (err) {916		dev_err(ocelot->dev, "timeout: switch sram init\n");917		return err;918	}919 920	/* enable switch core */921	ocelot_field_write(ocelot, SYS_RESET_CFG_CORE_ENA, 1);922 923	return 0;924}925 926/* Watermark encode927 * Bit 8:   Unit; 0:1, 1:16928 * Bit 7-0: Value to be multiplied with unit929 */930static u16 vsc9959_wm_enc(u16 value)931{932	WARN_ON(value >= 16 * BIT(8));933 934	if (value >= BIT(8))935		return BIT(8) | (value / 16);936 937	return value;938}939 940static u16 vsc9959_wm_dec(u16 wm)941{942	WARN_ON(wm & ~GENMASK(8, 0));943 944	if (wm & BIT(8))945		return (wm & GENMASK(7, 0)) * 16;946 947	return wm;948}949 950static void vsc9959_wm_stat(u32 val, u32 *inuse, u32 *maxuse)951{952	*inuse = (val & GENMASK(23, 12)) >> 12;953	*maxuse = val & GENMASK(11, 0);954}955 956static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)957{958	struct pci_dev *pdev = to_pci_dev(ocelot->dev);959	struct felix *felix = ocelot_to_felix(ocelot);960	struct enetc_mdio_priv *mdio_priv;961	struct device *dev = ocelot->dev;962	resource_size_t imdio_base;963	void __iomem *imdio_regs;964	struct resource res;965	struct enetc_hw *hw;966	struct mii_bus *bus;967	int port;968	int rc;969 970	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,971				  sizeof(struct phylink_pcs *),972				  GFP_KERNEL);973	if (!felix->pcs) {974		dev_err(dev, "failed to allocate array for PCS PHYs\n");975		return -ENOMEM;976	}977 978	imdio_base = pci_resource_start(pdev, VSC9959_IMDIO_PCI_BAR);979 980	memcpy(&res, &vsc9959_imdio_res, sizeof(res));981	res.start += imdio_base;982	res.end += imdio_base;983 984	imdio_regs = devm_ioremap_resource(dev, &res);985	if (IS_ERR(imdio_regs))986		return PTR_ERR(imdio_regs);987 988	hw = enetc_hw_alloc(dev, imdio_regs);989	if (IS_ERR(hw)) {990		dev_err(dev, "failed to allocate ENETC HW structure\n");991		return PTR_ERR(hw);992	}993 994	bus = mdiobus_alloc_size(sizeof(*mdio_priv));995	if (!bus)996		return -ENOMEM;997 998	bus->name = "VSC9959 internal MDIO bus";999	bus->read = enetc_mdio_read_c22;1000	bus->write = enetc_mdio_write_c22;1001	bus->read_c45 = enetc_mdio_read_c45;1002	bus->write_c45 = enetc_mdio_write_c45;1003	bus->parent = dev;1004	mdio_priv = bus->priv;1005	mdio_priv->hw = hw;1006	/* This gets added to imdio_regs, which already maps addresses1007	 * starting with the proper offset.1008	 */1009	mdio_priv->mdio_base = 0;1010	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));1011 1012	/* Needed in order to initialize the bus mutex lock */1013	rc = mdiobus_register(bus);1014	if (rc < 0) {1015		dev_err(dev, "failed to register MDIO bus\n");1016		mdiobus_free(bus);1017		return rc;1018	}1019 1020	felix->imdio = bus;1021 1022	for (port = 0; port < felix->info->num_ports; port++) {1023		struct ocelot_port *ocelot_port = ocelot->ports[port];1024		struct phylink_pcs *phylink_pcs;1025 1026		if (dsa_is_unused_port(felix->ds, port))1027			continue;1028 1029		if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)1030			continue;1031 1032		phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port);1033		if (IS_ERR(phylink_pcs))1034			continue;1035 1036		felix->pcs[port] = phylink_pcs;1037 1038		dev_info(dev, "Found PCS at internal MDIO address %d\n", port);1039	}1040 1041	return 0;1042}1043 1044static void vsc9959_mdio_bus_free(struct ocelot *ocelot)1045{1046	struct felix *felix = ocelot_to_felix(ocelot);1047	int port;1048 1049	for (port = 0; port < ocelot->num_phys_ports; port++) {1050		struct phylink_pcs *phylink_pcs = felix->pcs[port];1051 1052		if (phylink_pcs)1053			lynx_pcs_destroy(phylink_pcs);1054	}1055	mdiobus_unregister(felix->imdio);1056	mdiobus_free(felix->imdio);1057}1058 1059/* The switch considers any frame (regardless of size) as eligible for1060 * transmission if the traffic class gate is open for at least 33 ns.1061 * Overruns are prevented by cropping an interval at the end of the gate time1062 * slot for which egress scheduling is blocked, but we need to still keep 33 ns1063 * available for one packet to be transmitted, otherwise the port tc will hang.1064 * This function returns the size of a gate interval that remains available for1065 * setting the guard band, after reserving the space for one egress frame.1066 */1067static u64 vsc9959_tas_remaining_gate_len_ps(u64 gate_len_ns)1068{1069	/* Gate always open */1070	if (gate_len_ns == U64_MAX)1071		return U64_MAX;1072 1073	if (gate_len_ns < VSC9959_TAS_MIN_GATE_LEN_NS)1074		return 0;1075 1076	return (gate_len_ns - VSC9959_TAS_MIN_GATE_LEN_NS) * PSEC_PER_NSEC;1077}1078 1079/* Extract shortest continuous gate open intervals in ns for each traffic class1080 * of a cyclic tc-taprio schedule. If a gate is always open, the duration is1081 * considered U64_MAX. If the gate is always closed, it is considered 0.1082 */1083static void vsc9959_tas_min_gate_lengths(struct tc_taprio_qopt_offload *taprio,1084					 u64 min_gate_len[OCELOT_NUM_TC])1085{1086	struct tc_taprio_sched_entry *entry;1087	u64 gate_len[OCELOT_NUM_TC];1088	u8 gates_ever_opened = 0;1089	int tc, i, n;1090 1091	/* Initialize arrays */1092	for (tc = 0; tc < OCELOT_NUM_TC; tc++) {1093		min_gate_len[tc] = U64_MAX;1094		gate_len[tc] = 0;1095	}1096 1097	/* If we don't have taprio, consider all gates as permanently open */1098	if (!taprio)1099		return;1100 1101	n = taprio->num_entries;1102 1103	/* Walk through the gate list twice to determine the length1104	 * of consecutively open gates for a traffic class, including1105	 * open gates that wrap around. We are just interested in the1106	 * minimum window size, and this doesn't change what the1107	 * minimum is (if the gate never closes, min_gate_len will1108	 * remain U64_MAX).1109	 */1110	for (i = 0; i < 2 * n; i++) {1111		entry = &taprio->entries[i % n];1112 1113		for (tc = 0; tc < OCELOT_NUM_TC; tc++) {1114			if (entry->gate_mask & BIT(tc)) {1115				gate_len[tc] += entry->interval;1116				gates_ever_opened |= BIT(tc);1117			} else {1118				/* Gate closes now, record a potential new1119				 * minimum and reinitialize length1120				 */1121				if (min_gate_len[tc] > gate_len[tc] &&1122				    gate_len[tc])1123					min_gate_len[tc] = gate_len[tc];1124				gate_len[tc] = 0;1125			}1126		}1127	}1128 1129	/* min_gate_len[tc] actually tracks minimum *open* gate time, so for1130	 * permanently closed gates, min_gate_len[tc] will still be U64_MAX.1131	 * Therefore they are currently indistinguishable from permanently1132	 * open gates. Overwrite the gate len with 0 when we know they're1133	 * actually permanently closed, i.e. after the loop above.1134	 */1135	for (tc = 0; tc < OCELOT_NUM_TC; tc++)1136		if (!(gates_ever_opened & BIT(tc)))1137			min_gate_len[tc] = 0;1138}1139 1140/* ocelot_write_rix is a macro that concatenates QSYS_MAXSDU_CFG_* with _RSZ,1141 * so we need to spell out the register access to each traffic class in helper1142 * functions, to simplify callers1143 */1144static void vsc9959_port_qmaxsdu_set(struct ocelot *ocelot, int port, int tc,1145				     u32 max_sdu)1146{1147	switch (tc) {1148	case 0:1149		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_0,1150				 port);1151		break;1152	case 1:1153		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_1,1154				 port);1155		break;1156	case 2:1157		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_2,1158				 port);1159		break;1160	case 3:1161		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_3,1162				 port);1163		break;1164	case 4:1165		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_4,1166				 port);1167		break;1168	case 5:1169		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_5,1170				 port);1171		break;1172	case 6:1173		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_6,1174				 port);1175		break;1176	case 7:1177		ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_7,1178				 port);1179		break;1180	}1181}1182 1183static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc)1184{1185	switch (tc) {1186	case 0: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_0, port);1187	case 1: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_1, port);1188	case 2: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_2, port);1189	case 3: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_3, port);1190	case 4: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_4, port);1191	case 5: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_5, port);1192	case 6: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_6, port);1193	case 7: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_7, port);1194	default:1195		return 0;1196	}1197}1198 1199static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc)1200{1201	if (!taprio || !taprio->max_sdu[tc])1202		return 0;1203 1204	return taprio->max_sdu[tc] + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;1205}1206 1207/* Update QSYS_PORT_MAX_SDU to make sure the static guard bands added by the1208 * switch (see the ALWAYS_GUARD_BAND_SCH_Q comment) are correct at all MTU1209 * values (the default value is 1518). Also, for traffic class windows smaller1210 * than one MTU sized frame, update QSYS_QMAXSDU_CFG to enable oversized frame1211 * dropping, such that these won't hang the port, as they will never be sent.1212 */1213static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)1214{1215	struct ocelot_port *ocelot_port = ocelot->ports[port];1216	struct ocelot_mm_state *mm = &ocelot->mm[port];1217	struct tc_taprio_qopt_offload *taprio;1218	u64 min_gate_len[OCELOT_NUM_TC];1219	u32 val, maxlen, add_frag_size;1220	u64 needed_min_frag_time_ps;1221	int speed, picos_per_byte;1222	u64 needed_bit_time_ps;1223	u8 tas_speed;1224	int tc;1225 1226	lockdep_assert_held(&ocelot->fwd_domain_lock);1227 1228	taprio = ocelot_port->taprio;1229 1230	val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port);1231	tas_speed = QSYS_TAG_CONFIG_LINK_SPEED_X(val);1232 1233	switch (tas_speed) {1234	case OCELOT_SPEED_10:1235		speed = SPEED_10;1236		break;1237	case OCELOT_SPEED_100:1238		speed = SPEED_100;1239		break;1240	case OCELOT_SPEED_1000:1241		speed = SPEED_1000;1242		break;1243	case OCELOT_SPEED_2500:1244		speed = SPEED_2500;1245		break;1246	default:1247		return;1248	}1249 1250	picos_per_byte = (USEC_PER_SEC * 8) / speed;1251 1252	val = ocelot_port_readl(ocelot_port, DEV_MAC_MAXLEN_CFG);1253	/* MAXLEN_CFG accounts automatically for VLAN. We need to include it1254	 * manually in the bit time calculation, plus the preamble and SFD.1255	 */1256	maxlen = val + 2 * VLAN_HLEN;1257	/* Consider the standard Ethernet overhead of 8 octets preamble+SFD,1258	 * 4 octets FCS, 12 octets IFG.1259	 */1260	needed_bit_time_ps = (u64)(maxlen + 24) * picos_per_byte;1261 1262	/* Preemptible TCs don't need to pass a full MTU, the port will1263	 * automatically emit a HOLD request when a preemptible TC gate closes1264	 */1265	val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port);1266	add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val);1267	needed_min_frag_time_ps = picos_per_byte *1268		(u64)(24 + 2 * ethtool_mm_frag_size_add_to_min(add_frag_size));1269 1270	dev_dbg(ocelot->dev,1271		"port %d: max frame size %d needs %llu ps, %llu ps for mPackets at speed %d\n",1272		port, maxlen, needed_bit_time_ps, needed_min_frag_time_ps,1273		speed);1274 1275	vsc9959_tas_min_gate_lengths(taprio, min_gate_len);1276 1277	for (tc = 0; tc < OCELOT_NUM_TC; tc++) {1278		u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);1279		u64 remaining_gate_len_ps;1280		u32 max_sdu;1281 1282		remaining_gate_len_ps =1283			vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]);1284 1285		if ((mm->active_preemptible_tcs & BIT(tc)) ?1286		    remaining_gate_len_ps > needed_min_frag_time_ps :1287		    remaining_gate_len_ps > needed_bit_time_ps) {1288			/* Setting QMAXSDU_CFG to 0 disables oversized frame1289			 * dropping.1290			 */1291			max_sdu = requested_max_sdu;1292			dev_dbg(ocelot->dev,1293				"port %d tc %d min gate len %llu"1294				", sending all frames\n",1295				port, tc, min_gate_len[tc]);1296		} else {1297			/* If traffic class doesn't support a full MTU sized1298			 * frame, make sure to enable oversize frame dropping1299			 * for frames larger than the smallest that would fit.1300			 *1301			 * However, the exact same register, QSYS_QMAXSDU_CFG_*,1302			 * controls not only oversized frame dropping, but also1303			 * per-tc static guard band lengths, so it reduces the1304			 * useful gate interval length. Therefore, be careful1305			 * to calculate a guard band (and therefore max_sdu)1306			 * that still leaves 33 ns available in the time slot.1307			 */1308			max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte);1309			/* A TC gate may be completely closed, which is a1310			 * special case where all packets are oversized.1311			 * Any limit smaller than 64 octets accomplishes this1312			 */1313			if (!max_sdu)1314				max_sdu = 1;1315			/* Take L1 overhead into account, but just don't allow1316			 * max_sdu to go negative or to 0. Here we use 201317			 * because QSYS_MAXSDU_CFG_* already counts the 4 FCS1318			 * octets as part of packet size.1319			 */1320			if (max_sdu > 20)1321				max_sdu -= 20;1322 1323			if (requested_max_sdu && requested_max_sdu < max_sdu)1324				max_sdu = requested_max_sdu;1325 1326			dev_info(ocelot->dev,1327				 "port %d tc %d min gate length %llu"1328				 " ns not enough for max frame size %d at %d"1329				 " Mbps, dropping frames over %d"1330				 " octets including FCS\n",1331				 port, tc, min_gate_len[tc], maxlen, speed,1332				 max_sdu);1333		}1334 1335		vsc9959_port_qmaxsdu_set(ocelot, port, tc, max_sdu);1336	}1337 1338	ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);1339 1340	ocelot->ops->cut_through_fwd(ocelot);1341}1342 1343static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,1344				    u32 speed)1345{1346	struct ocelot_port *ocelot_port = ocelot->ports[port];1347	u8 tas_speed;1348 1349	switch (speed) {1350	case SPEED_10:1351		tas_speed = OCELOT_SPEED_10;1352		break;1353	case SPEED_100:1354		tas_speed = OCELOT_SPEED_100;1355		break;1356	case SPEED_1000:1357		tas_speed = OCELOT_SPEED_1000;1358		break;1359	case SPEED_2500:1360		tas_speed = OCELOT_SPEED_2500;1361		break;1362	default:1363		tas_speed = OCELOT_SPEED_1000;1364		break;1365	}1366 1367	mutex_lock(&ocelot->fwd_domain_lock);1368 1369	ocelot_rmw_rix(ocelot,1370		       QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),1371		       QSYS_TAG_CONFIG_LINK_SPEED_M,1372		       QSYS_TAG_CONFIG, port);1373 1374	if (ocelot_port->taprio)1375		vsc9959_tas_guard_bands_update(ocelot, port);1376 1377	mutex_unlock(&ocelot->fwd_domain_lock);1378}1379 1380static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,1381				  u64 cycle_time,1382				  struct timespec64 *new_base_ts)1383{1384	struct timespec64 ts;1385	ktime_t new_base_time;1386	ktime_t current_time;1387 1388	ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);1389	current_time = timespec64_to_ktime(ts);1390	new_base_time = base_time;1391 1392	if (base_time < current_time) {1393		u64 nr_of_cycles = current_time - base_time;1394 1395		do_div(nr_of_cycles, cycle_time);1396		new_base_time += cycle_time * (nr_of_cycles + 1);1397	}1398 1399	*new_base_ts = ktime_to_timespec64(new_base_time);1400}1401 1402static u32 vsc9959_tas_read_cfg_status(struct ocelot *ocelot)1403{1404	return ocelot_read(ocelot, QSYS_TAS_PARAM_CFG_CTRL);1405}1406 1407static void vsc9959_tas_gcl_set(struct ocelot *ocelot, const u32 gcl_ix,1408				struct tc_taprio_sched_entry *entry)1409{1410	ocelot_write(ocelot,1411		     QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM(gcl_ix) |1412		     QSYS_GCL_CFG_REG_1_GATE_STATE(entry->gate_mask),1413		     QSYS_GCL_CFG_REG_1);1414	ocelot_write(ocelot, entry->interval, QSYS_GCL_CFG_REG_2);1415}1416 1417static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,1418				    struct tc_taprio_qopt_offload *taprio)1419{1420	struct ocelot_port *ocelot_port = ocelot->ports[port];1421	struct timespec64 base_ts;1422	int ret, i;1423	u32 val;1424 1425	mutex_lock(&ocelot->fwd_domain_lock);1426 1427	if (taprio->cmd == TAPRIO_CMD_DESTROY) {1428		ocelot_port_mqprio(ocelot, port, &taprio->mqprio);1429		ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,1430			       QSYS_TAG_CONFIG, port);1431 1432		taprio_offload_free(ocelot_port->taprio);1433		ocelot_port->taprio = NULL;1434 1435		vsc9959_tas_guard_bands_update(ocelot, port);1436 1437		mutex_unlock(&ocelot->fwd_domain_lock);1438		return 0;1439	} else if (taprio->cmd != TAPRIO_CMD_REPLACE) {1440		ret = -EOPNOTSUPP;1441		goto err_unlock;1442	}1443 1444	ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio);1445	if (ret)1446		goto err_unlock;1447 1448	if (taprio->cycle_time > NSEC_PER_SEC ||1449	    taprio->cycle_time_extension >= NSEC_PER_SEC) {1450		ret = -EINVAL;1451		goto err_reset_tc;1452	}1453 1454	if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX) {1455		ret = -ERANGE;1456		goto err_reset_tc;1457	}1458 1459	/* Enable guard band. The switch will schedule frames without taking1460	 * their length into account. Thus we'll always need to enable the1461	 * guard band which reserves the time of a maximum sized frame at the1462	 * end of the time window.1463	 *1464	 * Although the ALWAYS_GUARD_BAND_SCH_Q bit is global for all ports, we1465	 * need to set PORT_NUM, because subsequent writes to PARAM_CFG_REG_n1466	 * operate on the port number.1467	 */1468	ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port) |1469		   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,1470		   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M |1471		   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,1472		   QSYS_TAS_PARAM_CFG_CTRL);1473 1474	/* Hardware errata -  Admin config could not be overwritten if1475	 * config is pending, need reset the TAS module1476	 */1477	val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port);1478	if (val & QSYS_TAG_CONFIG_ENABLE) {1479		val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);1480		if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) {1481			ret = -EBUSY;1482			goto err_reset_tc;1483		}1484	}1485 1486	ocelot_rmw_rix(ocelot,1487		       QSYS_TAG_CONFIG_ENABLE |1488		       QSYS_TAG_CONFIG_INIT_GATE_STATE(0xFF) |1489		       QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES(0xFF),1490		       QSYS_TAG_CONFIG_ENABLE |1491		       QSYS_TAG_CONFIG_INIT_GATE_STATE_M |1492		       QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES_M,1493		       QSYS_TAG_CONFIG, port);1494 1495	vsc9959_new_base_time(ocelot, taprio->base_time,1496			      taprio->cycle_time, &base_ts);1497	ocelot_write(ocelot, base_ts.tv_nsec, QSYS_PARAM_CFG_REG_1);1498	ocelot_write(ocelot, lower_32_bits(base_ts.tv_sec), QSYS_PARAM_CFG_REG_2);1499	val = upper_32_bits(base_ts.tv_sec);1500	ocelot_write(ocelot,1501		     QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB(val) |1502		     QSYS_PARAM_CFG_REG_3_LIST_LENGTH(taprio->num_entries),1503		     QSYS_PARAM_CFG_REG_3);1504	ocelot_write(ocelot, taprio->cycle_time, QSYS_PARAM_CFG_REG_4);1505	ocelot_write(ocelot, taprio->cycle_time_extension, QSYS_PARAM_CFG_REG_5);1506 1507	for (i = 0; i < taprio->num_entries; i++)1508		vsc9959_tas_gcl_set(ocelot, i, &taprio->entries[i]);1509 1510	ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,1511		   QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,1512		   QSYS_TAS_PARAM_CFG_CTRL);1513 1514	ret = readx_poll_timeout(vsc9959_tas_read_cfg_status, ocelot, val,1515				 !(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE),1516				 10, 100000);1517	if (ret)1518		goto err_reset_tc;1519 1520	ocelot_port->taprio = taprio_offload_get(taprio);1521	vsc9959_tas_guard_bands_update(ocelot, port);1522 1523	mutex_unlock(&ocelot->fwd_domain_lock);1524 1525	return 0;1526 1527err_reset_tc:1528	taprio->mqprio.qopt.num_tc = 0;1529	ocelot_port_mqprio(ocelot, port, &taprio->mqprio);1530err_unlock:1531	mutex_unlock(&ocelot->fwd_domain_lock);1532 1533	return ret;1534}1535 1536static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)1537{1538	struct tc_taprio_qopt_offload *taprio;1539	struct ocelot_port *ocelot_port;1540	struct timespec64 base_ts;1541	int port;1542	u32 val;1543 1544	mutex_lock(&ocelot->fwd_domain_lock);1545 1546	for (port = 0; port < ocelot->num_phys_ports; port++) {1547		ocelot_port = ocelot->ports[port];1548		taprio = ocelot_port->taprio;1549		if (!taprio)1550			continue;1551 1552		ocelot_rmw(ocelot,1553			   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port),1554			   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M,1555			   QSYS_TAS_PARAM_CFG_CTRL);1556 1557		/* Disable time-aware shaper */1558		ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,1559			       QSYS_TAG_CONFIG, port);1560 1561		vsc9959_new_base_time(ocelot, taprio->base_time,1562				      taprio->cycle_time, &base_ts);1563 1564		ocelot_write(ocelot, base_ts.tv_nsec, QSYS_PARAM_CFG_REG_1);1565		ocelot_write(ocelot, lower_32_bits(base_ts.tv_sec),1566			     QSYS_PARAM_CFG_REG_2);1567		val = upper_32_bits(base_ts.tv_sec);1568		ocelot_rmw(ocelot,1569			   QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB(val),1570			   QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB_M,1571			   QSYS_PARAM_CFG_REG_3);1572 1573		ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,1574			   QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,1575			   QSYS_TAS_PARAM_CFG_CTRL);1576 1577		/* Re-enable time-aware shaper */1578		ocelot_rmw_rix(ocelot, QSYS_TAG_CONFIG_ENABLE,1579			       QSYS_TAG_CONFIG_ENABLE,1580			       QSYS_TAG_CONFIG, port);1581	}1582	mutex_unlock(&ocelot->fwd_domain_lock);1583}1584 1585static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,1586				    struct tc_cbs_qopt_offload *cbs_qopt)1587{1588	struct ocelot *ocelot = ds->priv;1589	int port_ix = port * 8 + cbs_qopt->queue;1590	u32 rate, burst;1591 1592	if (cbs_qopt->queue >= ds->num_tx_queues)1593		return -EINVAL;1594 1595	if (!cbs_qopt->enable) {1596		ocelot_write_gix(ocelot, QSYS_CIR_CFG_CIR_RATE(0) |1597				 QSYS_CIR_CFG_CIR_BURST(0),1598				 QSYS_CIR_CFG, port_ix);1599 1600		ocelot_rmw_gix(ocelot, 0, QSYS_SE_CFG_SE_AVB_ENA,1601			       QSYS_SE_CFG, port_ix);1602 1603		return 0;1604	}1605 1606	/* Rate unit is 100 kbps */1607	rate = DIV_ROUND_UP(cbs_qopt->idleslope, 100);1608	/* Avoid using zero rate */1609	rate = clamp_t(u32, rate, 1, GENMASK(14, 0));1610	/* Burst unit is 4kB */1611	burst = DIV_ROUND_UP(cbs_qopt->hicredit, 4096);1612	/* Avoid using zero burst size */1613	burst = clamp_t(u32, burst, 1, GENMASK(5, 0));1614	ocelot_write_gix(ocelot,1615			 QSYS_CIR_CFG_CIR_RATE(rate) |1616			 QSYS_CIR_CFG_CIR_BURST(burst),1617			 QSYS_CIR_CFG,1618			 port_ix);1619 1620	ocelot_rmw_gix(ocelot,1621		       QSYS_SE_CFG_SE_FRM_MODE(0) |1622		       QSYS_SE_CFG_SE_AVB_ENA,1623		       QSYS_SE_CFG_SE_AVB_ENA |1624		       QSYS_SE_CFG_SE_FRM_MODE_M,1625		       QSYS_SE_CFG,1626		       port_ix);1627 1628	return 0;1629}1630 1631static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)1632{1633	switch (base->type) {1634	case TC_SETUP_QDISC_MQPRIO: {1635		struct tc_mqprio_caps *caps = base->caps;1636 1637		caps->validate_queue_counts = true;1638 1639		return 0;1640	}1641	case TC_SETUP_QDISC_TAPRIO: {1642		struct tc_taprio_caps *caps = base->caps;1643 1644		caps->supports_queue_max_sdu = true;1645 1646		return 0;1647	}1648	default:1649		return -EOPNOTSUPP;1650	}1651}1652 1653static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port,1654				   struct tc_mqprio_qopt_offload *mqprio)1655{1656	int ret;1657 1658	mutex_lock(&ocelot->fwd_domain_lock);1659	ret = ocelot_port_mqprio(ocelot, port, mqprio);1660	mutex_unlock(&ocelot->fwd_domain_lock);1661 1662	return ret;1663}1664 1665static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,1666				 enum tc_setup_type type,1667				 void *type_data)1668{1669	struct ocelot *ocelot = ds->priv;1670 1671	switch (type) {1672	case TC_QUERY_CAPS:1673		return vsc9959_qos_query_caps(type_data);1674	case TC_SETUP_QDISC_TAPRIO:1675		return vsc9959_qos_port_tas_set(ocelot, port, type_data);1676	case TC_SETUP_QDISC_MQPRIO:1677		return vsc9959_qos_port_mqprio(ocelot, port, type_data);1678	case TC_SETUP_QDISC_CBS:1679		return vsc9959_qos_port_cbs_set(ds, port, type_data);1680	default:1681		return -EOPNOTSUPP;1682	}1683}1684 1685#define VSC9959_PSFP_SFID_MAX			1751686#define VSC9959_PSFP_GATE_ID_MAX		1831687#define VSC9959_PSFP_POLICER_BASE		631688#define VSC9959_PSFP_POLICER_MAX		3831689#define VSC9959_PSFP_GATE_LIST_NUM		41690#define VSC9959_PSFP_GATE_CYCLETIME_MIN		50001691 1692struct felix_stream {1693	struct list_head list;1694	unsigned long id;1695	bool dummy;1696	int ports;1697	int port;1698	u8 dmac[ETH_ALEN];1699	u16 vid;1700	s8 prio;1701	u8 sfid_valid;1702	u8 ssid_valid;1703	u32 sfid;1704	u32 ssid;1705};1706 1707struct felix_stream_filter_counters {1708	u64 match;1709	u64 not_pass_gate;1710	u64 not_pass_sdu;1711	u64 red;1712};1713 1714struct felix_stream_filter {1715	struct felix_stream_filter_counters stats;1716	struct list_head list;1717	refcount_t refcount;1718	u32 index;1719	u8 enable;1720	int portmask;1721	u8 sg_valid;1722	u32 sgid;1723	u8 fm_valid;1724	u32 fmid;1725	u8 prio_valid;1726	u8 prio;1727	u32 maxsdu;1728};1729 1730struct felix_stream_gate {1731	u32 index;1732	u8 enable;1733	u8 ipv_valid;1734	u8 init_ipv;1735	u64 basetime;1736	u64 cycletime;1737	u64 cycletime_ext;1738	u32 num_entries;1739	struct action_gate_entry entries[] __counted_by(num_entries);1740};1741 1742struct felix_stream_gate_entry {1743	struct list_head list;1744	refcount_t refcount;1745	u32 index;1746};1747 1748static int vsc9959_stream_identify(struct flow_cls_offload *f,1749				   struct felix_stream *stream)1750{1751	struct flow_rule *rule = flow_cls_offload_flow_rule(f);1752	struct flow_dissector *dissector = rule->match.dissector;1753 1754	if (dissector->used_keys &1755	    ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |1756	      BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |1757	      BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |1758	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS)))1759		return -EOPNOTSUPP;1760 1761	if (flow_rule_match_has_control_flags(rule, f->common.extack))1762		return -EOPNOTSUPP;1763 1764	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {1765		struct flow_match_eth_addrs match;1766 1767		flow_rule_match_eth_addrs(rule, &match);1768		ether_addr_copy(stream->dmac, match.key->dst);1769		if (!is_zero_ether_addr(match.mask->src))1770			return -EOPNOTSUPP;1771	} else {1772		return -EOPNOTSUPP;1773	}1774 1775	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {1776		struct flow_match_vlan match;1777 1778		flow_rule_match_vlan(rule, &match);1779		if (match.mask->vlan_priority)1780			stream->prio = match.key->vlan_priority;1781		else1782			stream->prio = -1;1783 1784		if (!match.mask->vlan_id)1785			return -EOPNOTSUPP;1786		stream->vid = match.key->vlan_id;1787	} else {1788		return -EOPNOTSUPP;1789	}1790 1791	stream->id = f->cookie;1792 1793	return 0;1794}1795 1796static int vsc9959_mact_stream_set(struct ocelot *ocelot,1797				   struct felix_stream *stream,1798				   struct netlink_ext_ack *extack)1799{1800	enum macaccess_entry_type type;1801	int ret, sfid, ssid;1802	u32 vid, dst_idx;1803	u8 mac[ETH_ALEN];1804 1805	ether_addr_copy(mac, stream->dmac);1806	vid = stream->vid;1807 1808	/* Stream identification desn't support to add a stream with non1809	 * existent MAC (The MAC entry has not been learned in MAC table).1810	 */1811	ret = ocelot_mact_lookup(ocelot, &dst_idx, mac, vid, &type);1812	if (ret) {1813		if (extack)1814			NL_SET_ERR_MSG_MOD(extack, "Stream is not learned in MAC table");1815		return -EOPNOTSUPP;1816	}1817 1818	if ((stream->sfid_valid || stream->ssid_valid) &&1819	    type == ENTRYTYPE_NORMAL)1820		type = ENTRYTYPE_LOCKED;1821 1822	sfid = stream->sfid_valid ? stream->sfid : -1;1823	ssid = stream->ssid_valid ? stream->ssid : -1;1824 1825	ret = ocelot_mact_learn_streamdata(ocelot, dst_idx, mac, vid, type,1826					   sfid, ssid);1827 1828	return ret;1829}1830 1831static struct felix_stream *1832vsc9959_stream_table_lookup(struct list_head *stream_list,1833			    struct felix_stream *stream)1834{1835	struct felix_stream *tmp;1836 1837	list_for_each_entry(tmp, stream_list, list)1838		if (ether_addr_equal(tmp->dmac, stream->dmac) &&1839		    tmp->vid == stream->vid)1840			return tmp;1841 1842	return NULL;1843}1844 1845static int vsc9959_stream_table_add(struct ocelot *ocelot,1846				    struct list_head *stream_list,1847				    struct felix_stream *stream,1848				    struct netlink_ext_ack *extack)1849{1850	struct felix_stream *stream_entry;1851	int ret;1852 1853	stream_entry = kmemdup(stream, sizeof(*stream_entry), GFP_KERNEL);1854	if (!stream_entry)1855		return -ENOMEM;1856 1857	if (!stream->dummy) {1858		ret = vsc9959_mact_stream_set(ocelot, stream_entry, extack);1859		if (ret) {1860			kfree(stream_entry);1861			return ret;1862		}1863	}1864 1865	list_add_tail(&stream_entry->list, stream_list);1866 1867	return 0;1868}1869 1870static struct felix_stream *1871vsc9959_stream_table_get(struct list_head *stream_list, unsigned long id)1872{1873	struct felix_stream *tmp;1874 1875	list_for_each_entry(tmp, stream_list, list)1876		if (tmp->id == id)1877			return tmp;1878 1879	return NULL;1880}1881 1882static void vsc9959_stream_table_del(struct ocelot *ocelot,1883				     struct felix_stream *stream)1884{1885	if (!stream->dummy)1886		vsc9959_mact_stream_set(ocelot, stream, NULL);1887 1888	list_del(&stream->list);1889	kfree(stream);1890}1891 1892static u32 vsc9959_sfi_access_status(struct ocelot *ocelot)1893{1894	return ocelot_read(ocelot, ANA_TABLES_SFIDACCESS);1895}1896 1897static int vsc9959_psfp_sfi_set(struct ocelot *ocelot,1898				struct felix_stream_filter *sfi)1899{1900	u32 val;1901 1902	if (sfi->index > VSC9959_PSFP_SFID_MAX)1903		return -EINVAL;1904 1905	if (!sfi->enable) {1906		ocelot_write(ocelot, ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index),1907			     ANA_TABLES_SFIDTIDX);1908 1909		val = ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE);1910		ocelot_write(ocelot, val, ANA_TABLES_SFIDACCESS);1911 1912		return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val,1913					  (!ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(val)),1914					  10, 100000);1915	}1916 1917	if (sfi->sgid > VSC9959_PSFP_GATE_ID_MAX ||1918	    sfi->fmid > VSC9959_PSFP_POLICER_MAX)1919		return -EINVAL;1920 1921	ocelot_write(ocelot,1922		     (sfi->sg_valid ? ANA_TABLES_SFIDTIDX_SGID_VALID : 0) |1923		     ANA_TABLES_SFIDTIDX_SGID(sfi->sgid) |1924		     (sfi->fm_valid ? ANA_TABLES_SFIDTIDX_POL_ENA : 0) |1925		     ANA_TABLES_SFIDTIDX_POL_IDX(sfi->fmid) |1926		     ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index),1927		     ANA_TABLES_SFIDTIDX);1928 1929	ocelot_write(ocelot,1930		     (sfi->prio_valid ? ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA : 0) |1931		     ANA_TABLES_SFIDACCESS_IGR_PRIO(sfi->prio) |1932		     ANA_TABLES_SFIDACCESS_MAX_SDU_LEN(sfi->maxsdu) |1933		     ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE),1934		     ANA_TABLES_SFIDACCESS);1935 1936	return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val,1937				  (!ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(val)),1938				  10, 100000);1939}1940 1941static int vsc9959_psfp_sfidmask_set(struct ocelot *ocelot, u32 sfid, int ports)1942{1943	u32 val;1944 1945	ocelot_rmw(ocelot,1946		   ANA_TABLES_SFIDTIDX_SFID_INDEX(sfid),1947		   ANA_TABLES_SFIDTIDX_SFID_INDEX_M,1948		   ANA_TABLES_SFIDTIDX);1949 1950	ocelot_write(ocelot,1951		     ANA_TABLES_SFID_MASK_IGR_PORT_MASK(ports) |1952		     ANA_TABLES_SFID_MASK_IGR_SRCPORT_MATCH_ENA,1953		     ANA_TABLES_SFID_MASK);1954 1955	ocelot_rmw(ocelot,1956		   ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE),1957		   ANA_TABLES_SFIDACCESS_SFID_TBL_CMD_M,1958		   ANA_TABLES_SFIDACCESS);1959 1960	return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val,1961				  (!ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(val)),1962				  10, 100000);1963}1964 1965static int vsc9959_psfp_sfi_list_add(struct ocelot *ocelot,1966				     struct felix_stream_filter *sfi,1967				     struct list_head *pos)1968{1969	struct felix_stream_filter *sfi_entry;1970	int ret;1971 1972	sfi_entry = kmemdup(sfi, sizeof(*sfi_entry), GFP_KERNEL);1973	if (!sfi_entry)1974		return -ENOMEM;1975 1976	refcount_set(&sfi_entry->refcount, 1);1977 1978	ret = vsc9959_psfp_sfi_set(ocelot, sfi_entry);1979	if (ret) {1980		kfree(sfi_entry);1981		return ret;1982	}1983 1984	vsc9959_psfp_sfidmask_set(ocelot, sfi->index, sfi->portmask);1985 1986	list_add(&sfi_entry->list, pos);1987 1988	return 0;1989}1990 1991static int vsc9959_psfp_sfi_table_add(struct ocelot *ocelot,1992				      struct felix_stream_filter *sfi)1993{1994	struct list_head *pos, *q, *last;1995	struct felix_stream_filter *tmp;1996	struct ocelot_psfp_list *psfp;1997	u32 insert = 0;1998 1999	psfp = &ocelot->psfp;2000	last = &psfp->sfi_list;2001 2002	list_for_each_safe(pos, q, &psfp->sfi_list) {2003		tmp = list_entry(pos, struct felix_stream_filter, list);2004		if (sfi->sg_valid == tmp->sg_valid &&2005		    sfi->fm_valid == tmp->fm_valid &&2006		    sfi->portmask == tmp->portmask &&2007		    tmp->sgid == sfi->sgid &&2008		    tmp->fmid == sfi->fmid) {2009			sfi->index = tmp->index;2010			refcount_inc(&tmp->refcount);2011			return 0;2012		}2013		/* Make sure that the index is increasing in order. */2014		if (tmp->index == insert) {2015			last = pos;2016			insert++;2017		}2018	}2019	sfi->index = insert;2020 2021	return vsc9959_psfp_sfi_list_add(ocelot, sfi, last);2022}2023 2024static int vsc9959_psfp_sfi_table_add2(struct ocelot *ocelot,2025				       struct felix_stream_filter *sfi,2026				       struct felix_stream_filter *sfi2)2027{2028	struct felix_stream_filter *tmp;2029	struct list_head *pos, *q, *last;2030	struct ocelot_psfp_list *psfp;2031	u32 insert = 0;2032	int ret;2033 2034	psfp = &ocelot->psfp;2035	last = &psfp->sfi_list;2036 2037	list_for_each_safe(pos, q, &psfp->sfi_list) {2038		tmp = list_entry(pos, struct felix_stream_filter, list);2039		/* Make sure that the index is increasing in order. */2040		if (tmp->index >= insert + 2)2041			break;2042 2043		insert = tmp->index + 1;2044		last = pos;2045	}2046	sfi->index = insert;2047 2048	ret = vsc9959_psfp_sfi_list_add(ocelot, sfi, last);2049	if (ret)2050		return ret;2051 2052	sfi2->index = insert + 1;2053 2054	return vsc9959_psfp_sfi_list_add(ocelot, sfi2, last->next);2055}2056 2057static struct felix_stream_filter *2058vsc9959_psfp_sfi_table_get(struct list_head *sfi_list, u32 index)2059{2060	struct felix_stream_filter *tmp;2061 2062	list_for_each_entry(tmp, sfi_list, list)2063		if (tmp->index == index)2064			return tmp;2065 2066	return NULL;2067}2068 2069static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index)2070{2071	struct felix_stream_filter *tmp, *n;2072	struct ocelot_psfp_list *psfp;2073	u8 z;2074 2075	psfp = &ocelot->psfp;2076 2077	list_for_each_entry_safe(tmp, n, &psfp->sfi_list, list)2078		if (tmp->index == index) {2079			z = refcount_dec_and_test(&tmp->refcount);2080			if (z) {2081				tmp->enable = 0;2082				vsc9959_psfp_sfi_set(ocelot, tmp);2083				list_del(&tmp->list);2084				kfree(tmp);2085			}2086			break;2087		}2088}2089 2090static void vsc9959_psfp_parse_gate(const struct flow_action_entry *entry,2091				    struct felix_stream_gate *sgi)2092{2093	sgi->index = entry->hw_index;2094	sgi->ipv_valid = (entry->gate.prio < 0) ? 0 : 1;2095	sgi->init_ipv = (sgi->ipv_valid) ? entry->gate.prio : 0;2096	sgi->basetime = entry->gate.basetime;2097	sgi->cycletime = entry->gate.cycletime;2098	sgi->num_entries = entry->gate.num_entries;2099	sgi->enable = 1;2100 2101	memcpy(sgi->entries, entry->gate.entries,2102	       entry->gate.num_entries * sizeof(struct action_gate_entry));2103}2104 2105static u32 vsc9959_sgi_cfg_status(struct ocelot *ocelot)2106{2107	return ocelot_read(ocelot, ANA_SG_ACCESS_CTRL);2108}2109 2110static int vsc9959_psfp_sgi_set(struct ocelot *ocelot,2111				struct felix_stream_gate *sgi)2112{2113	struct action_gate_entry *e;2114	struct timespec64 base_ts;2115	u32 interval_sum = 0;2116	u32 val;2117	int i;2118 2119	if (sgi->index > VSC9959_PSFP_GATE_ID_MAX)2120		return -EINVAL;2121 2122	ocelot_write(ocelot, ANA_SG_ACCESS_CTRL_SGID(sgi->index),2123		     ANA_SG_ACCESS_CTRL);2124 2125	if (!sgi->enable) {2126		ocelot_rmw(ocelot, ANA_SG_CONFIG_REG_3_INIT_GATE_STATE,2127			   ANA_SG_CONFIG_REG_3_INIT_GATE_STATE |2128			   ANA_SG_CONFIG_REG_3_GATE_ENABLE,2129			   ANA_SG_CONFIG_REG_3);2130 2131		return 0;2132	}2133 2134	if (sgi->cycletime < VSC9959_PSFP_GATE_CYCLETIME_MIN ||2135	    sgi->cycletime > NSEC_PER_SEC)2136		return -EINVAL;2137 2138	if (sgi->num_entries > VSC9959_PSFP_GATE_LIST_NUM)2139		return -EINVAL;2140 2141	vsc9959_new_base_time(ocelot, sgi->basetime, sgi->cycletime, &base_ts);2142	ocelot_write(ocelot, base_ts.tv_nsec, ANA_SG_CONFIG_REG_1);2143	val = lower_32_bits(base_ts.tv_sec);2144	ocelot_write(ocelot, val, ANA_SG_CONFIG_REG_2);2145 2146	val = upper_32_bits(base_ts.tv_sec);2147	ocelot_write(ocelot,2148		     (sgi->ipv_valid ? ANA_SG_CONFIG_REG_3_IPV_VALID : 0) |2149		     ANA_SG_CONFIG_REG_3_INIT_IPV(sgi->init_ipv) |2150		     ANA_SG_CONFIG_REG_3_GATE_ENABLE |2151		     ANA_SG_CONFIG_REG_3_LIST_LENGTH(sgi->num_entries) |2152		     ANA_SG_CONFIG_REG_3_INIT_GATE_STATE |2153		     ANA_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB(val),2154		     ANA_SG_CONFIG_REG_3);2155 2156	ocelot_write(ocelot, sgi->cycletime, ANA_SG_CONFIG_REG_4);2157 2158	e = sgi->entries;2159	for (i = 0; i < sgi->num_entries; i++) {2160		u32 ips = (e[i].ipv < 0) ? 0 : (e[i].ipv + 8);2161 2162		ocelot_write_rix(ocelot, ANA_SG_GCL_GS_CONFIG_IPS(ips) |2163				 (e[i].gate_state ?2164				  ANA_SG_GCL_GS_CONFIG_GATE_STATE : 0),2165				 ANA_SG_GCL_GS_CONFIG, i);2166 2167		interval_sum += e[i].interval;2168		ocelot_write_rix(ocelot, interval_sum, ANA_SG_GCL_TI_CONFIG, i);2169	}2170 2171	ocelot_rmw(ocelot, ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,2172		   ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,2173		   ANA_SG_ACCESS_CTRL);2174 2175	return readx_poll_timeout(vsc9959_sgi_cfg_status, ocelot, val,2176				  (!(ANA_SG_ACCESS_CTRL_CONFIG_CHANGE & val)),2177				  10, 100000);2178}2179 2180static int vsc9959_psfp_sgi_table_add(struct ocelot *ocelot,2181				      struct felix_stream_gate *sgi)2182{2183	struct felix_stream_gate_entry *tmp;2184	struct ocelot_psfp_list *psfp;2185	int ret;2186 2187	psfp = &ocelot->psfp;2188 2189	list_for_each_entry(tmp, &psfp->sgi_list, list)2190		if (tmp->index == sgi->index) {2191			refcount_inc(&tmp->refcount);2192			return 0;2193		}2194 2195	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);2196	if (!tmp)2197		return -ENOMEM;2198 2199	ret = vsc9959_psfp_sgi_set(ocelot, sgi);2200	if (ret) {2201		kfree(tmp);2202		return ret;2203	}2204 2205	tmp->index = sgi->index;2206	refcount_set(&tmp->refcount, 1);2207	list_add_tail(&tmp->list, &psfp->sgi_list);2208 2209	return 0;2210}2211 2212static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,2213				       u32 index)2214{2215	struct felix_stream_gate_entry *tmp, *n;2216	struct felix_stream_gate sgi = {0};2217	struct ocelot_psfp_list *psfp;2218	u8 z;2219 2220	psfp = &ocelot->psfp;2221 2222	list_for_each_entry_safe(tmp, n, &psfp->sgi_list, list)2223		if (tmp->index == index) {2224			z = refcount_dec_and_test(&tmp->refcount);2225			if (z) {2226				sgi.index = index;2227				sgi.enable = 0;2228				vsc9959_psfp_sgi_set(ocelot, &sgi);2229				list_del(&tmp->list);2230				kfree(tmp);2231			}2232			break;2233		}2234}2235 2236static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,2237				   struct flow_cls_offload *f)2238{2239	struct netlink_ext_ack *extack = f->common.extack;2240	struct felix_stream_filter old_sfi, *sfi_entry;2241	struct felix_stream_filter sfi = {0};2242	const struct flow_action_entry *a;2243	struct felix_stream *stream_entry;2244	struct felix_stream stream = {0};2245	struct felix_stream_gate *sgi;2246	struct ocelot_psfp_list *psfp;2247	struct ocelot_policer pol;2248	int ret, i, size;2249	u64 rate, burst;2250	u32 index;2251 2252	psfp = &ocelot->psfp;2253 2254	ret = vsc9959_stream_identify(f, &stream);2255	if (ret) {2256		NL_SET_ERR_MSG_MOD(extack, "Only can match on VID, PCP, and dest MAC");2257		return ret;2258	}2259 2260	mutex_lock(&psfp->lock);2261 2262	flow_action_for_each(i, a, &f->rule->action) {2263		switch (a->id) {2264		case FLOW_ACTION_GATE:2265			size = struct_size(sgi, entries, a->gate.num_entries);2266			sgi = kzalloc(size, GFP_KERNEL);2267			if (!sgi) {2268				ret = -ENOMEM;2269				goto err;2270			}2271			vsc9959_psfp_parse_gate(a, sgi);2272			ret = vsc9959_psfp_sgi_table_add(ocelot, sgi);2273			if (ret) {2274				kfree(sgi);2275				goto err;2276			}2277			sfi.sg_valid = 1;2278			sfi.sgid = sgi->index;2279			kfree(sgi);2280			break;2281		case FLOW_ACTION_POLICE:2282			index = a->hw_index + VSC9959_PSFP_POLICER_BASE;2283			if (index > VSC9959_PSFP_POLICER_MAX) {2284				ret = -EINVAL;2285				goto err;2286			}2287 2288			rate = a->police.rate_bytes_ps;2289			burst = rate * PSCHED_NS2TICKS(a->police.burst);2290			pol = (struct ocelot_policer) {2291				.burst = div_u64(burst, PSCHED_TICKS_PER_SEC),2292				.rate = div_u64(rate, 1000) * 8,2293			};2294			ret = ocelot_vcap_policer_add(ocelot, index, &pol);2295			if (ret)2296				goto err;2297 2298			sfi.fm_valid = 1;2299			sfi.fmid = index;2300			sfi.maxsdu = a->police.mtu;2301			break;2302		default:2303			mutex_unlock(&psfp->lock);2304			return -EOPNOTSUPP;2305		}2306	}2307 2308	stream.ports = BIT(port);2309	stream.port = port;2310 2311	sfi.portmask = stream.ports;2312	sfi.prio_valid = (stream.prio < 0 ? 0 : 1);2313	sfi.prio = (sfi.prio_valid ? stream.prio : 0);2314	sfi.enable = 1;2315 2316	/* Check if stream is set. */2317	stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream);2318	if (stream_entry) {2319		if (stream_entry->ports & BIT(port)) {2320			NL_SET_ERR_MSG_MOD(extack,2321					   "The stream is added on this port");2322			ret = -EEXIST;2323			goto err;2324		}2325 2326		if (stream_entry->ports != BIT(stream_entry->port)) {2327			NL_SET_ERR_MSG_MOD(extack,2328					   "The stream is added on two ports");2329			ret = -EEXIST;2330			goto err;2331		}2332 2333		stream_entry->ports |= BIT(port);2334		stream.ports = stream_entry->ports;2335 2336		sfi_entry = vsc9959_psfp_sfi_table_get(&psfp->sfi_list,2337						       stream_entry->sfid);2338		memcpy(&old_sfi, sfi_entry, sizeof(old_sfi));2339 2340		vsc9959_psfp_sfi_table_del(ocelot, stream_entry->sfid);2341 2342		old_sfi.portmask = stream_entry->ports;2343		sfi.portmask = stream.ports;2344 2345		if (stream_entry->port > port) {2346			ret = vsc9959_psfp_sfi_table_add2(ocelot, &sfi,2347							  &old_sfi);2348			stream_entry->dummy = true;2349		} else {2350			ret = vsc9959_psfp_sfi_table_add2(ocelot, &old_sfi,2351							  &sfi);2352			stream.dummy = true;2353		}2354		if (ret)2355			goto err;2356 2357		stream_entry->sfid = old_sfi.index;2358	} else {2359		ret = vsc9959_psfp_sfi_table_add(ocelot, &sfi);2360		if (ret)2361			goto err;2362	}2363 2364	stream.sfid = sfi.index;2365	stream.sfid_valid = 1;2366	ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list,2367				       &stream, extack);2368	if (ret) {2369		vsc9959_psfp_sfi_table_del(ocelot, stream.sfid);2370		goto err;2371	}2372 2373	mutex_unlock(&psfp->lock);2374 2375	return 0;2376 2377err:2378	if (sfi.sg_valid)2379		vsc9959_psfp_sgi_table_del(ocelot, sfi.sgid);2380 2381	if (sfi.fm_valid)2382		ocelot_vcap_policer_del(ocelot, sfi.fmid);2383 2384	mutex_unlock(&psfp->lock);2385 2386	return ret;2387}2388 2389static int vsc9959_psfp_filter_del(struct ocelot *ocelot,2390				   struct flow_cls_offload *f)2391{2392	struct felix_stream *stream, tmp, *stream_entry;2393	struct ocelot_psfp_list *psfp = &ocelot->psfp;2394	static struct felix_stream_filter *sfi;2395 2396	mutex_lock(&psfp->lock);2397 2398	stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie);2399	if (!stream) {2400		mutex_unlock(&psfp->lock);2401		return -ENOMEM;2402	}2403 2404	sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid);2405	if (!sfi) {2406		mutex_unlock(&psfp->lock);2407		return -ENOMEM;2408	}2409 2410	if (sfi->sg_valid)2411		vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid);2412 2413	if (sfi->fm_valid)2414		ocelot_vcap_policer_del(ocelot, sfi->fmid);2415 2416	vsc9959_psfp_sfi_table_del(ocelot, stream->sfid);2417 2418	memcpy(&tmp, stream, sizeof(tmp));2419 2420	stream->sfid_valid = 0;2421	vsc9959_stream_table_del(ocelot, stream);2422 2423	stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &tmp);2424	if (stream_entry) {2425		stream_entry->ports = BIT(stream_entry->port);2426		if (stream_entry->dummy) {2427			stream_entry->dummy = false;2428			vsc9959_mact_stream_set(ocelot, stream_entry, NULL);2429		}2430		vsc9959_psfp_sfidmask_set(ocelot, stream_entry->sfid,2431					  stream_entry->ports);2432	}2433 2434	mutex_unlock(&psfp->lock);2435 2436	return 0;2437}2438 2439static void vsc9959_update_sfid_stats(struct ocelot *ocelot,2440				      struct felix_stream_filter *sfi)2441{2442	struct felix_stream_filter_counters *s = &sfi->stats;2443	u32 match, not_pass_gate, not_pass_sdu, red;2444	u32 sfid = sfi->index;2445 2446	lockdep_assert_held(&ocelot->stat_view_lock);2447 2448	ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(sfid),2449		   SYS_STAT_CFG_STAT_VIEW_M,2450		   SYS_STAT_CFG);2451 2452	match = ocelot_read(ocelot, SYS_COUNT_SF_MATCHING_FRAMES);2453	not_pass_gate = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_FRAMES);2454	not_pass_sdu = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_SDU);2455	red = ocelot_read(ocelot, SYS_COUNT_SF_RED_FRAMES);2456 2457	/* Clear the PSFP counter. */2458	ocelot_write(ocelot,2459		     SYS_STAT_CFG_STAT_VIEW(sfid) |2460		     SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),2461		     SYS_STAT_CFG);2462 2463	s->match += match;2464	s->not_pass_gate += not_pass_gate;2465	s->not_pass_sdu += not_pass_sdu;2466	s->red += red;2467}2468 2469/* Caller must hold &ocelot->stat_view_lock */2470static void vsc9959_update_stats(struct ocelot *ocelot)2471{2472	struct ocelot_psfp_list *psfp = &ocelot->psfp;2473	struct felix_stream_filter *sfi;2474 2475	mutex_lock(&psfp->lock);2476 2477	list_for_each_entry(sfi, &psfp->sfi_list, list)2478		vsc9959_update_sfid_stats(ocelot, sfi);2479 2480	mutex_unlock(&psfp->lock);2481}2482 2483static int vsc9959_psfp_stats_get(struct ocelot *ocelot,2484				  struct flow_cls_offload *f,2485				  struct flow_stats *stats)2486{2487	struct ocelot_psfp_list *psfp = &ocelot->psfp;2488	struct felix_stream_filter_counters *s;2489	static struct felix_stream_filter *sfi;2490	struct felix_stream *stream;2491 2492	stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie);2493	if (!stream)2494		return -ENOMEM;2495 2496	sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid);2497	if (!sfi)2498		return -EINVAL;2499 2500	mutex_lock(&ocelot->stat_view_lock);2501 2502	vsc9959_update_sfid_stats(ocelot, sfi);2503 2504	s = &sfi->stats;2505	stats->pkts = s->match;2506	stats->drops = s->not_pass_gate + s->not_pass_sdu + s->red;2507 2508	memset(s, 0, sizeof(*s));2509 2510	mutex_unlock(&ocelot->stat_view_lock);2511 2512	return 0;2513}2514 2515static void vsc9959_psfp_init(struct ocelot *ocelot)2516{2517	struct ocelot_psfp_list *psfp = &ocelot->psfp;2518 2519	INIT_LIST_HEAD(&psfp->stream_list);2520	INIT_LIST_HEAD(&psfp->sfi_list);2521	INIT_LIST_HEAD(&psfp->sgi_list);2522	mutex_init(&psfp->lock);2523}2524 2525/* When using cut-through forwarding and the egress port runs at a higher data2526 * rate than the ingress port, the packet currently under transmission would2527 * suffer an underrun since it would be transmitted faster than it is received.2528 * The Felix switch implementation of cut-through forwarding does not check in2529 * hardware whether this condition is satisfied or not, so we must restrict the2530 * list of ports that have cut-through forwarding enabled on egress to only be2531 * the ports operating at the lowest link speed within their respective2532 * forwarding domain.2533 */2534static void vsc9959_cut_through_fwd(struct ocelot *ocelot)2535{2536	struct felix *felix = ocelot_to_felix(ocelot);2537	struct dsa_switch *ds = felix->ds;2538	int tc, port, other_port;2539 2540	lockdep_assert_held(&ocelot->fwd_domain_lock);2541 2542	for (port = 0; port < ocelot->num_phys_ports; port++) {2543		struct ocelot_port *ocelot_port = ocelot->ports[port];2544		struct ocelot_mm_state *mm = &ocelot->mm[port];2545		int min_speed = ocelot_port->speed;2546		unsigned long mask = 0;2547		u32 tmp, val = 0;2548 2549		/* Disable cut-through on ports that are down */2550		if (ocelot_port->speed <= 0)2551			goto set;2552 2553		if (dsa_is_cpu_port(ds, port)) {2554			/* Ocelot switches forward from the NPI port towards2555			 * any port, regardless of it being in the NPI port's2556			 * forwarding domain or not.2557			 */2558			mask = dsa_user_ports(ds);2559		} else {2560			mask = ocelot_get_bridge_fwd_mask(ocelot, port);2561			mask &= ~BIT(port);2562			if (ocelot->npi >= 0)2563				mask |= BIT(ocelot->npi);2564			else2565				mask |= ocelot_port_assigned_dsa_8021q_cpu_mask(ocelot,2566										port);2567		}2568 2569		/* Calculate the minimum link speed, among the ports that are2570		 * up, of this source port's forwarding domain.2571		 */2572		for_each_set_bit(other_port, &mask, ocelot->num_phys_ports) {2573			struct ocelot_port *other_ocelot_port;2574 2575			other_ocelot_port = ocelot->ports[other_port];2576			if (other_ocelot_port->speed <= 0)2577				continue;2578 2579			if (min_speed > other_ocelot_port->speed)2580				min_speed = other_ocelot_port->speed;2581		}2582 2583		/* Enable cut-through forwarding for all traffic classes that2584		 * don't have oversized dropping enabled, since this check is2585		 * bypassed in cut-through mode. Also exclude preemptible2586		 * traffic classes, since these would hang the port for some2587		 * reason, if sent as cut-through.2588		 */2589		if (ocelot_port->speed == min_speed) {2590			val = GENMASK(7, 0) & ~mm->active_preemptible_tcs;2591 2592			for (tc = 0; tc < OCELOT_NUM_TC; tc++)2593				if (vsc9959_port_qmaxsdu_get(ocelot, port, tc))2594					val &= ~BIT(tc);2595		}2596 2597set:2598		tmp = ocelot_read_rix(ocelot, ANA_CUT_THRU_CFG, port);2599		if (tmp == val)2600			continue;2601 2602		dev_dbg(ocelot->dev,2603			"port %d fwd mask 0x%lx speed %d min_speed %d, %s cut-through forwarding on TC mask 0x%x\n",2604			port, mask, ocelot_port->speed, min_speed,2605			val ? "enabling" : "disabling", val);2606 2607		ocelot_write_rix(ocelot, val, ANA_CUT_THRU_CFG, port);2608	}2609}2610 2611/* The INTB interrupt is shared between for PTP TX timestamp availability2612 * notification and MAC Merge status change on each port.2613 */2614static irqreturn_t vsc9959_irq_handler(int irq, void *data)2615{2616	struct ocelot *ocelot = data;2617 2618	ocelot_get_txtstamp(ocelot);2619	ocelot_mm_irq(ocelot);2620 2621	return IRQ_HANDLED;2622}2623 2624static int vsc9959_request_irq(struct ocelot *ocelot)2625{2626	struct pci_dev *pdev = to_pci_dev(ocelot->dev);2627 2628	return devm_request_threaded_irq(ocelot->dev, pdev->irq, NULL,2629					 &vsc9959_irq_handler, IRQF_ONESHOT,2630					 "felix-intb", ocelot);2631}2632 2633static const struct ocelot_ops vsc9959_ops = {2634	.reset			= vsc9959_reset,2635	.wm_enc			= vsc9959_wm_enc,2636	.wm_dec			= vsc9959_wm_dec,2637	.wm_stat		= vsc9959_wm_stat,2638	.port_to_netdev		= felix_port_to_netdev,2639	.netdev_to_port		= felix_netdev_to_port,2640	.psfp_init		= vsc9959_psfp_init,2641	.psfp_filter_add	= vsc9959_psfp_filter_add,2642	.psfp_filter_del	= vsc9959_psfp_filter_del,2643	.psfp_stats_get		= vsc9959_psfp_stats_get,2644	.cut_through_fwd	= vsc9959_cut_through_fwd,2645	.tas_clock_adjust	= vsc9959_tas_clock_adjust,2646	.update_stats		= vsc9959_update_stats,2647	.tas_guard_bands_update	= vsc9959_tas_guard_bands_update,2648};2649 2650static const struct felix_info felix_info_vsc9959 = {2651	.resources		= vsc9959_resources,2652	.num_resources		= ARRAY_SIZE(vsc9959_resources),2653	.resource_names		= vsc9959_resource_names,2654	.regfields		= vsc9959_regfields,2655	.map			= vsc9959_regmap,2656	.ops			= &vsc9959_ops,2657	.vcap			= vsc9959_vcap_props,2658	.vcap_pol_base		= VSC9959_VCAP_POLICER_BASE,2659	.vcap_pol_max		= VSC9959_VCAP_POLICER_MAX,2660	.vcap_pol_base2		= 0,2661	.vcap_pol_max2		= 0,2662	.num_mact_rows		= 2048,2663	.num_ports		= VSC9959_NUM_PORTS,2664	.quirks			= FELIX_MAC_QUIRKS,2665	.quirk_no_xtr_irq	= true,2666	.ptp_caps		= &vsc9959_ptp_caps,2667	.mdio_bus_alloc		= vsc9959_mdio_bus_alloc,2668	.mdio_bus_free		= vsc9959_mdio_bus_free,2669	.port_modes		= vsc9959_port_modes,2670	.port_setup_tc		= vsc9959_port_setup_tc,2671	.port_sched_speed_set	= vsc9959_sched_speed_set,2672	.request_irq		= vsc9959_request_irq,2673};2674 2675static int felix_pci_probe(struct pci_dev *pdev,2676			   const struct pci_device_id *id)2677{2678	struct device *dev = &pdev->dev;2679	resource_size_t switch_base;2680	int err;2681 2682	err = pci_enable_device(pdev);2683	if (err) {2684		dev_err(dev, "device enable failed: %pe\n", ERR_PTR(err));2685		return err;2686	}2687 2688	pci_set_master(pdev);2689 2690	switch_base = pci_resource_start(pdev, VSC9959_SWITCH_PCI_BAR);2691 2692	err = felix_register_switch(dev, switch_base, OCELOT_NUM_TC,2693				    true, true, DSA_TAG_PROTO_OCELOT,2694				    &felix_info_vsc9959);2695	if (err)2696		goto out_disable;2697 2698	return 0;2699 2700out_disable:2701	pci_disable_device(pdev);2702	return err;2703}2704 2705static void felix_pci_remove(struct pci_dev *pdev)2706{2707	struct felix *felix = pci_get_drvdata(pdev);2708 2709	if (!felix)2710		return;2711 2712	dsa_unregister_switch(felix->ds);2713 2714	pci_disable_device(pdev);2715}2716 2717static void felix_pci_shutdown(struct pci_dev *pdev)2718{2719	struct felix *felix = pci_get_drvdata(pdev);2720 2721	if (!felix)2722		return;2723 2724	dsa_switch_shutdown(felix->ds);2725 2726	pci_set_drvdata(pdev, NULL);2727}2728 2729static struct pci_device_id felix_ids[] = {2730	{2731		/* NXP LS1028A */2732		PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),2733	},2734	{ 0, }2735};2736MODULE_DEVICE_TABLE(pci, felix_ids);2737 2738static struct pci_driver felix_vsc9959_pci_driver = {2739	.name		= "mscc_felix",2740	.id_table	= felix_ids,2741	.probe		= felix_pci_probe,2742	.remove		= felix_pci_remove,2743	.shutdown	= felix_pci_shutdown,2744};2745module_pci_driver(felix_vsc9959_pci_driver);2746 2747MODULE_DESCRIPTION("Felix Switch driver");2748MODULE_LICENSE("GPL v2");2749