aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/basler/excite/excite_prom.c
blob: 6ecd512b999dee1061b2f1914b5059416041591b (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
 *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
 *  Manish Lachwani.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <asm/bootinfo.h>
#include <asm/string.h>

#include <excite.h>

/* This struct is used by Redboot to pass arguments to the kernel */
typedef struct
{
	char *name;
	char *val;
} t_env_var;

struct parmblock {
	t_env_var memsize;
	t_env_var modetty0;
	t_env_var ethaddr;
	t_env_var env_end;
	char *argv[2];
	char text[0];
};

static unsigned int prom_argc;
static const char ** prom_argv;
static const t_env_var * prom_env;

static void prom_halt(void) __attribute__((noreturn));
static void prom_exit(void) __attribute__((noreturn));



const char *get_system_type(void)
{
	return "Basler eXcite";
}

/*
 * Halt the system
 */
static void prom_halt(void)
{
	printk(KERN_NOTICE "\n** System halted.\n");
	while (1)
		asm volatile (
			"\t.set\tmips3\n"
			"\twait\n"
			"\t.set\tmips0\n"
		);
}

/*
 * Reset the CPU and re-enter Redboot
 */
static void prom_exit(void)
{
	unsigned int i;
	volatile unsigned char * const flg =
		(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);

	/* Clear the watchdog reset flag, set the reboot flag */
	*flg &= ~0x01;
	*flg |= 0x80;

	for (i = 0; i < 10; i++) {
		*(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
		iob();
		mdelay(1000);
	}

	printk(KERN_NOTICE "Reset failed\n");
	prom_halt();
}

static const char __init *prom_getenv(char *name)
{
	const t_env_var * p;
	for (p = prom_env; p->name != NULL; p++)
		if(strcmp(name, p->name) == 0)
			break;
	return p->val;
}

/*
 * Init routine which accepts the variables from Redboot
 */
void __init prom_init(void)
{
	const struct parmblock * const pb = (struct parmblock *) fw_arg2;

	prom_argc = fw_arg0;
	prom_argv = (const char **) fw_arg1;
	prom_env = &pb->memsize;

	/* Callbacks for halt, restart */
	_machine_restart = (void (*)(char *)) prom_exit;
	_machine_halt = prom_halt;

#ifdef CONFIG_32BIT
	/* copy command line */
	strcpy(arcs_cmdline, prom_argv[1]);
	memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
	strcpy(modetty, prom_getenv("modetty0"));
#endif /* CONFIG_32BIT */

#ifdef CONFIG_64BIT
#	error 64 bit support not implemented
#endif /* CONFIG_64BIT */

	mips_machgroup = MACH_GROUP_TITAN;
	mips_machtype = MACH_TITAN_EXCITE;
}

/* This is called from free_initmem(), so we need to provide it */
void __init prom_free_prom_memory(void)
{
	/* Nothing to do */
}