Ticket #7938: overclock_atheros.c

File overclock_atheros.c, 12.4 KB (added by huey07@…, 6 years ago)

Successfully works on meraki mini. Haven't tested on any other atheros devices.

Line 
1/*
2 * overclock_atheros.c
3 *
4 * Copyright (C) 2008 Sebastian Gottschall <gottschall@dd-wrt.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 */
21
22#include <unistd.h>
23#include <sys/types.h>
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <fcntl.h>
28
29/*
30 * to prevent bricks and other troubles you should use this tool only
31 * manually. it will not be implemented in the webgui
32 */
33
34static void usage(void)
35{
36   printf("Usage:  overclock_atheros [New Clock Speed]\n");
37   printf("\n");
38   printf("Valid Clock Speeds are:\n");
39   printf("         184, 200, 220, 240 [ar2316]\n");
40   printf("         180, 200, 220, 240 [ar2312 viper revision]\n");
41   printf("\n");
42}
43
44void fixup( FILE * in, unsigned int src, unsigned int dst )
45{
46    fprintf( stderr, "fixup 0x%08X to 0x%08X\n", src, dst );
47    int f = ftell( in );
48
49    fseek( in, 0, SEEK_END );
50    int len = ftell( in );
51
52    fseek( in, 0, SEEK_SET );
53    int i;
54
55    for( i = 0; i < len; i++ )
56    {
57        fseek( in, i, SEEK_SET );
58        unsigned int chk;
59
60        fread( &chk, 4, 1, in );
61        if( chk == src )
62        {
63            fprintf( stderr, "fixup found at 0x%08X\n", i );
64            fseek( in, i, SEEK_SET );
65            fwrite( &dst, 4, 1, in );
66            fseek( in, f, SEEK_SET );
67            return;
68        }
69    }
70    fprintf( stderr, "warning. no fixup found\n" );
71    fseek( in, f, SEEK_SET );
72}
73
74void fixclk( FILE * in, int oldclk, int clk )
75{
76    // fixup amba clock
77    int amba = oldclk / 2 * 1000000;
78    unsigned int part1 = amba >> 16;
79    unsigned int part2 = amba & 0x0000ffff;
80
81    part1 = part1 | 0x3c020000;
82    part2 = part2 | 0x34420000;
83    int ambadst = clk / 2 * 1000000;
84    unsigned int part1dst = ambadst >> 16;
85    unsigned int part2dst = ambadst & 0x0000ffff;
86
87    part1dst = part1dst | 0x3c020000;
88    part2dst = part2dst | 0x34420000;
89    fixup( in, part1, part1dst );
90    fixup( in, part2, part2dst );
91    // fixup cpu frequency
92    /*
93     * //not required. code is not compiled into redboot amba = oldclk *
94     * 1000000; part1 = amba >> 16; part2 = amba & 0x0000ffff; part1 = part1
95     * | 0x3c020000; part2 = part2 | 0x34420000; ambadst = clk * 1000000;
96     * part1dst = ambadst >> 16; part2dst = ambadst & 0x0000ffff; part1dst =
97     * part1dst | 0x3c020000; part2dst = part2dst | 0x34420000;
98     * fixup(in,part1,part1dst); fixup(in,part2,part2dst);
99     */
100}
101
102int read_cpu(int new_clock)
103{
104    FILE * fh;
105    /* we receive default clock from call incase we can't read it */
106    int default_clock = 180;
107    unsigned int running_clock;
108    if ((fh = fopen("/proc/cpuinfo", "r"))) {
109      while (!feof(fh)) {
110        if (fscanf(fh, "BogoMIPS                : %u", &running_clock) == 0) {
111          /* Not on this line */
112          while (!feof(fh) && fgetc(fh) != '\n');
113        }
114        else {
115          /* Found it */
116          running_clock++;
117          fprintf( stderr, "board is currently running at %d mhz.\n", running_clock );
118          break;
119        }
120      }
121      fclose(fh);
122      if (new_clock != running_clock) {
123        return new_clock;
124      }
125      else {
126        return running_clock;
127      }
128    }
129    return default_clock;
130}
131
132
133void start_overclock(int new_clock)
134
135{
136    long len;
137    long i;
138
139#ifdef HAVE_ALPHA
140    FILE *in = fopen( "/dev/mtdblock0", "rb" );
141#elif HAVE_CA8
142    FILE *in = fopen( "/dev/mtdblock2", "rb" ); // zLoader Board Data
143#else
144    FILE *in = fopen( "/dev/mtdblock0", "rb" );
145#endif
146    FILE *out = fopen( "/tmp/boot", "wb" );
147
148    fseek( in, 0, SEEK_END );
149    len = ftell( in );
150    fprintf( stderr, "size = %ld\n", len );
151    fseek( in, 0, SEEK_SET );
152    for( i = 0; i < len; i++ )
153        putc( getc( in ), out );
154    fclose( in );
155    fclose( out );
156    int clk = read_cpu(new_clock);
157
158    in = fopen( "/tmp/boot", "r+b" );
159    fseek( in, 0xe64b, SEEK_SET );
160    int zmul = getc( in );
161
162    fseek( in, 0xcb, SEEK_SET );
163    int vipermul = getc( in );
164
165    fseek( in, 0x1e3, SEEK_SET );
166    int div = getc( in );
167
168    fseek( in, 0x1ef, SEEK_SET );
169    int mul = getc( in );
170
171    fseek( in, 0x17, SEEK_SET );
172    int dir300div = getc( in );
173
174    fseek( in, 0x23, SEEK_SET );
175    int dir300mul = getc( in );
176   
177    fseek( in, 0xdb, SEEK_SET );
178    int isalfa1=getc(in);
179    int isalfa=0;
180    if (isalfa1==0x6c)
181        isalfa=1;
182       
183    int dir300 = 0;
184
185    if( dir300div == 0x3 && dir300mul == 0x5c )
186    {
187        dir300 = 1;
188        div = dir300div;
189        mul = dir300mul;
190    }
191    if( dir300div == 0x1
192        && ( dir300mul == 0x28 || dir300mul == 0x2c || dir300mul == 0x30 ) )
193    {
194        dir300 = 1;
195        div = dir300div;
196        mul = dir300mul;
197    }
198
199    if( div == 0x3 && mul == 0x5c )
200    {
201        fprintf( stderr, "ap51/ap61 (ar2315 or ar2317) found\n" );
202        if( dir300 )
203            fseek( in, 0x17, SEEK_SET );
204        else
205            fseek( in, 0x1e3, SEEK_SET );
206        putc( 0x1, in );
207        if( dir300 )
208            fseek( in, 0x23, SEEK_SET );
209        else
210            fseek( in, 0x1ef, SEEK_SET );
211        if( clk == 200 )
212        {
213            if( mul == 0x2c )
214            {
215                fixclk( in, 220, 200 );
216            }
217            else if( mul == 0x30 )
218            {
219                fixclk( in, 240, 200 );
220            }
221            else
222                fixclk( in, 184, 200 );
223            putc( 0x28, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
224        }
225        else if( clk == 220 )
226        {
227            if( mul == 0x28 )
228            {
229                fixclk( in, 200, 220 );
230            }
231            else if( mul == 0x30 )
232            {
233                fixclk( in, 240, 220 );
234            }
235            else
236                fixclk( in, 184, 220 );
237
238            putc( 0x2c, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
239        }
240        else if( clk == 240 )
241        {
242            if( mul == 0x28 )
243            {
244                fixclk( in, 200, 240 );
245            }
246            else if( mul == 0x2c )
247            {
248                fixclk( in, 220, 240 );
249            }
250            else
251                fixclk( in, 184, 240 );
252            putc( 0x30, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
253        }
254        else
255        {
256            fixclk( in, 184, 200 );
257            clk = read_cpu(200);
258            putc( 0x28, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
259        }
260
261        fclose( in );
262        system("mtd -f write /tmp/boot RedBoot");
263    }
264    else if( div == 0x1 && ( mul == 0x28 || mul == 0x2c || mul == 0x30 ) )
265    {
266        fprintf( stderr, "ap51/ap61 (ar2315 or ar2317) found\n" );
267        if( clk == 200 && mul == 0x28 )
268        {
269            fprintf( stderr, "board already clocked to 200mhz\n" );
270            fclose( in );
271            return;
272        }
273        if( clk == 220 && mul == 0x2c )
274        {
275            fprintf( stderr, "board already clocked to 220mhz\n" );
276            fclose( in );
277            return;
278        }
279        if( clk == 240 && mul == 0x30 )
280        {
281            fprintf( stderr, "board already clocked to 240mhz\n" );
282            fclose( in );
283            return;
284        }
285        if( dir300 )
286            fseek( in, 0x17, SEEK_SET );
287        else
288            fseek( in, 0x1e3, SEEK_SET );
289        if( clk == 184 )
290            putc( 0x3, in );    // set divisor 5 = 40/5 = 8 mhz base which
291        // allows 184 clock setting
292        else
293            putc( 0x1, in );
294        if( dir300 )
295            fseek( in, 0x23, SEEK_SET );
296        else
297            fseek( in, 0x1ef, SEEK_SET );
298        if( clk == 184 )
299        {
300            if( mul == 0x28 )
301            {
302                fixclk( in, 200, 184 );
303            }
304            else if( mul == 0x2c )
305            {
306                fixclk( in, 220, 184 );
307            }
308            else if( mul == 0x30 )
309            {
310                fixclk( in, 240, 184 );
311            }
312            putc( 0x5c, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
313        }
314        else if( clk == 200 )
315        {
316            if( mul == 0x2c )
317            {
318                fixclk( in, 220, 200 );
319            }
320            else if( mul == 0x30 )
321            {
322                fixclk( in, 240, 200 );
323            }
324            else
325                fixclk( in, 184, 200 );
326            putc( 0x28, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
327        }
328        else if( clk == 220 )
329        {
330            if( mul == 0x28 )
331            {
332                fixclk( in, 200, 220 );
333            }
334            else if( mul == 0x30 )
335            {
336                fixclk( in, 240, 220 );
337            }
338            else
339                fixclk( in, 184, 220 );
340
341            putc( 0x2c, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
342        }
343        else if( clk == 240 )
344        {
345            if( mul == 0x28 )
346            {
347                fixclk( in, 200, 240 );
348            }
349            else if( mul == 0x2c )
350            {
351                fixclk( in, 220, 240 );
352            }
353            else
354                fixclk( in, 184, 240 );
355            putc( 0x30, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
356        }
357        else
358        {
359            fixclk( in, 184, 200 );
360            clk = read_cpu(200);
361            putc( 0x28, in );   // 0x2c for 220 mhz 0x30 for 240 mhz
362        }
363        fclose( in );
364        system("mtd -f write /tmp/boot RedBoot");
365    }
366    else if( vipermul == 0x9 || vipermul == 0xa || vipermul == 0xb
367             || vipermul == 0xc || vipermul == 0x17 )
368    {
369
370        if( vipermul == 0x17 )
371        {
372            fprintf( stderr, "weired alfa clocksetting found\n" );
373            fseek( in, 0xce, SEEK_SET );
374            if( getc( in ) == 0x32 )
375            {
376                if( getc( in ) == 0x45 )
377                {
378                    fprintf( stderr, "correct clock setting\n" );
379                    fseek( in, 0xcb, SEEK_SET );
380                    putc( 0x9, in );
381                    fseek( in, 0xce, SEEK_SET );
382                    putc( 0x12, in );
383                    putc( 0x45, in );
384//                  fseek( in, 0xe4, SEEK_SET );
385//                  putc( 0x0, in ); // nop out scratch register
386//                  putc( 0x0, in );
387                    vipermul = 0x9;
388                }
389                else
390                    exit( 1 );
391            }
392            else
393                exit( 1 );
394        }
395        fprintf( stderr, "viper (ar2313) found\n" );
396        if( clk == 180 && vipermul == 0x9 )
397        {
398            fprintf( stderr, "board already clocked to 180mhz\n" );
399            fclose( in );
400            return;
401        }
402        if( clk == 200 && vipermul == 0xa )
403        {
404            fprintf( stderr, "board already clocked to 200mhz\n" );
405            fclose( in );
406            return;
407        }
408        if( clk == 220 && vipermul == 0xb )
409        {
410            fprintf( stderr, "board already clocked to 220mhz\n" );
411            fclose( in );
412            return;
413        }
414        if( clk == 240 && vipermul == 0xc )
415        {
416            fprintf( stderr, "board already clocked to 240mhz\n" );
417            fclose( in );
418            return;
419        }
420        fseek( in, 0xcb, SEEK_SET );
421        if( clk == 180 )
422            putc( 0x9, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
423        else if( clk == 200 )
424            putc( 0xa, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
425        else if( clk == 220 )
426            putc( 0xb, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
427        else if( clk == 240 )
428            putc( 0xc, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
429        else
430        {
431            clk = read_cpu(220);
432            putc( 0xb, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
433        }
434        if (isalfa)
435            {
436            fprintf(stderr,"correct scratch register for alfa ap48\n");
437            int realclock=clk*1000000;
438            fseek(in,0xde,SEEK_SET);
439            putc((realclock>>24)&0xff,in);
440            putc((realclock>>16)&0xff,in);
441            fseek(in,0xe2,SEEK_SET);
442            putc((realclock>>8)&0xff,in);
443            putc(realclock&0xff,in);
444            }
445        fclose( in );
446        system("mtd -f write /tmp/boot RedBoot");
447    }
448    else if( zmul == 0x9 || zmul == 0xa || zmul == 0xb || zmul == 0xc ) // special
449        // handling
450        // for
451        // zLoader
452        // based
453        // boards
454    {
455        fprintf( stderr, "viper (ar2313) found (zLoader)\n" );
456        if( clk == 180 && zmul == 0x9 )
457        {
458            fprintf( stderr, "board already clocked to 180mhz\n" );
459            fclose( in );
460            return;
461        }
462        if( clk == 200 && zmul == 0xa )
463        {
464            fprintf( stderr, "board already clocked to 200mhz\n" );
465            fclose( in );
466            return;
467        }
468        if( clk == 220 && zmul == 0xb )
469        {
470            fprintf( stderr, "board already clocked to 220mhz\n" );
471            fclose( in );
472            return;
473        }
474        if( clk == 240 && zmul == 0xc )
475        {
476            fprintf( stderr, "board already clocked to 240mhz\n" );
477            fclose( in );
478            return;
479        }
480        fseek( in, 0xe64b, SEEK_SET );
481        if( clk == 180 )
482            putc( 0x9, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
483        else if( clk == 200 )
484            putc( 0xa, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
485        else if( clk == 220 )
486            putc( 0xb, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
487        else if( clk == 240 )
488            putc( 0xc, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
489        else
490        {
491            clk = read_cpu(220);
492            putc( 0xb, in );    // 0x2c for 220 mhz 0x30 for 240 mhz
493        }
494
495        unsigned int myclk = clk * 1000000;
496        unsigned short part1, part2;
497
498        part1 = myclk >> 16;
499        part2 = myclk & 0x0000ffff;
500
501        fprintf( stderr, "patch uart init with %X:%X\n", part1, part2 );
502        fseek( in, 0xed16, SEEK_SET );
503        fwrite( &part1, 2, 1, in );
504        fseek( in, 0xed1a, SEEK_SET );
505        fwrite( &part2, 2, 1, in );
506
507        fclose( in );
508        system("mtd -f write /tmp/boot bdata");
509    }
510    else
511    {
512        fprintf( stderr, "unknown board or no redboot found\n" );
513        fclose( in );
514        exit( 1 );
515    }
516    fprintf( stderr, "board is now clocked at %d mhz, please reboot\n", clk );
517    exit(1);
518}
519
520
521int main (int argc, char *argv[])
522{
523  if (argc != 2 ) {
524    usage();
525    exit(1);
526  }
527
528  int new_clock;
529  new_clock = atoi(argv[1]);
530
531  if (new_clock == 180 || new_clock == 184 || new_clock == 200 || new_clock == 220) {
532    start_overclock (new_clock);
533  }
534  else {
535    usage();
536    exit(1);
537  }
538  exit(1);
539}