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(<