Merge git://git.denx.de/u-boot-tegra
[oweals/u-boot.git] / arch / powerpc / cpu / mpc85xx / p1022_serdes.c
index 6b0fbf200cd02d14f269e3be62044244e244ce26..4c51a72630dc22ea33c7989e5c92b99551d13549 100644 (file)
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2010 Freescale Semiconductor, Inc.
  * Author: Timur Tabi <timur@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
  */
 
 #include <config.h>
@@ -17,6 +13,8 @@
 #define SRDS1_MAX_LANES                4
 #define SRDS2_MAX_LANES                2
 
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
 static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
        [0x00] = {NONE, NONE, NONE, NONE},
        [0x01] = {NONE, NONE, NONE, NONE},
@@ -72,27 +70,59 @@ static const u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
 };
 
 int is_serdes_configured(enum srds_prtcl device)
+{
+       int ret;
+
+       if (!(serdes1_prtcl_map & (1 << NONE)))
+               fsl_serdes_init();
+
+       ret = (1 << device) & serdes1_prtcl_map;
+
+       if (ret)
+               return ret;
+
+       if (!(serdes2_prtcl_map & (1 << NONE)))
+               fsl_serdes_init();
+
+       return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
 {
        ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
        u32 pordevsr = in_be32(&gur->pordevsr);
        u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
                                MPC85xx_PORDEVSR_IO_SEL_SHIFT;
-       unsigned int i;
+       int lane;
+
+       if (serdes1_prtcl_map & (1 << NONE) &&
+           serdes2_prtcl_map & (1 << NONE))
+               return;
+
+       debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+               printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+               return;
+       }
+       for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+               enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+               serdes1_prtcl_map |= (1 << lane_prtcl);
+       }
 
-       debug("%s: dev = %d\n", __FUNCTION__, device);
-       debug("PORDEVSR[IO_SEL] = 0x%x\n", srds_cfg);
+       /* Set the first bit to indicate serdes has been initialized */
+       serdes1_prtcl_map |= (1 << NONE);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
-               printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds_cfg);
-               return 0;
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+               printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+               return;
        }
 
-       for (i = 0; i < SRDS1_MAX_LANES; i++) {
-               if (serdes1_cfg_tbl[srds_cfg][i] == device)
-                       return 1;
-               if (serdes2_cfg_tbl[srds_cfg][i] == device)
-                       return 1;
+       for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+               enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+               serdes2_prtcl_map |= (1 << lane_prtcl);
        }
 
-       return 0;
+       /* Set the first bit to indicate serdes has been initialized */
+       serdes2_prtcl_map |= (1 << NONE);
 }