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 = (1 << device) & serdes1_prtcl_map;
  75
  76        if (ret)
  77                return ret;
  78
  79        return (1 << device) & serdes2_prtcl_map;
  80}
  81
  82void fsl_serdes_init(void)
  83{
  84        void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  85        void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
  86        u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
  87        u32 srds1_io_sel, srds2_io_sel;
  88        u32 tmp;
  89        int lane;
  90
  91        srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
  92                                MPC85xx_PORDEVSR_IO_SEL_SHIFT;
  93
  94        /* parse the SRDS2_IO_SEL of PORDEVSR */
  95        srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
  96                       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
  97
  98        debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
  99        debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
 100
 101        switch (srds2_io_sel) {
 102        case 1: /* Lane A - SATA1, Lane E - SATA2 */
 103                /* CR 0 */
 104                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 105                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 106                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 107                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 108                tmp |= FSL_SRDSCR0_TXEQE_SATA;
 109                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 110                /* CR 1 */
 111                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 112                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 113                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 114                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 115                /* CR 2 */
 116                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 117                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 118                tmp |= FSL_SRDSCR2_EICA_SATA;
 119                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 120                tmp |= FSL_SRDSCR2_EICE_SATA;
 121                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 122                /* CR 3 */
 123                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 124                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 125                tmp |= FSL_SRDSCR3_LANEA_SATA;
 126                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 127                tmp |= FSL_SRDSCR3_LANEE_SATA;
 128                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 129                break;
 130        case 3: /* Lane A - SATA1, Lane E - disabled */
 131                /* CR 0 */
 132                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 133                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 134                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 135                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 136                /* CR 1 */
 137                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 138                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 139                tmp |= FSL_SRDSCR1_LANEE_OFF;
 140                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 141                /* CR 2 */
 142                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 143                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 144                tmp |= FSL_SRDSCR2_EICA_SATA;
 145                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 146                /* CR 3 */
 147                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 148                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 149                tmp |= FSL_SRDSCR3_LANEA_SATA;
 150                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 151                break;
 152        case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
 153                /* CR 0 */
 154                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 155                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 156                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 157                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 158                tmp |= FSL_SRDSCR0_TXEQE_SGMII;
 159                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 160                /* CR 1 */
 161                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 162                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 163                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 164                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 165                /* CR 2 */
 166                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 167                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 168                tmp |= FSL_SRDSCR2_EICA_SGMII;
 169                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 170                tmp |= FSL_SRDSCR2_EICE_SGMII;
 171                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 172                /* CR 3 */
 173                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 174                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 175                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 176                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 177                tmp |= FSL_SRDSCR3_LANEE_SGMII;
 178                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 179                break;
 180        case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
 181                /* CR 0 */
 182                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 183                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 184                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 185                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 186                /* CR 1 */
 187                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 188                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 189                tmp |= FSL_SRDSCR1_LANEE_OFF;
 190                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 191                /* CR 2 */
 192                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 193                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 194                tmp |= FSL_SRDSCR2_EICA_SGMII;
 195                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 196                /* CR 3 */
 197                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 198                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 199                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 200                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 201                break;
 202        case 7: /* Lane A - disabled, Lane E - disabled */
 203                /* CR 1 */
 204                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 205                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 206                tmp |= FSL_SRDSCR1_LANEA_OFF;
 207                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 208                tmp |= FSL_SRDSCR1_LANEE_OFF;
 209                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 210                break;
 211        default:
 212                break;
 213        }
 214
 215        if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 216                printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
 217                return;
 218        }
 219        for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
 220                enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
 221                serdes1_prtcl_map |= (1 << lane_prtcl);
 222        }
 223
 224        if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 225                printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
 226                return;
 227        }
 228
 229        for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
 230                enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
 231                serdes2_prtcl_map |= (1 << lane_prtcl);
 232        }
 233}
 234