uboot/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2017-2019 NXP
   4 */
   5
   6#include <common.h>
   7#include <asm/arch/fsl_serdes.h>
   8#include <asm/arch/soc.h>
   9#include <asm/io.h>
  10
  11struct serdes_config {
  12        u8 ip_protocol;
  13        u8 lanes[SRDS_MAX_LANES];
  14        u8 rcw_lanes[SRDS_MAX_LANES];
  15};
  16
  17static struct serdes_config serdes1_cfg_tbl[] = {
  18        /* SerDes 1 */
  19        {0x12, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 3 }  },
  20        {0x15, {SGMII3, SGMII7, XFI1, XFI2 }, {3, 3, 1, 1 } },
  21        {0x16, {SGMII3, SGMII7, SGMII1, XFI2 }, {3, 3, 3, 1 } },
  22        {0x17, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 2 } },
  23        {0x18, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 2, 2 } },
  24        {0x19, {SGMII3, QSGMII_B, XFI1, XFI2}, {3, 4, 1, 1 } },
  25        {0x1A, {SGMII3, QSGMII_B, SGMII1, XFI2 }, {3, 4, 3, 1 } },
  26        {0x1B, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 2 } },
  27        {0x1C, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 2, 2 } },
  28        {0x1D, {QSGMII_A, QSGMII_B, XFI1, XFI2 }, {4, 4, 1, 1 } },
  29        {0x1E, {QSGMII_A, QSGMII_B, SGMII1, XFI2  }, {4, 4, 3, 1 } },
  30        {0x1F, {QSGMII_A, QSGMII_B, SGMII1, SGMII2  }, {4, 4, 3, 2 } },
  31        {0x20, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 2, 2 } },
  32        {0x35, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 3 } },
  33        {0x36, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 3, 3 } },
  34        {0x3A, {SGMII3, PCIE1, SGMII1, SGMII2 }, {3, 5, 3, 3 } },
  35                {}
  36};
  37
  38static struct serdes_config serdes2_cfg_tbl[] = {
  39        /* SerDes 2 */
  40        {0x0C, {PCIE1, PCIE1, PCIE1, PCIE1 }, {8, 8, 8, 8 } },
  41        {0x0D, {PCIE1, PCIE2, PCIE3, SATA1 }, {5, 5, 5, 9 }  },
  42        {0x0E, {PCIE1, PCIE1, PCIE2, SATA1 }, {7, 7, 6, 9 }  },
  43        {0x13, {PCIE1, PCIE1, PCIE3, PCIE3 }, {7, 7, 7, 7 }  },
  44        {0x14, {PCIE1, PCIE2, PCIE3, PCIE3 }, {5, 5, 7, 7 }  },
  45        {0x3C, {NONE, PCIE2, NONE, PCIE3 }, {0, 5, 0, 6 }  },
  46        {}
  47};
  48
  49static struct serdes_config *serdes_cfg_tbl[] = {
  50        serdes1_cfg_tbl,
  51        serdes2_cfg_tbl,
  52};
  53
  54bool soc_has_mac1(void)
  55{
  56        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  57        unsigned int svr = gur_in32(&gur->svr);
  58        unsigned int version = SVR_SOC_VER(svr);
  59
  60        return (version == SVR_LS1088A || version == SVR_LS1084A);
  61}
  62
  63int serdes_get_number(int serdes, int cfg)
  64{
  65        struct serdes_config *ptr;
  66        int i, j, index, lnk;
  67        int is_found, max_lane = SRDS_MAX_LANES;
  68
  69        if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
  70                return 0;
  71
  72        ptr = serdes_cfg_tbl[serdes];
  73
  74        while (ptr->ip_protocol) {
  75                is_found = 1;
  76                for (i = 0, j = max_lane - 1; i < max_lane; i++, j--) {
  77                        lnk = cfg & (0xf << 4 * i);
  78                        lnk = lnk >> (4 * i);
  79
  80                        index = (serdes == FSL_SRDS_1) ? j : i;
  81
  82                        if (ptr->rcw_lanes[index] == lnk && is_found)
  83                                is_found = 1;
  84                        else
  85                                is_found = 0;
  86                }
  87
  88                if (is_found)
  89                        return ptr->ip_protocol;
  90                ptr++;
  91        }
  92
  93        return 0;
  94}
  95
  96enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
  97{
  98        struct serdes_config *ptr;
  99
 100        if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
 101                return 0;
 102        /*
 103         * LS1044A/1048A  support only one XFI port
 104         * Disable MAC1 for LS1044A/1048A
 105         */
 106        if (serdes == FSL_SRDS_1 && lane == 2) {
 107                if (!soc_has_mac1())
 108                        return 0;
 109        }
 110        ptr = serdes_cfg_tbl[serdes];
 111        while (ptr->ip_protocol) {
 112                if (ptr->ip_protocol == cfg)
 113                        return ptr->lanes[lane];
 114                ptr++;
 115        }
 116
 117        return 0;
 118}
 119
 120int is_serdes_prtcl_valid(int serdes, u32 prtcl)
 121{
 122        int i;
 123        struct serdes_config *ptr;
 124
 125        if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
 126                return 0;
 127
 128        ptr = serdes_cfg_tbl[serdes];
 129        while (ptr->ip_protocol) {
 130                if (ptr->ip_protocol == prtcl)
 131                        break;
 132                ptr++;
 133        }
 134
 135        if (!ptr->ip_protocol)
 136                return 0;
 137
 138        for (i = 0; i < SRDS_MAX_LANES; i++) {
 139                if (ptr->lanes[i] != NONE)
 140                        return 1;
 141        }
 142
 143        return 0;
 144}
 145