1 /* 2 * Copyright (C) 2007 Freescale Semiconductor, Inc. 3 * Dave Liu <daveliu@freescale.com> 4 * 5 * CREDITS: Kim Phillips contribute to LIBFDT code 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 */ 12 13 #include <common.h> 14 #include <i2c.h> 15 #include <asm/io.h> 16 #include <asm/fsl_serdes.h> 17 #include <spd_sdram.h> 18 #include <tsec.h> 19 #include <libfdt.h> 20 #include <fdt_support.h> 21 #include "../common/pq-mds-pib.h" 22 23 int board_early_init_f(void) 24 { 25 u8 *bcsr = (u8 *)CONFIG_SYS_BCSR; 26 27 /* Enable flash write */ 28 bcsr[0x9] &= ~0x04; 29 /* Clear all of the interrupt of BCSR */ 30 bcsr[0xe] = 0xff; 31 32 #ifdef CONFIG_FSL_SERDES 33 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; 34 u32 spridr = in_be32(&immr->sysconf.spridr); 35 36 /* we check only part num, and don't look for CPU revisions */ 37 switch (PARTID_NO_E(spridr)) { 38 case SPR_8377: 39 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA, 40 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); 41 fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, 42 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); 43 break; 44 case SPR_8378: 45 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SGMII, 46 FSL_SERDES_CLK_125, FSL_SERDES_VDD_1V); 47 fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, 48 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); 49 break; 50 case SPR_8379: 51 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA, 52 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); 53 fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_SATA, 54 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); 55 break; 56 default: 57 printf("serdes not configured: unknown CPU part number: " 58 "%04x\n", spridr >> 16); 59 break; 60 } 61 #endif /* CONFIG_FSL_SERDES */ 62 return 0; 63 } 64 65 #if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) 66 int board_eth_init(bd_t *bd) 67 { 68 struct tsec_info_struct tsec_info[2]; 69 struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; 70 u32 rcwh = in_be32(&im->reset.rcwh); 71 u32 tsec_mode; 72 int num = 0; 73 74 /* New line after Net: */ 75 printf("\n"); 76 77 #ifdef CONFIG_TSEC1 78 SET_STD_TSEC_INFO(tsec_info[num], 1); 79 80 printf(CONFIG_TSEC1_NAME ": "); 81 82 tsec_mode = rcwh & HRCWH_TSEC1M_MASK; 83 if (tsec_mode == HRCWH_TSEC1M_IN_RGMII) { 84 printf("RGMII\n"); 85 /* this is default, no need to fixup */ 86 } else if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) { 87 printf("SGMII\n"); 88 tsec_info[num].phyaddr = TSEC1_PHY_ADDR_SGMII; 89 tsec_info[num].flags = TSEC_GIGABIT; 90 } else { 91 printf("unsupported PHY type\n"); 92 } 93 num++; 94 #endif 95 #ifdef CONFIG_TSEC2 96 SET_STD_TSEC_INFO(tsec_info[num], 2); 97 98 printf(CONFIG_TSEC2_NAME ": "); 99 100 tsec_mode = rcwh & HRCWH_TSEC2M_MASK; 101 if (tsec_mode == HRCWH_TSEC2M_IN_RGMII) { 102 printf("RGMII\n"); 103 /* this is default, no need to fixup */ 104 } else if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) { 105 printf("SGMII\n"); 106 tsec_info[num].phyaddr = TSEC2_PHY_ADDR_SGMII; 107 tsec_info[num].flags = TSEC_GIGABIT; 108 } else { 109 printf("unsupported PHY type\n"); 110 } 111 num++; 112 #endif 113 return tsec_eth_init(bd, tsec_info, num); 114 } 115 116 static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias, 117 int phy_addr) 118 { 119 const char *phy_type = "sgmii"; 120 const u32 *ph; 121 int off; 122 int err; 123 124 off = fdt_path_offset(blob, alias); 125 if (off < 0) { 126 printf("WARNING: could not find %s alias: %s.\n", alias, 127 fdt_strerror(off)); 128 return; 129 } 130 131 err = fdt_setprop(blob, off, "phy-connection-type", phy_type, 132 strlen(phy_type) + 1); 133 if (err) { 134 printf("WARNING: could not set phy-connection-type for %s: " 135 "%s.\n", alias, fdt_strerror(err)); 136 return; 137 } 138 139 ph = (u32 *)fdt_getprop(blob, off, "phy-handle", 0); 140 if (!ph) { 141 printf("WARNING: could not get phy-handle for %s.\n", 142 alias); 143 return; 144 } 145 146 off = fdt_node_offset_by_phandle(blob, *ph); 147 if (off < 0) { 148 printf("WARNING: could not get phy node for %s: %s\n", alias, 149 fdt_strerror(off)); 150 return; 151 } 152 153 phy_addr = cpu_to_fdt32(phy_addr); 154 err = fdt_setprop(blob, off, "reg", &phy_addr, sizeof(phy_addr)); 155 if (err < 0) { 156 printf("WARNING: could not set phy node's reg for %s: " 157 "%s.\n", alias, fdt_strerror(err)); 158 return; 159 } 160 } 161 162 static void ft_tsec_fixup(void *blob, bd_t *bd) 163 { 164 struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; 165 u32 rcwh = in_be32(&im->reset.rcwh); 166 u32 tsec_mode; 167 168 #ifdef CONFIG_TSEC1 169 tsec_mode = rcwh & HRCWH_TSEC1M_MASK; 170 if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) 171 __ft_tsec_fixup(blob, bd, "ethernet0", TSEC1_PHY_ADDR_SGMII); 172 #endif 173 174 #ifdef CONFIG_TSEC2 175 tsec_mode = rcwh & HRCWH_TSEC2M_MASK; 176 if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) 177 __ft_tsec_fixup(blob, bd, "ethernet1", TSEC2_PHY_ADDR_SGMII); 178 #endif 179 } 180 #else 181 static inline void ft_tsec_fixup(void *blob, bd_t *bd) {} 182 #endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */ 183 184 int board_early_init_r(void) 185 { 186 #ifdef CONFIG_PQ_MDS_PIB 187 pib_init(); 188 #endif 189 return 0; 190 } 191 192 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) 193 extern void ddr_enable_ecc(unsigned int dram_size); 194 #endif 195 int fixed_sdram(void); 196 197 phys_size_t initdram(int board_type) 198 { 199 volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; 200 u32 msize = 0; 201 202 if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) 203 return -1; 204 205 #if defined(CONFIG_SPD_EEPROM) 206 msize = spd_sdram(); 207 #else 208 msize = fixed_sdram(); 209 #endif 210 211 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) 212 /* Initialize DDR ECC byte */ 213 ddr_enable_ecc(msize * 1024 * 1024); 214 #endif 215 216 /* return total bus DDR size(bytes) */ 217 return (msize * 1024 * 1024); 218 } 219 220 #if !defined(CONFIG_SPD_EEPROM) 221 /************************************************************************* 222 * fixed sdram init -- doesn't use serial presence detect. 223 ************************************************************************/ 224 int fixed_sdram(void) 225 { 226 volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; 227 u32 msize = CONFIG_SYS_DDR_SIZE * 1024 * 1024; 228 u32 msize_log2 = __ilog2(msize); 229 230 im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000; 231 im->sysconf.ddrlaw[0].ar = LBLAWAR_EN | (msize_log2 - 1); 232 233 #if (CONFIG_SYS_DDR_SIZE != 512) 234 #warning Currenly any ddr size other than 512 is not supported 235 #endif 236 im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE; 237 udelay(50000); 238 239 im->ddr.sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL; 240 udelay(1000); 241 242 im->ddr.csbnds[0].csbnds = CONFIG_SYS_DDR_CS0_BNDS; 243 im->ddr.cs_config[0] = CONFIG_SYS_DDR_CS0_CONFIG; 244 udelay(1000); 245 246 im->ddr.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0; 247 im->ddr.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1; 248 im->ddr.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2; 249 im->ddr.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3; 250 im->ddr.sdram_cfg = CONFIG_SYS_DDR_SDRAM_CFG; 251 im->ddr.sdram_cfg2 = CONFIG_SYS_DDR_SDRAM_CFG2; 252 im->ddr.sdram_mode = CONFIG_SYS_DDR_MODE; 253 im->ddr.sdram_mode2 = CONFIG_SYS_DDR_MODE2; 254 im->ddr.sdram_interval = CONFIG_SYS_DDR_INTERVAL; 255 __asm__ __volatile__("sync"); 256 udelay(1000); 257 258 im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; 259 udelay(2000); 260 return CONFIG_SYS_DDR_SIZE; 261 } 262 #endif /*!CONFIG_SYS_SPD_EEPROM */ 263 264 int checkboard(void) 265 { 266 puts("Board: Freescale MPC837xEMDS\n"); 267 return 0; 268 } 269 270 #ifdef CONFIG_PCI 271 int board_pci_host_broken(void) 272 { 273 struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; 274 const u32 rcw_mask = HRCWH_PCI1_ARBITER_ENABLE | HRCWH_PCI_HOST; 275 const char *pci_ea = getenv("pci_external_arbiter"); 276 277 /* It's always OK in case of external arbiter. */ 278 if (pci_ea && !strcmp(pci_ea, "yes")) 279 return 0; 280 281 if ((in_be32(&im->reset.rcwh) & rcw_mask) != rcw_mask) 282 return 1; 283 284 return 0; 285 } 286 287 static void ft_pci_fixup(void *blob, bd_t *bd) 288 { 289 const char *status = "broken (no arbiter)"; 290 int off; 291 int err; 292 293 off = fdt_path_offset(blob, "pci0"); 294 if (off < 0) { 295 printf("WARNING: could not find pci0 alias: %s.\n", 296 fdt_strerror(off)); 297 return; 298 } 299 300 err = fdt_setprop(blob, off, "status", status, strlen(status) + 1); 301 if (err) { 302 printf("WARNING: could not set status for pci0: %s.\n", 303 fdt_strerror(err)); 304 return; 305 } 306 } 307 #endif 308 309 #if defined(CONFIG_OF_BOARD_SETUP) 310 void ft_board_setup(void *blob, bd_t *bd) 311 { 312 ft_cpu_setup(blob, bd); 313 ft_tsec_fixup(blob, bd); 314 fdt_fixup_dr_usb(blob, bd); 315 #ifdef CONFIG_PCI 316 ft_pci_setup(blob, bd); 317 if (board_pci_host_broken()) 318 ft_pci_fixup(blob, bd); 319 #endif 320 } 321 #endif /* CONFIG_OF_BOARD_SETUP */ 322