summaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu/mpc512x/cpu.c
blob: 4ee91e16f9c689efadf5c82d7760f290a817322c (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * (C) Copyright 2007-2010 DENX Software Engineering
 * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * CPU specific code for the MPC512x family.
 *
 * Derived from the MPC83xx code.
 */

#include <common.h>
#include <command.h>
#include <net.h>
#include <netdev.h>
#include <asm/processor.h>
#include <asm/io.h>

#if defined(CONFIG_OF_LIBFDT)
#include <fdt_support.h>
#endif

DECLARE_GLOBAL_DATA_PTR;

int checkcpu (void)
{
	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
	ulong clock = gd->cpu_clk;
	u32 pvr = get_pvr ();
	u32 spridr = in_be32(&immr->sysconf.spridr);
	char buf1[32], buf2[32];

	puts ("CPU:   ");

	switch (spridr & 0xffff0000) {
	case SPR_5121E:
		puts ("MPC5121e ");
		break;
	default:
		printf ("Unknown part ID %08x ", spridr & 0xffff0000);
	}
	printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));

	switch (pvr & 0xffff0000) {
	case PVR_E300C4:
		puts ("e300c4 ");
		break;
	default:
		puts ("unknown ");
	}
	printf ("at %s MHz, CSB at %s MHz (RSR=0x%04lx)\n",
		strmhz(buf1, clock),
		strmhz(buf2, gd->arch.csb_clk),
		gd->arch.reset_status & 0xffff);
	return 0;
}


int
do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	ulong msr;
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;

	/* Interrupts and MMU off */
	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);

	msr &= ~( MSR_EE | MSR_IR | MSR_DR);
	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));

	/*
	 * Enable Reset Control Reg - "RSTE" is the magic word that let us go
	 */
	out_be32(&immap->reset.rpr, 0x52535445);

	/* Verify Reset Control Reg is enabled */
	while (!(in_be32(&immap->reset.rcer) & RCER_CRE))
		;

	printf ("Resetting the board.\n");
	udelay(200);

	/* Perform reset */
	out_be32(&immap->reset.rcr, RCR_SWHR);

	/* Unreached... */
	return 1;
}


/*
 * Get timebase clock frequency (like cpu_clk in Hz)
 */
unsigned long get_tbclk (void)
{
	return (gd->bus_clk + 3L) / 4L;
}


#if defined(CONFIG_WATCHDOG)
void watchdog_reset (void)
{
	int re_enable = disable_interrupts ();

	/* Reset watchdog */
	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
	out_be32(&immr->wdt.swsrr, 0x556c);
	out_be32(&immr->wdt.swsrr, 0xaa39);

	if (re_enable)
		enable_interrupts ();
}
#endif

#ifdef CONFIG_OF_LIBFDT

#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
/*
 * fdt setup for old device trees
 * fix up
 * 	cpu clocks
 * 	soc clocks
 * 	ethernet addresses
 */
static void old_ft_cpu_setup(void *blob, bd_t *bd)
{
	/*
	 * avoid fixing up by path because that
	 * produces scary error messages
	 */
	uchar enetaddr[6];

	/*
	 * old device trees have ethernet nodes with
	 * device_type = "network"
	 */
	eth_getenv_enetaddr("ethaddr", enetaddr);
	do_fixup_by_prop(blob, "device_type", "network", 8,
		"local-mac-address", enetaddr, 6, 0);
	do_fixup_by_prop(blob, "device_type", "network", 8,
		"address", enetaddr, 6, 0);
	/*
	 * old device trees have soc nodes with
	 * device_type = "soc"
	 */
	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
		"bus-frequency", bd->bi_ipsfreq, 0);
}
#endif

static void ft_clock_setup(void *blob, bd_t *bd)
{
	char *cpu_path = "/cpus/" OF_CPU;

	/*
	 * fixup cpu clocks using path
	 */
	do_fixup_by_path_u32(blob, cpu_path,
		"timebase-frequency", OF_TBCLK, 1);
	do_fixup_by_path_u32(blob, cpu_path,
		"bus-frequency", bd->bi_busfreq, 1);
	do_fixup_by_path_u32(blob, cpu_path,
		"clock-frequency", bd->bi_intfreq, 1);
	/*
	 * fixup soc clocks using compatible
	 */
	do_fixup_by_compat_u32(blob, OF_SOC_COMPAT,
		"bus-frequency", bd->bi_ipsfreq, 1);
}

void ft_cpu_setup(void *blob, bd_t *bd)
{
#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
	old_ft_cpu_setup(blob, bd);
#endif
	ft_clock_setup(blob, bd);
#ifdef CONFIG_HAS_ETH0
	fdt_fixup_ethernet(blob);
#endif
	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
}
#endif

#ifdef CONFIG_MPC512x_FEC
/* Default initializations for FEC controllers.  To override,
 * create a board-specific function called:
 * 	int board_eth_init(bd_t *bis)
 */

int cpu_eth_init(bd_t *bis)
{
	return mpc512x_fec_initialize(bis);
}
#endif