arm: mvebu: a38x: serdes specification cleanup

Instead of allocating space in the driver for the serdes
specification table, just allow the board file to set a pointer
to it.  Also, allow the board to only specify the lanes that are
used instead of including unused lanes.

Signed-off-by: Kevin Smith <kevin.smith@elecsyscorp.com>
Acked-by: Stefan Roese <sr@denx.de>
Cc: Dirk Eibach <eibach@gdsys.de>
Cc: Luka Perkov <luka.perkov@sartura.hr>
master
Kevin Smith 10 years ago committed by Luka Perkov
parent 18c202aa54
commit 490753ace3
  1. 13
      arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
  2. 2
      arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
  3. 77
      arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
  4. 8
      arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
  5. 5
      board/Marvell/db-88f6820-gp/db-88f6820-gp.c

@ -13,17 +13,16 @@
#include "ctrl_pex.h" #include "ctrl_pex.h"
#include "sys_env_lib.h" #include "sys_env_lib.h"
int hws_pex_config(const struct serdes_map *serdes_map) int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
{ {
u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg, u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
temp_reg, addr, dev_id, ctrl_mode; temp_reg, addr, dev_id, ctrl_mode;
enum serdes_type serdes_type; enum serdes_type serdes_type;
u32 idx, max_lane_num; u32 idx;
DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n"); DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
max_lane_num = hws_serdes_get_max_lane(); for (idx = 0; idx < count; idx++) {
for (idx = 0; idx < max_lane_num; idx++) {
serdes_type = serdes_map[idx].serdes_type; serdes_type = serdes_map[idx].serdes_type;
/* configuration for PEX only */ /* configuration for PEX only */
if ((serdes_type != PEX0) && (serdes_type != PEX1) && if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
@ -47,7 +46,7 @@ int hws_pex_config(const struct serdes_map *serdes_map)
tmp = reg_read(SOC_CTRL_REG); tmp = reg_read(SOC_CTRL_REG);
tmp &= ~0x03; tmp &= ~0x03;
for (idx = 0; idx < max_lane_num; idx++) { for (idx = 0; idx < count; idx++) {
serdes_type = serdes_map[idx].serdes_type; serdes_type = serdes_map[idx].serdes_type;
if ((serdes_type != PEX0) && if ((serdes_type != PEX0) &&
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) || ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
@ -81,7 +80,7 @@ int hws_pex_config(const struct serdes_map *serdes_map)
next_busno = 0; next_busno = 0;
mdelay(150); mdelay(150);
for (idx = 0; idx < max_lane_num; idx++) { for (idx = 0; idx < count; idx++) {
serdes_type = serdes_map[idx].serdes_type; serdes_type = serdes_map[idx].serdes_type;
DEBUG_INIT_FULL_S(" serdes_type=0x"); DEBUG_INIT_FULL_S(" serdes_type=0x");
DEBUG_INIT_FULL_D(serdes_type, 8); DEBUG_INIT_FULL_D(serdes_type, 8);
@ -191,7 +190,7 @@ int hws_pex_config(const struct serdes_map *serdes_map)
/* Update pex DEVICE ID */ /* Update pex DEVICE ID */
ctrl_mode = sys_env_model_get(); ctrl_mode = sys_env_model_get();
for (idx = 0; idx < max_lane_num; idx++) { for (idx = 0; idx < count; idx++) {
serdes_type = serdes_map[idx].serdes_type; serdes_type = serdes_map[idx].serdes_type;
/* configuration for PEX only */ /* configuration for PEX only */
if ((serdes_type != PEX0) && (serdes_type != PEX1) && if ((serdes_type != PEX0) && (serdes_type != PEX1) &&

@ -78,7 +78,7 @@
#define PEX_STATUS_AND_COMMAND 0x004 #define PEX_STATUS_AND_COMMAND 0x004
#define PXSAC_MABORT BIT(29) /* Recieved Master Abort */ #define PXSAC_MABORT BIT(29) /* Recieved Master Abort */
int hws_pex_config(const struct serdes_map *serdes_map); int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
int pex_local_bus_num_set(u32 pex_if, u32 bus_num); int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
int pex_local_dev_num_set(u32 pex_if, u32 dev_num); int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off); u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off);

@ -20,11 +20,6 @@
#error "No device is defined" #error "No device is defined"
#endif #endif
/*
* The board topology map, initialized in the beginning of
* ctrl_high_speed_serdes_phy_config
*/
struct serdes_map serdes_configuration_map[MAX_SERDES_LANES];
/* /*
* serdes_seq_db - holds all serdes sequences, their size and the * serdes_seq_db - holds all serdes sequences, their size and the
@ -1362,7 +1357,8 @@ enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type,
return seq_id; return seq_id;
} }
void print_topology_details(const struct serdes_map *serdes_map_array) static void print_topology_details(const struct serdes_map *serdes_map,
u8 count)
{ {
u32 lane_num; u32 lane_num;
@ -1370,16 +1366,16 @@ void print_topology_details(const struct serdes_map *serdes_map_array)
DEBUG_INIT_S(" | Lane # | Speed | Type |\n"); DEBUG_INIT_S(" | Lane # | Speed | Type |\n");
DEBUG_INIT_S(" --------------------------------\n"); DEBUG_INIT_S(" --------------------------------\n");
for (lane_num = 0; lane_num < hws_serdes_get_max_lane(); lane_num++) { for (lane_num = 0; lane_num < count; lane_num++) {
if (serdes_map_array[lane_num].serdes_type == DEFAULT_SERDES) if (serdes_map[lane_num].serdes_type == DEFAULT_SERDES)
continue; continue;
DEBUG_INIT_S(" | "); DEBUG_INIT_S(" | ");
DEBUG_INIT_D(hws_get_physical_serdes_num(lane_num), 1); DEBUG_INIT_D(hws_get_physical_serdes_num(lane_num), 1);
DEBUG_INIT_S(" | "); DEBUG_INIT_S(" | ");
DEBUG_INIT_D(serdes_map_array[lane_num].serdes_speed, 2); DEBUG_INIT_D(serdes_map[lane_num].serdes_speed, 2);
DEBUG_INIT_S(" | "); DEBUG_INIT_S(" | ");
DEBUG_INIT_S((char *) DEBUG_INIT_S((char *)
serdes_type_to_string[serdes_map_array[lane_num]. serdes_type_to_string[serdes_map[lane_num].
serdes_type]); serdes_type]);
DEBUG_INIT_S("\t|\n"); DEBUG_INIT_S("\t|\n");
} }
@ -1413,6 +1409,9 @@ int hws_pre_serdes_init_config(void)
int serdes_phy_config(void) int serdes_phy_config(void)
{ {
struct serdes_map *serdes_map;
u8 serdes_count;
DEBUG_INIT_FULL_S("\n### ctrl_high_speed_serdes_phy_config ###\n"); DEBUG_INIT_FULL_S("\n### ctrl_high_speed_serdes_phy_config ###\n");
DEBUG_INIT_S("High speed PHY - Version: "); DEBUG_INIT_S("High speed PHY - Version: ");
@ -1428,17 +1427,21 @@ int serdes_phy_config(void)
/* Board topology load */ /* Board topology load */
DEBUG_INIT_FULL_S DEBUG_INIT_FULL_S
("ctrl_high_speed_serdes_phy_config: Loading board topology..\n"); ("ctrl_high_speed_serdes_phy_config: Loading board topology..\n");
CHECK_STATUS(hws_board_topology_load(serdes_configuration_map)); CHECK_STATUS(hws_board_topology_load(&serdes_map, &serdes_count));
if (serdes_count > hws_serdes_get_max_lane()) {
printf("Error: too many serdes lanes specified by board\n");
return MV_FAIL;
}
/* print topology */ /* print topology */
print_topology_details(serdes_configuration_map); print_topology_details(serdes_map, serdes_count);
CHECK_STATUS(hws_pre_serdes_init_config()); CHECK_STATUS(hws_pre_serdes_init_config());
/* Power-Up sequence */ /* Power-Up sequence */
DEBUG_INIT_FULL_S DEBUG_INIT_FULL_S
("ctrl_high_speed_serdes_phy_config: Starting serdes power up sequence\n"); ("ctrl_high_speed_serdes_phy_config: Starting serdes power up sequence\n");
CHECK_STATUS(hws_power_up_serdes_lanes(serdes_configuration_map)); CHECK_STATUS(hws_power_up_serdes_lanes(serdes_map, serdes_count));
DEBUG_INIT_FULL_S DEBUG_INIT_FULL_S
("\n### ctrl_high_speed_serdes_phy_config ended successfully ###\n"); ("\n### ctrl_high_speed_serdes_phy_config ended successfully ###\n");
@ -1462,7 +1465,7 @@ int serdes_polarity_config(u32 serdes_num, int is_rx)
return MV_OK; return MV_OK;
} }
int hws_power_up_serdes_lanes(const struct serdes_map *serdes_config_map) int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count)
{ {
u32 serdes_id, serdes_lane_num; u32 serdes_id, serdes_lane_num;
enum ref_clock ref_clock; enum ref_clock ref_clock;
@ -1484,22 +1487,21 @@ int hws_power_up_serdes_lanes(const struct serdes_map *serdes_config_map)
/* COMMON PHYS SELECTORS register configuration */ /* COMMON PHYS SELECTORS register configuration */
DEBUG_INIT_FULL_S DEBUG_INIT_FULL_S
("hws_power_up_serdes_lanes: Updating COMMON PHYS SELECTORS reg\n"); ("hws_power_up_serdes_lanes: Updating COMMON PHYS SELECTORS reg\n");
CHECK_STATUS(hws_update_serdes_phy_selectors(serdes_configuration_map)); CHECK_STATUS(hws_update_serdes_phy_selectors(serdes_map, count));
/* per Serdes Power Up */ /* per Serdes Power Up */
for (serdes_id = 0; serdes_id < hws_serdes_get_max_lane(); for (serdes_id = 0; serdes_id < count; serdes_id++) {
serdes_id++) {
DEBUG_INIT_FULL_S DEBUG_INIT_FULL_S
("calling serdes_power_up_ctrl: serdes lane number "); ("calling serdes_power_up_ctrl: serdes lane number ");
DEBUG_INIT_FULL_D_10(serdes_lane_num, 1); DEBUG_INIT_FULL_D_10(serdes_lane_num, 1);
DEBUG_INIT_FULL_S("\n"); DEBUG_INIT_FULL_S("\n");
serdes_lane_num = hws_get_physical_serdes_num(serdes_id); serdes_lane_num = hws_get_physical_serdes_num(serdes_id);
serdes_type = serdes_config_map[serdes_id].serdes_type; serdes_type = serdes_map[serdes_id].serdes_type;
serdes_speed = serdes_config_map[serdes_id].serdes_speed; serdes_speed = serdes_map[serdes_id].serdes_speed;
serdes_mode = serdes_config_map[serdes_id].serdes_mode; serdes_mode = serdes_map[serdes_id].serdes_mode;
serdes_rx_polarity_swap = serdes_config_map[serdes_id].swap_rx; serdes_rx_polarity_swap = serdes_map[serdes_id].swap_rx;
serdes_tx_polarity_swap = serdes_config_map[serdes_id].swap_tx; serdes_tx_polarity_swap = serdes_map[serdes_id].swap_tx;
/* serdes lane is not in use */ /* serdes lane is not in use */
if (serdes_type == DEFAULT_SERDES) if (serdes_type == DEFAULT_SERDES)
@ -1534,10 +1536,10 @@ int hws_power_up_serdes_lanes(const struct serdes_map *serdes_config_map)
/* Set PEX_TX_CONFIG_SEQ sequence for PEXx4 mode. /* Set PEX_TX_CONFIG_SEQ sequence for PEXx4 mode.
After finish the Power_up sequence for all lanes, After finish the Power_up sequence for all lanes,
the lanes should be released from reset state. */ the lanes should be released from reset state. */
CHECK_STATUS(hws_pex_tx_config_seq(serdes_config_map)); CHECK_STATUS(hws_pex_tx_config_seq(serdes_map, count));
/* PEX configuration */ /* PEX configuration */
CHECK_STATUS(hws_pex_config(serdes_config_map)); CHECK_STATUS(hws_pex_config(serdes_map, count));
} }
/* USB2 configuration */ /* USB2 configuration */
@ -1905,7 +1907,7 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
return MV_OK; return MV_OK;
} }
int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map) int hws_update_serdes_phy_selectors(struct serdes_map *serdes_map, u8 count)
{ {
u32 lane_data, idx, serdes_lane_hw_num, reg_data = 0; u32 lane_data, idx, serdes_lane_hw_num, reg_data = 0;
enum serdes_type serdes_type; enum serdes_type serdes_type;
@ -1927,10 +1929,9 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
* Updating bits 0-17 in the COMMON PHYS SELECTORS register * Updating bits 0-17 in the COMMON PHYS SELECTORS register
* according to the serdes types * according to the serdes types
*/ */
for (idx = 0; idx < hws_serdes_get_max_lane(); for (idx = 0; idx < count; idx++) {
idx++) { serdes_type = serdes_map[idx].serdes_type;
serdes_type = serdes_config_map[idx].serdes_type; serdes_mode = serdes_map[idx].serdes_mode;
serdes_mode = serdes_config_map[idx].serdes_mode;
serdes_lane_hw_num = hws_get_physical_serdes_num(idx); serdes_lane_hw_num = hws_get_physical_serdes_num(idx);
lane_data = lane_data =
@ -1942,7 +1943,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
if (hws_serdes_topology_verify if (hws_serdes_topology_verify
(serdes_type, idx, serdes_mode) != MV_OK) { (serdes_type, idx, serdes_mode) != MV_OK) {
serdes_config_map[idx].serdes_type = serdes_map[idx].serdes_type =
DEFAULT_SERDES; DEFAULT_SERDES;
printf("%s: SerDes lane #%d is disabled\n", __func__, printf("%s: SerDes lane #%d is disabled\n", __func__,
serdes_lane_hw_num); serdes_lane_hw_num);
@ -1968,8 +1969,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
printf printf
("%s: Warning: SerDes lane #%d and type %d are not supported together\n", ("%s: Warning: SerDes lane #%d and type %d are not supported together\n",
__func__, serdes_lane_hw_num, serdes_mode); __func__, serdes_lane_hw_num, serdes_mode);
serdes_config_map[idx].serdes_type = serdes_map[idx].serdes_type = DEFAULT_SERDES;
DEFAULT_SERDES;
printf("%s: SerDes lane #%d is disabled\n", __func__, printf("%s: SerDes lane #%d is disabled\n", __func__,
serdes_lane_hw_num); serdes_lane_hw_num);
continue; continue;
@ -1991,7 +1991,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
/* Print topology */ /* Print topology */
if (updated_topology_print) if (updated_topology_print)
print_topology_details(serdes_config_map); print_topology_details(serdes_map, count);
/* /*
* Updating the PEXx4 Enable bit in the COMMON PHYS SELECTORS * Updating the PEXx4 Enable bit in the COMMON PHYS SELECTORS
@ -2145,7 +2145,7 @@ int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type,
* RETURNS: MV_OK - for success * RETURNS: MV_OK - for success
* MV_BAD_PARAM - for fail * MV_BAD_PARAM - for fail
*/ */
int hws_pex_tx_config_seq(const struct serdes_map *serdes_map) int hws_pex_tx_config_seq(const struct serdes_map *serdes_map, u8 count)
{ {
enum serdes_mode serdes_mode; enum serdes_mode serdes_mode;
u32 serdes_lane_id, serdes_lane_hw_num; u32 serdes_lane_id, serdes_lane_hw_num;
@ -2159,8 +2159,7 @@ int hws_pex_tx_config_seq(const struct serdes_map *serdes_map)
*/ */
/* relese pipe soft reset for all lanes */ /* relese pipe soft reset for all lanes */
for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane(); for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
serdes_lane_id++) {
serdes_mode = serdes_map[serdes_lane_id].serdes_mode; serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
serdes_lane_hw_num = serdes_lane_hw_num =
hws_get_physical_serdes_num(serdes_lane_id); hws_get_physical_serdes_num(serdes_lane_id);
@ -2173,8 +2172,7 @@ int hws_pex_tx_config_seq(const struct serdes_map *serdes_map)
} }
/* set phy soft reset for all lanes */ /* set phy soft reset for all lanes */
for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane(); for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
serdes_lane_id++) {
serdes_mode = serdes_map[serdes_lane_id].serdes_mode; serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
serdes_lane_hw_num = serdes_lane_hw_num =
hws_get_physical_serdes_num(serdes_lane_id); hws_get_physical_serdes_num(serdes_lane_id);
@ -2186,8 +2184,7 @@ int hws_pex_tx_config_seq(const struct serdes_map *serdes_map)
} }
/* set phy soft reset for all lanes */ /* set phy soft reset for all lanes */
for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane(); for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
serdes_lane_id++) {
serdes_mode = serdes_map[serdes_lane_id].serdes_mode; serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
serdes_lane_hw_num = serdes_lane_hw_num =
hws_get_physical_serdes_num(serdes_lane_id); hws_get_physical_serdes_num(serdes_lane_id);

@ -215,12 +215,12 @@ extern u8 selectors_serdes_rev2_map[LAST_SERDES_TYPE][MAX_SERDES_LANES];
u8 hws_ctrl_serdes_rev_get(void); u8 hws_ctrl_serdes_rev_get(void);
int mv_update_serdes_select_phy_mode_seq(void); int mv_update_serdes_select_phy_mode_seq(void);
int hws_board_topology_load(struct serdes_map *serdes_map_array); int hws_board_topology_load(struct serdes_map **serdes_map, u8 *count);
enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type, enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type,
enum serdes_speed baud_rate); enum serdes_speed baud_rate);
int hws_serdes_seq_init(void); int hws_serdes_seq_init(void);
int hws_serdes_seq_db_init(void); int hws_serdes_seq_db_init(void);
int hws_power_up_serdes_lanes(const struct serdes_map *serdes_config_map); int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count);
int hws_ctrl_high_speed_serdes_phy_config(void); int hws_ctrl_high_speed_serdes_phy_config(void);
int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up, int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
enum serdes_type serdes_type, enum serdes_type serdes_type,
@ -237,14 +237,14 @@ int hws_serdes_pex_ref_clock_get(enum serdes_type serdes_type,
enum ref_clock *ref_clock); enum ref_clock *ref_clock);
int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type, int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type,
enum ref_clock ref_clock); enum ref_clock ref_clock);
int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map); int hws_update_serdes_phy_selectors(struct serdes_map *serdes_map, u8 count);
u32 hws_serdes_get_phy_selector_val(int serdes_num, u32 hws_serdes_get_phy_selector_val(int serdes_num,
enum serdes_type serdes_type); enum serdes_type serdes_type);
u32 hws_serdes_get_ref_clock_val(enum serdes_type serdes_type); u32 hws_serdes_get_ref_clock_val(enum serdes_type serdes_type);
u32 hws_serdes_get_max_lane(void); u32 hws_serdes_get_max_lane(void);
int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset, int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
u32 *unit_base_reg, u32 *unit_offset); u32 *unit_base_reg, u32 *unit_offset);
int hws_pex_tx_config_seq(const struct serdes_map *serdes_map); int hws_pex_tx_config_seq(const struct serdes_map *serdes_map, u8 count);
u32 hws_get_physical_serdes_num(u32 serdes_num); u32 hws_get_physical_serdes_num(u32 serdes_num);
int hws_is_serdes_active(u8 lane_num); int hws_is_serdes_active(u8 lane_num);

@ -65,9 +65,10 @@ static struct serdes_map board_serdes_map[] = {
{USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0} {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}
}; };
int hws_board_topology_load(struct serdes_map *serdes_map_array) int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{ {
memcpy(serdes_map_array, board_serdes_map, sizeof(board_serdes_map)); *serdes_map_array = board_serdes_map;
*count = ARRAY_SIZE(board_serdes_map);
return 0; return 0;
} }

Loading…
Cancel
Save