diff options
Diffstat (limited to 'drivers/ssb/driver_chipcommon_pmu.c')
-rw-r--r-- | drivers/ssb/driver_chipcommon_pmu.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 4aaddeec55a2..64abd11f6fbb 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, | |||
28 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); | 28 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); |
29 | } | 29 | } |
30 | 30 | ||
31 | static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc, | ||
32 | u32 offset, u32 mask, u32 set) | ||
33 | { | ||
34 | u32 value; | ||
35 | |||
36 | chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); | ||
37 | chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset); | ||
38 | chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); | ||
39 | value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); | ||
40 | value &= mask; | ||
41 | value |= set; | ||
42 | chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value); | ||
43 | chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); | ||
44 | } | ||
45 | |||
31 | struct pmu0_plltab_entry { | 46 | struct pmu0_plltab_entry { |
32 | u16 freq; /* Crystal frequency in kHz.*/ | 47 | u16 freq; /* Crystal frequency in kHz.*/ |
33 | u8 xf; /* Crystal frequency value for PMU control */ | 48 | u8 xf; /* Crystal frequency value for PMU control */ |
@@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) | |||
506 | ssb_pmu_pll_init(cc); | 521 | ssb_pmu_pll_init(cc); |
507 | ssb_pmu_resources_init(cc); | 522 | ssb_pmu_resources_init(cc); |
508 | } | 523 | } |
524 | |||
525 | void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, | ||
526 | enum ssb_pmu_ldo_volt_id id, u32 voltage) | ||
527 | { | ||
528 | struct ssb_bus *bus = cc->dev->bus; | ||
529 | u32 addr, shift, mask; | ||
530 | |||
531 | switch (bus->chip_id) { | ||
532 | case 0x4328: | ||
533 | case 0x5354: | ||
534 | switch (id) { | ||
535 | case LDO_VOLT1: | ||
536 | addr = 2; | ||
537 | shift = 25; | ||
538 | mask = 0xF; | ||
539 | break; | ||
540 | case LDO_VOLT2: | ||
541 | addr = 3; | ||
542 | shift = 1; | ||
543 | mask = 0xF; | ||
544 | break; | ||
545 | case LDO_VOLT3: | ||
546 | addr = 3; | ||
547 | shift = 9; | ||
548 | mask = 0xF; | ||
549 | break; | ||
550 | case LDO_PAREF: | ||
551 | addr = 3; | ||
552 | shift = 17; | ||
553 | mask = 0x3F; | ||
554 | break; | ||
555 | default: | ||
556 | SSB_WARN_ON(1); | ||
557 | return; | ||
558 | } | ||
559 | break; | ||
560 | case 0x4312: | ||
561 | if (SSB_WARN_ON(id != LDO_PAREF)) | ||
562 | return; | ||
563 | addr = 0; | ||
564 | shift = 21; | ||
565 | mask = 0x3F; | ||
566 | break; | ||
567 | default: | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift), | ||
572 | (voltage & mask) << shift); | ||
573 | } | ||
574 | |||
575 | void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) | ||
576 | { | ||
577 | struct ssb_bus *bus = cc->dev->bus; | ||
578 | int ldo; | ||
579 | |||
580 | switch (bus->chip_id) { | ||
581 | case 0x4312: | ||
582 | ldo = SSB_PMURES_4312_PA_REF_LDO; | ||
583 | break; | ||
584 | case 0x4328: | ||
585 | ldo = SSB_PMURES_4328_PA_REF_LDO; | ||
586 | break; | ||
587 | case 0x5354: | ||
588 | ldo = SSB_PMURES_5354_PA_REF_LDO; | ||
589 | break; | ||
590 | default: | ||
591 | return; | ||
592 | } | ||
593 | |||
594 | if (on) | ||
595 | chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo); | ||
596 | else | ||
597 | chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo)); | ||
598 | chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read? | ||
599 | } | ||
600 | |||
601 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); | ||
602 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); | ||