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