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 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <config.h>
  25#include <common.h>
  26#include <asm/io.h>
  27#include <asm/immap_85xx.h>
  28#include <asm/fsl_serdes.h>
  29
  30/* PORDEVSR register */
  31#define GUTS_PORDEVSR_OFFS              0xc
  32#define GUTS_PORDEVSR_SERDES2_IO_SEL    0x38000000
  33#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT      27
  34
  35/* SerDes CR0 register */
  36#define FSL_SRDSCR0_OFFS        0x0
  37#define FSL_SRDSCR0_TXEQA_MASK  0x00007000
  38#define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
  39#define FSL_SRDSCR0_TXEQA_SATA  0x00001000
  40#define FSL_SRDSCR0_TXEQE_MASK  0x00000700
  41#define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
  42#define FSL_SRDSCR0_TXEQE_SATA  0x00000100
  43
  44/* SerDes CR1 register */
  45#define FSL_SRDSCR1_OFFS        0x4
  46#define FSL_SRDSCR1_LANEA_MASK  0x80200000
  47#define FSL_SRDSCR1_LANEA_OFF   0x80200000
  48#define FSL_SRDSCR1_LANEE_MASK  0x08020000
  49#define FSL_SRDSCR1_LANEE_OFF   0x08020000
  50
  51/* SerDes CR2 register */
  52#define FSL_SRDSCR2_OFFS        0x8
  53#define FSL_SRDSCR2_EICA_MASK   0x00001f00
  54#define FSL_SRDSCR2_EICA_SGMII  0x00000400
  55#define FSL_SRDSCR2_EICA_SATA   0x00001400
  56#define FSL_SRDSCR2_EICE_MASK   0x0000001f
  57#define FSL_SRDSCR2_EICE_SGMII  0x00000004
  58#define FSL_SRDSCR2_EICE_SATA   0x00000014
  59
  60/* SerDes CR3 register */
  61#define FSL_SRDSCR3_OFFS        0xc
  62#define FSL_SRDSCR3_LANEA_MASK  0x3f000700
  63#define FSL_SRDSCR3_LANEA_SGMII 0x00000000
  64#define FSL_SRDSCR3_LANEA_SATA  0x15000500
  65#define FSL_SRDSCR3_LANEE_MASK  0x003f0007
  66#define FSL_SRDSCR3_LANEE_SGMII 0x00000000
  67#define FSL_SRDSCR3_LANEE_SATA  0x00150005
  68
  69#define SRDS1_MAX_LANES         8
  70#define SRDS2_MAX_LANES         2
  71
  72static u32 serdes1_prtcl_map, serdes2_prtcl_map;
  73
  74static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
  75        [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
  76        [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
  77        [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
  78        [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
  79};
  80
  81static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
  82        [0x1] = {SATA1, SATA2},
  83        [0x3] = {SATA1, NONE},
  84        [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
  85        [0x6] = {SGMII_TSEC1, NONE},
  86};
  87
  88int is_serdes_configured(enum srds_prtcl device)
  89{
  90        int ret = (1 << device) & serdes1_prtcl_map;
  91
  92        if (ret)
  93                return ret;
  94
  95        return (1 << device) & serdes2_prtcl_map;
  96}
  97
  98void fsl_serdes_init(void)
  99{
 100        void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 101        void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
 102        u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
 103        u32 srds1_io_sel, srds2_io_sel;
 104        u32 tmp;
 105        int lane;
 106
 107        srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
 108                                MPC85xx_PORDEVSR_IO_SEL_SHIFT;
 109
 110        /* parse the SRDS2_IO_SEL of PORDEVSR */
 111        srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
 112                       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
 113
 114        debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
 115        debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
 116
 117        switch (srds2_io_sel) {
 118        case 1: /* Lane A - SATA1, Lane E - SATA2 */
 119                /* CR 0 */
 120                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 121                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 122                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 123                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 124                tmp |= FSL_SRDSCR0_TXEQE_SATA;
 125                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 126                /* CR 1 */
 127                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 128                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 129                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 130                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 131                /* CR 2 */
 132                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 133                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 134                tmp |= FSL_SRDSCR2_EICA_SATA;
 135                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 136                tmp |= FSL_SRDSCR2_EICE_SATA;
 137                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 138                /* CR 3 */
 139                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 140                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 141                tmp |= FSL_SRDSCR3_LANEA_SATA;
 142                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 143                tmp |= FSL_SRDSCR3_LANEE_SATA;
 144                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 145                break;
 146        case 3: /* Lane A - SATA1, Lane E - disabled */
 147                /* CR 0 */
 148                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 149                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 150                tmp |= FSL_SRDSCR0_TXEQA_SATA;
 151                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 152                /* CR 1 */
 153                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 154                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 155                tmp |= FSL_SRDSCR1_LANEE_OFF;
 156                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 157                /* CR 2 */
 158                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 159                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 160                tmp |= FSL_SRDSCR2_EICA_SATA;
 161                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 162                /* CR 3 */
 163                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 164                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 165                tmp |= FSL_SRDSCR3_LANEA_SATA;
 166                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 167                break;
 168        case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
 169                /* CR 0 */
 170                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 171                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 172                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 173                tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
 174                tmp |= FSL_SRDSCR0_TXEQE_SGMII;
 175                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 176                /* CR 1 */
 177                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 178                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 179                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 180                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 181                /* CR 2 */
 182                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 183                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 184                tmp |= FSL_SRDSCR2_EICA_SGMII;
 185                tmp &= ~FSL_SRDSCR2_EICE_MASK;
 186                tmp |= FSL_SRDSCR2_EICE_SGMII;
 187                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 188                /* CR 3 */
 189                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 190                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 191                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 192                tmp &= ~FSL_SRDSCR3_LANEE_MASK;
 193                tmp |= FSL_SRDSCR3_LANEE_SGMII;
 194                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 195                break;
 196        case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
 197                /* CR 0 */
 198                tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
 199                tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
 200                tmp |= FSL_SRDSCR0_TXEQA_SGMII;
 201                out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
 202                /* CR 1 */
 203                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 204                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 205                tmp |= FSL_SRDSCR1_LANEE_OFF;
 206                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 207                /* CR 2 */
 208                tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
 209                tmp &= ~FSL_SRDSCR2_EICA_MASK;
 210                tmp |= FSL_SRDSCR2_EICA_SGMII;
 211                out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
 212                /* CR 3 */
 213                tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
 214                tmp &= ~FSL_SRDSCR3_LANEA_MASK;
 215                tmp |= FSL_SRDSCR3_LANEA_SGMII;
 216                out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
 217                break;
 218        case 7: /* Lane A - disabled, Lane E - disabled */
 219                /* CR 1 */
 220                tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
 221                tmp &= ~FSL_SRDSCR1_LANEA_MASK;
 222                tmp |= FSL_SRDSCR1_LANEA_OFF;
 223                tmp &= ~FSL_SRDSCR1_LANEE_MASK;
 224                tmp |= FSL_SRDSCR1_LANEE_OFF;
 225                out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
 226                break;
 227        default:
 228                break;
 229        }
 230
 231        if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 232                printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
 233                return;
 234        }
 235        for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
 236                enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
 237                serdes1_prtcl_map |= (1 << lane_prtcl);
 238        }
 239
 240        if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 241                printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
 242                return;
 243        }
 244
 245        for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
 246                enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
 247                serdes2_prtcl_map |= (1 << lane_prtcl);
 248        }
 249}
 250