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