aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/boot/simple/openbios.c
blob: 81f11d8b30a7ad80a426e348dc86715311bd70f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * arch/ppc/boot/simple/openbios.c
 *
 * Copyright (c) 2005 DENX Software Engineering
 * Stefan Roese <sr@denx.de>
 *
 * Based on original work by
 *      2005 (c) SYSGO AG - g.jaeger@sysgo.com
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without
 * any warranty of any kind, whether express or implied.
 *
 */

#include <linux/types.h>
#include <linux/config.h>
#include <linux/string.h>
#include <asm/ppcboot.h>
#include <asm/ibm4xx.h>
#include <asm/reg.h>
#ifdef CONFIG_40x
#include <asm/io.h>
#endif

#if defined(CONFIG_BUBINGA)
#define BOARD_INFO_VECTOR       0xFFF80B50 /* openbios 1.19 moved this vector down  - armin */
#else
#define BOARD_INFO_VECTOR	0xFFFE0B50
#endif

#ifdef CONFIG_40x
/* Supply a default Ethernet address for those eval boards that don't
 * ship with one.  This is an address from the MBX board I have, so
 * it is unlikely you will find it on your network.
 */
static	ushort	def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };

extern unsigned long timebase_period_ns;
#endif /* CONFIG_40x */

extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
				       unsigned long cksum);

/* We need to make sure that this is before the images to ensure
 * that it's in a mapped location. */
bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
bd_t *hold_residual = &hold_resid_buf;

typedef struct openbios_board_info {
        unsigned char    bi_s_version[4];       /* Version of this structure */
        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
#ifdef CONFIG_405EP
        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address */
#else /* CONFIG_405EP */
        unsigned char    bi_enetaddr[6];        /* Local Ethernet MAC address */
#endif /* CONFIG_405EP */
        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
#ifdef CONFIG_405EP
        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
#endif /* CONFIG_405EP */
} openbios_bd_t;

void *
load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
		void *ign1, void *ign2)
{
#ifdef CONFIG_40x
	openbios_bd_t *openbios_bd = NULL;
	openbios_bd_t *(*get_board_info)(void) =
		(openbios_bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);

	/*
	 * On 40x platforms we not only need the MAC-addresses, but also the
	 * clocks and memsize. Now try to get all values using the OpenBIOS
	 * "get_board_info()" callback.
	 */
	if ((openbios_bd = get_board_info()) != NULL) {
		/*
		 * Copy bd_info from OpenBIOS struct into U-Boot struct
		 * used by kernel
		 */
	        hold_residual->bi_memsize = openbios_bd->bi_memsize;
	        hold_residual->bi_intfreq = openbios_bd->bi_intfreq;
	        hold_residual->bi_busfreq = openbios_bd->bi_busfreq;
	        hold_residual->bi_pci_busfreq = openbios_bd->bi_pci_busfreq;
		memcpy(hold_residual->bi_pci_enetaddr, openbios_bd->bi_pci_enetaddr, 6);
#ifdef CONFIG_405EP
		memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr[0], 6);
		memcpy(hold_residual->bi_enet1addr, openbios_bd->bi_enetaddr[1], 6);
	        hold_residual->bi_opbfreq = openbios_bd->bi_opb_busfreq;
	        hold_residual->bi_procfreq = openbios_bd->bi_pllouta_freq;
#else /* CONFIG_405EP */
		memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr, 6);
#endif /* CONFIG_405EP */
	} else {
		/* Hmmm...better try to stuff some defaults.
		 */
		hold_residual->bi_memsize = 16 * 1024 * 1024;
		hold_residual->bi_intfreq = 200000000;
		hold_residual->bi_busfreq = 100000000;
		hold_residual->bi_pci_busfreq = 66666666;

		/*
		 * Only supply one mac-address in this fallback
		 */
		memcpy(hold_residual->bi_enetaddr, (void *)def_enet_addr, 6);
#ifdef CONFIG_405EP
	        hold_residual->bi_opbfreq = 50000000;
	        hold_residual->bi_procfreq = 200000000;
#endif /* CONFIG_405EP */
	}

	timebase_period_ns = 1000000000 / hold_residual->bi_intfreq;
#endif /* CONFIG_40x */

#ifdef CONFIG_440GP
	/* simply copy the MAC addresses */
	memcpy(hold_residual->bi_enetaddr,  (char *)OPENBIOS_MAC_BASE, 6);
	memcpy(hold_residual->bi_enet1addr, (char *)(OPENBIOS_MAC_BASE+OPENBIOS_MAC_OFFSET), 6);
#endif /* CONFIG_440GP */

	decompress_kernel(load_addr, num_words, cksum);

	return (void *)hold_residual;
}