1/*
2 * Copyright 2002 Momentum Computer Inc.
3 * Author: Matthew Dharm <mdharm@momenco.com>
4 *
5 * Based on Ocelot Linux port, which is
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: jsun@mvista.com or jsun@junsun.net
8 *
9 * This program is free software; you can redistribute  it and/or modify it
10 * under  the terms of  the GNU General  Public License as published by the
11 * Free Software Foundation;  either version 2 of the  License, or (at your
12 * option) any later version.
13 */
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/mm.h>
17#include <linux/sched.h>
18#include <linux/bootmem.h>
19
20#include <asm/addrspace.h>
21#include <asm/bootinfo.h>
22#include <asm/mv64340.h>
23
24#include "ocelot_c_fpga.h"
25
26struct callvectors {
27	int	(*open) (char*, int, int);
28	int	(*close) (int);
29	int	(*read) (int, void*, int);
30	int	(*write) (int, void*, int);
31	off_t	(*lseek) (int, off_t, int);
32	int	(*printf) (const char*, ...);
33	void	(*cacheflush) (void);
34	char*	(*gets) (char*);
35};
36
37struct callvectors* debug_vectors;
38char arcs_cmdline[CL_SIZE];
39
40extern unsigned long mv64340_base;
41extern unsigned long cpu_clock;
42
43#ifdef CONFIG_MV64340_ETH
44extern unsigned char prom_mac_addr_base[6];
45#endif
46
47const char *get_system_type(void)
48{
49#ifdef CONFIG_CPU_SR71000
50	return "Momentum Ocelot-CS";
51#else
52	return "Momentum Ocelot-C";
53#endif
54}
55
56#ifdef CONFIG_MV64340_ETH
57static void burn_clocks(void)
58{
59	int i;
60
61	/* this loop should burn at least 1us -- this should be plenty */
62	for (i = 0; i < 0x10000; i++)
63		;
64}
65
66static u8 exchange_bit(u8 val, u8 cs)
67{
68	/* place the data */
69	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
70	burn_clocks();
71
72	/* turn the clock on */
73	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
74	burn_clocks();
75
76	/* turn the clock off and read-strobe */
77	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
78
79	/* return the data */
80	return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
81}
82
83void get_mac(char dest[6])
84{
85	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
86	int i,j;
87
88	for (i = 0; i < 12; i++)
89		exchange_bit(read_opcode[i], 1);
90
91	for (j = 0; j < 6; j++) {
92		dest[j] = 0;
93		for (i = 0; i < 8; i++) {
94			dest[j] <<= 1;
95			dest[j] |= exchange_bit(0, 1);
96		}
97	}
98
99	/* turn off CS */
100	exchange_bit(0,0);
101}
102#endif
103
104/* [jsun@junsun.net] PMON passes arguments in C main() style */
105void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv)
106{
107	int i;
108
109	/* save the PROM vectors for debugging use */
110	debug_vectors = cv;
111
112	/* arg[0] is "g", the rest is boot parameters */
113	arcs_cmdline[0] = '\0';
114	for (i = 1; i < argc; i++) {
115		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
116		    >= sizeof(arcs_cmdline))
117			break;
118		strcat(arcs_cmdline, arg[i]);
119		strcat(arcs_cmdline, " ");
120	}
121
122	mips_machgroup = MACH_GROUP_MOMENCO;
123	mips_machtype = MACH_MOMENCO_OCELOT_C;
124
125	while (*env) {
126		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
127			mv64340_base = simple_strtol(*env + strlen("gtbase="),
128							NULL, 16);
129		}
130		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
131			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
132							NULL, 10);
133		}
134		env++;
135	}
136
137#ifdef CONFIG_MV64340_ETH
138	/* get the base MAC address for on-board ethernet ports */
139	get_mac(prom_mac_addr_base);
140#endif
141
142	debug_vectors->printf("Booting Linux kernel...\n");
143}
144
145void __init prom_free_prom_memory(void)
146{
147}
148
149void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
150{
151}
152