diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/mfd/db8500-prcmu.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 1674 |
1 files changed, 283 insertions, 1391 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dc8826d8d69..02a15d7cb3b 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -27,21 +27,23 @@ | |||
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/mfd/core.h> | 29 | #include <linux/mfd/core.h> |
30 | #include <linux/mfd/dbx500-prcmu.h> | 30 | #include <linux/mfd/db8500-prcmu.h> |
31 | #include <linux/mfd/abx500/ab8500.h> | ||
32 | #include <linux/regulator/db8500-prcmu.h> | 31 | #include <linux/regulator/db8500-prcmu.h> |
33 | #include <linux/regulator/machine.h> | 32 | #include <linux/regulator/machine.h> |
34 | #include <linux/cpufreq.h> | ||
35 | #include <asm/hardware/gic.h> | ||
36 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
37 | #include <mach/irqs.h> | 34 | #include <mach/irqs.h> |
38 | #include <mach/db8500-regs.h> | 35 | #include <mach/db8500-regs.h> |
39 | #include <mach/id.h> | 36 | #include <mach/id.h> |
40 | #include "dbx500-prcmu-regs.h" | 37 | #include "db8500-prcmu-regs.h" |
41 | 38 | ||
42 | /* Offset for the firmware version within the TCPM */ | 39 | /* Offset for the firmware version within the TCPM */ |
43 | #define PRCMU_FW_VERSION_OFFSET 0xA4 | 40 | #define PRCMU_FW_VERSION_OFFSET 0xA4 |
44 | 41 | ||
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 | |||
45 | /* Index of different voltages to be used when accessing AVSData */ | 47 | /* Index of different voltages to be used when accessing AVSData */ |
46 | #define PRCM_AVS_BASE 0x2FC | 48 | #define PRCM_AVS_BASE 0x2FC |
47 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) | 49 | #define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) |
@@ -129,16 +131,12 @@ | |||
129 | #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 | 131 | #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 |
130 | #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 | 132 | #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 |
131 | #define MB1H_RELEASE_USB_WAKEUP 0x5 | 133 | #define MB1H_RELEASE_USB_WAKEUP 0x5 |
132 | #define MB1H_PLL_ON_OFF 0x6 | ||
133 | 134 | ||
134 | /* Mailbox 1 Requests */ | 135 | /* Mailbox 1 Requests */ |
135 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) | 136 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) |
136 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) | 137 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) |
137 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) | 138 | #define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4) |
138 | #define PLL_SOC0_OFF 0x1 | 139 | #define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8) |
139 | #define PLL_SOC0_ON 0x2 | ||
140 | #define PLL_SOC1_OFF 0x4 | ||
141 | #define PLL_SOC1_ON 0x8 | ||
142 | 140 | ||
143 | /* Mailbox 1 ACKs */ | 141 | /* Mailbox 1 ACKs */ |
144 | #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) | 142 | #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) |
@@ -186,11 +184,6 @@ | |||
186 | #define MB4H_HOTDOG 0x12 | 184 | #define MB4H_HOTDOG 0x12 |
187 | #define MB4H_HOTMON 0x13 | 185 | #define MB4H_HOTMON 0x13 |
188 | #define MB4H_HOT_PERIOD 0x14 | 186 | #define MB4H_HOT_PERIOD 0x14 |
189 | #define MB4H_A9WDOG_CONF 0x16 | ||
190 | #define MB4H_A9WDOG_EN 0x17 | ||
191 | #define MB4H_A9WDOG_DIS 0x18 | ||
192 | #define MB4H_A9WDOG_LOAD 0x19 | ||
193 | #define MB4H_A9WDOG_KICK 0x20 | ||
194 | 187 | ||
195 | /* Mailbox 4 Requests */ | 188 | /* Mailbox 4 Requests */ |
196 | #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) | 189 | #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) |
@@ -203,13 +196,6 @@ | |||
203 | #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) | 196 | #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) |
204 | #define HOTMON_CONFIG_LOW BIT(0) | 197 | #define HOTMON_CONFIG_LOW BIT(0) |
205 | #define HOTMON_CONFIG_HIGH BIT(1) | 198 | #define HOTMON_CONFIG_HIGH BIT(1) |
206 | #define PRCM_REQ_MB4_A9WDOG_0 (PRCM_REQ_MB4 + 0x0) | ||
207 | #define PRCM_REQ_MB4_A9WDOG_1 (PRCM_REQ_MB4 + 0x1) | ||
208 | #define PRCM_REQ_MB4_A9WDOG_2 (PRCM_REQ_MB4 + 0x2) | ||
209 | #define PRCM_REQ_MB4_A9WDOG_3 (PRCM_REQ_MB4 + 0x3) | ||
210 | #define A9WDOG_AUTO_OFF_EN BIT(7) | ||
211 | #define A9WDOG_AUTO_OFF_DIS 0 | ||
212 | #define A9WDOG_ID_MASK 0xf | ||
213 | 199 | ||
214 | /* Mailbox 5 Requests */ | 200 | /* Mailbox 5 Requests */ |
215 | #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) | 201 | #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) |
@@ -266,13 +252,6 @@ | |||
266 | #define WAKEUP_BIT_GPIO7 BIT(30) | 252 | #define WAKEUP_BIT_GPIO7 BIT(30) |
267 | #define WAKEUP_BIT_GPIO8 BIT(31) | 253 | #define WAKEUP_BIT_GPIO8 BIT(31) |
268 | 254 | ||
269 | static struct { | ||
270 | bool valid; | ||
271 | struct prcmu_fw_version version; | ||
272 | } fw_info; | ||
273 | |||
274 | static struct irq_domain *db8500_irq_domain; | ||
275 | |||
276 | /* | 255 | /* |
277 | * This vector maps irq numbers to the bits in the bit field used in | 256 | * This vector maps irq numbers to the bits in the bit field used in |
278 | * communication with the PRCMU firmware. | 257 | * communication with the PRCMU firmware. |
@@ -348,13 +327,11 @@ static struct { | |||
348 | * mb1_transfer - state needed for mailbox 1 communication. | 327 | * mb1_transfer - state needed for mailbox 1 communication. |
349 | * @lock: The transaction lock. | 328 | * @lock: The transaction lock. |
350 | * @work: The transaction completion structure. | 329 | * @work: The transaction completion structure. |
351 | * @ape_opp: The current APE OPP. | ||
352 | * @ack: Reply ("acknowledge") data. | 330 | * @ack: Reply ("acknowledge") data. |
353 | */ | 331 | */ |
354 | static struct { | 332 | static struct { |
355 | struct mutex lock; | 333 | struct mutex lock; |
356 | struct completion work; | 334 | struct completion work; |
357 | u8 ape_opp; | ||
358 | struct { | 335 | struct { |
359 | u8 header; | 336 | u8 header; |
360 | u8 arm_opp; | 337 | u8 arm_opp; |
@@ -422,105 +399,52 @@ static struct { | |||
422 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); | 399 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); |
423 | 400 | ||
424 | /* Spinlocks */ | 401 | /* Spinlocks */ |
425 | static DEFINE_SPINLOCK(prcmu_lock); | ||
426 | static DEFINE_SPINLOCK(clkout_lock); | 402 | static DEFINE_SPINLOCK(clkout_lock); |
403 | static DEFINE_SPINLOCK(gpiocr_lock); | ||
427 | 404 | ||
428 | /* Global var to runtime determine TCDM base for v2 or v1 */ | 405 | /* Global var to runtime determine TCDM base for v2 or v1 */ |
429 | static __iomem void *tcdm_base; | 406 | static __iomem void *tcdm_base; |
430 | 407 | ||
431 | struct clk_mgt { | 408 | struct clk_mgt { |
432 | void __iomem *reg; | 409 | unsigned int offset; |
433 | u32 pllsw; | 410 | u32 pllsw; |
434 | int branch; | ||
435 | bool clk38div; | ||
436 | }; | ||
437 | |||
438 | enum { | ||
439 | PLL_RAW, | ||
440 | PLL_FIX, | ||
441 | PLL_DIV | ||
442 | }; | 411 | }; |
443 | 412 | ||
444 | static DEFINE_SPINLOCK(clk_mgt_lock); | 413 | static DEFINE_SPINLOCK(clk_mgt_lock); |
445 | 414 | ||
446 | #define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \ | 415 | #define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 } |
447 | { (PRCM_##_name##_MGT), 0 , _branch, _clk38div} | ||
448 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { | 416 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { |
449 | CLK_MGT_ENTRY(SGACLK, PLL_DIV, false), | 417 | CLK_MGT_ENTRY(SGACLK), |
450 | CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true), | 418 | CLK_MGT_ENTRY(UARTCLK), |
451 | CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true), | 419 | CLK_MGT_ENTRY(MSP02CLK), |
452 | CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true), | 420 | CLK_MGT_ENTRY(MSP1CLK), |
453 | CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true), | 421 | CLK_MGT_ENTRY(I2CCLK), |
454 | CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true), | 422 | CLK_MGT_ENTRY(SDMMCCLK), |
455 | CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true), | 423 | CLK_MGT_ENTRY(SLIMCLK), |
456 | CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true), | 424 | CLK_MGT_ENTRY(PER1CLK), |
457 | CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true), | 425 | CLK_MGT_ENTRY(PER2CLK), |
458 | CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true), | 426 | CLK_MGT_ENTRY(PER3CLK), |
459 | CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true), | 427 | CLK_MGT_ENTRY(PER5CLK), |
460 | CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true), | 428 | CLK_MGT_ENTRY(PER6CLK), |
461 | CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true), | 429 | CLK_MGT_ENTRY(PER7CLK), |
462 | CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true), | 430 | CLK_MGT_ENTRY(LCDCLK), |
463 | CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true), | 431 | CLK_MGT_ENTRY(BMLCLK), |
464 | CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true), | 432 | CLK_MGT_ENTRY(HSITXCLK), |
465 | CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true), | 433 | CLK_MGT_ENTRY(HSIRXCLK), |
466 | CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false), | 434 | CLK_MGT_ENTRY(HDMICLK), |
467 | CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true), | 435 | CLK_MGT_ENTRY(APEATCLK), |
468 | CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true), | 436 | CLK_MGT_ENTRY(APETRACECLK), |
469 | CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true), | 437 | CLK_MGT_ENTRY(MCDECLK), |
470 | CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true), | 438 | CLK_MGT_ENTRY(IPI2CCLK), |
471 | CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false), | 439 | CLK_MGT_ENTRY(DSIALTCLK), |
472 | CLK_MGT_ENTRY(DMACLK, PLL_DIV, true), | 440 | CLK_MGT_ENTRY(DMACLK), |
473 | CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true), | 441 | CLK_MGT_ENTRY(B2R2CLK), |
474 | CLK_MGT_ENTRY(TVCLK, PLL_FIX, true), | 442 | CLK_MGT_ENTRY(TVCLK), |
475 | CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true), | 443 | CLK_MGT_ENTRY(SSPCLK), |
476 | CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true), | 444 | CLK_MGT_ENTRY(RNGCLK), |
477 | CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false), | 445 | CLK_MGT_ENTRY(UICCCLK), |
478 | }; | ||
479 | |||
480 | struct dsiclk { | ||
481 | u32 divsel_mask; | ||
482 | u32 divsel_shift; | ||
483 | u32 divsel; | ||
484 | }; | ||
485 | |||
486 | static struct dsiclk dsiclk[2] = { | ||
487 | { | ||
488 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK, | ||
489 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT, | ||
490 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
491 | }, | ||
492 | { | ||
493 | .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK, | ||
494 | .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT, | ||
495 | .divsel = PRCM_DSI_PLLOUT_SEL_PHI, | ||
496 | } | ||
497 | }; | ||
498 | |||
499 | struct dsiescclk { | ||
500 | u32 en; | ||
501 | u32 div_mask; | ||
502 | u32 div_shift; | ||
503 | }; | ||
504 | |||
505 | static struct dsiescclk dsiescclk[3] = { | ||
506 | { | ||
507 | .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN, | ||
508 | .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK, | ||
509 | .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT, | ||
510 | }, | ||
511 | { | ||
512 | .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN, | ||
513 | .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK, | ||
514 | .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT, | ||
515 | }, | ||
516 | { | ||
517 | .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN, | ||
518 | .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK, | ||
519 | .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT, | ||
520 | } | ||
521 | }; | 446 | }; |
522 | 447 | ||
523 | |||
524 | /* | 448 | /* |
525 | * Used by MCDE to setup all necessary PRCMU registers | 449 | * Used by MCDE to setup all necessary PRCMU registers |
526 | */ | 450 | */ |
@@ -536,6 +460,9 @@ static struct dsiescclk dsiescclk[3] = { | |||
536 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ | 460 | /* PLLDIV=12, PLLSW=4 (PLLDDR) */ |
537 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C | 461 | #define PRCMU_DSI_CLOCK_SETTING 0x0000008C |
538 | 462 | ||
463 | /* PLLDIV=8, PLLSW=4 (PLLDDR) */ | ||
464 | #define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088 | ||
465 | |||
539 | /* DPI 50000000 Hz */ | 466 | /* DPI 50000000 Hz */ |
540 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ | 467 | #define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ |
541 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) | 468 | (16 << PRCMU_CLK_PLL_DIV_SHIFT)) |
@@ -544,6 +471,9 @@ static struct dsiescclk dsiescclk[3] = { | |||
544 | /* D=101, N=1, R=4, SELDIV2=0 */ | 471 | /* D=101, N=1, R=4, SELDIV2=0 */ |
545 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 | 472 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 |
546 | 473 | ||
474 | /* D=70, N=1, R=3, SELDIV2=0 */ | ||
475 | #define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146 | ||
476 | |||
547 | #define PRCMU_ENABLE_PLLDSI 0x00000001 | 477 | #define PRCMU_ENABLE_PLLDSI 0x00000001 |
548 | #define PRCMU_DISABLE_PLLDSI 0x00000000 | 478 | #define PRCMU_DISABLE_PLLDSI 0x00000000 |
549 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C | 479 | #define PRCMU_RELEASE_RESET_DSS 0x0000400C |
@@ -555,96 +485,116 @@ static struct dsiescclk dsiescclk[3] = { | |||
555 | 485 | ||
556 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 | 486 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 |
557 | 487 | ||
558 | int db8500_prcmu_enable_dsipll(void) | 488 | static struct { |
489 | u8 project_number; | ||
490 | u8 api_version; | ||
491 | u8 func_version; | ||
492 | u8 errata; | ||
493 | } prcmu_version; | ||
494 | |||
495 | |||
496 | int prcmu_enable_dsipll(void) | ||
559 | { | 497 | { |
560 | int i; | 498 | int i; |
499 | unsigned int plldsifreq; | ||
561 | 500 | ||
562 | /* Clear DSIPLL_RESETN */ | 501 | /* Clear DSIPLL_RESETN */ |
563 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); | 502 | writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR)); |
564 | /* Unclamp DSIPLL in/out */ | 503 | /* Unclamp DSIPLL in/out */ |
565 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); | 504 | writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR)); |
566 | 505 | ||
506 | if (prcmu_is_u8400()) | ||
507 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; | ||
508 | else | ||
509 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; | ||
567 | /* Set DSI PLL FREQ */ | 510 | /* Set DSI PLL FREQ */ |
568 | writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); | 511 | writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ)); |
569 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); | 512 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, |
513 | (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL)); | ||
570 | /* Enable Escape clocks */ | 514 | /* Enable Escape clocks */ |
571 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); | 515 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, |
516 | (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); | ||
572 | 517 | ||
573 | /* Start DSI PLL */ | 518 | /* Start DSI PLL */ |
574 | writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); | 519 | writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); |
575 | /* Reset DSI PLL */ | 520 | /* Reset DSI PLL */ |
576 | writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); | 521 | writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET)); |
577 | for (i = 0; i < 10; i++) { | 522 | for (i = 0; i < 10; i++) { |
578 | if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED) | 523 | if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & |
524 | PRCMU_PLLDSI_LOCKP_LOCKED) | ||
579 | == PRCMU_PLLDSI_LOCKP_LOCKED) | 525 | == PRCMU_PLLDSI_LOCKP_LOCKED) |
580 | break; | 526 | break; |
581 | udelay(100); | 527 | udelay(100); |
582 | } | 528 | } |
583 | /* Set DSIPLL_RESETN */ | 529 | /* Set DSIPLL_RESETN */ |
584 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); | 530 | writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); |
585 | return 0; | 531 | return 0; |
586 | } | 532 | } |
587 | 533 | ||
588 | int db8500_prcmu_disable_dsipll(void) | 534 | int prcmu_disable_dsipll(void) |
589 | { | 535 | { |
590 | /* Disable dsi pll */ | 536 | /* Disable dsi pll */ |
591 | writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); | 537 | writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); |
592 | /* Disable escapeclock */ | 538 | /* Disable escapeclock */ |
593 | writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); | 539 | writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, |
540 | (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); | ||
594 | return 0; | 541 | return 0; |
595 | } | 542 | } |
596 | 543 | ||
597 | int db8500_prcmu_set_display_clocks(void) | 544 | int prcmu_set_display_clocks(void) |
598 | { | 545 | { |
599 | unsigned long flags; | 546 | unsigned long flags; |
547 | unsigned int dsiclk; | ||
548 | |||
549 | if (prcmu_is_u8400()) | ||
550 | dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400; | ||
551 | else | ||
552 | dsiclk = PRCMU_DSI_CLOCK_SETTING; | ||
600 | 553 | ||
601 | spin_lock_irqsave(&clk_mgt_lock, flags); | 554 | spin_lock_irqsave(&clk_mgt_lock, flags); |
602 | 555 | ||
603 | /* Grab the HW semaphore. */ | 556 | /* Grab the HW semaphore. */ |
604 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 557 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
605 | cpu_relax(); | 558 | cpu_relax(); |
606 | 559 | ||
607 | writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); | 560 | writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT)); |
608 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); | 561 | writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT)); |
609 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); | 562 | writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT)); |
610 | 563 | ||
611 | /* Release the HW semaphore. */ | 564 | /* Release the HW semaphore. */ |
612 | writel(0, PRCM_SEM); | 565 | writel(0, (_PRCMU_BASE + PRCM_SEM)); |
613 | 566 | ||
614 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | 567 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
615 | 568 | ||
616 | return 0; | 569 | return 0; |
617 | } | 570 | } |
618 | 571 | ||
619 | u32 db8500_prcmu_read(unsigned int reg) | 572 | /** |
620 | { | 573 | * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. |
621 | return readl(_PRCMU_BASE + reg); | 574 | */ |
622 | } | 575 | void prcmu_enable_spi2(void) |
623 | |||
624 | void db8500_prcmu_write(unsigned int reg, u32 value) | ||
625 | { | 576 | { |
577 | u32 reg; | ||
626 | unsigned long flags; | 578 | unsigned long flags; |
627 | 579 | ||
628 | spin_lock_irqsave(&prcmu_lock, flags); | 580 | spin_lock_irqsave(&gpiocr_lock, flags); |
629 | writel(value, (_PRCMU_BASE + reg)); | 581 | reg = readl(_PRCMU_BASE + PRCM_GPIOCR); |
630 | spin_unlock_irqrestore(&prcmu_lock, flags); | 582 | writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); |
583 | spin_unlock_irqrestore(&gpiocr_lock, flags); | ||
631 | } | 584 | } |
632 | 585 | ||
633 | void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value) | 586 | /** |
587 | * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. | ||
588 | */ | ||
589 | void prcmu_disable_spi2(void) | ||
634 | { | 590 | { |
635 | u32 val; | 591 | u32 reg; |
636 | unsigned long flags; | 592 | unsigned long flags; |
637 | 593 | ||
638 | spin_lock_irqsave(&prcmu_lock, flags); | 594 | spin_lock_irqsave(&gpiocr_lock, flags); |
639 | val = readl(_PRCMU_BASE + reg); | 595 | reg = readl(_PRCMU_BASE + PRCM_GPIOCR); |
640 | val = ((val & ~mask) | (value & mask)); | 596 | writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); |
641 | writel(val, (_PRCMU_BASE + reg)); | 597 | spin_unlock_irqrestore(&gpiocr_lock, flags); |
642 | spin_unlock_irqrestore(&prcmu_lock, flags); | ||
643 | } | ||
644 | |||
645 | struct prcmu_fw_version *prcmu_get_fw_version(void) | ||
646 | { | ||
647 | return fw_info.valid ? &fw_info.version : NULL; | ||
648 | } | 598 | } |
649 | 599 | ||
650 | bool prcmu_has_arm_maxopp(void) | 600 | bool prcmu_has_arm_maxopp(void) |
@@ -653,6 +603,11 @@ bool prcmu_has_arm_maxopp(void) | |||
653 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; | 603 | PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; |
654 | } | 604 | } |
655 | 605 | ||
606 | bool prcmu_is_u8400(void) | ||
607 | { | ||
608 | return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0; | ||
609 | } | ||
610 | |||
656 | /** | 611 | /** |
657 | * prcmu_get_boot_status - PRCMU boot status checking | 612 | * prcmu_get_boot_status - PRCMU boot status checking |
658 | * Returns: the current PRCMU boot status | 613 | * Returns: the current PRCMU boot status |
@@ -746,7 +701,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) | |||
746 | 701 | ||
747 | spin_lock_irqsave(&clkout_lock, flags); | 702 | spin_lock_irqsave(&clkout_lock, flags); |
748 | 703 | ||
749 | val = readl(PRCM_CLKOCR); | 704 | val = readl(_PRCMU_BASE + PRCM_CLKOCR); |
750 | if (val & div_mask) { | 705 | if (val & div_mask) { |
751 | if (div) { | 706 | if (div) { |
752 | if ((val & mask) != bits) { | 707 | if ((val & mask) != bits) { |
@@ -760,7 +715,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) | |||
760 | } | 715 | } |
761 | } | 716 | } |
762 | } | 717 | } |
763 | writel((bits | (val & ~mask)), PRCM_CLKOCR); | 718 | writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR)); |
764 | requests[clkout] += (div ? 1 : -1); | 719 | requests[clkout] += (div ? 1 : -1); |
765 | 720 | ||
766 | unlock_and_return: | 721 | unlock_and_return: |
@@ -769,7 +724,7 @@ unlock_and_return: | |||
769 | return r; | 724 | return r; |
770 | } | 725 | } |
771 | 726 | ||
772 | int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | 727 | int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) |
773 | { | 728 | { |
774 | unsigned long flags; | 729 | unsigned long flags; |
775 | 730 | ||
@@ -777,7 +732,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
777 | 732 | ||
778 | spin_lock_irqsave(&mb0_transfer.lock, flags); | 733 | spin_lock_irqsave(&mb0_transfer.lock, flags); |
779 | 734 | ||
780 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 735 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
781 | cpu_relax(); | 736 | cpu_relax(); |
782 | 737 | ||
783 | writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 738 | writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
@@ -786,131 +741,13 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
786 | writeb((keep_ulp_clk ? 1 : 0), | 741 | writeb((keep_ulp_clk ? 1 : 0), |
787 | (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); | 742 | (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); |
788 | writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); | 743 | writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); |
789 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); | 744 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
790 | 745 | ||
791 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 746 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
792 | 747 | ||
793 | return 0; | 748 | return 0; |
794 | } | 749 | } |
795 | 750 | ||
796 | u8 db8500_prcmu_get_power_state_result(void) | ||
797 | { | ||
798 | return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS); | ||
799 | } | ||
800 | |||
801 | /* This function decouple the gic from the prcmu */ | ||
802 | int db8500_prcmu_gic_decouple(void) | ||
803 | { | ||
804 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
805 | |||
806 | /* Set bit 0 register value to 1 */ | ||
807 | writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, | ||
808 | PRCM_A9_MASK_REQ); | ||
809 | |||
810 | /* Make sure the register is updated */ | ||
811 | readl(PRCM_A9_MASK_REQ); | ||
812 | |||
813 | /* Wait a few cycles for the gic mask completion */ | ||
814 | udelay(1); | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* This function recouple the gic with the prcmu */ | ||
820 | int db8500_prcmu_gic_recouple(void) | ||
821 | { | ||
822 | u32 val = readl(PRCM_A9_MASK_REQ); | ||
823 | |||
824 | /* Set bit 0 register value to 0 */ | ||
825 | writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ); | ||
826 | |||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | #define PRCMU_GIC_NUMBER_REGS 5 | ||
831 | |||
832 | /* | ||
833 | * This function checks if there are pending irq on the gic. It only | ||
834 | * makes sense if the gic has been decoupled before with the | ||
835 | * db8500_prcmu_gic_decouple function. Disabling an interrupt only | ||
836 | * disables the forwarding of the interrupt to any CPU interface. It | ||
837 | * does not prevent the interrupt from changing state, for example | ||
838 | * becoming pending, or active and pending if it is already | ||
839 | * active. Hence, we have to check the interrupt is pending *and* is | ||
840 | * active. | ||
841 | */ | ||
842 | bool db8500_prcmu_gic_pending_irq(void) | ||
843 | { | ||
844 | u32 pr; /* Pending register */ | ||
845 | u32 er; /* Enable register */ | ||
846 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
847 | int i; | ||
848 | |||
849 | /* 5 registers. STI & PPI not skipped */ | ||
850 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) { | ||
851 | |||
852 | pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4); | ||
853 | er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); | ||
854 | |||
855 | if (pr & er) | ||
856 | return true; /* There is a pending interrupt */ | ||
857 | } | ||
858 | |||
859 | return false; | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * This function checks if there are pending interrupt on the | ||
864 | * prcmu which has been delegated to monitor the irqs with the | ||
865 | * db8500_prcmu_copy_gic_settings function. | ||
866 | */ | ||
867 | bool db8500_prcmu_pending_irq(void) | ||
868 | { | ||
869 | u32 it, im; | ||
870 | int i; | ||
871 | |||
872 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
873 | it = readl(PRCM_ARMITVAL31TO0 + i * 4); | ||
874 | im = readl(PRCM_ARMITMSK31TO0 + i * 4); | ||
875 | if (it & im) | ||
876 | return true; /* There is a pending interrupt */ | ||
877 | } | ||
878 | |||
879 | return false; | ||
880 | } | ||
881 | |||
882 | /* | ||
883 | * This function checks if the specified cpu is in in WFI. It's usage | ||
884 | * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple | ||
885 | * function. Of course passing smp_processor_id() to this function will | ||
886 | * always return false... | ||
887 | */ | ||
888 | bool db8500_prcmu_is_cpu_in_wfi(int cpu) | ||
889 | { | ||
890 | return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : | ||
891 | PRCM_ARM_WFI_STANDBY_WFI0; | ||
892 | } | ||
893 | |||
894 | /* | ||
895 | * This function copies the gic SPI settings to the prcmu in order to | ||
896 | * monitor them and abort/finish the retention/off sequence or state. | ||
897 | */ | ||
898 | int db8500_prcmu_copy_gic_settings(void) | ||
899 | { | ||
900 | u32 er; /* Enable register */ | ||
901 | void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE); | ||
902 | int i; | ||
903 | |||
904 | /* We skip the STI and PPI */ | ||
905 | for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) { | ||
906 | er = readl_relaxed(dist_base + | ||
907 | GIC_DIST_ENABLE_SET + (i + 1) * 4); | ||
908 | writel(er, PRCM_ARMITMSK31TO0 + i * 4); | ||
909 | } | ||
910 | |||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | /* This function should only be called while mb0_transfer.lock is held. */ | 751 | /* This function should only be called while mb0_transfer.lock is held. */ |
915 | static void config_wakeups(void) | 752 | static void config_wakeups(void) |
916 | { | 753 | { |
@@ -933,18 +770,18 @@ static void config_wakeups(void) | |||
933 | return; | 770 | return; |
934 | 771 | ||
935 | for (i = 0; i < 2; i++) { | 772 | for (i = 0; i < 2; i++) { |
936 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 773 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
937 | cpu_relax(); | 774 | cpu_relax(); |
938 | writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); | 775 | writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); |
939 | writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); | 776 | writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); |
940 | writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 777 | writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
941 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); | 778 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
942 | } | 779 | } |
943 | last_dbb_events = dbb_events; | 780 | last_dbb_events = dbb_events; |
944 | last_abb_events = abb_events; | 781 | last_abb_events = abb_events; |
945 | } | 782 | } |
946 | 783 | ||
947 | void db8500_prcmu_enable_wakeups(u32 wakeups) | 784 | void prcmu_enable_wakeups(u32 wakeups) |
948 | { | 785 | { |
949 | unsigned long flags; | 786 | unsigned long flags; |
950 | u32 bits; | 787 | u32 bits; |
@@ -965,7 +802,7 @@ void db8500_prcmu_enable_wakeups(u32 wakeups) | |||
965 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 802 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
966 | } | 803 | } |
967 | 804 | ||
968 | void db8500_prcmu_config_abb_event_readout(u32 abb_events) | 805 | void prcmu_config_abb_event_readout(u32 abb_events) |
969 | { | 806 | { |
970 | unsigned long flags; | 807 | unsigned long flags; |
971 | 808 | ||
@@ -977,7 +814,7 @@ void db8500_prcmu_config_abb_event_readout(u32 abb_events) | |||
977 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 814 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
978 | } | 815 | } |
979 | 816 | ||
980 | void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) | 817 | void prcmu_get_abb_event_buffer(void __iomem **buf) |
981 | { | 818 | { |
982 | if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) | 819 | if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) |
983 | *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500); | 820 | *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500); |
@@ -986,13 +823,13 @@ void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) | |||
986 | } | 823 | } |
987 | 824 | ||
988 | /** | 825 | /** |
989 | * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP | 826 | * prcmu_set_arm_opp - set the appropriate ARM OPP |
990 | * @opp: The new ARM operating point to which transition is to be made | 827 | * @opp: The new ARM operating point to which transition is to be made |
991 | * Returns: 0 on success, non-zero on failure | 828 | * Returns: 0 on success, non-zero on failure |
992 | * | 829 | * |
993 | * This function sets the the operating point of the ARM. | 830 | * This function sets the the operating point of the ARM. |
994 | */ | 831 | */ |
995 | int db8500_prcmu_set_arm_opp(u8 opp) | 832 | int prcmu_set_arm_opp(u8 opp) |
996 | { | 833 | { |
997 | int r; | 834 | int r; |
998 | 835 | ||
@@ -1003,14 +840,14 @@ int db8500_prcmu_set_arm_opp(u8 opp) | |||
1003 | 840 | ||
1004 | mutex_lock(&mb1_transfer.lock); | 841 | mutex_lock(&mb1_transfer.lock); |
1005 | 842 | ||
1006 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 843 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
1007 | cpu_relax(); | 844 | cpu_relax(); |
1008 | 845 | ||
1009 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 846 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1010 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 847 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
1011 | writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | 848 | writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); |
1012 | 849 | ||
1013 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 850 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1014 | wait_for_completion(&mb1_transfer.work); | 851 | wait_for_completion(&mb1_transfer.work); |
1015 | 852 | ||
1016 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || | 853 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || |
@@ -1023,155 +860,91 @@ int db8500_prcmu_set_arm_opp(u8 opp) | |||
1023 | } | 860 | } |
1024 | 861 | ||
1025 | /** | 862 | /** |
1026 | * db8500_prcmu_get_arm_opp - get the current ARM OPP | 863 | * prcmu_get_arm_opp - get the current ARM OPP |
1027 | * | 864 | * |
1028 | * Returns: the current ARM OPP | 865 | * Returns: the current ARM OPP |
1029 | */ | 866 | */ |
1030 | int db8500_prcmu_get_arm_opp(void) | 867 | int prcmu_get_arm_opp(void) |
1031 | { | 868 | { |
1032 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); | 869 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); |
1033 | } | 870 | } |
1034 | 871 | ||
1035 | /** | 872 | /** |
1036 | * db8500_prcmu_get_ddr_opp - get the current DDR OPP | 873 | * prcmu_get_ddr_opp - get the current DDR OPP |
1037 | * | 874 | * |
1038 | * Returns: the current DDR OPP | 875 | * Returns: the current DDR OPP |
1039 | */ | 876 | */ |
1040 | int db8500_prcmu_get_ddr_opp(void) | 877 | int prcmu_get_ddr_opp(void) |
1041 | { | 878 | { |
1042 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); | 879 | return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); |
1043 | } | 880 | } |
1044 | 881 | ||
1045 | /** | 882 | /** |
1046 | * db8500_set_ddr_opp - set the appropriate DDR OPP | 883 | * set_ddr_opp - set the appropriate DDR OPP |
1047 | * @opp: The new DDR operating point to which transition is to be made | 884 | * @opp: The new DDR operating point to which transition is to be made |
1048 | * Returns: 0 on success, non-zero on failure | 885 | * Returns: 0 on success, non-zero on failure |
1049 | * | 886 | * |
1050 | * This function sets the operating point of the DDR. | 887 | * This function sets the operating point of the DDR. |
1051 | */ | 888 | */ |
1052 | int db8500_prcmu_set_ddr_opp(u8 opp) | 889 | int prcmu_set_ddr_opp(u8 opp) |
1053 | { | 890 | { |
1054 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) | 891 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) |
1055 | return -EINVAL; | 892 | return -EINVAL; |
1056 | /* Changing the DDR OPP can hang the hardware pre-v21 */ | 893 | /* Changing the DDR OPP can hang the hardware pre-v21 */ |
1057 | if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) | 894 | if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) |
1058 | writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); | 895 | writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW)); |
1059 | 896 | ||
1060 | return 0; | 897 | return 0; |
1061 | } | 898 | } |
1062 | |||
1063 | /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ | ||
1064 | static void request_even_slower_clocks(bool enable) | ||
1065 | { | ||
1066 | void __iomem *clock_reg[] = { | ||
1067 | PRCM_ACLK_MGT, | ||
1068 | PRCM_DMACLK_MGT | ||
1069 | }; | ||
1070 | unsigned long flags; | ||
1071 | unsigned int i; | ||
1072 | |||
1073 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
1074 | |||
1075 | /* Grab the HW semaphore. */ | ||
1076 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
1077 | cpu_relax(); | ||
1078 | |||
1079 | for (i = 0; i < ARRAY_SIZE(clock_reg); i++) { | ||
1080 | u32 val; | ||
1081 | u32 div; | ||
1082 | |||
1083 | val = readl(clock_reg[i]); | ||
1084 | div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
1085 | if (enable) { | ||
1086 | if ((div <= 1) || (div > 15)) { | ||
1087 | pr_err("prcmu: Bad clock divider %d in %s\n", | ||
1088 | div, __func__); | ||
1089 | goto unlock_and_return; | ||
1090 | } | ||
1091 | div <<= 1; | ||
1092 | } else { | ||
1093 | if (div <= 2) | ||
1094 | goto unlock_and_return; | ||
1095 | div >>= 1; | ||
1096 | } | ||
1097 | val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) | | ||
1098 | (div & PRCM_CLK_MGT_CLKPLLDIV_MASK)); | ||
1099 | writel(val, clock_reg[i]); | ||
1100 | } | ||
1101 | |||
1102 | unlock_and_return: | ||
1103 | /* Release the HW semaphore. */ | ||
1104 | writel(0, PRCM_SEM); | ||
1105 | |||
1106 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
1107 | } | ||
1108 | |||
1109 | /** | 899 | /** |
1110 | * db8500_set_ape_opp - set the appropriate APE OPP | 900 | * set_ape_opp - set the appropriate APE OPP |
1111 | * @opp: The new APE operating point to which transition is to be made | 901 | * @opp: The new APE operating point to which transition is to be made |
1112 | * Returns: 0 on success, non-zero on failure | 902 | * Returns: 0 on success, non-zero on failure |
1113 | * | 903 | * |
1114 | * This function sets the operating point of the APE. | 904 | * This function sets the operating point of the APE. |
1115 | */ | 905 | */ |
1116 | int db8500_prcmu_set_ape_opp(u8 opp) | 906 | int prcmu_set_ape_opp(u8 opp) |
1117 | { | 907 | { |
1118 | int r = 0; | 908 | int r = 0; |
1119 | 909 | ||
1120 | if (opp == mb1_transfer.ape_opp) | ||
1121 | return 0; | ||
1122 | |||
1123 | mutex_lock(&mb1_transfer.lock); | 910 | mutex_lock(&mb1_transfer.lock); |
1124 | 911 | ||
1125 | if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP) | 912 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
1126 | request_even_slower_clocks(false); | ||
1127 | |||
1128 | if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP)) | ||
1129 | goto skip_message; | ||
1130 | |||
1131 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | ||
1132 | cpu_relax(); | 913 | cpu_relax(); |
1133 | 914 | ||
1134 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 915 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1135 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 916 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
1136 | writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp), | 917 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); |
1137 | (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | ||
1138 | 918 | ||
1139 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 919 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1140 | wait_for_completion(&mb1_transfer.work); | 920 | wait_for_completion(&mb1_transfer.work); |
1141 | 921 | ||
1142 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || | 922 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || |
1143 | (mb1_transfer.ack.ape_opp != opp)) | 923 | (mb1_transfer.ack.ape_opp != opp)) |
1144 | r = -EIO; | 924 | r = -EIO; |
1145 | 925 | ||
1146 | skip_message: | ||
1147 | if ((!r && (opp == APE_50_PARTLY_25_OPP)) || | ||
1148 | (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP))) | ||
1149 | request_even_slower_clocks(true); | ||
1150 | if (!r) | ||
1151 | mb1_transfer.ape_opp = opp; | ||
1152 | |||
1153 | mutex_unlock(&mb1_transfer.lock); | 926 | mutex_unlock(&mb1_transfer.lock); |
1154 | 927 | ||
1155 | return r; | 928 | return r; |
1156 | } | 929 | } |
1157 | 930 | ||
1158 | /** | 931 | /** |
1159 | * db8500_prcmu_get_ape_opp - get the current APE OPP | 932 | * prcmu_get_ape_opp - get the current APE OPP |
1160 | * | 933 | * |
1161 | * Returns: the current APE OPP | 934 | * Returns: the current APE OPP |
1162 | */ | 935 | */ |
1163 | int db8500_prcmu_get_ape_opp(void) | 936 | int prcmu_get_ape_opp(void) |
1164 | { | 937 | { |
1165 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); | 938 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); |
1166 | } | 939 | } |
1167 | 940 | ||
1168 | /** | 941 | /** |
1169 | * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage | 942 | * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage |
1170 | * @enable: true to request the higher voltage, false to drop a request. | 943 | * @enable: true to request the higher voltage, false to drop a request. |
1171 | * | 944 | * |
1172 | * Calls to this function to enable and disable requests must be balanced. | 945 | * Calls to this function to enable and disable requests must be balanced. |
1173 | */ | 946 | */ |
1174 | int db8500_prcmu_request_ape_opp_100_voltage(bool enable) | 947 | int prcmu_request_ape_opp_100_voltage(bool enable) |
1175 | { | 948 | { |
1176 | int r = 0; | 949 | int r = 0; |
1177 | u8 header; | 950 | u8 header; |
@@ -1193,12 +966,12 @@ int db8500_prcmu_request_ape_opp_100_voltage(bool enable) | |||
1193 | header = MB1H_RELEASE_APE_OPP_100_VOLT; | 966 | header = MB1H_RELEASE_APE_OPP_100_VOLT; |
1194 | } | 967 | } |
1195 | 968 | ||
1196 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 969 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
1197 | cpu_relax(); | 970 | cpu_relax(); |
1198 | 971 | ||
1199 | writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 972 | writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1200 | 973 | ||
1201 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 974 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1202 | wait_for_completion(&mb1_transfer.work); | 975 | wait_for_completion(&mb1_transfer.work); |
1203 | 976 | ||
1204 | if ((mb1_transfer.ack.header != header) || | 977 | if ((mb1_transfer.ack.header != header) || |
@@ -1222,13 +995,13 @@ int prcmu_release_usb_wakeup_state(void) | |||
1222 | 995 | ||
1223 | mutex_lock(&mb1_transfer.lock); | 996 | mutex_lock(&mb1_transfer.lock); |
1224 | 997 | ||
1225 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 998 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
1226 | cpu_relax(); | 999 | cpu_relax(); |
1227 | 1000 | ||
1228 | writeb(MB1H_RELEASE_USB_WAKEUP, | 1001 | writeb(MB1H_RELEASE_USB_WAKEUP, |
1229 | (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1002 | (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1230 | 1003 | ||
1231 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 1004 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1232 | wait_for_completion(&mb1_transfer.work); | 1005 | wait_for_completion(&mb1_transfer.work); |
1233 | 1006 | ||
1234 | if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || | 1007 | if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || |
@@ -1240,45 +1013,15 @@ int prcmu_release_usb_wakeup_state(void) | |||
1240 | return r; | 1013 | return r; |
1241 | } | 1014 | } |
1242 | 1015 | ||
1243 | static int request_pll(u8 clock, bool enable) | ||
1244 | { | ||
1245 | int r = 0; | ||
1246 | |||
1247 | if (clock == PRCMU_PLLSOC0) | ||
1248 | clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF); | ||
1249 | else if (clock == PRCMU_PLLSOC1) | ||
1250 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); | ||
1251 | else | ||
1252 | return -EINVAL; | ||
1253 | |||
1254 | mutex_lock(&mb1_transfer.lock); | ||
1255 | |||
1256 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | ||
1257 | cpu_relax(); | ||
1258 | |||
1259 | writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | ||
1260 | writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF)); | ||
1261 | |||
1262 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | ||
1263 | wait_for_completion(&mb1_transfer.work); | ||
1264 | |||
1265 | if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF) | ||
1266 | r = -EIO; | ||
1267 | |||
1268 | mutex_unlock(&mb1_transfer.lock); | ||
1269 | |||
1270 | return r; | ||
1271 | } | ||
1272 | |||
1273 | /** | 1016 | /** |
1274 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) | 1017 | * prcmu_set_epod - set the state of a EPOD (power domain) |
1275 | * @epod_id: The EPOD to set | 1018 | * @epod_id: The EPOD to set |
1276 | * @epod_state: The new EPOD state | 1019 | * @epod_state: The new EPOD state |
1277 | * | 1020 | * |
1278 | * This function sets the state of a EPOD (power domain). It may not be called | 1021 | * This function sets the state of a EPOD (power domain). It may not be called |
1279 | * from interrupt context. | 1022 | * from interrupt context. |
1280 | */ | 1023 | */ |
1281 | int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) | 1024 | int prcmu_set_epod(u16 epod_id, u8 epod_state) |
1282 | { | 1025 | { |
1283 | int r = 0; | 1026 | int r = 0; |
1284 | bool ram_retention = false; | 1027 | bool ram_retention = false; |
@@ -1305,7 +1048,7 @@ int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) | |||
1305 | mutex_lock(&mb2_transfer.lock); | 1048 | mutex_lock(&mb2_transfer.lock); |
1306 | 1049 | ||
1307 | /* wait for mailbox */ | 1050 | /* wait for mailbox */ |
1308 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) | 1051 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) |
1309 | cpu_relax(); | 1052 | cpu_relax(); |
1310 | 1053 | ||
1311 | /* fill in mailbox */ | 1054 | /* fill in mailbox */ |
@@ -1315,7 +1058,7 @@ int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) | |||
1315 | 1058 | ||
1316 | writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); | 1059 | writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); |
1317 | 1060 | ||
1318 | writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET); | 1061 | writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1319 | 1062 | ||
1320 | /* | 1063 | /* |
1321 | * The current firmware version does not handle errors correctly, | 1064 | * The current firmware version does not handle errors correctly, |
@@ -1402,13 +1145,13 @@ static int request_sysclk(bool enable) | |||
1402 | 1145 | ||
1403 | spin_lock_irqsave(&mb3_transfer.lock, flags); | 1146 | spin_lock_irqsave(&mb3_transfer.lock, flags); |
1404 | 1147 | ||
1405 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) | 1148 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) |
1406 | cpu_relax(); | 1149 | cpu_relax(); |
1407 | 1150 | ||
1408 | writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); | 1151 | writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); |
1409 | 1152 | ||
1410 | writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); | 1153 | writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); |
1411 | writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET); | 1154 | writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
1412 | 1155 | ||
1413 | spin_unlock_irqrestore(&mb3_transfer.lock, flags); | 1156 | spin_unlock_irqrestore(&mb3_transfer.lock, flags); |
1414 | 1157 | ||
@@ -1434,12 +1177,12 @@ static int request_timclk(bool enable) | |||
1434 | 1177 | ||
1435 | if (!enable) | 1178 | if (!enable) |
1436 | val |= PRCM_TCR_STOP_TIMERS; | 1179 | val |= PRCM_TCR_STOP_TIMERS; |
1437 | writel(val, PRCM_TCR); | 1180 | writel(val, (_PRCMU_BASE + PRCM_TCR)); |
1438 | 1181 | ||
1439 | return 0; | 1182 | return 0; |
1440 | } | 1183 | } |
1441 | 1184 | ||
1442 | static int request_clock(u8 clock, bool enable) | 1185 | static int request_reg_clock(u8 clock, bool enable) |
1443 | { | 1186 | { |
1444 | u32 val; | 1187 | u32 val; |
1445 | unsigned long flags; | 1188 | unsigned long flags; |
@@ -1447,645 +1190,47 @@ static int request_clock(u8 clock, bool enable) | |||
1447 | spin_lock_irqsave(&clk_mgt_lock, flags); | 1190 | spin_lock_irqsave(&clk_mgt_lock, flags); |
1448 | 1191 | ||
1449 | /* Grab the HW semaphore. */ | 1192 | /* Grab the HW semaphore. */ |
1450 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 1193 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
1451 | cpu_relax(); | 1194 | cpu_relax(); |
1452 | 1195 | ||
1453 | val = readl(clk_mgt[clock].reg); | 1196 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); |
1454 | if (enable) { | 1197 | if (enable) { |
1455 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); | 1198 | val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); |
1456 | } else { | 1199 | } else { |
1457 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | 1200 | clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); |
1458 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); | 1201 | val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); |
1459 | } | 1202 | } |
1460 | writel(val, clk_mgt[clock].reg); | 1203 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); |
1461 | 1204 | ||
1462 | /* Release the HW semaphore. */ | 1205 | /* Release the HW semaphore. */ |
1463 | writel(0, PRCM_SEM); | 1206 | writel(0, (_PRCMU_BASE + PRCM_SEM)); |
1464 | 1207 | ||
1465 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | 1208 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
1466 | 1209 | ||
1467 | return 0; | 1210 | return 0; |
1468 | } | 1211 | } |
1469 | 1212 | ||
1470 | static int request_sga_clock(u8 clock, bool enable) | ||
1471 | { | ||
1472 | u32 val; | ||
1473 | int ret; | ||
1474 | |||
1475 | if (enable) { | ||
1476 | val = readl(PRCM_CGATING_BYPASS); | ||
1477 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | ||
1478 | } | ||
1479 | |||
1480 | ret = request_clock(clock, enable); | ||
1481 | |||
1482 | if (!ret && !enable) { | ||
1483 | val = readl(PRCM_CGATING_BYPASS); | ||
1484 | writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | ||
1485 | } | ||
1486 | |||
1487 | return ret; | ||
1488 | } | ||
1489 | |||
1490 | static inline bool plldsi_locked(void) | ||
1491 | { | ||
1492 | return (readl(PRCM_PLLDSI_LOCKP) & | ||
1493 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
1494 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) == | ||
1495 | (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 | | ||
1496 | PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3); | ||
1497 | } | ||
1498 | |||
1499 | static int request_plldsi(bool enable) | ||
1500 | { | ||
1501 | int r = 0; | ||
1502 | u32 val; | ||
1503 | |||
1504 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
1505 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ? | ||
1506 | PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET)); | ||
1507 | |||
1508 | val = readl(PRCM_PLLDSI_ENABLE); | ||
1509 | if (enable) | ||
1510 | val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1511 | else | ||
1512 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1513 | writel(val, PRCM_PLLDSI_ENABLE); | ||
1514 | |||
1515 | if (enable) { | ||
1516 | unsigned int i; | ||
1517 | bool locked = plldsi_locked(); | ||
1518 | |||
1519 | for (i = 10; !locked && (i > 0); --i) { | ||
1520 | udelay(100); | ||
1521 | locked = plldsi_locked(); | ||
1522 | } | ||
1523 | if (locked) { | ||
1524 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, | ||
1525 | PRCM_APE_RESETN_SET); | ||
1526 | } else { | ||
1527 | writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP | | ||
1528 | PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), | ||
1529 | PRCM_MMIP_LS_CLAMP_SET); | ||
1530 | val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE; | ||
1531 | writel(val, PRCM_PLLDSI_ENABLE); | ||
1532 | r = -EAGAIN; | ||
1533 | } | ||
1534 | } else { | ||
1535 | writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR); | ||
1536 | } | ||
1537 | return r; | ||
1538 | } | ||
1539 | |||
1540 | static int request_dsiclk(u8 n, bool enable) | ||
1541 | { | ||
1542 | u32 val; | ||
1543 | |||
1544 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
1545 | val &= ~dsiclk[n].divsel_mask; | ||
1546 | val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) << | ||
1547 | dsiclk[n].divsel_shift); | ||
1548 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
1549 | return 0; | ||
1550 | } | ||
1551 | |||
1552 | static int request_dsiescclk(u8 n, bool enable) | ||
1553 | { | ||
1554 | u32 val; | ||
1555 | |||
1556 | val = readl(PRCM_DSITVCLK_DIV); | ||
1557 | enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en); | ||
1558 | writel(val, PRCM_DSITVCLK_DIV); | ||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1562 | /** | 1213 | /** |
1563 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. | 1214 | * prcmu_request_clock() - Request for a clock to be enabled or disabled. |
1564 | * @clock: The clock for which the request is made. | 1215 | * @clock: The clock for which the request is made. |
1565 | * @enable: Whether the clock should be enabled (true) or disabled (false). | 1216 | * @enable: Whether the clock should be enabled (true) or disabled (false). |
1566 | * | 1217 | * |
1567 | * This function should only be used by the clock implementation. | 1218 | * This function should only be used by the clock implementation. |
1568 | * Do not use it from any other place! | 1219 | * Do not use it from any other place! |
1569 | */ | 1220 | */ |
1570 | int db8500_prcmu_request_clock(u8 clock, bool enable) | 1221 | int prcmu_request_clock(u8 clock, bool enable) |
1571 | { | 1222 | { |
1572 | if (clock == PRCMU_SGACLK) | 1223 | if (clock < PRCMU_NUM_REG_CLOCKS) |
1573 | return request_sga_clock(clock, enable); | 1224 | return request_reg_clock(clock, enable); |
1574 | else if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1575 | return request_clock(clock, enable); | ||
1576 | else if (clock == PRCMU_TIMCLK) | 1225 | else if (clock == PRCMU_TIMCLK) |
1577 | return request_timclk(enable); | 1226 | return request_timclk(enable); |
1578 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1579 | return request_dsiclk((clock - PRCMU_DSI0CLK), enable); | ||
1580 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1581 | return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable); | ||
1582 | else if (clock == PRCMU_PLLDSI) | ||
1583 | return request_plldsi(enable); | ||
1584 | else if (clock == PRCMU_SYSCLK) | 1227 | else if (clock == PRCMU_SYSCLK) |
1585 | return request_sysclk(enable); | 1228 | return request_sysclk(enable); |
1586 | else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1)) | ||
1587 | return request_pll(clock, enable); | ||
1588 | else | 1229 | else |
1589 | return -EINVAL; | 1230 | return -EINVAL; |
1590 | } | 1231 | } |
1591 | 1232 | ||
1592 | static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, | 1233 | int prcmu_config_esram0_deep_sleep(u8 state) |
1593 | int branch) | ||
1594 | { | ||
1595 | u64 rate; | ||
1596 | u32 val; | ||
1597 | u32 d; | ||
1598 | u32 div = 1; | ||
1599 | |||
1600 | val = readl(reg); | ||
1601 | |||
1602 | rate = src_rate; | ||
1603 | rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT); | ||
1604 | |||
1605 | d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT); | ||
1606 | if (d > 1) | ||
1607 | div *= d; | ||
1608 | |||
1609 | d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT); | ||
1610 | if (d > 1) | ||
1611 | div *= d; | ||
1612 | |||
1613 | if (val & PRCM_PLL_FREQ_SELDIV2) | ||
1614 | div *= 2; | ||
1615 | |||
1616 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && | ||
1617 | (val & PRCM_PLL_FREQ_DIV2EN) && | ||
1618 | ((reg == PRCM_PLLSOC0_FREQ) || | ||
1619 | (reg == PRCM_PLLARM_FREQ) || | ||
1620 | (reg == PRCM_PLLDDR_FREQ)))) | ||
1621 | div *= 2; | ||
1622 | |||
1623 | (void)do_div(rate, div); | ||
1624 | |||
1625 | return (unsigned long)rate; | ||
1626 | } | ||
1627 | |||
1628 | #define ROOT_CLOCK_RATE 38400000 | ||
1629 | |||
1630 | static unsigned long clock_rate(u8 clock) | ||
1631 | { | ||
1632 | u32 val; | ||
1633 | u32 pllsw; | ||
1634 | unsigned long rate = ROOT_CLOCK_RATE; | ||
1635 | |||
1636 | val = readl(clk_mgt[clock].reg); | ||
1637 | |||
1638 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1639 | if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV)) | ||
1640 | rate /= 2; | ||
1641 | return rate; | ||
1642 | } | ||
1643 | |||
1644 | val |= clk_mgt[clock].pllsw; | ||
1645 | pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); | ||
1646 | |||
1647 | if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
1648 | rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch); | ||
1649 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
1650 | rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch); | ||
1651 | else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
1652 | rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch); | ||
1653 | else | ||
1654 | return 0; | ||
1655 | |||
1656 | if ((clock == PRCMU_SGACLK) && | ||
1657 | (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) { | ||
1658 | u64 r = (rate * 10); | ||
1659 | |||
1660 | (void)do_div(r, 25); | ||
1661 | return (unsigned long)r; | ||
1662 | } | ||
1663 | val &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1664 | if (val) | ||
1665 | return rate / val; | ||
1666 | else | ||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | static unsigned long armss_rate(void) | ||
1671 | { | ||
1672 | u32 r; | ||
1673 | unsigned long rate; | ||
1674 | |||
1675 | r = readl(PRCM_ARM_CHGCLKREQ); | ||
1676 | |||
1677 | if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) { | ||
1678 | /* External ARMCLKFIX clock */ | ||
1679 | |||
1680 | rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX); | ||
1681 | |||
1682 | /* Check PRCM_ARM_CHGCLKREQ divider */ | ||
1683 | if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL)) | ||
1684 | rate /= 2; | ||
1685 | |||
1686 | /* Check PRCM_ARMCLKFIX_MGT divider */ | ||
1687 | r = readl(PRCM_ARMCLKFIX_MGT); | ||
1688 | r &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1689 | rate /= r; | ||
1690 | |||
1691 | } else {/* ARM PLL */ | ||
1692 | rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV); | ||
1693 | } | ||
1694 | |||
1695 | return rate; | ||
1696 | } | ||
1697 | |||
1698 | static unsigned long dsiclk_rate(u8 n) | ||
1699 | { | ||
1700 | u32 divsel; | ||
1701 | u32 div = 1; | ||
1702 | |||
1703 | divsel = readl(PRCM_DSI_PLLOUT_SEL); | ||
1704 | divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift); | ||
1705 | |||
1706 | if (divsel == PRCM_DSI_PLLOUT_SEL_OFF) | ||
1707 | divsel = dsiclk[n].divsel; | ||
1708 | |||
1709 | switch (divsel) { | ||
1710 | case PRCM_DSI_PLLOUT_SEL_PHI_4: | ||
1711 | div *= 2; | ||
1712 | case PRCM_DSI_PLLOUT_SEL_PHI_2: | ||
1713 | div *= 2; | ||
1714 | case PRCM_DSI_PLLOUT_SEL_PHI: | ||
1715 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1716 | PLL_RAW) / div; | ||
1717 | default: | ||
1718 | return 0; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | static unsigned long dsiescclk_rate(u8 n) | ||
1723 | { | ||
1724 | u32 div; | ||
1725 | |||
1726 | div = readl(PRCM_DSITVCLK_DIV); | ||
1727 | div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift)); | ||
1728 | return clock_rate(PRCMU_TVCLK) / max((u32)1, div); | ||
1729 | } | ||
1730 | |||
1731 | unsigned long prcmu_clock_rate(u8 clock) | ||
1732 | { | ||
1733 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1734 | return clock_rate(clock); | ||
1735 | else if (clock == PRCMU_TIMCLK) | ||
1736 | return ROOT_CLOCK_RATE / 16; | ||
1737 | else if (clock == PRCMU_SYSCLK) | ||
1738 | return ROOT_CLOCK_RATE; | ||
1739 | else if (clock == PRCMU_PLLSOC0) | ||
1740 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1741 | else if (clock == PRCMU_PLLSOC1) | ||
1742 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1743 | else if (clock == PRCMU_ARMSS) | ||
1744 | return armss_rate(); | ||
1745 | else if (clock == PRCMU_PLLDDR) | ||
1746 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | ||
1747 | else if (clock == PRCMU_PLLDSI) | ||
1748 | return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1749 | PLL_RAW); | ||
1750 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1751 | return dsiclk_rate(clock - PRCMU_DSI0CLK); | ||
1752 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1753 | return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK); | ||
1754 | else | ||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1758 | static unsigned long clock_source_rate(u32 clk_mgt_val, int branch) | ||
1759 | { | ||
1760 | if (clk_mgt_val & PRCM_CLK_MGT_CLK38) | ||
1761 | return ROOT_CLOCK_RATE; | ||
1762 | clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK; | ||
1763 | if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0) | ||
1764 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch); | ||
1765 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1) | ||
1766 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch); | ||
1767 | else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR) | ||
1768 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch); | ||
1769 | else | ||
1770 | return 0; | ||
1771 | } | ||
1772 | |||
1773 | static u32 clock_divider(unsigned long src_rate, unsigned long rate) | ||
1774 | { | ||
1775 | u32 div; | ||
1776 | |||
1777 | div = (src_rate / rate); | ||
1778 | if (div == 0) | ||
1779 | return 1; | ||
1780 | if (rate < (src_rate / div)) | ||
1781 | div++; | ||
1782 | return div; | ||
1783 | } | ||
1784 | |||
1785 | static long round_clock_rate(u8 clock, unsigned long rate) | ||
1786 | { | ||
1787 | u32 val; | ||
1788 | u32 div; | ||
1789 | unsigned long src_rate; | ||
1790 | long rounded_rate; | ||
1791 | |||
1792 | val = readl(clk_mgt[clock].reg); | ||
1793 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
1794 | clk_mgt[clock].branch); | ||
1795 | div = clock_divider(src_rate, rate); | ||
1796 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1797 | if (clk_mgt[clock].clk38div) { | ||
1798 | if (div > 2) | ||
1799 | div = 2; | ||
1800 | } else { | ||
1801 | div = 1; | ||
1802 | } | ||
1803 | } else if ((clock == PRCMU_SGACLK) && (div == 3)) { | ||
1804 | u64 r = (src_rate * 10); | ||
1805 | |||
1806 | (void)do_div(r, 25); | ||
1807 | if (r <= rate) | ||
1808 | return (unsigned long)r; | ||
1809 | } | ||
1810 | rounded_rate = (src_rate / min(div, (u32)31)); | ||
1811 | |||
1812 | return rounded_rate; | ||
1813 | } | ||
1814 | |||
1815 | /* CPU FREQ table, may be changed due to if MAX_OPP is supported. */ | ||
1816 | static struct cpufreq_frequency_table db8500_cpufreq_table[] = { | ||
1817 | { .frequency = 200000, .index = ARM_EXTCLK,}, | ||
1818 | { .frequency = 400000, .index = ARM_50_OPP,}, | ||
1819 | { .frequency = 800000, .index = ARM_100_OPP,}, | ||
1820 | { .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */ | ||
1821 | { .frequency = CPUFREQ_TABLE_END,}, | ||
1822 | }; | ||
1823 | |||
1824 | static long round_armss_rate(unsigned long rate) | ||
1825 | { | ||
1826 | long freq = 0; | ||
1827 | int i = 0; | ||
1828 | |||
1829 | /* cpufreq table frequencies is in KHz. */ | ||
1830 | rate = rate / 1000; | ||
1831 | |||
1832 | /* Find the corresponding arm opp from the cpufreq table. */ | ||
1833 | while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) { | ||
1834 | freq = db8500_cpufreq_table[i].frequency; | ||
1835 | if (freq == rate) | ||
1836 | break; | ||
1837 | i++; | ||
1838 | } | ||
1839 | |||
1840 | /* Return the last valid value, even if a match was not found. */ | ||
1841 | return freq * 1000; | ||
1842 | } | ||
1843 | |||
1844 | #define MIN_PLL_VCO_RATE 600000000ULL | ||
1845 | #define MAX_PLL_VCO_RATE 1680640000ULL | ||
1846 | |||
1847 | static long round_plldsi_rate(unsigned long rate) | ||
1848 | { | ||
1849 | long rounded_rate = 0; | ||
1850 | unsigned long src_rate; | ||
1851 | unsigned long rem; | ||
1852 | u32 r; | ||
1853 | |||
1854 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
1855 | rem = rate; | ||
1856 | |||
1857 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
1858 | u64 d; | ||
1859 | |||
1860 | d = (r * rate); | ||
1861 | (void)do_div(d, src_rate); | ||
1862 | if (d < 6) | ||
1863 | d = 6; | ||
1864 | else if (d > 255) | ||
1865 | d = 255; | ||
1866 | d *= src_rate; | ||
1867 | if (((2 * d) < (r * MIN_PLL_VCO_RATE)) || | ||
1868 | ((r * MAX_PLL_VCO_RATE) < (2 * d))) | ||
1869 | continue; | ||
1870 | (void)do_div(d, r); | ||
1871 | if (rate < d) { | ||
1872 | if (rounded_rate == 0) | ||
1873 | rounded_rate = (long)d; | ||
1874 | break; | ||
1875 | } | ||
1876 | if ((rate - d) < rem) { | ||
1877 | rem = (rate - d); | ||
1878 | rounded_rate = (long)d; | ||
1879 | } | ||
1880 | } | ||
1881 | return rounded_rate; | ||
1882 | } | ||
1883 | |||
1884 | static long round_dsiclk_rate(unsigned long rate) | ||
1885 | { | ||
1886 | u32 div; | ||
1887 | unsigned long src_rate; | ||
1888 | long rounded_rate; | ||
1889 | |||
1890 | src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), | ||
1891 | PLL_RAW); | ||
1892 | div = clock_divider(src_rate, rate); | ||
1893 | rounded_rate = (src_rate / ((div > 2) ? 4 : div)); | ||
1894 | |||
1895 | return rounded_rate; | ||
1896 | } | ||
1897 | |||
1898 | static long round_dsiescclk_rate(unsigned long rate) | ||
1899 | { | ||
1900 | u32 div; | ||
1901 | unsigned long src_rate; | ||
1902 | long rounded_rate; | ||
1903 | |||
1904 | src_rate = clock_rate(PRCMU_TVCLK); | ||
1905 | div = clock_divider(src_rate, rate); | ||
1906 | rounded_rate = (src_rate / min(div, (u32)255)); | ||
1907 | |||
1908 | return rounded_rate; | ||
1909 | } | ||
1910 | |||
1911 | long prcmu_round_clock_rate(u8 clock, unsigned long rate) | ||
1912 | { | ||
1913 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1914 | return round_clock_rate(clock, rate); | ||
1915 | else if (clock == PRCMU_ARMSS) | ||
1916 | return round_armss_rate(rate); | ||
1917 | else if (clock == PRCMU_PLLDSI) | ||
1918 | return round_plldsi_rate(rate); | ||
1919 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
1920 | return round_dsiclk_rate(rate); | ||
1921 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
1922 | return round_dsiescclk_rate(rate); | ||
1923 | else | ||
1924 | return (long)prcmu_clock_rate(clock); | ||
1925 | } | ||
1926 | |||
1927 | static void set_clock_rate(u8 clock, unsigned long rate) | ||
1928 | { | ||
1929 | u32 val; | ||
1930 | u32 div; | ||
1931 | unsigned long src_rate; | ||
1932 | unsigned long flags; | ||
1933 | |||
1934 | spin_lock_irqsave(&clk_mgt_lock, flags); | ||
1935 | |||
1936 | /* Grab the HW semaphore. */ | ||
1937 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | ||
1938 | cpu_relax(); | ||
1939 | |||
1940 | val = readl(clk_mgt[clock].reg); | ||
1941 | src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), | ||
1942 | clk_mgt[clock].branch); | ||
1943 | div = clock_divider(src_rate, rate); | ||
1944 | if (val & PRCM_CLK_MGT_CLK38) { | ||
1945 | if (clk_mgt[clock].clk38div) { | ||
1946 | if (div > 1) | ||
1947 | val |= PRCM_CLK_MGT_CLK38DIV; | ||
1948 | else | ||
1949 | val &= ~PRCM_CLK_MGT_CLK38DIV; | ||
1950 | } | ||
1951 | } else if (clock == PRCMU_SGACLK) { | ||
1952 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK | | ||
1953 | PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN); | ||
1954 | if (div == 3) { | ||
1955 | u64 r = (src_rate * 10); | ||
1956 | |||
1957 | (void)do_div(r, 25); | ||
1958 | if (r <= rate) { | ||
1959 | val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN; | ||
1960 | div = 0; | ||
1961 | } | ||
1962 | } | ||
1963 | val |= min(div, (u32)31); | ||
1964 | } else { | ||
1965 | val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1966 | val |= min(div, (u32)31); | ||
1967 | } | ||
1968 | writel(val, clk_mgt[clock].reg); | ||
1969 | |||
1970 | /* Release the HW semaphore. */ | ||
1971 | writel(0, PRCM_SEM); | ||
1972 | |||
1973 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | ||
1974 | } | ||
1975 | |||
1976 | static int set_armss_rate(unsigned long rate) | ||
1977 | { | ||
1978 | int i = 0; | ||
1979 | |||
1980 | /* cpufreq table frequencies is in KHz. */ | ||
1981 | rate = rate / 1000; | ||
1982 | |||
1983 | /* Find the corresponding arm opp from the cpufreq table. */ | ||
1984 | while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) { | ||
1985 | if (db8500_cpufreq_table[i].frequency == rate) | ||
1986 | break; | ||
1987 | i++; | ||
1988 | } | ||
1989 | |||
1990 | if (db8500_cpufreq_table[i].frequency != rate) | ||
1991 | return -EINVAL; | ||
1992 | |||
1993 | /* Set the new arm opp. */ | ||
1994 | return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].index); | ||
1995 | } | ||
1996 | |||
1997 | static int set_plldsi_rate(unsigned long rate) | ||
1998 | { | ||
1999 | unsigned long src_rate; | ||
2000 | unsigned long rem; | ||
2001 | u32 pll_freq = 0; | ||
2002 | u32 r; | ||
2003 | |||
2004 | src_rate = clock_rate(PRCMU_HDMICLK); | ||
2005 | rem = rate; | ||
2006 | |||
2007 | for (r = 7; (rem > 0) && (r > 0); r--) { | ||
2008 | u64 d; | ||
2009 | u64 hwrate; | ||
2010 | |||
2011 | d = (r * rate); | ||
2012 | (void)do_div(d, src_rate); | ||
2013 | if (d < 6) | ||
2014 | d = 6; | ||
2015 | else if (d > 255) | ||
2016 | d = 255; | ||
2017 | hwrate = (d * src_rate); | ||
2018 | if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) || | ||
2019 | ((r * MAX_PLL_VCO_RATE) < (2 * hwrate))) | ||
2020 | continue; | ||
2021 | (void)do_div(hwrate, r); | ||
2022 | if (rate < hwrate) { | ||
2023 | if (pll_freq == 0) | ||
2024 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
2025 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
2026 | break; | ||
2027 | } | ||
2028 | if ((rate - hwrate) < rem) { | ||
2029 | rem = (rate - hwrate); | ||
2030 | pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) | | ||
2031 | (r << PRCM_PLL_FREQ_R_SHIFT)); | ||
2032 | } | ||
2033 | } | ||
2034 | if (pll_freq == 0) | ||
2035 | return -EINVAL; | ||
2036 | |||
2037 | pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT); | ||
2038 | writel(pll_freq, PRCM_PLLDSI_FREQ); | ||
2039 | |||
2040 | return 0; | ||
2041 | } | ||
2042 | |||
2043 | static void set_dsiclk_rate(u8 n, unsigned long rate) | ||
2044 | { | ||
2045 | u32 val; | ||
2046 | u32 div; | ||
2047 | |||
2048 | div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ, | ||
2049 | clock_rate(PRCMU_HDMICLK), PLL_RAW), rate); | ||
2050 | |||
2051 | dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI : | ||
2052 | (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 : | ||
2053 | /* else */ PRCM_DSI_PLLOUT_SEL_PHI_4; | ||
2054 | |||
2055 | val = readl(PRCM_DSI_PLLOUT_SEL); | ||
2056 | val &= ~dsiclk[n].divsel_mask; | ||
2057 | val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift); | ||
2058 | writel(val, PRCM_DSI_PLLOUT_SEL); | ||
2059 | } | ||
2060 | |||
2061 | static void set_dsiescclk_rate(u8 n, unsigned long rate) | ||
2062 | { | ||
2063 | u32 val; | ||
2064 | u32 div; | ||
2065 | |||
2066 | div = clock_divider(clock_rate(PRCMU_TVCLK), rate); | ||
2067 | val = readl(PRCM_DSITVCLK_DIV); | ||
2068 | val &= ~dsiescclk[n].div_mask; | ||
2069 | val |= (min(div, (u32)255) << dsiescclk[n].div_shift); | ||
2070 | writel(val, PRCM_DSITVCLK_DIV); | ||
2071 | } | ||
2072 | |||
2073 | int prcmu_set_clock_rate(u8 clock, unsigned long rate) | ||
2074 | { | ||
2075 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
2076 | set_clock_rate(clock, rate); | ||
2077 | else if (clock == PRCMU_ARMSS) | ||
2078 | return set_armss_rate(rate); | ||
2079 | else if (clock == PRCMU_PLLDSI) | ||
2080 | return set_plldsi_rate(rate); | ||
2081 | else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK)) | ||
2082 | set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate); | ||
2083 | else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK)) | ||
2084 | set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate); | ||
2085 | return 0; | ||
2086 | } | ||
2087 | |||
2088 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) | ||
2089 | { | 1234 | { |
2090 | if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || | 1235 | if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || |
2091 | (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) | 1236 | (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) |
@@ -2093,7 +1238,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) | |||
2093 | 1238 | ||
2094 | mutex_lock(&mb4_transfer.lock); | 1239 | mutex_lock(&mb4_transfer.lock); |
2095 | 1240 | ||
2096 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1241 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
2097 | cpu_relax(); | 1242 | cpu_relax(); |
2098 | 1243 | ||
2099 | writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1244 | writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
@@ -2103,7 +1248,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) | |||
2103 | (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); | 1248 | (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); |
2104 | writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); | 1249 | writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); |
2105 | 1250 | ||
2106 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | 1251 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2107 | wait_for_completion(&mb4_transfer.work); | 1252 | wait_for_completion(&mb4_transfer.work); |
2108 | 1253 | ||
2109 | mutex_unlock(&mb4_transfer.lock); | 1254 | mutex_unlock(&mb4_transfer.lock); |
@@ -2111,17 +1256,17 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) | |||
2111 | return 0; | 1256 | return 0; |
2112 | } | 1257 | } |
2113 | 1258 | ||
2114 | int db8500_prcmu_config_hotdog(u8 threshold) | 1259 | int prcmu_config_hotdog(u8 threshold) |
2115 | { | 1260 | { |
2116 | mutex_lock(&mb4_transfer.lock); | 1261 | mutex_lock(&mb4_transfer.lock); |
2117 | 1262 | ||
2118 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1263 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
2119 | cpu_relax(); | 1264 | cpu_relax(); |
2120 | 1265 | ||
2121 | writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); | 1266 | writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); |
2122 | writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1267 | writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
2123 | 1268 | ||
2124 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | 1269 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2125 | wait_for_completion(&mb4_transfer.work); | 1270 | wait_for_completion(&mb4_transfer.work); |
2126 | 1271 | ||
2127 | mutex_unlock(&mb4_transfer.lock); | 1272 | mutex_unlock(&mb4_transfer.lock); |
@@ -2129,11 +1274,11 @@ int db8500_prcmu_config_hotdog(u8 threshold) | |||
2129 | return 0; | 1274 | return 0; |
2130 | } | 1275 | } |
2131 | 1276 | ||
2132 | int db8500_prcmu_config_hotmon(u8 low, u8 high) | 1277 | int prcmu_config_hotmon(u8 low, u8 high) |
2133 | { | 1278 | { |
2134 | mutex_lock(&mb4_transfer.lock); | 1279 | mutex_lock(&mb4_transfer.lock); |
2135 | 1280 | ||
2136 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1281 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
2137 | cpu_relax(); | 1282 | cpu_relax(); |
2138 | 1283 | ||
2139 | writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); | 1284 | writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); |
@@ -2142,7 +1287,7 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high) | |||
2142 | (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); | 1287 | (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); |
2143 | writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1288 | writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
2144 | 1289 | ||
2145 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | 1290 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2146 | wait_for_completion(&mb4_transfer.work); | 1291 | wait_for_completion(&mb4_transfer.work); |
2147 | 1292 | ||
2148 | mutex_unlock(&mb4_transfer.lock); | 1293 | mutex_unlock(&mb4_transfer.lock); |
@@ -2154,13 +1299,13 @@ static int config_hot_period(u16 val) | |||
2154 | { | 1299 | { |
2155 | mutex_lock(&mb4_transfer.lock); | 1300 | mutex_lock(&mb4_transfer.lock); |
2156 | 1301 | ||
2157 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1302 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
2158 | cpu_relax(); | 1303 | cpu_relax(); |
2159 | 1304 | ||
2160 | writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); | 1305 | writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); |
2161 | writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1306 | writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
2162 | 1307 | ||
2163 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | 1308 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2164 | wait_for_completion(&mb4_transfer.work); | 1309 | wait_for_completion(&mb4_transfer.work); |
2165 | 1310 | ||
2166 | mutex_unlock(&mb4_transfer.lock); | 1311 | mutex_unlock(&mb4_transfer.lock); |
@@ -2168,7 +1313,7 @@ static int config_hot_period(u16 val) | |||
2168 | return 0; | 1313 | return 0; |
2169 | } | 1314 | } |
2170 | 1315 | ||
2171 | int db8500_prcmu_start_temp_sense(u16 cycles32k) | 1316 | int prcmu_start_temp_sense(u16 cycles32k) |
2172 | { | 1317 | { |
2173 | if (cycles32k == 0xFFFF) | 1318 | if (cycles32k == 0xFFFF) |
2174 | return -EINVAL; | 1319 | return -EINVAL; |
@@ -2176,73 +1321,44 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k) | |||
2176 | return config_hot_period(cycles32k); | 1321 | return config_hot_period(cycles32k); |
2177 | } | 1322 | } |
2178 | 1323 | ||
2179 | int db8500_prcmu_stop_temp_sense(void) | 1324 | int prcmu_stop_temp_sense(void) |
2180 | { | 1325 | { |
2181 | return config_hot_period(0xFFFF); | 1326 | return config_hot_period(0xFFFF); |
2182 | } | 1327 | } |
2183 | 1328 | ||
2184 | static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) | 1329 | /** |
1330 | * prcmu_set_clock_divider() - Configure the clock divider. | ||
1331 | * @clock: The clock for which the request is made. | ||
1332 | * @divider: The clock divider. (< 32) | ||
1333 | * | ||
1334 | * This function should only be used by the clock implementation. | ||
1335 | * Do not use it from any other place! | ||
1336 | */ | ||
1337 | int prcmu_set_clock_divider(u8 clock, u8 divider) | ||
2185 | { | 1338 | { |
1339 | u32 val; | ||
1340 | unsigned long flags; | ||
2186 | 1341 | ||
2187 | mutex_lock(&mb4_transfer.lock); | 1342 | if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider)) |
1343 | return -EINVAL; | ||
2188 | 1344 | ||
2189 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1345 | spin_lock_irqsave(&clk_mgt_lock, flags); |
2190 | cpu_relax(); | ||
2191 | 1346 | ||
2192 | writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0)); | 1347 | /* Grab the HW semaphore. */ |
2193 | writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1)); | 1348 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
2194 | writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2)); | 1349 | cpu_relax(); |
2195 | writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3)); | ||
2196 | 1350 | ||
2197 | writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1351 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); |
1352 | val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK); | ||
1353 | val |= (u32)divider; | ||
1354 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | ||
2198 | 1355 | ||
2199 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | 1356 | /* Release the HW semaphore. */ |
2200 | wait_for_completion(&mb4_transfer.work); | 1357 | writel(0, (_PRCMU_BASE + PRCM_SEM)); |
2201 | 1358 | ||
2202 | mutex_unlock(&mb4_transfer.lock); | 1359 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
2203 | 1360 | ||
2204 | return 0; | 1361 | return 0; |
2205 | |||
2206 | } | ||
2207 | |||
2208 | int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | ||
2209 | { | ||
2210 | BUG_ON(num == 0 || num > 0xf); | ||
2211 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, | ||
2212 | sleep_auto_off ? A9WDOG_AUTO_OFF_EN : | ||
2213 | A9WDOG_AUTO_OFF_DIS); | ||
2214 | } | ||
2215 | |||
2216 | int db8500_prcmu_enable_a9wdog(u8 id) | ||
2217 | { | ||
2218 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); | ||
2219 | } | ||
2220 | |||
2221 | int db8500_prcmu_disable_a9wdog(u8 id) | ||
2222 | { | ||
2223 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); | ||
2224 | } | ||
2225 | |||
2226 | int db8500_prcmu_kick_a9wdog(u8 id) | ||
2227 | { | ||
2228 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); | ||
2229 | } | ||
2230 | |||
2231 | /* | ||
2232 | * timeout is 28 bit, in ms. | ||
2233 | */ | ||
2234 | int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) | ||
2235 | { | ||
2236 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, | ||
2237 | (id & A9WDOG_ID_MASK) | | ||
2238 | /* | ||
2239 | * Put the lowest 28 bits of timeout at | ||
2240 | * offset 4. Four first bits are used for id. | ||
2241 | */ | ||
2242 | (u8)((timeout << 4) & 0xf0), | ||
2243 | (u8)((timeout >> 4) & 0xff), | ||
2244 | (u8)((timeout >> 12) & 0xff), | ||
2245 | (u8)((timeout >> 20) & 0xff)); | ||
2246 | } | 1362 | } |
2247 | 1363 | ||
2248 | /** | 1364 | /** |
@@ -2264,16 +1380,15 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
2264 | 1380 | ||
2265 | mutex_lock(&mb5_transfer.lock); | 1381 | mutex_lock(&mb5_transfer.lock); |
2266 | 1382 | ||
2267 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 1383 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
2268 | cpu_relax(); | 1384 | cpu_relax(); |
2269 | 1385 | ||
2270 | writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
2271 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 1386 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
2272 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 1387 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
2273 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 1388 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
2274 | writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); | 1389 | writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); |
2275 | 1390 | ||
2276 | writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); | 1391 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2277 | 1392 | ||
2278 | if (!wait_for_completion_timeout(&mb5_transfer.work, | 1393 | if (!wait_for_completion_timeout(&mb5_transfer.work, |
2279 | msecs_to_jiffies(20000))) { | 1394 | msecs_to_jiffies(20000))) { |
@@ -2293,19 +1408,16 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
2293 | } | 1408 | } |
2294 | 1409 | ||
2295 | /** | 1410 | /** |
2296 | * prcmu_abb_write_masked() - Write masked register value(s) to the ABB. | 1411 | * prcmu_abb_write() - Write register value(s) to the ABB. |
2297 | * @slave: The I2C slave address. | 1412 | * @slave: The I2C slave address. |
2298 | * @reg: The (start) register address. | 1413 | * @reg: The (start) register address. |
2299 | * @value: The value(s) to write. | 1414 | * @value: The value(s) to write. |
2300 | * @mask: The mask(s) to use. | ||
2301 | * @size: The number of registers to write. | 1415 | * @size: The number of registers to write. |
2302 | * | 1416 | * |
2303 | * Writes masked register value(s) to the ABB. | 1417 | * Reads register value(s) from the ABB. |
2304 | * For each @value, only the bits set to 1 in the corresponding @mask | ||
2305 | * will be written. The other bits are not changed. | ||
2306 | * @size has to be 1 for the current firmware version. | 1418 | * @size has to be 1 for the current firmware version. |
2307 | */ | 1419 | */ |
2308 | int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) | 1420 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) |
2309 | { | 1421 | { |
2310 | int r; | 1422 | int r; |
2311 | 1423 | ||
@@ -2314,16 +1426,15 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) | |||
2314 | 1426 | ||
2315 | mutex_lock(&mb5_transfer.lock); | 1427 | mutex_lock(&mb5_transfer.lock); |
2316 | 1428 | ||
2317 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 1429 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
2318 | cpu_relax(); | 1430 | cpu_relax(); |
2319 | 1431 | ||
2320 | writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5)); | ||
2321 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 1432 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
2322 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); | 1433 | writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); |
2323 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 1434 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
2324 | writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); | 1435 | writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); |
2325 | 1436 | ||
2326 | writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); | 1437 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2327 | 1438 | ||
2328 | if (!wait_for_completion_timeout(&mb5_transfer.work, | 1439 | if (!wait_for_completion_timeout(&mb5_transfer.work, |
2329 | msecs_to_jiffies(20000))) { | 1440 | msecs_to_jiffies(20000))) { |
@@ -2340,64 +1451,31 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size) | |||
2340 | } | 1451 | } |
2341 | 1452 | ||
2342 | /** | 1453 | /** |
2343 | * prcmu_abb_write() - Write register value(s) to the ABB. | ||
2344 | * @slave: The I2C slave address. | ||
2345 | * @reg: The (start) register address. | ||
2346 | * @value: The value(s) to write. | ||
2347 | * @size: The number of registers to write. | ||
2348 | * | ||
2349 | * Writes register value(s) to the ABB. | ||
2350 | * @size has to be 1 for the current firmware version. | ||
2351 | */ | ||
2352 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | ||
2353 | { | ||
2354 | u8 mask = ~0; | ||
2355 | |||
2356 | return prcmu_abb_write_masked(slave, reg, value, &mask, size); | ||
2357 | } | ||
2358 | |||
2359 | /** | ||
2360 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem | 1454 | * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem |
2361 | */ | 1455 | */ |
2362 | int prcmu_ac_wake_req(void) | 1456 | void prcmu_ac_wake_req(void) |
2363 | { | 1457 | { |
2364 | u32 val; | 1458 | u32 val; |
2365 | int ret = 0; | ||
2366 | 1459 | ||
2367 | mutex_lock(&mb0_transfer.ac_wake_lock); | 1460 | mutex_lock(&mb0_transfer.ac_wake_lock); |
2368 | 1461 | ||
2369 | val = readl(PRCM_HOSTACCESS_REQ); | 1462 | val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); |
2370 | if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) | 1463 | if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) |
2371 | goto unlock_and_return; | 1464 | goto unlock_and_return; |
2372 | 1465 | ||
2373 | atomic_set(&ac_wake_req_state, 1); | 1466 | atomic_set(&ac_wake_req_state, 1); |
2374 | 1467 | ||
2375 | /* | 1468 | writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), |
2376 | * Force Modem Wake-up before hostaccess_req ping-pong. | 1469 | (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); |
2377 | * It prevents Modem to enter in Sleep while acking the hostaccess | ||
2378 | * request. The 31us delay has been calculated by HWI. | ||
2379 | */ | ||
2380 | val |= PRCM_HOSTACCESS_REQ_WAKE_REQ; | ||
2381 | writel(val, PRCM_HOSTACCESS_REQ); | ||
2382 | |||
2383 | udelay(31); | ||
2384 | |||
2385 | val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ; | ||
2386 | writel(val, PRCM_HOSTACCESS_REQ); | ||
2387 | 1470 | ||
2388 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, | 1471 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, |
2389 | msecs_to_jiffies(5000))) { | 1472 | msecs_to_jiffies(20000))) { |
2390 | #if defined(CONFIG_DBX500_PRCMU_DEBUG) | 1473 | pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", |
2391 | db8500_prcmu_debug_dump(__func__, true, true); | ||
2392 | #endif | ||
2393 | pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n", | ||
2394 | __func__); | 1474 | __func__); |
2395 | ret = -EFAULT; | ||
2396 | } | 1475 | } |
2397 | 1476 | ||
2398 | unlock_and_return: | 1477 | unlock_and_return: |
2399 | mutex_unlock(&mb0_transfer.ac_wake_lock); | 1478 | mutex_unlock(&mb0_transfer.ac_wake_lock); |
2400 | return ret; | ||
2401 | } | 1479 | } |
2402 | 1480 | ||
2403 | /** | 1481 | /** |
@@ -2409,16 +1487,16 @@ void prcmu_ac_sleep_req() | |||
2409 | 1487 | ||
2410 | mutex_lock(&mb0_transfer.ac_wake_lock); | 1488 | mutex_lock(&mb0_transfer.ac_wake_lock); |
2411 | 1489 | ||
2412 | val = readl(PRCM_HOSTACCESS_REQ); | 1490 | val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); |
2413 | if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) | 1491 | if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) |
2414 | goto unlock_and_return; | 1492 | goto unlock_and_return; |
2415 | 1493 | ||
2416 | writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), | 1494 | writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), |
2417 | PRCM_HOSTACCESS_REQ); | 1495 | (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); |
2418 | 1496 | ||
2419 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, | 1497 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, |
2420 | msecs_to_jiffies(5000))) { | 1498 | msecs_to_jiffies(20000))) { |
2421 | pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n", | 1499 | pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", |
2422 | __func__); | 1500 | __func__); |
2423 | } | 1501 | } |
2424 | 1502 | ||
@@ -2428,46 +1506,35 @@ unlock_and_return: | |||
2428 | mutex_unlock(&mb0_transfer.ac_wake_lock); | 1506 | mutex_unlock(&mb0_transfer.ac_wake_lock); |
2429 | } | 1507 | } |
2430 | 1508 | ||
2431 | bool db8500_prcmu_is_ac_wake_requested(void) | 1509 | bool prcmu_is_ac_wake_requested(void) |
2432 | { | 1510 | { |
2433 | return (atomic_read(&ac_wake_req_state) != 0); | 1511 | return (atomic_read(&ac_wake_req_state) != 0); |
2434 | } | 1512 | } |
2435 | 1513 | ||
2436 | /** | 1514 | /** |
2437 | * db8500_prcmu_system_reset - System reset | 1515 | * prcmu_system_reset - System reset |
2438 | * | 1516 | * |
2439 | * Saves the reset reason code and then sets the APE_SOFTRST register which | 1517 | * Saves the reset reason code and then sets the APE_SOFRST register which |
2440 | * fires interrupt to fw | 1518 | * fires interrupt to fw |
2441 | */ | 1519 | */ |
2442 | void db8500_prcmu_system_reset(u16 reset_code) | 1520 | void prcmu_system_reset(u16 reset_code) |
2443 | { | 1521 | { |
2444 | writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); | 1522 | writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); |
2445 | writel(1, PRCM_APE_SOFTRST); | 1523 | writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST)); |
2446 | } | 1524 | } |
2447 | 1525 | ||
2448 | /** | 1526 | /** |
2449 | * db8500_prcmu_get_reset_code - Retrieve SW reset reason code | 1527 | * prcmu_reset_modem - ask the PRCMU to reset modem |
2450 | * | ||
2451 | * Retrieves the reset reason code stored by prcmu_system_reset() before | ||
2452 | * last restart. | ||
2453 | */ | 1528 | */ |
2454 | u16 db8500_prcmu_get_reset_code(void) | 1529 | void prcmu_modem_reset(void) |
2455 | { | ||
2456 | return readw(tcdm_base + PRCM_SW_RST_REASON); | ||
2457 | } | ||
2458 | |||
2459 | /** | ||
2460 | * db8500_prcmu_reset_modem - ask the PRCMU to reset modem | ||
2461 | */ | ||
2462 | void db8500_prcmu_modem_reset(void) | ||
2463 | { | 1530 | { |
2464 | mutex_lock(&mb1_transfer.lock); | 1531 | mutex_lock(&mb1_transfer.lock); |
2465 | 1532 | ||
2466 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1533 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
2467 | cpu_relax(); | 1534 | cpu_relax(); |
2468 | 1535 | ||
2469 | writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1536 | writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
2470 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | 1537 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2471 | wait_for_completion(&mb1_transfer.work); | 1538 | wait_for_completion(&mb1_transfer.work); |
2472 | 1539 | ||
2473 | /* | 1540 | /* |
@@ -2484,11 +1551,11 @@ static void ack_dbb_wakeup(void) | |||
2484 | 1551 | ||
2485 | spin_lock_irqsave(&mb0_transfer.lock, flags); | 1552 | spin_lock_irqsave(&mb0_transfer.lock, flags); |
2486 | 1553 | ||
2487 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 1554 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
2488 | cpu_relax(); | 1555 | cpu_relax(); |
2489 | 1556 | ||
2490 | writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 1557 | writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
2491 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); | 1558 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); |
2492 | 1559 | ||
2493 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 1560 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
2494 | } | 1561 | } |
@@ -2533,7 +1600,7 @@ static bool read_mailbox_0(void) | |||
2533 | r = false; | 1600 | r = false; |
2534 | break; | 1601 | break; |
2535 | } | 1602 | } |
2536 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR); | 1603 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2537 | return r; | 1604 | return r; |
2538 | } | 1605 | } |
2539 | 1606 | ||
@@ -2546,7 +1613,7 @@ static bool read_mailbox_1(void) | |||
2546 | PRCM_ACK_MB1_CURRENT_APE_OPP); | 1613 | PRCM_ACK_MB1_CURRENT_APE_OPP); |
2547 | mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + | 1614 | mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + |
2548 | PRCM_ACK_MB1_APE_VOLTAGE_STATUS); | 1615 | PRCM_ACK_MB1_APE_VOLTAGE_STATUS); |
2549 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR); | 1616 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2550 | complete(&mb1_transfer.work); | 1617 | complete(&mb1_transfer.work); |
2551 | return false; | 1618 | return false; |
2552 | } | 1619 | } |
@@ -2554,14 +1621,14 @@ static bool read_mailbox_1(void) | |||
2554 | static bool read_mailbox_2(void) | 1621 | static bool read_mailbox_2(void) |
2555 | { | 1622 | { |
2556 | mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); | 1623 | mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); |
2557 | writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR); | 1624 | writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2558 | complete(&mb2_transfer.work); | 1625 | complete(&mb2_transfer.work); |
2559 | return false; | 1626 | return false; |
2560 | } | 1627 | } |
2561 | 1628 | ||
2562 | static bool read_mailbox_3(void) | 1629 | static bool read_mailbox_3(void) |
2563 | { | 1630 | { |
2564 | writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR); | 1631 | writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2565 | return false; | 1632 | return false; |
2566 | } | 1633 | } |
2567 | 1634 | ||
@@ -2576,11 +1643,6 @@ static bool read_mailbox_4(void) | |||
2576 | case MB4H_HOTDOG: | 1643 | case MB4H_HOTDOG: |
2577 | case MB4H_HOTMON: | 1644 | case MB4H_HOTMON: |
2578 | case MB4H_HOT_PERIOD: | 1645 | case MB4H_HOT_PERIOD: |
2579 | case MB4H_A9WDOG_CONF: | ||
2580 | case MB4H_A9WDOG_EN: | ||
2581 | case MB4H_A9WDOG_DIS: | ||
2582 | case MB4H_A9WDOG_LOAD: | ||
2583 | case MB4H_A9WDOG_KICK: | ||
2584 | break; | 1646 | break; |
2585 | default: | 1647 | default: |
2586 | print_unknown_header_warning(4, header); | 1648 | print_unknown_header_warning(4, header); |
@@ -2588,7 +1650,7 @@ static bool read_mailbox_4(void) | |||
2588 | break; | 1650 | break; |
2589 | } | 1651 | } |
2590 | 1652 | ||
2591 | writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR); | 1653 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2592 | 1654 | ||
2593 | if (do_complete) | 1655 | if (do_complete) |
2594 | complete(&mb4_transfer.work); | 1656 | complete(&mb4_transfer.work); |
@@ -2600,20 +1662,20 @@ static bool read_mailbox_5(void) | |||
2600 | { | 1662 | { |
2601 | mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); | 1663 | mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); |
2602 | mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); | 1664 | mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); |
2603 | writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR); | 1665 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2604 | complete(&mb5_transfer.work); | 1666 | complete(&mb5_transfer.work); |
2605 | return false; | 1667 | return false; |
2606 | } | 1668 | } |
2607 | 1669 | ||
2608 | static bool read_mailbox_6(void) | 1670 | static bool read_mailbox_6(void) |
2609 | { | 1671 | { |
2610 | writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR); | 1672 | writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2611 | return false; | 1673 | return false; |
2612 | } | 1674 | } |
2613 | 1675 | ||
2614 | static bool read_mailbox_7(void) | 1676 | static bool read_mailbox_7(void) |
2615 | { | 1677 | { |
2616 | writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR); | 1678 | writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
2617 | return false; | 1679 | return false; |
2618 | } | 1680 | } |
2619 | 1681 | ||
@@ -2634,7 +1696,7 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) | |||
2634 | u8 n; | 1696 | u8 n; |
2635 | irqreturn_t r; | 1697 | irqreturn_t r; |
2636 | 1698 | ||
2637 | bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); | 1699 | bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); |
2638 | if (unlikely(!bits)) | 1700 | if (unlikely(!bits)) |
2639 | return IRQ_NONE; | 1701 | return IRQ_NONE; |
2640 | 1702 | ||
@@ -2672,7 +1734,7 @@ static void prcmu_irq_mask(struct irq_data *d) | |||
2672 | 1734 | ||
2673 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); | 1735 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); |
2674 | 1736 | ||
2675 | mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq]; | 1737 | mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; |
2676 | 1738 | ||
2677 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); | 1739 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); |
2678 | 1740 | ||
@@ -2686,7 +1748,7 @@ static void prcmu_irq_unmask(struct irq_data *d) | |||
2686 | 1748 | ||
2687 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); | 1749 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); |
2688 | 1750 | ||
2689 | mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq]; | 1751 | mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; |
2690 | 1752 | ||
2691 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); | 1753 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); |
2692 | 1754 | ||
@@ -2706,86 +1768,29 @@ static struct irq_chip prcmu_irq_chip = { | |||
2706 | .irq_unmask = prcmu_irq_unmask, | 1768 | .irq_unmask = prcmu_irq_unmask, |
2707 | }; | 1769 | }; |
2708 | 1770 | ||
2709 | static char *fw_project_name(u8 project) | 1771 | void __init prcmu_early_init(void) |
2710 | { | ||
2711 | switch (project) { | ||
2712 | case PRCMU_FW_PROJECT_U8500: | ||
2713 | return "U8500"; | ||
2714 | case PRCMU_FW_PROJECT_U8500_C2: | ||
2715 | return "U8500 C2"; | ||
2716 | case PRCMU_FW_PROJECT_U9500: | ||
2717 | return "U9500"; | ||
2718 | case PRCMU_FW_PROJECT_U9500_C2: | ||
2719 | return "U9500 C2"; | ||
2720 | case PRCMU_FW_PROJECT_U8520: | ||
2721 | return "U8520"; | ||
2722 | case PRCMU_FW_PROJECT_U8420: | ||
2723 | return "U8420"; | ||
2724 | default: | ||
2725 | return "Unknown"; | ||
2726 | } | ||
2727 | } | ||
2728 | |||
2729 | static int db8500_irq_map(struct irq_domain *d, unsigned int virq, | ||
2730 | irq_hw_number_t hwirq) | ||
2731 | { | ||
2732 | irq_set_chip_and_handler(virq, &prcmu_irq_chip, | ||
2733 | handle_simple_irq); | ||
2734 | set_irq_flags(virq, IRQF_VALID); | ||
2735 | |||
2736 | return 0; | ||
2737 | } | ||
2738 | |||
2739 | static struct irq_domain_ops db8500_irq_ops = { | ||
2740 | .map = db8500_irq_map, | ||
2741 | .xlate = irq_domain_xlate_twocell, | ||
2742 | }; | ||
2743 | |||
2744 | static int db8500_irq_init(struct device_node *np) | ||
2745 | { | 1772 | { |
2746 | int irq_base = -1; | 1773 | unsigned int i; |
2747 | |||
2748 | /* In the device tree case, just take some IRQs */ | ||
2749 | if (!np) | ||
2750 | irq_base = IRQ_PRCMU_BASE; | ||
2751 | |||
2752 | db8500_irq_domain = irq_domain_add_simple( | ||
2753 | np, NUM_PRCMU_WAKEUPS, irq_base, | ||
2754 | &db8500_irq_ops, NULL); | ||
2755 | |||
2756 | if (!db8500_irq_domain) { | ||
2757 | pr_err("Failed to create irqdomain\n"); | ||
2758 | return -ENOSYS; | ||
2759 | } | ||
2760 | |||
2761 | return 0; | ||
2762 | } | ||
2763 | 1774 | ||
2764 | void __init db8500_prcmu_early_init(void) | 1775 | if (cpu_is_u8500v1()) { |
2765 | { | 1776 | tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1); |
2766 | if (cpu_is_u8500v2() || cpu_is_u9540()) { | 1777 | } else if (cpu_is_u8500v2()) { |
2767 | void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); | 1778 | void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); |
2768 | 1779 | ||
2769 | if (tcpm_base != NULL) { | 1780 | if (tcpm_base != NULL) { |
2770 | u32 version; | 1781 | int version; |
2771 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); | 1782 | version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); |
2772 | fw_info.version.project = version & 0xFF; | 1783 | prcmu_version.project_number = version & 0xFF; |
2773 | fw_info.version.api_version = (version >> 8) & 0xFF; | 1784 | prcmu_version.api_version = (version >> 8) & 0xFF; |
2774 | fw_info.version.func_version = (version >> 16) & 0xFF; | 1785 | prcmu_version.func_version = (version >> 16) & 0xFF; |
2775 | fw_info.version.errata = (version >> 24) & 0xFF; | 1786 | prcmu_version.errata = (version >> 24) & 0xFF; |
2776 | fw_info.valid = true; | 1787 | pr_info("PRCMU firmware version %d.%d.%d\n", |
2777 | pr_info("PRCMU firmware: %s, version %d.%d.%d\n", | ||
2778 | fw_project_name(fw_info.version.project), | ||
2779 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, | 1788 | (version >> 8) & 0xFF, (version >> 16) & 0xFF, |
2780 | (version >> 24) & 0xFF); | 1789 | (version >> 24) & 0xFF); |
2781 | iounmap(tcpm_base); | 1790 | iounmap(tcpm_base); |
2782 | } | 1791 | } |
2783 | 1792 | ||
2784 | if (cpu_is_u9540()) | 1793 | tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); |
2785 | tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, | ||
2786 | SZ_4K + SZ_8K) + SZ_8K; | ||
2787 | else | ||
2788 | tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); | ||
2789 | } else { | 1794 | } else { |
2790 | pr_err("prcmu: Unsupported chip version\n"); | 1795 | pr_err("prcmu: Unsupported chip version\n"); |
2791 | BUG(); | 1796 | BUG(); |
@@ -2797,7 +1802,6 @@ void __init db8500_prcmu_early_init(void) | |||
2797 | init_completion(&mb0_transfer.ac_wake_work); | 1802 | init_completion(&mb0_transfer.ac_wake_work); |
2798 | mutex_init(&mb1_transfer.lock); | 1803 | mutex_init(&mb1_transfer.lock); |
2799 | init_completion(&mb1_transfer.work); | 1804 | init_completion(&mb1_transfer.work); |
2800 | mb1_transfer.ape_opp = APE_NO_CHANGE; | ||
2801 | mutex_init(&mb2_transfer.lock); | 1805 | mutex_init(&mb2_transfer.lock); |
2802 | init_completion(&mb2_transfer.work); | 1806 | init_completion(&mb2_transfer.work); |
2803 | spin_lock_init(&mb2_transfer.auto_pm_lock); | 1807 | spin_lock_init(&mb2_transfer.auto_pm_lock); |
@@ -2810,16 +1814,16 @@ void __init db8500_prcmu_early_init(void) | |||
2810 | init_completion(&mb5_transfer.work); | 1814 | init_completion(&mb5_transfer.work); |
2811 | 1815 | ||
2812 | INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); | 1816 | INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); |
2813 | } | ||
2814 | 1817 | ||
2815 | static void __init init_prcm_registers(void) | 1818 | /* Initalize irqs. */ |
2816 | { | 1819 | for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) { |
2817 | u32 val; | 1820 | unsigned int irq; |
2818 | 1821 | ||
2819 | val = readl(PRCM_A9PL_FORCE_CLKEN); | 1822 | irq = IRQ_PRCMU_BASE + i; |
2820 | val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN | | 1823 | irq_set_chip_and_handler(irq, &prcmu_irq_chip, |
2821 | PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN); | 1824 | handle_simple_irq); |
2822 | writel(val, (PRCM_A9PL_FORCE_CLKEN)); | 1825 | set_irq_flags(irq, IRQF_VALID); |
1826 | } | ||
2823 | } | 1827 | } |
2824 | 1828 | ||
2825 | /* | 1829 | /* |
@@ -2831,7 +1835,6 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { | |||
2831 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"), | 1835 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"), |
2832 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"), | 1836 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"), |
2833 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"), | 1837 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"), |
2834 | REGULATOR_SUPPLY("v-i2c", "nmk-i2c.4"), | ||
2835 | /* "v-mmc" changed to "vcore" in the mainline kernel */ | 1838 | /* "v-mmc" changed to "vcore" in the mainline kernel */ |
2836 | REGULATOR_SUPPLY("vcore", "sdi0"), | 1839 | REGULATOR_SUPPLY("vcore", "sdi0"), |
2837 | REGULATOR_SUPPLY("vcore", "sdi1"), | 1840 | REGULATOR_SUPPLY("vcore", "sdi1"), |
@@ -2845,55 +1848,20 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { | |||
2845 | REGULATOR_SUPPLY("vcore", "uart1"), | 1848 | REGULATOR_SUPPLY("vcore", "uart1"), |
2846 | REGULATOR_SUPPLY("vcore", "uart2"), | 1849 | REGULATOR_SUPPLY("vcore", "uart2"), |
2847 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), | 1850 | REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), |
2848 | REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"), | ||
2849 | REGULATOR_SUPPLY("vddvario", "smsc911x.0"), | ||
2850 | }; | 1851 | }; |
2851 | 1852 | ||
2852 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { | 1853 | static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { |
1854 | /* CG2900 and CW1200 power to off-chip peripherals */ | ||
1855 | REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), | ||
1856 | REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"), | ||
2853 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), | 1857 | REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), |
2854 | /* AV8100 regulator */ | 1858 | /* AV8100 regulator */ |
2855 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), | 1859 | REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), |
2856 | }; | 1860 | }; |
2857 | 1861 | ||
2858 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { | 1862 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { |
2859 | REGULATOR_SUPPLY("vsupply", "b2r2_bus"), | 1863 | REGULATOR_SUPPLY("vsupply", "b2r2.0"), |
2860 | REGULATOR_SUPPLY("vsupply", "mcde"), | 1864 | REGULATOR_SUPPLY("vsupply", "mcde.0"), |
2861 | }; | ||
2862 | |||
2863 | /* SVA MMDSP regulator switch */ | ||
2864 | static struct regulator_consumer_supply db8500_svammdsp_consumers[] = { | ||
2865 | REGULATOR_SUPPLY("sva-mmdsp", "cm_control"), | ||
2866 | }; | ||
2867 | |||
2868 | /* SVA pipe regulator switch */ | ||
2869 | static struct regulator_consumer_supply db8500_svapipe_consumers[] = { | ||
2870 | REGULATOR_SUPPLY("sva-pipe", "cm_control"), | ||
2871 | }; | ||
2872 | |||
2873 | /* SIA MMDSP regulator switch */ | ||
2874 | static struct regulator_consumer_supply db8500_siammdsp_consumers[] = { | ||
2875 | REGULATOR_SUPPLY("sia-mmdsp", "cm_control"), | ||
2876 | }; | ||
2877 | |||
2878 | /* SIA pipe regulator switch */ | ||
2879 | static struct regulator_consumer_supply db8500_siapipe_consumers[] = { | ||
2880 | REGULATOR_SUPPLY("sia-pipe", "cm_control"), | ||
2881 | }; | ||
2882 | |||
2883 | static struct regulator_consumer_supply db8500_sga_consumers[] = { | ||
2884 | REGULATOR_SUPPLY("v-mali", NULL), | ||
2885 | }; | ||
2886 | |||
2887 | /* ESRAM1 and 2 regulator switch */ | ||
2888 | static struct regulator_consumer_supply db8500_esram12_consumers[] = { | ||
2889 | REGULATOR_SUPPLY("esram12", "cm_control"), | ||
2890 | }; | ||
2891 | |||
2892 | /* ESRAM3 and 4 regulator switch */ | ||
2893 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { | ||
2894 | REGULATOR_SUPPLY("v-esram34", "mcde"), | ||
2895 | REGULATOR_SUPPLY("esram34", "cm_control"), | ||
2896 | REGULATOR_SUPPLY("lcla_esram", "dma40.0"), | ||
2897 | }; | 1865 | }; |
2898 | 1866 | ||
2899 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | 1867 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { |
@@ -2901,7 +1869,6 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2901 | .constraints = { | 1869 | .constraints = { |
2902 | .name = "db8500-vape", | 1870 | .name = "db8500-vape", |
2903 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1871 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
2904 | .always_on = true, | ||
2905 | }, | 1872 | }, |
2906 | .consumer_supplies = db8500_vape_consumers, | 1873 | .consumer_supplies = db8500_vape_consumers, |
2907 | .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers), | 1874 | .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers), |
@@ -2951,13 +1918,11 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2951 | }, | 1918 | }, |
2952 | }, | 1919 | }, |
2953 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { | 1920 | [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { |
2954 | /* dependency to u8500-vape is handled outside regulator framework */ | 1921 | .supply_regulator = "db8500-vape", |
2955 | .constraints = { | 1922 | .constraints = { |
2956 | .name = "db8500-sva-mmdsp", | 1923 | .name = "db8500-sva-mmdsp", |
2957 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1924 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
2958 | }, | 1925 | }, |
2959 | .consumer_supplies = db8500_svammdsp_consumers, | ||
2960 | .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers), | ||
2961 | }, | 1926 | }, |
2962 | [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { | 1927 | [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { |
2963 | .constraints = { | 1928 | .constraints = { |
@@ -2967,22 +1932,18 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2967 | }, | 1932 | }, |
2968 | }, | 1933 | }, |
2969 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { | 1934 | [DB8500_REGULATOR_SWITCH_SVAPIPE] = { |
2970 | /* dependency to u8500-vape is handled outside regulator framework */ | 1935 | .supply_regulator = "db8500-vape", |
2971 | .constraints = { | 1936 | .constraints = { |
2972 | .name = "db8500-sva-pipe", | 1937 | .name = "db8500-sva-pipe", |
2973 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1938 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
2974 | }, | 1939 | }, |
2975 | .consumer_supplies = db8500_svapipe_consumers, | ||
2976 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), | ||
2977 | }, | 1940 | }, |
2978 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { | 1941 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { |
2979 | /* dependency to u8500-vape is handled outside regulator framework */ | 1942 | .supply_regulator = "db8500-vape", |
2980 | .constraints = { | 1943 | .constraints = { |
2981 | .name = "db8500-sia-mmdsp", | 1944 | .name = "db8500-sia-mmdsp", |
2982 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1945 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
2983 | }, | 1946 | }, |
2984 | .consumer_supplies = db8500_siammdsp_consumers, | ||
2985 | .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers), | ||
2986 | }, | 1947 | }, |
2987 | [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { | 1948 | [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { |
2988 | .constraints = { | 1949 | .constraints = { |
@@ -2991,13 +1952,11 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
2991 | }, | 1952 | }, |
2992 | }, | 1953 | }, |
2993 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { | 1954 | [DB8500_REGULATOR_SWITCH_SIAPIPE] = { |
2994 | /* dependency to u8500-vape is handled outside regulator framework */ | 1955 | .supply_regulator = "db8500-vape", |
2995 | .constraints = { | 1956 | .constraints = { |
2996 | .name = "db8500-sia-pipe", | 1957 | .name = "db8500-sia-pipe", |
2997 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1958 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
2998 | }, | 1959 | }, |
2999 | .consumer_supplies = db8500_siapipe_consumers, | ||
3000 | .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers), | ||
3001 | }, | 1960 | }, |
3002 | [DB8500_REGULATOR_SWITCH_SGA] = { | 1961 | [DB8500_REGULATOR_SWITCH_SGA] = { |
3003 | .supply_regulator = "db8500-vape", | 1962 | .supply_regulator = "db8500-vape", |
@@ -3005,9 +1964,6 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
3005 | .name = "db8500-sga", | 1964 | .name = "db8500-sga", |
3006 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1965 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
3007 | }, | 1966 | }, |
3008 | .consumer_supplies = db8500_sga_consumers, | ||
3009 | .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers), | ||
3010 | |||
3011 | }, | 1967 | }, |
3012 | [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { | 1968 | [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { |
3013 | .supply_regulator = "db8500-vape", | 1969 | .supply_regulator = "db8500-vape", |
@@ -3019,16 +1975,11 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
3019 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), | 1975 | .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), |
3020 | }, | 1976 | }, |
3021 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { | 1977 | [DB8500_REGULATOR_SWITCH_ESRAM12] = { |
3022 | /* | 1978 | .supply_regulator = "db8500-vape", |
3023 | * esram12 is set in retention and supplied by Vsafe when Vape is off, | ||
3024 | * no need to hold Vape | ||
3025 | */ | ||
3026 | .constraints = { | 1979 | .constraints = { |
3027 | .name = "db8500-esram12", | 1980 | .name = "db8500-esram12", |
3028 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1981 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
3029 | }, | 1982 | }, |
3030 | .consumer_supplies = db8500_esram12_consumers, | ||
3031 | .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers), | ||
3032 | }, | 1983 | }, |
3033 | [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { | 1984 | [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { |
3034 | .constraints = { | 1985 | .constraints = { |
@@ -3037,16 +1988,11 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
3037 | }, | 1988 | }, |
3038 | }, | 1989 | }, |
3039 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { | 1990 | [DB8500_REGULATOR_SWITCH_ESRAM34] = { |
3040 | /* | 1991 | .supply_regulator = "db8500-vape", |
3041 | * esram34 is set in retention and supplied by Vsafe when Vape is off, | ||
3042 | * no need to hold Vape | ||
3043 | */ | ||
3044 | .constraints = { | 1992 | .constraints = { |
3045 | .name = "db8500-esram34", | 1993 | .name = "db8500-esram34", |
3046 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 1994 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
3047 | }, | 1995 | }, |
3048 | .consumer_supplies = db8500_esram34_consumers, | ||
3049 | .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers), | ||
3050 | }, | 1996 | }, |
3051 | [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { | 1997 | [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { |
3052 | .constraints = { | 1998 | .constraints = { |
@@ -3056,122 +2002,68 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
3056 | }, | 2002 | }, |
3057 | }; | 2003 | }; |
3058 | 2004 | ||
3059 | static struct resource ab8500_resources[] = { | ||
3060 | [0] = { | ||
3061 | .start = IRQ_DB8500_AB8500, | ||
3062 | .end = IRQ_DB8500_AB8500, | ||
3063 | .flags = IORESOURCE_IRQ | ||
3064 | } | ||
3065 | }; | ||
3066 | |||
3067 | static struct mfd_cell db8500_prcmu_devs[] = { | 2005 | static struct mfd_cell db8500_prcmu_devs[] = { |
3068 | { | 2006 | { |
3069 | .name = "db8500-prcmu-regulators", | 2007 | .name = "db8500-prcmu-regulators", |
3070 | .of_compatible = "stericsson,db8500-prcmu-regulator", | ||
3071 | .platform_data = &db8500_regulators, | 2008 | .platform_data = &db8500_regulators, |
3072 | .pdata_size = sizeof(db8500_regulators), | 2009 | .pdata_size = sizeof(db8500_regulators), |
3073 | }, | 2010 | }, |
3074 | { | 2011 | { |
3075 | .name = "cpufreq-u8500", | 2012 | .name = "cpufreq-u8500", |
3076 | .of_compatible = "stericsson,cpufreq-u8500", | ||
3077 | .platform_data = &db8500_cpufreq_table, | ||
3078 | .pdata_size = sizeof(db8500_cpufreq_table), | ||
3079 | }, | ||
3080 | { | ||
3081 | .name = "ab8500-core", | ||
3082 | .of_compatible = "stericsson,ab8500", | ||
3083 | .num_resources = ARRAY_SIZE(ab8500_resources), | ||
3084 | .resources = ab8500_resources, | ||
3085 | .id = AB8500_VERSION_AB8500, | ||
3086 | }, | 2013 | }, |
3087 | }; | 2014 | }; |
3088 | 2015 | ||
3089 | static void db8500_prcmu_update_cpufreq(void) | ||
3090 | { | ||
3091 | if (prcmu_has_arm_maxopp()) { | ||
3092 | db8500_cpufreq_table[3].frequency = 1000000; | ||
3093 | db8500_cpufreq_table[3].index = ARM_MAX_OPP; | ||
3094 | } | ||
3095 | } | ||
3096 | |||
3097 | /** | 2016 | /** |
3098 | * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic | 2017 | * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic |
3099 | * | 2018 | * |
3100 | */ | 2019 | */ |
3101 | static int db8500_prcmu_probe(struct platform_device *pdev) | 2020 | static int __init db8500_prcmu_probe(struct platform_device *pdev) |
3102 | { | 2021 | { |
3103 | struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data; | 2022 | int err = 0; |
3104 | struct device_node *np = pdev->dev.of_node; | ||
3105 | int irq = 0, err = 0, i; | ||
3106 | 2023 | ||
3107 | if (ux500_is_svp()) | 2024 | if (ux500_is_svp()) |
3108 | return -ENODEV; | 2025 | return -ENODEV; |
3109 | 2026 | ||
3110 | init_prcm_registers(); | ||
3111 | |||
3112 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 2027 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
3113 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); | 2028 | writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); |
3114 | |||
3115 | if (np) | ||
3116 | irq = platform_get_irq(pdev, 0); | ||
3117 | 2029 | ||
3118 | if (!np || irq <= 0) | 2030 | err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, |
3119 | irq = IRQ_DB8500_PRCMU1; | 2031 | prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); |
3120 | |||
3121 | err = request_threaded_irq(irq, prcmu_irq_handler, | ||
3122 | prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); | ||
3123 | if (err < 0) { | 2032 | if (err < 0) { |
3124 | pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n"); | 2033 | pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n"); |
3125 | err = -EBUSY; | 2034 | err = -EBUSY; |
3126 | goto no_irq_return; | 2035 | goto no_irq_return; |
3127 | } | 2036 | } |
3128 | 2037 | ||
3129 | db8500_irq_init(np); | ||
3130 | |||
3131 | for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { | ||
3132 | if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { | ||
3133 | db8500_prcmu_devs[i].platform_data = ab8500_platdata; | ||
3134 | db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data); | ||
3135 | } | ||
3136 | } | ||
3137 | |||
3138 | if (cpu_is_u8500v20_or_later()) | 2038 | if (cpu_is_u8500v20_or_later()) |
3139 | prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); | 2039 | prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); |
3140 | 2040 | ||
3141 | db8500_prcmu_update_cpufreq(); | ||
3142 | |||
3143 | err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, | 2041 | err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, |
3144 | ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); | 2042 | ARRAY_SIZE(db8500_prcmu_devs), NULL, |
3145 | if (err) { | 2043 | 0); |
3146 | pr_err("prcmu: Failed to add subdevices\n"); | ||
3147 | return err; | ||
3148 | } | ||
3149 | 2044 | ||
3150 | pr_info("DB8500 PRCMU initialized\n"); | 2045 | if (err) |
2046 | pr_err("prcmu: Failed to add subdevices\n"); | ||
2047 | else | ||
2048 | pr_info("DB8500 PRCMU initialized\n"); | ||
3151 | 2049 | ||
3152 | no_irq_return: | 2050 | no_irq_return: |
3153 | return err; | 2051 | return err; |
3154 | } | 2052 | } |
3155 | static const struct of_device_id db8500_prcmu_match[] = { | ||
3156 | { .compatible = "stericsson,db8500-prcmu"}, | ||
3157 | { }, | ||
3158 | }; | ||
3159 | 2053 | ||
3160 | static struct platform_driver db8500_prcmu_driver = { | 2054 | static struct platform_driver db8500_prcmu_driver = { |
3161 | .driver = { | 2055 | .driver = { |
3162 | .name = "db8500-prcmu", | 2056 | .name = "db8500-prcmu", |
3163 | .owner = THIS_MODULE, | 2057 | .owner = THIS_MODULE, |
3164 | .of_match_table = db8500_prcmu_match, | ||
3165 | }, | 2058 | }, |
3166 | .probe = db8500_prcmu_probe, | ||
3167 | }; | 2059 | }; |
3168 | 2060 | ||
3169 | static int __init db8500_prcmu_init(void) | 2061 | static int __init db8500_prcmu_init(void) |
3170 | { | 2062 | { |
3171 | return platform_driver_register(&db8500_prcmu_driver); | 2063 | return platform_driver_probe(&db8500_prcmu_driver, db8500_prcmu_probe); |
3172 | } | 2064 | } |
3173 | 2065 | ||
3174 | core_initcall(db8500_prcmu_init); | 2066 | arch_initcall(db8500_prcmu_init); |
3175 | 2067 | ||
3176 | MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>"); | 2068 | MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>"); |
3177 | MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); | 2069 | MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); |