diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-22 21:04:25 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-22 21:04:25 +0000 |
commit | 0a98e8af9d17b9b88676a1b6a3bb28c7aaddf7cd (patch) | |
tree | 1aea8aee0f4845410b2f23d73fe84b981d341278 | |
parent | 6d2e7769e2bafead0e6c8826c465ce0bbbb065ee (diff) | |
download | rockbox-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
-rw-r--r-- | firmware/target/arm/imx31/dvfs_dptc-imx31.c | 32 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c | 1 |
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 */ | |
85 | static void do_dvfs_update(unsigned int level, bool in_isr) | 85 | static 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. */ | ||
374 | static void dptc_int(unsigned long pmcr0) | 376 | static 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 */ | ||
436 | static void dptc_new_wp(unsigned int wp) | 440 | static 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 */ |