323-0004-brcmfmac-access-PMU-registers-using-standalone-PMU-c.patch 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
  2. Date: Tue, 26 Jan 2016 17:57:04 +0100
  3. Subject: [PATCH] brcmfmac: access PMU registers using standalone PMU core if
  4. available
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. On recent Broadcom chipsets PMU is present as separated core and it
  9. can't be accessed using ChipCommon anymore as it fails with e.g.:
  10. [ 18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f
  11. Add a new helper function that will return a proper core that should be
  12. used for accessing PMU registers.
  13. Signed-off-by: Rafał Miłecki <[email protected]>
  14. Signed-off-by: Kalle Valo <[email protected]>
  15. ---
  16. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
  17. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
  18. @@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf
  19. {
  20. struct brcmf_chip *pub;
  21. struct brcmf_core_priv *cc;
  22. + struct brcmf_core *pmu;
  23. u32 base;
  24. u32 val;
  25. int ret = 0;
  26. @@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf
  27. capabilities_ext));
  28. /* get pmu caps & rev */
  29. + pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */
  30. if (pub->cc_caps & CC_CAP_PMU) {
  31. val = chip->ops->read32(chip->ctx,
  32. - CORE_CC_REG(base, pmucapabilities));
  33. + CORE_CC_REG(pmu->base, pmucapabilities));
  34. pub->pmurev = val & PCAP_REV_MASK;
  35. pub->pmucaps = val;
  36. }
  37. @@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipco
  38. return &cc->pub;
  39. }
  40. +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)
  41. +{
  42. + struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);
  43. + struct brcmf_core *pmu;
  44. +
  45. + /* See if there is separated PMU core available */
  46. + if (cc->rev >= 35 &&
  47. + pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
  48. + pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);
  49. + if (pmu)
  50. + return pmu;
  51. + }
  52. +
  53. + /* Fallback to ChipCommon core for older hardware */
  54. + return cc;
  55. +}
  56. +
  57. bool brcmf_chip_iscoreup(struct brcmf_core *pub)
  58. {
  59. struct brcmf_core_priv *core;
  60. @@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
  61. {
  62. u32 base, addr, reg, pmu_cc3_mask = ~0;
  63. struct brcmf_chip_priv *chip;
  64. + struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);
  65. brcmf_dbg(TRACE, "Enter\n");
  66. @@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_
  67. case BRCM_CC_4335_CHIP_ID:
  68. case BRCM_CC_4339_CHIP_ID:
  69. /* read PMU chipcontrol register 3 */
  70. - addr = CORE_CC_REG(base, chipcontrol_addr);
  71. + addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
  72. chip->ops->write32(chip->ctx, addr, 3);
  73. - addr = CORE_CC_REG(base, chipcontrol_data);
  74. + addr = CORE_CC_REG(pmu->base, chipcontrol_data);
  75. reg = chip->ops->read32(chip->ctx, addr);
  76. return (reg & pmu_cc3_mask) != 0;
  77. case BRCM_CC_43430_CHIP_ID:
  78. @@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_
  79. reg = chip->ops->read32(chip->ctx, addr);
  80. return reg != 0;
  81. default:
  82. - addr = CORE_CC_REG(base, pmucapabilities_ext);
  83. + addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
  84. reg = chip->ops->read32(chip->ctx, addr);
  85. if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
  86. return false;
  87. - addr = CORE_CC_REG(base, retention_ctl);
  88. + addr = CORE_CC_REG(pmu->base, retention_ctl);
  89. reg = chip->ops->read32(chip->ctx, addr);
  90. return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
  91. PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
  92. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
  93. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
  94. @@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(voi
  95. void brcmf_chip_detach(struct brcmf_chip *chip);
  96. struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
  97. struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
  98. +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub);
  99. bool brcmf_chip_iscoreup(struct brcmf_core *core);
  100. void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
  101. void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
  102. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
  103. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
  104. @@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcm
  105. const struct sdiod_drive_str *str_tab = NULL;
  106. u32 str_mask;
  107. u32 str_shift;
  108. - u32 base;
  109. u32 i;
  110. u32 drivestrength_sel = 0;
  111. u32 cc_data_temp;
  112. @@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcm
  113. }
  114. if (str_tab != NULL) {
  115. + struct brcmf_core *pmu = brcmf_chip_get_pmu(ci);
  116. +
  117. for (i = 0; str_tab[i].strength != 0; i++) {
  118. if (drivestrength >= str_tab[i].strength) {
  119. drivestrength_sel = str_tab[i].sel;
  120. break;
  121. }
  122. }
  123. - base = brcmf_chip_get_chipcommon(ci)->base;
  124. - addr = CORE_CC_REG(base, chipcontrol_addr);
  125. + addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
  126. brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
  127. cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
  128. cc_data_temp &= ~str_mask;
  129. @@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
  130. goto fail;
  131. /* set PMUControl so a backplane reset does PMU state reload */
  132. - reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base,
  133. - pmucontrol);
  134. + reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
  135. reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
  136. if (err)
  137. goto fail;