123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986 |
- From eb5556db4c4fb8dff9a7b716c66a1ea3d3e696ce Mon Sep 17 00:00:00 2001
- From: Xiaoliang Yang <[email protected]>
- Date: Fri, 29 Nov 2019 11:02:43 +0800
- Subject: [PATCH] net: mscc: ocelot: tsn configuration support
- Support TSN configuration for ocelot switch. The TSN configuration
- fucntions are based on tsn netlink interface, it can support Qbv,
- Qbu, Qci, 802.1CB, and Qav configuration now.
- Signed-off-by: Xiaoliang Yang <[email protected]>
- ---
- drivers/net/ethernet/mscc/Makefile | 1 +
- drivers/net/ethernet/mscc/ocelot.c | 11 +-
- drivers/net/ethernet/mscc/ocelot.h | 2 +
- drivers/net/ethernet/mscc/ocelot_ana.h | 25 +-
- drivers/net/ethernet/mscc/ocelot_dev_gmii.h | 153 +++
- drivers/net/ethernet/mscc/ocelot_tsn.c | 1572 +++++++++++++++++++++++++++
- drivers/net/ethernet/mscc/ocelot_tsn.h | 51 +
- include/soc/mscc/ocelot.h | 52 +-
- 8 files changed, 1857 insertions(+), 10 deletions(-)
- create mode 100644 drivers/net/ethernet/mscc/ocelot_dev_gmii.h
- create mode 100644 drivers/net/ethernet/mscc/ocelot_tsn.c
- create mode 100644 drivers/net/ethernet/mscc/ocelot_tsn.h
- --- a/drivers/net/ethernet/mscc/Makefile
- +++ b/drivers/net/ethernet/mscc/Makefile
- @@ -2,4 +2,5 @@
- obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot_common.o
- mscc_ocelot_common-y := ocelot.o ocelot_io.o
- mscc_ocelot_common-y += ocelot_regs.o ocelot_tc.o ocelot_police.o ocelot_ace.o ocelot_flower.o
- +mscc_ocelot_common-y += ocelot_tsn.o
- obj-$(CONFIG_MSCC_OCELOT_SWITCH_OCELOT) += ocelot_board.o
- --- a/drivers/net/ethernet/mscc/ocelot.c
- +++ b/drivers/net/ethernet/mscc/ocelot.c
- @@ -780,7 +780,7 @@ static void ocelot_set_rx_mode(struct ne
- * forwarded to the CPU port.
- */
- val = GENMASK(ocelot->num_phys_ports - 1, 0);
- - for (i = ocelot->num_phys_ports + 1; i < PGID_CPU; i++)
- + for (i = ocelot->num_phys_ports + 1; i < PGID_MCRED; i++)
- ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i);
-
- __dev_mc_sync(dev, ocelot_mc_sync, ocelot_mc_unsync);
- @@ -2410,10 +2410,11 @@ int ocelot_init(struct ocelot *ocelot)
- SYS_FRM_AGING_MAX_AGE(307692), SYS_FRM_AGING);
-
- /* Setup flooding PGIDs */
- - ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
- - ANA_FLOODING_FLD_BROADCAST(PGID_MC) |
- - ANA_FLOODING_FLD_UNICAST(PGID_UC),
- - ANA_FLOODING, 0);
- + for (i = 0; i < 8; i++)
- + ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
- + ANA_FLOODING_FLD_BROADCAST(PGID_MC) |
- + ANA_FLOODING_FLD_UNICAST(PGID_UC),
- + ANA_FLOODING, i);
- ocelot_write(ocelot, ANA_FLOODING_IPMC_FLD_MC6_DATA(PGID_MCIPV6) |
- ANA_FLOODING_IPMC_FLD_MC6_CTRL(PGID_MC) |
- ANA_FLOODING_IPMC_FLD_MC4_DATA(PGID_MCIPV4) |
- --- a/drivers/net/ethernet/mscc/ocelot.h
- +++ b/drivers/net/ethernet/mscc/ocelot.h
- @@ -27,11 +27,13 @@
- #include "ocelot_qs.h"
- #include "ocelot_tc.h"
- #include "ocelot_ptp.h"
- +#include "ocelot_dev_gmii.h"
-
- #define PGID_AGGR 64
- #define PGID_SRC 80
-
- /* Reserved PGIDs */
- +#define PGID_MCRED (PGID_AGGR - 25)
- #define PGID_CPU (PGID_AGGR - 5)
- #define PGID_UC (PGID_AGGR - 4)
- #define PGID_MC (PGID_AGGR - 3)
- --- a/drivers/net/ethernet/mscc/ocelot_ana.h
- +++ b/drivers/net/ethernet/mscc/ocelot_ana.h
- @@ -227,6 +227,11 @@
- #define ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(x) ((x) & GENMASK(1, 0))
- #define ANA_TABLES_SFIDACCESS_SFID_TBL_CMD_M GENMASK(1, 0)
-
- +#define SFIDACCESS_CMD_IDLE 0
- +#define SFIDACCESS_CMD_READ 1
- +#define SFIDACCESS_CMD_WRITE 2
- +#define SFIDACCESS_CMD_INIT 3
- +
- #define ANA_TABLES_SFIDTIDX_SGID_VALID BIT(26)
- #define ANA_TABLES_SFIDTIDX_SGID(x) (((x) << 18) & GENMASK(25, 18))
- #define ANA_TABLES_SFIDTIDX_SGID_M GENMASK(25, 18)
- @@ -252,15 +257,23 @@
- #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_M GENMASK(18, 16)
- #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(x) (((x) & GENMASK(18, 16)) >> 16)
- #define ANA_SG_CONFIG_REG_3_GATE_ENABLE BIT(20)
- -#define ANA_SG_CONFIG_REG_3_INIT_IPS(x) (((x) << 24) & GENMASK(27, 24))
- -#define ANA_SG_CONFIG_REG_3_INIT_IPS_M GENMASK(27, 24)
- -#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(27, 24)) >> 24)
- -#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE BIT(28)
- +#define ANA_SG_CONFIG_REG_3_INIT_IPS(x) (((x) << 21) & GENMASK(24, 21))
- +#define ANA_SG_CONFIG_REG_3_INIT_IPS_M GENMASK(24, 21)
- +#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(24, 21)) >> 21)
- +#define ANA_SG_CONFIG_REG_3_IPV_VALID BIT(24)
- +#define ANA_SG_CONFIG_REG_3_IPV_INVALID(x) (((x) << 24) & GENMASK(24, 24))
- +#define ANA_SG_CONFIG_REG_3_INIT_IPV(x) (((x) << 21) & GENMASK(23, 21))
- +#define ANA_SG_CONFIG_REG_3_INIT_IPV_M GENMASK(23, 21)
- +#define ANA_SG_CONFIG_REG_3_INIT_IPV_X(x) (((x) & GENMASK(23, 21)) >> 21)
- +#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE BIT(25)
-
- #define ANA_SG_GCL_GS_CONFIG_RSZ 0x4
-
- #define ANA_SG_GCL_GS_CONFIG_IPS(x) ((x) & GENMASK(3, 0))
- #define ANA_SG_GCL_GS_CONFIG_IPS_M GENMASK(3, 0)
- +#define ANA_SG_GCL_GS_CONFIG_IPV_VALID BIT(3)
- +#define ANA_SG_GCL_GS_CONFIG_IPV(x) ((x) & GENMASK(2, 0))
- +#define ANA_SG_GCL_GS_CONFIG_IPV_M GENMASK(2, 0)
- #define ANA_SG_GCL_GS_CONFIG_GATE_STATE BIT(4)
-
- #define ANA_SG_GCL_TI_CONFIG_RSZ 0x4
- @@ -271,6 +284,10 @@
- #define ANA_SG_STATUS_REG_3_IPS(x) (((x) << 20) & GENMASK(23, 20))
- #define ANA_SG_STATUS_REG_3_IPS_M GENMASK(23, 20)
- #define ANA_SG_STATUS_REG_3_IPS_X(x) (((x) & GENMASK(23, 20)) >> 20)
- +#define ANA_SG_STATUS_REG_3_IPV_VALID BIT(23)
- +#define ANA_SG_STATUS_REG_3_IPV(x) (((x) << 20) & GENMASK(22, 20))
- +#define ANA_SG_STATUS_REG_3_IPV_M GENMASK(22, 20)
- +#define ANA_SG_STATUS_REG_3_IPV_X(x) (((x) & GENMASK(22, 20)) >> 20)
- #define ANA_SG_STATUS_REG_3_CONFIG_PENDING BIT(24)
-
- #define ANA_PORT_VLAN_CFG_GSZ 0x100
- --- /dev/null
- +++ b/drivers/net/ethernet/mscc/ocelot_dev_gmii.h
- @@ -0,0 +1,153 @@
- +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
- +/* Microsemi Ocelot Switch driver
- + *
- + * Copyright (c) 2017 Microsemi Corporation
- + */
- +
- +#ifndef _MSCC_OCELOT_DEV_GMII_H_
- +#define _MSCC_OCELOT_DEV_GMII_H_
- +
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG 0x0
- +
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_MAC_TX_RST BIT(5)
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_MAC_RX_RST BIT(4)
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_PORT_RST BIT(3)
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_PHY_RST BIT(2)
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_LINK_SPEED(x) ((x) & GENMASK(1, 0))
- +#define DEV_GMII_PORT_MODE_CLOCK_CFG_LINK_SPEED_M GENMASK(1, 0)
- +
- +#define DEV_GMII_PORT_MODE_PORT_MISC 0x4
- +
- +#define DEV_GMII_PORT_MODE_PORT_MISC_MPLS_RX_ENA BIT(5)
- +#define DEV_GMII_PORT_MODE_PORT_MISC_FWD_ERROR_ENA BIT(4)
- +#define DEV_GMII_PORT_MODE_PORT_MISC_FWD_PAUSE_ENA BIT(3)
- +#define DEV_GMII_PORT_MODE_PORT_MISC_FWD_CTRL_ENA BIT(2)
- +#define DEV_GMII_PORT_MODE_PORT_MISC_GMII_LOOP_ENA BIT(1)
- +#define DEV_GMII_PORT_MODE_PORT_MISC_DEV_LOOP_ENA BIT(0)
- +
- +#define DEV_GMII_PORT_MODE_EVENTS 0x8
- +
- +#define DEV_GMII_PORT_MODE_EEE_CFG 0xc
- +
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_ENA BIT(22)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_AGE(x) (((x) << 15) & GENMASK(21, 15))
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_AGE_M GENMASK(21, 15)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_AGE_X(x) (((x) & GENMASK(21, 15)) >> 15)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_WAKEUP(x) (((x) << 8) & GENMASK(14, 8))
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_WAKEUP_M GENMASK(14, 8)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_WAKEUP_X(x) (((x) & GENMASK(14, 8)) >> 8)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_HOLDOFF(x) (((x) << 1) & GENMASK(7, 1))
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_HOLDOFF_M GENMASK(7, 1)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_EEE_TIMER_HOLDOFF_X(x) (((x) & GENMASK(7, 1)) >> 1)
- +#define DEV_GMII_PORT_MODE_EEE_CFG_PORT_LPI BIT(0)
- +
- +#define DEV_GMII_PORT_MODE_RX_PATH_DELAY 0x10
- +
- +#define DEV_GMII_PORT_MODE_TX_PATH_DELAY 0x14
- +
- +#define DEV_GMII_PORT_MODE_PTP_PREDICT_CFG 0x18
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_ENA_CFG 0x1c
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_ENA_CFG_RX_ENA BIT(4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_ENA_CFG_TX_ENA BIT(0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_MODE_CFG 0x20
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_MODE_CFG_FC_WORD_SYNC_ENA BIT(8)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_MODE_CFG_GIGA_MODE_ENA BIT(4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_MODE_CFG_FDX_ENA BIT(0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_MAXLEN_CFG 0x24
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG 0x28
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_TAG_ID(x) (((x) << 16) & GENMASK(31, 16))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_TAG_ID_M GENMASK(31, 16)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_TAG_ID_X(x) (((x) & GENMASK(31, 16)) >> 16)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_PB_ENA BIT(1)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_VLAN_AWR_ENA BIT(0)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA BIT(2)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_ADV_CHK_CFG 0x2c
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_ADV_CHK_CFG_LEN_DROP_ENA BIT(0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG 0x30
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RESTORE_OLD_IPG_CHECK BIT(17)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_REDUCED_TX_IFG BIT(16)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_TX_IFG(x) (((x) << 8) & GENMASK(12, 8))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_TX_IFG_M GENMASK(12, 8)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_TX_IFG_X(x) (((x) & GENMASK(12, 8)) >> 8)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RX_IFG2(x) (((x) << 4) & GENMASK(7, 4))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RX_IFG2_M GENMASK(7, 4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RX_IFG2_X(x) (((x) & GENMASK(7, 4)) >> 4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RX_IFG1(x) ((x) & GENMASK(3, 0))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_IFG_CFG_RX_IFG1_M GENMASK(3, 0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG 0x34
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_BYPASS_COL_SYNC BIT(26)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_OB_ENA BIT(25)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_WEXC_DIS BIT(24)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_SEED(x) (((x) << 16) & GENMASK(23, 16))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_SEED_M GENMASK(23, 16)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_SEED_X(x) (((x) & GENMASK(23, 16)) >> 16)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_SEED_LOAD BIT(12)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_RETRY_AFTER_EXC_COL_ENA BIT(8)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_LATE_COL_POS(x) ((x) & GENMASK(6, 0))
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_HDX_CFG_LATE_COL_POS_M GENMASK(6, 0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_DBG_CFG 0x38
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_DBG_CFG_TBI_MODE BIT(4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_DBG_CFG_IFG_CRS_EXT_CHK_ENA BIT(0)
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_FC_MAC_LOW_CFG 0x3c
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_FC_MAC_HIGH_CFG 0x40
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY 0x44
- +
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_RX_IPG_SHRINK_STICKY BIT(9)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_RX_PREAM_SHRINK_STICKY BIT(8)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_RX_CARRIER_EXT_STICKY BIT(7)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_RX_CARRIER_EXT_ERR_STICKY BIT(6)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_RX_JUNK_STICKY BIT(5)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_TX_RETRANSMIT_STICKY BIT(4)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_TX_JAM_STICKY BIT(3)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_TX_FIFO_OFLW_STICKY BIT(2)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_TX_FRM_LEN_OVR_STICKY BIT(1)
- +#define DEV_GMII_MAC_CFG_STATUS_MAC_STICKY_TX_ABORT_STICKY BIT(0)
- +
- +#define DEV_GMII_MM_CONFIG_ENABLE_CONFIG 0x48
- +
- +#define DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA BIT(0)
- +#define DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA BIT(4)
- +#define DEV_GMII_MM_CONFIG_ENABLE_CONFIG_KEEP_S_AFTER_D BIT(8)
- +
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG 0x4c
- +
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS BIT(0)
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME(x) (((x) << 4) & GENMASK(11, 4))
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME_M GENMASK(11, 4)
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME_X(x) (((x) & GENMASK(11, 4)) >> 4)
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_VERIF_TIMER_UNITS(x) (((x) << 12) & GENMASK(13, 12))
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_VERIF_TIMER_UNITS_M GENMASK(13, 12)
- +#define DEV_GMII_MM_CONFIG_VERIF_CONFIG_VERIF_TIMER_UNITS_X(x) (((x) & GENMASK(13, 12)) >> 12)
- +
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS 0x50
- +
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_ACTIVE_STATUS BIT(0)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_ACTIVE_STICKY BIT(4)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_VERIFY_STATE(x) (((x) << 8) & GENMASK(10, 8))
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_VERIFY_STATE_M GENMASK(10, 8)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_VERIFY_STATE_X(x) (((x) & GENMASK(10, 8)) >> 8)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_UNEXP_RX_PFRM_STICKY BIT(12)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_UNEXP_TX_PFRM_STICKY BIT(16)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_MM_RX_FRAME_STATUS BIT(20)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_MM_TX_FRAME_STATUS BIT(24)
- +#define DEV_GMII_MM_STATISTICS_MM_STATUS_MM_TX_PRMPT_STATUS BIT(28)
- +
- +#endif
- --- /dev/null
- +++ b/drivers/net/ethernet/mscc/ocelot_tsn.c
- @@ -0,0 +1,1572 @@
- +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
- +/* Felix Switch TSN driver
- + *
- + * Copyright (c) 2018 Microsemi Corporation
- + * Copyright 2018-2019 NXP
- + */
- +
- +#include <linux/io.h>
- +#include <linux/kernel.h>
- +#include <linux/pci.h>
- +#include <linux/iopoll.h>
- +#include "ocelot.h"
- +#include <soc/mscc/ocelot_sys.h>
- +#include "ocelot_ana.h"
- +#include "ocelot_qsys.h"
- +#include "ocelot_rew.h"
- +#include "ocelot_dev_gmii.h"
- +#include "ocelot_tsn.h"
- +
- +#define MSCC_NUM_OUT_PORT 4 /* Number of physical output ports */
- +#define SE_IX_PORT 64
- +
- +/* MSCC TSN parameters limited */
- +#define NUM_MSCC_QOS_PRIO 8
- +#define MSCC_PSFP_SFID_NUM 176
- +#define MSCC_FRER_SSID_NUM 128
- +
- +/* Using the max number of MSCC_PSFP_SFID_NUM and MSCC_FRER_SSID_NUM */
- +#define MSCC_STREAM_HANDLE_NUM MSCC_PSFP_SFID_NUM
- +
- +int streamhandle_map[MSCC_STREAM_HANDLE_NUM] = {0};
- +static struct mscc_switch_capa capa __ro_after_init = {
- + .num_tas_gcl = 64,
- + .tas_ct_min = 100,
- + .tas_ct_max = 1000000000,
- + .tas_cte_max = 999999999,
- + .tas_it_max = 999999999,
- + .tas_it_min = 1000,
- + .num_hsch = 72,
- + .num_psfp_sfid = MSCC_PSFP_SFID_NUM,
- + .num_psfp_sgid = 184,
- + .psfp_fmi_max = 246,
- + .psfp_fmi_min = 63,
- + .num_sgi_gcl = 4,
- + .sgi_ct_min = 5000,
- + .sgi_ct_max = 1000000000,
- + .sgi_cte_max = 999999999,
- + .qos_pol_max = 383,
- + /* Maximum allowed value of committed burst size(CBS) is 240 KB */
- + .pol_cbs_max = 60,
- + /* Maximum allowed value of excess burst size(EBS) is 240 KB */
- + .pol_pbs_max = 60,
- + .num_frer_ssid = MSCC_FRER_SSID_NUM,
- + .frer_seq_len_min = 1,
- + .frer_seq_len_max = 28,
- + .frer_his_len_min = 1,
- + .frer_his_len_max = 32,
- + .qos_dscp_max = 63,
- + .qos_cos_max = NUM_MSCC_QOS_PRIO - 1,
- + .qos_dp_max = 1,
- +};
- +
- +static int qos_port_tas_gcl_set(struct ocelot *ocelot, const u8 gcl_ix,
- + struct tsn_qbv_entry *control_list)
- +{
- + if (gcl_ix >= capa.num_tas_gcl) {
- + dev_err(ocelot->dev, "Invalid gcl ix %u\n", gcl_ix);
- + return -EINVAL;
- + }
- + if (control_list->time_interval < capa.tas_it_min ||
- + control_list->time_interval > capa.tas_it_max) {
- + dev_err(ocelot->dev, "Invalid time_interval %u\n",
- + control_list->time_interval);
- +
- + return -EINVAL;
- + }
- +
- + ocelot_write(ocelot,
- + QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM(gcl_ix) |
- + QSYS_GCL_CFG_REG_1_GATE_STATE(control_list->gate_state),
- + QSYS_GCL_CFG_REG_1);
- +
- + ocelot_write(ocelot,
- + control_list->time_interval,
- + QSYS_GCL_CFG_REG_2);
- +
- + return 0;
- +}
- +
- +static u32 tas_read_status(struct ocelot *ocelot)
- +{
- + u32 val;
- +
- + val = ocelot_read(ocelot, QSYS_TAS_PARAM_CFG_CTRL);
- +
- + return val;
- +}
- +
- +int ocelot_qbv_set(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_conf *shaper_config)
- +{
- + struct tsn_qbv_basic *admin_basic = &shaper_config->admin;
- + struct tsn_qbv_entry *control_list = admin_basic->control_list;
- + u32 base_time_nsec = admin_basic->base_time % 1000000000;
- + u64 base_time_sec = admin_basic->base_time / 1000000000;
- + u64 cur_time;
- + u32 val;
- + u8 speed;
- + int i;
- + int ret;
- +
- + if (admin_basic->control_list_length > capa.num_tas_gcl) {
- + dev_err(ocelot->dev,
- + "Invalid admin_control_list_length %u\n",
- + admin_basic->control_list_length);
- + return -EINVAL;
- + }
- +
- + if ((admin_basic->cycle_time < capa.tas_ct_min ||
- + admin_basic->cycle_time > capa.tas_ct_max) &&
- + shaper_config->gate_enabled) {
- + dev_err(ocelot->dev, "Invalid admin_cycle_time %u ns\n",
- + admin_basic->cycle_time);
- + return -EINVAL;
- + }
- + if (admin_basic->cycle_time_extension > capa.tas_cte_max) {
- + dev_err(ocelot->dev,
- + "Invalid admin_cycle_time_extension %u\n",
- + admin_basic->cycle_time_extension);
- + return -EINVAL;
- + }
- +
- + cur_time = ocelot_read(ocelot, PTP_CUR_SEC_MSB);
- + cur_time = cur_time << 32;
- + cur_time += ocelot_read(ocelot, PTP_CUR_SEC_LSB);
- +
- + if (base_time_sec < cur_time) {
- + base_time_sec = cur_time;
- + base_time_nsec = ocelot_read(ocelot, PTP_CUR_NSEC);
- + }
- +
- + /* Select port */
- + ocelot_rmw(ocelot,
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port_id),
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M,
- + QSYS_TAS_PARAM_CFG_CTRL);
- +
- + val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);
- + if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) {
- + ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,
- + QSYS_TAG_CONFIG, port_id);
- + }
- +
- + if (!shaper_config->gate_enabled)
- + admin_basic->gate_states = 0xff;
- +
- + val = ocelot_read_gix(ocelot, ANA_PFC_PFC_CFG, port_id);
- + speed = ANA_PFC_PFC_CFG_FC_LINK_SPEED(val);
- +
- + ocelot_rmw_rix(ocelot,
- + (shaper_config->gate_enabled ?
- + QSYS_TAG_CONFIG_ENABLE : 0) |
- + QSYS_TAG_CONFIG_INIT_GATE_STATE(admin_basic->gate_states) |
- + QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES(0xff) |
- + QSYS_TAG_CONFIG_LINK_SPEED(speed),
- + QSYS_TAG_CONFIG_ENABLE |
- + QSYS_TAG_CONFIG_INIT_GATE_STATE_M |
- + QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES_M |
- + QSYS_TAG_CONFIG_LINK_SPEED_M,
- + QSYS_TAG_CONFIG,
- + port_id);
- +
- + ocelot_write_rix(ocelot, shaper_config->maxsdu,
- + QSYS_PORT_MAX_SDU, port_id);
- + /* TODO: add queue max SDU set */
- +
- + if (shaper_config->gate_enabled) {
- + ocelot_write(ocelot, base_time_nsec,
- + QSYS_PARAM_CFG_REG_1);
- +
- + ocelot_write(ocelot, base_time_sec & GENMASK(31, 0),
- + QSYS_PARAM_CFG_REG_2);
- +
- + ocelot_write(ocelot,
- + QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB(base_time_sec >> 32) |
- + QSYS_PARAM_CFG_REG_3_LIST_LENGTH(admin_basic->control_list_length),
- + QSYS_PARAM_CFG_REG_3);
- +
- + ocelot_write(ocelot, admin_basic->cycle_time,
- + QSYS_PARAM_CFG_REG_4);
- +
- + ocelot_write(ocelot, admin_basic->cycle_time_extension,
- + QSYS_PARAM_CFG_REG_5);
- +
- + for (i = 0; i < admin_basic->control_list_length; i++) {
- + qos_port_tas_gcl_set(ocelot, i, control_list);
- + control_list++;
- + }
- +
- + /* Start configuration change */
- + ocelot_rmw(ocelot,
- + QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,
- + QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE,
- + QSYS_TAS_PARAM_CFG_CTRL);
- +
- + ret = readx_poll_timeout(tas_read_status, ocelot, val,
- + !(QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE
- + & val), 10, 100000);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +int ocelot_qbv_get(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_conf *shaper_config)
- +{
- + u32 val, reg;
- + int i;
- + u32 base_timel;
- + u32 base_timeh;
- + struct tsn_qbv_basic *admin = &shaper_config->admin;
- + struct tsn_qbv_entry *list;
- +
- + ocelot_rmw(ocelot,
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port_id),
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M,
- + QSYS_TAS_PARAM_CFG_CTRL);
- +
- + val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port_id);
- + shaper_config->gate_enabled = (val & QSYS_TAG_CONFIG_ENABLE);
- + admin->gate_states = QSYS_TAG_CONFIG_INIT_GATE_STATE_X(val);
- +
- + base_timel = ocelot_read(ocelot, QSYS_PARAM_CFG_REG_1);
- + base_timeh = ocelot_read(ocelot, QSYS_PARAM_CFG_REG_2);
- + reg = ocelot_read(ocelot, QSYS_PARAM_CFG_REG_3);
- + admin->base_time = base_timeh |
- + (((u64)QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB(reg)) << 32);
- +
- + admin->base_time = (admin->base_time * 1000000000) + base_timel;
- +
- + admin->control_list_length =
- + QSYS_PARAM_CFG_REG_3_LIST_LENGTH_X(reg);
- +
- + admin->cycle_time = ocelot_read(ocelot, QSYS_PARAM_CFG_REG_4);
- + admin->cycle_time_extension =
- + ocelot_read(ocelot, QSYS_PARAM_CFG_REG_5);
- +
- + list = kmalloc_array(admin->control_list_length,
- + sizeof(struct tsn_qbv_entry), GFP_KERNEL);
- + admin->control_list = list;
- +
- + for (i = 0; i < admin->control_list_length; i++) {
- + ocelot_rmw(ocelot,
- + QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM(i),
- + QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM_M,
- + QSYS_GCL_CFG_REG_1);
- +
- + list->time_interval =
- + ocelot_read(ocelot, QSYS_GCL_CFG_REG_2);
- +
- + reg = ocelot_read(ocelot, QSYS_GCL_CFG_REG_1);
- + list->gate_state = QSYS_GCL_CFG_REG_1_GATE_STATE_X(reg);
- +
- + list++;
- + }
- +
- + return 0;
- +}
- +
- +static int qbv_get_gatelist(struct ocelot *ocelot,
- + struct tsn_qbv_basic *oper)
- +{
- + u32 base_timel;
- + u32 base_timeh;
- + u32 val;
- + struct tsn_qbv_entry *glist;
- + int i;
- +
- + base_timel = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_1);
- + base_timeh = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_2);
- + val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_3);
- + oper->base_time = base_timeh;
- + oper->base_time +=
- + ((u64)QSYS_PARAM_STATUS_REG_3_BASE_TIME_SEC_MSB(val)) <<
- + 32;
- + oper->base_time = (oper->base_time * 1000000000) + base_timel;
- +
- + oper->control_list_length =
- + QSYS_PARAM_STATUS_REG_3_LIST_LENGTH_X(val);
- +
- + oper->cycle_time = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_4);
- + oper->cycle_time_extension = ocelot_read(ocelot,
- + QSYS_PARAM_STATUS_REG_5);
- +
- + val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);
- + oper->gate_states = QSYS_PARAM_STATUS_REG_8_OPER_GATE_STATE_X(val);
- +
- + glist = kmalloc_array(oper->control_list_length,
- + sizeof(struct tsn_qbv_entry), GFP_KERNEL);
- +
- + oper->control_list = glist;
- +
- + for (i = 0; i < oper->control_list_length; i++) {
- + ocelot_rmw(ocelot,
- + QSYS_GCL_STATUS_REG_1_GCL_ENTRY_NUM(i),
- + QSYS_GCL_STATUS_REG_1_GCL_ENTRY_NUM_M,
- + QSYS_GCL_STATUS_REG_1);
- +
- + val = ocelot_read(ocelot, QSYS_GCL_STATUS_REG_2);
- + glist->time_interval = val;
- + val = ocelot_read(ocelot, QSYS_GCL_STATUS_REG_1);
- + glist->gate_state =
- + QSYS_GCL_STATUS_REG_1_GATE_STATE_X(val);
- +
- + glist++;
- + }
- +
- + return 0;
- +}
- +
- +int ocelot_qbv_get_status(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_status *qbvstatus)
- +{
- + struct tsn_qbv_basic *oper = &qbvstatus->oper;
- + u32 val;
- + ptptime_t cur_time;
- +
- + ocelot_rmw(ocelot,
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port_id),
- + QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M,
- + QSYS_TAS_PARAM_CFG_CTRL);
- +
- + qbvstatus->supported_list_max = capa.num_tas_gcl;
- +
- + val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);
- + qbvstatus->config_pending =
- + (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) ? 1 : 0;
- +
- + qbvstatus->config_change_time =
- + ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_7);
- +
- + qbvstatus->config_change_time +=
- + ((u64)QSYS_PARAM_STATUS_REG_8_CFG_CHG_TIME_SEC_MSB(val)) <<
- + 32;
- +
- + qbvstatus->config_change_time =
- + (qbvstatus->config_change_time * 1000000000) +
- + ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_6);
- +
- + qbvstatus->config_change_error =
- + ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_9);
- +
- + cur_time = ocelot_read(ocelot, PTP_CUR_SEC_MSB);
- + cur_time = cur_time << 32;
- + cur_time += ocelot_read(ocelot, PTP_CUR_SEC_LSB);
- + cur_time = (cur_time * 1000000000) +
- + ocelot_read(ocelot, PTP_CUR_NSEC);
- +
- + qbvstatus->current_time = cur_time;
- + qbv_get_gatelist(ocelot, oper);
- +
- + return 0;
- +}
- +
- +int ocelot_cut_thru_set(struct ocelot *ocelot, int port_id, u8 cut_thru)
- +{
- + ocelot_write_rix(ocelot, cut_thru, ANA_CUT_THRU_CFG, port_id);
- +
- + return 0;
- +}
- +
- +static int qos_shaper_conf_set(struct ocelot *ocelot, int port,
- + u32 port_ix, u8 percent)
- +{
- + u32 val;
- + int speed;
- + u32 cbs = 0;
- + u32 cir = 0;
- +
- + if (percent > 100) {
- + dev_err(ocelot->dev, "percentage %d larger than 100\n",
- + percent);
- + return -EINVAL;
- + }
- + if (port_ix >= capa.num_hsch) {
- + dev_err(ocelot->dev,
- + "CIR_CFG: id %d is exceed num of HSCH instance\n",
- + port_ix);
- + return -EINVAL;
- + }
- +
- + val = ocelot_read_gix(ocelot, ANA_PFC_PFC_CFG, port);
- + speed = ANA_PFC_PFC_CFG_FC_LINK_SPEED(val);
- + switch (speed) {
- + case OCELOT_SPEED_10:
- + cir = 10000;
- + break;
- + case OCELOT_SPEED_100:
- + cir = 100000;
- + break;
- + case OCELOT_SPEED_1000:
- + cir = 1000000;
- + break;
- + case OCELOT_SPEED_2500:
- + cir = 2500000;
- + break;
- + }
- +
- + cir = cir * percent / 100;
- + cir = DIV_ROUND_UP(cir, 100); /* Rate unit is 100 kbps */
- + cir = (cir ? cir : 1); /* Avoid using zero rate */
- + cbs = DIV_ROUND_UP(cbs, 4096); /* Burst unit is 4kB */
- + cbs = (cbs ? cbs : 1); /* Avoid using zero burst size */
- + cir = min_t(u32, GENMASK(15, 0), cir);
- + cbs = min_t(u32, GENMASK(6, 0), cbs);
- + ocelot_write_gix(ocelot,
- + QSYS_CIR_CFG_CIR_RATE(cir) |
- + QSYS_CIR_CFG_CIR_BURST(cbs),
- + QSYS_CIR_CFG,
- + port_ix);
- +
- + return 0;
- +}
- +
- +static int qos_shaper_conf_get(struct ocelot *ocelot, int port,
- + u32 port_ix)
- +{
- + u32 val;
- + u32 bandwidth = 0;
- + u32 cir = 0;
- + int percentage;
- + int speed;
- +
- + if (port_ix >= capa.num_hsch) {
- + dev_err(ocelot->dev,
- + "CIR_CFG: id %d is exceed num of HSCH instance\n",
- + port_ix);
- + return -EINVAL;
- + }
- +
- + val = ocelot_read_gix(ocelot, ANA_PFC_PFC_CFG, port);
- + speed = ANA_PFC_PFC_CFG_FC_LINK_SPEED(val);
- + switch (speed) {
- + case OCELOT_SPEED_10:
- + bandwidth = 10000;
- + break;
- + case OCELOT_SPEED_100:
- + bandwidth = 100000;
- + break;
- + case OCELOT_SPEED_1000:
- + bandwidth = 1000000;
- + break;
- + case OCELOT_SPEED_2500:
- + bandwidth = 2500000;
- + break;
- + }
- +
- + val = ocelot_read_gix(ocelot, QSYS_CIR_CFG, port_ix);
- +
- + cir = QSYS_CIR_CFG_CIR_RATE_X(val);
- + cir *= 100;
- + percentage = cir * 100 / bandwidth;
- +
- + return percentage;
- +}
- +
- +int ocelot_cbs_set(struct ocelot *ocelot, int port, u8 tc, u8 bw)
- +{
- + if (tc > capa.qos_cos_max) {
- + dev_err(ocelot->dev, "Invalid tc: %u\n", tc);
- + return -EINVAL;
- + }
- +
- + qos_shaper_conf_set(ocelot, port, port * 8 + tc, bw);
- +
- + ocelot_rmw_gix(ocelot,
- + QSYS_SE_CFG_SE_AVB_ENA,
- + QSYS_SE_CFG_SE_AVB_ENA,
- + QSYS_SE_CFG,
- + port * 8 + tc);
- +
- + return 0;
- +}
- +
- +int ocelot_cbs_get(struct ocelot *ocelot, int port, u8 tc)
- +{
- + int ret;
- +
- + if (tc > capa.qos_cos_max) {
- + dev_err(ocelot->dev, "Invalid tc: %u\n", tc);
- + return -EINVAL;
- + }
- +
- + ret = qos_shaper_conf_get(ocelot, port, port * 8 + tc);
- +
- + return ret;
- +}
- +
- +int ocelot_qbu_set(struct ocelot *ocelot, int port, u8 preemptible)
- +{
- + struct ocelot_port *ocelot_port = ocelot->ports[port];
- +
- + ocelot_port_rmwl(ocelot_port,
- + DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA |
- + DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA,
- + DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA |
- + DEV_GMII_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA,
- + DEV_GMII_MM_CONFIG_ENABLE_CONFIG);
- +
- + ocelot_rmw_rix(ocelot,
- + QSYS_PREEMPTION_CFG_P_QUEUES(preemptible),
- + QSYS_PREEMPTION_CFG_P_QUEUES_M,
- + QSYS_PREEMPTION_CFG,
- + port);
- +
- + return 0;
- +}
- +
- +int ocelot_qbu_get(struct ocelot *ocelot, int port,
- + struct tsn_preempt_status *c)
- +{
- + struct ocelot_port *ocelot_port = ocelot->ports[port];
- + u32 val;
- +
- + val = ocelot_read_rix(ocelot,
- + QSYS_PREEMPTION_CFG,
- + port);
- +
- + c->admin_state = QSYS_PREEMPTION_CFG_P_QUEUES(val);
- + c->hold_advance = QSYS_PREEMPTION_CFG_HOLD_ADVANCE_X(val);
- +
- + val = ocelot_port_readl(ocelot_port,
- + DEV_GMII_MM_STATISTICS_MM_STATUS);
- + c->preemption_active =
- + DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_ACTIVE_STATUS & val;
- +
- + return 0;
- +}
- +
- +int ocelot_cb_streamid_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_cb_streamid *streamid)
- +{
- + u32 m_index;
- + u32 bucket;
- + u32 val, dst, reg;
- + u64 dmac;
- + u32 ldmac, hdmac;
- +
- + if (index >= MSCC_STREAM_HANDLE_NUM) {
- + dev_err(ocelot->dev,
- + "Invalid stream handle %u, maximum:%u\n",
- + index, MSCC_STREAM_HANDLE_NUM - 1);
- + return -EINVAL;
- + }
- +
- + index = streamhandle_map[index];
- + m_index = index / 4;
- + bucket = index % 4;
- + streamid->type = 1;
- + regmap_field_write(ocelot->regfields[ANA_TABLES_MACTINDX_BUCKET],
- + bucket);
- + regmap_field_write(ocelot->regfields[ANA_TABLES_MACTINDX_M_INDEX],
- + m_index);
- +
- + /*READ command MACACCESS.VALID(11 bit) must be 0 */
- + ocelot_write(ocelot,
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
- + ANA_TABLES_MACACCESS);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
- + dst = ANA_TABLES_MACACCESS_DEST_IDX_X(val);
- + reg = ocelot_read_rix(ocelot, ANA_PGID_PGID, dst);
- + streamid->ofac_oport = ANA_PGID_PGID_PGID(reg);
- +
- + /*Get the entry's MAC address and VLAN id*/
- + ldmac = ocelot_read(ocelot, ANA_TABLES_MACLDATA);
- + val = ocelot_read(ocelot, ANA_TABLES_MACHDATA);
- + val &= 0x1fffffff;
- + hdmac = val & 0xffff;
- + dmac = hdmac;
- + dmac = (dmac << 32) | ldmac;
- + streamid->para.nid.dmac = dmac;
- +
- + streamid->para.nid.vid = ANA_TABLES_MACHDATA_VID_X(val);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_STREAMDATA);
- + if (!(val & ANA_TABLES_STREAMDATA_SFID_VALID))
- + return -EINVAL;
- +
- + streamid->handle = ANA_TABLES_STREAMDATA_SFID(val);
- +
- + return 0;
- +}
- +
- +static int lookup_mactable(struct ocelot *ocelot, u16 vid, u64 mac)
- +{
- + u32 mach, macl;
- + u32 reg1, reg2;
- + u32 index, bucket;
- +
- + macl = mac & 0xffffffff;
- + mach = (mac >> 32) & 0xffff;
- + ocelot_write(ocelot, macl, ANA_TABLES_MACLDATA);
- + ocelot_write(ocelot, ANA_TABLES_MACHDATA_VID(vid) |
- + ANA_TABLES_MACHDATA_MACHDATA(mach),
- + ANA_TABLES_MACHDATA);
- +
- + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
- + ANA_TABLES_MACACCESS);
- +
- + reg1 = ocelot_read(ocelot, ANA_TABLES_MACLDATA);
- + reg2 = ocelot_read(ocelot, ANA_TABLES_MACHDATA);
- + if (reg1 == 0 && reg2 == 0)
- + return -1;
- +
- + regmap_field_read(ocelot->regfields[ANA_TABLES_MACTINDX_BUCKET],
- + &bucket);
- + regmap_field_read(ocelot->regfields[ANA_TABLES_MACTINDX_M_INDEX],
- + &index);
- +
- + index = index * 4 + bucket;
- +
- + return index;
- +}
- +
- +int ocelot_cb_streamid_set(struct ocelot *ocelot, int port,
- + u32 index, bool enable,
- + struct tsn_cb_streamid *streamid)
- +{
- + struct regmap_field *rf;
- + u16 vid;
- + u64 mac;
- + u32 macl, mach;
- + u32 dst_idx;
- + int idx;
- + u32 reg;
- + int sfid, ssid;
- + u32 m_index, bucket;
- +
- + if (!enable) {
- + if (index >= MSCC_STREAM_HANDLE_NUM) {
- + dev_err(ocelot->dev,
- + "Invalid index %u, maximum:%u\n",
- + index, MSCC_STREAM_HANDLE_NUM - 1);
- + return -EINVAL;
- + }
- + m_index = streamhandle_map[index] / 4;
- + bucket = streamhandle_map[index] % 4;
- + rf = ocelot->regfields[ANA_TABLES_MACTINDX_BUCKET];
- + regmap_field_write(rf, bucket);
- + rf = ocelot->regfields[ANA_TABLES_MACTINDX_M_INDEX];
- + regmap_field_write(rf, m_index);
- +
- + /*READ command MACACCESS.VALID(11 bit) must be 0 */
- + ocelot_write(ocelot,
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
- + ANA_TABLES_MACACCESS);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET),
- + ANA_TABLES_MACACCESS);
- +
- + streamhandle_map[index] = 0;
- +
- + return 0;
- + }
- +
- + if (streamid->type != 1) {
- + dev_err(ocelot->dev, "Invalid stream type\n");
- + return -EINVAL;
- + }
- +
- + if (streamid->handle >= MSCC_STREAM_HANDLE_NUM) {
- + dev_err(ocelot->dev,
- + "Invalid stream handle %u, maximum:%u\n",
- + streamid->handle, MSCC_STREAM_HANDLE_NUM - 1);
- + return -EINVAL;
- + }
- +
- + sfid = streamid->handle;
- + ssid = (streamid->handle < MSCC_FRER_SSID_NUM ?
- + streamid->handle : (MSCC_FRER_SSID_NUM - 1));
- +
- + mac = streamid->para.nid.dmac;
- + macl = mac & 0xffffffff;
- + mach = (mac >> 32) & 0xffff;
- + vid = streamid->para.nid.vid;
- +
- + idx = lookup_mactable(ocelot, vid, mac);
- +
- + if (idx < 0) {
- + ocelot_write(ocelot, macl, ANA_TABLES_MACLDATA);
- + ocelot_write(ocelot, ANA_TABLES_MACHDATA_VID(vid) |
- + ANA_TABLES_MACHDATA_MACHDATA(mach),
- + ANA_TABLES_MACHDATA);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMDATA_SFID_VALID |
- + ANA_TABLES_STREAMDATA_SFID(sfid) |
- + ANA_TABLES_STREAMDATA_SSID_VALID |
- + ANA_TABLES_STREAMDATA_SSID(ssid),
- + ANA_TABLES_STREAMDATA);
- +
- + dst_idx = port;
- + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
- + ANA_TABLES_MACACCESS_ENTRYTYPE(1) |
- + ANA_TABLES_MACACCESS_DEST_IDX(dst_idx) |
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN),
- + ANA_TABLES_MACACCESS);
- +
- + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
- + ANA_TABLES_MACACCESS);
- +
- + regmap_field_read(ocelot->regfields[ANA_TABLES_MACTINDX_BUCKET],
- + &bucket);
- + regmap_field_read(ocelot->regfields[ANA_TABLES_MACTINDX_M_INDEX],
- + &m_index);
- +
- + m_index = m_index * 4 + bucket;
- + streamhandle_map[streamid->handle] = m_index;
- +
- + return 0;
- + }
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMDATA_SFID_VALID |
- + ANA_TABLES_STREAMDATA_SFID(sfid) |
- + ANA_TABLES_STREAMDATA_SSID_VALID |
- + ANA_TABLES_STREAMDATA_SSID(ssid),
- + ANA_TABLES_STREAMDATA);
- +
- + reg = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
- + dst_idx = ANA_TABLES_MACACCESS_DEST_IDX_X(reg);
- + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
- + ANA_TABLES_MACACCESS_ENTRYTYPE(1) |
- + ANA_TABLES_MACACCESS_DEST_IDX(dst_idx) |
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_WRITE),
- + ANA_TABLES_MACACCESS);
- +
- + streamhandle_map[streamid->handle] = idx;
- +
- + return 0;
- +}
- +
- +static int streamid_multi_forward_set(struct ocelot *ocelot, u32 index,
- + u8 fwdmask)
- +{
- + u32 m_index;
- + u32 bucket;
- + u32 val;
- + int m, n, i;
- + u8 pgid_val, fwdport;
- + u32 dst_idx;
- +
- + m_index = index / 4;
- + bucket = index % 4;
- +
- + regmap_field_write(ocelot->regfields[ANA_TABLES_MACTINDX_BUCKET],
- + bucket);
- + regmap_field_write(ocelot->regfields[ANA_TABLES_MACTINDX_M_INDEX],
- + m_index);
- +
- + /*READ command MACACCESS.VALID(11 bit) must be 0 */
- + ocelot_write(ocelot,
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
- + ANA_TABLES_MACACCESS);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
- + fwdport = ANA_TABLES_MACACCESS_DEST_IDX_X(val);
- +
- + if (fwdport >= MSCC_NUM_OUT_PORT) {
- + dst_idx = fwdport;
- + return 0;
- + }
- +
- + fwdmask |= (1 << fwdport);
- +
- + m = ocelot->num_phys_ports - 1;
- + for (i = m; i >= MSCC_NUM_OUT_PORT; i--) {
- + if (fwdmask & (1 << i)) {
- + dst_idx = PGID_MCRED +
- + (m - i) * MSCC_NUM_OUT_PORT +
- + fwdport;
- +
- + pgid_val = (1 << i) | (1 << fwdport);
- + break;
- + }
- + }
- +
- + if (i < MSCC_NUM_OUT_PORT) {
- + m = PGID_MCRED +
- + (ocelot->num_phys_ports - MSCC_NUM_OUT_PORT) *
- + MSCC_NUM_OUT_PORT;
- +
- + for (; i > 0; i--) {
- + if (fwdmask & (1 << i))
- + break;
- +
- + m = m + (1 << i) - 1;
- + }
- + n = fwdmask & ((1 << i) - 1);
- + if (n) {
- + dst_idx = m + n;
- + pgid_val = fwdmask & ((1 << MSCC_NUM_OUT_PORT) - 1);
- + } else {
- + dst_idx = fwdport;
- + }
- + }
- +
- + if (dst_idx < PGID_MCRED)
- + return 0;
- +
- + ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
- + ANA_TABLES_MACACCESS_ENTRYTYPE(1) |
- + ANA_TABLES_MACACCESS_DEST_IDX(dst_idx) |
- + ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_WRITE),
- + ANA_TABLES_MACACCESS);
- +
- + ocelot_write_rix(ocelot, pgid_val, ANA_PGID_PGID, dst_idx);
- +
- + return 0;
- +}
- +
- +int ocelot_qci_sfi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sfi_conf *sfi)
- +{
- + u32 val, reg, fmeter_id, max_sdu;
- + u32 sfid = index;
- +
- + if (sfid >= capa.num_psfp_sfid) {
- + dev_err(ocelot->dev, "Invalid index %u, maximum:%u\n",
- + sfid, capa.num_psfp_sfid);
- + return -EINVAL;
- + }
- +
- + ocelot_rmw(ocelot,
- + ANA_TABLES_SFIDTIDX_SFID_INDEX(sfid),
- + ANA_TABLES_SFIDTIDX_SFID_INDEX_M,
- + ANA_TABLES_SFIDTIDX);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_READ),
- + ANA_TABLES_SFIDACCESS);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_SFIDTIDX);
- + if (!(val & ANA_TABLES_SFIDTIDX_SGID_VALID))
- + return -EINVAL;
- +
- + sfi->stream_gate_instance_id = ANA_TABLES_SFIDTIDX_SGID_X(val);
- + fmeter_id = ANA_TABLES_SFIDTIDX_POL_IDX_X(val);
- + sfi->stream_filter.flow_meter_instance_id = fmeter_id;
- +
- + reg = ocelot_read(ocelot, ANA_TABLES_SFIDACCESS);
- + max_sdu = ANA_TABLES_SFIDACCESS_MAX_SDU_LEN_X(reg);
- + sfi->stream_filter.maximum_sdu_size = max_sdu;
- +
- + if (reg & ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA)
- + sfi->priority_spec = ANA_TABLES_SFIDACCESS_IGR_PRIO_X(reg);
- + else
- + dev_err(ocelot->dev, "priority not enable\n");
- +
- + return 0;
- +}
- +
- +int ocelot_qci_sfi_set(struct ocelot *ocelot, int port,
- + u32 index, bool enable,
- + struct tsn_qci_psfp_sfi_conf *sfi)
- +{
- + int igr_prio = sfi->priority_spec;
- + u16 sgid = sfi->stream_gate_instance_id;
- + u16 pol_idx;
- + int fmid = sfi->stream_filter.flow_meter_instance_id;
- + u16 max_sdu_len = sfi->stream_filter.maximum_sdu_size;
- + int sfid = index;
- + u32 val;
- +
- + if (fmid == -1)
- + pol_idx = capa.psfp_fmi_max;
- + else
- + pol_idx = (u16)fmid;
- +
- + if (sfid >= capa.num_psfp_sfid) {
- + dev_err(ocelot->dev, "Invalid index %u, maximum:%u\n",
- + sfid, capa.num_psfp_sfid);
- + return -EINVAL;
- + }
- +
- + if (!enable) {
- + val = ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE);
- + ocelot_write(ocelot,
- + ANA_TABLES_SFIDTIDX_SFID_INDEX(sfid),
- + ANA_TABLES_SFIDTIDX);
- + ocelot_write(ocelot, val, ANA_TABLES_SFIDACCESS);
- + return 0;
- + }
- +
- + if (sgid >= capa.num_psfp_sgid) {
- + dev_err(ocelot->dev, "Invalid sgid %u, maximum:%u\n",
- + sgid, capa.num_psfp_sgid);
- + return -EINVAL;
- + }
- + if (pol_idx > capa.psfp_fmi_max || pol_idx < capa.psfp_fmi_min) {
- + dev_err(ocelot->dev, "Invalid pol_idx %u, range:%d~%d\n",
- + pol_idx, capa.psfp_fmi_min, capa.psfp_fmi_max);
- + return -EINVAL;
- + }
- +
- + ocelot_write(ocelot, ANA_TABLES_SFIDTIDX_SGID_VALID |
- + ANA_TABLES_SFIDTIDX_SGID(sgid) |
- + ((fmid != -1) ? ANA_TABLES_SFIDTIDX_POL_ENA : 0) |
- + ANA_TABLES_SFIDTIDX_POL_IDX(pol_idx) |
- + ANA_TABLES_SFIDTIDX_SFID_INDEX(sfid),
- + ANA_TABLES_SFIDTIDX);
- +
- + ocelot_write(ocelot,
- + ((igr_prio >= 0) ?
- + ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA : 0) |
- + ANA_TABLES_SFIDACCESS_IGR_PRIO(igr_prio) |
- + ANA_TABLES_SFIDACCESS_MAX_SDU_LEN(max_sdu_len) |
- + ANA_TABLES_SFIDACCESS_SFID_TBL_CMD(SFIDACCESS_CMD_WRITE),
- + ANA_TABLES_SFIDACCESS);
- +
- + return 0;
- +}
- +
- +int ocelot_qci_sfi_counters_get(struct ocelot *ocelot, int port,
- + u32 index,
- + struct tsn_qci_psfp_sfi_counters *sfi_cnt)
- +{
- + u32 sfid = index;
- + u32 match, not_pass, not_pass_sdu, red;
- +
- + if (sfid >= capa.num_psfp_sfid) {
- + dev_err(ocelot->dev, "Invalid index %u, maximum:%u\n",
- + sfid, capa.num_psfp_sfid);
- + return -EINVAL;
- + }
- +
- + ocelot_rmw(ocelot,
- + SYS_STAT_CFG_STAT_VIEW(sfid),
- + SYS_STAT_CFG_STAT_VIEW_M,
- + SYS_STAT_CFG);
- +
- + match = ocelot_read_gix(ocelot, SYS_CNT, 0x200);
- + not_pass = ocelot_read_gix(ocelot, SYS_CNT, 0x201);
- + not_pass_sdu = ocelot_read_gix(ocelot, SYS_CNT, 0x202);
- + red = ocelot_read_gix(ocelot, SYS_CNT, 0x203);
- +
- + sfi_cnt->matching_frames_count = match;
- + sfi_cnt->not_passing_frames_count = not_pass;
- + sfi_cnt->not_passing_sdu_count = not_pass_sdu;
- + sfi_cnt->red_frames_count = red;
- +
- + sfi_cnt->passing_frames_count = match - not_pass;
- + sfi_cnt->passing_sdu_count = match - not_pass - not_pass_sdu;
- +
- + return 0;
- +}
- +
- +int ocelot_qci_max_cap_get(struct ocelot *ocelot,
- + struct tsn_qci_psfp_stream_param *stream_para)
- +{
- + /* MaxStreamFilterInstances */
- + stream_para->max_sf_instance = capa.num_psfp_sfid;
- + /* MaxStreamGateInstances */
- + stream_para->max_sg_instance = capa.num_psfp_sgid;
- + /* MaxFlowMeterInstances */
- + stream_para->max_fm_instance = capa.psfp_fmi_max -
- + capa.psfp_fmi_min + 1;
- + /* SupportedListMax */
- + stream_para->supported_list_max = capa.num_sgi_gcl;
- +
- + return 0;
- +}
- +
- +static int sgi_set_glist(struct ocelot *ocelot,
- + struct tsn_qci_psfp_gcl *gcl, uint32_t num)
- +{
- + u32 time_sum = 0;
- + int i;
- +
- + if (num > capa.num_sgi_gcl)
- + return -EINVAL;
- +
- + for (i = 0; i < num; i++) {
- + u32 val = ANA_SG_GCL_GS_CONFIG_IPS((gcl->ipv < 0) ?
- + 0 : gcl->ipv + 8);
- + val |= (gcl->gate_state ? ANA_SG_GCL_GS_CONFIG_GATE_STATE : 0);
- + ocelot_write_rix(ocelot, val, ANA_SG_GCL_GS_CONFIG, i);
- +
- + time_sum += gcl->time_interval;
- + ocelot_write_rix(ocelot, time_sum, ANA_SG_GCL_TI_CONFIG, i);
- +
- + gcl++;
- + }
- +
- + return 0;
- +}
- +
- +static u32 sgi_read_status(struct ocelot *ocelot)
- +{
- + u32 val;
- +
- + val = ocelot_read(ocelot, ANA_SG_ACCESS_CTRL);
- +
- + return val;
- +}
- +
- +int ocelot_qci_sgi_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sgi_conf *sgi_conf)
- +{
- + struct tsn_qci_sg_control *admin_list = &sgi_conf->admin;
- + u32 sgid = index;
- + u32 list_length = sgi_conf->admin.control_list_length;
- + u32 cycle_time = sgi_conf->admin.cycle_time;
- + u32 cycle_time_ex = sgi_conf->admin.cycle_time_extension;
- + u32 l_basetime = sgi_conf->admin.base_time % 1000000000;
- + u64 h_basetime = sgi_conf->admin.base_time / 1000000000;
- + u64 cur_time;
- + u32 val;
- + int ret;
- +
- + if (sgid >= capa.num_psfp_sgid) {
- + dev_err(ocelot->dev, "Invalid sgid %u, maximum:%u\n",
- + sgid, capa.num_psfp_sgid);
- + return -EINVAL;
- + }
- + if ((cycle_time < capa.sgi_ct_min ||
- + cycle_time > capa.sgi_ct_max) &&
- + sgi_conf->gate_enabled) {
- + dev_err(ocelot->dev, "Invalid cycle_time %u ns\n",
- + cycle_time);
- + return -EINVAL;
- + }
- + if (cycle_time_ex > capa.sgi_cte_max) {
- + dev_err(ocelot->dev,
- + "Invalid cycle_time_extension %u\n",
- + cycle_time_ex);
- + return -EINVAL;
- + }
- + if (list_length > capa.num_sgi_gcl) {
- + dev_err(ocelot->dev,
- + "Invalid sgi_gcl len %u, maximum:%u\n",
- + list_length, capa.num_sgi_gcl);
- + return -EINVAL;
- + }
- +
- + /*configure SGID*/
- + ocelot_rmw(ocelot,
- + ANA_SG_ACCESS_CTRL_SGID(sgid),
- + ANA_SG_ACCESS_CTRL_SGID_M,
- + ANA_SG_ACCESS_CTRL);
- +
- + /*Disable SG*/
- + if (!sgi_conf->gate_enabled) {
- + ocelot_rmw(ocelot,
- + ANA_SG_CONFIG_REG_3_INIT_GATE_STATE,
- + ANA_SG_CONFIG_REG_3_INIT_GATE_STATE |
- + ANA_SG_CONFIG_REG_3_GATE_ENABLE,
- + ANA_SG_CONFIG_REG_3);
- + return 0;
- + }
- +
- + /*admin parameters*/
- + cur_time = ocelot_read(ocelot, PTP_CUR_SEC_MSB);
- + cur_time = cur_time << 32;
- + cur_time += ocelot_read(ocelot, PTP_CUR_SEC_LSB);
- + if (h_basetime < cur_time) {
- + h_basetime = cur_time;
- + l_basetime = ocelot_read(ocelot, PTP_CUR_NSEC);
- + }
- +
- + ocelot_write(ocelot, l_basetime, ANA_SG_CONFIG_REG_1);
- + ocelot_write(ocelot, h_basetime, ANA_SG_CONFIG_REG_2);
- +
- + ocelot_write(ocelot,
- + (sgi_conf->admin.init_ipv < 0 ?
- + 0 : ANA_SG_CONFIG_REG_3_IPV_VALID) |
- + ANA_SG_CONFIG_REG_3_INIT_IPV(sgi_conf->admin.init_ipv) |
- + ANA_SG_CONFIG_REG_3_GATE_ENABLE |
- + ANA_SG_CONFIG_REG_3_LIST_LENGTH(list_length) |
- + (sgi_conf->admin.gate_states > 0 ?
- + ANA_SG_CONFIG_REG_3_INIT_GATE_STATE : 0) |
- + ANA_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB(h_basetime >> 32),
- + ANA_SG_CONFIG_REG_3);
- +
- + ocelot_write(ocelot, cycle_time, ANA_SG_CONFIG_REG_4);
- + ocelot_write(ocelot, cycle_time_ex, ANA_SG_CONFIG_REG_5);
- +
- + ret = sgi_set_glist(ocelot, admin_list->gcl, list_length);
- + if (ret < 0)
- + return ret;
- +
- + /* Start configuration change */
- + ocelot_rmw(ocelot,
- + ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,
- + ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,
- + ANA_SG_ACCESS_CTRL);
- +
- + ret = readx_poll_timeout(sgi_read_status, ocelot, val,
- + (!(ANA_SG_ACCESS_CTRL_CONFIG_CHANGE & val)),
- + 10, 100000);
- +
- + return ret;
- +}
- +
- +static int sgi_get_glist(struct ocelot *ocelot,
- + struct tsn_qci_psfp_gcl *gcl,
- + uint32_t num)
- +{
- + int i;
- + u16 val;
- + u32 time = 0;
- + u32 reg;
- +
- + if (num > capa.num_sgi_gcl)
- + return -EINVAL;
- +
- + for (i = 0; i < num; i++) {
- + val = ocelot_read_rix(ocelot, ANA_SG_GCL_GS_CONFIG, i);
- + gcl->gate_state = (val & ANA_SG_GCL_GS_CONFIG_GATE_STATE);
- +
- + if (val & ANA_SG_GCL_GS_CONFIG_IPV_VALID)
- + gcl->ipv = ANA_SG_GCL_GS_CONFIG_IPV(val);
- + else
- + gcl->ipv = -1;
- +
- + reg = ocelot_read_rix(ocelot, ANA_SG_GCL_TI_CONFIG, i);
- + gcl->time_interval = (reg - time);
- + time = reg;
- +
- + gcl++;
- + }
- +
- + return 0;
- +}
- +
- +int ocelot_qci_sgi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sgi_conf *sgi_conf)
- +{
- + struct tsn_qci_sg_control *admin = &sgi_conf->admin;
- + struct tsn_qci_psfp_gcl *glist;
- + u32 val, reg;
- + u32 list_num;
- + int ret;
- +
- + if (index >= capa.num_psfp_sgid) {
- + dev_err(ocelot->dev, "Invalid sgid %u, maximum:%u\n",
- + index, capa.num_psfp_sgid);
- + return -EINVAL;
- + }
- +
- + ocelot_rmw(ocelot,
- + ANA_SG_ACCESS_CTRL_SGID(index),
- + ANA_SG_ACCESS_CTRL_SGID_M,
- + ANA_SG_ACCESS_CTRL);
- +
- + admin->cycle_time = ocelot_read(ocelot, ANA_SG_CONFIG_REG_4);
- + admin->cycle_time_extension =
- + ocelot_read(ocelot, ANA_SG_CONFIG_REG_5);
- +
- + val = ocelot_read(ocelot, ANA_SG_CONFIG_REG_2);
- + admin->base_time = val;
- +
- + reg = ocelot_read(ocelot, ANA_SG_CONFIG_REG_1);
- + val = ocelot_read(ocelot, ANA_SG_CONFIG_REG_3);
- +
- + admin->base_time +=
- + ANA_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB(val) << 32;
- +
- + admin->base_time = admin->base_time * 1000000000 + reg;
- +
- + if (val & ANA_SG_CONFIG_REG_3_IPV_VALID)
- + admin->init_ipv = ANA_SG_CONFIG_REG_3_INIT_IPV_X(val);
- + else
- + admin->init_ipv = -1;
- +
- + if (val & ANA_SG_CONFIG_REG_3_GATE_ENABLE)
- + sgi_conf->gate_enabled = TRUE;
- +
- + admin->control_list_length = ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(val);
- +
- + list_num = admin->control_list_length;
- +
- + glist = kmalloc_array(list_num, sizeof(struct tsn_qci_psfp_gcl),
- + GFP_KERNEL);
- + admin->gcl = glist;
- +
- + ret = sgi_get_glist(ocelot, glist, list_num);
- +
- + return ret;
- +}
- +
- +int ocelot_qci_sgi_status_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_psfp_sgi_status *sgi_status)
- +{
- + u32 val, reg;
- +
- + if (index >= capa.num_psfp_sgid) {
- + dev_err(ocelot->dev, "Invalid sgid %u, maximum:%u\n",
- + index, capa.num_psfp_sgid);
- + return -EINVAL;
- + }
- +
- + ocelot_rmw(ocelot,
- + ANA_SG_ACCESS_CTRL_SGID(index),
- + ANA_SG_ACCESS_CTRL_SGID_M,
- + ANA_SG_ACCESS_CTRL);
- +
- + val = ocelot_read(ocelot, ANA_SG_STATUS_REG_2);
- + sgi_status->config_change_time = val;
- +
- + reg = ocelot_read(ocelot, ANA_SG_STATUS_REG_1);
- + val = ocelot_read(ocelot, ANA_SG_STATUS_REG_3);
- + sgi_status->config_change_time +=
- + ANA_SG_STATUS_REG_3_CFG_CHG_TIME_SEC_MSB(val) << 32;
- + sgi_status->config_change_time =
- + sgi_status->config_change_time * 1000000000 + reg;
- +
- + if (val & ANA_SG_STATUS_REG_3_CONFIG_PENDING)
- + sgi_status->config_pending = TRUE;
- + else
- + sgi_status->config_pending = FALSE;
- +
- + if (val & ANA_SG_STATUS_REG_3_GATE_STATE)
- + sgi_status->oper.gate_states = TRUE;
- + else
- + sgi_status->oper.gate_states = FALSE;
- + /*bit 3 encoding 0:IPV [0:2]is invalid . 1:IPV[0:2] is valid*/
- + if (val & ANA_SG_STATUS_REG_3_IPV_VALID)
- + sgi_status->oper.init_ipv = ANA_SG_STATUS_REG_3_IPV_X(val);
- + else
- + sgi_status->oper.init_ipv = -1;
- +
- + return 0;
- +}
- +
- +int ocelot_qci_fmi_set(struct ocelot *ocelot, int port, u32 index,
- + bool enable, struct tsn_qci_psfp_fmi *fmi)
- +{
- + u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
- + u32 cir_ena = 0;
- + u32 pbs_max = 0, cbs_max = 0;
- + bool cir_discard = 0, pir_discard = 0;
- +
- + if (index > capa.qos_pol_max) {
- + dev_err(ocelot->dev, "Invalid pol_idx %u, maximum: %u\n",
- + index, capa.qos_pol_max);
- + return -EINVAL;
- + }
- +
- + if (fmi->mark_red_enable && fmi->mark_red) {
- + fmi->eir = 0;
- + fmi->ebs = 0;
- + fmi->cir = 0;
- + fmi->cbs = 0;
- + }
- +
- + pir = fmi->eir;
- + pbs = fmi->ebs;
- +
- + if (!fmi->drop_on_yellow)
- + cir_ena = 1;
- +
- + if (cir_ena) {
- + cir = fmi->cir;
- + cbs = fmi->cbs;
- + if (cir == 0 && cbs == 0) {
- + cir_discard = 1;
- + } else {
- + cir = DIV_ROUND_UP(cir, 100);
- + cir *= 3; /* Rate unit is 33 1/3 kbps */
- + cbs = DIV_ROUND_UP(cbs, 4096);
- + cbs = (cbs ? cbs : 1);
- + cbs_max = capa.pol_cbs_max;
- + if (fmi->cf)
- + pir += fmi->cir;
- + }
- + }
- +
- + if (pir == 0 && pbs == 0) {
- + pir_discard = 1;
- + } else {
- + pir = DIV_ROUND_UP(pir, 100);
- + pir *= 3; /* Rate unit is 33 1/3 kbps */
- + pbs = DIV_ROUND_UP(pbs, 4096);
- + pbs = (pbs ? pbs : 1);
- + pbs_max = capa.pol_pbs_max;
- + }
- + pir = min_t(u32, GENMASK(15, 0), pir);
- + cir = min_t(u32, GENMASK(15, 0), cir);
- + pbs = min(pbs_max, pbs);
- + cbs = min(cbs_max, cbs);
- +
- + ocelot_write_gix(ocelot, (ANA_POL_MODE_CFG_IPG_SIZE(20) |
- + ANA_POL_MODE_CFG_FRM_MODE(1) |
- + (fmi->cf ? ANA_POL_MODE_CFG_DLB_COUPLED : 0) |
- + (cir_ena ? ANA_POL_MODE_CFG_CIR_ENA : 0) |
- + ANA_POL_MODE_CFG_OVERSHOOT_ENA),
- + ANA_POL_MODE_CFG, index);
- +
- + ocelot_write_gix(ocelot, ANA_POL_PIR_CFG_PIR_RATE(pir) |
- + ANA_POL_PIR_CFG_PIR_BURST(pbs),
- + ANA_POL_PIR_CFG, index);
- +
- + ocelot_write_gix(ocelot,
- + (pir_discard ? GENMASK(22, 0) : 0),
- + ANA_POL_PIR_STATE, index);
- +
- + ocelot_write_gix(ocelot, ANA_POL_CIR_CFG_CIR_RATE(cir) |
- + ANA_POL_CIR_CFG_CIR_BURST(cbs),
- + ANA_POL_CIR_CFG, index);
- +
- + ocelot_write_gix(ocelot,
- + (cir_discard ? GENMASK(22, 0) : 0),
- + ANA_POL_CIR_STATE, index);
- +
- + return 0;
- +}
- +
- +int ocelot_qci_fmi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_fmi *fmi,
- + struct tsn_qci_psfp_fmi_counters *counters)
- +{
- + u32 val, reg;
- +
- + if (index > capa.qos_pol_max) {
- + dev_err(ocelot->dev, "Invalid pol_idx %u, maximum: %u\n",
- + index, capa.qos_pol_max);
- + return -EINVAL;
- + }
- +
- + val = ocelot_read_gix(ocelot, ANA_POL_PIR_CFG, index);
- + reg = ocelot_read_gix(ocelot, ANA_POL_CIR_CFG, index);
- +
- + fmi->eir = ANA_POL_PIR_CFG_PIR_RATE_X(val);
- + fmi->eir = fmi->eir * 100 / 3;
- + fmi->ebs = ANA_POL_PIR_CFG_PIR_BURST(val);
- + fmi->ebs *= 4096;
- + fmi->cir = ANA_POL_CIR_CFG_CIR_RATE_X(reg);
- + fmi->cir = fmi->cir * 100 / 3;
- + fmi->cbs = ANA_POL_CIR_CFG_CIR_BURST(reg);
- + fmi->cbs *= 4096;
- + if (!(fmi->eir | fmi->ebs | fmi->cir | fmi->cbs))
- + fmi->mark_red = TRUE;
- + else
- + fmi->mark_red = FALSE;
- +
- + val = ocelot_read_gix(ocelot, ANA_POL_MODE_CFG, index);
- + if (val & ANA_POL_MODE_CFG_DLB_COUPLED)
- + fmi->cf = TRUE;
- + else
- + fmi->cf = FALSE;
- + if (val & ANA_POL_MODE_CFG_CIR_ENA)
- + fmi->drop_on_yellow = FALSE;
- + else
- + fmi->drop_on_yellow = TRUE;
- +
- + return 0;
- +}
- +
- +int ocelot_seq_gen_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_seq_gen_conf *sg_conf)
- +{
- + u8 iport_mask = sg_conf->iport_mask;
- + u8 split_mask = sg_conf->split_mask;
- + u8 seq_len = sg_conf->seq_len;
- + u32 seq_num = sg_conf->seq_num;
- +
- + if (index >= capa.num_frer_ssid) {
- + dev_err(ocelot->dev, "Invalid SSID %u, maximum:%u\n",
- + index, capa.num_frer_ssid - 1);
- + return -EINVAL;
- + }
- + if (seq_len < capa.frer_seq_len_min ||
- + seq_len > capa.frer_seq_len_max) {
- + dev_err(ocelot->dev,
- + "Invalid seq_space_bits num %u,range:%d~%d\n",
- + seq_len,
- + capa.frer_seq_len_min,
- + capa.frer_seq_len_max);
- + return -EINVAL;
- + }
- +
- + streamid_multi_forward_set(ocelot,
- + streamhandle_map[index],
- + split_mask);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_SEQ_MASK_SPLIT_MASK(split_mask) |
- + ANA_TABLES_SEQ_MASK_INPUT_PORT_MASK(iport_mask),
- + ANA_TABLES_SEQ_MASK);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMTIDX_S_INDEX(index) |
- + ANA_TABLES_STREAMTIDX_STREAM_SPLIT |
- + ANA_TABLES_STREAMTIDX_SEQ_SPACE_LOG2(seq_len),
- + ANA_TABLES_STREAMTIDX);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMACCESS_GEN_REC_SEQ_NUM(seq_num) |
- + ANA_TABLES_STREAMACCESS_SEQ_GEN_REC_ENA |
- + ANA_TABLES_STREAMACCESS_STREAM_TBL_CMD(SFIDACCESS_CMD_WRITE),
- + ANA_TABLES_STREAMACCESS);
- +
- + return 0;
- +}
- +
- +int ocelot_seq_rec_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_seq_rec_conf *sr_conf)
- +{
- + u8 seq_len = sr_conf->seq_len;
- + u8 hislen = sr_conf->his_len;
- +
- + if (index >= capa.num_frer_ssid) {
- + dev_err(ocelot->dev, "Invalid SSID %u, maximum:%u\n",
- + index, capa.num_frer_ssid - 1);
- + return -EINVAL;
- + }
- + if (seq_len < capa.frer_seq_len_min ||
- + seq_len > capa.frer_seq_len_max) {
- + dev_err(ocelot->dev,
- + "Invalid seq_space_bits num %u,range:%d~%d\n",
- + seq_len,
- + capa.frer_seq_len_min,
- + capa.frer_seq_len_max);
- + return -EINVAL;
- + }
- + if (hislen < capa.frer_his_len_min ||
- + hislen > capa.frer_his_len_max) {
- + dev_err(ocelot->dev,
- + "Invalid history_bits num %u,range:%d~%d\n",
- + hislen,
- + capa.frer_his_len_min,
- + capa.frer_his_len_max);
- + return -EINVAL;
- + }
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMTIDX_S_INDEX(index) |
- + ANA_TABLES_STREAMTIDX_FORCE_SF_BEHAVIOUR |
- + ANA_TABLES_STREAMTIDX_SEQ_HISTORY_LEN(hislen) |
- + ANA_TABLES_STREAMTIDX_RESET_ON_ROGUE |
- + (sr_conf->rtag_pop_en ?
- + ANA_TABLES_STREAMTIDX_REDTAG_POP : 0) |
- + ANA_TABLES_STREAMTIDX_SEQ_SPACE_LOG2(seq_len),
- + ANA_TABLES_STREAMTIDX);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMACCESS_SEQ_GEN_REC_ENA |
- + ANA_TABLES_STREAMACCESS_GEN_REC_TYPE |
- + ANA_TABLES_STREAMACCESS_STREAM_TBL_CMD(SFIDACCESS_CMD_WRITE),
- + ANA_TABLES_STREAMACCESS);
- +
- + return 0;
- +}
- +
- +int ocelot_cb_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_cb_status *c)
- +{
- + u32 val;
- +
- + if (index >= capa.num_frer_ssid) {
- + dev_err(ocelot->dev, "Invalid SSID %u, maximum:%u\n",
- + index, capa.num_frer_ssid - 1);
- + return -EINVAL;
- + }
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMTIDX_S_INDEX(index),
- + ANA_TABLES_STREAMTIDX);
- +
- + ocelot_write(ocelot,
- + ANA_TABLES_STREAMACCESS_STREAM_TBL_CMD(SFIDACCESS_CMD_READ),
- + ANA_TABLES_STREAMACCESS);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_STREAMACCESS);
- + c->gen_rec = (ANA_TABLES_STREAMACCESS_GEN_REC_TYPE & val) >> 2;
- + c->seq_num = ANA_TABLES_STREAMACCESS_GEN_REC_SEQ_NUM_X(val);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_STREAMTIDX);
- + c->err = ANA_TABLES_STREAMTIDX_SEQ_GEN_ERR_STATUS_X(val);
- + c->his_len = ANA_TABLES_STREAMTIDX_SEQ_HISTORY_LEN_X(val);
- + c->seq_len = ANA_TABLES_STREAMTIDX_SEQ_SPACE_LOG2(val);
- +
- + val = ocelot_read(ocelot, ANA_TABLES_SEQ_MASK);
- + c->split_mask = ANA_TABLES_SEQ_MASK_SPLIT_MASK_X(val);
- + c->iport_mask = ANA_TABLES_SEQ_MASK_INPUT_PORT_MASK(val);
- +
- + c->seq_his = ocelot_read(ocelot, ANA_TABLES_SEQ_HISTORY);
- +
- + return 0;
- +}
- +
- +int ocelot_pcp_map_enable(struct ocelot *ocelot, u8 port)
- +{
- + int i;
- +
- + ocelot_rmw_gix(ocelot,
- + ANA_PORT_QOS_CFG_QOS_PCP_ENA,
- + ANA_PORT_QOS_CFG_QOS_PCP_ENA,
- + ANA_PORT_QOS_CFG,
- + port);
- +
- + for (i = 0; i < NUM_MSCC_QOS_PRIO * 2; i++) {
- + ocelot_rmw_ix(ocelot,
- + (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & i) |
- + ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i),
- + ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL |
- + ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M,
- + ANA_PORT_PCP_DEI_MAP,
- + port, i);
- + }
- +
- + return 0;
- +}
- +
- +int ocelot_rtag_parse_enable(struct ocelot *ocelot, u8 port)
- +{
- + ocelot_rmw_rix(ocelot,
- + ANA_PORT_MODE_REDTAG_PARSE_CFG,
- + ANA_PORT_MODE_REDTAG_PARSE_CFG,
- + ANA_PORT_MODE,
- + port);
- +
- + return 0;
- +}
- +
- +int ocelot_dscp_set(struct ocelot *ocelot, int port,
- + bool enable, const u8 dscp_ix,
- + struct tsn_qos_switch_dscp_conf *c)
- +{
- + u32 val, ri = dscp_ix;
- +
- + c->dscp = 0;
- + c->trust = 1;
- + c->remark = 0;
- +
- + if (dscp_ix > capa.qos_dscp_max) {
- + dev_err(ocelot->dev, "Invalid dscp_ix %u\n", dscp_ix);
- + return -EINVAL;
- + }
- + if (c->cos > capa.qos_cos_max) {
- + dev_err(ocelot->dev, "Invalid cos %d\n", c->cos);
- + return -EINVAL;
- + }
- + if (c->dpl > capa.qos_dp_max) {
- + dev_err(ocelot->dev, "Invalid dpl %d\n", c->dpl);
- + return -EINVAL;
- + }
- +
- + ocelot_rmw_gix(ocelot,
- + (enable ? ANA_PORT_QOS_CFG_QOS_DSCP_ENA : 0) |
- + (c->dscp ? ANA_PORT_QOS_CFG_DSCP_TRANSLATE_ENA : 0),
- + ANA_PORT_QOS_CFG_QOS_DSCP_ENA |
- + ANA_PORT_QOS_CFG_DSCP_TRANSLATE_ENA,
- + ANA_PORT_QOS_CFG,
- + port);
- +
- + val = (c->dpl ? ANA_DSCP_CFG_DP_DSCP_VAL : 0) |
- + ANA_DSCP_CFG_QOS_DSCP_VAL(c->cos) |
- + ANA_DSCP_CFG_DSCP_TRANSLATE_VAL(c->dscp) |
- + (c->trust ? ANA_DSCP_CFG_DSCP_TRUST_ENA : 0) |
- + (c->remark ? ANA_DSCP_CFG_DSCP_REWR_ENA : 0);
- +
- + ocelot_write_rix(ocelot, val, ANA_DSCP_CFG, ri);
- +
- + return 0;
- +}
- --- /dev/null
- +++ b/drivers/net/ethernet/mscc/ocelot_tsn.h
- @@ -0,0 +1,51 @@
- +/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
- + *
- + * TSN_SWITCH driver
- + *
- + * Copyright 2018-2019 NXP
- + */
- +
- +#ifndef _MSCC_OCELOT_SWITCH_TSN_H_
- +#define _MSCC_OCELOT_SWITCH_TSN_H_
- +
- +#define TRUE 1
- +#define FALSE 0
- +
- +struct mscc_switch_capa {
- + u8 num_tas_gcl; /* Number of TAS Gate Control Lists */
- + u32 tas_ct_min; /* Minimum supported TAS CycleTime in nS */
- + u32 tas_ct_max; /* Maximum supported TAS CycleTime in nS */
- + u32 tas_cte_max; /* Maximum supported TAS CycleTimeExtension in nS
- + */
- + u32 tas_it_max;
- + u32 tas_it_min;
- + u8 num_hsch;
- + u8 num_psfp_sfid;
- + u8 num_frer_ssid;
- + u8 num_psfp_sgid;
- + u16 psfp_fmi_max;
- + u16 psfp_fmi_min;
- + u8 num_sgi_gcl;
- + u32 sgi_ct_min;
- + u32 sgi_ct_max;
- + u32 sgi_cte_max;
- + u16 qos_pol_max;
- + u8 pol_cbs_max;
- + u8 pol_pbs_max;
- + u8 frer_seq_len_min;
- + u8 frer_seq_len_max;
- + u8 frer_his_len_min;
- + u8 frer_his_len_max;
- + u8 qos_dscp_max;
- + u8 qos_cos_max;
- + u8 qos_dp_max;
- +};
- +
- +static inline void ocelot_port_rmwl(struct ocelot_port *port, u32 val,
- + u32 mask, u32 reg)
- +{
- + u32 cur = ocelot_port_readl(port, reg);
- +
- + ocelot_port_writel(port, (cur & (~mask)) | val, reg);
- +}
- +#endif
- --- a/include/soc/mscc/ocelot.h
- +++ b/include/soc/mscc/ocelot.h
- @@ -10,6 +10,7 @@
- #include <linux/if_vlan.h>
- #include <linux/regmap.h>
- #include <net/dsa.h>
- +#include <net/tsn.h>
-
- #define IFH_INJ_BYPASS BIT(31)
- #define IFH_INJ_POP_CNT_DISABLE (3 << 28)
- @@ -328,6 +329,10 @@ enum ocelot_reg {
- PTP_CFG_MISC,
- PTP_CLK_CFG_ADJ_CFG,
- PTP_CLK_CFG_ADJ_FREQ,
- + PTP_CUR_NSF,
- + PTP_CUR_NSEC,
- + PTP_CUR_SEC_LSB,
- + PTP_CUR_SEC_MSB,
- GCB_SOFT_RST = GCB << TARGET_OFFSET,
- };
-
- @@ -539,5 +544,50 @@ int ocelot_ptp_gettime64(struct ptp_cloc
- int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
- struct sk_buff *skb);
- void ocelot_get_txtstamp(struct ocelot *ocelot);
- -
- +int ocelot_qbv_set(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_conf *shaper_config);
- +int ocelot_qbv_get(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_conf *shaper_config);
- +int ocelot_qbv_get_status(struct ocelot *ocelot, int port_id,
- + struct tsn_qbv_status *qbvstatus);
- +int ocelot_cut_thru_set(struct ocelot *ocelot, int port_id, u8 cut_thru);
- +int ocelot_cbs_set(struct ocelot *ocelot, int port, u8 tc, u8 bw);
- +int ocelot_cbs_get(struct ocelot *ocelot, int port, u8 tc);
- +int ocelot_qbu_set(struct ocelot *ocelot, int port, u8 preemptible);
- +int ocelot_qbu_get(struct ocelot *ocelot, int port,
- + struct tsn_preempt_status *c);
- +int ocelot_cb_streamid_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_cb_streamid *streamid);
- +int ocelot_cb_streamid_set(struct ocelot *ocelot, int port, u32 index,
- + bool enable, struct tsn_cb_streamid *streamid);
- +int ocelot_qci_sfi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sfi_conf *sfi);
- +int ocelot_qci_sfi_set(struct ocelot *ocelot, int port, u32 index,
- + bool enable, struct tsn_qci_psfp_sfi_conf *sfi);
- +int ocelot_qci_sfi_counters_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sfi_counters *sfi_counters);
- +int ocelot_qci_max_cap_get(struct ocelot *ocelot,
- + struct tsn_qci_psfp_stream_param *stream_para);
- +int ocelot_qci_sgi_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sgi_conf *sgi_conf);
- +int ocelot_qci_sgi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_sgi_conf *sgi_conf);
- +int ocelot_qci_sgi_status_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_psfp_sgi_status *sgi_status);
- +int ocelot_qci_fmi_set(struct ocelot *ocelot, int port, u32 index,
- + bool enable, struct tsn_qci_psfp_fmi *fmi);
- +int ocelot_qci_fmi_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_qci_psfp_fmi *fmi,
- + struct tsn_qci_psfp_fmi_counters *counters);
- +int ocelot_seq_gen_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_seq_gen_conf *sg_conf);
- +int ocelot_seq_rec_set(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_seq_rec_conf *sr_conf);
- +int ocelot_cb_get(struct ocelot *ocelot, int port, u32 index,
- + struct tsn_cb_status *c);
- +int ocelot_pcp_map_enable(struct ocelot *ocelot, u8 port);
- +int ocelot_rtag_parse_enable(struct ocelot *ocelot, u8 port);
- +int ocelot_dscp_set(struct ocelot *ocelot, int port,
- + bool enable, const u8 dscp_ix,
- + struct tsn_qos_switch_dscp_conf *c);
- #endif
|