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