diff options
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 1220 |
1 files changed, 886 insertions, 334 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index af8e0efedbe4..ebc1e8658226 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mfd/dbx500-prcmu.h> | 30 | #include <linux/mfd/dbx500-prcmu.h> |
31 | #include <linux/regulator/db8500-prcmu.h> | 31 | #include <linux/regulator/db8500-prcmu.h> |
32 | #include <linux/regulator/machine.h> | 32 | #include <linux/regulator/machine.h> |
33 | #include <asm/hardware/gic.h> | ||
33 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
34 | #include <mach/irqs.h> | 35 | #include <mach/irqs.h> |
35 | #include <mach/db8500-regs.h> | 36 | #include <mach/db8500-regs.h> |
@@ -39,11 +40,6 @@ | |||
39 | /* Offset for the firmware version within the TCPM */ | 40 | /* Offset for the firmware version within the TCPM */ |
40 | #define PRCMU_FW_VERSION_OFFSET 0xA4 | 41 | #define PRCMU_FW_VERSION_OFFSET 0xA4 |
41 | 42 | ||
42 | /* PRCMU project numbers, defined by PRCMU FW */ | ||
43 | #define PRCMU_PROJECT_ID_8500V1_0 1 | ||
44 | #define PRCMU_PROJECT_ID_8500V2_0 2 | ||
45 | #define PRCMU_PROJECT_ID_8400V2_0 3 | ||
46 | |||
47 | /* Index of different voltages to be used when accessing AVSData */ | 43 | /* Index of different voltages to be used when accessing AVSData */ |
48 | #define PRCM_AVS_BASE 0x2FC | 44 | #define PRCM_AVS_BASE 0x2FC |
49 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) | 45 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) |
@@ -137,6 +133,8 @@ | |||
137 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) | 133 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) |
138 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) | 134 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) |
139 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) | 135 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) |
136 | #define PLL_SOC0_OFF 0x1 | ||
137 | #define PLL_SOC0_ON 0x2 | ||
140 | #define PLL_SOC1_OFF 0x4 | 138 | #define PLL_SOC1_OFF 0x4 |
141 | #define PLL_SOC1_ON 0x8 | 139 | #define PLL_SOC1_ON 0x8 |
142 | 140 | ||
@@ -266,6 +264,11 @@ | |||
266 | #define WAKEUP_BIT_GPIO7 BIT(30) | 264 | #define WAKEUP_BIT_GPIO7 BIT(30) |
267 | #define WAKEUP_BIT_GPIO8 BIT(31) | 265 | #define WAKEUP_BIT_GPIO8 BIT(31) |
268 | 266 | ||
267 | static struct { | ||
268 | bool valid; | ||
269 | struct prcmu_fw_version version; | ||
270 | } fw_info; | ||
271 | |||
269 | /* | 272 | /* |
270 | * This vector maps irq numbers to the bits in the bit field used in | 273 | * This vector maps irq numbers to the bits in the bit field used in |
271 | * communication with the PRCMU firmware. | 274 | * communication with the PRCMU firmware. |
@@ -341,11 +344,13 @@ static struct { | |||
341 | * mb1_transfer - state needed for mailbox 1 communication. | 344 | * mb1_transfer - state needed for mailbox 1 communication. |
342 | * @lock: The transaction lock. | 345 | * @lock: The transaction lock. |
343 | * @work: The transaction completion structure. | 346 | * @work: The transaction completion structure. |
347 | * @ape_opp: The current APE OPP. | ||
344 | * @ack: Reply ("acknowledge") data. | 348 | * @ack: Reply ("acknowledge") data. |
345 | */ | 349 | */ |
346 | static struct { | 350 | static struct { |
347 | struct mutex lock; | 351 | struct mutex lock; |
348 | struct completion work; | 352 | struct completion work; |
353 | u8 ape_opp; | ||
349 | struct { | 354 | struct { |
350 | u8 header; | 355 | u8 header; |
351 | u8 arm_opp; | 356 | u8 arm_opp; |
@@ -413,79 +418,102 @@ static struct { | |||
413 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); | 418 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); |
414 | 419 | ||
415 | /* Spinlocks */ | 420 | /* Spinlocks */ |
421 | static DEFINE_SPINLOCK(prcmu_lock); | ||
416 | static DEFINE_SPINLOCK(clkout_lock); | 422 | static DEFINE_SPINLOCK(clkout_lock); |
417 | static DEFINE_SPINLOCK(gpiocr_lock); | ||
418 | 423 | ||
419 | /* Global var to runtime determine TCDM base for v2 or v1 */ | 424 | /* Global var to runtime determine TCDM base for v2 or v1 */ |
420 | static __iomem void *tcdm_base; | 425 | static __iomem void *tcdm_base; |
421 | 426 | ||
422 | struct clk_mgt { | 427 | struct clk_mgt { |
423 | unsigned int offset; | 428 | void __iomem *reg; |
424 | u32 pllsw; | 429 | u32 pllsw; |
430 | int branch; | ||
431 | bool clk38div; | ||
432 | }; | ||
433 | |||
434 | enum { | ||
435 | PLL_RAW, | ||
436 | PLL_FIX, | ||
437 | PLL_DIV | ||
425 | }; | 438 | }; |
426 | 439 | ||
427 | static DEFINE_SPINLOCK(clk_mgt_lock); | 440 | static DEFINE_SPINLOCK(clk_mgt_lock); |
428 | 441 | ||
429 | #define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 } | 442 | #define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \ |
443 | { (PRCM_##_name##_MGT), 0 , _branch, _clk38div} | ||
430 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { | 444 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { |
431 | CLK_MGT_ENTRY(SGACLK), | 445 | CLK_MGT_ENTRY(SGACLK, PLL_DIV, false), |
432 | CLK_MGT_ENTRY(UARTCLK), | 446 | CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true), |
433 | CLK_MGT_ENTRY(MSP02CLK), | 447 | CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true), |
434 | CLK_MGT_ENTRY(MSP1CLK), | 448 | CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true), |
435 | CLK_MGT_ENTRY(I2CCLK), | 449 | CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true), |
436 | CLK_MGT_ENTRY(SDMMCCLK), | 450 | CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true), |
437 | CLK_MGT_ENTRY(SLIMCLK), | 451 | CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true), |
438 | CLK_MGT_ENTRY(PER1CLK), | 452 | CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true), |
439 | CLK_MGT_ENTRY(PER2CLK), | 453 | CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true), |
440 | CLK_MGT_ENTRY(PER3CLK), | 454 | CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true), |
441 | CLK_MGT_ENTRY(PER5CLK), | 455 | CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true), |
442 | CLK_MGT_ENTRY(PER6CLK), | 456 | CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true), |
443 | CLK_MGT_ENTRY(PER7CLK), | 457 | CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true), |
444 | CLK_MGT_ENTRY(LCDCLK), | 458 | CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true), |
445 | CLK_MGT_ENTRY(BMLCLK), | 459 | CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true), |
446 | CLK_MGT_ENTRY(HSITXCLK), | 460 | CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true), |
447 | CLK_MGT_ENTRY(HSIRXCLK), | 461 | CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true), |
448 | CLK_MGT_ENTRY(HDMICLK), | 462 | CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false), |
449 | CLK_MGT_ENTRY(APEATCLK), | 463 | CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true), |
450 | CLK_MGT_ENTRY(APETRACECLK), | 464 | CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true), |
451 | CLK_MGT_ENTRY(MCDECLK), | 465 | CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true), |
452 | CLK_MGT_ENTRY(IPI2CCLK), | 466 | CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true), |
453 | CLK_MGT_ENTRY(DSIALTCLK), | 467 | CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false), |
454 | CLK_MGT_ENTRY(DMACLK), | 468 | CLK_MGT_ENTRY(DMACLK, PLL_DIV, true), |
455 | CLK_MGT_ENTRY(B2R2CLK), | 469 | CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true), |
456 | CLK_MGT_ENTRY(TVCLK), | 470 | CLK_MGT_ENTRY(TVCLK, PLL_FIX, true), |
457 | CLK_MGT_ENTRY(SSPCLK), | 471 | CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true), |
458 | CLK_MGT_ENTRY(RNGCLK), | 472 | CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true), |
459 | CLK_MGT_ENTRY(UICCCLK), | 473 | CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false), |
474 | }; | ||
475 | |||
476 | struct dsiclk { | ||
477 | u32 divsel_mask; | ||
478 | u32 divsel_shift; | ||
479 | u32 divsel; | ||
480 | }; | ||
481 | |||
482 | static struct dsiclk dsiclk[2] = { | ||
483 | { | ||
484 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK, | ||
485 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT, | ||
486 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
487 | }, | ||
488 | { | ||
489 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK, | ||
490 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT, | ||
491 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
492 | } | ||
460 | }; | 493 | }; |
461 | 494 | ||
462 | static struct regulator *hwacc_regulator[NUM_HW_ACC]; | 495 | struct dsiescclk { |
463 | static struct regulator *hwacc_ret_regulator[NUM_HW_ACC]; | 496 | u32 en; |
464 | 497 | u32 div_mask; | |
465 | static bool hwacc_enabled[NUM_HW_ACC]; | 498 | u32 div_shift; |
466 | static bool hwacc_ret_enabled[NUM_HW_ACC]; | ||
467 | |||
468 | static const char *hwacc_regulator_name[NUM_HW_ACC] = { | ||
469 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp", | ||
470 | [HW_ACC_SVAPIPE] = "hwacc-sva-pipe", | ||
471 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp", | ||
472 | [HW_ACC_SIAPIPE] = "hwacc-sia-pipe", | ||
473 | [HW_ACC_SGA] = "hwacc-sga", | ||
474 | [HW_ACC_B2R2] = "hwacc-b2r2", | ||
475 | [HW_ACC_MCDE] = "hwacc-mcde", | ||
476 | [HW_ACC_ESRAM1] = "hwacc-esram1", | ||
477 | [HW_ACC_ESRAM2] = "hwacc-esram2", | ||
478 | [HW_ACC_ESRAM3] = "hwacc-esram3", | ||
479 | [HW_ACC_ESRAM4] = "hwacc-esram4", | ||
480 | }; | 499 | }; |
481 | 500 | ||
482 | static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | 501 | static struct dsiescclk dsiescclk[3] = { |
483 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret", | 502 | { |
484 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret", | 503 | .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN, |
485 | [HW_ACC_ESRAM1] = "hwacc-esram1-ret", | 504 | .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK, |
486 | [HW_ACC_ESRAM2] = "hwacc-esram2-ret", | 505 | .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT, |
487 | [HW_ACC_ESRAM3] = "hwacc-esram3-ret", | 506 | }, |
488 | [HW_ACC_ESRAM4] = "hwacc-esram4-ret", | 507 | { |
508 | .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN, | ||
509 | .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK, | ||
510 | .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT, | ||
511 | }, | ||
512 | { | ||
513 | .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN, | ||
514 | .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK, | ||
515 | .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT, | ||
516 | } | ||
489 | }; | 517 | }; |
490 | 518 | ||
491 | /* | 519 | /* |
@@ -503,9 +531,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
503 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ | 531 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ |
504 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C | 532 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C |
505 | 533 | ||
506 | /* PLLDIV=8, PLLSW=4 (PLLDDR) */ | ||
507 | #define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088 | ||
508 | |||
509 | /* DPI 50000000 Hz */ | 534 | /* DPI 50000000 Hz */ |
510 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ | 535 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ |
511 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) | 536 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) |
@@ -514,9 +539,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
514 | /* D=101, N=1, R=4, SELDIV2=0 */ | 539 | /* D=101, N=1, R=4, SELDIV2=0 */ |
515 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 | 540 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 |
516 | 541 | ||
517 | /* D=70, N=1, R=3, SELDIV2=0 */ | ||
518 | #define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146 | ||
519 | |||
520 | #define PRCMU_ENABLE_PLLDSI 0x00000001 | 542 | #define PRCMU_ENABLE_PLLDSI 0x00000001 |
521 | #define PRCMU_DISABLE_PLLDSI 0x00000000 | 543 | #define PRCMU_DISABLE_PLLDSI 0x00000000 |
522 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C | 544 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C |
@@ -528,30 +550,17 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | |||
528 | 550 | ||
529 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 | 551 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 |
530 | 552 | ||
531 | static struct { | ||
532 | u8 project_number; | ||
533 | u8 api_version; | ||
534 | u8 func_version; | ||
535 | u8 errata; | ||
536 | } prcmu_version; | ||
537 | |||
538 | |||
539 | int db8500_prcmu_enable_dsipll(void) | 553 | int db8500_prcmu_enable_dsipll(void) |
540 | { | 554 | { |
541 | int i; | 555 | int i; |
542 | unsigned int plldsifreq; | ||
543 | 556 | ||
544 | /* Clear DSIPLL_RESETN */ | 557 | /* Clear DSIPLL_RESETN */ |
545 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); | 558 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); |
546 | /* Unclamp DSIPLL in/out */ | 559 | /* Unclamp DSIPLL in/out */ |
547 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); | 560 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); |
548 | 561 | ||
549 | if (prcmu_is_u8400()) | ||
550 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; | ||
551 | else | ||
552 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; | ||
553 | /* Set DSI PLL FREQ */ | 562 | /* Set DSI PLL FREQ */ |
554 | writel(plldsifreq, PRCM_PLLDSI_FREQ); | 563 | writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); |
555 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); | 564 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); |
556 | /* Enable Escape clocks */ | 565 | /* Enable Escape clocks */ |
557 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); | 566 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
@@ -583,12 +592,6 @@ int db8500_prcmu_disable_dsipll(void) | |||
583 | int db8500_prcmu_set_display_clocks(void) | 592 | int db8500_prcmu_set_display_clocks(void) |
584 | { | 593 | { |
585 | unsigned long flags; | 594 | unsigned long flags; |
586 | unsigned int dsiclk; | ||
587 | |||
588 | if (prcmu_is_u8400()) | ||
589 | dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400; | ||
590 | else | ||
591 | dsiclk = PRCMU_DSI_CLOCK_SETTING; | ||
592 | 595 | ||
593 | spin_lock_irqsave(&clk_mgt_lock, flags); | 596 | spin_lock_irqsave(&clk_mgt_lock, flags); |
594 | 597 | ||
@@ -596,7 +599,7 @@ int db8500_prcmu_set_display_clocks(void) | |||
596 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 599 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
597 | cpu_relax(); | 600 | cpu_relax(); |
598 | 601 | ||
599 | writel(dsiclk, PRCM_HDMICLK_MGT); | 602 | writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); |
600 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); | 603 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); |
601 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); | 604 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); |
602 | 605 | ||
@@ -608,43 +611,41 @@ int db8500_prcmu_set_display_clocks(void) | |||
608 | return 0; | 611 | return 0; |
609 | } | 612 | } |
610 | 613 | ||
611 | /** | 614 | u32 db8500_prcmu_read(unsigned int reg) |
612 | * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. | 615 | { |
613 | */ | 616 | return readl(_PRCMU_BASE + reg); |
614 | void prcmu_enable_spi2(void) | 617 | } |
618 | |||
619 | void db8500_prcmu_write(unsigned int reg, u32 value) | ||
615 | { | 620 | { |
616 | u32 reg; | ||
617 | unsigned long flags; | 621 | unsigned long flags; |
618 | 622 | ||
619 | spin_lock_irqsave(&gpiocr_lock, flags); | 623 | spin_lock_irqsave(&prcmu_lock, flags); |
620 | reg = readl(PRCM_GPIOCR); | 624 | writel(value, (_PRCMU_BASE + reg)); |
621 | writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); | 625 | spin_unlock_irqrestore(&prcmu_lock, flags); |
622 | spin_unlock_irqrestore(&gpiocr_lock, flags); | ||
623 | } | 626 | } |
624 | 627 | ||
625 | /** | 628 | void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) |
626 | * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. | ||
627 | */ | ||
628 | void prcmu_disable_spi2(void) | ||
629 | { | 629 | { |
630 | u32 reg; | 630 | u32 val; |
631 | unsigned long flags; | 631 | unsigned long flags; |
632 | 632 | ||
633 | spin_lock_irqsave(&gpiocr_lock, flags); | 633 | spin_lock_irqsave(&prcmu_lock, flags); |
634 | reg = readl(PRCM_GPIOCR); | 634 | val = readl(_PRCMU_BASE + reg); |
635 | writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); | 635 | val = ((val & ~mask) | (value & mask)); |
636 | spin_unlock_irqrestore(&gpiocr_lock, flags); | 636 | writel(val, (_PRCMU_BASE + reg)); |
637 | spin_unlock_irqrestore(&prcmu_lock, flags); | ||
637 | } | 638 | } |
638 | 639 | ||
639 | bool prcmu_has_arm_maxopp(void) | 640 | struct prcmu_fw_version *prcmu_get_fw_version(void) |
640 | { | 641 | { |
641 | return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & | 642 | return fw_info.valid ? &fw_info.version : NULL; |
642 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; | ||
643 | } | 643 | } |
644 | 644 | ||
645 | bool prcmu_is_u8400(void) | 645 | bool prcmu_has_arm_maxopp(void) |
646 | { | 646 | { |
647 | return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0; | 647 | return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & |
648 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; | ||
648 | } | 649 | } |
649 | 650 | ||
650 | /** | 651 | /** |
@@ -787,6 +788,124 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
787 | return 0; | 788 | return 0; |
788 | } | 789 | } |
789 | 790 | ||
791 | u8 db8500_prcmu_get_power_state_result(void) | ||
792 | { | ||
793 | return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS); | ||
794 | } | ||
795 | |||
796 | /* This function decouple the gic from the prcmu */ | ||
797 | int db8500_prcmu_gic_decouple(void) | ||
798 | { | ||
799 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
800 | |||
801 | /* Set bit 0 register value to 1 */ | ||
802 | writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, | ||
803 | PRCM_A9_MASK_REQ); | ||
804 | |||
805 | /* Make sure the register is updated */ | ||
806 | readl(PRCM_A9_MASK_REQ); | ||
807 | |||
808 | /* Wait a few cycles for the gic mask completion */ | ||
809 | udelay(1); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | /* This function recouple the gic with the prcmu */ | ||
815 | int db8500_prcmu_gic_recouple(void) | ||
816 | { | ||
817 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
818 | |||
819 | /* Set bit 0 register value to 0 */ | ||
820 | writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ); | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | #define PRCMU_GIC_NUMBER_REGS 5 | ||
826 | |||
827 | /* | ||
828 | * This function checks if there are pending irq on the gic. It only | ||
829 | * makes sense if the gic has been decoupled before with the | ||
830 | * db8500_prcmu_gic_decouple function. Disabling an interrupt only | ||
831 | * disables the forwarding of the interrupt to any CPU interface. It | ||
832 | * does not prevent the interrupt from changing state, for example | ||
833 | * becoming pending, or active and pending if it is already | ||
834 | * active. Hence, we have to check the interrupt is pending *and* is | ||
835 | * active. | ||
836 | */ | ||
837 | bool db8500_prcmu_gic_pending_irq(void) | ||
838 | { | ||
839 | u32 pr; /* Pending register */ | ||
840 | u32 er; /* Enable register */ | ||
841 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
842 | int i; | ||
843 | |||
844 | /* 5 registers. STI & PPI not skipped */ | ||
845 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) { | ||
846 | |||
847 | pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4); | ||
848 | er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); | ||
849 | |||
850 | if (pr & er) | ||
851 | return true; /* There is a pending interrupt */ | ||
852 | } | ||
853 | |||
854 | return false; | ||
855 | } | ||
856 | |||
857 | /* | ||
858 | * This function checks if there are pending interrupt on the | ||
859 | * prcmu which has been delegated to monitor the irqs with the | ||
860 | * db8500_prcmu_copy_gic_settings function. | ||
861 | */ | ||
862 | bool db8500_prcmu_pending_irq(void) | ||
863 | { | ||
864 | u32 it, im; | ||
865 | int i; | ||
866 | |||
867 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
868 | it = readl(PRCM_ARMITVAL31TO0 + i * 4); | ||
869 | im = readl(PRCM_ARMITMSK31TO0 + i * 4); | ||
870 | if (it & im) | ||
871 | return true; /* There is a pending interrupt */ | ||
872 | } | ||
873 | |||
874 | return false; | ||
875 | } | ||
876 | |||
877 | /* | ||
878 | * This function checks if the specified cpu is in in WFI. It's usage | ||
879 | * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple | ||
880 | * function. Of course passing smp_processor_id() to this function will | ||
881 | * always return false... | ||
882 | */ | ||
883 | bool db8500_prcmu_is_cpu_in_wfi(int cpu) | ||
884 | { | ||
885 | return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : | ||
886 | PRCM_ARM_WFI_STANDBY_WFI0; | ||
887 | } | ||
888 | |||
889 | /* | ||
890 | * This function copies the gic SPI settings to the prcmu in order to | ||
891 | * monitor them and abort/finish the retention/off sequence or state. | ||
892 | */ | ||
893 | int db8500_prcmu_copy_gic_settings(void) | ||
894 | { | ||
895 | u32 er; /* Enable register */ | ||
896 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
897 | int i; | ||
898 | |||
899 | /* We skip the STI and PPI */ | ||
900 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
901 | er = readl_relaxed(dist_base + | ||
902 | GIC_DIST_ENABLE_SET + (i + 1) * 4); | ||
903 | writel(er, PRCM_ARMITMSK31TO0 + i * 4); | ||
904 | } | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
790 | /* This function should only be called while mb0_transfer.lock is held. */ | 909 | /* This function should only be called while mb0_transfer.lock is held. */ |
791 | static void config_wakeups(void) | 910 | static void config_wakeups(void) |
792 | { | 911 | { |
@@ -909,23 +1028,23 @@ int db8500_prcmu_get_arm_opp(void) | |||
909 | } | 1028 | } |
910 | 1029 | ||
911 | /** | 1030 | /** |
912 | * prcmu_get_ddr_opp - get the current DDR OPP | 1031 | * db8500_prcmu_get_ddr_opp - get the current DDR OPP |
913 | * | 1032 | * |
914 | * Returns: the current DDR OPP | 1033 | * Returns: the current DDR OPP |
915 | */ | 1034 | */ |
916 | int prcmu_get_ddr_opp(void) | 1035 | int db8500_prcmu_get_ddr_opp(void) |
917 | { | 1036 | { |
918 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); | 1037 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); |
919 | } | 1038 | } |
920 | 1039 | ||
921 | /** | 1040 | /** |
922 | * set_ddr_opp - set the appropriate DDR OPP | 1041 | * db8500_set_ddr_opp - set the appropriate DDR OPP |
923 | * @opp: The new DDR operating point to which transition is to be made | 1042 | * @opp: The new DDR operating point to which transition is to be made |
924 | * Returns: 0 on success, non-zero on failure | 1043 | * Returns: 0 on success, non-zero on failure |
925 | * | 1044 | * |
926 | * This function sets the operating point of the DDR. | 1045 | * This function sets the operating point of the DDR. |
927 | */ | 1046 | */ |
928 | int prcmu_set_ddr_opp(u8 opp) | 1047 | int db8500_prcmu_set_ddr_opp(u8 opp) |
929 | { | 1048 | { |
930 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) | 1049 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) |
931 | return -EINVAL; | 1050 | return -EINVAL; |
@@ -935,25 +1054,82 @@ int prcmu_set_ddr_opp(u8 opp) | |||
935 | 1054 | ||
936 | return 0; | 1055 | return 0; |
937 | } | 1056 | } |
1057 | |||
1058 | /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ | ||
1059 | static void request_even_slower_clocks(bool enable) | ||
1060 | { | ||
1061 | void __iomem *clock_reg[] = { | ||
1062 | PRCM_ACLK_MGT, | ||
1063 | PRCM_DMACLK_MGT | ||
1064 | }; | ||
1065 | unsigned long flags; | ||
1066 | unsigned int i; | ||
1067 | |||
1068 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
1069 | |||
1070 | /* Grab the HW semaphore. */ | ||
1071 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
1072 | cpu_relax(); | ||
1073 | |||
1074 | for (i = 0; i < ARRAY_SIZE(clock_reg); i++) { | ||
1075 | u32 val; | ||
1076 | u32 div; | ||
1077 | |||
1078 | val = readl(clock_reg[i]); | ||
1079 | div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
1080 | if (enable) { | ||
1081 | if ((div <= 1) || (div > 15)) { | ||
1082 | pr_err("prcmu: Bad clock divider %d in %s\n", | ||
1083 | div, __func__); | ||
1084 | goto unlock_and_return; | ||
1085 | } | ||
1086 | div <<= 1; | ||
1087 | } else { | ||
1088 | if (div <= 2) | ||
1089 | goto unlock_and_return; | ||
1090 | div >>= 1; | ||
1091 | } | ||
1092 | val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) | | ||
1093 | (div & PRCM_CLK_MGT_CLKPLLDIV_MASK)); | ||
1094 | writel(val, clock_reg[i]); | ||
1095 | } | ||
1096 | |||
1097 | unlock_and_return: | ||
1098 | /* Release the HW semaphore. */ | ||
1099 | writel(0, PRCM_SEM); | ||
1100 | |||
1101 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
1102 | } | ||
1103 | |||
938 | /** | 1104 | /** |
939 | * set_ape_opp - set the appropriate APE OPP | 1105 | * db8500_set_ape_opp - set the appropriate APE OPP |
940 | * @opp: The new APE operating point to which transition is to be made | 1106 | * @opp: The new APE operating point to which transition is to be made |
941 | * Returns: 0 on success, non-zero on failure | 1107 | * Returns: 0 on success, non-zero on failure |
942 | * | 1108 | * |
943 | * This function sets the operating point of the APE. | 1109 | * This function sets the operating point of the APE. |
944 | */ | 1110 | */ |
945 | int prcmu_set_ape_opp(u8 opp) | 1111 | int db8500_prcmu_set_ape_opp(u8 opp) |
946 | { | 1112 | { |
947 | int r = 0; | 1113 | int r = 0; |
948 | 1114 | ||
1115 | if (opp == mb1_transfer.ape_opp) | ||
1116 | return 0; | ||
1117 | |||
949 | mutex_lock(&mb1_transfer.lock); | 1118 | mutex_lock(&mb1_transfer.lock); |
950 | 1119 | ||
1120 | if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP) | ||
1121 | request_even_slower_clocks(false); | ||
1122 | |||
1123 | if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP)) | ||
1124 | goto skip_message; | ||
1125 | |||
951 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1126 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
952 | cpu_relax(); | 1127 | cpu_relax(); |
953 | 1128 | ||
954 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1129 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
955 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 1130 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
956 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | 1131 | writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp), |
1132 | (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | ||
957 | 1133 | ||
958 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 1134 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
959 | wait_for_completion(&mb1_transfer.work); | 1135 | wait_for_completion(&mb1_transfer.work); |
@@ -962,17 +1138,24 @@ int prcmu_set_ape_opp(u8 opp) | |||
962 | (mb1_transfer.ack.ape_opp != opp)) | 1138 | (mb1_transfer.ack.ape_opp != opp)) |
963 | r = -EIO; | 1139 | r = -EIO; |
964 | 1140 | ||
1141 | skip_message: | ||
1142 | if ((!r && (opp == APE_50_PARTLY_25_OPP)) || | ||
1143 | (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP))) | ||
1144 | request_even_slower_clocks(true); | ||
1145 | if (!r) | ||
1146 | mb1_transfer.ape_opp = opp; | ||
1147 | |||
965 | mutex_unlock(&mb1_transfer.lock); | 1148 | mutex_unlock(&mb1_transfer.lock); |
966 | 1149 | ||
967 | return r; | 1150 | return r; |
968 | } | 1151 | } |
969 | 1152 | ||
970 | /** | 1153 | /** |
971 | * prcmu_get_ape_opp - get the current APE OPP | 1154 | * db8500_prcmu_get_ape_opp - get the current APE OPP |
972 | * | 1155 | * |
973 | * Returns: the current APE OPP | 1156 | * Returns: the current APE OPP |
974 | */ | 1157 | */ |
975 | int prcmu_get_ape_opp(void) | 1158 | int db8500_prcmu_get_ape_opp(void) |
976 | { | 1159 | { |
977 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); | 1160 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); |
978 | } | 1161 | } |
@@ -1056,7 +1239,9 @@ static int request_pll(u8 clock, bool enable) | |||
1056 | { | 1239 | { |
1057 | int r = 0; | 1240 | int r = 0; |
1058 | 1241 | ||
1059 | if (clock == PRCMU_PLLSOC1) | 1242 | if (clock == PRCMU_PLLSOC0) |
1243 | clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF); | ||
1244 | else if (clock == PRCMU_PLLSOC1) | ||
1060 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); | 1245 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); |
1061 | else | 1246 | else |
1062 | return -EINVAL; | 1247 | return -EINVAL; |
@@ -1081,132 +1266,6 @@ static int request_pll(u8 clock, bool enable) | |||
1081 | } | 1266 | } |
1082 | 1267 | ||
1083 | /** | 1268 | /** |
1084 | * prcmu_set_hwacc - set the power state of a h/w accelerator | ||
1085 | * @hwacc_dev: The hardware accelerator (enum hw_acc_dev). | ||
1086 | * @state: The new power state (enum hw_acc_state). | ||
1087 | * | ||
1088 | * This function sets the power state of a hardware accelerator. | ||
1089 | * This function should not be called from interrupt context. | ||
1090 | * | ||
1091 | * NOTE! Deprecated, to be removed when all users switched over to use the | ||
1092 | * regulator framework API. | ||
1093 | */ | ||
1094 | int prcmu_set_hwacc(u16 hwacc_dev, u8 state) | ||
1095 | { | ||
1096 | int r = 0; | ||
1097 | bool ram_retention = false; | ||
1098 | bool enable, enable_ret; | ||
1099 | |||
1100 | /* check argument */ | ||
1101 | BUG_ON(hwacc_dev >= NUM_HW_ACC); | ||
1102 | |||
1103 | /* get state of switches */ | ||
1104 | enable = hwacc_enabled[hwacc_dev]; | ||
1105 | enable_ret = hwacc_ret_enabled[hwacc_dev]; | ||
1106 | |||
1107 | /* set flag if retention is possible */ | ||
1108 | switch (hwacc_dev) { | ||
1109 | case HW_ACC_SVAMMDSP: | ||
1110 | case HW_ACC_SIAMMDSP: | ||
1111 | case HW_ACC_ESRAM1: | ||
1112 | case HW_ACC_ESRAM2: | ||
1113 | case HW_ACC_ESRAM3: | ||
1114 | case HW_ACC_ESRAM4: | ||
1115 | ram_retention = true; | ||
1116 | break; | ||
1117 | } | ||
1118 | |||
1119 | /* check argument */ | ||
1120 | BUG_ON(state > HW_ON); | ||
1121 | BUG_ON(state == HW_OFF_RAMRET && !ram_retention); | ||
1122 | |||
1123 | /* modify enable flags */ | ||
1124 | switch (state) { | ||
1125 | case HW_OFF: | ||
1126 | enable_ret = false; | ||
1127 | enable = false; | ||
1128 | break; | ||
1129 | case HW_ON: | ||
1130 | enable = true; | ||
1131 | break; | ||
1132 | case HW_OFF_RAMRET: | ||
1133 | enable_ret = true; | ||
1134 | enable = false; | ||
1135 | break; | ||
1136 | } | ||
1137 | |||
1138 | /* get regulator (lazy) */ | ||
1139 | if (hwacc_regulator[hwacc_dev] == NULL) { | ||
1140 | hwacc_regulator[hwacc_dev] = regulator_get(NULL, | ||
1141 | hwacc_regulator_name[hwacc_dev]); | ||
1142 | if (IS_ERR(hwacc_regulator[hwacc_dev])) { | ||
1143 | pr_err("prcmu: failed to get supply %s\n", | ||
1144 | hwacc_regulator_name[hwacc_dev]); | ||
1145 | r = PTR_ERR(hwacc_regulator[hwacc_dev]); | ||
1146 | goto out; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | if (ram_retention) { | ||
1151 | if (hwacc_ret_regulator[hwacc_dev] == NULL) { | ||
1152 | hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL, | ||
1153 | hwacc_ret_regulator_name[hwacc_dev]); | ||
1154 | if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) { | ||
1155 | pr_err("prcmu: failed to get supply %s\n", | ||
1156 | hwacc_ret_regulator_name[hwacc_dev]); | ||
1157 | r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]); | ||
1158 | goto out; | ||
1159 | } | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | /* set regulators */ | ||
1164 | if (ram_retention) { | ||
1165 | if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) { | ||
1166 | r = regulator_enable(hwacc_ret_regulator[hwacc_dev]); | ||
1167 | if (r < 0) { | ||
1168 | pr_err("prcmu_set_hwacc: ret enable failed\n"); | ||
1169 | goto out; | ||
1170 | } | ||
1171 | hwacc_ret_enabled[hwacc_dev] = true; | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | if (enable && !hwacc_enabled[hwacc_dev]) { | ||
1176 | r = regulator_enable(hwacc_regulator[hwacc_dev]); | ||
1177 | if (r < 0) { | ||
1178 | pr_err("prcmu_set_hwacc: enable failed\n"); | ||
1179 | goto out; | ||
1180 | } | ||
1181 | hwacc_enabled[hwacc_dev] = true; | ||
1182 | } | ||
1183 | |||
1184 | if (!enable && hwacc_enabled[hwacc_dev]) { | ||
1185 | r = regulator_disable(hwacc_regulator[hwacc_dev]); | ||
1186 | if (r < 0) { | ||
1187 | pr_err("prcmu_set_hwacc: disable failed\n"); | ||
1188 | goto out; | ||
1189 | } | ||
1190 | hwacc_enabled[hwacc_dev] = false; | ||
1191 | } | ||
1192 | |||
1193 | if (ram_retention) { | ||
1194 | if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) { | ||
1195 | r = regulator_disable(hwacc_ret_regulator[hwacc_dev]); | ||
1196 | if (r < 0) { | ||
1197 | pr_err("prcmu_set_hwacc: ret disable failed\n"); | ||
1198 | goto out; | ||
1199 | } | ||
1200 | hwacc_ret_enabled[hwacc_dev] = false; | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | out: | ||
1205 | return r; | ||
1206 | } | ||
1207 | EXPORT_SYMBOL(prcmu_set_hwacc); | ||
1208 | |||
1209 | /** | ||
1210 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) | 1269 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) |
1211 | * @epod_id: The EPOD to set | 1270 | * @epod_id: The EPOD to set |
1212 | * @epod_state: The new EPOD state | 1271 | * @epod_state: The new EPOD state |
@@ -1375,7 +1434,7 @@ static int request_timclk(bool enable) | |||
1375 | return 0; | 1434 | return 0; |
1376 | } | 1435 | } |
1377 | 1436 | ||
1378 | static int request_reg_clock(u8 clock, bool enable) | 1437 | static int request_clock(u8 clock, bool enable) |
1379 | { | 1438 | { |
1380 | u32 val; | 1439 | u32 val; |
1381 | unsigned long flags; | 1440 | unsigned long flags; |
@@ -1386,14 +1445,14 @@ static int request_reg_clock(u8 clock, bool enable) | |||
1386 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 1445 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
1387 | cpu_relax(); | 1446 | cpu_relax(); |
1388 | 1447 | ||
1389 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | 1448 | val = readl(clk_mgt[clock].reg); |
1390 | if (enable) { | 1449 | if (enable) { |
1391 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); | 1450 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); |
1392 | } else { | 1451 | } else { |
1393 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | 1452 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); |
1394 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); | 1453 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); |
1395 | } | 1454 | } |
1396 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | 1455 | writel(val, clk_mgt[clock].reg); |
1397 | 1456 | ||
1398 | /* Release the HW semaphore. */ | 1457 | /* Release the HW semaphore. */ |
1399 | writel(0, PRCM_SEM); | 1458 | writel(0, PRCM_SEM); |
@@ -1413,7 +1472,7 @@ static int request_sga_clock(u8 clock, bool enable) | |||
1413 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | 1472 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); |
1414 | } | 1473 | } |
1415 | 1474 | ||
1416 | ret = request_reg_clock(clock, enable); | 1475 | ret = request_clock(clock, enable); |
1417 | 1476 | ||
1418 | if (!ret && !enable) { | 1477 | if (!ret && !enable) { |
1419 | val = readl(PRCM_CGATING_BYPASS); | 1478 | val = readl(PRCM_CGATING_BYPASS); |
@@ -1423,6 +1482,78 @@ static int request_sga_clock(u8 clock, bool enable) | |||
1423 | return ret; | 1482 | return ret; |
1424 | } | 1483 | } |
1425 | 1484 | ||
1485 | static inline bool plldsi_locked(void) | ||
1486 | { | ||
1487 | return (readl(PRCM_PLLDSI_LOCKP) & | ||
1488 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
1489 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) == | ||
1490 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
1491 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3); | ||
1492 | } | ||
1493 | |||
1494 | static int request_plldsi(bool enable) | ||
1495 | { | ||
1496 | int r = 0; | ||
1497 | u32 val; | ||
1498 | |||
1499 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
1500 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ? | ||
1501 | PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET)); | ||
1502 | |||
1503 | val = readl(PRCM_PLLDSI_ENABLE); | ||
1504 | if (enable) | ||
1505 | val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1506 | else | ||
1507 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1508 | writel(val, PRCM_PLLDSI_ENABLE); | ||
1509 | |||
1510 | if (enable) { | ||
1511 | unsigned int i; | ||
1512 | bool locked = plldsi_locked(); | ||
1513 | |||
1514 | for (i = 10; !locked && (i > 0); --i) { | ||
1515 | udelay(100); | ||
1516 | locked = plldsi_locked(); | ||
1517 | } | ||
1518 | if (locked) { | ||
1519 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, | ||
1520 | PRCM_APE_RESETN_SET); | ||
1521 | } else { | ||
1522 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
1523 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), | ||
1524 | PRCM_MMIP_LS_CLAMP_SET); | ||
1525 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1526 | writel(val, PRCM_PLLDSI_ENABLE); | ||
1527 | r = -EAGAIN; | ||
1528 | } | ||
1529 | } else { | ||
1530 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR); | ||
1531 | } | ||
1532 | return r; | ||
1533 | } | ||
1534 | |||
1535 | static int request_dsiclk(u8 n, bool enable) | ||
1536 | { | ||
1537 | u32 val; | ||
1538 | |||
1539 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
1540 | val &= ~dsiclk[n].divsel_mask; | ||
1541 | val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) << | ||
1542 | dsiclk[n].divsel_shift); | ||
1543 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | static int request_dsiescclk(u8 n, bool enable) | ||
1548 | { | ||
1549 | u32 val; | ||
1550 | |||
1551 | val = readl(PRCM_DSITVCLK_DIV); | ||
1552 | enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en); | ||
1553 | writel(val, PRCM_DSITVCLK_DIV); | ||
1554 | return 0; | ||
1555 | } | ||
1556 | |||
1426 | /** | 1557 | /** |
1427 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. | 1558 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. |
1428 | * @clock: The clock for which the request is made. | 1559 | * @clock: The clock for which the request is made. |
@@ -1433,21 +1564,435 @@ static int request_sga_clock(u8 clock, bool enable) | |||
1433 | */ | 1564 | */ |
1434 | int db8500_prcmu_request_clock(u8 clock, bool enable) | 1565 | int db8500_prcmu_request_clock(u8 clock, bool enable) |
1435 | { | 1566 | { |
1436 | switch(clock) { | 1567 | if (clock == PRCMU_SGACLK) |
1437 | case PRCMU_SGACLK: | ||
1438 | return request_sga_clock(clock, enable); | 1568 | return request_sga_clock(clock, enable); |
1439 | case PRCMU_TIMCLK: | 1569 | else if (clock < PRCMU_NUM_REG_CLOCKS) |
1570 | return request_clock(clock, enable); | ||
1571 | else if (clock == PRCMU_TIMCLK) | ||
1440 | return request_timclk(enable); | 1572 | return request_timclk(enable); |
1441 | case PRCMU_SYSCLK: | 1573 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) |
1574 | return request_dsiclk((clock - PRCMU_DSI0CLK), enable); | ||
1575 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1576 | return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable); | ||
1577 | else if (clock == PRCMU_PLLDSI) | ||
1578 | return request_plldsi(enable); | ||
1579 | else if (clock == PRCMU_SYSCLK) | ||
1442 | return request_sysclk(enable); | 1580 | return request_sysclk(enable); |
1443 | case PRCMU_PLLSOC1: | 1581 | else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1)) |
1444 | return request_pll(clock, enable); | 1582 | return request_pll(clock, enable); |
1583 | else | ||
1584 | return -EINVAL; | ||
1585 | } | ||
1586 | |||
1587 | static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, | ||
1588 | int branch) | ||
1589 | { | ||
1590 | u64 rate; | ||
1591 | u32 val; | ||
1592 | u32 d; | ||
1593 | u32 div = 1; | ||
1594 | |||
1595 | val = readl(reg); | ||
1596 | |||
1597 | rate = src_rate; | ||
1598 | rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT); | ||
1599 | |||
1600 | d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT); | ||
1601 | if (d > 1) | ||
1602 | div *= d; | ||
1603 | |||
1604 | d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT); | ||
1605 | if (d > 1) | ||
1606 | div *= d; | ||
1607 | |||
1608 | if (val & PRCM_PLL_FREQ_SELDIV2) | ||
1609 | div *= 2; | ||
1610 | |||
1611 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && | ||
1612 | (val & PRCM_PLL_FREQ_DIV2EN) && | ||
1613 | ((reg == PRCM_PLLSOC0_FREQ) || | ||
1614 | (reg == PRCM_PLLDDR_FREQ)))) | ||
1615 | div *= 2; | ||
1616 | |||
1617 | (void)do_div(rate, div); | ||
1618 | |||
1619 | return (unsigned long)rate; | ||
1620 | } | ||
1621 | |||
1622 | #define ROOT_CLOCK_RATE 38400000 | ||
1623 | |||
1624 | static unsigned long clock_rate(u8 clock) | ||
1625 | { | ||
1626 | u32 val; | ||
1627 | u32 pllsw; | ||
1628 | unsigned long rate = ROOT_CLOCK_RATE; | ||
1629 | |||
1630 | val = readl(clk_mgt[clock].reg); | ||
1631 | |||
1632 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1633 | if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV)) | ||
1634 | rate /= 2; | ||
1635 | return rate; | ||
1636 | } | ||
1637 | |||
1638 | val |= clk_mgt[clock].pllsw; | ||
1639 | pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | ||
1640 | |||
1641 | if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
1642 | rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch); | ||
1643 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
1644 | rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch); | ||
1645 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
1646 | rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch); | ||
1647 | else | ||
1648 | return 0; | ||
1649 | |||
1650 | if ((clock == PRCMU_SGACLK) && | ||
1651 | (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) { | ||
1652 | u64 r = (rate * 10); | ||
1653 | |||
1654 | (void)do_div(r, 25); | ||
1655 | return (unsigned long)r; | ||
1656 | } | ||
1657 | val &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1658 | if (val) | ||
1659 | return rate / val; | ||
1660 | else | ||
1661 | return 0; | ||
1662 | } | ||
1663 | |||
1664 | static unsigned long dsiclk_rate(u8 n) | ||
1665 | { | ||
1666 | u32 divsel; | ||
1667 | u32 div = 1; | ||
1668 | |||
1669 | divsel = readl(PRCM_DSI_PLLOUT_SEL); | ||
1670 | divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift); | ||
1671 | |||
1672 | if (divsel == PRCM_DSI_PLLOUT_SEL_OFF) | ||
1673 | divsel = dsiclk[n].divsel; | ||
1674 | |||
1675 | switch (divsel) { | ||
1676 | case PRCM_DSI_PLLOUT_SEL_PHI_4: | ||
1677 | div *= 2; | ||
1678 | case PRCM_DSI_PLLOUT_SEL_PHI_2: | ||
1679 | div *= 2; | ||
1680 | case PRCM_DSI_PLLOUT_SEL_PHI: | ||
1681 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1682 | PLL_RAW) / div; | ||
1445 | default: | 1683 | default: |
1446 | break; | 1684 | return 0; |
1685 | } | ||
1686 | } | ||
1687 | |||
1688 | static unsigned long dsiescclk_rate(u8 n) | ||
1689 | { | ||
1690 | u32 div; | ||
1691 | |||
1692 | div = readl(PRCM_DSITVCLK_DIV); | ||
1693 | div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift)); | ||
1694 | return clock_rate(PRCMU_TVCLK) / max((u32)1, div); | ||
1695 | } | ||
1696 | |||
1697 | unsigned long prcmu_clock_rate(u8 clock) | ||
1698 | { | ||
1699 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1700 | return clock_rate(clock); | ||
1701 | else if (clock == PRCMU_TIMCLK) | ||
1702 | return ROOT_CLOCK_RATE / 16; | ||
1703 | else if (clock == PRCMU_SYSCLK) | ||
1704 | return ROOT_CLOCK_RATE; | ||
1705 | else if (clock == PRCMU_PLLSOC0) | ||
1706 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1707 | else if (clock == PRCMU_PLLSOC1) | ||
1708 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1709 | else if (clock == PRCMU_PLLDDR) | ||
1710 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1711 | else if (clock == PRCMU_PLLDSI) | ||
1712 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1713 | PLL_RAW); | ||
1714 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1715 | return dsiclk_rate(clock - PRCMU_DSI0CLK); | ||
1716 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1717 | return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK); | ||
1718 | else | ||
1719 | return 0; | ||
1720 | } | ||
1721 | |||
1722 | static unsigned long clock_source_rate(u32 clk_mgt_val, int branch) | ||
1723 | { | ||
1724 | if (clk_mgt_val & PRCM_CLK_MGT_CLK38) | ||
1725 | return ROOT_CLOCK_RATE; | ||
1726 | clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK; | ||
1727 | if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
1728 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch); | ||
1729 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
1730 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch); | ||
1731 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
1732 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch); | ||
1733 | else | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static u32 clock_divider(unsigned long src_rate, unsigned long rate) | ||
1738 | { | ||
1739 | u32 div; | ||
1740 | |||
1741 | div = (src_rate / rate); | ||
1742 | if (div == 0) | ||
1743 | return 1; | ||
1744 | if (rate < (src_rate / div)) | ||
1745 | div++; | ||
1746 | return div; | ||
1747 | } | ||
1748 | |||
1749 | static long round_clock_rate(u8 clock, unsigned long rate) | ||
1750 | { | ||
1751 | u32 val; | ||
1752 | u32 div; | ||
1753 | unsigned long src_rate; | ||
1754 | long rounded_rate; | ||
1755 | |||
1756 | val = readl(clk_mgt[clock].reg); | ||
1757 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
1758 | clk_mgt[clock].branch); | ||
1759 | div = clock_divider(src_rate, rate); | ||
1760 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1761 | if (clk_mgt[clock].clk38div) { | ||
1762 | if (div > 2) | ||
1763 | div = 2; | ||
1764 | } else { | ||
1765 | div = 1; | ||
1766 | } | ||
1767 | } else if ((clock == PRCMU_SGACLK) && (div == 3)) { | ||
1768 | u64 r = (src_rate * 10); | ||
1769 | |||
1770 | (void)do_div(r, 25); | ||
1771 | if (r <= rate) | ||
1772 | return (unsigned long)r; | ||
1773 | } | ||
1774 | rounded_rate = (src_rate / min(div, (u32)31)); | ||
1775 | |||
1776 | return rounded_rate; | ||
1777 | } | ||
1778 | |||
1779 | #define MIN_PLL_VCO_RATE 600000000ULL | ||
1780 | #define MAX_PLL_VCO_RATE 1680640000ULL | ||
1781 | |||
1782 | static long round_plldsi_rate(unsigned long rate) | ||
1783 | { | ||
1784 | long rounded_rate = 0; | ||
1785 | unsigned long src_rate; | ||
1786 | unsigned long rem; | ||
1787 | u32 r; | ||
1788 | |||
1789 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
1790 | rem = rate; | ||
1791 | |||
1792 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
1793 | u64 d; | ||
1794 | |||
1795 | d = (r * rate); | ||
1796 | (void)do_div(d, src_rate); | ||
1797 | if (d < 6) | ||
1798 | d = 6; | ||
1799 | else if (d > 255) | ||
1800 | d = 255; | ||
1801 | d *= src_rate; | ||
1802 | if (((2 * d) < (r * MIN_PLL_VCO_RATE)) || | ||
1803 | ((r * MAX_PLL_VCO_RATE) < (2 * d))) | ||
1804 | continue; | ||
1805 | (void)do_div(d, r); | ||
1806 | if (rate < d) { | ||
1807 | if (rounded_rate == 0) | ||
1808 | rounded_rate = (long)d; | ||
1809 | break; | ||
1810 | } | ||
1811 | if ((rate - d) < rem) { | ||
1812 | rem = (rate - d); | ||
1813 | rounded_rate = (long)d; | ||
1814 | } | ||
1815 | } | ||
1816 | return rounded_rate; | ||
1817 | } | ||
1818 | |||
1819 | static long round_dsiclk_rate(unsigned long rate) | ||
1820 | { | ||
1821 | u32 div; | ||
1822 | unsigned long src_rate; | ||
1823 | long rounded_rate; | ||
1824 | |||
1825 | src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1826 | PLL_RAW); | ||
1827 | div = clock_divider(src_rate, rate); | ||
1828 | rounded_rate = (src_rate / ((div > 2) ? 4 : div)); | ||
1829 | |||
1830 | return rounded_rate; | ||
1831 | } | ||
1832 | |||
1833 | static long round_dsiescclk_rate(unsigned long rate) | ||
1834 | { | ||
1835 | u32 div; | ||
1836 | unsigned long src_rate; | ||
1837 | long rounded_rate; | ||
1838 | |||
1839 | src_rate = clock_rate(PRCMU_TVCLK); | ||
1840 | div = clock_divider(src_rate, rate); | ||
1841 | rounded_rate = (src_rate / min(div, (u32)255)); | ||
1842 | |||
1843 | return rounded_rate; | ||
1844 | } | ||
1845 | |||
1846 | long prcmu_round_clock_rate(u8 clock, unsigned long rate) | ||
1847 | { | ||
1848 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1849 | return round_clock_rate(clock, rate); | ||
1850 | else if (clock == PRCMU_PLLDSI) | ||
1851 | return round_plldsi_rate(rate); | ||
1852 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1853 | return round_dsiclk_rate(rate); | ||
1854 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1855 | return round_dsiescclk_rate(rate); | ||
1856 | else | ||
1857 | return (long)prcmu_clock_rate(clock); | ||
1858 | } | ||
1859 | |||
1860 | static void set_clock_rate(u8 clock, unsigned long rate) | ||
1861 | { | ||
1862 | u32 val; | ||
1863 | u32 div; | ||
1864 | unsigned long src_rate; | ||
1865 | unsigned long flags; | ||
1866 | |||
1867 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
1868 | |||
1869 | /* Grab the HW semaphore. */ | ||
1870 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
1871 | cpu_relax(); | ||
1872 | |||
1873 | val = readl(clk_mgt[clock].reg); | ||
1874 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
1875 | clk_mgt[clock].branch); | ||
1876 | div = clock_divider(src_rate, rate); | ||
1877 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1878 | if (clk_mgt[clock].clk38div) { | ||
1879 | if (div > 1) | ||
1880 | val |= PRCM_CLK_MGT_CLK38DIV; | ||
1881 | else | ||
1882 | val &= ~PRCM_CLK_MGT_CLK38DIV; | ||
1883 | } | ||
1884 | } else if (clock == PRCMU_SGACLK) { | ||
1885 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK | | ||
1886 | PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN); | ||
1887 | if (div == 3) { | ||
1888 | u64 r = (src_rate * 10); | ||
1889 | |||
1890 | (void)do_div(r, 25); | ||
1891 | if (r <= rate) { | ||
1892 | val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN; | ||
1893 | div = 0; | ||
1894 | } | ||
1895 | } | ||
1896 | val |= min(div, (u32)31); | ||
1897 | } else { | ||
1898 | val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1899 | val |= min(div, (u32)31); | ||
1900 | } | ||
1901 | writel(val, clk_mgt[clock].reg); | ||
1902 | |||
1903 | /* Release the HW semaphore. */ | ||
1904 | writel(0, PRCM_SEM); | ||
1905 | |||
1906 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
1907 | } | ||
1908 | |||
1909 | static int set_plldsi_rate(unsigned long rate) | ||
1910 | { | ||
1911 | unsigned long src_rate; | ||
1912 | unsigned long rem; | ||
1913 | u32 pll_freq = 0; | ||
1914 | u32 r; | ||
1915 | |||
1916 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
1917 | rem = rate; | ||
1918 | |||
1919 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
1920 | u64 d; | ||
1921 | u64 hwrate; | ||
1922 | |||
1923 | d = (r * rate); | ||
1924 | (void)do_div(d, src_rate); | ||
1925 | if (d < 6) | ||
1926 | d = 6; | ||
1927 | else if (d > 255) | ||
1928 | d = 255; | ||
1929 | hwrate = (d * src_rate); | ||
1930 | if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) || | ||
1931 | ((r * MAX_PLL_VCO_RATE) < (2 * hwrate))) | ||
1932 | continue; | ||
1933 | (void)do_div(hwrate, r); | ||
1934 | if (rate < hwrate) { | ||
1935 | if (pll_freq == 0) | ||
1936 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
1937 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
1938 | break; | ||
1939 | } | ||
1940 | if ((rate - hwrate) < rem) { | ||
1941 | rem = (rate - hwrate); | ||
1942 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
1943 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
1944 | } | ||
1447 | } | 1945 | } |
1946 | if (pll_freq == 0) | ||
1947 | return -EINVAL; | ||
1948 | |||
1949 | pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT); | ||
1950 | writel(pll_freq, PRCM_PLLDSI_FREQ); | ||
1951 | |||
1952 | return 0; | ||
1953 | } | ||
1954 | |||
1955 | static void set_dsiclk_rate(u8 n, unsigned long rate) | ||
1956 | { | ||
1957 | u32 val; | ||
1958 | u32 div; | ||
1959 | |||
1960 | div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ, | ||
1961 | clock_rate(PRCMU_HDMICLK), PLL_RAW), rate); | ||
1962 | |||
1963 | dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI : | ||
1964 | (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 : | ||
1965 | /* else */ PRCM_DSI_PLLOUT_SEL_PHI_4; | ||
1966 | |||
1967 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
1968 | val &= ~dsiclk[n].divsel_mask; | ||
1969 | val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift); | ||
1970 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
1971 | } | ||
1972 | |||
1973 | static void set_dsiescclk_rate(u8 n, unsigned long rate) | ||
1974 | { | ||
1975 | u32 val; | ||
1976 | u32 div; | ||
1977 | |||
1978 | div = clock_divider(clock_rate(PRCMU_TVCLK), rate); | ||
1979 | val = readl(PRCM_DSITVCLK_DIV); | ||
1980 | val &= ~dsiescclk[n].div_mask; | ||
1981 | val |= (min(div, (u32)255) << dsiescclk[n].div_shift); | ||
1982 | writel(val, PRCM_DSITVCLK_DIV); | ||
1983 | } | ||
1984 | |||
1985 | int prcmu_set_clock_rate(u8 clock, unsigned long rate) | ||
1986 | { | ||
1448 | if (clock < PRCMU_NUM_REG_CLOCKS) | 1987 | if (clock < PRCMU_NUM_REG_CLOCKS) |
1449 | return request_reg_clock(clock, enable); | 1988 | set_clock_rate(clock, rate); |
1450 | return -EINVAL; | 1989 | else if (clock == PRCMU_PLLDSI) |
1990 | return set_plldsi_rate(rate); | ||
1991 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1992 | set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate); | ||
1993 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1994 | set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate); | ||
1995 | return 0; | ||
1451 | } | 1996 | } |
1452 | 1997 | ||
1453 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) | 1998 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) |
@@ -1476,7 +2021,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) | |||
1476 | return 0; | 2021 | return 0; |
1477 | } | 2022 | } |
1478 | 2023 | ||
1479 | int prcmu_config_hotdog(u8 threshold) | 2024 | int db8500_prcmu_config_hotdog(u8 threshold) |
1480 | { | 2025 | { |
1481 | mutex_lock(&mb4_transfer.lock); | 2026 | mutex_lock(&mb4_transfer.lock); |
1482 | 2027 | ||
@@ -1494,7 +2039,7 @@ int prcmu_config_hotdog(u8 threshold) | |||
1494 | return 0; | 2039 | return 0; |
1495 | } | 2040 | } |
1496 | 2041 | ||
1497 | int prcmu_config_hotmon(u8 low, u8 high) | 2042 | int db8500_prcmu_config_hotmon(u8 low, u8 high) |
1498 | { | 2043 | { |
1499 | mutex_lock(&mb4_transfer.lock); | 2044 | mutex_lock(&mb4_transfer.lock); |
1500 | 2045 | ||
@@ -1533,7 +2078,7 @@ static int config_hot_period(u16 val) | |||
1533 | return 0; | 2078 | return 0; |
1534 | } | 2079 | } |
1535 | 2080 | ||
1536 | int prcmu_start_temp_sense(u16 cycles32k) | 2081 | int db8500_prcmu_start_temp_sense(u16 cycles32k) |
1537 | { | 2082 | { |
1538 | if (cycles32k == 0xFFFF) | 2083 | if (cycles32k == 0xFFFF) |
1539 | return -EINVAL; | 2084 | return -EINVAL; |
@@ -1541,7 +2086,7 @@ int prcmu_start_temp_sense(u16 cycles32k) | |||
1541 | return config_hot_period(cycles32k); | 2086 | return config_hot_period(cycles32k); |
1542 | } | 2087 | } |
1543 | 2088 | ||
1544 | int prcmu_stop_temp_sense(void) | 2089 | int db8500_prcmu_stop_temp_sense(void) |
1545 | { | 2090 | { |
1546 | return config_hot_period(0xFFFF); | 2091 | return config_hot_period(0xFFFF); |
1547 | } | 2092 | } |
@@ -1570,7 +2115,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) | |||
1570 | 2115 | ||
1571 | } | 2116 | } |
1572 | 2117 | ||
1573 | int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | 2118 | int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) |
1574 | { | 2119 | { |
1575 | BUG_ON(num == 0 || num > 0xf); | 2120 | BUG_ON(num == 0 || num > 0xf); |
1576 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, | 2121 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, |
@@ -1578,17 +2123,17 @@ int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | |||
1578 | A9WDOG_AUTO_OFF_DIS); | 2123 | A9WDOG_AUTO_OFF_DIS); |
1579 | } | 2124 | } |
1580 | 2125 | ||
1581 | int prcmu_enable_a9wdog(u8 id) | 2126 | int db8500_prcmu_enable_a9wdog(u8 id) |
1582 | { | 2127 | { |
1583 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); | 2128 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); |
1584 | } | 2129 | } |
1585 | 2130 | ||
1586 | int prcmu_disable_a9wdog(u8 id) | 2131 | int db8500_prcmu_disable_a9wdog(u8 id) |
1587 | { | 2132 | { |
1588 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); | 2133 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); |
1589 | } | 2134 | } |
1590 | 2135 | ||
1591 | int prcmu_kick_a9wdog(u8 id) | 2136 | int db8500_prcmu_kick_a9wdog(u8 id) |
1592 | { | 2137 | { |
1593 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); | 2138 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); |
1594 | } | 2139 | } |
@@ -1596,16 +2141,8 @@ int prcmu_kick_a9wdog(u8 id) | |||
1596 | /* | 2141 | /* |
1597 | * timeout is 28 bit, in ms. | 2142 | * timeout is 28 bit, in ms. |
1598 | */ | 2143 | */ |
1599 | #define MAX_WATCHDOG_TIMEOUT 131000 | 2144 | int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) |
1600 | int prcmu_load_a9wdog(u8 id, u32 timeout) | ||
1601 | { | 2145 | { |
1602 | if (timeout > MAX_WATCHDOG_TIMEOUT) | ||
1603 | /* | ||
1604 | * Due to calculation bug in prcmu fw, timeouts | ||
1605 | * can't be bigger than 131 seconds. | ||
1606 | */ | ||
1607 | return -EINVAL; | ||
1608 | |||
1609 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, | 2146 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, |
1610 | (id & A9WDOG_ID_MASK) | | 2147 | (id & A9WDOG_ID_MASK) | |
1611 | /* | 2148 | /* |
@@ -1619,41 +2156,6 @@ int prcmu_load_a9wdog(u8 id, u32 timeout) | |||
1619 | } | 2156 | } |
1620 | 2157 | ||
1621 | /** | 2158 | /** |
1622 | * prcmu_set_clock_divider() - Configure the clock divider. | ||
1623 | * @clock: The clock for which the request is made. | ||
1624 | * @divider: The clock divider. (< 32) | ||
1625 | * | ||
1626 | * This function should only be used by the clock implementation. | ||
1627 | * Do not use it from any other place! | ||
1628 | */ | ||
1629 | int prcmu_set_clock_divider(u8 clock, u8 divider) | ||
1630 | { | ||
1631 | u32 val; | ||
1632 | unsigned long flags; | ||
1633 | |||
1634 | if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider)) | ||
1635 | return -EINVAL; | ||
1636 | |||
1637 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
1638 | |||
1639 | /* Grab the HW semaphore. */ | ||
1640 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
1641 | cpu_relax(); | ||
1642 | |||
1643 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | ||
1644 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
1645 | val |= (u32)divider; | ||
1646 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | ||
1647 | |||
1648 | /* Release the HW semaphore. */ | ||
1649 | writel(0, PRCM_SEM); | ||
1650 | |||
1651 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
1652 | |||
1653 | return 0; | ||
1654 | } | ||
1655 | |||
1656 | /** | ||
1657 | * prcmu_abb_read() - Read register value(s) from the ABB. | 2159 | * prcmu_abb_read() - Read register value(s) from the ABB. |
1658 | * @slave: The I2C slave address. | 2160 | * @slave: The I2C slave address. |
1659 | * @reg: The (start) register address. | 2161 | * @reg: The (start) register address. |
@@ -1675,6 +2177,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
1675 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 2177 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
1676 | cpu_relax(); | 2178 | cpu_relax(); |
1677 | 2179 | ||
2180 | writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
1678 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 2181 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
1679 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 2182 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
1680 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 2183 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
@@ -1700,16 +2203,19 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
1700 | } | 2203 | } |
1701 | 2204 | ||
1702 | /** | 2205 | /** |
1703 | * prcmu_abb_write() - Write register value(s) to the ABB. | 2206 | * prcmu_abb_write_masked() - Write masked register value(s) to the ABB. |
1704 | * @slave: The I2C slave address. | 2207 | * @slave: The I2C slave address. |
1705 | * @reg: The (start) register address. | 2208 | * @reg: The (start) register address. |
1706 | * @value: The value(s) to write. | 2209 | * @value: The value(s) to write. |
2210 | * @mask: The mask(s) to use. | ||
1707 | * @size: The number of registers to write. | 2211 | * @size: The number of registers to write. |
1708 | * | 2212 | * |
1709 | * Reads register value(s) from the ABB. | 2213 | * Writes masked register value(s) to the ABB. |
2214 | * For each @value, only the bits set to 1 in the corresponding @mask | ||
2215 | * will be written. The other bits are not changed. | ||
1710 | * @size has to be 1 for the current firmware version. | 2216 | * @size has to be 1 for the current firmware version. |
1711 | */ | 2217 | */ |
1712 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | 2218 | int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) |
1713 | { | 2219 | { |
1714 | int r; | 2220 | int r; |
1715 | 2221 | ||
@@ -1721,6 +2227,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
1721 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 2227 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
1722 | cpu_relax(); | 2228 | cpu_relax(); |
1723 | 2229 | ||
2230 | writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
1724 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 2231 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
1725 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 2232 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
1726 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 2233 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
@@ -1743,6 +2250,23 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
1743 | } | 2250 | } |
1744 | 2251 | ||
1745 | /** | 2252 | /** |
2253 | * prcmu_abb_write() - Write register value(s) to the ABB. | ||
2254 | * @slave: The I2C slave address. | ||
2255 | * @reg: The (start) register address. | ||
2256 | * @value: The value(s) to write. | ||
2257 | * @size: The number of registers to write. | ||
2258 | * | ||
2259 | * Writes register value(s) to the ABB. | ||
2260 | * @size has to be 1 for the current firmware version. | ||
2261 | */ | ||
2262 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | ||
2263 | { | ||
2264 | u8 mask = ~0; | ||
2265 | |||
2266 | return prcmu_abb_write_masked(slave, reg, value, &mask, size); | ||
2267 | } | ||
2268 | |||
2269 | /** | ||
1746 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem | 2270 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem |
1747 | */ | 2271 | */ |
1748 | void prcmu_ac_wake_req(void) | 2272 | void prcmu_ac_wake_req(void) |
@@ -1850,9 +2374,9 @@ u16 db8500_prcmu_get_reset_code(void) | |||
1850 | } | 2374 | } |
1851 | 2375 | ||
1852 | /** | 2376 | /** |
1853 | * prcmu_reset_modem - ask the PRCMU to reset modem | 2377 | * db8500_prcmu_reset_modem - ask the PRCMU to reset modem |
1854 | */ | 2378 | */ |
1855 | void prcmu_modem_reset(void) | 2379 | void db8500_prcmu_modem_reset(void) |
1856 | { | 2380 | { |
1857 | mutex_lock(&mb1_transfer.lock); | 2381 | mutex_lock(&mb1_transfer.lock); |
1858 | 2382 | ||
@@ -2099,6 +2623,26 @@ static struct irq_chip prcmu_irq_chip = { | |||
2099 | .irq_unmask = prcmu_irq_unmask, | 2623 | .irq_unmask = prcmu_irq_unmask, |
2100 | }; | 2624 | }; |
2101 | 2625 | ||
2626 | static char *fw_project_name(u8 project) | ||
2627 | { | ||
2628 | switch (project) { | ||
2629 | case PRCMU_FW_PROJECT_U8500: | ||
2630 | return "U8500"; | ||
2631 | case PRCMU_FW_PROJECT_U8500_C2: | ||
2632 | return "U8500 C2"; | ||
2633 | case PRCMU_FW_PROJECT_U9500: | ||
2634 | return "U9500"; | ||
2635 | case PRCMU_FW_PROJECT_U9500_C2: | ||
2636 | return "U9500 C2"; | ||
2637 | case PRCMU_FW_PROJECT_U8520: | ||
2638 | return "U8520"; | ||
2639 | case PRCMU_FW_PROJECT_U8420: | ||
2640 | return "U8420"; | ||
2641 | default: | ||
2642 | return "Unknown"; | ||
2643 | } | ||
2644 | } | ||
2645 | |||
2102 | void __init db8500_prcmu_early_init(void) | 2646 | void __init db8500_prcmu_early_init(void) |
2103 | { | 2647 | { |
2104 | unsigned int i; | 2648 | unsigned int i; |
@@ -2108,11 +2652,13 @@ void __init db8500_prcmu_early_init(void) | |||
2108 | if (tcpm_base != NULL) { | 2652 | if (tcpm_base != NULL) { |
2109 | u32 version; | 2653 | u32 version; |
2110 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); | 2654 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); |
2111 | prcmu_version.project_number = version & 0xFF; | 2655 | fw_info.version.project = version & 0xFF; |
2112 | prcmu_version.api_version = (version >> 8) & 0xFF; | 2656 | fw_info.version.api_version = (version >> 8) & 0xFF; |
2113 | prcmu_version.func_version = (version >> 16) & 0xFF; | 2657 | fw_info.version.func_version = (version >> 16) & 0xFF; |
2114 | prcmu_version.errata = (version >> 24) & 0xFF; | 2658 | fw_info.version.errata = (version >> 24) & 0xFF; |
2115 | pr_info("PRCMU firmware version %d.%d.%d\n", | 2659 | fw_info.valid = true; |
2660 | pr_info("PRCMU firmware: %s, version %d.%d.%d\n", | ||
2661 | fw_project_name(fw_info.version.project), | ||
2116 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, | 2662 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, |
2117 | (version >> 24) & 0xFF); | 2663 | (version >> 24) & 0xFF); |
2118 | iounmap(tcpm_base); | 2664 | iounmap(tcpm_base); |
@@ -2130,6 +2676,7 @@ void __init db8500_prcmu_early_init(void) | |||
2130 | init_completion(&mb0_transfer.ac_wake_work); | 2676 | init_completion(&mb0_transfer.ac_wake_work); |
2131 | mutex_init(&mb1_transfer.lock); | 2677 | mutex_init(&mb1_transfer.lock); |
2132 | init_completion(&mb1_transfer.work); | 2678 | init_completion(&mb1_transfer.work); |
2679 | mb1_transfer.ape_opp = APE_NO_CHANGE; | ||
2133 | mutex_init(&mb2_transfer.lock); | 2680 | mutex_init(&mb2_transfer.lock); |
2134 | init_completion(&mb2_transfer.work); | 2681 | init_completion(&mb2_transfer.work); |
2135 | spin_lock_init(&mb2_transfer.auto_pm_lock); | 2682 | spin_lock_init(&mb2_transfer.auto_pm_lock); |
@@ -2154,7 +2701,7 @@ void __init db8500_prcmu_early_init(void) | |||
2154 | } | 2701 | } |
2155 | } | 2702 | } |
2156 | 2703 | ||
2157 | static void __init db8500_prcmu_init_clkforce(void) | 2704 | static void __init init_prcm_registers(void) |
2158 | { | 2705 | { |
2159 | u32 val; | 2706 | u32 val; |
2160 | 2707 | ||
@@ -2186,19 +2733,17 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { | |||
2186 | REGULATOR_SUPPLY("vcore", "uart1"), | 2733 | REGULATOR_SUPPLY("vcore", "uart1"), |
2187 | REGULATOR_SUPPLY("vcore", "uart2"), | 2734 | REGULATOR_SUPPLY("vcore", "uart2"), |
2188 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), | 2735 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), |
2736 | REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"), | ||
2189 | }; | 2737 | }; |
2190 | 2738 | ||
2191 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { | 2739 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { |
2192 | /* CG2900 and CW1200 power to off-chip peripherals */ | ||
2193 | REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), | ||
2194 | REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"), | ||
2195 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), | 2740 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), |
2196 | /* AV8100 regulator */ | 2741 | /* AV8100 regulator */ |
2197 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), | 2742 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), |
2198 | }; | 2743 | }; |
2199 | 2744 | ||
2200 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { | 2745 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { |
2201 | REGULATOR_SUPPLY("vsupply", "b2r2.0"), | 2746 | REGULATOR_SUPPLY("vsupply", "b2r2_bus"), |
2202 | REGULATOR_SUPPLY("vsupply", "mcde"), | 2747 | REGULATOR_SUPPLY("vsupply", "mcde"), |
2203 | }; | 2748 | }; |
2204 | 2749 | ||
@@ -2235,6 +2780,7 @@ static struct regulator_consumer_supply db8500_esram12_consumers[] = { | |||
2235 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { | 2780 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { |
2236 | REGULATOR_SUPPLY("v-esram34", "mcde"), | 2781 | REGULATOR_SUPPLY("v-esram34", "mcde"), |
2237 | REGULATOR_SUPPLY("esram34", "cm_control"), | 2782 | REGULATOR_SUPPLY("esram34", "cm_control"), |
2783 | REGULATOR_SUPPLY("lcla_esram", "dma40.0"), | ||
2238 | }; | 2784 | }; |
2239 | 2785 | ||
2240 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | 2786 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { |
@@ -2291,7 +2837,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2291 | }, | 2837 | }, |
2292 | }, | 2838 | }, |
2293 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { | 2839 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { |
2294 | .supply_regulator = "db8500-vape", | 2840 | /* dependency to u8500-vape is handled outside regulator framework */ |
2295 | .constraints = { | 2841 | .constraints = { |
2296 | .name = "db8500-sva-mmdsp", | 2842 | .name = "db8500-sva-mmdsp", |
2297 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2843 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2307,7 +2853,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2307 | }, | 2853 | }, |
2308 | }, | 2854 | }, |
2309 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { | 2855 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { |
2310 | .supply_regulator = "db8500-vape", | 2856 | /* dependency to u8500-vape is handled outside regulator framework */ |
2311 | .constraints = { | 2857 | .constraints = { |
2312 | .name = "db8500-sva-pipe", | 2858 | .name = "db8500-sva-pipe", |
2313 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2859 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2316,7 +2862,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2316 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), | 2862 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), |
2317 | }, | 2863 | }, |
2318 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { | 2864 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { |
2319 | .supply_regulator = "db8500-vape", | 2865 | /* dependency to u8500-vape is handled outside regulator framework */ |
2320 | .constraints = { | 2866 | .constraints = { |
2321 | .name = "db8500-sia-mmdsp", | 2867 | .name = "db8500-sia-mmdsp", |
2322 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2868 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2331,7 +2877,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2331 | }, | 2877 | }, |
2332 | }, | 2878 | }, |
2333 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { | 2879 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { |
2334 | .supply_regulator = "db8500-vape", | 2880 | /* dependency to u8500-vape is handled outside regulator framework */ |
2335 | .constraints = { | 2881 | .constraints = { |
2336 | .name = "db8500-sia-pipe", | 2882 | .name = "db8500-sia-pipe", |
2337 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2883 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2359,7 +2905,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2359 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), | 2905 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), |
2360 | }, | 2906 | }, |
2361 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { | 2907 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { |
2362 | .supply_regulator = "db8500-vape", | 2908 | /* |
2909 | * esram12 is set in retention and supplied by Vsafe when Vape is off, | ||
2910 | * no need to hold Vape | ||
2911 | */ | ||
2363 | .constraints = { | 2912 | .constraints = { |
2364 | .name = "db8500-esram12", | 2913 | .name = "db8500-esram12", |
2365 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2914 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2374,7 +2923,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2374 | }, | 2923 | }, |
2375 | }, | 2924 | }, |
2376 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { | 2925 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { |
2377 | .supply_regulator = "db8500-vape", | 2926 | /* |
2927 | * esram34 is set in retention and supplied by Vsafe when Vape is off, | ||
2928 | * no need to hold Vape | ||
2929 | */ | ||
2378 | .constraints = { | 2930 | .constraints = { |
2379 | .name = "db8500-esram34", | 2931 | .name = "db8500-esram34", |
2380 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2932 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -2412,7 +2964,7 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) | |||
2412 | if (ux500_is_svp()) | 2964 | if (ux500_is_svp()) |
2413 | return -ENODEV; | 2965 | return -ENODEV; |
2414 | 2966 | ||
2415 | db8500_prcmu_init_clkforce(); | 2967 | init_prcm_registers(); |
2416 | 2968 | ||
2417 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 2969 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
2418 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); | 2970 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); |