summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.h1
-rw-r--r--firmware/target/arm/imx233/emi-imx233.c186
-rw-r--r--firmware/target/arm/imx233/emi-imx233.h260
-rw-r--r--firmware/target/arm/imx233/system-imx233.c21
-rw-r--r--firmware/target/arm/imx233/system-target.h30
5 files changed, 489 insertions, 9 deletions
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.h b/firmware/target/arm/imx233/clkctrl-imx233.h
index 665674108c..30c1c54545 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.h
+++ b/firmware/target/arm/imx233/clkctrl-imx233.h
@@ -81,6 +81,7 @@
81#define HW_CLKCTRL_EMI__DIV_XTAL_BP 8 81#define HW_CLKCTRL_EMI__DIV_XTAL_BP 8
82#define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8) 82#define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8)
83#define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28) 83#define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28)
84#define HW_CLKCTRL_EMI__BUSY_REF_XTAL (1 << 29)
84#define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30) 85#define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30)
85#define HW_CLKCTRL_EMI__CLKGATE (1 << 31) 86#define HW_CLKCTRL_EMI__CLKGATE (1 << 31)
86 87
diff --git a/firmware/target/arm/imx233/emi-imx233.c b/firmware/target/arm/imx233/emi-imx233.c
new file mode 100644
index 0000000000..b10d08134d
--- /dev/null
+++ b/firmware/target/arm/imx233/emi-imx233.c
@@ -0,0 +1,186 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "emi-imx233.h"
22#include "clkctrl-imx233.h"
23
24struct emi_reg_t
25{
26 int index;
27 uint32_t value;
28};
29
30/* hardcode all the register values for the different settings. This is ugly
31 * but I don't understand what they mean and it's faster this way so...
32 * Recall that everything should be put in iram !
33 * Make sure the last value is written to register 40. */
34
35/* Values extracted from Sigmatel linux port (GPL) */
36
37/** mDDR value */
38static struct emi_reg_t settings_24M[15] ICONST_ATTR =
39{
40 {4, 0x01000101}, {7, 0x01000101}, {12, 0x02010002}, {13, 0x06060a02},
41 {15, 0x01030000}, {17, 0x2d000102}, {18, 0x20200000}, {19, 0x027f1414},
42 {20, 0x01021608}, {21, 0x00000002}, {26, 0x000000b3}, {32, 0x00030687},
43 {33, 0x00000003}, {34, 0x000012c1}, {40, 0x00010000}
44};
45
46static struct emi_reg_t settings_48M[15] ICONST_ATTR =
47{
48 {4, 0x01000101}, {7, 0x01000101}, {13, 0x06060a02}, {12, 0x02010002},
49 {15, 0x02040000}, {17, 0x2d000104}, {18, 0x1f1f0000}, {19, 0x027f0a0a},
50 {20, 0x01021608}, {21, 0x00000004}, {26, 0x0000016f}, {32, 0x00060d17},
51 {33, 0x00000006}, {34, 0x00002582}, {40, 0x00020000}
52};
53
54static struct emi_reg_t settings_60M[15] ICONST_ATTR =
55{
56 {4, 0x01000101}, {7, 0x01000101}, {12, 0x02020002}, {13, 0x06060a02},
57 {15, 0x02040000}, {17, 0x2d000005}, {18, 0x1f1f0000}, {19, 0x027f0a0a},
58 {20, 0x02040a10}, {21, 0x00000006}, {26, 0x000001cc}, {32, 0x00081060},
59 {33, 0x00000008}, {34, 0x00002ee5}, {40, 0x00020000}
60};
61
62static struct emi_reg_t settings_80M[15] ICONST_ATTR __attribute__((alias("settings_60M")));
63
64static struct emi_reg_t settings_96M[15] ICONST_ATTR =
65{
66 {4, 0x00000101}, {7, 0x01000001}, {12, 0x02020002}, {13, 0x06070a02},
67 {15, 0x03050000}, {17, 0x2d000808}, {18, 0x1f1f0000}, {19, 0x020c1010},
68 {20, 0x0305101c}, {21, 0x00000007}, {26, 0x000002e6}, {32, 0x000c1a3b},
69 {33, 0x0000000c}, {34, 0x00004b0d}, {40, 0x00030000}
70};
71
72static struct emi_reg_t settings_120M[15] ICONST_ATTR =
73{
74 {4, 0x00000101}, {7, 0x01000001}, {12, 0x02020002}, {13, 0x06070a02},
75 {15, 0x03050000}, {17, 0x2300080a}, {18, 0x1f1f0000}, {19, 0x020c1010},
76 {20, 0x0306101c}, {21, 0x00000009}, {26, 0x000003a1}, {32, 0x000f20ca},
77 {33, 0x0000000f}, {34, 0x00005dca}, {40, 0x00040000}
78};
79
80static struct emi_reg_t settings_133M[15] ICONST_ATTR =
81{
82 {4, 0x00000101}, {7, 0x01000001}, {12, 0x02020002}, {13, 0x06070a02},
83 {15, 0x03050000}, {17, 0x2000080a}, {18, 0x1f1f0000}, {19, 0x020c1010},
84 {20, 0x0306101c}, {21, 0x0000000a}, {26, 0x00000408}, {32, 0x0010245f},
85 {33, 0x00000010}, {34, 0x00006808}, {40, 0x00040000}
86};
87
88static struct emi_reg_t settings_155M[15] ICONST_ATTR __attribute__((alias("settings_133M")));
89
90static void set_frequency(unsigned long freq) ICODE_ATTR;
91
92static void set_frequency(unsigned long freq)
93{
94 /* Set divider and clear clkgate. Do byte access to register to avoid bothering
95 * with other PFDs */
96 switch(freq)
97 {
98 case IMX233_EMIFREQ_151_MHz:
99 /* clk_emi@ref_emi/3*18/19 */
100 HW_CLKCTRL_FRAC_EMI = 19;
101 __FIELD_SET(HW_CLKCTRL_EMI, DIV_EMI, 3);
102 /* ref_emi@480 MHz
103 * clk_emi@151.58 MHz */
104 break;
105 case IMX233_EMIFREQ_130_MHz:
106 /* clk_emi@ref_emi/2*18/33 */
107 HW_CLKCTRL_FRAC_EMI = 33;
108 __FIELD_SET(HW_CLKCTRL_EMI, DIV_EMI, 2);
109 /* ref_emi@480 MHz
110 * clk_emi@130.91 MHz */
111 break;
112 case IMX233_EMIFREQ_64_MHz:
113 default:
114 /* clk_emi@ref_emi/5*18/27 */
115 HW_CLKCTRL_FRAC_EMI = 27;
116 __FIELD_SET(HW_CLKCTRL_EMI, DIV_EMI, 5);
117 /* ref_emi@480 MHz
118 * clk_emi@64 MHz */
119 break;
120 }
121}
122
123void imx233_emi_set_frequency(unsigned long freq) ICODE_ATTR;
124
125void imx233_emi_set_frequency(unsigned long freq)
126{
127 /** FIXME we rely on the compiler to NOT use the stack here because it's
128 * in iram ! If it's not smart enough, one can switch the switch to use
129 * the irq stack since we are running interrupts disable here ! */
130 /** BUG for freq<=24 MHz we must keep bypass mode since we run on xtal
131 * we this setting is unused by our code so ignore this bug for now */
132 /** WARNING DANGER
133 * Changing the EMI frequency is complicated because it requires to
134 * completely shutdown the external memory interface. We must make sure
135 * that this code and all the data it uses in in iram and that no access to
136 * the sdram will be made during the change. Care must be taken w.r.t to
137 * the cache also. */
138 /** FIXME assume that auto-slow is disabled here since that could put some
139 * clock below the minimum value and we want to spend as less time as
140 * possible in this state anyway. */
141
142 /* first disable all interrupts */
143 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
144 /* flush the cache */
145 commit_discard_idcache();
146 /* put DRAM into self-refresh mode */
147 HW_DRAM_CTL08 |= HW_DRAM_CTL08__SREFRESH;
148 /* wait for DRAM to be halted */
149 while(!(HW_EMI_STAT & HW_EMI_STAT__DRAM_HALTED));
150 /* load timings */
151 struct emi_reg_t *regs;
152 if(freq <= 24000) regs = settings_24M;
153 else if(freq <= 48000) regs = settings_48M;
154 else if(freq <= 60000) regs = settings_60M;
155 else if(freq <= 80000) regs = settings_80M;
156 else if(freq <= 96000) regs = settings_96M;
157 else if(freq <= 120000) regs = settings_120M;
158 else if(freq <= 133000) regs = settings_133M;
159 else regs = settings_155M;
160
161 do
162 HW_DRAM_CTLxx(regs->index) = regs->value;
163 while((regs++)->index != 40);
164 /* switch emi to xtal */
165 __REG_SET(HW_CLKCTRL_CLKSEQ) = HW_CLKCTRL_CLKSEQ__BYPASS_EMI;
166 /* wait for transition */
167 while(HW_CLKCTRL_EMI & HW_CLKCTRL_EMI__BUSY_REF_XTAL);
168 /* put emi dll into reset mode */
169 __REG_SET(HW_EMI_CTRL) = HW_EMI_CTRL__DLL_RESET | HW_EMI_CTRL__DLL_SHIFT_RESET;
170 /* load the new frequency dividers */
171 set_frequency(freq);
172 /* switch emi back to pll */
173 __REG_CLR(HW_CLKCTRL_CLKSEQ) = HW_CLKCTRL_CLKSEQ__BYPASS_EMI;
174 /* wait for transition */
175 while(HW_CLKCTRL_EMI & HW_CLKCTRL_EMI__BUSY_REF_EMI);
176 /* allow emi dll to lock again */
177 __REG_CLR(HW_EMI_CTRL) = HW_EMI_CTRL__DLL_RESET | HW_EMI_CTRL__DLL_SHIFT_RESET;
178 /* wait for lock */
179 while(!(HW_DRAM_CTL04 & HW_DRAM_CTL04__DLLLOCKREG));
180 /* get DRAM out of self-refresh mode */
181 HW_DRAM_CTL08 &= ~HW_DRAM_CTL08__SREFRESH;
182 /* wait for DRAM to be to run again */
183 while(HW_EMI_STAT & HW_EMI_STAT__DRAM_HALTED);
184
185 restore_interrupt(oldstatus);
186}
diff --git a/firmware/target/arm/imx233/emi-imx233.h b/firmware/target/arm/imx233/emi-imx233.h
new file mode 100644
index 0000000000..8106d27dfe
--- /dev/null
+++ b/firmware/target/arm/imx233/emi-imx233.h
@@ -0,0 +1,260 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __EMI_IMX233_H__
22#define __EMI_IMX233_H__
23
24#include "cpu.h"
25#include "system.h"
26#include "system-target.h"
27
28#define HW_EMI_BASE 0x80020000
29
30#define HW_EMI_CTRL (*(volatile uint32_t *)(HW_EMI_BASE + 0x0))
31#define HW_EMI_CTRL__DLL_SHIFT_RESET (1 << 25)
32#define HW_EMI_CTRL__DLL_RESET (1 << 24)
33
34/* this register is undocumented but exists, I put the whole doc here */
35#define HW_EMI_STAT (*(volatile uint32_t *)(HW_EMI_BASE + 0x10))
36#define HW_EMI_STAT__DRAM_PRESENT (1 << 31)
37#define HW_EMI_STAT__NOR_PRESENT (1 << 30)
38#define HW_EMI_STAT__LARGE_DRAM_ENABLED (1 << 29)
39#define HW_EMI_STAT__DRAM_HALTED (1 << 1)
40#define HW_EMI_STAT__NOR_BUSY (1 << 0)
41
42/* another undocumented registers (there are some more) */
43#define HW_EMI_TIME (*(volatile uint32_t *)(HW_EMI_BASE + 0x20))
44#define HW_EMI_TIME__THZ_BP 24
45#define HW_EMI_TIME__THZ_BM (0xf << 24)
46#define HW_EMI_TIME__TDH_BP 16
47#define HW_EMI_TIME__TDH_BM (0xf << 16)
48#define HW_EMI_TIME__TDS_BP 8
49#define HW_EMI_TIME__TDS_BM (0x1f << 8)
50#define HW_EMI_TIME__TAS_BP 0
51#define HW_EMI_TIME__TAS_BM (0xf << 0)
52
53/** WARNING: the HW_DRAM_* registers don't have a SCT variant ! */
54#define HW_DRAM_BASE 0x800E0000
55
56#define HW_DRAM_CTLxx(xx) (*(volatile uint32_t *)(HW_DRAM_BASE + 0x4 * (xx)))
57
58#define HW_DRAM_CTL00 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x0))
59#define HW_DRAM_CTL01 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x4))
60#define HW_DRAM_CTL02 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x8))
61#define HW_DRAM_CTL03 (*(volatile uint32_t *)(HW_DRAM_BASE + 0xc))
62
63#define HW_DRAM_CTL04 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x10))
64#define HW_DRAM_CTL04__DLL_BYPASS_MODE (1 << 24)
65#define HW_DRAM_CTL04__DLLLOCKREG (1 << 16)
66
67#define HW_DRAM_CTL05 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x14))
68#define HW_DRAM_CTL05__EN_LOWPOWER_MODE (1 << 0)
69
70#define HW_DRAM_CTL06 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x18))
71#define HW_DRAM_CTL07 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x1c))
72
73#define HW_DRAM_CTL08 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x20))
74#define HW_DRAM_CTL08__SREFRESH (1 << 8)
75
76#define HW_DRAM_CTL09 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x24))
77
78#define HW_DRAM_CTL10 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x28))
79#define HW_DRAM_CTL10__TEMRS_BP 8
80#define HW_DRAM_CTL10__TEMRS_BM (0x3 << 8)
81
82#define HW_DRAM_CTL11 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x2c))
83#define HW_DRAM_CTL11__CASLAT_BP 0
84#define HW_DRAM_CTL11__CASLAT_BM (0x7 << 0)
85
86#define HW_DRAM_CTL12 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x30))
87#define HW_DRAM_CTL12__TCKE_BP 0
88#define HW_DRAM_CTL12__TCKE_BM (0x7 << 0)
89#define HW_DRAM_CTL12__TRRD_BP 16
90#define HW_DRAM_CTL12__TRRD_BM (0x7 << 16)
91#define HW_DRAM_CTL12__TWR_INT_BP 24
92#define HW_DRAM_CTL12__TWR_INT_BM (0x7 << 24)
93
94#define HW_DRAM_CTL13 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x34))
95#define HW_DRAM_CTL13__TWTR_BP 0
96#define HW_DRAM_CTL13__TWTR_BM (0x7 << 0)
97#define HW_DRAM_CTL13__CASLAT_LIN_BP 16
98#define HW_DRAM_CTL13__CASLAT_LIN_BM (0xf << 16)
99#define HW_DRAM_CTL13__CASLAT_LIN_GATE_BP 24
100#define HW_DRAM_CTL13__CASLAT_LIN_GATE_BM (0xf << 24)
101
102#define HW_DRAM_CTL14 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x38))
103
104#define HW_DRAM_CTL15 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x3c))
105#define HW_DRAM_CTL15__TDAL_BP 16
106#define HW_DRAM_CTL15__TDAL_BM (0xf << 16)
107#define HW_DRAM_CTL15__TRP_BP 24
108#define HW_DRAM_CTL15__TRP_BM (0xf << 24)
109
110#define HW_DRAM_CTL16 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x40))
111#define HW_DRAM_CTL16__TMRD_BP 24
112#define HW_DRAM_CTL16__TMRD_BM (0x1f << 24)
113
114#define HW_DRAM_CTL17 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x44))
115#define HW_DRAM_CTL17__TRC_BP 0
116#define HW_DRAM_CTL17__TRC_BM (0x1f << 0)
117#define HW_DRAM_CTL17__DLL_INCREMENT_BP 8
118#define HW_DRAM_CTL17__DLL_INCREMENT_BM (0xff << 0)
119#define HW_DRAM_CTL17__DLL_START_POINT_BP 24
120#define HW_DRAM_CTL17__DLL_START_POINT_BM (0xff << 24)
121
122#define HW_DRAM_CTL18 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x48))
123#define HW_DRAM_CTL17__DLL_DQS_DELAY_0_BP 16
124#define HW_DRAM_CTL17__DLL_DQS_DELAY_0_BM (0x7f << 16)
125#define HW_DRAM_CTL17__DLL_DQS_DELAY_1_BP 24
126#define HW_DRAM_CTL17__DLL_DQS_DELAY_1_BM (0x7f << 24)
127
128#define HW_DRAM_CTL19 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x4c))
129#define HW_DRAM_CTL19__DQS_OUT_SHIFT_BP 16
130#define HW_DRAM_CTL19__DQS_OUT_SHIFT_BM (0x7f << 16)
131
132#define HW_DRAM_CTL20 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x50))
133#define HW_DRAM_CTL20__WR_DQS_SHIFT_BP 0
134#define HW_DRAM_CTL20__WR_DQS_SHIFT_BM (0x7f << 0)
135#define HW_DRAM_CTL20__TRAS_MIN_BP 16
136#define HW_DRAM_CTL20__TRAS_MIN_BM (0xff << 16)
137#define HW_DRAM_CTL20__TRCD_INT_BP 24
138#define HW_DRAM_CTL20__TRCD_INT_BM (0xff << 24)
139
140#define HW_DRAM_CTL21 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x54))
141#define HW_DRAM_CTL21__TRFC_BP 0
142#define HW_DRAM_CTL21__TRFC_BM (0xff << 0)
143
144#define HW_DRAM_CTL22 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x58))
145#define HW_DRAM_CTL23 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x5c))
146#define HW_DRAM_CTL24 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x60))
147#define HW_DRAM_CTL25 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x64))
148
149#define HW_DRAM_CTL26 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x68))
150#define HW_DRAM_CTL26__TREF_BP 0
151#define HW_DRAM_CTL26__TREF_BM (0xfff << 0)
152
153#define HW_DRAM_CTL27 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x6c))
154#define HW_DRAM_CTL28 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x70))
155#define HW_DRAM_CTL29 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x74))
156#define HW_DRAM_CTL30 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x78))
157
158#define HW_DRAM_CTL31 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x7c))
159#define HW_DRAM_CTL31__TDLL_BP 16
160#define HW_DRAM_CTL31__TDLL_BM (0xffff << 16)
161
162#define HW_DRAM_CTL32 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x80))
163#define HW_DRAM_CTL32__TRAS_MAX_BP 0
164#define HW_DRAM_CTL32__TRAS_MAX_BM (0xffff << 0)
165#define HW_DRAM_CTL32__TXSNR_BP 16
166#define HW_DRAM_CTL32__TXSNR_BM (0xffff << 16)
167
168#define HW_DRAM_CTL33 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x84))
169#define HW_DRAM_CTL33__TXSR_BP 0
170#define HW_DRAM_CTL33__TXSR_BM (0xffff << 0)
171
172#define HW_DRAM_CTL34 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x88))
173#define HW_DRAM_CTL34__TINIT_BP 0
174#define HW_DRAM_CTL34__TINIT_BM 0xffffff
175
176#define HW_DRAM_CTL35 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x8c))
177#define HW_DRAM_CTL36 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x90))
178#define HW_DRAM_CTL37 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x94))
179#define HW_DRAM_CTL38 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x98))
180#define HW_DRAM_CTL39 (*(volatile uint32_t *)(HW_DRAM_BASE + 0x9a))
181
182#define HW_DRAM_CTL40 (*(volatile uint32_t *)(HW_DRAM_BASE + 0xa0))
183#define HW_DRAM_CTL40__TPDEX_BP 16
184#define HW_DRAM_CTL40__TPDEX_BM (0xffff << 16)
185
186/** Interesting fields:
187 * - TCKE: CTL12
188 * - TDAL: CTL15
189 * - TDLL: CTL31
190 * - TEMRS: CTL10
191 * - TINIT: CTL34
192 * - TMRD: CTL16
193 * - TPDEX: CTL40
194 * - TRAS_MAX: CTL32
195 * - TRAS_MIN: CTL20
196 * - TRC: CTL17
197 * - TRCD_INT: CTL20
198 * - TREF: CTL26
199 * - TRFC: CTL21
200 * - TRP: CTL15
201 * - TRRD: CTL12
202 * - TWR_INT: CTL12
203 * - TWTR: CTL13
204 * - TXSNR: CTL32
205 * - TXSR: CTL33
206 * - DLL_DQS_DELAY_BYPASS_0
207 * - DLL_DQS_DELAY_BYPASS_1
208 * - DQS_OUT_SHIFT_BYPASS
209 * - WR_DQS_SHIFT_BYPASS
210 * - DLL_INCREMENT: CTL17
211 * - DLL_START_POINT: CTL17
212 * - DLL_DQS_DELAY_0: CTL18
213 * - DLL_DQS_DELAY_1: CTL18
214 * - DQS_OUT_SHIFT: CTL19
215 * - WR_DQS_SHIFT: CTL20
216 * - CAS: CTL11
217 * - DLL_BYPASS_MODE: CTL04
218 * - SREFRESH: CTL08
219 * - CASLAT_LIN: CTL13
220 * - CASLAT_LIN_GATE: CTL13
221 *
222 * Interesting registers:
223 * - CTL04: DLL_BYPASS_MODE
224 * - CTL08: SREFRESH
225 * - CTL10: TEMRS
226 * - CTL11: CASLAT
227 * - CTL12: TCKE TRRD TWR_INT
228 * - CTL13: TWTR CASLAT_LIN CASLAT_LIN_GATE
229 * - CTL15: TDAL TRP
230 * - CTL16: TMRD
231 * - CTL17: TRC DLL_INCREMENT DLL_START_POINT
232 * - CTL18: DLL_DQS_DELAY_0 DLL_DQS_DELAY_1
233 * - CTL19: DQS_OUT_SHIFT
234 * - CTL20: WR_DQS_SHIFT TRAS_MIN TRCD_INT
235 * - CTL21 TRFC
236 * - CTL26: TREF
237 * - CTL31: TDLL
238 * - CTL32: TRAS_MAX TXSNR TXSR: CTL33
239 * - CTL34: TINIT
240 * - CTL40: TPDEX
241
242 * - DLL_DQS_DELAY_BYPASS_0
243 * - DLL_DQS_DELAY_BYPASS_1
244 * - DQS_OUT_SHIFT_BYPASS
245 * - WR_DQS_SHIFT_BYPASS
246 */
247
248/**
249 * Absolute maximum EMI speed: 151.58 MHz (mDDR), 130.91 MHz (DDR)
250 * Intermediate EMI speeds: 130.91 MHz, 120.00 MHz, 64 MHz, 24 MHz
251 * Absolute minimum CPU speed: 24 MHz */
252#define IMX233_EMIFREQ_151_MHz 151580
253#define IMX233_EMIFREQ_130_MHz 130910
254#define IMX233_EMIFREQ_120_MHz 120000
255#define IMX233_EMIFREQ_64_MHz 64000
256#define IMX233_EMIFREQ_24_MHz 24000
257
258void imx233_emi_set_frequency(unsigned long freq);
259
260#endif /* __EMI_IMX233_H__ */
diff --git a/firmware/target/arm/imx233/system-imx233.c b/firmware/target/arm/imx233/system-imx233.c
index 07ab62d680..68f063512d 100644
--- a/firmware/target/arm/imx233/system-imx233.c
+++ b/firmware/target/arm/imx233/system-imx233.c
@@ -36,6 +36,7 @@
36#include "lradc-imx233.h" 36#include "lradc-imx233.h"
37#include "rtc-imx233.h" 37#include "rtc-imx233.h"
38#include "power-imx233.h" 38#include "power-imx233.h"
39#include "emi-imx233.h"
39#include "lcd.h" 40#include "lcd.h"
40#include "backlight-target.h" 41#include "backlight-target.h"
41#include "button.h" 42#include "button.h"
@@ -196,6 +197,8 @@ void set_cpu_frequency(long frequency)
196 imx233_clkctrl_set_fractional_divisor(CLK_CPU, 19); 197 imx233_clkctrl_set_fractional_divisor(CLK_CPU, 19);
197 imx233_clkctrl_set_clock_divisor(CLK_CPU, 1); 198 imx233_clkctrl_set_clock_divisor(CLK_CPU, 1);
198 imx233_clkctrl_set_bypass_pll(CLK_CPU, false); 199 imx233_clkctrl_set_bypass_pll(CLK_CPU, false);
200
201 imx233_emi_set_frequency(IMX233_EMIFREQ_130_MHz);
199 /* ref_cpu@480 MHz 202 /* ref_cpu@480 MHz
200 * ref_emi@480 MHz 203 * ref_emi@480 MHz
201 * clk_emi@130.91 MHz 204 * clk_emi@130.91 MHz
@@ -211,12 +214,30 @@ void set_cpu_frequency(long frequency)
211 imx233_clkctrl_set_fractional_divisor(CLK_CPU, 33); 214 imx233_clkctrl_set_fractional_divisor(CLK_CPU, 33);
212 imx233_clkctrl_set_clock_divisor(CLK_CPU, 1); 215 imx233_clkctrl_set_clock_divisor(CLK_CPU, 1);
213 imx233_clkctrl_set_bypass_pll(CLK_CPU, false); 216 imx233_clkctrl_set_bypass_pll(CLK_CPU, false);
217
218 imx233_emi_set_frequency(IMX233_EMIFREQ_130_MHz);
214 /* ref_cpu@480 MHz 219 /* ref_cpu@480 MHz
215 * ref_emi@480 MHz 220 * ref_emi@480 MHz
216 * clk_emi@130.91 MHz 221 * clk_emi@130.91 MHz
217 * clk_p@261.82 MHz 222 * clk_p@261.82 MHz
218 * clk_h@130.91 MHz */ 223 * clk_h@130.91 MHz */
219 break; 224 break;
225 case IMX233_CPUFREQ_64_MHz:
226 /* set VDDD to 1.050 mV (brownout at 0.975 mV) */
227 imx233_power_set_regulator(REGULATOR_VDDD, 1050, 975);
228 /* clk_h@clk_p */
229 imx233_clkctrl_set_clock_divisor(CLK_HBUS, 1);
230 /* clk_p@ref_cpu/5*18/27 */
231 imx233_clkctrl_set_fractional_divisor(CLK_CPU, 27);
232 imx233_clkctrl_set_clock_divisor(CLK_CPU, 5);
233 imx233_clkctrl_set_bypass_pll(CLK_CPU, false);
234
235 imx233_emi_set_frequency(IMX233_EMIFREQ_64_MHz);
236 /* ref_cpu@480 MHz
237 * ref_emi@480 MHz
238 * clk_emi@64 MHz
239 * clk_p@64 MHz
240 * clk_h@64 MHz */
220 default: 241 default:
221 break; 242 break;
222 } 243 }
diff --git a/firmware/target/arm/imx233/system-target.h b/firmware/target/arm/imx233/system-target.h
index 5515597570..c6073a9ae3 100644
--- a/firmware/target/arm/imx233/system-target.h
+++ b/firmware/target/arm/imx233/system-target.h
@@ -37,6 +37,18 @@
37 37
38#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) 38#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
39 39
40#define HW_DIGCTL_ARMCACHE (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x2b0))
41#define HW_DIGCTL_ARMCACHE__ITAG_SS_BP 0
42#define HW_DIGCTL_ARMCACHE__ITAG_SS_BM (3 << 0)
43#define HW_DIGCTL_ARMCACHE__DTAG_SS_BP 4
44#define HW_DIGCTL_ARMCACHE__DTAG_SS_BM (3 << 4)
45#define HW_DIGCTL_ARMCACHE__CACHE_SS_BP 8
46#define HW_DIGCTL_ARMCACHE__CACHE_SS_BM (3 << 8)
47#define HW_DIGCTL_ARMCACHE__DRTY_SS_BP 12
48#define HW_DIGCTL_ARMCACHE__DRTY_SS_BM (3 << 12)
49#define HW_DIGCTL_ARMCACHE__VALID_SS_BP 16
50#define HW_DIGCTL_ARMCACHE__VALID_SS_BM (3 << 16)
51
40/* USB Phy */ 52/* USB Phy */
41#define HW_USBPHY_BASE 0x8007C000 53#define HW_USBPHY_BASE 0x8007C000
42#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0)) 54#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
@@ -48,17 +60,17 @@
48 * Absolute maximum CPU speed: 454.74 MHz 60 * Absolute maximum CPU speed: 454.74 MHz
49 * Intermediate CPU speeds: 392.73 MHz, 360MHz, 261.82 MHz, 64 MHz 61 * Intermediate CPU speeds: 392.73 MHz, 360MHz, 261.82 MHz, 64 MHz
50 * Absolute minimum CPU speed: 24 MHz */ 62 * Absolute minimum CPU speed: 24 MHz */
51#define IMX233_CPUFREQ_454_MHz 454740000 63#define IMX233_CPUFREQ_454_MHz 454740
52#define IMX233_CPUFREQ_392_MHz 392730000 64#define IMX233_CPUFREQ_392_MHz 392730
53#define IMX233_CPUFREQ_360_MHz 360000000 65#define IMX233_CPUFREQ_360_MHz 360000
54#define IMX233_CPUFREQ_261_MHz 261820000 66#define IMX233_CPUFREQ_261_MHz 261820
55#define IMX233_CPUFREQ_64_MHz 64000000 67#define IMX233_CPUFREQ_64_MHz 64000
56#define IMX233_CPUFREQ_24_MHz 24000000 68#define IMX233_CPUFREQ_24_MHz 24000
57 69
58#define CPUFREQ_DEFAULT IMX233_CPUFREQ_261_MHz 70#define CPUFREQ_DEFAULT IMX233_CPUFREQ_64_MHz
59#define CPUFREQ_NORMAL IMX233_CPUFREQ_261_MHz 71#define CPUFREQ_NORMAL IMX233_CPUFREQ_64_MHz
60#define CPUFREQ_MAX IMX233_CPUFREQ_454_MHz 72#define CPUFREQ_MAX IMX233_CPUFREQ_454_MHz
61#define CPUFREQ_SLEEP IMX233_CPUFREQ_261_MHz 73#define CPUFREQ_SLEEP IMX233_CPUFREQ_64_MHz
62 74
63void udelay(unsigned us); 75void udelay(unsigned us);
64bool imx233_us_elapsed(uint32_t ref, unsigned us_delay); 76bool imx233_us_elapsed(uint32_t ref, unsigned us_delay);