Lines Matching +full:sparx5 +full:- +full:switch

1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
37 static u32 sparx5_target_bandwidth(struct sparx5 *sparx5) in sparx5_target_bandwidth() argument
39 switch (sparx5->target_ct) { in sparx5_target_bandwidth()
78 switch (cclock) { in sparx5_clk_to_bandwidth()
90 switch (speed) { in sparx5_cal_speed_to_value()
104 switch (bw) { in sparx5_bandwidth_to_calendar()
118 enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5, u32 portno) in sparx5_get_port_cal_speed() argument
122 if (portno >= sparx5->data->consts->n_ports) { in sparx5_get_port_cal_speed()
125 sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0) || in sparx5_get_port_cal_speed()
127 sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1)) { in sparx5_get_port_cal_speed()
131 sparx5_get_internal_port(sparx5, SPX5_PORT_VD0)) { in sparx5_get_port_cal_speed()
135 sparx5_get_internal_port(sparx5, SPX5_PORT_VD1)) { in sparx5_get_port_cal_speed()
139 sparx5_get_internal_port(sparx5, SPX5_PORT_VD2)) { in sparx5_get_port_cal_speed()
146 /* Front ports - may be used */ in sparx5_get_port_cal_speed()
147 port = sparx5->ports[portno]; in sparx5_get_port_cal_speed()
150 return sparx5_bandwidth_to_calendar(port->conf.bandwidth); in sparx5_get_port_cal_speed()
154 int sparx5_config_auto_calendar(struct sparx5 *sparx5) in sparx5_config_auto_calendar() argument
156 const struct sparx5_consts *consts = sparx5->data->consts; in sparx5_config_auto_calendar()
165 max_core_bw = sparx5_clk_to_bandwidth(sparx5->coreclock); in sparx5_config_auto_calendar()
167 dev_err(sparx5->dev, "Core clock not supported"); in sparx5_config_auto_calendar()
168 return -EINVAL; in sparx5_config_auto_calendar()
172 for (portno = 0; portno < consts->n_ports_all; portno++) { in sparx5_config_auto_calendar()
175 spd = sparx5_get_port_cal_speed(sparx5, portno); in sparx5_config_auto_calendar()
180 if (portno < consts->n_ports) in sparx5_config_auto_calendar()
191 if (used_port_bw > sparx5_target_bandwidth(sparx5)) { in sparx5_config_auto_calendar()
192 dev_err(sparx5->dev, in sparx5_config_auto_calendar()
194 used_port_bw, sparx5_target_bandwidth(sparx5)); in sparx5_config_auto_calendar()
195 return -EINVAL; in sparx5_config_auto_calendar()
199 dev_err(sparx5->dev, in sparx5_config_auto_calendar()
200 "Total BW %u above switch core BW %u\n", in sparx5_config_auto_calendar()
202 return -EINVAL; in sparx5_config_auto_calendar()
206 if (is_sparx5(sparx5)) in sparx5_config_auto_calendar()
209 sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
212 for (idx = 0; idx < consts->n_auto_cals; idx++) in sparx5_config_auto_calendar()
213 spx5_wr(cal[idx], sparx5, QSYS_CAL_AUTO(idx)); in sparx5_config_auto_calendar()
218 spx5_rmw(QSYS_CAL_CTRL_CAL_AUTO_GRANT_RATE_SET(671), /* 672->671 */ in sparx5_config_auto_calendar()
220 sparx5, in sparx5_config_auto_calendar()
223 /* Grant idle usage to VD 0-2 */ in sparx5_config_auto_calendar()
226 sparx5, in sparx5_config_auto_calendar()
232 sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
235 value = spx5_rd(sparx5, QSYS_CAL_CTRL); in sparx5_config_auto_calendar()
237 dev_err(sparx5->dev, "QSYS calendar error\n"); in sparx5_config_auto_calendar()
238 err = -EINVAL; in sparx5_config_auto_calendar()
277 int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi, in sparx5_dsm_calendar_calc() argument
285 clk_period_ps = sparx5_clk_period(sparx5->coreclock); in sparx5_dsm_calendar_calc()
288 memcpy(data->taxi_ports, &sparx5_taxi_ports[taxi], in sparx5_dsm_calendar_calc()
289 sizeof(data->taxi_ports)); in sparx5_dsm_calendar_calc()
292 data->new_slots[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
293 data->schedule[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
294 data->temp_sched[idx] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
297 data->schedule[0] = SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; in sparx5_dsm_calendar_calc()
301 u32 portno = data->taxi_ports[idx]; in sparx5_dsm_calendar_calc()
303 if (portno < sparx5->data->consts->n_ports_all) { in sparx5_dsm_calendar_calc()
304 data->taxi_speeds[idx] = sparx5_cal_speed_to_value in sparx5_dsm_calendar_calc()
305 (sparx5_get_port_cal_speed(sparx5, portno)); in sparx5_dsm_calendar_calc()
307 data->taxi_speeds[idx] = 0; in sparx5_dsm_calendar_calc()
313 for (idx = 0; idx < ARRAY_SIZE(data->taxi_speeds); idx++) { in sparx5_dsm_calendar_calc()
316 sum += data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
317 if (data->taxi_speeds[idx] && data->taxi_speeds[idx] < min) in sparx5_dsm_calendar_calc()
318 min = data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
320 for (jdx = 0; jdx < ARRAY_SIZE(data->taxi_speeds); jdx++) in sparx5_dsm_calendar_calc()
321 gcd = sparx5_dsm_exb_gcd(gcd, data->taxi_speeds[jdx]); in sparx5_dsm_calendar_calc()
326 factor = 100 * 100 * 1000 / (100 * 100 - SPX5_DSM_CAL_BW_LOSS); in sparx5_dsm_calendar_calc()
329 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
332 return -EINVAL; in sparx5_dsm_calendar_calc()
355 for (idx = 0; idx < ARRAY_SIZE(data->taxi_speeds); idx++) { in sparx5_dsm_calendar_calc()
356 u32 spd = data->taxi_speeds[idx]; in sparx5_dsm_calendar_calc()
357 u32 adjusted_speed = data->taxi_speeds[idx] * factor / 1000; in sparx5_dsm_calendar_calc()
360 data->avg_dist[idx] = (128 * 1000000 * 10) / in sparx5_dsm_calendar_calc()
363 data->avg_dist[idx] = -1; in sparx5_dsm_calendar_calc()
365 data->dev_slots[idx] = ((spd * factor / slot_spd) + 999) / 1000; in sparx5_dsm_calendar_calc()
367 if (num_of_slots < (5 * data->dev_slots[idx])) { in sparx5_dsm_calendar_calc()
368 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
371 return -EINVAL; in sparx5_dsm_calendar_calc()
374 sum += data->dev_slots[idx]; in sparx5_dsm_calendar_calc()
376 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
379 return -EINVAL; in sparx5_dsm_calendar_calc()
383 empty_slots = num_of_slots - sum; in sparx5_dsm_calendar_calc()
386 data->schedule[idx] = SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; in sparx5_dsm_calendar_calc()
394 for (slot = 0; slot < ARRAY_SIZE(data->dev_slots); slot++) { in sparx5_dsm_calendar_calc()
395 if (data->dev_slots[slot] == idx) { in sparx5_dsm_calendar_calc()
396 data->indices[indices_len] = slot; in sparx5_dsm_calendar_calc()
405 data->new_slots[kdx] = data->indices[jdx]; in sparx5_dsm_calendar_calc()
409 if (data->schedule[slot] == SPX5_DSM_CAL_EMPTY) in sparx5_dsm_calendar_calc()
419 memcpy(data->short_list, data->schedule, in sparx5_dsm_calendar_calc()
420 sizeof(data->short_list)); in sparx5_dsm_calendar_calc()
421 memcpy(data->long_list, data->new_slots, in sparx5_dsm_calendar_calc()
422 sizeof(data->long_list)); in sparx5_dsm_calendar_calc()
426 memcpy(data->short_list, data->new_slots, in sparx5_dsm_calendar_calc()
427 sizeof(data->short_list)); in sparx5_dsm_calendar_calc()
428 memcpy(data->long_list, data->schedule, in sparx5_dsm_calendar_calc()
429 sizeof(data->long_list)); in sparx5_dsm_calendar_calc()
434 while (sparx5_dsm_cal_len(data->short_list) > 0 || in sparx5_dsm_calendar_calc()
435 sparx5_dsm_cal_len(data->long_list) > 0) { in sparx5_dsm_calendar_calc()
438 if (sparx5_dsm_cal_len(data->short_list) > 0) { in sparx5_dsm_calendar_calc()
439 data->temp_sched[ts] = in sparx5_dsm_calendar_calc()
440 sparx5_dsm_cp_cal(data->short_list); in sparx5_dsm_calendar_calc()
445 while (sparx5_dsm_cal_len(data->long_list) > 0 && in sparx5_dsm_calendar_calc()
447 data->temp_sched[ts] = in sparx5_dsm_calendar_calc()
448 sparx5_dsm_cp_cal(data->long_list); in sparx5_dsm_calendar_calc()
450 cnt -= tgt_score; in sparx5_dsm_calendar_calc()
454 dev_err(sparx5->dev, in sparx5_dsm_calendar_calc()
456 return -EINVAL; in sparx5_dsm_calendar_calc()
461 if (data->temp_sched[slot] == SPX5_DSM_CAL_EMPTY) in sparx5_dsm_calendar_calc()
465 data->schedule[slot] = data->temp_sched[slot]; in sparx5_dsm_calendar_calc()
466 data->temp_sched[slot] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
467 data->new_slots[slot] = SPX5_DSM_CAL_EMPTY; in sparx5_dsm_calendar_calc()
473 static int sparx5_dsm_calendar_check(struct sparx5 *sparx5, in sparx5_dsm_calendar_check() argument
479 u32 cal_length = sparx5_dsm_cal_len(data->schedule); in sparx5_dsm_calendar_check()
483 max_dist = data->avg_dist[port]; in sparx5_dsm_calendar_check()
490 if (data->schedule[idx] == port) { in sparx5_dsm_calendar_check()
499 distances[idx] = (slot_indices[idx + 1] - in sparx5_dsm_calendar_check()
506 cnt = distances[idx] - max_dist; in sparx5_dsm_calendar_check()
508 cnt = -cnt; in sparx5_dsm_calendar_check()
513 cnt = cnt + distances[jdx] - max_dist; in sparx5_dsm_calendar_check()
515 cnt = -cnt; in sparx5_dsm_calendar_check()
523 dev_err(sparx5->dev, in sparx5_dsm_calendar_check()
526 return -EINVAL; in sparx5_dsm_calendar_check()
529 static int sparx5_dsm_calendar_update(struct sparx5 *sparx5, u32 taxi, in sparx5_dsm_calendar_update() argument
532 u32 cal_len = sparx5_dsm_cal_len(data->schedule), len, idx; in sparx5_dsm_calendar_update()
534 if (!is_sparx5(sparx5)) { in sparx5_dsm_calendar_update()
537 val = spx5_rd(sparx5, DSM_TAXI_CAL_CFG(taxi)); in sparx5_dsm_calendar_update()
542 sparx5, DSM_TAXI_CAL_CFG(taxi)); in sparx5_dsm_calendar_update()
547 sparx5, in sparx5_dsm_calendar_update()
552 sparx5, in sparx5_dsm_calendar_update()
554 spx5_rmw(DSM_TAXI_CAL_CFG_CAL_PGM_VAL_SET(data->schedule[idx]), in sparx5_dsm_calendar_update()
556 sparx5, in sparx5_dsm_calendar_update()
561 sparx5, in sparx5_dsm_calendar_update()
563 len = DSM_TAXI_CAL_CFG_CAL_CUR_LEN_GET(spx5_rd(sparx5, in sparx5_dsm_calendar_update()
565 if (len != cal_len - 1) in sparx5_dsm_calendar_update()
568 if (!is_sparx5(sparx5)) { in sparx5_dsm_calendar_update()
571 sparx5, DSM_TAXI_CAL_CFG(taxi)); in sparx5_dsm_calendar_update()
576 dev_err(sparx5->dev, "Incorrect calendar length: %u\n", len); in sparx5_dsm_calendar_update()
577 return -EINVAL; in sparx5_dsm_calendar_update()
581 int sparx5_config_dsm_calendar(struct sparx5 *sparx5) in sparx5_config_dsm_calendar() argument
583 const struct sparx5_ops *ops = sparx5->data->ops; in sparx5_config_dsm_calendar()
590 return -ENOMEM; in sparx5_config_dsm_calendar()
592 for (taxi = 0; taxi < sparx5->data->consts->n_dsm_cal_taxis; ++taxi) { in sparx5_config_dsm_calendar()
593 err = ops->dsm_calendar_calc(sparx5, taxi, data); in sparx5_config_dsm_calendar()
595 dev_err(sparx5->dev, "DSM calendar calculation failed\n"); in sparx5_config_dsm_calendar()
598 err = sparx5_dsm_calendar_check(sparx5, data); in sparx5_config_dsm_calendar()
600 dev_err(sparx5->dev, "DSM calendar check failed\n"); in sparx5_config_dsm_calendar()
603 err = sparx5_dsm_calendar_update(sparx5, taxi, data); in sparx5_config_dsm_calendar()
605 dev_err(sparx5->dev, "DSM calendar update failed\n"); in sparx5_config_dsm_calendar()