uboot/board/cm5200/cm5200.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003-2007
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2004
   6 * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
   7 *
   8 * (C) Copyright 2004-2005
   9 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
  10 *
  11 * Adapted to U-Boot 1.2 by:
  12 *   Bartlomiej Sieka <tur@semihalf.com>:
  13 *      - HW ID readout from EEPROM
  14 *      - module detection
  15 *   Grzegorz Bernacki <gjb@semihalf.com>:
  16 *      - run-time SDRAM controller configuration
  17 *      - LIBFDT support
  18 *
  19 * See file CREDITS for list of people who contributed to this
  20 * project.
  21 *
  22 * This program is free software; you can redistribute it and/or
  23 * modify it under the terms of the GNU General Public License as
  24 * published by the Free Software Foundation; either version 2 of
  25 * the License, or (at your option) any later version.
  26 *
  27 * This program is distributed in the hope that it will be useful,
  28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30 * GNU General Public License for more details.
  31 *
  32 * You should have received a copy of the GNU General Public License
  33 * along with this program; if not, write to the Free Software
  34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  35 * MA 02111-1307 USA
  36 */
  37
  38#include <common.h>
  39#include <mpc5xxx.h>
  40#include <pci.h>
  41#include <asm/processor.h>
  42#include <i2c.h>
  43#include <linux/ctype.h>
  44
  45#ifdef CONFIG_OF_LIBFDT
  46#include <libfdt.h>
  47#include <libfdt_env.h>
  48#include <fdt_support.h>
  49#endif /* CONFIG_OF_LIBFDT */
  50
  51
  52#include "cm5200.h"
  53#include "fwupdate.h"
  54
  55DECLARE_GLOBAL_DATA_PTR;
  56
  57static hw_id_t hw_id;
  58
  59
  60#ifndef CONFIG_SYS_RAMBOOT
  61/*
  62 * Helper function to initialize SDRAM controller.
  63 */
  64static void sdram_start(int hi_addr, mem_conf_t *mem_conf)
  65{
  66        long hi_addr_bit = hi_addr ? 0x01000000 : 0;
  67
  68        /* unlock mode register */
  69        *(vu_long *)MPC5XXX_SDRAM_CTRL = mem_conf->control | 0x80000000 |
  70                                                hi_addr_bit;
  71
  72        /* precharge all banks */
  73        *(vu_long *)MPC5XXX_SDRAM_CTRL = mem_conf->control | 0x80000002 |
  74                                                hi_addr_bit;
  75
  76        /* auto refresh */
  77        *(vu_long *)MPC5XXX_SDRAM_CTRL = mem_conf->control | 0x80000004 |
  78                                                hi_addr_bit;
  79
  80        /* auto refresh, second time */
  81        *(vu_long *)MPC5XXX_SDRAM_CTRL = mem_conf->control | 0x80000004 |
  82                                                hi_addr_bit;
  83
  84        /* set mode register */
  85        *(vu_long *)MPC5XXX_SDRAM_MODE = mem_conf->mode;
  86
  87        /* normal operation */
  88        *(vu_long *)MPC5XXX_SDRAM_CTRL = mem_conf->control | hi_addr_bit;
  89}
  90#endif /* CONFIG_SYS_RAMBOOT */
  91
  92
  93/*
  94 * Retrieve memory configuration for a given module. board_type is the index
  95 * in hw_id_list[] corresponding to the module we are executing on; we return
  96 * SDRAM controller settings approprate for this module.
  97 */
  98static mem_conf_t* get_mem_config(int board_type)
  99{
 100        switch(board_type){
 101                case CM1_QA:
 102                        return memory_config[0];
 103                case CM11_QA:
 104                case CMU1_QA:
 105                        return memory_config[1];
 106                default:
 107                        printf("ERROR: Unknown module, using a default SDRAM "
 108                                "configuration - things may not work!!!.\n");
 109                        return memory_config[0];
 110        }
 111}
 112
 113
 114/*
 115 * Initalize SDRAM - configure SDRAM controller, detect memory size.
 116 */
 117phys_size_t initdram(int board_type)
 118{
 119        ulong dramsize = 0;
 120#ifndef CONFIG_SYS_RAMBOOT
 121        ulong test1, test2;
 122        mem_conf_t *mem_conf;
 123
 124        mem_conf = get_mem_config(board_type);
 125
 126        /* configure SDRAM start/end for detection */
 127        *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e; /* 2G at 0x0 */
 128
 129        /* setup config registers */
 130        *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = mem_conf->config1;
 131        *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = mem_conf->config2;
 132
 133        sdram_start(0, mem_conf);
 134        test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
 135        sdram_start(1, mem_conf);
 136        test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
 137        if (test1 > test2) {
 138                sdram_start(0, mem_conf);
 139                dramsize = test1;
 140        } else
 141                dramsize = test2;
 142
 143        /* memory smaller than 1MB is impossible */
 144        if (dramsize < (1 << 20))
 145                dramsize = 0;
 146
 147        /* set SDRAM CS0 size according to the amount of RAM found */
 148        if (dramsize > 0) {
 149                *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 +
 150                        __builtin_ffs(dramsize >> 20) - 1;
 151        } else
 152                *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
 153#else /* CONFIG_SYS_RAMBOOT */
 154        /* retrieve size of memory connected to SDRAM CS0 */
 155        dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF;
 156        if (dramsize >= 0x13)
 157                dramsize = (1 << (dramsize - 0x13)) << 20;
 158        else
 159                dramsize = 0;
 160#endif /* !CONFIG_SYS_RAMBOOT */
 161
 162        /*
 163         * On MPC5200B we need to set the special configuration delay in the
 164         * DDR controller.  Refer to chapter 8.7.5 SDelay--MBAR + 0x0190 of
 165         * the MPC5200B User's Manual.
 166         */
 167        *(vu_long *)MPC5XXX_SDRAM_SDELAY = 0x04;
 168        __asm__ volatile ("sync");
 169
 170        return dramsize;
 171}
 172
 173
 174/*
 175 * Read module hardware identification data from the I2C EEPROM.
 176 */
 177static void read_hw_id(hw_id_t hw_id)
 178{
 179        int i;
 180        for (i = 0; i < HW_ID_ELEM_COUNT; ++i)
 181                if (i2c_read(CONFIG_SYS_I2C_EEPROM,
 182                                hw_id_format[i].offset,
 183                                2,
 184                                (uchar *)&hw_id[i][0],
 185                                hw_id_format[i].length) != 0)
 186                        printf("ERROR: can't read HW ID from EEPROM\n");
 187}
 188
 189
 190/*
 191 * Identify module we are running on, set gd->board_type to the index in
 192 * hw_id_list[] corresponding to the module identifed, or to
 193 * CM5200_UNKNOWN_MODULE if we can't identify the module.
 194 */
 195static void identify_module(hw_id_t hw_id)
 196{
 197        int i, j, element;
 198        char match;
 199        gd->board_type = CM5200_UNKNOWN_MODULE;
 200        for (i = 0; i < sizeof (hw_id_list) / sizeof (char **); ++i) {
 201                match = 1;
 202                for (j = 0; j < sizeof (hw_id_identify) / sizeof (int); ++j) {
 203                        element = hw_id_identify[j];
 204                        if (strncmp(hw_id_list[i][element],
 205                                        &hw_id[element][0],
 206                                        hw_id_format[element].length) != 0) {
 207                                match = 0;
 208                                break;
 209                        }
 210                }
 211                if (match) {
 212                        gd->board_type = i;
 213                        break;
 214                }
 215        }
 216}
 217
 218
 219/*
 220 * Compose string with module name.
 221 * buf is assumed to have enough space, and be null-terminated.
 222 */
 223static void compose_module_name(hw_id_t hw_id, char *buf)
 224{
 225        char tmp[MODULE_NAME_MAXLEN];
 226        strncat(buf, &hw_id[PCB_NAME][0], hw_id_format[PCB_NAME].length);
 227        strncat(buf, ".", 1);
 228        strncat(buf, &hw_id[FORM][0], hw_id_format[FORM].length);
 229        strncat(buf, &hw_id[VERSION][0], hw_id_format[VERSION].length);
 230        strncat(buf, " (", 2);
 231        strncat(buf, &hw_id[IDENTIFICATION_NUMBER][0],
 232                hw_id_format[IDENTIFICATION_NUMBER].length);
 233        sprintf(tmp, " / %u.%u)",
 234                hw_id[MAJOR_SW_VERSION][0],
 235                hw_id[MINOR_SW_VERSION][0]);
 236        strcat(buf, tmp);
 237}
 238
 239
 240/*
 241 * Compose string with hostname.
 242 * buf is assumed to have enough space, and be null-terminated.
 243 */
 244static void compose_hostname(hw_id_t hw_id, char *buf)
 245{
 246        char *p;
 247        strncat(buf, &hw_id[PCB_NAME][0], hw_id_format[PCB_NAME].length);
 248        strncat(buf, "_", 1);
 249        strncat(buf, &hw_id[FORM][0], hw_id_format[FORM].length);
 250        strncat(buf, &hw_id[VERSION][0], hw_id_format[VERSION].length);
 251        for (p = buf; *p; ++p)
 252                *p = tolower(*p);
 253
 254}
 255
 256
 257#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
 258/*
 259 * Update 'model' and 'memory' properties in the blob according to the module
 260 * that we are running on.
 261 */
 262static void ft_blob_update(void *blob, bd_t *bd)
 263{
 264        int len, ret, nodeoffset = 0;
 265        char module_name[MODULE_NAME_MAXLEN] = {0};
 266
 267        compose_module_name(hw_id, module_name);
 268        len = strlen(module_name) + 1;
 269
 270        ret = fdt_setprop(blob, nodeoffset, "model", module_name, len);
 271        if (ret < 0)
 272        printf("ft_blob_update(): cannot set /model property err:%s\n",
 273                fdt_strerror(ret));
 274}
 275#endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
 276
 277
 278/*
 279 * Read HW ID from I2C EEPROM and detect the modue we are running on. Note
 280 * that we need to use local variable for readout, because global data is not
 281 * writable yet (and we'll have to redo the readout later on).
 282 */
 283int checkboard(void)
 284{
 285        hw_id_t hw_id_tmp;
 286        char module_name_tmp[MODULE_NAME_MAXLEN] = "";
 287
 288        /*
 289         * We need I2C to access HW ID data from EEPROM, so we call i2c_init()
 290         * here despite the fact that it will be called again later on. We
 291         * also use a little trick to silence I2C-related output.
 292         */
 293        gd->flags |= GD_FLG_SILENT;
 294        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 295        gd->flags &= ~GD_FLG_SILENT;
 296
 297        read_hw_id(hw_id_tmp);
 298        identify_module(hw_id_tmp);     /* this sets gd->board_type */
 299        compose_module_name(hw_id_tmp, module_name_tmp);
 300
 301        if (gd->board_type != CM5200_UNKNOWN_MODULE)
 302                printf("Board: %s\n", module_name_tmp);
 303        else
 304                printf("Board: unrecognized cm5200 module (%s)\n",
 305                        module_name_tmp);
 306
 307        return 0;
 308}
 309
 310
 311int board_early_init_r(void)
 312{
 313        /*
 314         * Now, when we are in RAM, enable flash write access for detection
 315         * process. Note that CS_BOOT cannot be cleared when executing in
 316         * flash.
 317         */
 318        *(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */
 319
 320        /* Now that we can write to global data, read HW ID again. */
 321        read_hw_id(hw_id);
 322        return 0;
 323}
 324
 325
 326#ifdef CONFIG_MISC_INIT_R
 327int misc_init_r(void)
 328{
 329#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
 330        uchar buf[6];
 331        char str[18];
 332        char hostname[MODULE_NAME_MAXLEN];
 333
 334        /* Read ethaddr from EEPROM */
 335        if (i2c_read(CONFIG_SYS_I2C_EEPROM, CONFIG_MAC_OFFSET, 2, buf, 6) == 0) {
 336                sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X",
 337                        buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
 338                /* Check if MAC addr is owned by Schindler */
 339                if (strstr(str, "00:06:C3") != str)
 340                        printf(LOG_PREFIX "Warning - Illegal MAC address (%s)"
 341                                " in EEPROM.\n", str);
 342                else {
 343                        printf(LOG_PREFIX "Using MAC (%s) from I2C EEPROM\n",
 344                                str);
 345                        setenv("ethaddr", str);
 346                }
 347        } else {
 348                printf(LOG_PREFIX "Warning - Unable to read MAC from I2C"
 349                        " device at address %02X:%04X\n", CONFIG_SYS_I2C_EEPROM,
 350                        CONFIG_MAC_OFFSET);
 351        }
 352#endif /* defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) */
 353        if (!getenv("ethaddr"))
 354                printf(LOG_PREFIX "MAC address not set, networking is not "
 355                                        "operational\n");
 356
 357        /* set the hostname appropriate to the module we're running on */
 358        hostname[0] = 0x00;
 359        compose_hostname(hw_id, hostname);
 360        setenv("hostname", hostname);
 361
 362        return 0;
 363}
 364#endif /* CONFIG_MISC_INIT_R */
 365
 366
 367#ifdef CONFIG_LAST_STAGE_INIT
 368int last_stage_init(void)
 369{
 370#ifdef CONFIG_USB_STORAGE
 371        cm5200_fwupdate();
 372#endif /* CONFIG_USB_STORAGE */
 373        return 0;
 374}
 375#endif /* CONFIG_LAST_STAGE_INIT */
 376
 377
 378#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 379void ft_board_setup(void *blob, bd_t *bd)
 380{
 381        ft_cpu_setup(blob, bd);
 382        ft_blob_update(blob, bd);
 383}
 384#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
 385