summaryrefslogtreecommitdiffstats
path: root/firmware/target/coldfire/iriver/system-iriver.c
blob: 1cb0a502be920b442c1922ec359bac03c9cbb1fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2006 by Linus Nielsen Feltzing
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "kernel.h"
#include "system.h"
#include "power.h"
#include "timer.h"
#include "pcf50606.h"

/* Settings for all possible clock frequencies (with properly working timers)
 * NOTE: Some 5249 chips don't like having PLLDIV set to 0. We must avoid that!
 *
 *                        xxx_REFRESH_TIMER below
 * system.h, CPUFREQ_xxx_MULT        |
 *              |                    |
 *              V                    V
 *                              Refreshtim.                         IDECONFIG1/IDECONFIG2
 * CPUCLK/Hz  MULT    PLLCR     16MB  32MB  CSCR0   CSCR1   CSCR3   CS2Pre CS2Post CS2Wait
 * ---------------------------------------------------------------------------------------
 *  11289600    1   0x10c00200    4     1   0x0180  0x0180  0x0180     1      0       0
 *  22579200    2   0x15c9e025   10     4   0x0180  0x0180  0x0180     1      0       0
 *  33868800    3   0x13c8e025   15     7   0x0180  0x0180  0x0180     1      0       0
 *  45158400    4   0x15c9e021   21    10   0x0580  0x0180  0x0580     1      0       0
 *  56448000    5   0x12c9e025   26    12   0x0580          0x0980
 *  67737600    6   0x13c8e021   32    15   0x0980          0x0d80
 *  79027200    7   0x13ca6021   37    18   0x0980          0x1180
 *  90316800    8   0x13cbe021   43    21   0x0d80          0x1580
 * 101606400    9   0x11c92025   48    23   0x0d80          0x1980
 * 112896000   10   0x11c9e025   54    26   0x1180          0x1d80
 * 124185600   11   0x11cae025   59    29   0x1180  0x1180  0x2180     2      1       2
 */

#if MEM < 32
#define MAX_REFRESH_TIMER     59
#define NORMAL_REFRESH_TIMER  21
#define DEFAULT_REFRESH_TIMER 4
#else
#define MAX_REFRESH_TIMER     29
#define NORMAL_REFRESH_TIMER  10
#define DEFAULT_REFRESH_TIMER 1
#endif

#ifdef IRIVER_H300_SERIES
#define RECALC_DELAYS(f) \
        pcf50606_i2c_recalc_delay(f)
#else
#define RECALC_DELAYS(f)
#endif

#ifdef HAVE_SERIAL
#define BAUD_RATE 57600
#define BAUDRATE_DIV_DEFAULT (CPUFREQ_DEFAULT/(BAUD_RATE*32*2))
#define BAUDRATE_DIV_NORMAL (CPUFREQ_NORMAL/(BAUD_RATE*32*2))
#define BAUDRATE_DIV_MAX (CPUFREQ_MAX/(BAUD_RATE*32*2))
#endif

void set_cpu_frequency (long) __attribute__ ((section (".icode")));
void set_cpu_frequency(long frequency)
{
    switch(frequency)
    {
    case CPUFREQ_MAX:
        DCR = (0x8200 | DEFAULT_REFRESH_TIMER);
              /* Refresh timer for bypass frequency */
        PLLCR &= ~1;  /* Bypass mode */
        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
        RECALC_DELAYS(CPUFREQ_MAX);
        PLLCR = 0x018ae025 | (PLLCR & 0x70400000);
        CSCR0 = 0x00001180; /* Flash: 4 wait states */
        CSCR1 = 0x00001580; /* LCD: 5 wait states */
#if defined(CONFIG_USBOTG) && CONFIG_USBOTG == USBOTG_ISP1362
        CSCR3 = 0x00002180; /* USBOTG: 8 wait states */
#endif
        while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
                                            This may take up to 10ms! */
        timers_adjust_prescale(CPUFREQ_MAX_MULT, true);
        DCR = (0x8200 | MAX_REFRESH_TIMER);          /* Refresh timer */
        cpu_frequency = CPUFREQ_MAX;
        IDECONFIG1 = 0x10100000 | (1 << 13) | (2 << 10);
        /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */
        IDECONFIG2 = 0x40000 | (2 << 8); /* TA enable + CS2wait */

#ifdef HAVE_SERIAL
        UBG10 = BAUDRATE_DIV_MAX >> 8;
        UBG20 = BAUDRATE_DIV_MAX & 0xff;
#endif
        break;

    case CPUFREQ_NORMAL:
        DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
              /* Refresh timer for bypass frequency */
        PLLCR &= ~1;  /* Bypass mode */
        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
        RECALC_DELAYS(CPUFREQ_NORMAL);
        PLLCR = 0x038be025 | (PLLCR & 0x70400000);
        CSCR0 = 0x00000580; /* Flash: 1 wait state */
        CSCR1 = 0x00000180; /* LCD: 0 wait states */
#if defined(CONFIG_USBOTG) && CONFIG_USBOTG == USBOTG_ISP1362
        CSCR3 = 0x00000580; /* USBOTG: 1 wait state */
#endif
        while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
                                            This may take up to 10ms! */
        timers_adjust_prescale(CPUFREQ_NORMAL_MULT, true);
        DCR = (0x8000 | NORMAL_REFRESH_TIMER);       /* Refresh timer */
        cpu_frequency = CPUFREQ_NORMAL;
        IDECONFIG1 = 0x10100000 | (0 << 13) | (1 << 10);
        /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */
        IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */

#ifdef HAVE_SERIAL
        UBG10 = BAUDRATE_DIV_NORMAL >> 8;
        UBG20 = BAUDRATE_DIV_NORMAL & 0xff;
#endif
        break;
    default:
        DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
              /* Refresh timer for bypass frequency */
        PLLCR &= ~1;  /* Bypass mode */
        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
        RECALC_DELAYS(CPUFREQ_DEFAULT);
        /* Power down PLL, but keep CRSEL and CLSEL */
        PLLCR = 0x00800200 | (PLLCR & 0x70400000);
        CSCR0 = 0x00000180; /* Flash: 0 wait states */
        CSCR1 = 0x00000180; /* LCD: 0 wait states */
#if defined(CONFIG_USBOTG) && CONFIG_USBOTG == USBOTG_ISP1362
        CSCR3 = 0x00000180; /* USBOTG: 0 wait states */
#endif
        DCR = (0x8000 | DEFAULT_REFRESH_TIMER);       /* Refresh timer */
        cpu_frequency = CPUFREQ_DEFAULT;
        IDECONFIG1 = 0x10100000 | (0 << 13) | (1 << 10);
        /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */
        IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */

#ifdef HAVE_SERIAL
        UBG10 = BAUDRATE_DIV_DEFAULT >> 8;
        UBG20 = BAUDRATE_DIV_DEFAULT & 0xff;
#endif
        break;
    }
}