root/src/linux/rt2880/linux-2.6.23/arch/mips/rt2880/init.c

Revision 12433, 10.0 kB (checked in by BrainSlayer, 5 months ago)

fixes usb issues with some devices

Line 
1 /**************************************************************************
2  *
3  *  BRIEF MODULE DESCRIPTION
4  *     init setup for Ralink RT2880 solution
5  *
6  *  Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
14  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
15  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
16  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
17  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
19  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
21  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  *  You should have received a copy of the  GNU General Public License along
25  *  with this program; if not, write  to the Free Software Foundation, Inc.,
26  *  675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  *
29  **************************************************************************
30  * May 2007 Bruce Chang
31  *
32  * Initial Release
33  *
34  *
35  *
36  **************************************************************************
37  */
38
39 #include <linux/init.h>
40 #include <linux/string.h>
41 #include <linux/kernel.h>
42 #include <linux/serial.h>
43 #include <linux/serialP.h>
44 #include <linux/serial_core.h>
45 #include <asm/bootinfo.h>
46 #include <asm/io.h>
47 #include <asm/serial.h>
48 #include <asm/rt2880/prom.h>
49 #include <asm/rt2880/generic.h>
50 #include <asm/rt2880/surfboard.h>
51 #include <asm/rt2880/surfboardint.h>
52 #include <asm/rt2880/rt_mmap.h>
53 extern unsigned long surfboard_sysclk;
54 extern unsigned long mips_machgroup;
55 u32 mips_cpu_feq;
56
57 /* Environment variable */
58 typedef struct {
59         char *name;
60         char *val;
61 } t_env_var;
62
63 int prom_argc;
64 int *_prom_argv, *_prom_envp;
65
66 /* PROM version of rs_table - needed for Serial Console */
67 //struct serial_state prom_rs_table[] = {
68 //       SERIAL_PORT_DFNS        /* Defined in serial.h */
69 //};
70
71 /*
72  * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
73  * This macro take care of sign extension, if running in 64-bit mode.
74  */
75 #define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)]))
76
77 int init_debug = 0;
78
79 char *prom_getenv(char *envname)
80 {
81         /*
82          * Return a pointer to the given environment variable.
83          * In 64-bit mode: we're using 64-bit pointers, but all pointers
84          * in the PROM structures are only 32-bit, so we need some
85          * workarounds, if we are running in 64-bit mode.
86          */
87         int i, index=0;
88         // Dennis Lee +
89         return NULL;
90         //
91         i = strlen(envname);
92
93         while (prom_envp(index)) {
94                 if(strncmp(envname, prom_envp(index), i) == 0) {
95                         return(prom_envp(index+1));
96                 }
97                 index += 2;
98         }
99
100         return NULL;
101 }
102
103 static inline unsigned char str2hexnum(unsigned char c)
104 {
105         if (c >= '0' && c <= '9')
106                 return c - '0';
107         if (c >= 'a' && c <= 'f')
108                 return c - 'a' + 10;
109         return 0; /* foo */
110 }
111
112 static inline void str2eaddr(unsigned char *ea, unsigned char *str)
113 {
114         int i;
115
116         for (i = 0; i < 6; i++) {
117                 unsigned char num;
118
119                 if((*str == '.') || (*str == ':'))
120                         str++;
121                 num = str2hexnum(*str++) << 4;
122                 num |= (str2hexnum(*str++));
123                 ea[i] = num;
124         }
125 }
126
127 int get_ethernet_addr(char *ethernet_addr)
128 {
129         char *ethaddr_str;
130
131         ethaddr_str = prom_getenv("ethaddr");
132         if (!ethaddr_str) {
133                 printk("ethaddr not set in boot prom\n");
134                 return -1;
135         }
136         str2eaddr(ethernet_addr, ethaddr_str);
137
138         if (init_debug > 1) {
139                 int i;
140                 printk("get_ethernet_addr: ");
141                 for (i=0; i<5; i++)
142                         printk("%02x:", (unsigned char)*(ethernet_addr+i));
143                 printk("%02x\n", *(ethernet_addr+i));
144         }
145
146         return 0;
147 }
148
149 void prom_init_sysclk(void)
150 {
151
152 #if defined(CONFIG_RT2880_FPGA)
153         mips_cpu_feq = 25000000;
154 #elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT2883_FPGA)
155         mips_cpu_feq = 40000000;
156 #else
157         u32     reg;
158         u8      clk_sel;
159
160         reg = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)));
161 #if defined (CONFIG_RT2880_ASIC)
162         clk_sel = (reg>>20) & 0x03;
163 #elif defined (CONFIG_RT2883_ASIC)
164         clk_sel = (reg>>18) & 0x03;
165 #elif defined (CONFIG_RT3052_ASIC)
166         clk_sel = (reg>>18) & 0x01;
167 #else
168 #error Please Choice System Type
169 #endif
170         switch(clk_sel) {
171 #if defined (CONFIG_RALINK_RT2880_SHUTTLE)
172         case 0:
173                 mips_cpu_feq = (233333333);
174                 break;
175         case 1:
176                 mips_cpu_feq = (250000000);
177                 break;
178         case 2:
179                 mips_cpu_feq = (266666666);
180                 break;
181         case 3:
182                 mips_cpu_feq = (280000000);
183                 break;
184 #elif defined (CONFIG_RALINK_RT2880_MP)
185         case 0:
186                 mips_cpu_feq = (250000000);
187                 break;
188         case 1:
189                 mips_cpu_feq = (266666666);
190                 break;
191         case 2:
192                 mips_cpu_feq = (280000000);
193                 break;
194         case 3:
195                 mips_cpu_feq = (300000000);
196                 break;
197 #elif defined (CONFIG_RALINK_RT2883)
198         case 0:
199                 mips_cpu_feq = (380*1000*1000);
200                 break;
201         case 1:
202                 mips_cpu_feq = (400*1000*1000);
203                 break;
204         case 2:
205                 mips_cpu_feq = (420*1000*1000);
206                 break;
207         case 3:
208                 mips_cpu_feq = (430*1000*1000);
209                 break;
210 #elif defined (CONFIG_RALINK_RT3052)
211         case 0:
212                 mips_cpu_feq = (320*1000*1000);
213                 break;
214         case 1:
215                 mips_cpu_feq = (384*1000*1000);
216                 break;
217 #else
218 #error Please Choice Chip Type
219 #endif
220         }
221
222 #endif
223        
224 #if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT2883) 
225         surfboard_sysclk = mips_cpu_feq/3;
226 #else
227         surfboard_sysclk = mips_cpu_feq/2;
228 #endif
229         printk("\n The CPU frequency set to %d MHz\n",mips_cpu_feq / 1000 / 1000);
230 }
231
232 /*
233 ** This function sets up the local prom_rs_table used only for the fake console
234 ** console (mainly prom_printf for debug display and no input processing)
235 ** and also sets up the global rs_table used for the actual serial console.
236 ** To get the correct baud_base value, prom_init_sysclk() must be called before
237 ** this function is called.
238 */
239 #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
240 extern int early_serial_setup(struct uart_port *port);
241
242 static struct uart_port serial_req[2];
243 int prom_init_serial_port(void)
244 {
245
246   /*
247    * baud rate = system clock freq / (CLKDIV * 16)
248    * CLKDIV=system clock freq/16/baud rate
249    */
250   memset(serial_req, 0, 2*sizeof(serial_req));
251
252   serial_req[0].type       = PORT_16550A;
253   serial_req[0].line       = 0;
254   serial_req[0].irq        = SURFBOARDINT_UART;
255   serial_req[0].flags      = STD_COM_FLAGS;
256   serial_req[0].uartclk    = 57600 *16;
257   serial_req[0].iotype     = SERIAL_IO_PORT;
258   serial_req[0].iobase     = KSEG1ADDR(RALINK_UART_BASE);
259   serial_req[0].regshift   = 2;
260   serial_req[0].mapbase    = KSEG1ADDR(RALINK_UART_BASE);
261   serial_req[0].custom_divisor = (surfboard_sysclk / SURFBOARD_BAUD_DIV / 57600);
262
263   serial_req[1].type       = PORT_16550A;
264   serial_req[1].line       = 1;
265   serial_req[1].irq        = SURFBOARDINT_UART1;
266   serial_req[1].flags      = STD_COM_FLAGS;
267   serial_req[1].uartclk    = 57600 *16;
268   serial_req[1].iotype     = SERIAL_IO_PORT;
269   serial_req[1].iobase     = KSEG1ADDR(RALINK_UART_LITE_BASE);
270   serial_req[1].regshift   = 2;
271   serial_req[1].mapbase    = KSEG1ADDR(RALINK_UART_LITE_BASE);
272   serial_req[1].custom_divisor = (surfboard_sysclk / SURFBOARD_BAUD_DIV / 57600);
273
274   early_serial_setup(&serial_req[0]);
275   early_serial_setup(&serial_req[1]);
276
277   return(0);
278 }
279
280 //early_initcall(prom_init_serial_port);
281
282 int prom_get_ttysnum(void)
283 {
284         char *argptr;
285         int ttys_num = 0;       /* default */
286
287         /* get ttys_num to use with the fake console/prom_printf */
288         argptr = prom_getcmdline();
289
290         if ((argptr = strstr(argptr, "console=ttyS")) != NULL)
291         {
292                 argptr += strlen("console=ttyS");
293
294                 if (argptr[0] == '0')           /* ttyS0 */
295                         ttys_num = 0;           /* happens to be rs_table[0] */
296                 else if (argptr[0] == '1')      /* ttyS1 */
297                         ttys_num = 1;           /* happens to be rs_table[1] */
298         }
299
300         return (ttys_num);
301 }
302
303 static void serial_setbrg(unsigned long wBaud)
304 {
305         unsigned int clock_divisor = 0;
306         clock_divisor = (surfboard_sysclk / SURFBOARD_BAUD_DIV);
307        
308 #if 1
309         //fix at 57600 8 n 1 n
310         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0xC08)= 0;
311         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0xC10)= 0;
312         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0xC14)= 0x3;
313         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0xC28)= (surfboard_sysclk / SURFBOARD_BAUD_DIV / 57600);
314         //fix at 57600 8 n 1 n
315         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x508)= 0;
316         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x510)= 0;
317         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x514)= 0x3;
318         *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x528)= (surfboard_sysclk / SURFBOARD_BAUD_DIV / 57600);
319 #else
320         IER(CFG_RT2880_CONSOLE) = 0;                                    /* Disable for now */
321         FCR(CFG_RT2880_CONSOLE) = 0;                                    /* No fifos enabled */
322
323         /* set baud rate */
324         LCR(CFG_RT2880_CONSOLE) = LCR_WLS0 | LCR_WLS1 | LCR_DLAB;
325         DLL(CFG_RT2880_CONSOLE) = clock_divisor &0xffff;
326         LCR(CFG_RT2880_CONSOLE) = LCR_WLS0 | LCR_WLS1;
327 #endif
328 }
329
330
331 int serial_init(unsigned long wBaud)
332 {
333         serial_setbrg(wBaud);
334
335         return (0);
336 }
337 __init void prom_init(void)
338 {
339
340         mips_machgroup = MACH_GROUP_RT2880;
341         mips_machtype = MACH_RALINK_ROUTER;
342
343         prom_init_cmdline();
344         prom_init_sysclk();
345
346         set_io_port_base(KSEG1);
347         write_c0_wired(0);
348         serial_init(57600);
349
350         prom_init_serial_port();  /* Needed for Serial Console */
351         prom_meminit();
352         prom_setup_printf(prom_get_ttysnum());
353 //      *(unsigned long *)(KSEG1ADDR(RALINK_USB_OTG_BASE+0xE00)) = 0x0; //Enable USB Port
354         prom_printf("\nLINUX started...\n");
355 #if defined(CONFIG_RT2880_FPGA) || defined(CONFIG_RT3052_FPGA) || defined(CONFIG_RT2883_FPGA)
356         prom_printf("\n THIS IS FPGA\n");
357 #elif defined(CONFIG_RT2880_ASIC) || defined(CONFIG_RT3052_ASIC) || defined (CONFIG_RT2883_ASIC)
358         prom_printf("\n THIS IS ASIC\n");
359 #endif
360
361 }
362
Note: See TracBrowser for help on using the browser.