Linux Audio

Check our new training course

In-person Linux kernel drivers training

Jun 16-20, 2025
Register
Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2/* Copyright 2017 Microsemi Corporation
   3 * Copyright 2018-2019 NXP Semiconductors
   4 */
   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_ptp.h>
   9#include <soc/mscc/ocelot_sys.h>
  10#include <soc/mscc/ocelot.h>
  11#include <linux/packing.h>
  12#include <net/pkt_sched.h>
  13#include <linux/iopoll.h>
  14#include <linux/mdio.h>
  15#include <linux/pci.h>
  16#include "felix.h"
  17
  18#define VSC9959_VCAP_IS2_CNT		1024
  19#define VSC9959_VCAP_IS2_ENTRY_WIDTH	376
  20#define VSC9959_VCAP_PORT_CNT		6
  21#define VSC9959_TAS_GCL_ENTRY_MAX	63
  22
  23static const u32 vsc9959_ana_regmap[] = {
  24	REG(ANA_ADVLEARN,			0x0089a0),
  25	REG(ANA_VLANMASK,			0x0089a4),
  26	REG_RESERVED(ANA_PORT_B_DOMAIN),
  27	REG(ANA_ANAGEFIL,			0x0089ac),
  28	REG(ANA_ANEVENTS,			0x0089b0),
  29	REG(ANA_STORMLIMIT_BURST,		0x0089b4),
  30	REG(ANA_STORMLIMIT_CFG,			0x0089b8),
  31	REG(ANA_ISOLATED_PORTS,			0x0089c8),
  32	REG(ANA_COMMUNITY_PORTS,		0x0089cc),
  33	REG(ANA_AUTOAGE,			0x0089d0),
  34	REG(ANA_MACTOPTIONS,			0x0089d4),
  35	REG(ANA_LEARNDISC,			0x0089d8),
  36	REG(ANA_AGENCTRL,			0x0089dc),
  37	REG(ANA_MIRRORPORTS,			0x0089e0),
  38	REG(ANA_EMIRRORPORTS,			0x0089e4),
  39	REG(ANA_FLOODING,			0x0089e8),
  40	REG(ANA_FLOODING_IPMC,			0x008a08),
  41	REG(ANA_SFLOW_CFG,			0x008a0c),
  42	REG(ANA_PORT_MODE,			0x008a28),
  43	REG(ANA_CUT_THRU_CFG,			0x008a48),
  44	REG(ANA_PGID_PGID,			0x008400),
  45	REG(ANA_TABLES_ANMOVED,			0x007f1c),
  46	REG(ANA_TABLES_MACHDATA,		0x007f20),
  47	REG(ANA_TABLES_MACLDATA,		0x007f24),
  48	REG(ANA_TABLES_STREAMDATA,		0x007f28),
  49	REG(ANA_TABLES_MACACCESS,		0x007f2c),
  50	REG(ANA_TABLES_MACTINDX,		0x007f30),
  51	REG(ANA_TABLES_VLANACCESS,		0x007f34),
  52	REG(ANA_TABLES_VLANTIDX,		0x007f38),
  53	REG(ANA_TABLES_ISDXACCESS,		0x007f3c),
  54	REG(ANA_TABLES_ISDXTIDX,		0x007f40),
  55	REG(ANA_TABLES_ENTRYLIM,		0x007f00),
  56	REG(ANA_TABLES_PTP_ID_HIGH,		0x007f44),
  57	REG(ANA_TABLES_PTP_ID_LOW,		0x007f48),
  58	REG(ANA_TABLES_STREAMACCESS,		0x007f4c),
  59	REG(ANA_TABLES_STREAMTIDX,		0x007f50),
  60	REG(ANA_TABLES_SEQ_HISTORY,		0x007f54),
  61	REG(ANA_TABLES_SEQ_MASK,		0x007f58),
  62	REG(ANA_TABLES_SFID_MASK,		0x007f5c),
  63	REG(ANA_TABLES_SFIDACCESS,		0x007f60),
  64	REG(ANA_TABLES_SFIDTIDX,		0x007f64),
  65	REG(ANA_MSTI_STATE,			0x008600),
  66	REG(ANA_OAM_UPM_LM_CNT,			0x008000),
  67	REG(ANA_SG_ACCESS_CTRL,			0x008a64),
  68	REG(ANA_SG_CONFIG_REG_1,		0x007fb0),
  69	REG(ANA_SG_CONFIG_REG_2,		0x007fb4),
  70	REG(ANA_SG_CONFIG_REG_3,		0x007fb8),
  71	REG(ANA_SG_CONFIG_REG_4,		0x007fbc),
  72	REG(ANA_SG_CONFIG_REG_5,		0x007fc0),
  73	REG(ANA_SG_GCL_GS_CONFIG,		0x007f80),
  74	REG(ANA_SG_GCL_TI_CONFIG,		0x007f90),
  75	REG(ANA_SG_STATUS_REG_1,		0x008980),
  76	REG(ANA_SG_STATUS_REG_2,		0x008984),
  77	REG(ANA_SG_STATUS_REG_3,		0x008988),
  78	REG(ANA_PORT_VLAN_CFG,			0x007800),
  79	REG(ANA_PORT_DROP_CFG,			0x007804),
  80	REG(ANA_PORT_QOS_CFG,			0x007808),
  81	REG(ANA_PORT_VCAP_CFG,			0x00780c),
  82	REG(ANA_PORT_VCAP_S1_KEY_CFG,		0x007810),
  83	REG(ANA_PORT_VCAP_S2_CFG,		0x00781c),
  84	REG(ANA_PORT_PCP_DEI_MAP,		0x007820),
  85	REG(ANA_PORT_CPU_FWD_CFG,		0x007860),
  86	REG(ANA_PORT_CPU_FWD_BPDU_CFG,		0x007864),
  87	REG(ANA_PORT_CPU_FWD_GARP_CFG,		0x007868),
  88	REG(ANA_PORT_CPU_FWD_CCM_CFG,		0x00786c),
  89	REG(ANA_PORT_PORT_CFG,			0x007870),
  90	REG(ANA_PORT_POL_CFG,			0x007874),
  91	REG(ANA_PORT_PTP_CFG,			0x007878),
  92	REG(ANA_PORT_PTP_DLY1_CFG,		0x00787c),
  93	REG(ANA_PORT_PTP_DLY2_CFG,		0x007880),
  94	REG(ANA_PORT_SFID_CFG,			0x007884),
  95	REG(ANA_PFC_PFC_CFG,			0x008800),
  96	REG_RESERVED(ANA_PFC_PFC_TIMER),
  97	REG_RESERVED(ANA_IPT_OAM_MEP_CFG),
  98	REG_RESERVED(ANA_IPT_IPT),
  99	REG_RESERVED(ANA_PPT_PPT),
 100	REG_RESERVED(ANA_FID_MAP_FID_MAP),
 101	REG(ANA_AGGR_CFG,			0x008a68),
 102	REG(ANA_CPUQ_CFG,			0x008a6c),
 103	REG_RESERVED(ANA_CPUQ_CFG2),
 104	REG(ANA_CPUQ_8021_CFG,			0x008a74),
 105	REG(ANA_DSCP_CFG,			0x008ab4),
 106	REG(ANA_DSCP_REWR_CFG,			0x008bb4),
 107	REG(ANA_VCAP_RNG_TYPE_CFG,		0x008bf4),
 108	REG(ANA_VCAP_RNG_VAL_CFG,		0x008c14),
 109	REG_RESERVED(ANA_VRAP_CFG),
 110	REG_RESERVED(ANA_VRAP_HDR_DATA),
 111	REG_RESERVED(ANA_VRAP_HDR_MASK),
 112	REG(ANA_DISCARD_CFG,			0x008c40),
 113	REG(ANA_FID_CFG,			0x008c44),
 114	REG(ANA_POL_PIR_CFG,			0x004000),
 115	REG(ANA_POL_CIR_CFG,			0x004004),
 116	REG(ANA_POL_MODE_CFG,			0x004008),
 117	REG(ANA_POL_PIR_STATE,			0x00400c),
 118	REG(ANA_POL_CIR_STATE,			0x004010),
 119	REG_RESERVED(ANA_POL_STATE),
 120	REG(ANA_POL_FLOWC,			0x008c48),
 121	REG(ANA_POL_HYST,			0x008cb4),
 122	REG_RESERVED(ANA_POL_MISC_CFG),
 123};
 124
 125static const u32 vsc9959_qs_regmap[] = {
 126	REG(QS_XTR_GRP_CFG,			0x000000),
 127	REG(QS_XTR_RD,				0x000008),
 128	REG(QS_XTR_FRM_PRUNING,			0x000010),
 129	REG(QS_XTR_FLUSH,			0x000018),
 130	REG(QS_XTR_DATA_PRESENT,		0x00001c),
 131	REG(QS_XTR_CFG,				0x000020),
 132	REG(QS_INJ_GRP_CFG,			0x000024),
 133	REG(QS_INJ_WR,				0x00002c),
 134	REG(QS_INJ_CTRL,			0x000034),
 135	REG(QS_INJ_STATUS,			0x00003c),
 136	REG(QS_INJ_ERR,				0x000040),
 137	REG_RESERVED(QS_INH_DBG),
 138};
 139
 140static const u32 vsc9959_s2_regmap[] = {
 141	REG(S2_CORE_UPDATE_CTRL,		0x000000),
 142	REG(S2_CORE_MV_CFG,			0x000004),
 143	REG(S2_CACHE_ENTRY_DAT,			0x000008),
 144	REG(S2_CACHE_MASK_DAT,			0x000108),
 145	REG(S2_CACHE_ACTION_DAT,		0x000208),
 146	REG(S2_CACHE_CNT_DAT,			0x000308),
 147	REG(S2_CACHE_TG_DAT,			0x000388),
 148};
 149
 150static const u32 vsc9959_qsys_regmap[] = {
 151	REG(QSYS_PORT_MODE,			0x00f460),
 152	REG(QSYS_SWITCH_PORT_MODE,		0x00f480),
 153	REG(QSYS_STAT_CNT_CFG,			0x00f49c),
 154	REG(QSYS_EEE_CFG,			0x00f4a0),
 155	REG(QSYS_EEE_THRES,			0x00f4b8),
 156	REG(QSYS_IGR_NO_SHARING,		0x00f4bc),
 157	REG(QSYS_EGR_NO_SHARING,		0x00f4c0),
 158	REG(QSYS_SW_STATUS,			0x00f4c4),
 159	REG(QSYS_EXT_CPU_CFG,			0x00f4e0),
 160	REG_RESERVED(QSYS_PAD_CFG),
 161	REG(QSYS_CPU_GROUP_MAP,			0x00f4e8),
 162	REG_RESERVED(QSYS_QMAP),
 163	REG_RESERVED(QSYS_ISDX_SGRP),
 164	REG_RESERVED(QSYS_TIMED_FRAME_ENTRY),
 165	REG(QSYS_TFRM_MISC,			0x00f50c),
 166	REG(QSYS_TFRM_PORT_DLY,			0x00f510),
 167	REG(QSYS_TFRM_TIMER_CFG_1,		0x00f514),
 168	REG(QSYS_TFRM_TIMER_CFG_2,		0x00f518),
 169	REG(QSYS_TFRM_TIMER_CFG_3,		0x00f51c),
 170	REG(QSYS_TFRM_TIMER_CFG_4,		0x00f520),
 171	REG(QSYS_TFRM_TIMER_CFG_5,		0x00f524),
 172	REG(QSYS_TFRM_TIMER_CFG_6,		0x00f528),
 173	REG(QSYS_TFRM_TIMER_CFG_7,		0x00f52c),
 174	REG(QSYS_TFRM_TIMER_CFG_8,		0x00f530),
 175	REG(QSYS_RED_PROFILE,			0x00f534),
 176	REG(QSYS_RES_QOS_MODE,			0x00f574),
 177	REG(QSYS_RES_CFG,			0x00c000),
 178	REG(QSYS_RES_STAT,			0x00c004),
 179	REG(QSYS_EGR_DROP_MODE,			0x00f578),
 180	REG(QSYS_EQ_CTRL,			0x00f57c),
 181	REG_RESERVED(QSYS_EVENTS_CORE),
 182	REG(QSYS_QMAXSDU_CFG_0,			0x00f584),
 183	REG(QSYS_QMAXSDU_CFG_1,			0x00f5a0),
 184	REG(QSYS_QMAXSDU_CFG_2,			0x00f5bc),
 185	REG(QSYS_QMAXSDU_CFG_3,			0x00f5d8),
 186	REG(QSYS_QMAXSDU_CFG_4,			0x00f5f4),
 187	REG(QSYS_QMAXSDU_CFG_5,			0x00f610),
 188	REG(QSYS_QMAXSDU_CFG_6,			0x00f62c),
 189	REG(QSYS_QMAXSDU_CFG_7,			0x00f648),
 190	REG(QSYS_PREEMPTION_CFG,		0x00f664),
 191	REG(QSYS_CIR_CFG,			0x000000),
 192	REG(QSYS_EIR_CFG,			0x000004),
 193	REG(QSYS_SE_CFG,			0x000008),
 194	REG(QSYS_SE_DWRR_CFG,			0x00000c),
 195	REG_RESERVED(QSYS_SE_CONNECT),
 196	REG(QSYS_SE_DLB_SENSE,			0x000040),
 197	REG(QSYS_CIR_STATE,			0x000044),
 198	REG(QSYS_EIR_STATE,			0x000048),
 199	REG_RESERVED(QSYS_SE_STATE),
 200	REG(QSYS_HSCH_MISC_CFG,			0x00f67c),
 201	REG(QSYS_TAG_CONFIG,			0x00f680),
 202	REG(QSYS_TAS_PARAM_CFG_CTRL,		0x00f698),
 203	REG(QSYS_PORT_MAX_SDU,			0x00f69c),
 204	REG(QSYS_PARAM_CFG_REG_1,		0x00f440),
 205	REG(QSYS_PARAM_CFG_REG_2,		0x00f444),
 206	REG(QSYS_PARAM_CFG_REG_3,		0x00f448),
 207	REG(QSYS_PARAM_CFG_REG_4,		0x00f44c),
 208	REG(QSYS_PARAM_CFG_REG_5,		0x00f450),
 209	REG(QSYS_GCL_CFG_REG_1,			0x00f454),
 210	REG(QSYS_GCL_CFG_REG_2,			0x00f458),
 211	REG(QSYS_PARAM_STATUS_REG_1,		0x00f400),
 212	REG(QSYS_PARAM_STATUS_REG_2,		0x00f404),
 213	REG(QSYS_PARAM_STATUS_REG_3,		0x00f408),
 214	REG(QSYS_PARAM_STATUS_REG_4,		0x00f40c),
 215	REG(QSYS_PARAM_STATUS_REG_5,		0x00f410),
 216	REG(QSYS_PARAM_STATUS_REG_6,		0x00f414),
 217	REG(QSYS_PARAM_STATUS_REG_7,		0x00f418),
 218	REG(QSYS_PARAM_STATUS_REG_8,		0x00f41c),
 219	REG(QSYS_PARAM_STATUS_REG_9,		0x00f420),
 220	REG(QSYS_GCL_STATUS_REG_1,		0x00f424),
 221	REG(QSYS_GCL_STATUS_REG_2,		0x00f428),
 222};
 223
 224static const u32 vsc9959_rew_regmap[] = {
 225	REG(REW_PORT_VLAN_CFG,			0x000000),
 226	REG(REW_TAG_CFG,			0x000004),
 227	REG(REW_PORT_CFG,			0x000008),
 228	REG(REW_DSCP_CFG,			0x00000c),
 229	REG(REW_PCP_DEI_QOS_MAP_CFG,		0x000010),
 230	REG(REW_PTP_CFG,			0x000050),
 231	REG(REW_PTP_DLY1_CFG,			0x000054),
 232	REG(REW_RED_TAG_CFG,			0x000058),
 233	REG(REW_DSCP_REMAP_DP1_CFG,		0x000410),
 234	REG(REW_DSCP_REMAP_CFG,			0x000510),
 235	REG_RESERVED(REW_STAT_CFG),
 236	REG_RESERVED(REW_REW_STICKY),
 237	REG_RESERVED(REW_PPT),
 238};
 239
 240static const u32 vsc9959_sys_regmap[] = {
 241	REG(SYS_COUNT_RX_OCTETS,		0x000000),
 242	REG(SYS_COUNT_RX_MULTICAST,		0x000008),
 243	REG(SYS_COUNT_RX_SHORTS,		0x000010),
 244	REG(SYS_COUNT_RX_FRAGMENTS,		0x000014),
 245	REG(SYS_COUNT_RX_JABBERS,		0x000018),
 246	REG(SYS_COUNT_RX_64,			0x000024),
 247	REG(SYS_COUNT_RX_65_127,		0x000028),
 248	REG(SYS_COUNT_RX_128_255,		0x00002c),
 249	REG(SYS_COUNT_RX_256_1023,		0x000030),
 250	REG(SYS_COUNT_RX_1024_1526,		0x000034),
 251	REG(SYS_COUNT_RX_1527_MAX,		0x000038),
 252	REG(SYS_COUNT_RX_LONGS,			0x000044),
 253	REG(SYS_COUNT_TX_OCTETS,		0x000200),
 254	REG(SYS_COUNT_TX_COLLISION,		0x000210),
 255	REG(SYS_COUNT_TX_DROPS,			0x000214),
 256	REG(SYS_COUNT_TX_64,			0x00021c),
 257	REG(SYS_COUNT_TX_65_127,		0x000220),
 258	REG(SYS_COUNT_TX_128_511,		0x000224),
 259	REG(SYS_COUNT_TX_512_1023,		0x000228),
 260	REG(SYS_COUNT_TX_1024_1526,		0x00022c),
 261	REG(SYS_COUNT_TX_1527_MAX,		0x000230),
 262	REG(SYS_COUNT_TX_AGING,			0x000278),
 263	REG(SYS_RESET_CFG,			0x000e00),
 264	REG(SYS_SR_ETYPE_CFG,			0x000e04),
 265	REG(SYS_VLAN_ETYPE_CFG,			0x000e08),
 266	REG(SYS_PORT_MODE,			0x000e0c),
 267	REG(SYS_FRONT_PORT_MODE,		0x000e2c),
 268	REG(SYS_FRM_AGING,			0x000e44),
 269	REG(SYS_STAT_CFG,			0x000e48),
 270	REG(SYS_SW_STATUS,			0x000e4c),
 271	REG_RESERVED(SYS_MISC_CFG),
 272	REG(SYS_REW_MAC_HIGH_CFG,		0x000e6c),
 273	REG(SYS_REW_MAC_LOW_CFG,		0x000e84),
 274	REG(SYS_TIMESTAMP_OFFSET,		0x000e9c),
 275	REG(SYS_PAUSE_CFG,			0x000ea0),
 276	REG(SYS_PAUSE_TOT_CFG,			0x000ebc),
 277	REG(SYS_ATOP,				0x000ec0),
 278	REG(SYS_ATOP_TOT_CFG,			0x000edc),
 279	REG(SYS_MAC_FC_CFG,			0x000ee0),
 280	REG(SYS_MMGT,				0x000ef8),
 281	REG_RESERVED(SYS_MMGT_FAST),
 282	REG_RESERVED(SYS_EVENTS_DIF),
 283	REG_RESERVED(SYS_EVENTS_CORE),
 284	REG_RESERVED(SYS_CNT),
 285	REG(SYS_PTP_STATUS,			0x000f14),
 286	REG(SYS_PTP_TXSTAMP,			0x000f18),
 287	REG(SYS_PTP_NXT,			0x000f1c),
 288	REG(SYS_PTP_CFG,			0x000f20),
 289	REG(SYS_RAM_INIT,			0x000f24),
 290	REG_RESERVED(SYS_CM_ADDR),
 291	REG_RESERVED(SYS_CM_DATA_WR),
 292	REG_RESERVED(SYS_CM_DATA_RD),
 293	REG_RESERVED(SYS_CM_OP),
 294	REG_RESERVED(SYS_CM_DATA),
 295};
 296
 297static const u32 vsc9959_ptp_regmap[] = {
 298	REG(PTP_PIN_CFG,                   0x000000),
 299	REG(PTP_PIN_TOD_SEC_MSB,           0x000004),
 300	REG(PTP_PIN_TOD_SEC_LSB,           0x000008),
 301	REG(PTP_PIN_TOD_NSEC,              0x00000c),
 302	REG(PTP_PIN_WF_HIGH_PERIOD,        0x000014),
 303	REG(PTP_PIN_WF_LOW_PERIOD,         0x000018),
 304	REG(PTP_CFG_MISC,                  0x0000a0),
 305	REG(PTP_CLK_CFG_ADJ_CFG,           0x0000a4),
 306	REG(PTP_CLK_CFG_ADJ_FREQ,          0x0000a8),
 307};
 308
 309static const u32 vsc9959_gcb_regmap[] = {
 310	REG(GCB_SOFT_RST,			0x000004),
 311};
 312
 313static const u32 vsc9959_dev_gmii_regmap[] = {
 314	REG(DEV_CLOCK_CFG,			0x0),
 315	REG(DEV_PORT_MISC,			0x4),
 316	REG(DEV_EVENTS,				0x8),
 317	REG(DEV_EEE_CFG,			0xc),
 318	REG(DEV_RX_PATH_DELAY,			0x10),
 319	REG(DEV_TX_PATH_DELAY,			0x14),
 320	REG(DEV_PTP_PREDICT_CFG,		0x18),
 321	REG(DEV_MAC_ENA_CFG,			0x1c),
 322	REG(DEV_MAC_MODE_CFG,			0x20),
 323	REG(DEV_MAC_MAXLEN_CFG,			0x24),
 324	REG(DEV_MAC_TAGS_CFG,			0x28),
 325	REG(DEV_MAC_ADV_CHK_CFG,		0x2c),
 326	REG(DEV_MAC_IFG_CFG,			0x30),
 327	REG(DEV_MAC_HDX_CFG,			0x34),
 328	REG(DEV_MAC_DBG_CFG,			0x38),
 329	REG(DEV_MAC_FC_MAC_LOW_CFG,		0x3c),
 330	REG(DEV_MAC_FC_MAC_HIGH_CFG,		0x40),
 331	REG(DEV_MAC_STICKY,			0x44),
 332	REG_RESERVED(PCS1G_CFG),
 333	REG_RESERVED(PCS1G_MODE_CFG),
 334	REG_RESERVED(PCS1G_SD_CFG),
 335	REG_RESERVED(PCS1G_ANEG_CFG),
 336	REG_RESERVED(PCS1G_ANEG_NP_CFG),
 337	REG_RESERVED(PCS1G_LB_CFG),
 338	REG_RESERVED(PCS1G_DBG_CFG),
 339	REG_RESERVED(PCS1G_CDET_CFG),
 340	REG_RESERVED(PCS1G_ANEG_STATUS),
 341	REG_RESERVED(PCS1G_ANEG_NP_STATUS),
 342	REG_RESERVED(PCS1G_LINK_STATUS),
 343	REG_RESERVED(PCS1G_LINK_DOWN_CNT),
 344	REG_RESERVED(PCS1G_STICKY),
 345	REG_RESERVED(PCS1G_DEBUG_STATUS),
 346	REG_RESERVED(PCS1G_LPI_CFG),
 347	REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT),
 348	REG_RESERVED(PCS1G_LPI_STATUS),
 349	REG_RESERVED(PCS1G_TSTPAT_MODE_CFG),
 350	REG_RESERVED(PCS1G_TSTPAT_STATUS),
 351	REG_RESERVED(DEV_PCS_FX100_CFG),
 352	REG_RESERVED(DEV_PCS_FX100_STATUS),
 353};
 354
 355static const u32 *vsc9959_regmap[TARGET_MAX] = {
 356	[ANA]	= vsc9959_ana_regmap,
 357	[QS]	= vsc9959_qs_regmap,
 358	[QSYS]	= vsc9959_qsys_regmap,
 359	[REW]	= vsc9959_rew_regmap,
 360	[SYS]	= vsc9959_sys_regmap,
 361	[S2]	= vsc9959_s2_regmap,
 362	[PTP]	= vsc9959_ptp_regmap,
 363	[GCB]	= vsc9959_gcb_regmap,
 364	[DEV_GMII] = vsc9959_dev_gmii_regmap,
 365};
 366
 367/* Addresses are relative to the PCI device's base address */
 368static const struct resource vsc9959_target_io_res[TARGET_MAX] = {
 369	[ANA] = {
 370		.start	= 0x0280000,
 371		.end	= 0x028ffff,
 372		.name	= "ana",
 373	},
 374	[QS] = {
 375		.start	= 0x0080000,
 376		.end	= 0x00800ff,
 377		.name	= "qs",
 378	},
 379	[QSYS] = {
 380		.start	= 0x0200000,
 381		.end	= 0x021ffff,
 382		.name	= "qsys",
 383	},
 384	[REW] = {
 385		.start	= 0x0030000,
 386		.end	= 0x003ffff,
 387		.name	= "rew",
 388	},
 389	[SYS] = {
 390		.start	= 0x0010000,
 391		.end	= 0x001ffff,
 392		.name	= "sys",
 393	},
 394	[S2] = {
 395		.start	= 0x0060000,
 396		.end	= 0x00603ff,
 397		.name	= "s2",
 398	},
 399	[PTP] = {
 400		.start	= 0x0090000,
 401		.end	= 0x00900cb,
 402		.name	= "ptp",
 403	},
 404	[GCB] = {
 405		.start	= 0x0070000,
 406		.end	= 0x00701ff,
 407		.name	= "devcpu_gcb",
 408	},
 409};
 410
 411static const struct resource vsc9959_port_io_res[] = {
 412	{
 413		.start	= 0x0100000,
 414		.end	= 0x010ffff,
 415		.name	= "port0",
 416	},
 417	{
 418		.start	= 0x0110000,
 419		.end	= 0x011ffff,
 420		.name	= "port1",
 421	},
 422	{
 423		.start	= 0x0120000,
 424		.end	= 0x012ffff,
 425		.name	= "port2",
 426	},
 427	{
 428		.start	= 0x0130000,
 429		.end	= 0x013ffff,
 430		.name	= "port3",
 431	},
 432	{
 433		.start	= 0x0140000,
 434		.end	= 0x014ffff,
 435		.name	= "port4",
 436	},
 437	{
 438		.start	= 0x0150000,
 439		.end	= 0x015ffff,
 440		.name	= "port5",
 441	},
 442};
 443
 444/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
 445 * SGMII/QSGMII MAC PCS can be found.
 446 */
 447static const struct resource vsc9959_imdio_res = {
 448	.start		= 0x8030,
 449	.end		= 0x8040,
 450	.name		= "imdio",
 451};
 452
 453static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {
 454	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
 455	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),
 456	[ANA_ANEVENTS_FLOOD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 30, 30),
 457	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 26, 26),
 458	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 24, 24),
 459	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 23, 23),
 460	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 22, 22),
 461	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 21, 21),
 462	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 20, 20),
 463	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 19, 19),
 464	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
 465	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 17, 17),
 466	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 15, 15),
 467	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 14, 14),
 468	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 13, 13),
 469	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 12, 12),
 470	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
 471	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
 472	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 9, 9),
 473	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 8, 8),
 474	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 7, 7),
 475	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
 476	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
 477	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 4, 4),
 478	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 3, 3),
 479	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 2, 2),
 480	[ANA_ANEVENTS_SEQ_GEN_ERR_0] = REG_FIELD(ANA_ANEVENTS, 1, 1),
 481	[ANA_ANEVENTS_SEQ_GEN_ERR_1] = REG_FIELD(ANA_ANEVENTS, 0, 0),
 482	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 16, 16),
 483	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 11, 12),
 484	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10),
 485	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 0, 0),
 486	[GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0),
 487	/* Replicated per number of ports (7), register size 4 per port */
 488	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 7, 4),
 489	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 7, 4),
 490	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 7, 4),
 491	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 7, 4),
 492	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 7, 4),
 493	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 7, 4),
 494	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 7, 4),
 495	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 7, 4),
 496	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4),
 497	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 7, 4),
 498	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 7, 4),
 499	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 7, 4),
 500	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4),
 501};
 502
 503static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
 504	{ .offset = 0x00,	.name = "rx_octets", },
 505	{ .offset = 0x01,	.name = "rx_unicast", },
 506	{ .offset = 0x02,	.name = "rx_multicast", },
 507	{ .offset = 0x03,	.name = "rx_broadcast", },
 508	{ .offset = 0x04,	.name = "rx_shorts", },
 509	{ .offset = 0x05,	.name = "rx_fragments", },
 510	{ .offset = 0x06,	.name = "rx_jabbers", },
 511	{ .offset = 0x07,	.name = "rx_crc_align_errs", },
 512	{ .offset = 0x08,	.name = "rx_sym_errs", },
 513	{ .offset = 0x09,	.name = "rx_frames_below_65_octets", },
 514	{ .offset = 0x0A,	.name = "rx_frames_65_to_127_octets", },
 515	{ .offset = 0x0B,	.name = "rx_frames_128_to_255_octets", },
 516	{ .offset = 0x0C,	.name = "rx_frames_256_to_511_octets", },
 517	{ .offset = 0x0D,	.name = "rx_frames_512_to_1023_octets", },
 518	{ .offset = 0x0E,	.name = "rx_frames_1024_to_1526_octets", },
 519	{ .offset = 0x0F,	.name = "rx_frames_over_1526_octets", },
 520	{ .offset = 0x10,	.name = "rx_pause", },
 521	{ .offset = 0x11,	.name = "rx_control", },
 522	{ .offset = 0x12,	.name = "rx_longs", },
 523	{ .offset = 0x13,	.name = "rx_classified_drops", },
 524	{ .offset = 0x14,	.name = "rx_red_prio_0", },
 525	{ .offset = 0x15,	.name = "rx_red_prio_1", },
 526	{ .offset = 0x16,	.name = "rx_red_prio_2", },
 527	{ .offset = 0x17,	.name = "rx_red_prio_3", },
 528	{ .offset = 0x18,	.name = "rx_red_prio_4", },
 529	{ .offset = 0x19,	.name = "rx_red_prio_5", },
 530	{ .offset = 0x1A,	.name = "rx_red_prio_6", },
 531	{ .offset = 0x1B,	.name = "rx_red_prio_7", },
 532	{ .offset = 0x1C,	.name = "rx_yellow_prio_0", },
 533	{ .offset = 0x1D,	.name = "rx_yellow_prio_1", },
 534	{ .offset = 0x1E,	.name = "rx_yellow_prio_2", },
 535	{ .offset = 0x1F,	.name = "rx_yellow_prio_3", },
 536	{ .offset = 0x20,	.name = "rx_yellow_prio_4", },
 537	{ .offset = 0x21,	.name = "rx_yellow_prio_5", },
 538	{ .offset = 0x22,	.name = "rx_yellow_prio_6", },
 539	{ .offset = 0x23,	.name = "rx_yellow_prio_7", },
 540	{ .offset = 0x24,	.name = "rx_green_prio_0", },
 541	{ .offset = 0x25,	.name = "rx_green_prio_1", },
 542	{ .offset = 0x26,	.name = "rx_green_prio_2", },
 543	{ .offset = 0x27,	.name = "rx_green_prio_3", },
 544	{ .offset = 0x28,	.name = "rx_green_prio_4", },
 545	{ .offset = 0x29,	.name = "rx_green_prio_5", },
 546	{ .offset = 0x2A,	.name = "rx_green_prio_6", },
 547	{ .offset = 0x2B,	.name = "rx_green_prio_7", },
 548	{ .offset = 0x80,	.name = "tx_octets", },
 549	{ .offset = 0x81,	.name = "tx_unicast", },
 550	{ .offset = 0x82,	.name = "tx_multicast", },
 551	{ .offset = 0x83,	.name = "tx_broadcast", },
 552	{ .offset = 0x84,	.name = "tx_collision", },
 553	{ .offset = 0x85,	.name = "tx_drops", },
 554	{ .offset = 0x86,	.name = "tx_pause", },
 555	{ .offset = 0x87,	.name = "tx_frames_below_65_octets", },
 556	{ .offset = 0x88,	.name = "tx_frames_65_to_127_octets", },
 557	{ .offset = 0x89,	.name = "tx_frames_128_255_octets", },
 558	{ .offset = 0x8B,	.name = "tx_frames_256_511_octets", },
 559	{ .offset = 0x8C,	.name = "tx_frames_1024_1526_octets", },
 560	{ .offset = 0x8D,	.name = "tx_frames_over_1526_octets", },
 561	{ .offset = 0x8E,	.name = "tx_yellow_prio_0", },
 562	{ .offset = 0x8F,	.name = "tx_yellow_prio_1", },
 563	{ .offset = 0x90,	.name = "tx_yellow_prio_2", },
 564	{ .offset = 0x91,	.name = "tx_yellow_prio_3", },
 565	{ .offset = 0x92,	.name = "tx_yellow_prio_4", },
 566	{ .offset = 0x93,	.name = "tx_yellow_prio_5", },
 567	{ .offset = 0x94,	.name = "tx_yellow_prio_6", },
 568	{ .offset = 0x95,	.name = "tx_yellow_prio_7", },
 569	{ .offset = 0x96,	.name = "tx_green_prio_0", },
 570	{ .offset = 0x97,	.name = "tx_green_prio_1", },
 571	{ .offset = 0x98,	.name = "tx_green_prio_2", },
 572	{ .offset = 0x99,	.name = "tx_green_prio_3", },
 573	{ .offset = 0x9A,	.name = "tx_green_prio_4", },
 574	{ .offset = 0x9B,	.name = "tx_green_prio_5", },
 575	{ .offset = 0x9C,	.name = "tx_green_prio_6", },
 576	{ .offset = 0x9D,	.name = "tx_green_prio_7", },
 577	{ .offset = 0x9E,	.name = "tx_aged", },
 578	{ .offset = 0x100,	.name = "drop_local", },
 579	{ .offset = 0x101,	.name = "drop_tail", },
 580	{ .offset = 0x102,	.name = "drop_yellow_prio_0", },
 581	{ .offset = 0x103,	.name = "drop_yellow_prio_1", },
 582	{ .offset = 0x104,	.name = "drop_yellow_prio_2", },
 583	{ .offset = 0x105,	.name = "drop_yellow_prio_3", },
 584	{ .offset = 0x106,	.name = "drop_yellow_prio_4", },
 585	{ .offset = 0x107,	.name = "drop_yellow_prio_5", },
 586	{ .offset = 0x108,	.name = "drop_yellow_prio_6", },
 587	{ .offset = 0x109,	.name = "drop_yellow_prio_7", },
 588	{ .offset = 0x10A,	.name = "drop_green_prio_0", },
 589	{ .offset = 0x10B,	.name = "drop_green_prio_1", },
 590	{ .offset = 0x10C,	.name = "drop_green_prio_2", },
 591	{ .offset = 0x10D,	.name = "drop_green_prio_3", },
 592	{ .offset = 0x10E,	.name = "drop_green_prio_4", },
 593	{ .offset = 0x10F,	.name = "drop_green_prio_5", },
 594	{ .offset = 0x110,	.name = "drop_green_prio_6", },
 595	{ .offset = 0x111,	.name = "drop_green_prio_7", },
 596};
 597
 598static struct vcap_field vsc9959_vcap_is2_keys[] = {
 599	/* Common: 41 bits */
 600	[VCAP_IS2_TYPE]				= {  0,   4},
 601	[VCAP_IS2_HK_FIRST]			= {  4,   1},
 602	[VCAP_IS2_HK_PAG]			= {  5,   8},
 603	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,   7},
 604	[VCAP_IS2_HK_RSV2]			= { 20,   1},
 605	[VCAP_IS2_HK_HOST_MATCH]		= { 21,   1},
 606	[VCAP_IS2_HK_L2_MC]			= { 22,   1},
 607	[VCAP_IS2_HK_L2_BC]			= { 23,   1},
 608	[VCAP_IS2_HK_VLAN_TAGGED]		= { 24,   1},
 609	[VCAP_IS2_HK_VID]			= { 25,  12},
 610	[VCAP_IS2_HK_DEI]			= { 37,   1},
 611	[VCAP_IS2_HK_PCP]			= { 38,   3},
 612	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
 613	[VCAP_IS2_HK_L2_DMAC]			= { 41,  48},
 614	[VCAP_IS2_HK_L2_SMAC]			= { 89,  48},
 615	/* MAC_ETYPE (TYPE=000) */
 616	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {137,  16},
 617	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {153,  16},
 618	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {169,   8},
 619	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {177,   3},
 620	/* MAC_LLC (TYPE=001) */
 621	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {137,  40},
 622	/* MAC_SNAP (TYPE=010) */
 623	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {137,  40},
 624	/* MAC_ARP (TYPE=011) */
 625	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 41,  48},
 626	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 89,   1},
 627	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 90,   1},
 628	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 91,   1},
 629	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 92,   1},
 630	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 93,   1},
 631	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 94,   1},
 632	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= { 95,   2},
 633	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= { 97,  32},
 634	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {129,  32},
 635	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {161,   1},
 636	/* IP4_TCP_UDP / IP4_OTHER common */
 637	[VCAP_IS2_HK_IP4]			= { 41,   1},
 638	[VCAP_IS2_HK_L3_FRAGMENT]		= { 42,   1},
 639	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 43,   1},
 640	[VCAP_IS2_HK_L3_OPTIONS]		= { 44,   1},
 641	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 45,   1},
 642	[VCAP_IS2_HK_L3_TOS]			= { 46,   8},
 643	[VCAP_IS2_HK_L3_IP4_DIP]		= { 54,  32},
 644	[VCAP_IS2_HK_L3_IP4_SIP]		= { 86,  32},
 645	[VCAP_IS2_HK_DIP_EQ_SIP]		= {118,   1},
 646	/* IP4_TCP_UDP (TYPE=100) */
 647	[VCAP_IS2_HK_TCP]			= {119,   1},
 648	[VCAP_IS2_HK_L4_DPORT]			= {120,  16},
 649	[VCAP_IS2_HK_L4_SPORT]			= {136,  16},
 650	[VCAP_IS2_HK_L4_RNG]			= {152,   8},
 651	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {160,   1},
 652	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {161,   1},
 653	[VCAP_IS2_HK_L4_FIN]			= {162,   1},
 654	[VCAP_IS2_HK_L4_SYN]			= {163,   1},
 655	[VCAP_IS2_HK_L4_RST]			= {164,   1},
 656	[VCAP_IS2_HK_L4_PSH]			= {165,   1},
 657	[VCAP_IS2_HK_L4_ACK]			= {166,   1},
 658	[VCAP_IS2_HK_L4_URG]			= {167,   1},
 659	[VCAP_IS2_HK_L4_1588_DOM]		= {168,   8},
 660	[VCAP_IS2_HK_L4_1588_VER]		= {176,   4},
 661	/* IP4_OTHER (TYPE=101) */
 662	[VCAP_IS2_HK_IP4_L3_PROTO]		= {119,   8},
 663	[VCAP_IS2_HK_L3_PAYLOAD]		= {127,  56},
 664	/* IP6_STD (TYPE=110) */
 665	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 41,   1},
 666	[VCAP_IS2_HK_L3_IP6_SIP]		= { 42, 128},
 667	[VCAP_IS2_HK_IP6_L3_PROTO]		= {170,   8},
 668	/* OAM (TYPE=111) */
 669	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= {137,   7},
 670	[VCAP_IS2_HK_OAM_VER]			= {144,   5},
 671	[VCAP_IS2_HK_OAM_OPCODE]		= {149,   8},
 672	[VCAP_IS2_HK_OAM_FLAGS]			= {157,   8},
 673	[VCAP_IS2_HK_OAM_MEPID]			= {165,  16},
 674	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= {181,   1},
 675	[VCAP_IS2_HK_OAM_IS_Y1731]		= {182,   1},
 676};
 677
 678static struct vcap_field vsc9959_vcap_is2_actions[] = {
 679	[VCAP_IS2_ACT_HIT_ME_ONCE]		= {  0,  1},
 680	[VCAP_IS2_ACT_CPU_COPY_ENA]		= {  1,  1},
 681	[VCAP_IS2_ACT_CPU_QU_NUM]		= {  2,  3},
 682	[VCAP_IS2_ACT_MASK_MODE]		= {  5,  2},
 683	[VCAP_IS2_ACT_MIRROR_ENA]		= {  7,  1},
 684	[VCAP_IS2_ACT_LRN_DIS]			= {  8,  1},
 685	[VCAP_IS2_ACT_POLICE_ENA]		= {  9,  1},
 686	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9},
 687	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1},
 688	[VCAP_IS2_ACT_PORT_MASK]		= { 20,  6},
 689	[VCAP_IS2_ACT_REW_OP]			= { 26,  9},
 690	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 35,  1},
 691	[VCAP_IS2_ACT_RSV]			= { 36,  2},
 692	[VCAP_IS2_ACT_ACL_ID]			= { 38,  6},
 693	[VCAP_IS2_ACT_HIT_CNT]			= { 44, 32},
 694};
 695
 696static const struct vcap_props vsc9959_vcap_props[] = {
 697	[VCAP_IS2] = {
 698		.tg_width = 2,
 699		.sw_count = 4,
 700		.entry_count = VSC9959_VCAP_IS2_CNT,
 701		.entry_width = VSC9959_VCAP_IS2_ENTRY_WIDTH,
 702		.action_count = VSC9959_VCAP_IS2_CNT +
 703				VSC9959_VCAP_PORT_CNT + 2,
 704		.action_width = 89,
 705		.action_type_width = 1,
 706		.action_table = {
 707			[IS2_ACTION_TYPE_NORMAL] = {
 708				.width = 44,
 709				.count = 2
 710			},
 711			[IS2_ACTION_TYPE_SMAC_SIP] = {
 712				.width = 6,
 713				.count = 4
 714			},
 715		},
 716		.counter_words = 4,
 717		.counter_width = 32,
 718	},
 719};
 720
 721#define VSC9959_INIT_TIMEOUT			50000
 722#define VSC9959_GCB_RST_SLEEP			100
 723#define VSC9959_SYS_RAMINIT_SLEEP		80
 724
 725static int vsc9959_gcb_soft_rst_status(struct ocelot *ocelot)
 726{
 727	int val;
 728
 729	regmap_field_read(ocelot->regfields[GCB_SOFT_RST_SWC_RST], &val);
 730
 731	return val;
 732}
 733
 734static int vsc9959_sys_ram_init_status(struct ocelot *ocelot)
 735{
 736	return ocelot_read(ocelot, SYS_RAM_INIT);
 737}
 738
 739static int vsc9959_reset(struct ocelot *ocelot)
 740{
 741	int val, err;
 742
 743	/* soft-reset the switch core */
 744	regmap_field_write(ocelot->regfields[GCB_SOFT_RST_SWC_RST], 1);
 745
 746	err = readx_poll_timeout(vsc9959_gcb_soft_rst_status, ocelot, val, !val,
 747				 VSC9959_GCB_RST_SLEEP, VSC9959_INIT_TIMEOUT);
 748	if (err) {
 749		dev_err(ocelot->dev, "timeout: switch core reset\n");
 750		return err;
 751	}
 752
 753	/* initialize switch mem ~40us */
 754	ocelot_write(ocelot, SYS_RAM_INIT_RAM_INIT, SYS_RAM_INIT);
 755	err = readx_poll_timeout(vsc9959_sys_ram_init_status, ocelot, val, !val,
 756				 VSC9959_SYS_RAMINIT_SLEEP,
 757				 VSC9959_INIT_TIMEOUT);
 758	if (err) {
 759		dev_err(ocelot->dev, "timeout: switch sram init\n");
 760		return err;
 761	}
 762
 763	/* enable switch core */
 764	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
 765
 766	return 0;
 767}
 768
 769/* We enable SGMII AN only when the PHY has managed = "in-band-status" in the
 770 * device tree. If we are in MLO_AN_PHY mode, we program directly state->speed
 771 * into the PCS, which is retrieved out-of-band over MDIO. This also has the
 772 * benefit of working with SGMII fixed-links, like downstream switches, where
 773 * both link partners attempt to operate as AN slaves and therefore AN never
 774 * completes.  But it also has the disadvantage that some PHY chips don't pass
 775 * traffic if SGMII AN is enabled but not completed (acknowledged by us), so
 776 * setting MLO_AN_INBAND is actually required for those.
 777 */
 778static void vsc9959_pcs_config_sgmii(struct phy_device *pcs,
 779				     unsigned int link_an_mode,
 780				     const struct phylink_link_state *state)
 781{
 782	int bmsr, bmcr;
 783
 784	/* Some PHYs like VSC8234 don't like it when AN restarts on
 785	 * their system  side and they restart line side AN too, going
 786	 * into an endless link up/down loop.  Don't restart PCS AN if
 787	 * link is up already.
 788	 * We do check that AN is enabled just in case this is the 1st
 789	 * call, PCS detects a carrier but AN is disabled from power on
 790	 * or by boot loader.
 791	 */
 792	bmcr = phy_read(pcs, MII_BMCR);
 793	if (bmcr < 0)
 794		return;
 795
 796	bmsr = phy_read(pcs, MII_BMSR);
 797	if (bmsr < 0)
 798		return;
 799
 800	if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_LSTATUS))
 801		return;
 802
 803	/* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
 804	 * for the MAC PCS in order to acknowledge the AN.
 805	 */
 806	phy_write(pcs, MII_ADVERTISE, ADVERTISE_SGMII |
 807				      ADVERTISE_LPACK);
 808
 809	phy_write(pcs, ENETC_PCS_IF_MODE,
 810		  ENETC_PCS_IF_MODE_SGMII_EN |
 811		  ENETC_PCS_IF_MODE_USE_SGMII_AN);
 812
 813	/* Adjust link timer for SGMII */
 814	phy_write(pcs, ENETC_PCS_LINK_TIMER1,
 815		  ENETC_PCS_LINK_TIMER1_VAL);
 816	phy_write(pcs, ENETC_PCS_LINK_TIMER2,
 817		  ENETC_PCS_LINK_TIMER2_VAL);
 818
 819	phy_set_bits(pcs, MII_BMCR, BMCR_ANENABLE);
 820}
 821
 822static void vsc9959_pcs_config_usxgmii(struct phy_device *pcs,
 823				       unsigned int link_an_mode,
 824				       const struct phylink_link_state *state)
 825{
 826	/* Configure device ability for the USXGMII Replicator */
 827	phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_ADVERTISE,
 828		      MDIO_USXGMII_2500FULL |
 829		      MDIO_USXGMII_LINK |
 830		      ADVERTISE_SGMII |
 831		      ADVERTISE_LPACK);
 832}
 833
 834void vsc9959_pcs_config(struct ocelot *ocelot, int port,
 835			unsigned int link_an_mode,
 836			const struct phylink_link_state *state)
 837{
 838	struct felix *felix = ocelot_to_felix(ocelot);
 839	struct phy_device *pcs = felix->pcs[port];
 840
 841	if (!pcs)
 842		return;
 843
 844	/* The PCS does not implement the BMSR register fully, so capability
 845	 * detection via genphy_read_abilities does not work. Since we can get
 846	 * the PHY config word from the LPA register though, there is still
 847	 * value in using the generic phy_resolve_aneg_linkmode function. So
 848	 * populate the supported and advertising link modes manually here.
 849	 */
 850	linkmode_set_bit_array(phy_basic_ports_array,
 851			       ARRAY_SIZE(phy_basic_ports_array),
 852			       pcs->supported);
 853	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, pcs->supported);
 854	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pcs->supported);
 855	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, pcs->supported);
 856	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pcs->supported);
 857	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, pcs->supported);
 858	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pcs->supported);
 859	if (pcs->interface == PHY_INTERFACE_MODE_2500BASEX ||
 860	    pcs->interface == PHY_INTERFACE_MODE_USXGMII)
 861		linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
 862				 pcs->supported);
 863	if (pcs->interface != PHY_INTERFACE_MODE_2500BASEX)
 864		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 865				 pcs->supported);
 866	phy_advertise_supported(pcs);
 867
 868	if (!phylink_autoneg_inband(link_an_mode))
 869		return;
 870
 871	switch (pcs->interface) {
 872	case PHY_INTERFACE_MODE_SGMII:
 873	case PHY_INTERFACE_MODE_QSGMII:
 874		vsc9959_pcs_config_sgmii(pcs, link_an_mode, state);
 875		break;
 876	case PHY_INTERFACE_MODE_2500BASEX:
 877		phydev_err(pcs, "AN not supported on 3.125GHz SerDes lane\n");
 878		break;
 879	case PHY_INTERFACE_MODE_USXGMII:
 880		vsc9959_pcs_config_usxgmii(pcs, link_an_mode, state);
 881		break;
 882	default:
 883		dev_err(ocelot->dev, "Unsupported link mode %s\n",
 884			phy_modes(pcs->interface));
 885	}
 886}
 887
 888static void vsc9959_pcs_link_up_sgmii(struct phy_device *pcs,
 889				      unsigned int link_an_mode,
 890				      int speed, int duplex)
 891{
 892	u16 if_mode = ENETC_PCS_IF_MODE_SGMII_EN;
 893
 894	switch (speed) {
 895	case SPEED_1000:
 896		if_mode |= ENETC_PCS_IF_MODE_SGMII_SPEED(ENETC_PCS_SPEED_1000);
 897		break;
 898	case SPEED_100:
 899		if_mode |= ENETC_PCS_IF_MODE_SGMII_SPEED(ENETC_PCS_SPEED_100);
 900		break;
 901	case SPEED_10:
 902		if_mode |= ENETC_PCS_IF_MODE_SGMII_SPEED(ENETC_PCS_SPEED_10);
 903		break;
 904	default:
 905		phydev_err(pcs, "Invalid PCS speed %d\n", speed);
 906		return;
 907	}
 908
 909	if (duplex == DUPLEX_HALF)
 910		if_mode |= ENETC_PCS_IF_MODE_DUPLEX_HALF;
 911
 912	phy_write(pcs, ENETC_PCS_IF_MODE, if_mode);
 913	phy_clear_bits(pcs, MII_BMCR, BMCR_ANENABLE);
 914}
 915
 916/* 2500Base-X is SerDes protocol 7 on Felix and 6 on ENETC. It is a SerDes lane
 917 * clocked at 3.125 GHz which encodes symbols with 8b/10b and does not have
 918 * auto-negotiation of any link parameters. Electrically it is compatible with
 919 * a single lane of XAUI.
 920 * The hardware reference manual wants to call this mode SGMII, but it isn't
 921 * really, since the fundamental features of SGMII:
 922 * - Downgrading the link speed by duplicating symbols
 923 * - Auto-negotiation
 924 * are not there.
 925 * The speed is configured at 1000 in the IF_MODE and BMCR MDIO registers
 926 * because the clock frequency is actually given by a PLL configured in the
 927 * Reset Configuration Word (RCW).
 928 * Since there is no difference between fixed speed SGMII w/o AN and 802.3z w/o
 929 * AN, we call this PHY interface type 2500Base-X. In case a PHY negotiates a
 930 * lower link speed on line side, the system-side interface remains fixed at
 931 * 2500 Mbps and we do rate adaptation through pause frames.
 932 */
 933static void vsc9959_pcs_link_up_2500basex(struct phy_device *pcs,
 934					  unsigned int link_an_mode,
 935					  int speed, int duplex)
 936{
 937	u16 if_mode = ENETC_PCS_IF_MODE_SGMII_SPEED(ENETC_PCS_SPEED_2500) |
 938		      ENETC_PCS_IF_MODE_SGMII_EN;
 939
 940	if (duplex == DUPLEX_HALF)
 941		if_mode |= ENETC_PCS_IF_MODE_DUPLEX_HALF;
 942
 943	phy_write(pcs, ENETC_PCS_IF_MODE, if_mode);
 944	phy_clear_bits(pcs, MII_BMCR, BMCR_ANENABLE);
 945}
 946
 947void vsc9959_pcs_link_up(struct ocelot *ocelot, int port,
 948			 unsigned int link_an_mode,
 949			 phy_interface_t interface,
 950			 int speed, int duplex)
 951{
 952	struct felix *felix = ocelot_to_felix(ocelot);
 953	struct phy_device *pcs = felix->pcs[port];
 954
 955	if (!pcs)
 956		return;
 957
 958	if (phylink_autoneg_inband(link_an_mode))
 959		return;
 960
 961	switch (interface) {
 962	case PHY_INTERFACE_MODE_SGMII:
 963	case PHY_INTERFACE_MODE_QSGMII:
 964		vsc9959_pcs_link_up_sgmii(pcs, link_an_mode, speed, duplex);
 965		break;
 966	case PHY_INTERFACE_MODE_2500BASEX:
 967		vsc9959_pcs_link_up_2500basex(pcs, link_an_mode, speed,
 968					      duplex);
 969		break;
 970	case PHY_INTERFACE_MODE_USXGMII:
 971		phydev_err(pcs, "USXGMII only supports in-band AN for now\n");
 972		break;
 973	default:
 974		dev_err(ocelot->dev, "Unsupported link mode %s\n",
 975			phy_modes(pcs->interface));
 976	}
 977}
 978
 979static void vsc9959_pcs_link_state_resolve(struct phy_device *pcs,
 980					   struct phylink_link_state *state)
 981{
 982	state->an_complete = pcs->autoneg_complete;
 983	state->an_enabled = pcs->autoneg;
 984	state->link = pcs->link;
 985	state->duplex = pcs->duplex;
 986	state->speed = pcs->speed;
 987	/* SGMII AN does not negotiate flow control, but that's ok,
 988	 * since phylink already knows that, and does:
 989	 *	link_state.pause |= pl->phy_state.pause;
 990	 */
 991	state->pause = MLO_PAUSE_NONE;
 992
 993	phydev_dbg(pcs,
 994		   "mode=%s/%s/%s adv=%*pb lpa=%*pb link=%u an_enabled=%u an_complete=%u\n",
 995		   phy_modes(pcs->interface),
 996		   phy_speed_to_str(pcs->speed),
 997		   phy_duplex_to_str(pcs->duplex),
 998		   __ETHTOOL_LINK_MODE_MASK_NBITS, pcs->advertising,
 999		   __ETHTOOL_LINK_MODE_MASK_NBITS, pcs->lp_advertising,
1000		   pcs->link, pcs->autoneg, pcs->autoneg_complete);
1001}
1002
1003static void vsc9959_pcs_link_state_sgmii(struct phy_device *pcs,
1004					 struct phylink_link_state *state)
1005{
1006	int err;
1007
1008	err = genphy_update_link(pcs);
1009	if (err < 0)
1010		return;
1011
1012	if (pcs->autoneg_complete) {
1013		u16 lpa = phy_read(pcs, MII_LPA);
1014
1015		mii_lpa_to_linkmode_lpa_sgmii(pcs->lp_advertising, lpa);
1016
1017		phy_resolve_aneg_linkmode(pcs);
1018	}
1019}
1020
1021static void vsc9959_pcs_link_state_2500basex(struct phy_device *pcs,
1022					     struct phylink_link_state *state)
1023{
1024	int err;
1025
1026	err = genphy_update_link(pcs);
1027	if (err < 0)
1028		return;
1029
1030	pcs->speed = SPEED_2500;
1031	pcs->asym_pause = true;
1032	pcs->pause = true;
1033}
1034
1035static void vsc9959_pcs_link_state_usxgmii(struct phy_device *pcs,
1036					   struct phylink_link_state *state)
1037{
1038	int status, lpa;
1039
1040	status = phy_read_mmd(pcs, MDIO_MMD_VEND2, MII_BMSR);
1041	if (status < 0)
1042		return;
1043
1044	pcs->autoneg = true;
1045	pcs->autoneg_complete = !!(status & BMSR_ANEGCOMPLETE);
1046	pcs->link = !!(status & BMSR_LSTATUS);
1047
1048	if (!pcs->link || !pcs->autoneg_complete)
1049		return;
1050
1051	lpa = phy_read_mmd(pcs, MDIO_MMD_VEND2, MII_LPA);
1052	if (lpa < 0)
1053		return;
1054
1055	switch (lpa & MDIO_USXGMII_SPD_MASK) {
1056	case MDIO_USXGMII_10:
1057		pcs->speed = SPEED_10;
1058		break;
1059	case MDIO_USXGMII_100:
1060		pcs->speed = SPEED_100;
1061		break;
1062	case MDIO_USXGMII_1000:
1063		pcs->speed = SPEED_1000;
1064		break;
1065	case MDIO_USXGMII_2500:
1066		pcs->speed = SPEED_2500;
1067		break;
1068	default:
1069		break;
1070	}
1071
1072	if (lpa & MDIO_USXGMII_FULL_DUPLEX)
1073		pcs->duplex = DUPLEX_FULL;
1074	else
1075		pcs->duplex = DUPLEX_HALF;
1076}
1077
1078void vsc9959_pcs_link_state(struct ocelot *ocelot, int port,
1079			    struct phylink_link_state *state)
1080{
1081	struct felix *felix = ocelot_to_felix(ocelot);
1082	struct phy_device *pcs = felix->pcs[port];
1083
1084	if (!pcs)
1085		return;
1086
1087	pcs->speed = SPEED_UNKNOWN;
1088	pcs->duplex = DUPLEX_UNKNOWN;
1089	pcs->pause = 0;
1090	pcs->asym_pause = 0;
1091
1092	switch (pcs->interface) {
1093	case PHY_INTERFACE_MODE_SGMII:
1094	case PHY_INTERFACE_MODE_QSGMII:
1095		vsc9959_pcs_link_state_sgmii(pcs, state);
1096		break;
1097	case PHY_INTERFACE_MODE_2500BASEX:
1098		vsc9959_pcs_link_state_2500basex(pcs, state);
1099		break;
1100	case PHY_INTERFACE_MODE_USXGMII:
1101		vsc9959_pcs_link_state_usxgmii(pcs, state);
1102		break;
1103	default:
1104		return;
1105	}
1106
1107	vsc9959_pcs_link_state_resolve(pcs, state);
1108}
1109
1110static void vsc9959_phylink_validate(struct ocelot *ocelot, int port,
1111				     unsigned long *supported,
1112				     struct phylink_link_state *state)
1113{
1114	struct ocelot_port *ocelot_port = ocelot->ports[port];
1115	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
1116
1117	if (state->interface != PHY_INTERFACE_MODE_NA &&
1118	    state->interface != ocelot_port->phy_mode) {
1119		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
1120		return;
1121	}
1122
1123	phylink_set_port_modes(mask);
1124	phylink_set(mask, Autoneg);
1125	phylink_set(mask, Pause);
1126	phylink_set(mask, Asym_Pause);
1127	phylink_set(mask, 10baseT_Half);
1128	phylink_set(mask, 10baseT_Full);
1129	phylink_set(mask, 100baseT_Half);
1130	phylink_set(mask, 100baseT_Full);
1131	phylink_set(mask, 1000baseT_Half);
1132	phylink_set(mask, 1000baseT_Full);
1133
1134	if (state->interface == PHY_INTERFACE_MODE_INTERNAL ||
1135	    state->interface == PHY_INTERFACE_MODE_2500BASEX ||
1136	    state->interface == PHY_INTERFACE_MODE_USXGMII) {
1137		phylink_set(mask, 2500baseT_Full);
1138		phylink_set(mask, 2500baseX_Full);
1139	}
1140
1141	bitmap_and(supported, supported, mask,
1142		   __ETHTOOL_LINK_MODE_MASK_NBITS);
1143	bitmap_and(state->advertising, state->advertising, mask,
1144		   __ETHTOOL_LINK_MODE_MASK_NBITS);
1145}
1146
1147static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port,
1148					phy_interface_t phy_mode)
1149{
1150	switch (phy_mode) {
1151	case PHY_INTERFACE_MODE_INTERNAL:
1152		if (port != 4 && port != 5)
1153			return -ENOTSUPP;
1154		return 0;
1155	case PHY_INTERFACE_MODE_SGMII:
1156	case PHY_INTERFACE_MODE_QSGMII:
1157	case PHY_INTERFACE_MODE_USXGMII:
1158	case PHY_INTERFACE_MODE_2500BASEX:
1159		/* Not supported on internal to-CPU ports */
1160		if (port == 4 || port == 5)
1161			return -ENOTSUPP;
1162		return 0;
1163	default:
1164		return -ENOTSUPP;
1165	}
1166}
1167
1168/* Watermark encode
1169 * Bit 8:   Unit; 0:1, 1:16
1170 * Bit 7-0: Value to be multiplied with unit
1171 */
1172static u16 vsc9959_wm_enc(u16 value)
1173{
1174	WARN_ON(value >= 16 * BIT(8));
1175
1176	if (value >= BIT(8))
1177		return BIT(8) | (value / 16);
1178
1179	return value;
1180}
1181
1182static const struct ocelot_ops vsc9959_ops = {
1183	.reset			= vsc9959_reset,
1184	.wm_enc			= vsc9959_wm_enc,
1185};
1186
1187static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
1188{
1189	struct felix *felix = ocelot_to_felix(ocelot);
1190	struct enetc_mdio_priv *mdio_priv;
1191	struct device *dev = ocelot->dev;
1192	void __iomem *imdio_regs;
1193	struct resource res;
1194	struct enetc_hw *hw;
1195	struct mii_bus *bus;
1196	int port;
1197	int rc;
1198
1199	felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
1200				  sizeof(struct phy_device *),
1201				  GFP_KERNEL);
1202	if (!felix->pcs) {
1203		dev_err(dev, "failed to allocate array for PCS PHYs\n");
1204		return -ENOMEM;
1205	}
1206
1207	memcpy(&res, felix->info->imdio_res, sizeof(res));
1208	res.flags = IORESOURCE_MEM;
1209	res.start += felix->imdio_base;
1210	res.end += felix->imdio_base;
1211
1212	imdio_regs = devm_ioremap_resource(dev, &res);
1213	if (IS_ERR(imdio_regs)) {
1214		dev_err(dev, "failed to map internal MDIO registers\n");
1215		return PTR_ERR(imdio_regs);
1216	}
1217
1218	hw = enetc_hw_alloc(dev, imdio_regs);
1219	if (IS_ERR(hw)) {
1220		dev_err(dev, "failed to allocate ENETC HW structure\n");
1221		return PTR_ERR(hw);
1222	}
1223
1224	bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
1225	if (!bus)
1226		return -ENOMEM;
1227
1228	bus->name = "VSC9959 internal MDIO bus";
1229	bus->read = enetc_mdio_read;
1230	bus->write = enetc_mdio_write;
1231	bus->parent = dev;
1232	mdio_priv = bus->priv;
1233	mdio_priv->hw = hw;
1234	/* This gets added to imdio_regs, which already maps addresses
1235	 * starting with the proper offset.
1236	 */
1237	mdio_priv->mdio_base = 0;
1238	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
1239
1240	/* Needed in order to initialize the bus mutex lock */
1241	rc = mdiobus_register(bus);
1242	if (rc < 0) {
1243		dev_err(dev, "failed to register MDIO bus\n");
1244		return rc;
1245	}
1246
1247	felix->imdio = bus;
1248
1249	for (port = 0; port < felix->info->num_ports; port++) {
1250		struct ocelot_port *ocelot_port = ocelot->ports[port];
1251		struct phy_device *pcs;
1252		bool is_c45 = false;
1253
1254		if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_USXGMII)
1255			is_c45 = true;
1256
1257		pcs = get_phy_device(felix->imdio, port, is_c45);
1258		if (IS_ERR(pcs))
1259			continue;
1260
1261		pcs->interface = ocelot_port->phy_mode;
1262		felix->pcs[port] = pcs;
1263
1264		dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
1265	}
1266
1267	return 0;
1268}
1269
1270void vsc9959_mdio_bus_free(struct ocelot *ocelot)
1271{
1272	struct felix *felix = ocelot_to_felix(ocelot);
1273	int port;
1274
1275	for (port = 0; port < ocelot->num_phys_ports; port++) {
1276		struct phy_device *pcs = felix->pcs[port];
1277
1278		if (!pcs)
1279			continue;
1280
1281		put_device(&pcs->mdio.dev);
1282	}
1283	mdiobus_unregister(felix->imdio);
1284}
1285
1286static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
1287				    u32 speed)
1288{
1289	u8 tas_speed;
1290
1291	switch (speed) {
1292	case SPEED_10:
1293		tas_speed = OCELOT_SPEED_10;
1294		break;
1295	case SPEED_100:
1296		tas_speed = OCELOT_SPEED_100;
1297		break;
1298	case SPEED_1000:
1299		tas_speed = OCELOT_SPEED_1000;
1300		break;
1301	case SPEED_2500:
1302		tas_speed = OCELOT_SPEED_2500;
1303		break;
1304	default:
1305		tas_speed = OCELOT_SPEED_1000;
1306		break;
1307	}
1308
1309	ocelot_rmw_rix(ocelot,
1310		       QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
1311		       QSYS_TAG_CONFIG_LINK_SPEED_M,
1312		       QSYS_TAG_CONFIG, port);
1313}
1314
1315static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
1316				  u64 cycle_time,
1317				  struct timespec64 *new_base_ts)
1318{
1319	struct timespec64 ts;
1320	ktime_t new_base_time;
1321	ktime_t current_time;
1322
1323	ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
1324	current_time = timespec64_to_ktime(ts);
1325	new_base_time = base_time;
1326
1327	if (base_time < current_time) {
1328		u64 nr_of_cycles = current_time - base_time;
1329
1330		do_div(nr_of_cycles, cycle_time);
1331		new_base_time += cycle_time * (nr_of_cycles + 1);
1332	}
1333
1334	*new_base_ts = ktime_to_timespec64(new_base_time);
1335}
1336
1337static u32 vsc9959_tas_read_cfg_status(struct ocelot *ocelot)
1338{
1339	return ocelot_read(ocelot, QSYS_TAS_PARAM_CFG_CTRL);
1340}
1341
1342static void vsc9959_tas_gcl_set(struct ocelot *ocelot, const u32 gcl_ix,
1343				struct tc_taprio_sched_entry *entry)
1344{
1345	ocelot_write(ocelot,
1346		     QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM(gcl_ix) |
1347		     QSYS_GCL_CFG_REG_1_GATE_STATE(entry->gate_mask),
1348		     QSYS_GCL_CFG_REG_1);
1349	ocelot_write(ocelot, entry->interval, QSYS_GCL_CFG_REG_2);
1350}
1351
1352static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
1353				    struct tc_taprio_qopt_offload *taprio)
1354{
1355	struct timespec64 base_ts;
1356	int ret, i;
1357	u32 val;
1358
1359	if (!taprio->enable) {
1360		ocelot_rmw_rix(ocelot,
1361			       QSYS_TAG_CONFIG_INIT_GATE_STATE(0xFF),
1362			       QSYS_TAG_CONFIG_ENABLE |
1363			       QSYS_TAG_CONFIG_INIT_GATE_STATE_M,
1364			       QSYS_TAG_CONFIG, port);
1365
1366		return 0;
1367	}
1368
1369	if (taprio->cycle_time > NSEC_PER_SEC ||
1370	    taprio->cycle_time_extension >= NSEC_PER_SEC)
1371		return -EINVAL;
1372
1373	if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX)
1374		return -ERANGE;
1375
1376	ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port) |
1377		   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
1378		   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M |
1379		   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
1380		   QSYS_TAS_PARAM_CFG_CTRL);
1381
1382	/* Hardware errata -  Admin config could not be overwritten if
1383	 * config is pending, need reset the TAS module
1384	 */
1385	val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);
1386	if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING)
1387		return  -EBUSY;
1388
1389	ocelot_rmw_rix(ocelot,
1390		       QSYS_TAG_CONFIG_ENABLE |
1391		       QSYS_TAG_CONFIG_INIT_GATE_STATE(0xFF) |
1392		       QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES(0xFF),
1393		       QSYS_TAG_CONFIG_ENABLE |
1394		       QSYS_TAG_CONFIG_INIT_GATE_STATE_M |
1395		       QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES_M,
1396		       QSYS_TAG_CONFIG, port);
1397
1398	vsc9959_new_base_time(ocelot, taprio->base_time,
1399			      taprio->cycle_time, &base_ts);
1400	ocelot_write(ocelot, base_ts.tv_nsec, QSYS_PARAM_CFG_REG_1);
1401	ocelot_write(ocelot, lower_32_bits(base_ts.tv_sec), QSYS_PARAM_CFG_REG_2);
1402	val = upper_32_bits(base_ts.tv_sec);
1403	ocelot_write(ocelot,
1404		     QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB(val) |
1405		     QSYS_PARAM_CFG_REG_3_LIST_LENGTH(taprio->num_entries),
1406		     QSYS_PARAM_CFG_REG_3);
1407	ocelot_write(ocelot, taprio->cycle_time, QSYS_PARAM_CFG_REG_4);
1408	ocelot_write(ocelot, taprio->cycle_time_extension, QSYS_PARAM_CFG_REG_5);
1409
1410	for (i = 0; i < taprio->num_entries; i++)
1411		vsc9959_tas_gcl_set(ocelot, i, &taprio->entries[i]);
1412
1413	ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,
1414		   QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,
1415		   QSYS_TAS_PARAM_CFG_CTRL);
1416
1417	ret = readx_poll_timeout(vsc9959_tas_read_cfg_status, ocelot, val,
1418				 !(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE),
1419				 10, 100000);
1420
1421	return ret;
1422}
1423
1424static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
1425				    struct tc_cbs_qopt_offload *cbs_qopt)
1426{
1427	struct ocelot *ocelot = ds->priv;
1428	int port_ix = port * 8 + cbs_qopt->queue;
1429	u32 rate, burst;
1430
1431	if (cbs_qopt->queue >= ds->num_tx_queues)
1432		return -EINVAL;
1433
1434	if (!cbs_qopt->enable) {
1435		ocelot_write_gix(ocelot, QSYS_CIR_CFG_CIR_RATE(0) |
1436				 QSYS_CIR_CFG_CIR_BURST(0),
1437				 QSYS_CIR_CFG, port_ix);
1438
1439		ocelot_rmw_gix(ocelot, 0, QSYS_SE_CFG_SE_AVB_ENA,
1440			       QSYS_SE_CFG, port_ix);
1441
1442		return 0;
1443	}
1444
1445	/* Rate unit is 100 kbps */
1446	rate = DIV_ROUND_UP(cbs_qopt->idleslope, 100);
1447	/* Avoid using zero rate */
1448	rate = clamp_t(u32, rate, 1, GENMASK(14, 0));
1449	/* Burst unit is 4kB */
1450	burst = DIV_ROUND_UP(cbs_qopt->hicredit, 4096);
1451	/* Avoid using zero burst size */
1452	burst = clamp_t(u32, burst, 1, GENMASK(5, 0));
1453	ocelot_write_gix(ocelot,
1454			 QSYS_CIR_CFG_CIR_RATE(rate) |
1455			 QSYS_CIR_CFG_CIR_BURST(burst),
1456			 QSYS_CIR_CFG,
1457			 port_ix);
1458
1459	ocelot_rmw_gix(ocelot,
1460		       QSYS_SE_CFG_SE_FRM_MODE(0) |
1461		       QSYS_SE_CFG_SE_AVB_ENA,
1462		       QSYS_SE_CFG_SE_AVB_ENA |
1463		       QSYS_SE_CFG_SE_FRM_MODE_M,
1464		       QSYS_SE_CFG,
1465		       port_ix);
1466
1467	return 0;
1468}
1469
1470static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
1471				 enum tc_setup_type type,
1472				 void *type_data)
1473{
1474	struct ocelot *ocelot = ds->priv;
1475
1476	switch (type) {
1477	case TC_SETUP_QDISC_TAPRIO:
1478		return vsc9959_qos_port_tas_set(ocelot, port, type_data);
1479	case TC_SETUP_QDISC_CBS:
1480		return vsc9959_qos_port_cbs_set(ds, port, type_data);
1481	default:
1482		return -EOPNOTSUPP;
1483	}
1484}
1485
1486static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port)
1487{
1488	struct ocelot_port *ocelot_port = ocelot->ports[port];
1489	u8 *template = ocelot_port->xmit_template;
1490	u64 bypass, dest, src;
1491
1492	/* Set the source port as the CPU port module and not the
1493	 * NPI port
1494	 */
1495	src = ocelot->num_phys_ports;
1496	dest = BIT(port);
1497	bypass = true;
1498
1499	packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
1500	packing(template, &dest,    68,  56, OCELOT_TAG_LEN, PACK, 0);
1501	packing(template, &src,     46,  43, OCELOT_TAG_LEN, PACK, 0);
1502}
1503
1504static const struct felix_info felix_info_vsc9959 = {
1505	.target_io_res		= vsc9959_target_io_res,
1506	.port_io_res		= vsc9959_port_io_res,
1507	.imdio_res		= &vsc9959_imdio_res,
1508	.regfields		= vsc9959_regfields,
1509	.map			= vsc9959_regmap,
1510	.ops			= &vsc9959_ops,
1511	.stats_layout		= vsc9959_stats_layout,
1512	.num_stats		= ARRAY_SIZE(vsc9959_stats_layout),
1513	.vcap_is2_keys		= vsc9959_vcap_is2_keys,
1514	.vcap_is2_actions	= vsc9959_vcap_is2_actions,
1515	.vcap			= vsc9959_vcap_props,
1516	.shared_queue_sz	= 128 * 1024,
1517	.num_mact_rows		= 2048,
1518	.num_ports		= 6,
1519	.num_tx_queues		= FELIX_NUM_TC,
1520	.switch_pci_bar		= 4,
1521	.imdio_pci_bar		= 0,
1522	.mdio_bus_alloc		= vsc9959_mdio_bus_alloc,
1523	.mdio_bus_free		= vsc9959_mdio_bus_free,
1524	.pcs_config		= vsc9959_pcs_config,
1525	.pcs_link_up		= vsc9959_pcs_link_up,
1526	.pcs_link_state		= vsc9959_pcs_link_state,
1527	.phylink_validate	= vsc9959_phylink_validate,
1528	.prevalidate_phy_mode	= vsc9959_prevalidate_phy_mode,
1529	.port_setup_tc          = vsc9959_port_setup_tc,
1530	.port_sched_speed_set   = vsc9959_sched_speed_set,
1531	.xmit_template_populate	= vsc9959_xmit_template_populate,
1532};
1533
1534static irqreturn_t felix_irq_handler(int irq, void *data)
1535{
1536	struct ocelot *ocelot = (struct ocelot *)data;
1537
1538	/* The INTB interrupt is used for both PTP TX timestamp interrupt
1539	 * and preemption status change interrupt on each port.
1540	 *
1541	 * - Get txtstamp if have
1542	 * - TODO: handle preemption. Without handling it, driver may get
1543	 *   interrupt storm.
1544	 */
1545
1546	ocelot_get_txtstamp(ocelot);
1547
1548	return IRQ_HANDLED;
1549}
1550
1551static int felix_pci_probe(struct pci_dev *pdev,
1552			   const struct pci_device_id *id)
1553{
1554	struct dsa_switch *ds;
1555	struct ocelot *ocelot;
1556	struct felix *felix;
1557	int err;
1558
1559	if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
1560		dev_info(&pdev->dev, "device is disabled, skipping\n");
1561		return -ENODEV;
1562	}
1563
1564	err = pci_enable_device(pdev);
1565	if (err) {
1566		dev_err(&pdev->dev, "device enable failed\n");
1567		goto err_pci_enable;
1568	}
1569
1570	/* set up for high or low dma */
1571	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
1572	if (err) {
1573		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
1574		if (err) {
1575			dev_err(&pdev->dev,
1576				"DMA configuration failed: 0x%x\n", err);
1577			goto err_dma;
1578		}
1579	}
1580
1581	felix = kzalloc(sizeof(struct felix), GFP_KERNEL);
1582	if (!felix) {
1583		err = -ENOMEM;
1584		dev_err(&pdev->dev, "Failed to allocate driver memory\n");
1585		goto err_alloc_felix;
1586	}
1587
1588	pci_set_drvdata(pdev, felix);
1589	ocelot = &felix->ocelot;
1590	ocelot->dev = &pdev->dev;
1591	felix->info = &felix_info_vsc9959;
1592	felix->switch_base = pci_resource_start(pdev,
1593						felix->info->switch_pci_bar);
1594	felix->imdio_base = pci_resource_start(pdev,
1595					       felix->info->imdio_pci_bar);
1596
1597	pci_set_master(pdev);
1598
1599	err = devm_request_threaded_irq(&pdev->dev, pdev->irq, NULL,
1600					&felix_irq_handler, IRQF_ONESHOT,
1601					"felix-intb", ocelot);
1602	if (err) {
1603		dev_err(&pdev->dev, "Failed to request irq\n");
1604		goto err_alloc_irq;
1605	}
1606
1607	ocelot->ptp = 1;
1608
1609	ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
1610	if (!ds) {
1611		err = -ENOMEM;
1612		dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
1613		goto err_alloc_ds;
1614	}
1615
1616	ds->dev = &pdev->dev;
1617	ds->num_ports = felix->info->num_ports;
1618	ds->num_tx_queues = felix->info->num_tx_queues;
1619	ds->ops = &felix_switch_ops;
1620	ds->priv = ocelot;
1621	felix->ds = ds;
1622
1623	err = dsa_register_switch(ds);
1624	if (err) {
1625		dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
1626		goto err_register_ds;
1627	}
1628
1629	return 0;
1630
1631err_register_ds:
1632	kfree(ds);
1633err_alloc_ds:
1634err_alloc_irq:
1635err_alloc_felix:
1636	kfree(felix);
1637err_dma:
1638	pci_disable_device(pdev);
1639err_pci_enable:
1640	return err;
1641}
1642
1643static void felix_pci_remove(struct pci_dev *pdev)
1644{
1645	struct felix *felix;
1646
1647	felix = pci_get_drvdata(pdev);
1648
1649	dsa_unregister_switch(felix->ds);
1650
1651	kfree(felix->ds);
1652	kfree(felix);
1653
1654	pci_disable_device(pdev);
1655}
1656
1657static struct pci_device_id felix_ids[] = {
1658	{
1659		/* NXP LS1028A */
1660		PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),
1661	},
1662	{ 0, }
1663};
1664MODULE_DEVICE_TABLE(pci, felix_ids);
1665
1666struct pci_driver felix_vsc9959_pci_driver = {
1667	.name		= "mscc_felix",
1668	.id_table	= felix_ids,
1669	.probe		= felix_pci_probe,
1670	.remove		= felix_pci_remove,
1671};