uboot/board/freescale/mpc837xemds/mpc837xemds.c
<<
>>
Prefs
   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_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
  26int 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
  65int 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)
  86int 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
 136static 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
 182static 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
 201static inline void ft_tsec_fixup(void *blob, bd_t *bd) {}
 202#endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */
 203
 204int 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)
 213extern void ddr_enable_ecc(unsigned int dram_size);
 214#endif
 215int fixed_sdram(void);
 216
 217phys_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 ************************************************************************/
 244int 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
 284int checkboard(void)
 285{
 286        puts("Board: Freescale MPC837xEMDS\n");
 287        return 0;
 288}
 289
 290#ifdef CONFIG_PCI
 291int 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
 306static 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)
 329void 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