linux/arch/powerpc/boot/treeboot-akebono.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright © 2013 Tony Breeds IBM Corporation
   4 * Copyright © 2013 Alistair Popple IBM Corporation
   5 *
   6 * Based on earlier code:
   7 *   Copyright (C) Paul Mackerras 1997.
   8 *
   9 *   Matt Porter <mporter@kernel.crashing.org>
  10 *   Copyright 2002-2005 MontaVista Software Inc.
  11 *
  12 *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  13 *   Copyright (c) 2003, 2004 Zultys Technologies
  14 *
  15 *    Copyright 2007 David Gibson, IBM Corporation.
  16 *    Copyright 2010 Ben. Herrenschmidt, IBM Corporation.
  17 *    Copyright © 2011 David Kleikamp IBM Corporation
  18 */
  19#include <stdarg.h>
  20#include <stddef.h>
  21#include "types.h"
  22#include "elf.h"
  23#include "string.h"
  24#include "stdlib.h"
  25#include "stdio.h"
  26#include "page.h"
  27#include "ops.h"
  28#include "reg.h"
  29#include "io.h"
  30#include "dcr.h"
  31#include "4xx.h"
  32#include "44x.h"
  33#include "libfdt.h"
  34
  35BSS_STACK(4096);
  36
  37#define SPRN_PIR        0x11E   /* Processor Identification Register */
  38#define USERDATA_LEN    256     /* Length of userdata passed in by PIBS */
  39#define MAX_RANKS       0x4
  40#define DDR3_MR0CF      0x80010011U
  41#define CCTL0_MCO2      0x8000080FU
  42#define CCTL0_MCO3      0x80000810U
  43#define CCTL0_MCO4      0x80000811U
  44#define CCTL0_MCO5      0x80000812U
  45#define CCTL0_MCO6      0x80000813U
  46
  47static unsigned long long ibm_akebono_memsize;
  48static long long unsigned mac_addr;
  49
  50static unsigned long long ibm_akebono_detect_memsize(void)
  51{
  52        u32 reg;
  53        unsigned i;
  54        unsigned long long memsize = 0;
  55
  56        for (i = 0; i < MAX_RANKS; i++) {
  57                reg = mfdcrx(DDR3_MR0CF + i);
  58
  59                if (!(reg & 1))
  60                        continue;
  61
  62                reg &= 0x0000f000;
  63                reg >>= 12;
  64                memsize += (0x800000ULL << reg);
  65        }
  66
  67        return memsize;
  68}
  69
  70static void ibm_akebono_fixups(void)
  71{
  72        void *emac;
  73        u32 reg;
  74
  75        dt_fixup_memory(0x0ULL,  ibm_akebono_memsize);
  76
  77        /* Fixup the SD timeout frequency */
  78        mtdcrx(CCTL0_MCO4, 0x1);
  79
  80        /* Disable SD high-speed mode (which seems to be broken) */
  81        reg = mfdcrx(CCTL0_MCO2) & ~0x2;
  82        mtdcrx(CCTL0_MCO2, reg);
  83
  84        /* Set the MAC address */
  85        emac = finddevice("/plb/opb/ethernet");
  86        if (emac > 0) {
  87                if (mac_addr)
  88                        setprop(emac, "local-mac-address",
  89                                ((u8 *) &mac_addr) + 2 , 6);
  90        }
  91}
  92
  93void platform_init(char *userdata)
  94{
  95        unsigned long end_of_ram, avail_ram;
  96        u32 pir_reg;
  97        int node, size;
  98        const u32 *timebase;
  99        int len, i, userdata_len;
 100        char *end;
 101
 102        userdata[USERDATA_LEN - 1] = '\0';
 103        userdata_len = strlen(userdata);
 104        for (i = 0; i < userdata_len - 15; i++) {
 105                if (strncmp(&userdata[i], "local-mac-addr=", 15) == 0) {
 106                        if (i > 0 && userdata[i - 1] != ' ') {
 107                                /* We've only found a substring ending
 108                                 * with local-mac-addr so this isn't
 109                                 * our mac address. */
 110                                continue;
 111                        }
 112
 113                        mac_addr = strtoull(&userdata[i + 15], &end, 16);
 114
 115                        /* Remove the "local-mac-addr=<...>" from the kernel
 116                         * command line, including the tailing space if
 117                         * present. */
 118                        if (*end == ' ')
 119                                end++;
 120
 121                        len = ((int) end) - ((int) &userdata[i]);
 122                        memmove(&userdata[i], end,
 123                                userdata_len - (len + i) + 1);
 124                        break;
 125                }
 126        }
 127
 128        loader_info.cmdline = userdata;
 129        loader_info.cmdline_len = 256;
 130
 131        ibm_akebono_memsize = ibm_akebono_detect_memsize();
 132        if (ibm_akebono_memsize >> 32)
 133                end_of_ram = ~0UL;
 134        else
 135                end_of_ram = ibm_akebono_memsize;
 136        avail_ram = end_of_ram - (unsigned long)_end;
 137
 138        simple_alloc_init(_end, avail_ram, 128, 64);
 139        platform_ops.fixups = ibm_akebono_fixups;
 140        platform_ops.exit = ibm44x_dbcr_reset;
 141        pir_reg = mfspr(SPRN_PIR);
 142
 143        /* Make sure FDT blob is sane */
 144        if (fdt_check_header(_dtb_start) != 0)
 145                fatal("Invalid device tree blob\n");
 146
 147        node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
 148                                             "cpu", sizeof("cpu"));
 149        if (!node)
 150                fatal("Cannot find cpu node\n");
 151        timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
 152        if (timebase && (size == 4))
 153                timebase_period_ns = 1000000000 / *timebase;
 154
 155        fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
 156        fdt_init(_dtb_start);
 157
 158        serial_console_init();
 159}
 160