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