/* * Copyright (C) 2008 Freescale Semicondutor, Inc. All rights reserved. * Dave Liu <daveliu@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> #include <common.h> #include <asm/io.h> #include <asm/immap_85xx.h> /* PORDEVSR register */ #define GUTS_PORDEVSR_OFFS 0xc #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27 /* SerDes CR0 register */ #define FSL_SRDSCR0_OFFS 0x0 #define FSL_SRDSCR0_TXEQA_MASK 0x00007000 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000 #define FSL_SRDSCR0_TXEQA_SATA 0x00001000 #define FSL_SRDSCR0_TXEQE_MASK 0x00000700 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400 #define FSL_SRDSCR0_TXEQE_SATA 0x00000100 /* SerDes CR1 register */ #define FSL_SRDSCR1_OFFS 0x4 #define FSL_SRDSCR1_LANEA_MASK 0x80200000 #define FSL_SRDSCR1_LANEA_OFF 0x80200000 #define FSL_SRDSCR1_LANEE_MASK 0x08020000 #define FSL_SRDSCR1_LANEE_OFF 0x08020000 /* SerDes CR2 register */ #define FSL_SRDSCR2_OFFS 0x8 #define FSL_SRDSCR2_EICA_MASK 0x00001f00 #define FSL_SRDSCR2_EICA_SGMII 0x00000400 #define FSL_SRDSCR2_EICA_SATA 0x00001400 #define FSL_SRDSCR2_EICE_MASK 0x0000001f #define FSL_SRDSCR2_EICE_SGMII 0x00000004 #define FSL_SRDSCR2_EICE_SATA 0x00000014 /* SerDes CR3 register */ #define FSL_SRDSCR3_OFFS 0xc #define FSL_SRDSCR3_LANEA_MASK 0x3f000700 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000 #define FSL_SRDSCR3_LANEA_SATA 0x15000500 #define FSL_SRDSCR3_LANEE_MASK 0x003f0007 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000 #define FSL_SRDSCR3_LANEE_SATA 0x00150005 void fsl_serdes_init(void) { void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR; u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS); u32 srds2_io_sel; u32 tmp; /* parse the SRDS2_IO_SEL of PORDEVSR */ srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL) >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT; switch (srds2_io_sel) { case 1: /* Lane A - SATA1, Lane E - SATA2 */ /* CR 0 */ tmp = in_be32(sd + FSL_SRDSCR0_OFFS); tmp &= ~FSL_SRDSCR0_TXEQA_MASK; tmp |= FSL_SRDSCR0_TXEQA_SATA; tmp &= ~FSL_SRDSCR0_TXEQE_MASK; tmp |= FSL_SRDSCR0_TXEQE_SATA; out_be32(sd + FSL_SRDSCR0_OFFS, tmp); /* CR 1 */ tmp = in_be32(sd + FSL_SRDSCR1_OFFS); tmp &= ~FSL_SRDSCR1_LANEA_MASK; tmp &= ~FSL_SRDSCR1_LANEE_MASK; out_be32(sd + FSL_SRDSCR1_OFFS, tmp); /* CR 2 */ tmp = in_be32(sd + FSL_SRDSCR2_OFFS); tmp &= ~FSL_SRDSCR2_EICA_MASK; tmp |= FSL_SRDSCR2_EICA_SATA; tmp &= ~FSL_SRDSCR2_EICE_MASK; tmp |= FSL_SRDSCR2_EICE_SATA; out_be32(sd + FSL_SRDSCR2_OFFS, tmp); /* CR 3 */ tmp = in_be32(sd + FSL_SRDSCR3_OFFS); tmp &= ~FSL_SRDSCR3_LANEA_MASK; tmp |= FSL_SRDSCR3_LANEA_SATA; tmp &= ~FSL_SRDSCR3_LANEE_MASK; tmp |= FSL_SRDSCR3_LANEE_SATA; out_be32(sd + FSL_SRDSCR3_OFFS, tmp); break; case 3: /* Lane A - SATA1, Lane E - disabled */ /* CR 0 */ tmp = in_be32(sd + FSL_SRDSCR0_OFFS); tmp &= ~FSL_SRDSCR0_TXEQA_MASK; tmp |= FSL_SRDSCR0_TXEQA_SATA; out_be32(sd + FSL_SRDSCR0_OFFS, tmp); /* CR 1 */ tmp = in_be32(sd + FSL_SRDSCR1_OFFS); tmp &= ~FSL_SRDSCR1_LANEE_MASK; tmp |= FSL_SRDSCR1_LANEE_OFF; out_be32(sd + FSL_SRDSCR1_OFFS, tmp); /* CR 2 */ tmp = in_be32(sd + FSL_SRDSCR2_OFFS); tmp &= ~FSL_SRDSCR2_EICA_MASK; tmp |= FSL_SRDSCR2_EICA_SATA; out_be32(sd + FSL_SRDSCR2_OFFS, tmp); /* CR 3 */ tmp = in_be32(sd + FSL_SRDSCR3_OFFS); tmp &= ~FSL_SRDSCR3_LANEA_MASK; tmp |= FSL_SRDSCR3_LANEA_SATA; out_be32(sd + FSL_SRDSCR3_OFFS, tmp); break; case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */ /* CR 0 */ tmp = in_be32(sd + FSL_SRDSCR0_OFFS); tmp &= ~FSL_SRDSCR0_TXEQA_MASK; tmp |= FSL_SRDSCR0_TXEQA_SGMII; tmp &= ~FSL_SRDSCR0_TXEQE_MASK; tmp |= FSL_SRDSCR0_TXEQE_SGMII; out_be32(sd + FSL_SRDSCR0_OFFS, tmp); /* CR 1 */ tmp = in_be32(sd + FSL_SRDSCR1_OFFS); tmp &= ~FSL_SRDSCR1_LANEA_MASK; tmp &= ~FSL_SRDSCR1_LANEE_MASK; out_be32(sd + FSL_SRDSCR1_OFFS, tmp); /* CR 2 */ tmp = in_be32(sd + FSL_SRDSCR2_OFFS); tmp &= ~FSL_SRDSCR2_EICA_MASK; tmp |= FSL_SRDSCR2_EICA_SGMII; tmp &= ~FSL_SRDSCR2_EICE_MASK; tmp |= FSL_SRDSCR2_EICE_SGMII; out_be32(sd + FSL_SRDSCR2_OFFS, tmp); /* CR 3 */ tmp = in_be32(sd + FSL_SRDSCR3_OFFS); tmp &= ~FSL_SRDSCR3_LANEA_MASK; tmp |= FSL_SRDSCR3_LANEA_SGMII; tmp &= ~FSL_SRDSCR3_LANEE_MASK; tmp |= FSL_SRDSCR3_LANEE_SGMII; out_be32(sd + FSL_SRDSCR3_OFFS, tmp); break; case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */ /* CR 0 */ tmp = in_be32(sd + FSL_SRDSCR0_OFFS); tmp &= ~FSL_SRDSCR0_TXEQA_MASK; tmp |= FSL_SRDSCR0_TXEQA_SGMII; out_be32(sd + FSL_SRDSCR0_OFFS, tmp); /* CR 1 */ tmp = in_be32(sd + FSL_SRDSCR1_OFFS); tmp &= ~FSL_SRDSCR1_LANEE_MASK; tmp |= FSL_SRDSCR1_LANEE_OFF; out_be32(sd + FSL_SRDSCR1_OFFS, tmp); /* CR 2 */ tmp = in_be32(sd + FSL_SRDSCR2_OFFS); tmp &= ~FSL_SRDSCR2_EICA_MASK; tmp |= FSL_SRDSCR2_EICA_SGMII; out_be32(sd + FSL_SRDSCR2_OFFS, tmp); /* CR 3 */ tmp = in_be32(sd + FSL_SRDSCR3_OFFS); tmp &= ~FSL_SRDSCR3_LANEA_MASK; tmp |= FSL_SRDSCR3_LANEA_SGMII; out_be32(sd + FSL_SRDSCR3_OFFS, tmp); break; case 7: /* Lane A - disabled, Lane E - disabled */ /* CR 1 */ tmp = in_be32(sd + FSL_SRDSCR1_OFFS); tmp &= ~FSL_SRDSCR1_LANEA_MASK; tmp |= FSL_SRDSCR1_LANEA_OFF; tmp &= ~FSL_SRDSCR1_LANEE_MASK; tmp |= FSL_SRDSCR1_LANEE_OFF; out_be32(sd + FSL_SRDSCR1_OFFS, tmp); break; default: break; } }