1*a47a12beSStefan Roese /* 2*a47a12beSStefan Roese * Freescale SerDes initialization routine 3*a47a12beSStefan Roese * 4*a47a12beSStefan Roese * Copyright (C) 2007 Freescale Semicondutor, Inc. 5*a47a12beSStefan Roese * Copyright (C) 2008 MontaVista Software, Inc. 6*a47a12beSStefan Roese * 7*a47a12beSStefan Roese * Author: Li Yang <leoli@freescale.com> 8*a47a12beSStefan Roese * 9*a47a12beSStefan Roese * This program is free software; you can redistribute it and/or modify it 10*a47a12beSStefan Roese * under the terms of the GNU General Public License as published by the 11*a47a12beSStefan Roese * Free Software Foundation; either version 2 of the License, or (at your 12*a47a12beSStefan Roese * option) any later version. 13*a47a12beSStefan Roese */ 14*a47a12beSStefan Roese 15*a47a12beSStefan Roese #include <config.h> 16*a47a12beSStefan Roese #include <common.h> 17*a47a12beSStefan Roese #include <asm/io.h> 18*a47a12beSStefan Roese #include <asm/fsl_serdes.h> 19*a47a12beSStefan Roese 20*a47a12beSStefan Roese /* SerDes registers */ 21*a47a12beSStefan Roese #define FSL_SRDSCR0_OFFS 0x0 22*a47a12beSStefan Roese #define FSL_SRDSCR0_DPP_1V2 0x00008800 23*a47a12beSStefan Roese #define FSL_SRDSCR1_OFFS 0x4 24*a47a12beSStefan Roese #define FSL_SRDSCR1_PLLBW 0x00000040 25*a47a12beSStefan Roese #define FSL_SRDSCR2_OFFS 0x8 26*a47a12beSStefan Roese #define FSL_SRDSCR2_VDD_1V2 0x00800000 27*a47a12beSStefan Roese #define FSL_SRDSCR2_SEIC_MASK 0x00001c1c 28*a47a12beSStefan Roese #define FSL_SRDSCR2_SEIC_SATA 0x00001414 29*a47a12beSStefan Roese #define FSL_SRDSCR2_SEIC_PEX 0x00001010 30*a47a12beSStefan Roese #define FSL_SRDSCR2_SEIC_SGMII 0x00000101 31*a47a12beSStefan Roese #define FSL_SRDSCR3_OFFS 0xc 32*a47a12beSStefan Roese #define FSL_SRDSCR3_KFR_SATA 0x10100000 33*a47a12beSStefan Roese #define FSL_SRDSCR3_KPH_SATA 0x04040000 34*a47a12beSStefan Roese #define FSL_SRDSCR3_SDFM_SATA_PEX 0x01010000 35*a47a12beSStefan Roese #define FSL_SRDSCR3_SDTXL_SATA 0x00000505 36*a47a12beSStefan Roese #define FSL_SRDSCR4_OFFS 0x10 37*a47a12beSStefan Roese #define FSL_SRDSCR4_PROT_SATA 0x00000808 38*a47a12beSStefan Roese #define FSL_SRDSCR4_PROT_PEX 0x00000101 39*a47a12beSStefan Roese #define FSL_SRDSCR4_PROT_SGMII 0x00000505 40*a47a12beSStefan Roese #define FSL_SRDSCR4_PLANE_X2 0x01000000 41*a47a12beSStefan Roese #define FSL_SRDSRSTCTL_OFFS 0x20 42*a47a12beSStefan Roese #define FSL_SRDSRSTCTL_RST 0x80000000 43*a47a12beSStefan Roese #define FSL_SRDSRSTCTL_SATA_RESET 0xf 44*a47a12beSStefan Roese 45*a47a12beSStefan Roese void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd) 46*a47a12beSStefan Roese { 47*a47a12beSStefan Roese void *regs = (void *)CONFIG_SYS_IMMR + offset; 48*a47a12beSStefan Roese u32 tmp; 49*a47a12beSStefan Roese 50*a47a12beSStefan Roese /* 1.0V corevdd */ 51*a47a12beSStefan Roese if (vdd) { 52*a47a12beSStefan Roese /* DPPE/DPPA = 0 */ 53*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR0_OFFS); 54*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR0_DPP_1V2; 55*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR0_OFFS, tmp); 56*a47a12beSStefan Roese 57*a47a12beSStefan Roese /* VDD = 0 */ 58*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR2_OFFS); 59*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR2_VDD_1V2; 60*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR2_OFFS, tmp); 61*a47a12beSStefan Roese } 62*a47a12beSStefan Roese 63*a47a12beSStefan Roese /* protocol specific configuration */ 64*a47a12beSStefan Roese switch (proto) { 65*a47a12beSStefan Roese case FSL_SERDES_PROTO_SATA: 66*a47a12beSStefan Roese /* Set and clear reset bits */ 67*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS); 68*a47a12beSStefan Roese tmp |= FSL_SRDSRSTCTL_SATA_RESET; 69*a47a12beSStefan Roese out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp); 70*a47a12beSStefan Roese udelay(1000); 71*a47a12beSStefan Roese tmp &= ~FSL_SRDSRSTCTL_SATA_RESET; 72*a47a12beSStefan Roese out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp); 73*a47a12beSStefan Roese 74*a47a12beSStefan Roese /* Configure SRDSCR1 */ 75*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR1_OFFS); 76*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR1_PLLBW; 77*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR1_OFFS, tmp); 78*a47a12beSStefan Roese 79*a47a12beSStefan Roese /* Configure SRDSCR2 */ 80*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR2_OFFS); 81*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR2_SEIC_MASK; 82*a47a12beSStefan Roese tmp |= FSL_SRDSCR2_SEIC_SATA; 83*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR2_OFFS, tmp); 84*a47a12beSStefan Roese 85*a47a12beSStefan Roese /* Configure SRDSCR3 */ 86*a47a12beSStefan Roese tmp = FSL_SRDSCR3_KFR_SATA | FSL_SRDSCR3_KPH_SATA | 87*a47a12beSStefan Roese FSL_SRDSCR3_SDFM_SATA_PEX | 88*a47a12beSStefan Roese FSL_SRDSCR3_SDTXL_SATA; 89*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR3_OFFS, tmp); 90*a47a12beSStefan Roese 91*a47a12beSStefan Roese /* Configure SRDSCR4 */ 92*a47a12beSStefan Roese tmp = rfcks | FSL_SRDSCR4_PROT_SATA; 93*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR4_OFFS, tmp); 94*a47a12beSStefan Roese break; 95*a47a12beSStefan Roese case FSL_SERDES_PROTO_PEX: 96*a47a12beSStefan Roese case FSL_SERDES_PROTO_PEX_X2: 97*a47a12beSStefan Roese /* Configure SRDSCR1 */ 98*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR1_OFFS); 99*a47a12beSStefan Roese tmp |= FSL_SRDSCR1_PLLBW; 100*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR1_OFFS, tmp); 101*a47a12beSStefan Roese 102*a47a12beSStefan Roese /* Configure SRDSCR2 */ 103*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR2_OFFS); 104*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR2_SEIC_MASK; 105*a47a12beSStefan Roese tmp |= FSL_SRDSCR2_SEIC_PEX; 106*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR2_OFFS, tmp); 107*a47a12beSStefan Roese 108*a47a12beSStefan Roese /* Configure SRDSCR3 */ 109*a47a12beSStefan Roese tmp = FSL_SRDSCR3_SDFM_SATA_PEX; 110*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR3_OFFS, tmp); 111*a47a12beSStefan Roese 112*a47a12beSStefan Roese /* Configure SRDSCR4 */ 113*a47a12beSStefan Roese tmp = rfcks | FSL_SRDSCR4_PROT_PEX; 114*a47a12beSStefan Roese if (proto == FSL_SERDES_PROTO_PEX_X2) 115*a47a12beSStefan Roese tmp |= FSL_SRDSCR4_PLANE_X2; 116*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR4_OFFS, tmp); 117*a47a12beSStefan Roese break; 118*a47a12beSStefan Roese case FSL_SERDES_PROTO_SGMII: 119*a47a12beSStefan Roese /* Configure SRDSCR1 */ 120*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR1_OFFS); 121*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR1_PLLBW; 122*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR1_OFFS, tmp); 123*a47a12beSStefan Roese 124*a47a12beSStefan Roese /* Configure SRDSCR2 */ 125*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSCR2_OFFS); 126*a47a12beSStefan Roese tmp &= ~FSL_SRDSCR2_SEIC_MASK; 127*a47a12beSStefan Roese tmp |= FSL_SRDSCR2_SEIC_SGMII; 128*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR2_OFFS, tmp); 129*a47a12beSStefan Roese 130*a47a12beSStefan Roese /* Configure SRDSCR3 */ 131*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR3_OFFS, 0); 132*a47a12beSStefan Roese 133*a47a12beSStefan Roese /* Configure SRDSCR4 */ 134*a47a12beSStefan Roese tmp = rfcks | FSL_SRDSCR4_PROT_SGMII; 135*a47a12beSStefan Roese out_be32(regs + FSL_SRDSCR4_OFFS, tmp); 136*a47a12beSStefan Roese break; 137*a47a12beSStefan Roese default: 138*a47a12beSStefan Roese return; 139*a47a12beSStefan Roese } 140*a47a12beSStefan Roese 141*a47a12beSStefan Roese /* Do a software reset */ 142*a47a12beSStefan Roese tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS); 143*a47a12beSStefan Roese tmp |= FSL_SRDSRSTCTL_RST; 144*a47a12beSStefan Roese out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp); 145*a47a12beSStefan Roese } 146