summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-06 03:23:51 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-06 03:23:51 +0000
commita36a498c577ae5c9daa8487c8440df46d325bab3 (patch)
treeba8a35620ee10da2a7e1d6e6ed9234f0f35647d9
parent8fd3ec97271001d0b50d4404f5891c9a4e77d960 (diff)
downloadrockbox-a36a498c577ae5c9daa8487c8440df46d325bab3.tar.gz
rockbox-a36a498c577ae5c9daa8487c8440df46d325bab3.zip
i.MX31/Gigabeat S: This should fix stability problems. One problem was to start using the DVFS controller properly so that interrupts will be masked at the lowest and highest frequency indexes. Millions of useless interrupts were occurring at 132MHz because its index was 2, not 3, which masks it automatically when it can't go slower. Stopping the flood was enough to actually see the difference in general. IRQ must be disabled when fiddling with the CCM registers and only enabled when waiting for voltage ramp as having them enables also causes spurious DVFS ints. Implement interruptible ISR pro/epilogue more safely (always using IRQ stack even in SVC mode handling). Fix an improper inequality in DVFS code (which set regs for down when going up and v.v.). Misc. support changes. Have internal tables take less RAM.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25837 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/imx31/avic-imx31.c15
-rw-r--r--firmware/target/arm/imx31/avic-imx31.h33
-rw-r--r--firmware/target/arm/imx31/debug-imx31.c12
-rw-r--r--firmware/target/arm/imx31/dvfs_dptc-imx31.c41
-rw-r--r--firmware/target/arm/imx31/dvfs_dptc-imx31.h10
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/dvfs_dptc_tables-target.h224
6 files changed, 178 insertions, 157 deletions
diff --git a/firmware/target/arm/imx31/avic-imx31.c b/firmware/target/arm/imx31/avic-imx31.c
index 51ba14d0b3..e349c97d82 100644
--- a/firmware/target/arm/imx31/avic-imx31.c
+++ b/firmware/target/arm/imx31/avic-imx31.c
@@ -119,8 +119,10 @@ void avic_init(void)
119 for (i = 0; i < 8; i++) 119 for (i = 0; i < 8; i++)
120 avic->nipriority[i] = 0; 120 avic->nipriority[i] = 0;
121 121
122 /* Set NM bit to enable VIC */ 122 /* Set NM bit to enable VIC. Mask fast interrupts. Core arbiter rise
123 avic->intcntl |= AVIC_INTCNTL_NM; 123 * for normal interrupts (for lowest latency). */
124 avic->intcntl |= AVIC_INTCNTL_NM | AVIC_INTCNTL_FIDIS |
125 AVIC_INTCNTL_NIAD;
124 126
125 /* Enable VE bit in CP15 Control reg to enable VIC */ 127 /* Enable VE bit in CP15 Control reg to enable VIC */
126 asm volatile ( 128 asm volatile (
@@ -213,7 +215,12 @@ void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype)
213 restore_interrupt(oldstatus); 215 restore_interrupt(oldstatus);
214} 216}
215 217
216void avic_set_ni_level(unsigned int level) 218void avic_set_ni_level(int level)
217{ 219{
218 AVIC_NIMASK = level > 0x1f ? 0x1f : level; 220 if (level < 0)
221 level = 0x1f; /* -1 */
222 else if (level > 15)
223 level = 15;
224
225 AVIC_NIMASK = level;
219} 226}
diff --git a/firmware/target/arm/imx31/avic-imx31.h b/firmware/target/arm/imx31/avic-imx31.h
index 43fd726db3..ba9e50652d 100644
--- a/firmware/target/arm/imx31/avic-imx31.h
+++ b/firmware/target/arm/imx31/avic-imx31.h
@@ -214,14 +214,16 @@ void avic_set_int_priority(enum IMX31_INT_LIST ints,
214void avic_disable_int(enum IMX31_INT_LIST ints); 214void avic_disable_int(enum IMX31_INT_LIST ints);
215void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype); 215void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype);
216 216
217#define AVIC_NIL_DISABLE 0xf 217#define AVIC_NIL_DISABLE 15
218#define AVIC_NIL_ENABLE 0x1f 218#define AVIC_NIL_ENABLE (-1)
219void avic_set_ni_level(unsigned int level); 219void avic_set_ni_level(int level);
220 220
221 221
222/* Call a service routine while allowing preemption by interrupts of higher 222/* Call a service routine while allowing preemption by interrupts of higher
223 * priority. r4-r7 must be preserved for epilogue code to restore context. */ 223 * priority. Avoid using any app or other SVC stack by doing it with a mini
224#define AVIC_NESTED_NI_CALL_PROLOGUE(prio) \ 224 * "stack on irq stack". Avoid actually enabling IRQ until the routine
225 * decides to do so; epilogue code will always disable them again. */
226#define AVIC_NESTED_NI_CALL_PROLOGUE(prio, stacksize) \
225({ asm volatile ( \ 227({ asm volatile ( \
226 "sub lr, lr, #4 \n" /* prepare return address */ \ 228 "sub lr, lr, #4 \n" /* prepare return address */ \
227 "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \ 229 "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \
@@ -230,18 +232,25 @@ void avic_set_ni_level(unsigned int level);
230 "mov r1, %0 \n" /* load interrupt level */ \ 232 "mov r1, %0 \n" /* load interrupt level */ \
231 "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \ 233 "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \
232 "str r1, [r0, #0x04] \n" /* set interrupt level */ \ 234 "str r1, [r0, #0x04] \n" /* set interrupt level */ \
233 "cpsie i, #0x13 \n" /* change to SVC mode, unmask IRQ */ \ 235 "mov r0, sp \n" /* grab IRQ stack */ \
234 "stmfd sp!, { r2, lr } \n" /* push NIMASK and LR on SVC stack */ \ 236 "sub sp, sp, %1 \n" /* allocate space for routine to SP_irq */ \
235 : : "i"(prio)); }) 237 "cps #0x13 \n" /* change to SVC mode */ \
238 "mov r1, sp \n" /* save SP_svc */ \
239 "mov sp, r0 \n" /* switch to SP_irq *copy* */ \
240 "stmfd sp!, { r1, r2, lr } \n" /* push SP_svc, NIMASK and LR_svc */ \
241 : : "i"(prio), "i"(stacksize)); })
236 242
237#define AVIC_NESTED_NI_CALL_EPILOGUE() \ 243#define AVIC_NESTED_NI_CALL_EPILOGUE(stacksize) \
238({ asm volatile ( \ 244({ asm volatile ( \
239 "ldmfd sp!, { r2, lr } \n" /* pop original LR and NIMASK */ \ 245 "cpsid i \n" /* disable IRQ */ \
240 "cpsid i, #0x12 \n" /* return to IRQ mode, mask IRQ */ \ 246 "ldmfd sp!, { r1, r2, lr } \n" /* pop SP_svc, NIMASK and LR_svc */ \
247 "mov sp, r1 \n" /* restore SP_svc */ \
248 "cps #0x12 \n" /* return to IRQ mode */ \
249 "add sp, sp, %0 \n" /* deallocate routine space */ \
241 "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \ 250 "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \
242 "str r2, [r0, #0x04] \n" /* restore NIMASK */ \ 251 "str r2, [r0, #0x04] \n" /* restore NIMASK */ \
243 "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \ 252 "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \
244 "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \ 253 "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \
245 ); }) 254 : : "i"(stacksize)); })
246 255
247#endif /* AVIC_IMX31_H */ 256#endif /* AVIC_IMX31_H */
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c
index 2c4f8b4023..783ba728a6 100644
--- a/firmware/target/arm/imx31/debug-imx31.c
+++ b/firmware/target/arm/imx31/debug-imx31.c
@@ -40,8 +40,10 @@ bool __dbg_hw_info(void)
40 unsigned int freq; 40 unsigned int freq;
41 uint32_t regval; 41 uint32_t regval;
42 42
43 extern volatile unsigned int dvfs_nr_dn, dvfs_nr_up, dvfs_nr_pnc; 43 extern volatile unsigned int dvfs_nr_dn, dvfs_nr_up,
44 extern volatile unsigned int dptc_nr_dn, dptc_nr_up, dptc_nr_pnc; 44 dvfs_nr_pnc, dvfs_nr_no;
45 extern volatile unsigned int dptc_nr_dn, dptc_nr_up,
46 dptc_nr_pnc, dptc_nr_no;
45 47
46 lcd_clear_display(); 48 lcd_clear_display();
47 lcd_setfont(FONT_SYSFIXED); 49 lcd_setfont(FONT_SYSFIXED);
@@ -119,13 +121,15 @@ bool __dbg_hw_info(void)
119 lcd_putsf(0, line++, "cpu_frequency: %ld Hz", cpu_frequency); 121 lcd_putsf(0, line++, "cpu_frequency: %ld Hz", cpu_frequency);
120 122
121 lcd_putsf(0, line++, "dvfs_level: %u", dvfs_get_level()); 123 lcd_putsf(0, line++, "dvfs_level: %u", dvfs_get_level());
122 lcd_putsf(0, line++, "dvfs d|u|p: %u %u %u", dvfs_nr_dn, dvfs_nr_up, dvfs_nr_pnc); 124 lcd_putsf(0, line++, "dvfs d|u|p|n: %u %u %u %u",
125 dvfs_nr_dn, dvfs_nr_up, dvfs_nr_pnc, dvfs_nr_no);
123 regval = dvfs_dptc_get_voltage(); 126 regval = dvfs_dptc_get_voltage();
124 lcd_putsf(0, line++, "cpu_voltage: %d.%03d V", regval / 1000, 127 lcd_putsf(0, line++, "cpu_voltage: %d.%03d V", regval / 1000,
125 regval % 1000); 128 regval % 1000);
126 129
127 lcd_putsf(0, line++, "dptc_wp: %u", dptc_get_wp()); 130 lcd_putsf(0, line++, "dptc_wp: %u", dptc_get_wp());
128 lcd_putsf(0, line++, "dptc d|u|p: %u %u %u", dptc_nr_dn, dptc_nr_up, dptc_nr_pnc); 131 lcd_putsf(0, line++, "dptc d|u|p|n: %u %u %u %u",
132 dptc_nr_dn, dptc_nr_up, dptc_nr_pnc, dptc_nr_no);
129 lcd_putsf(0, line++, "DVCR0,1: %08lX %08lX", CCM_DCVR0, CCM_DCVR1); 133 lcd_putsf(0, line++, "DVCR0,1: %08lX %08lX", CCM_DCVR0, CCM_DCVR1);
130 lcd_putsf(0, line++, "DVCR2,3: %08lX %08lX", CCM_DCVR2, CCM_DCVR3); 134 lcd_putsf(0, line++, "DVCR2,3: %08lX %08lX", CCM_DCVR2, CCM_DCVR3);
131 lcd_putsf(0, line++, "SWITCHERS0: %08lX", mc13783_read(MC13783_SWITCHERS0)); 135 lcd_putsf(0, line++, "SWITCHERS0: %08lX", mc13783_read(MC13783_SWITCHERS0));
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.c b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
index 680b015c81..cae9a384c9 100644
--- a/firmware/target/arm/imx31/dvfs_dptc-imx31.c
+++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
@@ -72,6 +72,7 @@ static bool dvfs_running = false; /* Has driver enabled DVFS? */
72unsigned int dvfs_nr_dn = 0; 72unsigned int dvfs_nr_dn = 0;
73unsigned int dvfs_nr_up = 0; 73unsigned int dvfs_nr_up = 0;
74unsigned int dvfs_nr_pnc = 0; 74unsigned int dvfs_nr_pnc = 0;
75unsigned int dvfs_nr_no = 0;
75 76
76static void dvfs_stop(void); 77static void dvfs_stop(void);
77 78
@@ -83,7 +84,7 @@ static inline void wait_for_dvfs_update_en(void)
83} 84}
84 85
85 86
86static void do_dvfs_update(unsigned int level) 87static void do_dvfs_update(unsigned int level, bool in_isr)
87{ 88{
88 const struct dvfs_clock_table_entry *setting = &dvfs_clock_table[level]; 89 const struct dvfs_clock_table_entry *setting = &dvfs_clock_table[level];
89 unsigned long pmcr0 = CCM_PMCR0; 90 unsigned long pmcr0 = CCM_PMCR0;
@@ -96,7 +97,7 @@ static void do_dvfs_update(unsigned int level)
96 97
97 pmcr0 &= ~CCM_PMCR0_VSCNT; 98 pmcr0 &= ~CCM_PMCR0_VSCNT;
98 99
99 if (level > ((pmcr0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS)) 100 if (level < ((pmcr0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS))
100 { 101 {
101 pmcr0 |= CCM_PMCR0_UDSC; /* Up scaling, increase */ 102 pmcr0 |= CCM_PMCR0_UDSC; /* Up scaling, increase */
102 pmcr0 |= setting->vscnt << CCM_PMCR0_VSCNT_POS; 103 pmcr0 |= setting->vscnt << CCM_PMCR0_VSCNT_POS;
@@ -126,7 +127,15 @@ static void do_dvfs_update(unsigned int level)
126 } 127 }
127 128
128 CCM_PMCR0 = pmcr0; 129 CCM_PMCR0 = pmcr0;
130 /* Note: changes to frequency with ints unmaked seem to cause spurious
131 * DVFS interrupts with value CCM_PMCR0_FSVAI_NO_INT. These aren't
132 * supposed to happen. Only do the lengthy delay with them enabled iff
133 * called from the IRQ handler. */
134 if (in_isr)
135 enable_irq();
129 udelay(100); /* Software wait for voltage ramp-up */ 136 udelay(100); /* Software wait for voltage ramp-up */
137 if (in_isr)
138 disable_irq();
130 CCM_PDR0 = setting->pdr_val; 139 CCM_PDR0 = setting->pdr_val;
131 140
132 if (!(pmcr0 & CCM_PMCR0_DFSUP_POST_DIVIDERS)) 141 if (!(pmcr0 & CCM_PMCR0_DFSUP_POST_DIVIDERS))
@@ -160,7 +169,7 @@ static void set_current_dvfs_level(unsigned int level)
160 169
161 wait_for_dvfs_update_en(); 170 wait_for_dvfs_update_en();
162 171
163 do_dvfs_update(level); 172 do_dvfs_update(level, false);
164 173
165 wait_for_dvfs_update_en(); 174 wait_for_dvfs_update_en();
166 175
@@ -191,7 +200,8 @@ static void __attribute__((used)) dvfs_int(void)
191 200
192 /* Upon the DECREASE event, the frequency will be changed to the next 201 /* Upon the DECREASE event, the frequency will be changed to the next
193 * higher state index. */ 202 * higher state index. */
194 level++; 203 while (((1u << ++level) & DVFS_LEVEL_MASK) == 0);
204
195 dvfs_nr_dn++; 205 dvfs_nr_dn++;
196 break; 206 break;
197 207
@@ -202,7 +212,8 @@ static void __attribute__((used)) dvfs_int(void)
202 212
203 /* Upon the INCREASE event, the frequency will be changed to the next 213 /* Upon the INCREASE event, the frequency will be changed to the next
204 * lower state index. */ 214 * lower state index. */
205 level--; 215 while (((1u << --level) & DVFS_LEVEL_MASK) == 0);
216
206 dvfs_nr_up++; 217 dvfs_nr_up++;
207 break; 218 break;
208 219
@@ -218,11 +229,11 @@ static void __attribute__((used)) dvfs_int(void)
218 break; 229 break;
219 230
220 case CCM_PMCR0_FSVAI_NO_INT: 231 case CCM_PMCR0_FSVAI_NO_INT:
221 default: 232 dvfs_nr_no++;
222 return; /* Do nothing. Freq change is not required */ 233 return; /* Do nothing. Freq change is not required */
223 } /* end switch */ 234 } /* end switch */
224 235
225 do_dvfs_update(level); 236 do_dvfs_update(level, true);
226} 237}
227 238
228 239
@@ -230,9 +241,9 @@ static void __attribute__((used)) dvfs_int(void)
230static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) 241static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void)
231{ 242{
232 /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */ 243 /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */
233 AVIC_NESTED_NI_CALL_PROLOGUE(INT_PRIO_DVFS); 244 AVIC_NESTED_NI_CALL_PROLOGUE(INT_PRIO_DVFS, 32*4);
234 asm volatile ("bl dvfs_int"); 245 asm volatile ("bl dvfs_int");
235 AVIC_NESTED_NI_CALL_EPILOGUE(); 246 AVIC_NESTED_NI_CALL_EPILOGUE(32*4);
236} 247}
237 248
238 249
@@ -281,7 +292,7 @@ static void dvfs_init(void)
281 imx31_regmod32(&CCM_LTR0, 292 imx31_regmod32(&CCM_LTR0,
282 DVFS_UPTHR << CCM_LTR0_UPTHR_POS | 293 DVFS_UPTHR << CCM_LTR0_UPTHR_POS |
283 DVFS_DNTHR << CCM_LTR0_DNTHR_POS | 294 DVFS_DNTHR << CCM_LTR0_DNTHR_POS |
284 DVFS_DIV3CK, 295 DVFS_DIV3CK << CCM_LTR0_DIV3CK_POS,
285 CCM_LTR0_UPTHR | CCM_LTR0_DNTHR | CCM_LTR0_DIV3CK); 296 CCM_LTR0_UPTHR | CCM_LTR0_DNTHR | CCM_LTR0_DIV3CK);
286 297
287 /* Set up LTR1. */ 298 /* Set up LTR1. */
@@ -356,7 +367,7 @@ static void dvfs_stop(void)
356 { 367 {
357 /* Set default frequency level */ 368 /* Set default frequency level */
358 wait_for_dvfs_update_en(); 369 wait_for_dvfs_update_en();
359 do_dvfs_update(DVFS_LEVEL_DEFAULT); 370 do_dvfs_update(DVFS_LEVEL_DEFAULT, false);
360 wait_for_dvfs_update_en(); 371 wait_for_dvfs_update_en();
361 } 372 }
362 373
@@ -379,6 +390,7 @@ static bool dptc_running = false; /* Has driver enabled DPTC? */
379unsigned int dptc_nr_dn = 0; 390unsigned int dptc_nr_dn = 0;
380unsigned int dptc_nr_up = 0; 391unsigned int dptc_nr_up = 0;
381unsigned int dptc_nr_pnc = 0; 392unsigned int dptc_nr_pnc = 0;
393unsigned int dptc_nr_no = 0;
382 394
383static struct spi_transfer_desc dptc_pmic_xfer; /* Transfer descriptor */ 395static struct spi_transfer_desc dptc_pmic_xfer; /* Transfer descriptor */
384static const unsigned char dptc_pmic_regs[2] = /* Register subaddresses */ 396static const unsigned char dptc_pmic_regs[2] = /* Register subaddresses */
@@ -492,7 +504,12 @@ static void dptc_new_wp(unsigned int wp)
492/* Interrupt vector for DPTC */ 504/* Interrupt vector for DPTC */
493static __attribute__((interrupt("IRQ"))) void CCM_CLK_HANDLER(void) 505static __attribute__((interrupt("IRQ"))) void CCM_CLK_HANDLER(void)
494{ 506{
495 dptc_int(CCM_PMCR0); 507 unsigned long pmcr0 = CCM_PMCR0;
508
509 if ((pmcr0 & CCM_PMCR0_PTVAI) == CCM_PMCR0_PTVAI_NO_INT)
510 dptc_nr_no++;
511
512 dptc_int(pmcr0);
496} 513}
497 514
498 515
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.h b/firmware/target/arm/imx31/dvfs_dptc-imx31.h
index 2bf6114a11..844fd6ebff 100644
--- a/firmware/target/arm/imx31/dvfs_dptc-imx31.h
+++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.h
@@ -107,6 +107,16 @@ struct dvfs_lt_signal_descriptor
107 uint8_t detect : 1; /* 1 = edge-detected */ 107 uint8_t detect : 1; /* 1 = edge-detected */
108}; 108};
109 109
110#define DVFS_NUM_LEVELS 4
111#define DPTC_NUM_WP 17
112
113/* 0 and 3 are *required*. DVFS hardware depends upon DVSUP pins showing
114 * minimum (11) and maximum (00) levels or interrupts will be continuously
115 * asserted. */
116#define DVFS_LEVEL_0 (1u << 0)
117#define DVFS_LEVEL_1 (1u << 1)
118#define DVFS_LEVEL_2 (1u << 2)
119#define DVFS_LEVEL_3 (1u << 3)
110 120
111extern long cpu_voltage_setting; 121extern long cpu_voltage_setting;
112 122
diff --git a/firmware/target/arm/imx31/gigabeat-s/dvfs_dptc_tables-target.h b/firmware/target/arm/imx31/gigabeat-s/dvfs_dptc_tables-target.h
index 4876736a2b..7fc7b56dff 100644
--- a/firmware/target/arm/imx31/gigabeat-s/dvfs_dptc_tables-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/dvfs_dptc_tables-target.h
@@ -24,12 +24,12 @@
24#define _DVFS_DPTC_TARGET_H_ 24#define _DVFS_DPTC_TARGET_H_
25 25
26#define DVFS_LEVEL_DEFAULT 1 /* 264 MHz - safe frequency for 1.35V */ 26#define DVFS_LEVEL_DEFAULT 1 /* 264 MHz - safe frequency for 1.35V */
27#define DVFS_NUM_LEVELS 3 /* 528 MHz, 264 MHz, 132 MHz */
28#define DVFS_NO_PWRRDY /* PWRRDY is connected to different SoC port */ 27#define DVFS_NO_PWRRDY /* PWRRDY is connected to different SoC port */
28#define DVFS_LEVEL_MASK (DVFS_LEVEL_0 | DVFS_LEVEL_1 | DVFS_LEVEL_3)
29 29
30#define DPTC_WP_DEFAULT 1 /* 1.600, 1.350, 1.350 */ 30#define DPTC_WP_DEFAULT 1 /* 1.600, 1.350, 1.350 */
31#define DPTC_WP_PANIC 3 /* Up to minimum for > 400 MHz */ 31#define DPTC_WP_PANIC 3 /* Up to minimum for > 400 MHz */
32#define DPTC_NUM_WP 17 32
33 33
34#define VOLTAGE_SETTING_MIN MC13783_SW_1_350 34#define VOLTAGE_SETTING_MIN MC13783_SW_1_350
35#define VOLTAGE_SETTING_MAX MC13783_SW_1_625 35#define VOLTAGE_SETTING_MAX MC13783_SW_1_625
@@ -54,7 +54,7 @@
54 * and the values have an additional division or the comments in the BSP are 54 * and the values have an additional division or the comments in the BSP are
55 * incorrect. 55 * incorrect.
56 */ 56 */
57#define DVFS_DIV3CK CCM_LTR0_DIV3CK_131072 57#define DVFS_DIV3CK 0x3
58 58
59/* UPCNT defines the amount of times the up threshold should be exceeded 59/* UPCNT defines the amount of times the up threshold should be exceeded
60 * before DVFS will trigger frequency increase request. */ 60 * before DVFS will trigger frequency increase request. */
@@ -109,146 +109,120 @@ dvfs_dptc_voltage_table[DPTC_NUM_WP] =
109 { { MC13783_SW_1_225, MC13783_SW_1_350, MC13783_SW_1_350, MC13783_SW_1_350 } }, 109 { { MC13783_SW_1_225, MC13783_SW_1_350, MC13783_SW_1_350, MC13783_SW_1_350 } },
110}; 110};
111 111
112#if 1 112#if CONFIG_CKIH_FREQ == 27000000
113/* For 27 MHz PLL reference clock */ 113/* For 27 MHz PLL reference clock */
114static const struct dptc_dcvr_table_entry 114static const struct dptc_dcvr_table_entry
115dptc_dcvr_table[DVFS_NUM_LEVELS][DPTC_NUM_WP] = 115dptc_dcvr_table_0[DPTC_NUM_WP] =
116{ 116 /* DCVR0 DCVR1 DCVR2 DCVR3 */
117 /* DCVR0 DCVR1 DCVR2 DCVR3 */ 117{ /* 528 MHz */
118 { /* 528 MHz */ 118 { 0xffc00000, 0x90400000, 0xffc00000, 0xdd000000 },
119 { 0xffc00000, 0x90400000, 0xffc00000, 0xdd000000 }, 119 { 0xffc00000, 0x90629890, 0xffc00000, 0xdd34ed20 },
120 { 0xffc00000, 0x90629890, 0xffc00000, 0xdd34ed20 }, 120 { 0xffc00000, 0x90629890, 0xffc00000, 0xdd34ed20 },
121 { 0xffc00000, 0x90629890, 0xffc00000, 0xdd34ed20 }, 121 { 0xffc00000, 0x90629894, 0xffc00000, 0xdd74fd24 },
122 { 0xffc00000, 0x90629894, 0xffc00000, 0xdd74fd24 }, 122 { 0xffc00000, 0x90a2a894, 0xffc00000, 0xddb50d28 },
123 { 0xffc00000, 0x90a2a894, 0xffc00000, 0xddb50d28 }, 123 { 0xffc00000, 0x90e2b89c, 0xffc00000, 0xde352d30 },
124 { 0xffc00000, 0x90e2b89c, 0xffc00000, 0xde352d30 }, 124 { 0xffc00000, 0x9162d8a0, 0xffc00000, 0xdef55d38 },
125 { 0xffc00000, 0x9162d8a0, 0xffc00000, 0xdef55d38 }, 125 { 0xffc00000, 0x91e2f8a8, 0xffc00000, 0xdfb58d44 },
126 { 0xffc00000, 0x91e2f8a8, 0xffc00000, 0xdfb58d44 }, 126 { 0xffc00000, 0x926308b0, 0xffc00000, 0xe0b5cd54 },
127 { 0xffc00000, 0x926308b0, 0xffc00000, 0xe0b5cd54 }, 127 { 0xffc00000, 0x92e328bc, 0xffc00000, 0xe1f60d64 },
128 { 0xffc00000, 0x92e328bc, 0xffc00000, 0xe1f60d64 }, 128 { 0xffc00000, 0x93a358c0, 0xffc00000, 0xe3365d74 },
129 { 0xffc00000, 0x93a358c0, 0xffc00000, 0xe3365d74 }, 129 { 0xffc00000, 0xf66388cc, 0xffc00000, 0xf6768d84 },
130 { 0xffc00000, 0xf66388cc, 0xffc00000, 0xf6768d84 }, 130 { 0xffc00000, 0xf663b8d4, 0xffc00000, 0xf676dd98 },
131 { 0xffc00000, 0xf663b8d4, 0xffc00000, 0xf676dd98 }, 131 { 0xffc00000, 0xf663e8e0, 0xffc00000, 0xf6773da4 },
132 { 0xffc00000, 0xf663e8e0, 0xffc00000, 0xf6773da4 }, 132 { 0xffc00000, 0xf66418ec, 0xffc00000, 0xf6778dbc },
133 { 0xffc00000, 0xf66418ec, 0xffc00000, 0xf6778dbc }, 133 { 0xffc00000, 0xf66458fc, 0xffc00000, 0xf677edd0 },
134 { 0xffc00000, 0xf66458fc, 0xffc00000, 0xf677edd0 }, 134 { 0xffc00000, 0xf6648908, 0xffc00000, 0xf6783de8 },
135 { 0xffc00000, 0xf6648908, 0xffc00000, 0xf6783de8 }, 135};
136 136
137 }, 137static const struct dptc_dcvr_table_entry
138 { /* 264 MHz */ 138dptc_dcvr_table_1_3[DPTC_NUM_WP] =
139 { 0xffc00000, 0x90400000, 0xffc00000, 0xdd000000 }, 139 /* DCVR0 DCVR1 DCVR2 DCVR3 */
140 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 }, 140{ /* 264 MHz, 132 MHz */
141 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 }, 141 { 0xffc00000, 0x90400000, 0xffc00000, 0xdd000000 },
142 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd4d4348 }, 142 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 },
143 { 0xffc00000, 0x9088b228, 0xffc00000, 0xdd8d434c }, 143 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 },
144 { 0xffc00000, 0x90c8b228, 0xffc00000, 0xde0d534c }, 144 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd4d4348 },
145 { 0xffc00000, 0x9148b228, 0xffc00000, 0xdecd5350 }, 145 { 0xffc00000, 0x9088b228, 0xffc00000, 0xdd8d434c },
146 { 0xffc00000, 0x91c8c22c, 0xffc00000, 0xdf8d6354 }, 146 { 0xffc00000, 0x90c8b228, 0xffc00000, 0xde0d534c },
147 { 0xffc00000, 0x9248d22c, 0xffc00000, 0xe08d7354 }, 147 { 0xffc00000, 0x9148b228, 0xffc00000, 0xdecd5350 },
148 { 0xffc00000, 0x92c8d230, 0xffc00000, 0xe1cd8358 }, 148 { 0xffc00000, 0x91c8c22c, 0xffc00000, 0xdf8d6354 },
149 { 0xffc00000, 0x9388e234, 0xffc00000, 0xe30d935c }, 149 { 0xffc00000, 0x9248d22c, 0xffc00000, 0xe08d7354 },
150 { 0xffc00000, 0xf648e234, 0xffc00000, 0xf64db364 }, 150 { 0xffc00000, 0x92c8d230, 0xffc00000, 0xe1cd8358 },
151 { 0xffc00000, 0xf648f238, 0xffc00000, 0xf64dc368 }, 151 { 0xffc00000, 0x9388e234, 0xffc00000, 0xe30d935c },
152 { 0xffc00000, 0xf648f23c, 0xffc00000, 0xf64dd36c }, 152 { 0xffc00000, 0xf648e234, 0xffc00000, 0xf64db364 },
153 { 0xffc00000, 0xf649023c, 0xffc00000, 0xf64de370 }, 153 { 0xffc00000, 0xf648f238, 0xffc00000, 0xf64dc368 },
154 { 0xffc00000, 0xf649123c, 0xffc00000, 0xf64df374 }, 154 { 0xffc00000, 0xf648f23c, 0xffc00000, 0xf64dd36c },
155 { 0xffc00000, 0xf6492240, 0xffc00000, 0xf64e1378 }, 155 { 0xffc00000, 0xf649023c, 0xffc00000, 0xf64de370 },
156 { 0xffc00000, 0xf649123c, 0xffc00000, 0xf64df374 },
157 { 0xffc00000, 0xf6492240, 0xffc00000, 0xf64e1378 },
156 158
157 },
158 { /* 132 MHz */
159 { 0xffc00000, 0x90400000, 0xffc00000, 0xdd000000 },
160 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 },
161 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd0d4348 },
162 { 0xffc00000, 0x9048a224, 0xffc00000, 0xdd4d4348 },
163 { 0xffc00000, 0x9088b228, 0xffc00000, 0xdd8d434c },
164 { 0xffc00000, 0x90c8b228, 0xffc00000, 0xde0d534c },
165 { 0xffc00000, 0x9148b228, 0xffc00000, 0xdecd5350 },
166 { 0xffc00000, 0x91c8c22c, 0xffc00000, 0xdf8d6354 },
167 { 0xffc00000, 0x9248d22c, 0xffc00000, 0xe08d7354 },
168 { 0xffc00000, 0x92c8d230, 0xffc00000, 0xe1cd8358 },
169 { 0xffc00000, 0x9388e234, 0xffc00000, 0xe30d935c },
170 { 0xffc00000, 0xf648e234, 0xffc00000, 0xf64db364 },
171 { 0xffc00000, 0xf648f238, 0xffc00000, 0xf64dc368 },
172 { 0xffc00000, 0xf648f23c, 0xffc00000, 0xf64dd36c },
173 { 0xffc00000, 0xf649023c, 0xffc00000, 0xf64de370 },
174 { 0xffc00000, 0xf649123c, 0xffc00000, 0xf64df374 },
175 { 0xffc00000, 0xf6492240, 0xffc00000, 0xf64e1378 },
176 },
177}; 159};
178#else/* For 26 MHz PLL reference clock */ 160#else/* For 26 MHz PLL reference clock */
179static const struct dptc_dcvr_table_entry 161static const struct dptc_dcvr_table_entry
180dptc_dcvr_table[DVFS_NUM_LEVELS][DPTC_NUM_WP] = 162dptc_dcvr_table_0[DPTC_NUM_WP] =
181{ 163 /* DCVR0 DCVR1 DCVR2 DCVR3 */
182 /* DCVR0 DCVR1 DCVR2 DCVR3 */ 164{ /* 528 MHz */
183 { /* 528 MHz */ 165 { 0xffc00000, 0x95c00000, 0xffc00000, 0xe5800000 },
184 { 0xffc00000, 0x95c00000, 0xffc00000, 0xe5800000 }, 166 { 0xffc00000, 0x95e3e8e4, 0xffc00000, 0xe5b6fda0 },
185 { 0xffc00000, 0x95e3e8e4, 0xffc00000, 0xe5b6fda0 }, 167 { 0xffc00000, 0x95e3e8e4, 0xffc00000, 0xe5b6fda0 },
186 { 0xffc00000, 0x95e3e8e4, 0xffc00000, 0xe5b6fda0 }, 168 { 0xffc00000, 0x95e3e8e8, 0xffc00000, 0xe5f70da4 },
187 { 0xffc00000, 0x95e3e8e8, 0xffc00000, 0xe5f70da4 }, 169 { 0xffc00000, 0x9623f8e8, 0xffc00000, 0xe6371da8 },
188 { 0xffc00000, 0x9623f8e8, 0xffc00000, 0xe6371da8 }, 170 { 0xffc00000, 0x966408f0, 0xffc00000, 0xe6b73db0 },
189 { 0xffc00000, 0x966408f0, 0xffc00000, 0xe6b73db0 }, 171 { 0xffc00000, 0x96e428f4, 0xffc00000, 0xe7776dbc },
190 { 0xffc00000, 0x96e428f4, 0xffc00000, 0xe7776dbc }, 172 { 0xffc00000, 0x976448fc, 0xffc00000, 0xe8379dc8 },
191 { 0xffc00000, 0x976448fc, 0xffc00000, 0xe8379dc8 }, 173 { 0xffc00000, 0x97e46904, 0xffc00000, 0xe977ddd8 },
192 { 0xffc00000, 0x97e46904, 0xffc00000, 0xe977ddd8 }, 174 { 0xffc00000, 0x98a48910, 0xffc00000, 0xeab81de8 },
193 { 0xffc00000, 0x98a48910, 0xffc00000, 0xeab81de8 }, 175 { 0xffc00000, 0x9964b918, 0xffc00000, 0xebf86df8 },
194 { 0xffc00000, 0x9964b918, 0xffc00000, 0xebf86df8 }, 176 { 0xffc00000, 0xffe4e924, 0xffc00000, 0xfff8ae08 },
195 { 0xffc00000, 0xffe4e924, 0xffc00000, 0xfff8ae08 }, 177 { 0xffc00000, 0xffe5192c, 0xffc00000, 0xfff8fe1c },
196 { 0xffc00000, 0xffe5192c, 0xffc00000, 0xfff8fe1c }, 178 { 0xffc00000, 0xffe54938, 0xffc00000, 0xfff95e2c },
197 { 0xffc00000, 0xffe54938, 0xffc00000, 0xfff95e2c }, 179 { 0xffc00000, 0xffe57944, 0xffc00000, 0xfff9ae44 },
198 { 0xffc00000, 0xffe57944, 0xffc00000, 0xfff9ae44 }, 180 { 0xffc00000, 0xffe5b954, 0xffc00000, 0xfffa0e58 },
199 { 0xffc00000, 0xffe5b954, 0xffc00000, 0xfffa0e58 }, 181 { 0xffc00000, 0xffe5e960, 0xffc00000, 0xfffa6e70 },
200 { 0xffc00000, 0xffe5e960, 0xffc00000, 0xfffa6e70 }, 182};
201 }, 183
202 { /* 264 MHz */ 184static const struct dptc_dcvr_table_entry
203 { 0xffc00000, 0x95c00000, 0xffc00000, 0xe5800000 }, 185dptc_dcvr_table_1_3[DPTC_NUM_WP] =
204 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 }, 186 /* DCVR0 DCVR1 DCVR2 DCVR3 */
205 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 }, 187{ /* 264 MHz, 132 MHz */
206 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe5cdc368 }, 188 { 0xffc00000, 0x95c00000, 0xffc00000, 0xe5800000 },
207 { 0xffc00000, 0x9609023c, 0xffc00000, 0xe60dc36c }, 189 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 },
208 { 0xffc00000, 0x9649023c, 0xffc00000, 0xe68dd36c }, 190 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 },
209 { 0xffc00000, 0x96c9023c, 0xffc00000, 0xe74dd370 }, 191 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe5cdc368 },
210 { 0xffc00000, 0x97491240, 0xffc00000, 0xe80de374 }, 192 { 0xffc00000, 0x9609023c, 0xffc00000, 0xe60dc36c },
211 { 0xffc00000, 0x97c92240, 0xffc00000, 0xe94df374 }, 193 { 0xffc00000, 0x9649023c, 0xffc00000, 0xe68dd36c },
212 { 0xffc00000, 0x98892244, 0xffc00000, 0xea8e0378 }, 194 { 0xffc00000, 0x96c9023c, 0xffc00000, 0xe74dd370 },
213 { 0xffc00000, 0x99493248, 0xffc00000, 0xebce137c }, 195 { 0xffc00000, 0x97491240, 0xffc00000, 0xe80de374 },
214 { 0xffc00000, 0xffc93248, 0xffc00000, 0xffce3384 }, 196 { 0xffc00000, 0x97c92240, 0xffc00000, 0xe94df374 },
215 { 0xffc00000, 0xffc9424c, 0xffc00000, 0xffce4388 }, 197 { 0xffc00000, 0x98892244, 0xffc00000, 0xea8e0378 },
216 { 0xffc00000, 0xffc95250, 0xffc00000, 0xffce538c }, 198 { 0xffc00000, 0x99493248, 0xffc00000, 0xebce137c },
217 { 0xffc00000, 0xffc96250, 0xffc00000, 0xffce7390 }, 199 { 0xffc00000, 0xffc93248, 0xffc00000, 0xffce3384 },
218 { 0xffc00000, 0xffc97254, 0xffc00000, 0xffce8394 }, 200 { 0xffc00000, 0xffc9424c, 0xffc00000, 0xffce4388 },
219 { 0xffc00000, 0xffc98258, 0xffc00000, 0xffcea39c }, 201 { 0xffc00000, 0xffc95250, 0xffc00000, 0xffce538c },
220 }, 202 { 0xffc00000, 0xffc96250, 0xffc00000, 0xffce7390 },
221 { /* 132 MHz */ 203 { 0xffc00000, 0xffc97254, 0xffc00000, 0xffce8394 },
222 { 0xffc00000, 0x95c00000, 0xffc00000, 0xe5800000 }, 204 { 0xffc00000, 0xffc98258, 0xffc00000, 0xffcea39c },
223 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 },
224 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe58dc368 },
225 { 0xffc00000, 0x95c8f238, 0xffc00000, 0xe5cdc368 },
226 { 0xffc00000, 0x9609023c, 0xffc00000, 0xe60dc36c },
227 { 0xffc00000, 0x9649023c, 0xffc00000, 0xe68dd36c },
228 { 0xffc00000, 0x96c9023c, 0xffc00000, 0xe74dd370 },
229 { 0xffc00000, 0x97491240, 0xffc00000, 0xe80de374 },
230 { 0xffc00000, 0x97c92240, 0xffc00000, 0xe94df374 },
231 { 0xffc00000, 0x98892244, 0xffc00000, 0xea8e0378 },
232 { 0xffc00000, 0x99493248, 0xffc00000, 0xebce137c },
233 { 0xffc00000, 0xffc93248, 0xffc00000, 0xffce3384 },
234 { 0xffc00000, 0xffc9424c, 0xffc00000, 0xffce4388 },
235 { 0xffc00000, 0xffc95250, 0xffc00000, 0xffce538c },
236 { 0xffc00000, 0xffc96250, 0xffc00000, 0xffce7390 },
237 { 0xffc00000, 0xffc97254, 0xffc00000, 0xffce8394 },
238 { 0xffc00000, 0xffc98258, 0xffc00000, 0xffcea39c },
239 },
240}; 205};
241#endif 206#endif
242 207
208static const struct dptc_dcvr_table_entry * const
209 dptc_dcvr_table [DVFS_NUM_LEVELS] =
210{
211 dptc_dcvr_table_0,
212 dptc_dcvr_table_1_3,
213 NULL,
214 dptc_dcvr_table_1_3,
215};
243 216
244/* For 27 MHz PLL reference clock */ 217/* For 27 MHz PLL reference clock */
245static const struct dvfs_clock_table_entry 218static const struct dvfs_clock_table_entry
246dvfs_clock_table[DVFS_NUM_LEVELS] = 219dvfs_clock_table[4] =
247{ 220{
248 /* PLL val PDR0 val PLL VSCNT */ 221 /* PLL val PDR0 val PLL VSCNT */
249 { 0x00082407, 0xff841e58, 1, 7 }, /* MCUPLL, 528 MHz, /1 = 528 MHz */ 222 { 0x00082407, 0xff841e58, 1, 7 }, /* MCUPLL, 528 MHz, /1 = 528 MHz */
250 { 0x00082407, 0xff841e59, 1, 7 }, /* MCUPLL, 528 MHz, /2 = 264 MHz */ 223 { 0x00082407, 0xff841e59, 1, 7 }, /* MCUPLL, 528 MHz, /2 = 264 MHz */
251 { 0x00082407, 0xff841e5b, 1, 7 }, /* MCUPLL, 528 MHz, /4 = 132 MHz */ 224 { 0x00082407, 0xff841e5b, 1, 7 }, /* MCUPLL, 528 MHz, /4 = 132 MHz */
225 { 0x00082407, 0xff841e5b, 1, 7 }, /* MCUPLL, 528 MHz, /4 = 132 MHz */
252}; 226};
253 227
254 228