33 * Copyright 2018-2019 NXP Semiconductors
44 */
55#include <linux/fsl/enetc_mdio.h>
6+ #include <soc/mscc/ocelot_qsys.h>
67#include <soc/mscc/ocelot_vcap.h>
8+ #include <soc/mscc/ocelot_ptp.h>
79#include <soc/mscc/ocelot_sys.h>
810#include <soc/mscc/ocelot.h>
11+ #include <net/pkt_sched.h>
912#include <linux/iopoll.h>
1013#include <linux/pci.h>
1114#include "felix.h"
2730#define USXGMII_LPA_DUPLEX (lpa ) (((lpa) & GENMASK(12, 12)) >> 12)
2831#define USXGMII_LPA_SPEED (lpa ) (((lpa) & GENMASK(11, 9)) >> 9)
2932
33+ #define VSC9959_TAS_GCL_ENTRY_MAX 63
34+
3035enum usxgmii_speed {
3136 USXGMII_SPEED_10 = 0 ,
3237 USXGMII_SPEED_100 = 1 ,
@@ -1209,6 +1214,138 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
12091214 mdiobus_unregister (felix -> imdio );
12101215}
12111216
1217+ static void vsc9959_sched_speed_set (struct ocelot * ocelot , int port ,
1218+ u32 speed )
1219+ {
1220+ ocelot_rmw_rix (ocelot ,
1221+ QSYS_TAG_CONFIG_LINK_SPEED (speed ),
1222+ QSYS_TAG_CONFIG_LINK_SPEED_M ,
1223+ QSYS_TAG_CONFIG , port );
1224+ }
1225+
1226+ static void vsc9959_new_base_time (struct ocelot * ocelot , ktime_t base_time ,
1227+ u64 cycle_time ,
1228+ struct timespec64 * new_base_ts )
1229+ {
1230+ struct timespec64 ts ;
1231+ ktime_t new_base_time ;
1232+ ktime_t current_time ;
1233+
1234+ ocelot_ptp_gettime64 (& ocelot -> ptp_info , & ts );
1235+ current_time = timespec64_to_ktime (ts );
1236+ new_base_time = base_time ;
1237+
1238+ if (base_time < current_time ) {
1239+ u64 nr_of_cycles = current_time - base_time ;
1240+
1241+ do_div (nr_of_cycles , cycle_time );
1242+ new_base_time += cycle_time * (nr_of_cycles + 1 );
1243+ }
1244+
1245+ * new_base_ts = ktime_to_timespec64 (new_base_time );
1246+ }
1247+
1248+ static u32 vsc9959_tas_read_cfg_status (struct ocelot * ocelot )
1249+ {
1250+ return ocelot_read (ocelot , QSYS_TAS_PARAM_CFG_CTRL );
1251+ }
1252+
1253+ static void vsc9959_tas_gcl_set (struct ocelot * ocelot , const u32 gcl_ix ,
1254+ struct tc_taprio_sched_entry * entry )
1255+ {
1256+ ocelot_write (ocelot ,
1257+ QSYS_GCL_CFG_REG_1_GCL_ENTRY_NUM (gcl_ix ) |
1258+ QSYS_GCL_CFG_REG_1_GATE_STATE (entry -> gate_mask ),
1259+ QSYS_GCL_CFG_REG_1 );
1260+ ocelot_write (ocelot , entry -> interval , QSYS_GCL_CFG_REG_2 );
1261+ }
1262+
1263+ static int vsc9959_qos_port_tas_set (struct ocelot * ocelot , int port ,
1264+ struct tc_taprio_qopt_offload * taprio )
1265+ {
1266+ struct timespec64 base_ts ;
1267+ int ret , i ;
1268+ u32 val ;
1269+
1270+ if (!taprio -> enable ) {
1271+ ocelot_rmw_rix (ocelot ,
1272+ QSYS_TAG_CONFIG_INIT_GATE_STATE (0xFF ),
1273+ QSYS_TAG_CONFIG_ENABLE |
1274+ QSYS_TAG_CONFIG_INIT_GATE_STATE_M ,
1275+ QSYS_TAG_CONFIG , port );
1276+
1277+ return 0 ;
1278+ }
1279+
1280+ if (taprio -> cycle_time > NSEC_PER_SEC ||
1281+ taprio -> cycle_time_extension >= NSEC_PER_SEC )
1282+ return - EINVAL ;
1283+
1284+ if (taprio -> num_entries > VSC9959_TAS_GCL_ENTRY_MAX )
1285+ return - ERANGE ;
1286+
1287+ ocelot_rmw (ocelot , QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM (port ) |
1288+ QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q ,
1289+ QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M |
1290+ QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q ,
1291+ QSYS_TAS_PARAM_CFG_CTRL );
1292+
1293+ /* Hardware errata - Admin config could not be overwritten if
1294+ * config is pending, need reset the TAS module
1295+ */
1296+ val = ocelot_read (ocelot , QSYS_PARAM_STATUS_REG_8 );
1297+ if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING )
1298+ return - EBUSY ;
1299+
1300+ ocelot_rmw_rix (ocelot ,
1301+ QSYS_TAG_CONFIG_ENABLE |
1302+ QSYS_TAG_CONFIG_INIT_GATE_STATE (0xFF ) |
1303+ QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES (0xFF ),
1304+ QSYS_TAG_CONFIG_ENABLE |
1305+ QSYS_TAG_CONFIG_INIT_GATE_STATE_M |
1306+ QSYS_TAG_CONFIG_SCH_TRAFFIC_QUEUES_M ,
1307+ QSYS_TAG_CONFIG , port );
1308+
1309+ vsc9959_new_base_time (ocelot , taprio -> base_time ,
1310+ taprio -> cycle_time , & base_ts );
1311+ ocelot_write (ocelot , base_ts .tv_nsec , QSYS_PARAM_CFG_REG_1 );
1312+ ocelot_write (ocelot , lower_32_bits (base_ts .tv_sec ), QSYS_PARAM_CFG_REG_2 );
1313+ val = upper_32_bits (base_ts .tv_sec );
1314+ ocelot_write (ocelot ,
1315+ QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB (val ) |
1316+ QSYS_PARAM_CFG_REG_3_LIST_LENGTH (taprio -> num_entries ),
1317+ QSYS_PARAM_CFG_REG_3 );
1318+ ocelot_write (ocelot , taprio -> cycle_time , QSYS_PARAM_CFG_REG_4 );
1319+ ocelot_write (ocelot , taprio -> cycle_time_extension , QSYS_PARAM_CFG_REG_5 );
1320+
1321+ for (i = 0 ; i < taprio -> num_entries ; i ++ )
1322+ vsc9959_tas_gcl_set (ocelot , i , & taprio -> entries [i ]);
1323+
1324+ ocelot_rmw (ocelot , QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE ,
1325+ QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE ,
1326+ QSYS_TAS_PARAM_CFG_CTRL );
1327+
1328+ ret = readx_poll_timeout (vsc9959_tas_read_cfg_status , ocelot , val ,
1329+ !(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE ),
1330+ 10 , 100000 );
1331+
1332+ return ret ;
1333+ }
1334+
1335+ static int vsc9959_port_setup_tc (struct dsa_switch * ds , int port ,
1336+ enum tc_setup_type type ,
1337+ void * type_data )
1338+ {
1339+ struct ocelot * ocelot = ds -> priv ;
1340+
1341+ switch (type ) {
1342+ case TC_SETUP_QDISC_TAPRIO :
1343+ return vsc9959_qos_port_tas_set (ocelot , port , type_data );
1344+ default :
1345+ return - EOPNOTSUPP ;
1346+ }
1347+ }
1348+
12121349struct felix_info felix_info_vsc9959 = {
12131350 .target_io_res = vsc9959_target_io_res ,
12141351 .port_io_res = vsc9959_port_io_res ,
@@ -1224,6 +1361,7 @@ struct felix_info felix_info_vsc9959 = {
12241361 .shared_queue_sz = 128 * 1024 ,
12251362 .num_mact_rows = 2048 ,
12261363 .num_ports = 6 ,
1364+ .num_tx_queues = FELIX_NUM_TC ,
12271365 .switch_pci_bar = 4 ,
12281366 .imdio_pci_bar = 0 ,
12291367 .mdio_bus_alloc = vsc9959_mdio_bus_alloc ,
@@ -1232,4 +1370,6 @@ struct felix_info felix_info_vsc9959 = {
12321370 .pcs_an_restart = vsc9959_pcs_an_restart ,
12331371 .pcs_link_state = vsc9959_pcs_link_state ,
12341372 .prevalidate_phy_mode = vsc9959_prevalidate_phy_mode ,
1373+ .port_setup_tc = vsc9959_port_setup_tc ,
1374+ .port_sched_speed_set = vsc9959_sched_speed_set ,
12351375};
0 commit comments