uboot/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008,2010 Freescale Semiconductor, Inc.
   3 *      Dave Liu <daveliu@freescale.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <config.h>
   9#include <common.h>
  10#include <asm/io.h>
  11#include <asm/immap_85xx.h>
  12#include <asm/fsl_serdes.h>
  13
  14/* PORDEVSR register */
  15#define GUTS_PORDEVSR_OFFS              0xc
  16#define GUTS_PORDEVSR_SERDES2_IO_SEL    0x38000000
  17#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT      27
  18
  19/* SerDes CR0 register */
  20#define FSL_SRDSCR0_OFFS        0x0
  21#define FSL_SRDSCR0_TXEQA_MASK  0x00007000
  22#define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
  23#define FSL_SRDSCR0_TXEQA_SATA  0x00001000
  24#define FSL_SRDSCR0_TXEQE_MASK  0x00000700
  25#define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
  26#define FSL_SRDSCR0_TXEQE_SATA  0x00000100
  27
  28/* SerDes CR1 register */
  29#define FSL_SRDSCR1_OFFS        0x4
  30#define FSL_SRDSCR1_LANEA_MASK  0x80200000
  31#define FSL_SRDSCR1_LANEA_OFF   0x80200000
  32#define FSL_SRDSCR1_LANEE_MASK  0x08020000
  33#define FSL_SRDSCR1_LANEE_OFF   0x08020000
  34
  35/* SerDes CR2 register */
  36#define FSL_SRDSCR2_OFFS        0x8
  37#define FSL_SRDSCR2_EICA_MASK   0x00001f00
  38#define FSL_SRDSCR2_EICA_SGMII  0x00000400
  39#define FSL_SRDSCR2_EICA_SATA   0x00001400
  40#define FSL_SRDSCR2_EICE_MASK   0x0000001f
  41#define FSL_SRDSCR2_EICE_SGMII  0x00000004
  42#define FSL_SRDSCR2_EICE_SATA   0x00000014
  43
  44/* SerDes CR3 register */
  45#define FSL_SRDSCR3_OFFS        0xc
  46#define FSL_SRDSCR3_LANEA_MASK  0x3f000700
  47#define FSL_SRDSCR3_LANEA_SGMII 0x00000000
  48#define FSL_SRDSCR3_LANEA_SATA  0x15000500
  49#define FSL_SRDSCR3_LANEE_MASK  0x003f0007
  50#define FSL_SRDSCR3_LANEE_SGMII 0x00000000
  51#define FSL_SRDSCR3_LANEE_SATA  0x00150005
  52
  53#define SRDS1_MAX_LANES         8
  54#define SRDS2_MAX_LANES         2
  55
  56static u32 serdes1_prtcl_map, serdes2_prtcl_map;
  57
  58static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
  59        [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
  60        [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
  61        [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
  62        [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
  63};
  64
  65static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
  66        [0x1] = {SATA1, SATA2},
  67        [0x3] = {SATA1, NONE},
  68        [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
  69        [0x6] = {SGMII_TSEC1, NONE},
  70};
  71
  72int is_serdes_configured(enum srds_prtcl device)
  73{
  74        int ret;
  75
  76        if (!(serdes1_prtcl_map & (1 << NONE)))
  77                fsl_serdes_init();
  78
  79        ret = (1 << device) & serdes1_prtcl_map;
  80
  81        if (ret)
  82                return ret;
  83
  84        if (!(serdes2_prtcl_map & (1 << NONE)))
  85                fsl_serdes_init();
  86
  87        return (1 << device) & serdes2_prtcl_map;
  88}
  89
  90void fsl_serdes_init(void)
  91{
  92        void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  93        void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
  94        u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
  95        u32 srds1_io_sel, srds2_io_sel;
  96        u32 tmp;
  97        int lane;
  98
  99        if (serdes1_prtcl_map & (1 << NONE) &&
 100            serdes2_prtcl_map & (1 << NONE))
 101                return;
 102
 103        srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
 104                                MPC85xx_PORDEVSR_IO_SEL_SHIFT;
 105
 106        /* parse the SRDS2_IO_SEL of PORDEVSR */
 107        srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
 108                       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
 109
 110        debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
 111        debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
 112
 113        switch (srds2_io_sel) {
 114        case 1: /* Lane A - SATA1, Lane E - SATA2 */
 115                /* CR 0 */
 116                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 117                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 118                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 119                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 120                tmp |= FSL_SRDSCR0_TXEQE_SATA;
 121                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 122                /* CR 1 */
 123                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 124                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 125                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 126                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 127                /* CR 2 */
 128                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 129                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 130                tmp |= FSL_SRDSCR2_EICA_SATA;
 131                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 132                tmp |= FSL_SRDSCR2_EICE_SATA;
 133                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 134                /* CR 3 */
 135                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 136                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 137                tmp |= FSL_SRDSCR3_LANEA_SATA;
 138                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 139                tmp |= FSL_SRDSCR3_LANEE_SATA;
 140                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 141                break;
 142        case 3: /* Lane A - SATA1, Lane E - disabled */
 143                /* CR 0 */
 144                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 145                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 146                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 147                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 148                /* CR 1 */
 149                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 150                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 151                tmp |= FSL_SRDSCR1_LANEE_OFF;
 152                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 153                /* CR 2 */
 154                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 155                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 156                tmp |= FSL_SRDSCR2_EICA_SATA;
 157                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 158                /* CR 3 */
 159                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 160                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 161                tmp |= FSL_SRDSCR3_LANEA_SATA;
 162                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 163                break;
 164        case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
 165                /* CR 0 */
 166                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 167                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 168                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 169                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 170                tmp |= FSL_SRDSCR0_TXEQE_SGMII;
 171                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 172                /* CR 1 */
 173                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 174                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 175                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 176                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 177                /* CR 2 */
 178                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 179                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 180                tmp |= FSL_SRDSCR2_EICA_SGMII;
 181                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 182                tmp |= FSL_SRDSCR2_EICE_SGMII;
 183                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 184                /* CR 3 */
 185                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 186                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 187                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 188                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 189                tmp |= FSL_SRDSCR3_LANEE_SGMII;
 190                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 191                break;
 192        case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
 193                /* CR 0 */
 194                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 195                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 196                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 197                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 198                /* CR 1 */
 199                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 200                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 201                tmp |= FSL_SRDSCR1_LANEE_OFF;
 202                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 203                /* CR 2 */
 204                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 205                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 206                tmp |= FSL_SRDSCR2_EICA_SGMII;
 207                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 208                /* CR 3 */
 209                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 210                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 211                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 212                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 213                break;
 214        case 7: /* Lane A - disabled, Lane E - disabled */
 215                /* CR 1 */
 216                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 217                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 218                tmp |= FSL_SRDSCR1_LANEA_OFF;
 219                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 220                tmp |= FSL_SRDSCR1_LANEE_OFF;
 221                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 222                break;
 223        default:
 224                break;
 225        }
 226
 227        if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 228                printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
 229                return;
 230        }
 231        for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
 232                enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
 233                serdes1_prtcl_map |= (1 << lane_prtcl);
 234        }
 235
 236        /* Set the first bit to indicate serdes has been initialized */
 237        serdes1_prtcl_map |= (1 << NONE);
 238
 239        if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 240                printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
 241                return;
 242        }
 243
 244        for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
 245                enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
 246                serdes2_prtcl_map |= (1 << lane_prtcl);
 247        }
 248
 249        /* Set the first bit to indicate serdes has been initialized */
 250        serdes2_prtcl_map |= (1 << NONE);
 251}
 252