uboot/board/freescale/mpc837xemds/mpc837xemds.c
<<
>>
Prefs
   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
  29int 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
  68int 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)
  89int 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
 145static 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
 190static 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
 209static inline void ft_tsec_fixup(void *blob, bd_t *bd) {}
 210#endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */
 211
 212int 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)
 221extern void ddr_enable_ecc(unsigned int dram_size);
 222#endif
 223int fixed_sdram(void);
 224
 225phys_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 ************************************************************************/
 252int 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
 292int checkboard(void)
 293{
 294        puts("Board: Freescale MPC837xEMDS\n");
 295        return 0;
 296}
 297
 298#ifdef CONFIG_PCI
 299int 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
 314static 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)
 337void 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