diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-23 20:21:35 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-23 20:21:35 +0000 |
commit | 480c663e5b67d521f3e062fb90d10c7c5c186280 (patch) | |
tree | 688d19071afa676814b981e9338f3677f6556f3b | |
parent | 264e27d5b069104137587ba08cbae3ef301a850d (diff) | |
download | rockbox-480c663e5b67d521f3e062fb90d10c7c5c186280.tar.gz rockbox-480c663e5b67d521f3e062fb90d10c7c5c186280.zip |
i.MX31: Now that it matters because there's a debug screeen that allows changing things while running, some DVFS/DPTC stuff has to be done more carefully. Trim out some stuff and group functions better as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29122 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | bootloader/gigabeat-s.c | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/dvfs_dptc-imx31.c | 424 | ||||
-rw-r--r-- | firmware/target/arm/imx31/dvfs_dptc-imx31.h | 21 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c | 7 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx31/mc13783-imx31.c | 2 |
7 files changed, 211 insertions, 251 deletions
diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c index 06f675644c..2500496fd4 100644 --- a/bootloader/gigabeat-s.c +++ b/bootloader/gigabeat-s.c | |||
@@ -341,8 +341,6 @@ void main(void) | |||
341 | system_init(); | 341 | system_init(); |
342 | kernel_init(); | 342 | kernel_init(); |
343 | 343 | ||
344 | enable_interrupt(IRQ_FIQ_STATUS); | ||
345 | |||
346 | /* Keep button_device_init early to delay calls to button_read_device */ | 344 | /* Keep button_device_init early to delay calls to button_read_device */ |
347 | button_init_device(); | 345 | button_init_device(); |
348 | 346 | ||
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.c b/firmware/target/arm/imx31/dvfs_dptc-imx31.c index 58be2118a1..1c5ad863ce 100644 --- a/firmware/target/arm/imx31/dvfs_dptc-imx31.c +++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.c | |||
@@ -38,20 +38,28 @@ static volatile unsigned int dvfs_level = DVFS_LEVEL_DEFAULT; | |||
38 | /* The current DPTC working point */ | 38 | /* The current DPTC working point */ |
39 | static volatile unsigned int dptc_wp = DPTC_WP_DEFAULT; | 39 | static volatile unsigned int dptc_wp = DPTC_WP_DEFAULT; |
40 | 40 | ||
41 | 41 | /* Synchronize DPTC comparator value registers to new table row */ | |
42 | static void update_dptc_counts(unsigned int level, unsigned int wp) | 42 | static void update_dptc_counts(void) |
43 | { | 43 | { |
44 | int oldlevel = disable_irq_save(); | 44 | const struct dptc_dcvr_table_entry * const entry = |
45 | const struct dptc_dcvr_table_entry *entry = &dptc_dcvr_table[level][wp]; | 45 | &dptc_dcvr_table[dvfs_level][dptc_wp]; |
46 | 46 | ||
47 | CCM_DCVR0 = entry->dcvr0; | 47 | CCM_DCVR0 = entry->dcvr0; |
48 | CCM_DCVR1 = entry->dcvr1; | 48 | CCM_DCVR1 = entry->dcvr1; |
49 | CCM_DCVR2 = entry->dcvr2; | 49 | CCM_DCVR2 = entry->dcvr2; |
50 | CCM_DCVR3 = entry->dcvr3; | 50 | CCM_DCVR3 = entry->dcvr3; |
51 | |||
52 | restore_irq(oldlevel); | ||
53 | } | 51 | } |
54 | 52 | ||
53 | /* Enable DPTC and unmask interrupt. */ | ||
54 | static void enable_dptc(void) | ||
55 | { | ||
56 | /* Enable DPTC, assert voltage change request. */ | ||
57 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_PTVAIM) | CCM_PMCR0_DPTEN | | ||
58 | CCM_PMCR0_DPVCR; | ||
59 | udelay(2); | ||
60 | /* Now set that voltage is valid */ | ||
61 | CCM_PMCR0 |= CCM_PMCR0_DPVV; | ||
62 | } | ||
55 | 63 | ||
56 | static uint32_t check_regulator_setting(uint32_t setting) | 64 | static uint32_t check_regulator_setting(uint32_t setting) |
57 | { | 65 | { |
@@ -74,9 +82,8 @@ unsigned int dvfs_nr_up = 0; | |||
74 | unsigned int dvfs_nr_pnc = 0; | 82 | unsigned int dvfs_nr_pnc = 0; |
75 | unsigned int dvfs_nr_no = 0; | 83 | unsigned int dvfs_nr_no = 0; |
76 | 84 | ||
77 | |||
78 | /* Wait for the UPDTEN flag to be set so that all bits may be written */ | 85 | /* Wait for the UPDTEN flag to be set so that all bits may be written */ |
79 | static inline void wait_for_dvfs_update_en(void) | 86 | static inline void updten_wait(void) |
80 | { | 87 | { |
81 | while (!(CCM_PMCR0 & CCM_PMCR0_UPDTEN)); | 88 | while (!(CCM_PMCR0 & CCM_PMCR0_UPDTEN)); |
82 | } | 89 | } |
@@ -111,6 +118,7 @@ static void do_dvfs_update(unsigned int level) | |||
111 | /* DVSUP (new frequency index) setup */ | 118 | /* DVSUP (new frequency index) setup */ |
112 | pmcr0 = (pmcr0 & ~CCM_PMCR0_DVSUP) | (level << CCM_PMCR0_DVSUP_POS); | 119 | pmcr0 = (pmcr0 & ~CCM_PMCR0_DVSUP) | (level << CCM_PMCR0_DVSUP_POS); |
113 | 120 | ||
121 | /* Save new level */ | ||
114 | dvfs_level = level; | 122 | dvfs_level = level; |
115 | 123 | ||
116 | if ((setting->pll_num << CCM_PMCR0_DFSUP_MCUPLL_POS) ^ | 124 | if ((setting->pll_num << CCM_PMCR0_DFSUP_MCUPLL_POS) ^ |
@@ -148,35 +156,30 @@ static void do_dvfs_update(unsigned int level) | |||
148 | 156 | ||
149 | if (pmcr0 & CCM_PMCR0_DPTEN) | 157 | if (pmcr0 & CCM_PMCR0_DPTEN) |
150 | { | 158 | { |
151 | update_dptc_counts(level, dptc_wp); | 159 | update_dptc_counts(); |
152 | /* Enable DPTC to request voltage changes, unmask interrupt. */ | 160 | enable_dptc(); |
153 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_PTVAIM) | CCM_PMCR0_DPVCR; | ||
154 | udelay(2); | ||
155 | /* Voltage is valid. */ | ||
156 | CCM_PMCR0 |= CCM_PMCR0_DPVV; | ||
157 | } | 161 | } |
158 | } | 162 | } |
159 | 163 | ||
160 | |||
161 | /* Start DVFS, change the set point and stop it */ | 164 | /* Start DVFS, change the set point and stop it */ |
162 | static void set_current_dvfs_level(unsigned int level) | 165 | static void set_current_dvfs_level(unsigned int level) |
163 | { | 166 | { |
164 | int oldlevel = disable_irq_save(); | 167 | int oldlevel; |
165 | |||
166 | CCM_PMCR0 |= CCM_PMCR0_DVFEN; | ||
167 | 168 | ||
168 | wait_for_dvfs_update_en(); | 169 | /* Have to wait at least 3 div3 clocks before enabling after being |
170 | * stopped. */ | ||
171 | udelay(1500); | ||
169 | 172 | ||
173 | oldlevel = disable_irq_save(); | ||
174 | CCM_PMCR0 |= CCM_PMCR0_DVFEN; | ||
170 | do_dvfs_update(level); | 175 | do_dvfs_update(level); |
176 | restore_irq(oldlevel); | ||
171 | 177 | ||
172 | wait_for_dvfs_update_en(); | 178 | updten_wait(); |
173 | |||
174 | CCM_PMCR0 &= ~CCM_PMCR0_DVFEN; | ||
175 | 179 | ||
176 | restore_irq(oldlevel); | 180 | bitclr32(&CCM_PMCR0, CCM_PMCR0_DVFEN); |
177 | } | 181 | } |
178 | 182 | ||
179 | |||
180 | /* DVFS Interrupt handler */ | 183 | /* DVFS Interrupt handler */ |
181 | static void __attribute__((used)) dvfs_int(void) | 184 | static void __attribute__((used)) dvfs_int(void) |
182 | { | 185 | { |
@@ -234,7 +237,6 @@ static void __attribute__((used)) dvfs_int(void) | |||
234 | do_dvfs_update(level); | 237 | do_dvfs_update(level); |
235 | } | 238 | } |
236 | 239 | ||
237 | |||
238 | /* Interrupt vector for DVFS */ | 240 | /* Interrupt vector for DVFS */ |
239 | static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) | 241 | static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) |
240 | { | 242 | { |
@@ -244,17 +246,9 @@ static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) | |||
244 | AVIC_NESTED_NI_CALL_EPILOGUE(32*4); | 246 | AVIC_NESTED_NI_CALL_EPILOGUE(32*4); |
245 | } | 247 | } |
246 | 248 | ||
247 | |||
248 | /* Initialize the DVFS hardware */ | 249 | /* Initialize the DVFS hardware */ |
249 | static void INIT_ATTR dvfs_init(void) | 250 | static void INIT_ATTR dvfs_init(void) |
250 | { | 251 | { |
251 | if (CCM_PMCR0 & CCM_PMCR0_DVFEN) | ||
252 | { | ||
253 | /* Turn it off first. Really, shouldn't happen though. */ | ||
254 | dvfs_running = true; | ||
255 | dvfs_stop(); | ||
256 | } | ||
257 | |||
258 | /* Combine SW1A and SW1B DVS pins for a possible five DVS levels | 252 | /* Combine SW1A and SW1B DVS pins for a possible five DVS levels |
259 | * per working point. Four, MAXIMUM, are actually used, one for each | 253 | * per working point. Four, MAXIMUM, are actually used, one for each |
260 | * frequency. */ | 254 | * frequency. */ |
@@ -308,8 +302,10 @@ static void INIT_ATTR dvfs_init(void) | |||
308 | /* Set up LTR2-- EMA configuration. */ | 302 | /* Set up LTR2-- EMA configuration. */ |
309 | bitmod32(&CCM_LTR2, DVFS_EMAC << CCM_LTR2_EMAC_POS, CCM_LTR2_EMAC); | 303 | bitmod32(&CCM_LTR2, DVFS_EMAC << CCM_LTR2_EMAC_POS, CCM_LTR2_EMAC); |
310 | 304 | ||
311 | /* DVFS interrupt goes to MCU. Mask load buffer full interrupt. */ | 305 | /* DVFS interrupt goes to MCU. Mask load buffer full interrupt. Do not |
312 | bitset32(&CCM_PMCR0, CCM_PMCR0_DVFIS | CCM_PMCR0_LBMI); | 306 | * always give an event. */ |
307 | bitmod32(&CCM_PMCR0, CCM_PMCR0_DVFIS | CCM_PMCR0_LBMI, | ||
308 | CCM_PMCR0_DVFIS | CCM_PMCR0_LBMI | CCM_PMCR0_DVFEV); | ||
313 | 309 | ||
314 | /* Initialize current core PLL and dividers for default level. Assumes | 310 | /* Initialize current core PLL and dividers for default level. Assumes |
315 | * clocking scheme has been set up appropriately in other init code. */ | 311 | * clocking scheme has been set up appropriately in other init code. */ |
@@ -322,6 +318,7 @@ static void INIT_ATTR dvfs_init(void) | |||
322 | logf("DVFS: Initialized"); | 318 | logf("DVFS: Initialized"); |
323 | } | 319 | } |
324 | 320 | ||
321 | |||
325 | /** DPTC **/ | 322 | /** DPTC **/ |
326 | 323 | ||
327 | /* Request tracking since boot */ | 324 | /* Request tracking since boot */ |
@@ -332,54 +329,41 @@ unsigned int dptc_nr_up = 0; | |||
332 | unsigned int dptc_nr_pnc = 0; | 329 | unsigned int dptc_nr_pnc = 0; |
333 | unsigned int dptc_nr_no = 0; | 330 | unsigned int dptc_nr_no = 0; |
334 | 331 | ||
335 | static struct spi_transfer_desc dptc_pmic_xfer; /* Transfer descriptor */ | 332 | struct dptc_async_buf |
336 | static const unsigned char dptc_pmic_regs[2] = /* Register subaddresses */ | ||
337 | { MC13783_SWITCHERS0, MC13783_SWITCHERS1 }; | ||
338 | static uint32_t dptc_reg_shadows[2]; /* shadow regs */ | ||
339 | static uint32_t dptc_regs_buf[2]; /* buffer for async write */ | ||
340 | |||
341 | |||
342 | /* Enable DPTC and unmask interrupt. */ | ||
343 | static void enable_dptc(void) | ||
344 | { | 333 | { |
345 | int oldlevel = disable_irq_save(); | 334 | struct spi_transfer_desc xfer; /* transfer descriptor */ |
346 | 335 | unsigned int wp; /* new working point */ | |
347 | /* Enable DPTC, assert voltage change request. */ | 336 | uint32_t buf[2]; /* buffer for async write */ |
348 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_PTVAIM) | CCM_PMCR0_DPTEN | | 337 | }; |
349 | CCM_PMCR0_DPVCR; | ||
350 | |||
351 | udelay(2); | ||
352 | |||
353 | /* Set voltage valid *after* setting change request */ | ||
354 | CCM_PMCR0 |= CCM_PMCR0_DPVV; | ||
355 | |||
356 | restore_irq(oldlevel); | ||
357 | } | ||
358 | 338 | ||
339 | static struct dptc_async_buf dptc_async_buf; /* ISR async write buffer */ | ||
340 | static const unsigned char dptc_pmic_regs[2] = /* Register subaddresses */ | ||
341 | { MC13783_SWITCHERS0, MC13783_SWITCHERS1 }; | ||
342 | static uint32_t dptc_reg_shadows[2]; /* shadow regs */ | ||
359 | 343 | ||
360 | /* Called after asynchronous PMIC write is completed */ | 344 | /* Called (in SPI INT context) after asynchronous PMIC write is completed */ |
361 | static void dptc_transfer_done_callback(struct spi_transfer_desc *xfer) | 345 | static void dptc_transfer_done_callback(struct spi_transfer_desc *xfer) |
362 | { | 346 | { |
363 | if (xfer->count != 0) | 347 | if (xfer->count != 0) |
364 | return; | 348 | return; |
365 | 349 | ||
366 | update_dptc_counts(dvfs_level, dptc_wp); | 350 | /* Save new working point */ |
351 | dptc_wp = ((struct dptc_async_buf *)xfer)->wp; | ||
352 | |||
353 | update_dptc_counts(); | ||
367 | 354 | ||
368 | if (dptc_running) | 355 | if (dptc_running) |
369 | enable_dptc(); | 356 | enable_dptc(); |
370 | } | 357 | } |
371 | 358 | ||
372 | |||
373 | /* Handle the DPTC interrupt and sometimes the manual setting - always call | 359 | /* Handle the DPTC interrupt and sometimes the manual setting - always call |
374 | * with IRQ masked. */ | 360 | * with IRQ masked. */ |
375 | static void dptc_int(unsigned long pmcr0) | 361 | static void dptc_int(unsigned long pmcr0, int wp, struct dptc_async_buf *abuf) |
376 | { | 362 | { |
377 | const union dvfs_dptc_voltage_table_entry *entry; | 363 | const union dvfs_dptc_voltage_table_entry *entry; |
378 | uint32_t sw1a, sw1advs, sw1bdvs, sw1bstby; | 364 | uint32_t sw1a, sw1advs, sw1bdvs, sw1bstby; |
379 | uint32_t switchers0, switchers1; | 365 | uint32_t switchers0, switchers1; |
380 | 366 | ||
381 | int wp = dptc_wp; | ||
382 | |||
383 | /* Mask DPTC interrupt and disable DPTC until the change request is | 367 | /* Mask DPTC interrupt and disable DPTC until the change request is |
384 | * serviced. */ | 368 | * serviced. */ |
385 | CCM_PMCR0 = (pmcr0 & ~CCM_PMCR0_DPTEN) | CCM_PMCR0_PTVAIM; | 369 | CCM_PMCR0 = (pmcr0 & ~CCM_PMCR0_DPTEN) | CCM_PMCR0_PTVAIM; |
@@ -387,30 +371,40 @@ static void dptc_int(unsigned long pmcr0) | |||
387 | switch (pmcr0 & CCM_PMCR0_PTVAI) | 371 | switch (pmcr0 & CCM_PMCR0_PTVAI) |
388 | { | 372 | { |
389 | case CCM_PMCR0_PTVAI_DECREASE: | 373 | case CCM_PMCR0_PTVAI_DECREASE: |
374 | /* Decrease voltage request - increment working point */ | ||
390 | wp++; | 375 | wp++; |
391 | dptc_nr_dn++; | 376 | dptc_nr_dn++; |
392 | break; | 377 | break; |
393 | 378 | ||
394 | case CCM_PMCR0_PTVAI_INCREASE: | 379 | case CCM_PMCR0_PTVAI_INCREASE: |
380 | /* Increase voltage request - decrement working point */ | ||
395 | wp--; | 381 | wp--; |
396 | dptc_nr_up++; | 382 | dptc_nr_up++; |
397 | break; | 383 | break; |
398 | 384 | ||
399 | case CCM_PMCR0_PTVAI_INCREASE_NOW: | 385 | case CCM_PMCR0_PTVAI_INCREASE_NOW: |
386 | /* Panic request - move immediately to panic working point if | ||
387 | * decrement results in greater working point than DPTC_WP_PANIC. */ | ||
400 | if (--wp > DPTC_WP_PANIC) | 388 | if (--wp > DPTC_WP_PANIC) |
401 | wp = DPTC_WP_PANIC; | 389 | wp = DPTC_WP_PANIC; |
402 | dptc_nr_pnc++; | 390 | dptc_nr_pnc++; |
403 | break; | 391 | break; |
404 | 392 | ||
405 | case CCM_PMCR0_PTVAI_NO_INT: | 393 | case CCM_PMCR0_PTVAI_NO_INT: |
406 | break; /* Just maintain at global level */ | 394 | /* Just maintain at global level */ |
395 | if (abuf == &dptc_async_buf) | ||
396 | dptc_nr_no++; | ||
397 | break; | ||
407 | } | 398 | } |
408 | 399 | ||
400 | /* Keep result in range */ | ||
409 | if (wp < 0) | 401 | if (wp < 0) |
410 | wp = 0; | 402 | wp = 0; |
411 | else if (wp >= DPTC_NUM_WP) | 403 | else if (wp >= DPTC_NUM_WP) |
412 | wp = DPTC_NUM_WP - 1; | 404 | wp = DPTC_NUM_WP - 1; |
413 | 405 | ||
406 | /* Get new regulator register settings, sanity check them and write them | ||
407 | * in the background. */ | ||
414 | entry = &dvfs_dptc_voltage_table[wp]; | 408 | entry = &dvfs_dptc_voltage_table[wp]; |
415 | 409 | ||
416 | sw1a = check_regulator_setting(entry->sw1a); | 410 | sw1a = check_regulator_setting(entry->sw1a); |
@@ -419,154 +413,183 @@ static void dptc_int(unsigned long pmcr0) | |||
419 | sw1bstby = check_regulator_setting(entry->sw1bstby); | 413 | sw1bstby = check_regulator_setting(entry->sw1bstby); |
420 | 414 | ||
421 | switchers0 = dptc_reg_shadows[0] & ~(MC13783_SW1A | MC13783_SW1ADVS); | 415 | switchers0 = dptc_reg_shadows[0] & ~(MC13783_SW1A | MC13783_SW1ADVS); |
422 | dptc_regs_buf[0] = switchers0 | | 416 | abuf->buf[0] = switchers0 | |
423 | sw1a << MC13783_SW1A_POS | /* SW1A */ | 417 | sw1a << MC13783_SW1A_POS | /* SW1A */ |
424 | sw1advs << MC13783_SW1ADVS_POS; /* SW1ADVS */ | 418 | sw1advs << MC13783_SW1ADVS_POS; /* SW1ADVS */ |
425 | switchers1 = dptc_reg_shadows[1] & ~(MC13783_SW1BDVS | MC13783_SW1BSTBY); | 419 | switchers1 = dptc_reg_shadows[1] & ~(MC13783_SW1BDVS | MC13783_SW1BSTBY); |
426 | dptc_regs_buf[1] = switchers1 | | 420 | abuf->buf[1] = switchers1 | |
427 | sw1bdvs << MC13783_SW1BDVS_POS | /* SW1BDVS */ | 421 | sw1bdvs << MC13783_SW1BDVS_POS | /* SW1BDVS */ |
428 | sw1bstby << MC13783_SW1BSTBY_POS; /* SW1BSTBY */ | 422 | sw1bstby << MC13783_SW1BSTBY_POS; /* SW1BSTBY */ |
429 | |||
430 | dptc_wp = wp; | ||
431 | 423 | ||
432 | mc13783_write_async(&dptc_pmic_xfer, dptc_pmic_regs, | 424 | abuf->wp = wp; /* Save new for xfer completion handler */ |
433 | dptc_regs_buf, 2, dptc_transfer_done_callback); | 425 | mc13783_write_async(&abuf->xfer, dptc_pmic_regs, abuf->buf, 2, |
426 | dptc_transfer_done_callback); | ||
434 | } | 427 | } |
435 | 428 | ||
436 | |||
437 | /* Handle setting the working point explicitly - always call with IRQ | 429 | /* Handle setting the working point explicitly - always call with IRQ |
438 | * masked */ | 430 | * masked */ |
439 | static void dptc_new_wp(unsigned int wp) | 431 | static void dptc_new_wp(unsigned int wp) |
440 | { | 432 | { |
441 | dptc_wp = wp; | 433 | struct dptc_async_buf buf; |
434 | |||
442 | /* "NO_INT" so the working point isn't incremented, just set. */ | 435 | /* "NO_INT" so the working point isn't incremented, just set. */ |
443 | dptc_int((CCM_PMCR0 & ~CCM_PMCR0_PTVAI) | CCM_PMCR0_PTVAI_NO_INT); | 436 | dptc_int(CCM_PMCR0 & ~CCM_PMCR0_PTVAI, wp, &buf); |
444 | } | ||
445 | 437 | ||
438 | /* Wait for PMIC write */ | ||
439 | while (!spi_transfer_complete(&buf.xfer)) | ||
440 | { | ||
441 | enable_irq(); | ||
442 | nop; nop; nop; nop; nop; | ||
443 | disable_irq(); | ||
444 | } | ||
445 | } | ||
446 | 446 | ||
447 | /* Interrupt vector for DPTC */ | 447 | /* Interrupt vector for DPTC */ |
448 | static __attribute__((interrupt("IRQ"))) void CCM_CLK_HANDLER(void) | 448 | static __attribute__((interrupt("IRQ"))) void CCM_CLK_HANDLER(void) |
449 | { | 449 | { |
450 | unsigned long pmcr0 = CCM_PMCR0; | 450 | dptc_int(CCM_PMCR0, dptc_wp, &dptc_async_buf); |
451 | |||
452 | if ((pmcr0 & CCM_PMCR0_PTVAI) == CCM_PMCR0_PTVAI_NO_INT) | ||
453 | dptc_nr_no++; | ||
454 | |||
455 | dptc_int(pmcr0); | ||
456 | } | 451 | } |
457 | 452 | ||
458 | |||
459 | /* Initialize the DPTC hardware */ | 453 | /* Initialize the DPTC hardware */ |
460 | static void INIT_ATTR dptc_init(void) | 454 | static void INIT_ATTR dptc_init(void) |
461 | { | 455 | { |
462 | /* Force DPTC off if running for some reason. */ | 456 | int oldlevel; |
463 | bitmod32(&CCM_PMCR0, CCM_PMCR0_PTVAIM, | ||
464 | CCM_PMCR0_PTVAIM | CCM_PMCR0_DPTEN); | ||
465 | 457 | ||
466 | /* Shadow the regulator registers */ | 458 | /* Shadow the regulator registers */ |
467 | mc13783_read_regs(dptc_pmic_regs, dptc_reg_shadows, 2); | 459 | mc13783_read_regs(dptc_pmic_regs, dptc_reg_shadows, 2); |
468 | 460 | ||
469 | /* Set default, safe working point. */ | 461 | /* Set default, safe working point. */ |
462 | oldlevel = disable_irq_save(); | ||
470 | dptc_new_wp(DPTC_WP_DEFAULT); | 463 | dptc_new_wp(DPTC_WP_DEFAULT); |
464 | restore_irq(oldlevel); | ||
471 | 465 | ||
472 | /* Interrupt goes to MCU, specified reference circuits enabled when | 466 | /* Interrupt goes to MCU, specified reference circuits enabled when |
473 | * DPTC is active. */ | 467 | * DPTC is active, DPTC counting range = 256 system clocks */ |
474 | bitset32(&CCM_PMCR0, CCM_PMCR0_PTVIS); | 468 | bitmod32(&CCM_PMCR0, |
475 | 469 | CCM_PMCR0_PTVIS | DPTC_DRCE_MASK, | |
476 | bitmod32(&CCM_PMCR0, DPTC_DRCE_MASK, | 470 | CCM_PMCR0_PTVIS | CCM_PMCR0_DCR | |
477 | CCM_PMCR0_DRCE0 | CCM_PMCR0_DRCE1 | | 471 | CCM_PMCR0_DRCE0 | CCM_PMCR0_DRCE1 | |
478 | CCM_PMCR0_DRCE2 | CCM_PMCR0_DRCE3); | 472 | CCM_PMCR0_DRCE2 | CCM_PMCR0_DRCE3); |
479 | 473 | ||
480 | /* DPTC counting range = 256 system clocks */ | ||
481 | bitclr32(&CCM_PMCR0, CCM_PMCR0_DCR); | ||
482 | |||
483 | logf("DPTC: Initialized"); | 474 | logf("DPTC: Initialized"); |
484 | } | 475 | } |
485 | 476 | ||
486 | 477 | ||
487 | /** Main module interface **/ | 478 | /** Main module interface **/ |
488 | 479 | ||
480 | /** DVFS+DPTC **/ | ||
481 | |||
489 | /* Initialize DVFS and DPTC */ | 482 | /* Initialize DVFS and DPTC */ |
490 | void INIT_ATTR dvfs_dptc_init(void) | 483 | void INIT_ATTR dvfs_dptc_init(void) |
491 | { | 484 | { |
485 | /* DVFS or DPTC on for some reason? Force off. */ | ||
486 | bitmod32(&CCM_PMCR0, | ||
487 | CCM_PMCR0_FSVAIM | CCM_PMCR0_LBMI | | ||
488 | CCM_PMCR0_PTVAIM, | ||
489 | CCM_PMCR0_FSVAIM | CCM_PMCR0_LBMI | CCM_PMCR0_DVFEN | | ||
490 | CCM_PMCR0_PTVAIM | CCM_PMCR0_DPTEN); | ||
491 | |||
492 | /* Ensure correct order - after this, the two appear independent */ | ||
492 | dptc_init(); | 493 | dptc_init(); |
493 | dvfs_init(); | 494 | dvfs_init(); |
494 | } | 495 | } |
495 | 496 | ||
496 | 497 | /* Obtain the current core voltage setting, in millivolts 8-) */ | |
497 | /* Start DVFS and DPTC */ | 498 | unsigned int dvfs_dptc_get_voltage(void) |
498 | void dvfs_dptc_start(void) | ||
499 | { | 499 | { |
500 | dvfs_start(); | 500 | unsigned int v; |
501 | dptc_start(); | ||
502 | } | ||
503 | 501 | ||
502 | int oldlevel = disable_irq_save(); | ||
503 | v = dvfs_dptc_voltage_table[dptc_wp].sw[dvfs_level]; | ||
504 | restore_irq(oldlevel); | ||
504 | 505 | ||
505 | /* Stop DVFS and DPTC */ | 506 | /* 25mV steps from 0.900V to 1.675V */ |
506 | void dvfs_dptc_stop(void) | 507 | return v * 25 + 900; |
507 | { | ||
508 | dptc_stop(); | ||
509 | dvfs_stop(); | ||
510 | } | 508 | } |
511 | 509 | ||
510 | |||
511 | /** DVFS **/ | ||
512 | |||
512 | /* Start the DVFS hardware */ | 513 | /* Start the DVFS hardware */ |
513 | void dvfs_start(void) | 514 | void dvfs_start(void) |
514 | { | 515 | { |
515 | int oldlevel; | 516 | if (dvfs_running) |
517 | return; | ||
516 | 518 | ||
517 | /* Have to wait at least 3 div3 clocks before enabling after being | 519 | /* Have to wait at least 3 div3 clocks before enabling after being |
518 | * stopped. */ | 520 | * stopped. */ |
519 | udelay(1500); | 521 | udelay(1500); |
520 | 522 | ||
521 | oldlevel = disable_irq_save(); | 523 | /* Unmask DVFS interrupt source and enable DVFS. */ |
524 | bitmod32(&CCM_PMCR0, CCM_PMCR0_DVFEN, | ||
525 | CCM_PMCR0_FSVAIM | CCM_PMCR0_DVFEN); | ||
522 | 526 | ||
523 | if (!dvfs_running) | 527 | dvfs_running = true; |
524 | { | ||
525 | dvfs_running = true; | ||
526 | 528 | ||
527 | /* Unmask DVFS interrupt source and enable DVFS. */ | 529 | avic_enable_int(INT_CCM_DVFS, INT_TYPE_IRQ, INT_PRIO_DVFS, |
528 | avic_enable_int(INT_CCM_DVFS, INT_TYPE_IRQ, INT_PRIO_DVFS, | 530 | CCM_DVFS_HANDLER); |
529 | CCM_DVFS_HANDLER); | ||
530 | |||
531 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_FSVAIM) | CCM_PMCR0_DVFEN; | ||
532 | } | ||
533 | |||
534 | restore_irq(oldlevel); | ||
535 | 531 | ||
536 | logf("DVFS: started"); | 532 | logf("DVFS: started"); |
537 | } | 533 | } |
538 | 534 | ||
539 | |||
540 | /* Stop the DVFS hardware and return to default frequency */ | 535 | /* Stop the DVFS hardware and return to default frequency */ |
541 | void dvfs_stop(void) | 536 | void dvfs_stop(void) |
542 | { | 537 | { |
543 | int oldlevel = disable_irq_save(); | 538 | if (!dvfs_running) |
544 | 539 | return; | |
545 | if (dvfs_running) | ||
546 | { | ||
547 | /* Mask DVFS interrupts. */ | ||
548 | CCM_PMCR0 |= CCM_PMCR0_FSVAIM | CCM_PMCR0_LBMI; | ||
549 | avic_disable_int(INT_CCM_DVFS); | ||
550 | 540 | ||
551 | if (((CCM_PMCR0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS) != | 541 | /* Mask DVFS interrupts. */ |
552 | DVFS_LEVEL_DEFAULT) | 542 | avic_disable_int(INT_CCM_DVFS); |
553 | { | 543 | bitset32(&CCM_PMCR0, CCM_PMCR0_FSVAIM | CCM_PMCR0_LBMI); |
554 | /* Set default frequency level */ | ||
555 | wait_for_dvfs_update_en(); | ||
556 | do_dvfs_update(DVFS_LEVEL_DEFAULT); | ||
557 | wait_for_dvfs_update_en(); | ||
558 | } | ||
559 | 544 | ||
560 | /* Disable DVFS. */ | 545 | if (((CCM_PMCR0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS) != |
561 | CCM_PMCR0 &= ~CCM_PMCR0_DVFEN; | 546 | DVFS_LEVEL_DEFAULT) |
562 | dvfs_running = false; | 547 | { |
548 | int oldlevel; | ||
549 | /* Set default frequency level */ | ||
550 | updten_wait(); | ||
551 | oldlevel = disable_irq_save(); | ||
552 | do_dvfs_update(DVFS_LEVEL_DEFAULT); | ||
553 | restore_irq(oldlevel); | ||
554 | updten_wait(); | ||
563 | } | 555 | } |
564 | 556 | ||
565 | restore_irq(oldlevel); | 557 | /* Disable DVFS. */ |
558 | bitclr32(&CCM_PMCR0, CCM_PMCR0_DVFEN); | ||
559 | dvfs_running = false; | ||
566 | 560 | ||
567 | logf("DVFS: stopped"); | 561 | logf("DVFS: stopped"); |
568 | } | 562 | } |
569 | 563 | ||
564 | /* Is DVFS enabled? */ | ||
565 | bool dvfs_enabled(void) | ||
566 | { | ||
567 | return dvfs_running; | ||
568 | } | ||
569 | |||
570 | /* If DVFS is disabled, set the level explicitly */ | ||
571 | void dvfs_set_level(unsigned int level) | ||
572 | { | ||
573 | if (dvfs_running || | ||
574 | level >= DVFS_NUM_LEVELS || | ||
575 | !((1 << level) & DVFS_LEVEL_MASK) || | ||
576 | level == ((CCM_PMCR0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS)) | ||
577 | return; | ||
578 | |||
579 | set_current_dvfs_level(level); | ||
580 | } | ||
581 | |||
582 | /* Get the current DVFS level */ | ||
583 | unsigned int dvfs_get_level(void) | ||
584 | { | ||
585 | return dvfs_level; | ||
586 | } | ||
587 | |||
588 | /* Get bitmask of levels supported */ | ||
589 | unsigned int dvfs_level_mask(void) | ||
590 | { | ||
591 | return DVFS_LEVEL_MASK; | ||
592 | } | ||
570 | 593 | ||
571 | /* Mask the DVFS interrupt without affecting running status */ | 594 | /* Mask the DVFS interrupt without affecting running status */ |
572 | void dvfs_int_mask(bool mask) | 595 | void dvfs_int_mask(bool mask) |
@@ -583,7 +606,6 @@ void dvfs_int_mask(bool mask) | |||
583 | } | 606 | } |
584 | } | 607 | } |
585 | 608 | ||
586 | |||
587 | /* Set a signal load tracking weight */ | 609 | /* Set a signal load tracking weight */ |
588 | void dvfs_set_lt_weight(enum DVFS_LT_SIGS index, unsigned long value) | 610 | void dvfs_set_lt_weight(enum DVFS_LT_SIGS index, unsigned long value) |
589 | { | 611 | { |
@@ -603,7 +625,6 @@ void dvfs_set_lt_weight(enum DVFS_LT_SIGS index, unsigned long value) | |||
603 | bitmod32(reg_p, value << shift, 0x7 << shift); | 625 | bitmod32(reg_p, value << shift, 0x7 << shift); |
604 | } | 626 | } |
605 | 627 | ||
606 | |||
607 | /* Return a signal load tracking weight */ | 628 | /* Return a signal load tracking weight */ |
608 | unsigned long dvfs_get_lt_weight(enum DVFS_LT_SIGS index) | 629 | unsigned long dvfs_get_lt_weight(enum DVFS_LT_SIGS index) |
609 | { | 630 | { |
@@ -623,7 +644,6 @@ unsigned long dvfs_get_lt_weight(enum DVFS_LT_SIGS index) | |||
623 | return (*reg_p & (0x7 << shift)) >> shift; | 644 | return (*reg_p & (0x7 << shift)) >> shift; |
624 | } | 645 | } |
625 | 646 | ||
626 | |||
627 | /* Set a signal load detection mode */ | 647 | /* Set a signal load detection mode */ |
628 | void dvfs_set_lt_detect(enum DVFS_LT_SIGS index, bool edge) | 648 | void dvfs_set_lt_detect(enum DVFS_LT_SIGS index, bool edge) |
629 | { | 649 | { |
@@ -637,7 +657,6 @@ void dvfs_set_lt_detect(enum DVFS_LT_SIGS index, bool edge) | |||
637 | bitmod32(&CCM_LTR0, edge ? bit : 0, bit); | 657 | bitmod32(&CCM_LTR0, edge ? bit : 0, bit); |
638 | } | 658 | } |
639 | 659 | ||
640 | |||
641 | /* Returns a signal load detection mode */ | 660 | /* Returns a signal load detection mode */ |
642 | bool dvfs_get_lt_detect(enum DVFS_LT_SIGS index) | 661 | bool dvfs_get_lt_detect(enum DVFS_LT_SIGS index) |
643 | { | 662 | { |
@@ -651,7 +670,6 @@ bool dvfs_get_lt_detect(enum DVFS_LT_SIGS index) | |||
651 | return !!((CCM_LTR0 & (1ul << shift)) >> shift); | 670 | return !!((CCM_LTR0 & (1ul << shift)) >> shift); |
652 | } | 671 | } |
653 | 672 | ||
654 | |||
655 | /* Set/clear the general-purpose load tracking bit */ | 673 | /* Set/clear the general-purpose load tracking bit */ |
656 | void dvfs_set_gp_bit(enum DVFS_DVGPS dvgp, bool assert) | 674 | void dvfs_set_gp_bit(enum DVFS_DVGPS dvgp, bool assert) |
657 | { | 675 | { |
@@ -662,7 +680,6 @@ void dvfs_set_gp_bit(enum DVFS_DVGPS dvgp, bool assert) | |||
662 | } | 680 | } |
663 | } | 681 | } |
664 | 682 | ||
665 | |||
666 | /* Return the general-purpose load tracking bit */ | 683 | /* Return the general-purpose load tracking bit */ |
667 | bool dvfs_get_gp_bit(enum DVFS_DVGPS dvgp) | 684 | bool dvfs_get_gp_bit(enum DVFS_DVGPS dvgp) |
668 | { | 685 | { |
@@ -671,7 +688,6 @@ bool dvfs_get_gp_bit(enum DVFS_DVGPS dvgp) | |||
671 | return false; | 688 | return false; |
672 | } | 689 | } |
673 | 690 | ||
674 | |||
675 | /* Set GP load tracking by code. | 691 | /* Set GP load tracking by code. |
676 | * level_code: | 692 | * level_code: |
677 | * lt 0 =defaults | 693 | * lt 0 =defaults |
@@ -738,7 +754,6 @@ void dvfs_get_gp_sense(int *level_code, unsigned long *detect_mask) | |||
738 | *detect_mask = mask; | 754 | *detect_mask = mask; |
739 | } | 755 | } |
740 | 756 | ||
741 | |||
742 | /* Turn the wait-for-interrupt monitoring on or off */ | 757 | /* Turn the wait-for-interrupt monitoring on or off */ |
743 | void dvfs_wfi_monitor(bool on) | 758 | void dvfs_wfi_monitor(bool on) |
744 | { | 759 | { |
@@ -746,125 +761,68 @@ void dvfs_wfi_monitor(bool on) | |||
746 | } | 761 | } |
747 | 762 | ||
748 | 763 | ||
749 | /* Obtain the current core voltage setting, in millivolts 8-) */ | 764 | /** DPTC **/ |
750 | unsigned int dvfs_dptc_get_voltage(void) | ||
751 | { | ||
752 | unsigned int v; | ||
753 | |||
754 | int oldlevel = disable_irq_save(); | ||
755 | v = dvfs_dptc_voltage_table[dptc_wp].sw[dvfs_level]; | ||
756 | restore_irq(oldlevel); | ||
757 | |||
758 | /* 25mV steps from 0.900V to 1.675V */ | ||
759 | return v * 25 + 900; | ||
760 | } | ||
761 | |||
762 | |||
763 | /* Get the current DVFS level */ | ||
764 | unsigned int dvfs_get_level(void) | ||
765 | { | ||
766 | return dvfs_level; | ||
767 | } | ||
768 | |||
769 | |||
770 | /* Is DVFS enabled? */ | ||
771 | bool dvfs_enabled(void) | ||
772 | { | ||
773 | return dvfs_running; | ||
774 | } | ||
775 | |||
776 | |||
777 | /* Get bitmask of levels supported */ | ||
778 | unsigned int dvfs_level_mask(void) | ||
779 | { | ||
780 | return DVFS_LEVEL_MASK; | ||
781 | } | ||
782 | |||
783 | |||
784 | /* If DVFS is disabled, set the level explicitly */ | ||
785 | void dvfs_set_level(unsigned int level) | ||
786 | { | ||
787 | int oldlevel = disable_irq_save(); | ||
788 | |||
789 | if (!dvfs_running && level < DVFS_NUM_LEVELS) | ||
790 | { | ||
791 | unsigned int currlevel = | ||
792 | (CCM_PMCR0 & CCM_PMCR0_DVSUP) >> CCM_PMCR0_DVSUP_POS; | ||
793 | if (level != currlevel && ((1 << level) & DVFS_LEVEL_MASK)) | ||
794 | set_current_dvfs_level(level); | ||
795 | } | ||
796 | |||
797 | restore_irq(oldlevel); | ||
798 | } | ||
799 | |||
800 | 765 | ||
801 | /* Start DPTC module */ | 766 | /* Start DPTC module */ |
802 | void dptc_start(void) | 767 | void dptc_start(void) |
803 | { | 768 | { |
804 | int oldlevel = disable_irq_save(); | 769 | int oldlevel; |
805 | |||
806 | if (!dptc_running) | ||
807 | { | ||
808 | dptc_running = true; | ||
809 | 770 | ||
810 | /* Enable DPTC and unmask interrupt. */ | 771 | if (dptc_running) |
811 | avic_enable_int(INT_CCM_CLK, INT_TYPE_IRQ, INT_PRIO_DPTC, | 772 | return; |
812 | CCM_CLK_HANDLER); | ||
813 | 773 | ||
814 | update_dptc_counts(dvfs_level, dptc_wp); | 774 | oldlevel = disable_irq_save(); |
815 | enable_dptc(); | 775 | dptc_running = true; |
816 | } | ||
817 | 776 | ||
777 | /* Enable DPTC and unmask interrupt. */ | ||
778 | update_dptc_counts(); | ||
779 | enable_dptc(); | ||
818 | restore_irq(oldlevel); | 780 | restore_irq(oldlevel); |
819 | 781 | ||
782 | avic_enable_int(INT_CCM_CLK, INT_TYPE_IRQ, INT_PRIO_DPTC, | ||
783 | CCM_CLK_HANDLER); | ||
784 | |||
820 | logf("DPTC: started"); | 785 | logf("DPTC: started"); |
821 | } | 786 | } |
822 | 787 | ||
823 | |||
824 | /* Stop the DPTC hardware if running and go back to default working point */ | 788 | /* Stop the DPTC hardware if running and go back to default working point */ |
825 | void dptc_stop(void) | 789 | void dptc_stop(void) |
826 | { | 790 | { |
827 | int oldlevel = disable_irq_save(); | 791 | int oldlevel; |
828 | 792 | ||
829 | if (dptc_running) | 793 | if (!dptc_running) |
830 | { | 794 | return; |
831 | dptc_running = false; | ||
832 | 795 | ||
833 | /* Disable DPTC and mask interrupt. */ | 796 | avic_disable_int(INT_CCM_CLK); |
834 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_DPTEN) | CCM_PMCR0_PTVAIM; | ||
835 | avic_disable_int(INT_CCM_CLK); | ||
836 | 797 | ||
837 | /* Go back to default working point. */ | 798 | oldlevel = disable_irq_save(); |
838 | dptc_new_wp(DPTC_WP_DEFAULT); | 799 | dptc_running = false; |
839 | } | ||
840 | 800 | ||
801 | /* Disable DPTC and mask interrupt. */ | ||
802 | CCM_PMCR0 = (CCM_PMCR0 & ~CCM_PMCR0_DPTEN) | CCM_PMCR0_PTVAIM; | ||
803 | |||
804 | /* Go back to default working point. */ | ||
805 | dptc_new_wp(DPTC_WP_DEFAULT); | ||
841 | restore_irq(oldlevel); | 806 | restore_irq(oldlevel); |
842 | 807 | ||
843 | logf("DPTC: stopped"); | 808 | logf("DPTC: stopped"); |
844 | } | 809 | } |
845 | 810 | ||
846 | |||
847 | /* Get the current DPTC working point */ | ||
848 | unsigned int dptc_get_wp(void) | ||
849 | { | ||
850 | return dptc_wp; | ||
851 | } | ||
852 | |||
853 | |||
854 | /* Is DPTC enabled? */ | 811 | /* Is DPTC enabled? */ |
855 | bool dptc_enabled(void) | 812 | bool dptc_enabled(void) |
856 | { | 813 | { |
857 | return dptc_running; | 814 | return dptc_running; |
858 | } | 815 | } |
859 | 816 | ||
860 | |||
861 | /* If DPTC is not running, set the working point explicitly */ | 817 | /* If DPTC is not running, set the working point explicitly */ |
862 | void dptc_set_wp(unsigned int wp) | 818 | void dptc_set_wp(unsigned int wp) |
863 | { | 819 | { |
864 | int oldlevel = disable_irq_save(); | ||
865 | |||
866 | if (!dptc_running && wp < DPTC_NUM_WP) | 820 | if (!dptc_running && wp < DPTC_NUM_WP) |
867 | dptc_new_wp(wp); | 821 | dptc_new_wp(wp); |
822 | } | ||
868 | 823 | ||
869 | restore_irq(oldlevel); | 824 | /* Get the current DPTC working point */ |
825 | unsigned int dptc_get_wp(void) | ||
826 | { | ||
827 | return dptc_wp; | ||
870 | } | 828 | } |
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.h b/firmware/target/arm/imx31/dvfs_dptc-imx31.h index 1f3f1ab20d..8c599fe402 100644 --- a/firmware/target/arm/imx31/dvfs_dptc-imx31.h +++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.h | |||
@@ -118,15 +118,19 @@ struct dvfs_lt_signal_descriptor | |||
118 | #define DVFS_LEVEL_2 (1u << 2) | 118 | #define DVFS_LEVEL_2 (1u << 2) |
119 | #define DVFS_LEVEL_3 (1u << 3) | 119 | #define DVFS_LEVEL_3 (1u << 3) |
120 | 120 | ||
121 | extern long cpu_voltage_setting; | 121 | /* DVFS+DPTC */ |
122 | |||
123 | void dvfs_dptc_init(void); | 122 | void dvfs_dptc_init(void); |
124 | void dvfs_dptc_start(void); | 123 | unsigned int dvfs_dptc_get_voltage(void); |
125 | void dvfs_dptc_stop(void); | ||
126 | 124 | ||
125 | /* DVFS */ | ||
127 | void dvfs_start(void); | 126 | void dvfs_start(void); |
128 | void dvfs_stop(void); | 127 | void dvfs_stop(void); |
129 | bool dvfs_enabled(void); | 128 | bool dvfs_enabled(void); |
129 | unsigned int dvfs_level_mask(void); | ||
130 | void dvfs_set_level(unsigned int level); | ||
131 | unsigned int dvfs_get_level(void); | ||
132 | void dvfs_int_mask(bool mask); | ||
133 | |||
130 | void dvfs_wfi_monitor(bool on); | 134 | void dvfs_wfi_monitor(bool on); |
131 | void dvfs_set_lt_weight(enum DVFS_LT_SIGS index, unsigned long value); | 135 | void dvfs_set_lt_weight(enum DVFS_LT_SIGS index, unsigned long value); |
132 | unsigned long dvfs_get_lt_weight(enum DVFS_LT_SIGS index); | 136 | unsigned long dvfs_get_lt_weight(enum DVFS_LT_SIGS index); |
@@ -134,19 +138,14 @@ void dvfs_set_lt_detect(enum DVFS_LT_SIGS index, bool edge); | |||
134 | bool dvfs_get_lt_detect(enum DVFS_LT_SIGS index); | 138 | bool dvfs_get_lt_detect(enum DVFS_LT_SIGS index); |
135 | void dvfs_set_gp_bit(enum DVFS_DVGPS dvgp, bool assert); | 139 | void dvfs_set_gp_bit(enum DVFS_DVGPS dvgp, bool assert); |
136 | bool dvfs_get_gp_bit(enum DVFS_DVGPS dvgp); | 140 | bool dvfs_get_gp_bit(enum DVFS_DVGPS dvgp); |
137 | void dvfs_int_mask(bool mask); | ||
138 | void dvfs_set_gp_sense(int level_code, unsigned long detect_mask); | 141 | void dvfs_set_gp_sense(int level_code, unsigned long detect_mask); |
139 | void dvfs_get_gp_sense(int *level_code, unsigned long *detect_mask); | 142 | void dvfs_get_gp_sense(int *level_code, unsigned long *detect_mask); |
140 | unsigned int dvfs_level_mask(void); | ||
141 | |||
142 | unsigned int dvfs_dptc_get_voltage(void); | ||
143 | unsigned int dvfs_get_level(void); | ||
144 | void dvfs_set_level(unsigned int level); | ||
145 | 143 | ||
144 | /* DPTC */ | ||
146 | void dptc_start(void); | 145 | void dptc_start(void); |
147 | void dptc_stop(void); | 146 | void dptc_stop(void); |
148 | bool dptc_enabled(void); | 147 | bool dptc_enabled(void); |
149 | unsigned int dptc_get_wp(void); | ||
150 | void dptc_set_wp(unsigned int wp); | 148 | void dptc_set_wp(unsigned int wp); |
149 | unsigned int dptc_get_wp(void); | ||
151 | 150 | ||
152 | #endif /* _DVFS_DPTC_IMX31_H_ */ | 151 | #endif /* _DVFS_DPTC_IMX31_H_ */ |
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 481cb467bd..f30287d4e9 100644 --- a/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c | |||
@@ -71,10 +71,11 @@ void INIT_ATTR kernel_device_init(void) | |||
71 | spi_init(); | 71 | spi_init(); |
72 | enable_interrupt(IRQ_FIQ_STATUS); | 72 | enable_interrupt(IRQ_FIQ_STATUS); |
73 | mc13783_init(); | 73 | mc13783_init(); |
74 | dvfs_dptc_init(); | 74 | dvfs_dptc_init(); /* Init also sets default points */ |
75 | dvfs_wfi_monitor(true); /* Monitor the WFI signal */ | ||
76 | #ifndef BOOTLOADER | 75 | #ifndef BOOTLOADER |
77 | dvfs_dptc_start(); /* Should be ok to start even so early */ | 76 | dvfs_wfi_monitor(true); /* Monitor the WFI signal */ |
77 | dvfs_start(); /* Should be ok to start even so early */ | ||
78 | dptc_start(); | ||
78 | #endif | 79 | #endif |
79 | } | 80 | } |
80 | 81 | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c index 9d7d30547b..11276a6c3a 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c | |||
@@ -129,7 +129,8 @@ bool tuner_powered(void) | |||
129 | void power_off(void) | 129 | void power_off(void) |
130 | { | 130 | { |
131 | /* Turn off voltage and frequency scaling */ | 131 | /* Turn off voltage and frequency scaling */ |
132 | dvfs_dptc_stop(); | 132 | dvfs_stop(); |
133 | dptc_stop(); | ||
133 | 134 | ||
134 | /* Cut backlight */ | 135 | /* Cut backlight */ |
135 | _backlight_off(); | 136 | _backlight_off(); |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c index 1f177d4252..16b17ba403 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c | |||
@@ -210,7 +210,8 @@ void INIT_ATTR system_init(void) | |||
210 | 210 | ||
211 | void system_prepare_fw_start(void) | 211 | void system_prepare_fw_start(void) |
212 | { | 212 | { |
213 | dvfs_dptc_stop(); | 213 | dvfs_stop(); |
214 | dptc_stop(); | ||
214 | mc13783_close(); | 215 | mc13783_close(); |
215 | tick_stop(); | 216 | tick_stop(); |
216 | disable_interrupt(IRQ_FIQ_STATUS); | 217 | disable_interrupt(IRQ_FIQ_STATUS); |
diff --git a/firmware/target/arm/imx31/mc13783-imx31.c b/firmware/target/arm/imx31/mc13783-imx31.c index b236dcd2ab..d5d22e2c75 100644 --- a/firmware/target/arm/imx31/mc13783-imx31.c +++ b/firmware/target/arm/imx31/mc13783-imx31.c | |||
@@ -396,6 +396,7 @@ bool mc13783_read_async(struct spi_transfer_desc *xfer, | |||
396 | xfer->rxbuf = buffer; | 396 | xfer->rxbuf = buffer; |
397 | xfer->count = count; | 397 | xfer->count = count; |
398 | xfer->callback = callback; | 398 | xfer->callback = callback; |
399 | xfer->next = NULL; | ||
399 | 400 | ||
400 | return spi_transfer(xfer); | 401 | return spi_transfer(xfer); |
401 | } | 402 | } |
@@ -422,6 +423,7 @@ bool mc13783_write_async(struct spi_transfer_desc *xfer, | |||
422 | xfer->rxbuf = NULL; | 423 | xfer->rxbuf = NULL; |
423 | xfer->count = count; | 424 | xfer->count = count; |
424 | xfer->callback = callback; | 425 | xfer->callback = callback; |
426 | xfer->next = NULL; | ||
425 | 427 | ||
426 | return spi_transfer(xfer); | 428 | return spi_transfer(xfer); |
427 | } | 429 | } |