Lines Matching +full:sparx5 +full:- +full:switch
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
53 static u32 sparx5_target_bandwidth(struct sparx5 *sparx5) in sparx5_target_bandwidth() argument
55 switch (sparx5->target_ct) { in sparx5_target_bandwidth()
90 switch (cclock) { in sparx5_clk_to_bandwidth()
101 switch (speed) { in sparx5_cal_speed_to_value()
115 switch (bw) { in sparx5_bandwidth_to_calendar()
129 static enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5, in sparx5_get_port_cal_speed() argument
152 /* Front ports - may be used */ in sparx5_get_port_cal_speed()
153 port = sparx5->ports[portno]; in sparx5_get_port_cal_speed()
156 return sparx5_bandwidth_to_calendar(port->conf.bandwidth); in sparx5_get_port_cal_speed()
160 int sparx5_config_auto_calendar(struct sparx5 *sparx5) in sparx5_config_auto_calendar() argument
170 max_core_bw = sparx5_clk_to_bandwidth(sparx5->coreclock); in sparx5_config_auto_calendar()
172 dev_err(sparx5->dev, "Core clock not supported"); in sparx5_config_auto_calendar()
173 return -EINVAL; in sparx5_config_auto_calendar()
180 spd = sparx5_get_port_cal_speed(sparx5, portno); in sparx5_config_auto_calendar()
196 if (used_port_bw > sparx5_target_bandwidth(sparx5)) { in sparx5_config_auto_calendar()
197 dev_err(sparx5->dev, in sparx5_config_auto_calendar()
199 used_port_bw, sparx5_target_bandwidth(sparx5)); in sparx5_config_auto_calendar()
200 return -EINVAL; in sparx5_config_auto_calendar()
204 dev_err(sparx5->dev, in sparx5_config_auto_calendar()
205 "Total BW %u above switch core BW %u\n", in sparx5_config_auto_calendar()
207 return -EINVAL; in sparx5_config_auto_calendar()
213 sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
217 spx5_wr(cal[idx], sparx5, QSYS_CAL_AUTO(idx)); in sparx5_config_auto_calendar()
222 spx5_rmw(QSYS_CAL_CTRL_CAL_AUTO_GRANT_RATE_SET(671), /* 672->671 */ in sparx5_config_auto_calendar()
224 sparx5, in sparx5_config_auto_calendar()
227 /* Grant idle usage to VD 0-2 */ in sparx5_config_auto_calendar()
230 sparx5, in sparx5_config_auto_calendar()
236 sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
239 value = spx5_rd(sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
241 dev_err(sparx5->dev, "QSYS calendar error\n"); in sparx5_config_auto_calendar()
242 err = -EINVAL; in sparx5_config_auto_calendar()
281 static int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi, in sparx5_dsm_calendar_calc() argument
289 clk_period_ps = sparx5_clk_period(sparx5->coreclock); in sparx5_dsm_calendar_calc()
292 memcpy(data->taxi_ports, &sparx5_taxi_ports[taxi], in sparx5_dsm_calendar_calc()
293 sizeof(data->taxi_ports)); in sparx5_dsm_calendar_calc()
296 data->new_slots[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
297 data->schedule[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
298 data->temp_sched[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
301 data->schedule[0] = SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; in sparx5_dsm_calendar_calc()
305 u32 portno = data->taxi_ports[idx]; in sparx5_dsm_calendar_calc()
308 data->taxi_speeds[idx] = sparx5_cal_speed_to_value in sparx5_dsm_calendar_calc()
309 (sparx5_get_port_cal_speed(sparx5, portno)); in sparx5_dsm_calendar_calc()
311 data->taxi_speeds[idx] = 0; in sparx5_dsm_calendar_calc()
317 for (idx = 0; idx < ARRAY_SIZE(data->taxi_speeds); idx++) { in sparx5_dsm_calendar_calc()
320 sum += data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
321 if (data->taxi_speeds[idx] && data->taxi_speeds[idx] < min) in sparx5_dsm_calendar_calc()
322 min = data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
324 for (jdx = 0; jdx < ARRAY_SIZE(data->taxi_speeds); jdx++) in sparx5_dsm_calendar_calc()
325 gcd = sparx5_dsm_exb_gcd(gcd, data->taxi_speeds[jdx]); in sparx5_dsm_calendar_calc()
330 factor = 100 * 100 * 1000 / (100 * 100 - SPX5_DSM_CAL_BW_LOSS); in sparx5_dsm_calendar_calc()
333 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
336 return -EINVAL; in sparx5_dsm_calendar_calc()
359 for (idx = 0; idx < ARRAY_SIZE(data->taxi_speeds); idx++) { in sparx5_dsm_calendar_calc()
360 u32 spd = data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
361 u32 adjusted_speed = data->taxi_speeds[idx] * factor / 1000; in sparx5_dsm_calendar_calc()
364 data->avg_dist[idx] = (128 * 1000000 * 10) / in sparx5_dsm_calendar_calc()
367 data->avg_dist[idx] = -1; in sparx5_dsm_calendar_calc()
369 data->dev_slots[idx] = ((spd * factor / slot_spd) + 999) / 1000; in sparx5_dsm_calendar_calc()
371 if (num_of_slots < (5 * data->dev_slots[idx])) { in sparx5_dsm_calendar_calc()
372 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
375 return -EINVAL; in sparx5_dsm_calendar_calc()
378 sum += data->dev_slots[idx]; in sparx5_dsm_calendar_calc()
380 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
383 return -EINVAL; in sparx5_dsm_calendar_calc()
387 empty_slots = num_of_slots - sum; in sparx5_dsm_calendar_calc()
390 data->schedule[idx] = SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; in sparx5_dsm_calendar_calc()
398 for (slot = 0; slot < ARRAY_SIZE(data->dev_slots); slot++) { in sparx5_dsm_calendar_calc()
399 if (data->dev_slots[slot] == idx) { in sparx5_dsm_calendar_calc()
400 data->indices[indices_len] = slot; in sparx5_dsm_calendar_calc()
409 data->new_slots[kdx] = data->indices[jdx]; in sparx5_dsm_calendar_calc()
413 if (data->schedule[slot] == SPX5_DSM_CAL_EMPTY) in sparx5_dsm_calendar_calc()
423 memcpy(data->short_list, data->schedule, in sparx5_dsm_calendar_calc()
424 sizeof(data->short_list)); in sparx5_dsm_calendar_calc()
425 memcpy(data->long_list, data->new_slots, in sparx5_dsm_calendar_calc()
426 sizeof(data->long_list)); in sparx5_dsm_calendar_calc()
430 memcpy(data->short_list, data->new_slots, in sparx5_dsm_calendar_calc()
431 sizeof(data->short_list)); in sparx5_dsm_calendar_calc()
432 memcpy(data->long_list, data->schedule, in sparx5_dsm_calendar_calc()
433 sizeof(data->long_list)); in sparx5_dsm_calendar_calc()
438 while (sparx5_dsm_cal_len(data->short_list) > 0 || in sparx5_dsm_calendar_calc()
439 sparx5_dsm_cal_len(data->long_list) > 0) { in sparx5_dsm_calendar_calc()
442 if (sparx5_dsm_cal_len(data->short_list) > 0) { in sparx5_dsm_calendar_calc()
443 data->temp_sched[ts] = in sparx5_dsm_calendar_calc()
444 sparx5_dsm_cp_cal(data->short_list); in sparx5_dsm_calendar_calc()
449 while (sparx5_dsm_cal_len(data->long_list) > 0 && in sparx5_dsm_calendar_calc()
451 data->temp_sched[ts] = in sparx5_dsm_calendar_calc()
452 sparx5_dsm_cp_cal(data->long_list); in sparx5_dsm_calendar_calc()
454 cnt -= tgt_score; in sparx5_dsm_calendar_calc()
458 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
460 return -EINVAL; in sparx5_dsm_calendar_calc()
465 if (data->temp_sched[slot] == SPX5_DSM_CAL_EMPTY) in sparx5_dsm_calendar_calc()
469 data->schedule[slot] = data->temp_sched[slot]; in sparx5_dsm_calendar_calc()
470 data->temp_sched[slot] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
471 data->new_slots[slot] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
477 static int sparx5_dsm_calendar_check(struct sparx5 *sparx5, in sparx5_dsm_calendar_check() argument
483 u32 cal_length = sparx5_dsm_cal_len(data->schedule); in sparx5_dsm_calendar_check()
487 max_dist = data->avg_dist[port]; in sparx5_dsm_calendar_check()
494 if (data->schedule[idx] == port) { in sparx5_dsm_calendar_check()
503 distances[idx] = (slot_indices[idx + 1] - in sparx5_dsm_calendar_check()
510 cnt = distances[idx] - max_dist; in sparx5_dsm_calendar_check()
512 cnt = -cnt; in sparx5_dsm_calendar_check()
517 cnt = cnt + distances[jdx] - max_dist; in sparx5_dsm_calendar_check()
519 cnt = -cnt; in sparx5_dsm_calendar_check()
527 dev_err(sparx5->dev, in sparx5_dsm_calendar_check()
530 return -EINVAL; in sparx5_dsm_calendar_check()
533 static int sparx5_dsm_calendar_update(struct sparx5 *sparx5, u32 taxi, in sparx5_dsm_calendar_update() argument
537 u32 cal_len = sparx5_dsm_cal_len(data->schedule), len; in sparx5_dsm_calendar_update()
540 sparx5, in sparx5_dsm_calendar_update()
545 sparx5, in sparx5_dsm_calendar_update()
547 spx5_rmw(DSM_TAXI_CAL_CFG_CAL_PGM_VAL_SET(data->schedule[idx]), in sparx5_dsm_calendar_update()
549 sparx5, in sparx5_dsm_calendar_update()
553 sparx5, in sparx5_dsm_calendar_update()
555 len = DSM_TAXI_CAL_CFG_CAL_CUR_LEN_GET(spx5_rd(sparx5, in sparx5_dsm_calendar_update()
557 if (len != cal_len - 1) in sparx5_dsm_calendar_update()
561 dev_err(sparx5->dev, "Incorrect calendar length: %u\n", len); in sparx5_dsm_calendar_update()
562 return -EINVAL; in sparx5_dsm_calendar_update()
566 int sparx5_config_dsm_calendar(struct sparx5 *sparx5) in sparx5_config_dsm_calendar() argument
574 return -ENOMEM; in sparx5_config_dsm_calendar()
577 err = sparx5_dsm_calendar_calc(sparx5, taxi, data); in sparx5_config_dsm_calendar()
579 dev_err(sparx5->dev, "DSM calendar calculation failed\n"); in sparx5_config_dsm_calendar()
582 err = sparx5_dsm_calendar_check(sparx5, data); in sparx5_config_dsm_calendar()
584 dev_err(sparx5->dev, "DSM calendar check failed\n"); in sparx5_config_dsm_calendar()
587 err = sparx5_dsm_calendar_update(sparx5, taxi, data); in sparx5_config_dsm_calendar()
589 dev_err(sparx5->dev, "DSM calendar update failed\n"); in sparx5_config_dsm_calendar()