summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-01-22 21:04:25 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-01-22 21:04:25 +0000
commit0a98e8af9d17b9b88676a1b6a3bb28c7aaddf7cd (patch)
tree1aea8aee0f4845410b2f23d73fe84b981d341278 /firmware
parent6d2e7769e2bafead0e6c8826c465ce0bbbb065ee (diff)
downloadrockbox-0a98e8af9d17b9b88676a1b6a3bb28c7aaddf7cd.tar.gz
rockbox-0a98e8af9d17b9b88676a1b6a3bb28c7aaddf7cd.zip
i.MX31: Allow interrupts in thread context, not just ISR context, during the lengthy DVFS voltage ramp-up delay. Also, explicitly enable them just before mc13783_init since that does anyway because of the PMIC write inside it.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29116 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/imx31/dvfs_dptc-imx31.c32
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c1
2 files changed, 19 insertions, 14 deletions
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.c b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
index b78a995f87..1c4e3a923f 100644
--- a/firmware/target/arm/imx31/dvfs_dptc-imx31.c
+++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.c
@@ -81,16 +81,19 @@ static inline void wait_for_dvfs_update_en(void)
81 while (!(CCM_PMCR0 & CCM_PMCR0_UPDTEN)); 81 while (!(CCM_PMCR0 & CCM_PMCR0_UPDTEN));
82} 82}
83 83
84 84/* Do the actual frequency and DVFS pin change - always call with IRQ masked */
85static void do_dvfs_update(unsigned int level, bool in_isr) 85static void do_dvfs_update(unsigned int level)
86{ 86{
87 const struct dvfs_clock_table_entry *setting = &dvfs_clock_table[level]; 87 const struct dvfs_clock_table_entry *setting = &dvfs_clock_table[level];
88 unsigned long pmcr0 = CCM_PMCR0; 88 unsigned long pmcr0 = CCM_PMCR0;
89 int oldlevel;
89 90
90 if (pmcr0 & CCM_PMCR0_DPTEN) 91 if (pmcr0 & CCM_PMCR0_DPTEN)
91 { 92 {
92 /* Ignore voltage change request from DPTC. Voltage is *not* valid. */ 93 /* Ignore voltage change request from DPTC. Voltage is *not* valid. */
93 pmcr0 &= ~CCM_PMCR0_DPVCR; 94 pmcr0 &= ~CCM_PMCR0_DPVCR;
95 /* Mask DPTC interrupt for when called in thread context */
96 pmcr0 |= CCM_PMCR0_PTVAIM;
94 } 97 }
95 98
96 pmcr0 &= ~CCM_PMCR0_VSCNT; 99 pmcr0 &= ~CCM_PMCR0_VSCNT;
@@ -127,13 +130,10 @@ static void do_dvfs_update(unsigned int level, bool in_isr)
127 CCM_PMCR0 = pmcr0; 130 CCM_PMCR0 = pmcr0;
128 /* Note: changes to frequency with ints unmaked seem to cause spurious 131 /* Note: changes to frequency with ints unmaked seem to cause spurious
129 * DVFS interrupts with value CCM_PMCR0_FSVAI_NO_INT. These aren't 132 * DVFS interrupts with value CCM_PMCR0_FSVAI_NO_INT. These aren't
130 * supposed to happen. Only do the lengthy delay with them enabled iff 133 * supposed to happen. Only do the lengthy delay with them enabled. */
131 * called from the IRQ handler. */ 134 enable_irq();
132 if (in_isr)
133 enable_irq();
134 udelay(100); /* Software wait for voltage ramp-up */ 135 udelay(100); /* Software wait for voltage ramp-up */
135 if (in_isr) 136 disable_irq();
136 disable_irq();
137 CCM_PDR0 = setting->pdr_val; 137 CCM_PDR0 = setting->pdr_val;
138 138
139 if (!(pmcr0 & CCM_PMCR0_DFSUP_POST_DIVIDERS)) 139 if (!(pmcr0 & CCM_PMCR0_DFSUP_POST_DIVIDERS))
@@ -150,9 +150,10 @@ static void do_dvfs_update(unsigned int level, bool in_isr)
150 if (pmcr0 & CCM_PMCR0_DPTEN) 150 if (pmcr0 & CCM_PMCR0_DPTEN)
151 { 151 {
152 update_dptc_counts(level, dptc_wp); 152 update_dptc_counts(level, dptc_wp);
153 /* Enable DPTC to request voltage changes. Voltage is valid. */ 153 /* Enable DPTC to request voltage changes, unmask interrupt. */
154 CCM_PMCR0 |= CCM_PMCR0_DPVCR; 154 CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_PTVAIM) | CCM_PMCR0_DPVCR;
155 udelay(2); 155 udelay(2);
156 /* Voltage is valid. */
156 CCM_PMCR0 |= CCM_PMCR0_DPVV; 157 CCM_PMCR0 |= CCM_PMCR0_DPVV;
157 } 158 }
158} 159}
@@ -167,7 +168,7 @@ static void set_current_dvfs_level(unsigned int level)
167 168
168 wait_for_dvfs_update_en(); 169 wait_for_dvfs_update_en();
169 170
170 do_dvfs_update(level, false); 171 do_dvfs_update(level);
171 172
172 wait_for_dvfs_update_en(); 173 wait_for_dvfs_update_en();
173 174
@@ -231,7 +232,7 @@ static void __attribute__((used)) dvfs_int(void)
231 return; /* Do nothing. Freq change is not required */ 232 return; /* Do nothing. Freq change is not required */
232 } /* end switch */ 233 } /* end switch */
233 234
234 do_dvfs_update(level, true); 235 do_dvfs_update(level);
235} 236}
236 237
237 238
@@ -370,7 +371,8 @@ static void dptc_transfer_done_callback(struct spi_transfer_desc *xfer)
370} 371}
371 372
372 373
373/* Handle the DPTC interrupt and sometimes the manual setting */ 374/* Handle the DPTC interrupt and sometimes the manual setting - always call
375 * with IRQ masked. */
374static void dptc_int(unsigned long pmcr0) 376static void dptc_int(unsigned long pmcr0)
375{ 377{
376 const union dvfs_dptc_voltage_table_entry *entry; 378 const union dvfs_dptc_voltage_table_entry *entry;
@@ -433,6 +435,8 @@ static void dptc_int(unsigned long pmcr0)
433} 435}
434 436
435 437
438/* Handle setting the working point explicitly - always call with IRQ
439 * masked */
436static void dptc_new_wp(unsigned int wp) 440static void dptc_new_wp(unsigned int wp)
437{ 441{
438 dptc_wp = wp; 442 dptc_wp = wp;
@@ -550,7 +554,7 @@ void dvfs_stop(void)
550 { 554 {
551 /* Set default frequency level */ 555 /* Set default frequency level */
552 wait_for_dvfs_update_en(); 556 wait_for_dvfs_update_en();
553 do_dvfs_update(DVFS_LEVEL_DEFAULT, false); 557 do_dvfs_update(DVFS_LEVEL_DEFAULT);
554 wait_for_dvfs_update_en(); 558 wait_for_dvfs_update_en();
555 } 559 }
556 560
diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c
index f040d8fcf1..481cb467bd 100644
--- a/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c
@@ -69,6 +69,7 @@ void INIT_ATTR kernel_device_init(void)
69{ 69{
70 sdma_init(); 70 sdma_init();
71 spi_init(); 71 spi_init();
72 enable_interrupt(IRQ_FIQ_STATUS);
72 mc13783_init(); 73 mc13783_init();
73 dvfs_dptc_init(); 74 dvfs_dptc_init();
74 dvfs_wfi_monitor(true); /* Monitor the WFI signal */ 75 dvfs_wfi_monitor(true); /* Monitor the WFI signal */