Merge tag 'mips-pull-2018-11-30' of git://git.denx.de/u-boot-mips
[oweals/u-boot.git] / arch / arm / mach-mvebu / serdes / a38x / high_speed_env_spec.c
index 23af7698fd10d51b53f053133191fb5bc30027ae..33e70569bc480a459099c39256a67ca97284dcb9 100644 (file)
@@ -1,18 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Marvell International Ltd. and its affiliates
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <common.h>
-#include <i2c.h>
 #include <spl.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 
 #include "high_speed_env_spec.h"
-#include "high_speed_topology_spec.h"
 #include "sys_env_lib.h"
 #include "ctrl_pex.h"
 
 #error "No device is defined"
 #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
@@ -34,7 +26,7 @@ struct serdes_map serdes_configuration_map[MAX_SERDES_LANES];
  */
 struct cfg_seq serdes_seq_db[SERDES_LAST_SEQ];
 
-#define        SERDES_VERION           "2.0"
+#define        SERDES_VERSION          "2.0"
 #define ENDED_OK               "High speed PHY - Ended Successfully\n"
 
 #define LINK_WAIT_CNTR         100
@@ -605,6 +597,8 @@ struct op_params pex_electrical_config_serdes_rev2_params[] = {
        {LANE_CFG4_REG, 0x800, 0x8, {0x8}, 0, 0},
        /* tximpcal_th and rximpcal_th */
        {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000}, 0, 0},
+       /* Force receiver detected */
+       {LANE_CFG0_REG, 0x800, 0x8000, {0x8000}, 0, 0},
 };
 
 /* PEX - configuration seq for REF_CLOCK_25MHz */
@@ -842,25 +836,26 @@ u32 hws_serdes_topology_verify(enum serdes_type serdes_type, u32 serdes_id,
                }
        } else {
                test_result = SERDES_ALREADY_IN_USE;
-               if (test_result == SERDES_ALREADY_IN_USE) {
-                       printf("%s: Error: serdes lane %d is configured to type %s: type already in use\n",
-                              __func__, serdes_id,
-                              serdes_type_to_string[serdes_type]);
-                       return MV_FAIL;
-               } else if (test_result == WRONG_NUMBER_OF_UNITS) {
-                       printf("%s: Warning: serdes lane %d is set to type %s.\n",
-                              __func__, serdes_id,
-                              serdes_type_to_string[serdes_type]);
-                       printf("%s: Maximum supported lanes are already set to this type (limit = %d)\n",
-                              __func__, serd_max_num);
-                       return MV_FAIL;
-               } else if (test_result == UNIT_NUMBER_VIOLATION) {
-                       printf("%s: Warning: serdes lane %d type is %s: current device support only %d units of this type.\n",
-                              __func__, serdes_id,
-                              serdes_type_to_string[serdes_type],
-                              serd_max_num);
-                       return MV_FAIL;
-               }
+       }
+
+       if (test_result == SERDES_ALREADY_IN_USE) {
+               printf("%s: Error: serdes lane %d is configured to type %s: type already in use\n",
+                      __func__, serdes_id,
+                      serdes_type_to_string[serdes_type]);
+               return MV_FAIL;
+       } else if (test_result == WRONG_NUMBER_OF_UNITS) {
+               printf("%s: Warning: serdes lane %d is set to type %s.\n",
+                      __func__, serdes_id,
+                      serdes_type_to_string[serdes_type]);
+               printf("%s: Maximum supported lanes are already set to this type (limit = %d)\n",
+                      __func__, serd_max_num);
+               return MV_FAIL;
+       } else if (test_result == UNIT_NUMBER_VIOLATION) {
+               printf("%s: Warning: serdes lane %d type is %s: current device support only %d units of this type.\n",
+                      __func__, serdes_id,
+                      serdes_type_to_string[serdes_type],
+                      serd_max_num);
+               return MV_FAIL;
        }
 
        return MV_OK;
@@ -1364,28 +1359,8 @@ enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type,
        return seq_id;
 }
 
-/*
- * This is the weak default function for the Marvell evaluation or
- * development boarrds. Like the DB-88F6820-GP and others.
- * Custom boards should define this function in their board
- * code (board directory). And overwrite this default function
- * with this custom specific code.
- */
-__weak int hws_board_topology_load(struct serdes_map *serdes_map_array)
-{
-       u32 board_id = mv_board_id_get();
-       u32 board_id_index = mv_board_id_index_get(board_id);
-
-       DEBUG_INIT_FULL_S("\n### hws_board_topology_load ###\n");
-       /* getting board topology according to the board id */
-       DEBUG_INIT_FULL_S("Getting board topology according to the board id\n");
-
-       CHECK_STATUS(load_topology_func_arr[board_id_index] (serdes_map_array));
-
-       return MV_OK;
-}
-
-void print_topology_details(struct serdes_map *serdes_map_array)
+static void print_topology_details(const struct serdes_map *serdes_map,
+                                                               u8 count)
 {
        u32 lane_num;
 
@@ -1393,16 +1368,16 @@ void print_topology_details(struct serdes_map *serdes_map_array)
 
        DEBUG_INIT_S(" | Lane #  | Speed |  Type       |\n");
        DEBUG_INIT_S(" --------------------------------\n");
-       for (lane_num = 0; lane_num < hws_serdes_get_max_lane(); lane_num++) {
-               if (serdes_map_array[lane_num].serdes_type == DEFAULT_SERDES)
+       for (lane_num = 0; lane_num < count; lane_num++) {
+               if (serdes_map[lane_num].serdes_type == DEFAULT_SERDES)
                        continue;
                DEBUG_INIT_S(" |   ");
                DEBUG_INIT_D(hws_get_physical_serdes_num(lane_num), 1);
                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((char *)
-                            serdes_type_to_string[serdes_map_array[lane_num].
+                            serdes_type_to_string[serdes_map[lane_num].
                                                   serdes_type]);
                DEBUG_INIT_S("\t|\n");
        }
@@ -1436,10 +1411,13 @@ int hws_pre_serdes_init_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_S("High speed PHY - Version: ");
-       DEBUG_INIT_S(SERDES_VERION);
+       DEBUG_INIT_S(SERDES_VERSION);
        DEBUG_INIT_S("\n");
 
        /* Init serdes sequences DB */
@@ -1448,23 +1426,24 @@ int serdes_phy_config(void)
                return MV_FAIL;
        }
 
-       /* I2C init */
-       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
-
        /* Board topology load */
        DEBUG_INIT_FULL_S
            ("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_details(serdes_configuration_map);
+       print_topology_details(serdes_map, serdes_count);
        CHECK_STATUS(hws_pre_serdes_init_config());
 
        /* Power-Up sequence */
        DEBUG_INIT_FULL_S
                ("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
                ("\n### ctrl_high_speed_serdes_phy_config ended successfully ###\n");
@@ -1488,7 +1467,7 @@ int serdes_polarity_config(u32 serdes_num, int is_rx)
        return MV_OK;
 }
 
-int hws_power_up_serdes_lanes(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;
        enum ref_clock ref_clock;
@@ -1510,22 +1489,21 @@ int hws_power_up_serdes_lanes(struct serdes_map *serdes_config_map)
        /* COMMON PHYS SELECTORS register configuration */
        DEBUG_INIT_FULL_S
            ("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 */
-       for (serdes_id = 0; serdes_id < hws_serdes_get_max_lane();
-            serdes_id++) {
+       for (serdes_id = 0; serdes_id < count; serdes_id++) {
                DEBUG_INIT_FULL_S
                    ("calling serdes_power_up_ctrl: serdes lane number ");
                DEBUG_INIT_FULL_D_10(serdes_lane_num, 1);
                DEBUG_INIT_FULL_S("\n");
 
                serdes_lane_num = hws_get_physical_serdes_num(serdes_id);
-               serdes_type = serdes_config_map[serdes_id].serdes_type;
-               serdes_speed = serdes_config_map[serdes_id].serdes_speed;
-               serdes_mode = serdes_config_map[serdes_id].serdes_mode;
-               serdes_rx_polarity_swap = serdes_config_map[serdes_id].swap_rx;
-               serdes_tx_polarity_swap = serdes_config_map[serdes_id].swap_tx;
+               serdes_type = serdes_map[serdes_id].serdes_type;
+               serdes_speed = serdes_map[serdes_id].serdes_speed;
+               serdes_mode = serdes_map[serdes_id].serdes_mode;
+               serdes_rx_polarity_swap = serdes_map[serdes_id].swap_rx;
+               serdes_tx_polarity_swap = serdes_map[serdes_id].swap_tx;
 
                /* serdes lane is not in use */
                if (serdes_type == DEFAULT_SERDES)
@@ -1560,10 +1538,10 @@ int hws_power_up_serdes_lanes(struct serdes_map *serdes_config_map)
                /* Set PEX_TX_CONFIG_SEQ sequence for PEXx4 mode.
                   After finish the Power_up sequence for all lanes,
                   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 */
-               CHECK_STATUS(hws_pex_config(serdes_config_map));
+               CHECK_STATUS(hws_pex_config(serdes_map, count));
        }
 
        /* USB2 configuration */
@@ -1931,7 +1909,7 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
        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;
        enum serdes_type serdes_type;
@@ -1953,10 +1931,9 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
         * Updating bits 0-17 in the COMMON PHYS SELECTORS register
         * according to the serdes types
         */
-       for (idx = 0; idx < hws_serdes_get_max_lane();
-            idx++) {
-               serdes_type = serdes_config_map[idx].serdes_type;
-               serdes_mode = serdes_config_map[idx].serdes_mode;
+       for (idx = 0; idx < count; idx++) {
+               serdes_type = serdes_map[idx].serdes_type;
+               serdes_mode = serdes_map[idx].serdes_mode;
                serdes_lane_hw_num = hws_get_physical_serdes_num(idx);
 
                lane_data =
@@ -1968,7 +1945,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
 
                if (hws_serdes_topology_verify
                    (serdes_type, idx, serdes_mode) != MV_OK) {
-                       serdes_config_map[idx].serdes_type =
+                       serdes_map[idx].serdes_type =
                            DEFAULT_SERDES;
                        printf("%s: SerDes lane #%d is  disabled\n", __func__,
                               serdes_lane_hw_num);
@@ -1994,8 +1971,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
                        printf
                            ("%s: Warning: SerDes lane #%d and type %d are not supported together\n",
                             __func__, serdes_lane_hw_num, serdes_mode);
-                       serdes_config_map[idx].serdes_type =
-                               DEFAULT_SERDES;
+                       serdes_map[idx].serdes_type = DEFAULT_SERDES;
                        printf("%s: SerDes lane #%d is  disabled\n", __func__,
                               serdes_lane_hw_num);
                        continue;
@@ -2017,7 +1993,7 @@ int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map)
 
        /* Print topology */
        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
@@ -2171,7 +2147,7 @@ int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type,
  * RETURNS:              MV_OK           - for success
  *                       MV_BAD_PARAM    - for fail
  */
-int hws_pex_tx_config_seq(struct serdes_map *serdes_map)
+int hws_pex_tx_config_seq(const struct serdes_map *serdes_map, u8 count)
 {
        enum serdes_mode serdes_mode;
        u32 serdes_lane_id, serdes_lane_hw_num;
@@ -2185,8 +2161,7 @@ int hws_pex_tx_config_seq(struct serdes_map *serdes_map)
         */
 
        /* relese pipe soft reset for all lanes */
-       for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane();
-            serdes_lane_id++) {
+       for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
                serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
                serdes_lane_hw_num =
                    hws_get_physical_serdes_num(serdes_lane_id);
@@ -2199,8 +2174,7 @@ int hws_pex_tx_config_seq(struct serdes_map *serdes_map)
        }
 
        /* set phy soft reset for all lanes */
-       for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane();
-            serdes_lane_id++) {
+       for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
                serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
                serdes_lane_hw_num =
                    hws_get_physical_serdes_num(serdes_lane_id);
@@ -2212,8 +2186,7 @@ int hws_pex_tx_config_seq(struct serdes_map *serdes_map)
        }
 
        /* set phy soft reset for all lanes */
-       for (serdes_lane_id = 0; serdes_lane_id < hws_serdes_get_max_lane();
-            serdes_lane_id++) {
+       for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) {
                serdes_mode = serdes_map[serdes_lane_id].serdes_mode;
                serdes_lane_hw_num =
                    hws_get_physical_serdes_num(serdes_lane_id);