diff options
Diffstat (limited to 'drivers/net/wireless/bcmdhd/hndpmu.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/hndpmu.c | 83 |
1 files changed, 74 insertions, 9 deletions
diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c index 92a56db..70d383e 100644 --- a/drivers/net/wireless/bcmdhd/hndpmu.c +++ b/drivers/net/wireless/bcmdhd/hndpmu.c @@ -2,7 +2,7 @@ * Misc utility routines for accessing PMU corerev specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2012, Broadcom Corporation + * Copyright (C) 1999-2014, Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you @@ -22,16 +22,18 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.c 367414 2012-11-08 00:40:54Z $ + * $Id: hndpmu.c 433378 2013-10-31 17:19:39Z $ */ + /* * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs. * However, in the context of this file the baseband ('BB') PLL/FLL is referred to. * * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used. * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012) - * pmu2_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop) + * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports + * fractional frequency generation. pmu2_ does not support fractional frequency generation. */ #include <bcm_cfg.h> @@ -54,6 +56,16 @@ */ #define PMU_NONE(args) +/** contains resource bit positions for a specific chip */ +struct rsc_per_chip_s { + uint8 ht_avail; + uint8 macphy_clkavail; + uint8 ht_start; + uint8 otp_pu; +}; + +typedef struct rsc_per_chip_s rsc_per_chip_t; + /* SDIO Pad drive strength to select value mappings. * The last strength value in each table must be 0 (the tri-state value). @@ -118,23 +130,61 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { /* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */ -/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */ +/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */ static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = { {3, 0x3}, {2, 0x2}, {1, 0x1}, {0, 0x0} }; + +/** + * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel + * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture + * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has + * been written '1'. + */ +#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 + +static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = { + /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */ + {16, 0x7}, + {12, 0x5}, + {8, 0x3}, + {4, 0x1} }; /* note: 43143 does not support tristate */ + +#else + +static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = { + /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */ + {8, 0x7}, + {6, 0x5}, + {4, 0x3}, + {2, 0x1} }; /* note: 43143 does not support tristate */ + +#endif /* BCM_SDIO_VDDIO */ + #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) +/** + * Balance between stable SDIO operation and power consumption is achieved using this function. + * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this + * function should read the VDDIO itself to select the correct table. For now it has been solved + * with the 'BCM_SDIO_VDDIO' preprocessor constant. + * + * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if + * hardware supports this), if no hw support drive strength is not programmed. + */ void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) { chipcregs_t *cc; uint origidx, intr_val = 0; sdiod_drive_str_t *str_tab = NULL; - uint32 str_mask = 0; + uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */ uint32 str_shift = 0; + uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */ + uint32 str_ovr_pmuval = 0; /* position of bit within this register */ if (!(sih->cccaps & CC_CAP_PMU)) { return; @@ -182,10 +232,22 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) str_mask = 0x00001800; str_shift = 11; break; + case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): +#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 + if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) { + str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3; + } +#else + if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) { + str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8; + } +#endif /* BCM_SDIO_VDDIO */ + str_mask = 0x00000007; + str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR; + break; default: PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev)); - break; } @@ -202,16 +264,19 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) if (i > 0 && drivestrength > str_tab[i].strength) i--; - W_REG(osh, &cc->chipcontrol_addr, 1); + W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1); cc_data_temp = R_REG(osh, &cc->chipcontrol_data); cc_data_temp &= ~str_mask; cc_data_temp |= str_tab[i].sel << str_shift; W_REG(osh, &cc->chipcontrol_data, cc_data_temp); - + if (str_ovr_pmuval) { /* enables the selected drive strength */ + W_REG(osh, &cc->chipcontrol_addr, str_ovr_pmuctl); + OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval); + } PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", drivestrength, str_tab[i].strength)); } /* Return to original core */ si_restore_core(sih, origidx, intr_val); -} +} /* si_sdiod_drive_strength_init */ |