d19714c85baaec181519e57189b97efed44eb960
[openwrt.git] / target / linux / ar7-2.6 / files / arch / mips / ar7 / prom.c
1 /*
2  * $Id$
3  * 
4  * Copyright (C) 2006, 2007 OpenWrt.org
5  * 
6  * Carsten Langgaard, carstenl@mips.com
7  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
8  *
9  *  This program is free software; you can distribute it and/or modify it
10  *  under the terms of the GNU General Public License (Version 2) as
11  *  published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope it will be useful, but WITHOUT
14  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  *  for more details.
17  *
18  *  You should have received a copy of the GNU General Public License along
19  *  with this program; if not, write to the Free Software Foundation, Inc.,
20  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
21  *
22  * Putting things on the screen/serial line using YAMONs facilities.
23  */
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/serial_reg.h>
27 #include <linux/spinlock.h>
28 #include <linux/module.h>
29 #include <asm/io.h>
30 #include <asm/bootinfo.h>
31 #include <asm/mips-boards/prom.h>
32
33 #include <asm/ar7/ar7.h>
34
35 #define MAX_ENTRY 80
36
37 struct env_var {
38         char *name;
39         char *value;
40 };
41
42 struct psp_chip_map {
43         u16 chip;
44         char *names[50];
45 };
46
47 /* I hate this. No. *I* *HATE* *THIS* */
48 static __initdata struct psp_chip_map psp_chip_map[] = {
49         {
50                 .chip = AR7_CHIP_7100,
51                 .names = {
52                         "dummy", "cpufrequency", "memsize",
53                         "flashsize", "modetty0", "modetty1", "prompt",
54                         "bootcfg", "maca", "macb", "usb_rndis_mac",
55                         "macap", "my_ipaddress", "server_ipaddress",
56                         "bline_maca", "bline_macb", "bline_rndis",
57                         "bline_atm", "usb_pid", "usb_vid",
58                         "usb_eppolli", "gateway_ipaddress",
59                         "subnet_mask", "usb_serial", "usb_board_mac",
60                         "remote_user", "remote_pass", "remote_dir",
61                         "sysfrequency", "link_timeout", "mac_port",
62                         "path", "hostname", "tftpcfg", "buildops",
63                         "tftp_fo_fname", "tftp_fo_ports",
64                         "console_state", "mipsfrequency", 
65                 },
66         },
67         {
68                 .chip = AR7_CHIP_7200,
69                 .names = {
70                         "dummy", "cpufrequency", "memsize",
71                         "flashsize", "modetty0", "modetty1", "prompt",
72                         "bootcfg", "maca", "macb", "usb_rndis_mac",
73                         "macap", "my_ipaddress", "server_ipaddress",
74                         "bline_maca", "bline_macb", "bline_rndis",
75                         "bline_atm", "usb_pid", "usb_vid",
76                         "usb_eppolli", "gateway_ipaddress",
77                         "subnet_mask", "usb_serial", "usb_board_mac",
78                         "remote_user", "remote_pass", "remote_dir",
79                         "sysfrequency", "link_timeout", "mac_port",
80                         "path", "hostname", "tftpcfg", "buildops",
81                         "tftp_fo_fname", "tftp_fo_ports",
82                         "console_state", "mipsfrequency", 
83                 },
84         },
85         {
86                 .chip = AR7_CHIP_7300,
87                 .names = {
88                         "dummy", "cpufrequency", "memsize",
89                         "flashsize", "modetty0", "modetty1", "prompt",
90                         "bootcfg", "maca", "macb", "usb_rndis_mac",
91                         "macap", "my_ipaddress", "server_ipaddress",
92                         "bline_maca", "bline_macb", "bline_rndis",
93                         "bline_atm", "usb_pid", "usb_vid",
94                         "usb_eppolli", "gateway_ipaddress",
95                         "subnet_mask", "usb_serial", "usb_board_mac",
96                         "remote_user", "remote_pass", "remote_dir",
97                         "sysfrequency", "link_timeout", "mac_port",
98                         "path", "hostname", "tftpcfg", "buildops",
99                         "tftp_fo_fname", "tftp_fo_ports",
100                         "console_state", "mipsfrequency", 
101                 },
102         },
103         {
104                 .chip = 0x0,
105         },
106 };
107
108 static struct env_var adam2_env[MAX_ENTRY] = { { 0, }, };
109
110 char * prom_getenv(char *name)
111 {
112         int i;
113         for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
114                 if (!strcmp(name, adam2_env[i].name))
115                         return adam2_env[i].value;
116
117         return NULL;
118 }
119
120 char * __init prom_getcmdline(void)
121 {
122         return &(arcs_cmdline[0]);
123 }
124
125 static void  __init ar7_init_cmdline(int argc, char *argv[])
126 {
127         char *cp;
128         int actr;
129
130         actr = 1; /* Always ignore argv[0] */
131
132         cp = &(arcs_cmdline[0]);
133         while(actr < argc) {
134                 strcpy(cp, argv[actr]);
135                 cp += strlen(argv[actr]);
136                 *cp++ = ' ';
137                 actr++;
138         }
139         if (cp != &(arcs_cmdline[0])) {
140                 /* get rid of trailing space */
141                 --cp;
142                 *cp = '\0';
143         }
144 }
145
146 struct psbl_rec {
147         u32 psbl_size;
148         u32 env_base;
149         u32 env_size;
150         u32 ffs_base;
151         u32 ffs_size;
152 };
153
154 static __initdata char psp_env_version[] = "TIENV0.8";
155
156 struct psp_env_var {
157         unsigned char num;
158         unsigned char ctrl;
159         unsigned short csum;
160         unsigned char len;
161         unsigned char data[11];
162 };
163
164 static char psp_env_data[2048] = { 0, };
165
166 static void __init add_adam2_var(char *name, char *value)
167 {
168         int i;
169         for (i = 0; i < MAX_ENTRY; i++) {
170                 if (!adam2_env[i].name) {
171                         adam2_env[i].name = name;
172                         adam2_env[i].value = value;
173                         return;
174                 } else if (!strcmp(adam2_env[i].name, name)) {
175                         adam2_env[i].value = value;
176                         return;
177                 }
178         }
179 }
180
181 static int __init parse_psp_env(void *start)
182 {
183         int i, j;
184         u16 chip;
185         struct psp_chip_map *map;
186         char *src, *dest, *name, *value;
187         struct psp_env_var *vars = start;
188
189         chip = ar7_chip_id();
190         for (map = psp_chip_map; map->chip; map++)
191                 if (map->chip == chip)
192                         break;
193
194         if (!map->chip)
195                 return -EINVAL;
196
197         i = 1;
198         j = 0;
199         dest = psp_env_data;
200         while (vars[i].num < 0xff) {
201                 src = vars[i].data;
202                 if (vars[i].num) {
203                         strcpy(dest, map->names[vars[i].num]);
204                         name = dest;
205                 } else {
206                         strcpy(dest, src);
207                         name = dest;
208                         src += strlen(src) + 1;
209                 }                       
210                 dest += strlen(dest) + 1;
211                 strcpy(dest, src);
212                 value = dest;
213                 dest += strlen(dest) + 1;
214                 add_adam2_var(name, value);
215                 i += vars[i].len;
216         }
217         return 0;
218 }
219
220 static void __init ar7_init_env(struct env_var *env)
221 {
222         int i;
223         struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
224         void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
225
226         if(strcmp(psp_env, psp_env_version) == 0) {
227                 parse_psp_env(psp_env);
228         } else {
229                 for (i = 0; i < MAX_ENTRY; i++, env++)
230                         if (env->name)
231                                 add_adam2_var(env->name, env->value);
232         }
233 }
234
235 void __init prom_init(void)
236 {
237         prom_printf("\nLINUX running...\n");
238         ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
239         ar7_init_env((struct env_var *)fw_arg2);
240 }
241
242 #define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
243 static inline unsigned int serial_in(int offset)
244 {
245         return readb((void *)PORT(offset));
246 }
247
248 static inline void serial_out(int offset, int value)
249 {
250         writeb(value, (void *)PORT(offset));
251 }
252
253 char prom_getchar(void)
254 {
255         while (!(serial_in(UART_LSR) & UART_LSR_DR));
256         return serial_in(UART_RX);
257 }
258
259 int prom_putchar(char c)
260 {
261         while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0);
262         serial_out(UART_TX, c);
263         return 1;
264 }
265
266 EXPORT_SYMBOL(prom_getenv);