From a3df2250cbd23608c175fb402d73d2c19667e89f Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 22 Jul 2014 21:40:41 +0000 Subject: kernel: update bcma and ssb to version master-2014-07-22 This is a backport of bcma and ssb from wireless-tesing/master tag master-2014-07-22. Signed-off-by: Hauke Mehrtens git-svn-id: svn://svn.openwrt.org/openwrt/trunk@41804 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../generic/patches-3.10/020-ssb_update.patch | 199 +++++++++ .../generic/patches-3.10/025-bcma_backport.patch | 486 +++++++++++++++++++- .../generic/patches-3.13/020-ssb_update.patch | 201 +++++++++ .../generic/patches-3.13/025-bcma_backport.patch | 488 ++++++++++++++++++++- .../generic/patches-3.14/020-ssb_update.patch | 235 ++++++++-- .../generic/patches-3.14/025-bcma_backport.patch | 488 ++++++++++++++++++++- 6 files changed, 2054 insertions(+), 43 deletions(-) (limited to 'target/linux/generic') diff --git a/target/linux/generic/patches-3.10/020-ssb_update.patch b/target/linux/generic/patches-3.10/020-ssb_update.patch index 07ac79f92d..48788a69c6 100644 --- a/target/linux/generic/patches-3.10/020-ssb_update.patch +++ b/target/linux/generic/patches-3.10/020-ssb_update.patch @@ -559,6 +559,161 @@ err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); +--- a/drivers/ssb/pci.c ++++ b/drivers/ssb/pci.c +@@ -326,13 +326,13 @@ err_ctlreg: + return err; + } + +-static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, +- u16 mask, u16 shift) ++static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, ++ u16 mask, u16 shift) + { + u16 v; + u8 gain; + +- v = in[SPOFF(SSB_SPROM1_AGAIN)]; ++ v = in[SPOFF(offset)]; + gain = (v & mask) >> shift; + if (gain == 0xFF) + gain = 2; /* If unset use 2dBm */ +@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ss + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + + /* Extract the antenna gain values. */ +- out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_BG, +- SSB_SPROM1_AGAIN_BG_SHIFT); +- out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_A, +- SSB_SPROM1_AGAIN_A_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_BG, ++ SSB_SPROM1_AGAIN_BG_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_A, ++ SSB_SPROM1_AGAIN_A_SHIFT); + if (out->revision >= 2) + sprom_extract_r23(out, in); + } +@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ss + + static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) + { ++ static const u16 pwr_info_offset[] = { ++ SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, ++ SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 ++ }; + u16 il0mac_offset; ++ int i; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != ++ ARRAY_SIZE(out->core_pwr_info)); + + if (out->revision == 4) + il0mac_offset = SSB_SPROM4_IL0MAC; +@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb + } + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN0, ++ SSB_SPROM4_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN1, ++ SSB_SPROM4_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN2, ++ SSB_SPROM4_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN3, ++ SSB_SPROM4_AGAIN3_SHIFT); ++ ++ /* Extract cores power info info */ ++ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { ++ u16 o = pwr_info_offset[i]; ++ ++ SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_MAXP, 0); ++ ++ SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); ++ ++ SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GH_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); ++ ++ SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); ++ } + + sprom_extract_r458(out, in); + +@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_ + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c @@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci @@ -683,6 +838,50 @@ #define SSB_SPROM_BASE1 0x1000 #define SSB_SPROM_BASE31 0x0800 #define SSB_SPROM_REVISION 0x007E +@@ -344,6 +345,43 @@ + #define SSB_SPROM4_TXPID5GH2_SHIFT 0 + #define SSB_SPROM4_TXPID5GH3 0xFF00 + #define SSB_SPROM4_TXPID5GH3_SHIFT 8 ++ ++/* There are 4 blocks with power info sharing the same layout */ ++#define SSB_SPROM4_PWR_INFO_CORE0 0x0080 ++#define SSB_SPROM4_PWR_INFO_CORE1 0x00AE ++#define SSB_SPROM4_PWR_INFO_CORE2 0x00DC ++#define SSB_SPROM4_PWR_INFO_CORE3 0x010A ++ ++#define SSB_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */ ++#define SSB_SPROM4_2G_MAXP 0x00FF ++#define SSB_SPROM4_2G_ITSSI 0xFF00 ++#define SSB_SPROM4_2G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */ ++#define SSB_SPROM4_2G_PA_1 0x04 ++#define SSB_SPROM4_2G_PA_2 0x06 ++#define SSB_SPROM4_2G_PA_3 0x08 ++#define SSB_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */ ++#define SSB_SPROM4_5G_MAXP 0x00FF ++#define SSB_SPROM4_5G_ITSSI 0xFF00 ++#define SSB_SPROM4_5G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */ ++#define SSB_SPROM4_5GH_MAXP 0x00FF ++#define SSB_SPROM4_5GL_MAXP 0xFF00 ++#define SSB_SPROM4_5GL_MAXP_SHIFT 8 ++#define SSB_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */ ++#define SSB_SPROM4_5G_PA_1 0x10 ++#define SSB_SPROM4_5G_PA_2 0x12 ++#define SSB_SPROM4_5G_PA_3 0x14 ++#define SSB_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */ ++#define SSB_SPROM4_5GL_PA_1 0x18 ++#define SSB_SPROM4_5GL_PA_2 0x1A ++#define SSB_SPROM4_5GL_PA_3 0x1C ++#define SSB_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */ ++#define SSB_SPROM4_5GH_PA_1 0x20 ++#define SSB_SPROM4_5GH_PA_2 0x22 ++#define SSB_SPROM4_5GH_PA_3 0x24 ++ ++/* TODO: Make it deprecated */ + #define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */ + #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ + #define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char diff --git a/target/linux/generic/patches-3.10/025-bcma_backport.patch b/target/linux/generic/patches-3.10/025-bcma_backport.patch index c3f7ffb354..a6ae0cb2a2 100644 --- a/target/linux/generic/patches-3.10/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.10/025-bcma_backport.patch @@ -33,6 +33,16 @@ help Driver to provide access to the GPIO pins of the bcma bus. +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver + bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o + bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o + bcma-y += driver_pci.o ++bcma-y += driver_pcie2.o + bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -22,6 +22,8 @@ @@ -274,6 +284,14 @@ bcma_pmu_resources_init(cc); bcma_pmu_workarounds(cc); } +@@ -480,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct + tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; + break; + ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { @@ -479,7 +497,7 @@ chip->label = "bcma_gpio"; chip->owner = THIS_MODULE; -@@ -95,8 +215,17 @@ int bcma_gpio_init(struct bcma_drv_cc *c +@@ -95,8 +215,18 @@ int bcma_gpio_init(struct bcma_drv_cc *c chip->set = bcma_gpio_set_value; chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; @@ -489,6 +507,7 @@ +#endif + switch (cc->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM5357: ++ case BCMA_CHIP_ID_BCM53572: + chip->ngpio = 32; + break; + default: @@ -498,7 +517,7 @@ /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get * a random base number. */ -@@ -105,10 +234,21 @@ int bcma_gpio_init(struct bcma_drv_cc *c +@@ -105,10 +235,21 @@ int bcma_gpio_init(struct bcma_drv_cc *c else chip->base = -1; @@ -659,6 +678,184 @@ return 0; } EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); +--- /dev/null ++++ b/drivers/bcma/driver_pcie2.c +@@ -0,0 +1,175 @@ ++/* ++ * Broadcom specific AMBA ++ * PCIe Gen 2 Core ++ * ++ * Copyright 2014, Broadcom Corporation ++ * Copyright 2014, Rafał Miłecki ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include ++ ++/************************************************** ++ * R/W ops. ++ **************************************************/ ++ ++#if 0 ++static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++} ++#endif ++ ++static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, ++ u32 val) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); ++} ++ ++/************************************************** ++ * Init. ++ **************************************************/ ++ ++static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, ++ bool enable) ++{ ++ u32 val; ++ ++ /* restore back to default */ ++ val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++ val |= PCIE2_CLKC_DLYPERST; ++ val &= ~PCIE2_CLKC_DISSPROMLD; ++ if (enable) { ++ val &= ~PCIE2_CLKC_DLYPERST; ++ val |= PCIE2_CLKC_DISSPROMLD; ++ } ++ pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); ++ /* flush */ ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++} ++ ++static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) ++{ ++ /* LTR0 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); ++ /* LTR1 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); ++ /* LTR2 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); ++} ++ ++static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ u32 devstsctr2; ++ ++ if (core_rev < 2 || core_rev == 10 || core_rev > 13) ++ return; ++ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++ if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { ++ /* force the right LTR values */ ++ bcma_core_pcie2_set_ltr_vals(pcie2); ++ ++ /* TODO: ++ si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */ ++ ++ /* enable the LTR */ ++ devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); ++ ++ /* set the LTR state to be active */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_ACTIVE); ++ usleep_range(1000, 2000); ++ ++ /* set the LTR state to be sleep */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_SLEEP); ++ usleep_range(1000, 2000); ++ } ++} ++ ++static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ bool pciewar160, pciewar162; ++ ++ pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; ++ pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || ++ core_rev == 9 || core_rev == 11; ++ ++ if (!pciewar160 && !pciewar162) ++ return; ++ ++/* TODO */ ++#if 0 ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, ++ PCIE_DISABLE_L1CLK_GATING); ++#if 0 ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIEGEN2_COE_PVT_TL_CTRL_0); ++ pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, ++ ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); ++#endif ++#endif ++} ++ ++static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); ++} ++ ++static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); ++} ++ ++static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; ++ u8 core_rev = pcie2->core->id.rev; ++ u32 alp_khz, pm_value; ++ ++ if (core_rev <= 13) { ++ alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; ++ pm_value = (1000000 * 2) / alp_khz; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_PVT_REG_PM_CLK_PERIOD); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); ++ } ++} ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo; ++ u32 tmp; ++ ++ tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); ++ if ((tmp & 0xe) >> 1 == 2) ++ bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); ++ ++ /* TODO: Do we need pcie_reqsize? */ ++ ++ if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) ++ bcma_core_pcie2_war_delay_perst_enab(pcie2, true); ++ bcma_core_pcie2_hw_ltr_war(pcie2); ++ pciedev_crwlpciegen2(pcie2); ++ pciedev_reg_pm_clk_period(pcie2); ++ pciedev_crwlpciegen2_180(pcie2); ++ pciedev_crwlpciegen2_182(pcie2); ++} --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -188,8 +188,11 @@ static int bcma_host_pci_probe(struct pc @@ -683,7 +880,7 @@ } #ifdef CONFIG_PM_SLEEP -@@ -267,14 +269,16 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc +@@ -267,14 +269,17 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc #endif /* CONFIG_PM_SLEEP */ @@ -698,6 +895,7 @@ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, }; @@ -751,7 +949,15 @@ } static void bcma_release_core_dev(struct device *dev) -@@ -148,6 +156,7 @@ static int bcma_register_cores(struct bc +@@ -115,6 +123,7 @@ static int bcma_register_cores(struct bc + case BCMA_CORE_CHIPCOMMON: + case BCMA_CORE_PCI: + case BCMA_CORE_PCIE: ++ case BCMA_CORE_PCIE2: + case BCMA_CORE_MIPS_74K: + case BCMA_CORE_4706_MAC_GBIT_COMMON: + continue; +@@ -148,6 +157,7 @@ static int bcma_register_cores(struct bc bcma_err(bus, "Could not register dev for core 0x%03X\n", core->id.id); @@ -759,7 +965,7 @@ continue; } core->dev_registered = true; -@@ -218,7 +227,7 @@ int bcma_bus_register(struct bcma_bus *b +@@ -218,7 +228,7 @@ int bcma_bus_register(struct bcma_bus *b err = bcma_bus_scan(bus); if (err) { bcma_err(bus, "Failed to scan: %d\n", err); @@ -768,6 +974,20 @@ } /* Early init CC core */ +@@ -263,6 +273,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_pci_init(&bus->drv_pci[1]); + } + ++ /* Init PCIe Gen 2 core */ ++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0); ++ if (core) { ++ bus->drv_pcie2.core = core; ++ bcma_core_pcie2_init(&bus->drv_pcie2); ++ } ++ + /* Init GBIT MAC COMMON core */ + core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); + if (core) { --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -32,6 +32,18 @@ static const struct bcma_device_id_name @@ -948,7 +1168,31 @@ return 0; } -@@ -208,9 +212,6 @@ static void bcma_sprom_extract_r8(struct +@@ -197,6 +201,23 @@ static int bcma_sprom_valid(const u16 *s + SPEX(_field[7], _offset + 14, _mask, _shift); \ + } while (0) + ++static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) ++{ ++ u16 v; ++ u8 gain; ++ ++ v = in[SPOFF(offset)]; ++ gain = (v & mask) >> shift; ++ if (gain == 0xFF) { ++ gain = 8; /* If unset use 2dBm */ ++ } else { ++ /* Q5.2 Fractional part is stored in 0xC0 */ ++ gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); ++ } ++ ++ return (s8)gain; ++} ++ + static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) + { + u16 v, o; +@@ -208,9 +229,6 @@ static void bcma_sprom_extract_r8(struct BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != ARRAY_SIZE(bus->sprom.core_pwr_info)); @@ -958,7 +1202,38 @@ for (i = 0; i < 3; i++) { v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); -@@ -502,7 +503,7 @@ static bool bcma_sprom_onchip_available( +@@ -380,14 +398,22 @@ static void bcma_sprom_extract_r8(struct + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, + SSB_SPROM8_LEDDC_ON_SHIFT); +@@ -502,12 +528,13 @@ static bool bcma_sprom_onchip_available( case BCMA_CHIP_ID_BCM4331: present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; break; @@ -967,7 +1242,13 @@ case BCMA_CHIP_ID_BCM43224: case BCMA_CHIP_ID_BCM43225: /* for these chips OTP is always available */ -@@ -550,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + present = true; + break; ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: +@@ -550,7 +577,9 @@ int bcma_sprom_get(struct bcma_bus *bus) { u16 offset = BCMA_CC_SPROM; u16 *sprom; @@ -978,7 +1259,7 @@ if (!bus->drv_cc.core) return -EOPNOTSUPP; -@@ -579,32 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) +@@ -579,32 +608,37 @@ int bcma_sprom_get(struct bcma_bus *bus) } } @@ -1031,7 +1312,15 @@ } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h -@@ -72,7 +72,19 @@ struct bcma_host_ops { +@@ -6,6 +6,7 @@ + + #include + #include ++#include + #include + #include + #include /* SPROM sharing */ +@@ -72,7 +73,19 @@ struct bcma_host_ops { /* Core-ID values. */ #define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */ #define BCMA_CORE_4706_CHIPCOMMON 0x500 @@ -1051,15 +1340,17 @@ #define BCMA_CORE_4706_MAC_GBIT 0x52D #define BCMA_CORE_AMEMC 0x52E /* DDR1/2 memory controller core */ #define BCMA_CORE_ALTA 0x534 /* I2S core */ -@@ -144,6 +156,7 @@ struct bcma_host_ops { +@@ -144,6 +157,9 @@ struct bcma_host_ops { /* Chip IDs of PCIe devices */ #define BCMA_CHIP_ID_BCM4313 0x4313 +#define BCMA_CHIP_ID_BCM43142 43142 ++#define BCMA_CHIP_ID_BCM43217 43217 ++#define BCMA_CHIP_ID_BCM43222 43222 #define BCMA_CHIP_ID_BCM43224 43224 #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa -@@ -176,6 +189,11 @@ struct bcma_host_ops { +@@ -176,6 +192,11 @@ struct bcma_host_ops { #define BCMA_PKG_ID_BCM5357 11 #define BCMA_CHIP_ID_BCM53572 53572 #define BCMA_PKG_ID_BCM47188 9 @@ -1071,7 +1362,15 @@ /* Board types (on PCI usually equals to the subsystem dev id) */ /* BCM4313 */ -@@ -400,7 +418,14 @@ static inline void bcma_maskset16(struct +@@ -315,6 +336,7 @@ struct bcma_bus { + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci[2]; ++ struct bcma_drv_pcie2 drv_pcie2; + struct bcma_drv_mips drv_mips; + struct bcma_drv_gmac_cmn drv_gmac_cmn; + +@@ -400,7 +422,14 @@ static inline void bcma_maskset16(struct bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); } @@ -1225,6 +1524,167 @@ extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev); extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev); +--- /dev/null ++++ b/include/linux/bcma/bcma_driver_pcie2.h +@@ -0,0 +1,158 @@ ++#ifndef LINUX_BCMA_DRIVER_PCIE2_H_ ++#define LINUX_BCMA_DRIVER_PCIE2_H_ ++ ++#define BCMA_CORE_PCIE2_CLK_CONTROL 0x0000 ++#define PCIE2_CLKC_RST_OE 0x0001 /* When set, drives PCI_RESET out to pin */ ++#define PCIE2_CLKC_RST 0x0002 /* Value driven out to pin */ ++#define PCIE2_CLKC_SPERST 0x0004 /* SurvivePeRst */ ++#define PCIE2_CLKC_DISABLE_L1CLK_GATING 0x0010 ++#define PCIE2_CLKC_DLYPERST 0x0100 /* Delay PeRst to CoE Core */ ++#define PCIE2_CLKC_DISSPROMLD 0x0200 /* DisableSpromLoadOnPerst */ ++#define PCIE2_CLKC_WAKE_MODE_L2 0x1000 /* Wake on L2 */ ++#define BCMA_CORE_PCIE2_RC_PM_CONTROL 0x0004 ++#define BCMA_CORE_PCIE2_RC_PM_STATUS 0x0008 ++#define BCMA_CORE_PCIE2_EP_PM_CONTROL 0x000C ++#define BCMA_CORE_PCIE2_EP_PM_STATUS 0x0010 ++#define BCMA_CORE_PCIE2_EP_LTR_CONTROL 0x0014 ++#define BCMA_CORE_PCIE2_EP_LTR_STATUS 0x0018 ++#define BCMA_CORE_PCIE2_EP_OBFF_STATUS 0x001C ++#define BCMA_CORE_PCIE2_PCIE_ERR_STATUS 0x0020 ++#define BCMA_CORE_PCIE2_RC_AXI_CONFIG 0x0100 ++#define BCMA_CORE_PCIE2_EP_AXI_CONFIG 0x0104 ++#define BCMA_CORE_PCIE2_RXDEBUG_STATUS0 0x0108 ++#define BCMA_CORE_PCIE2_RXDEBUG_CONTROL0 0x010C ++#define BCMA_CORE_PCIE2_CONFIGINDADDR 0x0120 ++#define BCMA_CORE_PCIE2_CONFIGINDDATA 0x0124 ++#define BCMA_CORE_PCIE2_MDIOCONTROL 0x0128 ++#define BCMA_CORE_PCIE2_MDIOWRDATA 0x012C ++#define BCMA_CORE_PCIE2_MDIORDDATA 0x0130 ++#define BCMA_CORE_PCIE2_DATAINTF 0x0180 ++#define BCMA_CORE_PCIE2_D2H_INTRLAZY_0 0x0188 ++#define BCMA_CORE_PCIE2_H2D_INTRLAZY_0 0x018c ++#define BCMA_CORE_PCIE2_H2D_INTSTAT_0 0x0190 ++#define BCMA_CORE_PCIE2_H2D_INTMASK_0 0x0194 ++#define BCMA_CORE_PCIE2_D2H_INTSTAT_0 0x0198 ++#define BCMA_CORE_PCIE2_D2H_INTMASK_0 0x019c ++#define BCMA_CORE_PCIE2_LTR_STATE 0x01A0 /* Latency Tolerance Reporting */ ++#define PCIE2_LTR_ACTIVE 2 ++#define PCIE2_LTR_ACTIVE_IDLE 1 ++#define PCIE2_LTR_SLEEP 0 ++#define PCIE2_LTR_FINAL_MASK 0x300 ++#define PCIE2_LTR_FINAL_SHIFT 8 ++#define BCMA_CORE_PCIE2_PWR_INT_STATUS 0x01A4 ++#define BCMA_CORE_PCIE2_PWR_INT_MASK 0x01A8 ++#define BCMA_CORE_PCIE2_CFG_ADDR 0x01F8 ++#define BCMA_CORE_PCIE2_CFG_DATA 0x01FC ++#define BCMA_CORE_PCIE2_SYS_EQ_PAGE 0x0200 ++#define BCMA_CORE_PCIE2_SYS_MSI_PAGE 0x0204 ++#define BCMA_CORE_PCIE2_SYS_MSI_INTREN 0x0208 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL0 0x0210 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL1 0x0214 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL2 0x0218 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL3 0x021C ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL4 0x0220 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL5 0x0224 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD0 0x0250 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL0 0x0254 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD1 0x0258 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL1 0x025C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD2 0x0260 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL2 0x0264 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD3 0x0268 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL3 0x026C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD4 0x0270 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL4 0x0274 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD5 0x0278 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL5 0x027C ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_EN 0x0330 ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_CSR 0x0334 ++#define BCMA_CORE_PCIE2_SYS_MSI_REQ 0x0340 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_EN 0x0344 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_CSR 0x0348 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR0 0x0350 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR1 0x0354 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR2 0x0358 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR3 0x035C ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN0 0x0360 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN1 0x0364 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR0 0x0370 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR1 0x0374 ++#define BCMA_CORE_PCIE2_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_0 0x0C00 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_1 0x0C04 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_2 0x0C08 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_3 0x0C0C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_4 0x0C10 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_5 0x0C14 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_6 0x0C18 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_7 0x0C1C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_0 0x0C20 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_1 0x0C24 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_2 0x0C28 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_3 0x0C2C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_4 0x0C30 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_5 0x0C34 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_6 0x0C38 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_7 0x0C3C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP1 0x0C80 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP1 0x0C88 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP2 0x0CC0 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP2 0x0CC8 ++#define BCMA_CORE_PCIE2_IARR0_LOWER 0x0D00 ++#define BCMA_CORE_PCIE2_IARR0_UPPER 0x0D04 ++#define BCMA_CORE_PCIE2_IARR1_LOWER 0x0D08 ++#define BCMA_CORE_PCIE2_IARR1_UPPER 0x0D0C ++#define BCMA_CORE_PCIE2_IARR2_LOWER 0x0D10 ++#define BCMA_CORE_PCIE2_IARR2_UPPER 0x0D14 ++#define BCMA_CORE_PCIE2_OARR0 0x0D20 ++#define BCMA_CORE_PCIE2_OARR1 0x0D28 ++#define BCMA_CORE_PCIE2_OARR2 0x0D30 ++#define BCMA_CORE_PCIE2_OMAP0_LOWER 0x0D40 ++#define BCMA_CORE_PCIE2_OMAP0_UPPER 0x0D44 ++#define BCMA_CORE_PCIE2_OMAP1_LOWER 0x0D48 ++#define BCMA_CORE_PCIE2_OMAP1_UPPER 0x0D4C ++#define BCMA_CORE_PCIE2_OMAP2_LOWER 0x0D50 ++#define BCMA_CORE_PCIE2_OMAP2_UPPER 0x0D54 ++#define BCMA_CORE_PCIE2_FUNC1_IARR1_SIZE 0x0D58 ++#define BCMA_CORE_PCIE2_FUNC1_IARR2_SIZE 0x0D5C ++#define BCMA_CORE_PCIE2_MEM_CONTROL 0x0F00 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG0 0x0F04 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG1 0x0F08 ++#define BCMA_CORE_PCIE2_LINK_STATUS 0x0F0C ++#define BCMA_CORE_PCIE2_STRAP_STATUS 0x0F10 ++#define BCMA_CORE_PCIE2_RESET_STATUS 0x0F14 ++#define BCMA_CORE_PCIE2_RESETEN_IN_LINKDOWN 0x0F18 ++#define BCMA_CORE_PCIE2_MISC_INTR_EN 0x0F1C ++#define BCMA_CORE_PCIE2_TX_DEBUG_CFG 0x0F20 ++#define BCMA_CORE_PCIE2_MISC_CONFIG 0x0F24 ++#define BCMA_CORE_PCIE2_MISC_STATUS 0x0F28 ++#define BCMA_CORE_PCIE2_INTR_EN 0x0F30 ++#define BCMA_CORE_PCIE2_INTR_CLEAR 0x0F34 ++#define BCMA_CORE_PCIE2_INTR_STATUS 0x0F38 ++ ++/* PCIE gen2 config regs */ ++#define PCIE2_INTSTATUS 0x090 ++#define PCIE2_INTMASK 0x094 ++#define PCIE2_SBMBX 0x098 ++ ++#define PCIE2_PMCR_REFUP 0x1814 /* Trefup time */ ++ ++#define PCIE2_CAP_DEVSTSCTRL2_OFFSET 0xD4 ++#define PCIE2_CAP_DEVSTSCTRL2_LTRENAB 0x400 ++#define PCIE2_PVT_REG_PM_CLK_PERIOD 0x184c ++ ++struct bcma_drv_pcie2 { ++ struct bcma_device *core; ++}; ++ ++#define pcie2_read16(pcie2, offset) bcma_read16((pcie2)->core, offset) ++#define pcie2_read32(pcie2, offset) bcma_read32((pcie2)->core, offset) ++#define pcie2_write16(pcie2, offset, val) bcma_write16((pcie2)->core, offset, val) ++#define pcie2_write32(pcie2, offset, val) bcma_write32((pcie2)->core, offset, val) ++ ++#define pcie2_set32(pcie2, offset, set) bcma_set32((pcie2)->core, offset, set) ++#define pcie2_mask32(pcie2, offset, mask) bcma_mask32((pcie2)->core, offset, mask) ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2); ++ ++#endif /* LINUX_BCMA_DRIVER_PCIE2_H_ */ --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c @@ -679,27 +679,6 @@ bool ai_clkctl_cc(struct si_pub *sih, en diff --git a/target/linux/generic/patches-3.13/020-ssb_update.patch b/target/linux/generic/patches-3.13/020-ssb_update.patch index 2755bf0bdc..ec13f48e69 100644 --- a/target/linux/generic/patches-3.13/020-ssb_update.patch +++ b/target/linux/generic/patches-3.13/020-ssb_update.patch @@ -455,6 +455,161 @@ err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); +--- a/drivers/ssb/pci.c ++++ b/drivers/ssb/pci.c +@@ -326,13 +326,13 @@ err_ctlreg: + return err; + } + +-static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, +- u16 mask, u16 shift) ++static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, ++ u16 mask, u16 shift) + { + u16 v; + u8 gain; + +- v = in[SPOFF(SSB_SPROM1_AGAIN)]; ++ v = in[SPOFF(offset)]; + gain = (v & mask) >> shift; + if (gain == 0xFF) + gain = 2; /* If unset use 2dBm */ +@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ss + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + + /* Extract the antenna gain values. */ +- out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_BG, +- SSB_SPROM1_AGAIN_BG_SHIFT); +- out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_A, +- SSB_SPROM1_AGAIN_A_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_BG, ++ SSB_SPROM1_AGAIN_BG_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_A, ++ SSB_SPROM1_AGAIN_A_SHIFT); + if (out->revision >= 2) + sprom_extract_r23(out, in); + } +@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ss + + static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) + { ++ static const u16 pwr_info_offset[] = { ++ SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, ++ SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 ++ }; + u16 il0mac_offset; ++ int i; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != ++ ARRAY_SIZE(out->core_pwr_info)); + + if (out->revision == 4) + il0mac_offset = SSB_SPROM4_IL0MAC; +@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb + } + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN0, ++ SSB_SPROM4_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN1, ++ SSB_SPROM4_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN2, ++ SSB_SPROM4_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN3, ++ SSB_SPROM4_AGAIN3_SHIFT); ++ ++ /* Extract cores power info info */ ++ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { ++ u16 o = pwr_info_offset[i]; ++ ++ SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_MAXP, 0); ++ ++ SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); ++ ++ SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GH_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); ++ ++ SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); ++ } + + sprom_extract_r458(out, in); + +@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_ + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -33,6 +33,7 @@ struct ssb_sprom { @@ -473,6 +628,52 @@ #endif /* DRIVER_GPIO */ /* Internal-only stuff follows. Do not touch. */ +--- a/include/linux/ssb/ssb_regs.h ++++ b/include/linux/ssb/ssb_regs.h +@@ -345,6 +345,43 @@ + #define SSB_SPROM4_TXPID5GH2_SHIFT 0 + #define SSB_SPROM4_TXPID5GH3 0xFF00 + #define SSB_SPROM4_TXPID5GH3_SHIFT 8 ++ ++/* There are 4 blocks with power info sharing the same layout */ ++#define SSB_SPROM4_PWR_INFO_CORE0 0x0080 ++#define SSB_SPROM4_PWR_INFO_CORE1 0x00AE ++#define SSB_SPROM4_PWR_INFO_CORE2 0x00DC ++#define SSB_SPROM4_PWR_INFO_CORE3 0x010A ++ ++#define SSB_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */ ++#define SSB_SPROM4_2G_MAXP 0x00FF ++#define SSB_SPROM4_2G_ITSSI 0xFF00 ++#define SSB_SPROM4_2G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */ ++#define SSB_SPROM4_2G_PA_1 0x04 ++#define SSB_SPROM4_2G_PA_2 0x06 ++#define SSB_SPROM4_2G_PA_3 0x08 ++#define SSB_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */ ++#define SSB_SPROM4_5G_MAXP 0x00FF ++#define SSB_SPROM4_5G_ITSSI 0xFF00 ++#define SSB_SPROM4_5G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */ ++#define SSB_SPROM4_5GH_MAXP 0x00FF ++#define SSB_SPROM4_5GL_MAXP 0xFF00 ++#define SSB_SPROM4_5GL_MAXP_SHIFT 8 ++#define SSB_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */ ++#define SSB_SPROM4_5G_PA_1 0x10 ++#define SSB_SPROM4_5G_PA_2 0x12 ++#define SSB_SPROM4_5G_PA_3 0x14 ++#define SSB_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */ ++#define SSB_SPROM4_5GL_PA_1 0x18 ++#define SSB_SPROM4_5GL_PA_2 0x1A ++#define SSB_SPROM4_5GL_PA_3 0x1C ++#define SSB_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */ ++#define SSB_SPROM4_5GH_PA_1 0x20 ++#define SSB_SPROM4_5GH_PA_2 0x22 ++#define SSB_SPROM4_5GH_PA_3 0x24 ++ ++/* TODO: Make it deprecated */ + #define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */ + #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ + #define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char diff --git a/target/linux/generic/patches-3.13/025-bcma_backport.patch b/target/linux/generic/patches-3.13/025-bcma_backport.patch index dcb712dbbc..301a97c558 100644 --- a/target/linux/generic/patches-3.13/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.13/025-bcma_backport.patch @@ -8,6 +8,16 @@ help Driver to provide access to the GPIO pins of the bcma bus. +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver + bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o + bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o + bcma-y += driver_pci.o ++bcma-y += driver_pcie2.o + bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -33,8 +33,6 @@ int __init bcma_bus_early_register(struc @@ -19,6 +29,16 @@ /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -603,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct + tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; + break; + ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -38,7 +38,7 @@ static const struct bcma_sflash_tbl_e bc @@ -198,7 +218,7 @@ chip->label = "bcma_gpio"; chip->owner = THIS_MODULE; -@@ -95,8 +215,17 @@ int bcma_gpio_init(struct bcma_drv_cc *c +@@ -95,8 +215,18 @@ int bcma_gpio_init(struct bcma_drv_cc *c chip->set = bcma_gpio_set_value; chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; @@ -208,6 +228,7 @@ +#endif + switch (cc->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM5357: ++ case BCMA_CHIP_ID_BCM53572: + chip->ngpio = 32; + break; + default: @@ -217,7 +238,7 @@ /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get * a random base number. */ -@@ -105,10 +234,21 @@ int bcma_gpio_init(struct bcma_drv_cc *c +@@ -105,10 +235,21 @@ int bcma_gpio_init(struct bcma_drv_cc *c else chip->base = -1; @@ -240,6 +261,184 @@ + bcma_gpio_irq_domain_exit(cc); return gpiochip_remove(&cc->gpio); } +--- /dev/null ++++ b/drivers/bcma/driver_pcie2.c +@@ -0,0 +1,175 @@ ++/* ++ * Broadcom specific AMBA ++ * PCIe Gen 2 Core ++ * ++ * Copyright 2014, Broadcom Corporation ++ * Copyright 2014, Rafał Miłecki ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include ++ ++/************************************************** ++ * R/W ops. ++ **************************************************/ ++ ++#if 0 ++static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++} ++#endif ++ ++static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, ++ u32 val) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); ++} ++ ++/************************************************** ++ * Init. ++ **************************************************/ ++ ++static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, ++ bool enable) ++{ ++ u32 val; ++ ++ /* restore back to default */ ++ val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++ val |= PCIE2_CLKC_DLYPERST; ++ val &= ~PCIE2_CLKC_DISSPROMLD; ++ if (enable) { ++ val &= ~PCIE2_CLKC_DLYPERST; ++ val |= PCIE2_CLKC_DISSPROMLD; ++ } ++ pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); ++ /* flush */ ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++} ++ ++static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) ++{ ++ /* LTR0 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); ++ /* LTR1 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); ++ /* LTR2 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); ++} ++ ++static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ u32 devstsctr2; ++ ++ if (core_rev < 2 || core_rev == 10 || core_rev > 13) ++ return; ++ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++ if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { ++ /* force the right LTR values */ ++ bcma_core_pcie2_set_ltr_vals(pcie2); ++ ++ /* TODO: ++ si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */ ++ ++ /* enable the LTR */ ++ devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); ++ ++ /* set the LTR state to be active */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_ACTIVE); ++ usleep_range(1000, 2000); ++ ++ /* set the LTR state to be sleep */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_SLEEP); ++ usleep_range(1000, 2000); ++ } ++} ++ ++static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ bool pciewar160, pciewar162; ++ ++ pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; ++ pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || ++ core_rev == 9 || core_rev == 11; ++ ++ if (!pciewar160 && !pciewar162) ++ return; ++ ++/* TODO */ ++#if 0 ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, ++ PCIE_DISABLE_L1CLK_GATING); ++#if 0 ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIEGEN2_COE_PVT_TL_CTRL_0); ++ pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, ++ ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); ++#endif ++#endif ++} ++ ++static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); ++} ++ ++static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); ++} ++ ++static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; ++ u8 core_rev = pcie2->core->id.rev; ++ u32 alp_khz, pm_value; ++ ++ if (core_rev <= 13) { ++ alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; ++ pm_value = (1000000 * 2) / alp_khz; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_PVT_REG_PM_CLK_PERIOD); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); ++ } ++} ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo; ++ u32 tmp; ++ ++ tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); ++ if ((tmp & 0xe) >> 1 == 2) ++ bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); ++ ++ /* TODO: Do we need pcie_reqsize? */ ++ ++ if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) ++ bcma_core_pcie2_war_delay_perst_enab(pcie2, true); ++ bcma_core_pcie2_hw_ltr_war(pcie2); ++ pciedev_crwlpciegen2(pcie2); ++ pciedev_reg_pm_clk_period(pcie2); ++ pciedev_crwlpciegen2_180(pcie2); ++ pciedev_crwlpciegen2_182(pcie2); ++} --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -238,7 +238,6 @@ static void bcma_host_pci_remove(struct @@ -259,6 +458,14 @@ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, +@@ -280,6 +279,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, + { 0, }, + }; --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -78,18 +78,6 @@ static u16 bcma_cc_core_id(struct bcma_b @@ -288,7 +495,15 @@ bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, int timeout) -@@ -176,6 +165,7 @@ static int bcma_register_cores(struct bc +@@ -143,6 +132,7 @@ static int bcma_register_cores(struct bc + case BCMA_CORE_CHIPCOMMON: + case BCMA_CORE_PCI: + case BCMA_CORE_PCIE: ++ case BCMA_CORE_PCIE2: + case BCMA_CORE_MIPS_74K: + case BCMA_CORE_4706_MAC_GBIT_COMMON: + continue; +@@ -176,6 +166,7 @@ static int bcma_register_cores(struct bc bcma_err(bus, "Could not register dev for core 0x%03X\n", core->id.id); @@ -296,9 +511,113 @@ continue; } core->dev_registered = true; +@@ -291,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_pci_init(&bus->drv_pci[1]); + } + ++ /* Init PCIe Gen 2 core */ ++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0); ++ if (core) { ++ bus->drv_pcie2.core = core; ++ bcma_core_pcie2_init(&bus->drv_pcie2); ++ } ++ + /* Init GBIT MAC COMMON core */ + core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); + if (core) { +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_ + SPEX(_field[7], _offset + 14, _mask, _shift); \ + } while (0) + ++static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) ++{ ++ u16 v; ++ u8 gain; ++ ++ v = in[SPOFF(offset)]; ++ gain = (v & mask) >> shift; ++ if (gain == 0xFF) { ++ gain = 8; /* If unset use 2dBm */ ++ } else { ++ /* Q5.2 Fractional part is stored in 0xC0 */ ++ gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); ++ } ++ ++ return (s8)gain; ++} ++ + static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) + { + u16 v, o; +@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, + SSB_SPROM8_LEDDC_ON_SHIFT); +@@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available( + /* for these chips OTP is always available */ + present = true; + break; ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h -@@ -418,7 +418,14 @@ static inline void bcma_maskset16(struct +@@ -6,6 +6,7 @@ + + #include + #include ++#include + #include + #include + #include /* SPROM sharing */ +@@ -157,6 +158,8 @@ struct bcma_host_ops { + /* Chip IDs of PCIe devices */ + #define BCMA_CHIP_ID_BCM4313 0x4313 + #define BCMA_CHIP_ID_BCM43142 43142 ++#define BCMA_CHIP_ID_BCM43217 43217 ++#define BCMA_CHIP_ID_BCM43222 43222 + #define BCMA_CHIP_ID_BCM43224 43224 + #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 + #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa +@@ -333,6 +336,7 @@ struct bcma_bus { + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci[2]; ++ struct bcma_drv_pcie2 drv_pcie2; + struct bcma_drv_mips drv_mips; + struct bcma_drv_gmac_cmn drv_gmac_cmn; + +@@ -418,7 +422,14 @@ static inline void bcma_maskset16(struct bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); } @@ -324,3 +643,164 @@ #endif }; +--- /dev/null ++++ b/include/linux/bcma/bcma_driver_pcie2.h +@@ -0,0 +1,158 @@ ++#ifndef LINUX_BCMA_DRIVER_PCIE2_H_ ++#define LINUX_BCMA_DRIVER_PCIE2_H_ ++ ++#define BCMA_CORE_PCIE2_CLK_CONTROL 0x0000 ++#define PCIE2_CLKC_RST_OE 0x0001 /* When set, drives PCI_RESET out to pin */ ++#define PCIE2_CLKC_RST 0x0002 /* Value driven out to pin */ ++#define PCIE2_CLKC_SPERST 0x0004 /* SurvivePeRst */ ++#define PCIE2_CLKC_DISABLE_L1CLK_GATING 0x0010 ++#define PCIE2_CLKC_DLYPERST 0x0100 /* Delay PeRst to CoE Core */ ++#define PCIE2_CLKC_DISSPROMLD 0x0200 /* DisableSpromLoadOnPerst */ ++#define PCIE2_CLKC_WAKE_MODE_L2 0x1000 /* Wake on L2 */ ++#define BCMA_CORE_PCIE2_RC_PM_CONTROL 0x0004 ++#define BCMA_CORE_PCIE2_RC_PM_STATUS 0x0008 ++#define BCMA_CORE_PCIE2_EP_PM_CONTROL 0x000C ++#define BCMA_CORE_PCIE2_EP_PM_STATUS 0x0010 ++#define BCMA_CORE_PCIE2_EP_LTR_CONTROL 0x0014 ++#define BCMA_CORE_PCIE2_EP_LTR_STATUS 0x0018 ++#define BCMA_CORE_PCIE2_EP_OBFF_STATUS 0x001C ++#define BCMA_CORE_PCIE2_PCIE_ERR_STATUS 0x0020 ++#define BCMA_CORE_PCIE2_RC_AXI_CONFIG 0x0100 ++#define BCMA_CORE_PCIE2_EP_AXI_CONFIG 0x0104 ++#define BCMA_CORE_PCIE2_RXDEBUG_STATUS0 0x0108 ++#define BCMA_CORE_PCIE2_RXDEBUG_CONTROL0 0x010C ++#define BCMA_CORE_PCIE2_CONFIGINDADDR 0x0120 ++#define BCMA_CORE_PCIE2_CONFIGINDDATA 0x0124 ++#define BCMA_CORE_PCIE2_MDIOCONTROL 0x0128 ++#define BCMA_CORE_PCIE2_MDIOWRDATA 0x012C ++#define BCMA_CORE_PCIE2_MDIORDDATA 0x0130 ++#define BCMA_CORE_PCIE2_DATAINTF 0x0180 ++#define BCMA_CORE_PCIE2_D2H_INTRLAZY_0 0x0188 ++#define BCMA_CORE_PCIE2_H2D_INTRLAZY_0 0x018c ++#define BCMA_CORE_PCIE2_H2D_INTSTAT_0 0x0190 ++#define BCMA_CORE_PCIE2_H2D_INTMASK_0 0x0194 ++#define BCMA_CORE_PCIE2_D2H_INTSTAT_0 0x0198 ++#define BCMA_CORE_PCIE2_D2H_INTMASK_0 0x019c ++#define BCMA_CORE_PCIE2_LTR_STATE 0x01A0 /* Latency Tolerance Reporting */ ++#define PCIE2_LTR_ACTIVE 2 ++#define PCIE2_LTR_ACTIVE_IDLE 1 ++#define PCIE2_LTR_SLEEP 0 ++#define PCIE2_LTR_FINAL_MASK 0x300 ++#define PCIE2_LTR_FINAL_SHIFT 8 ++#define BCMA_CORE_PCIE2_PWR_INT_STATUS 0x01A4 ++#define BCMA_CORE_PCIE2_PWR_INT_MASK 0x01A8 ++#define BCMA_CORE_PCIE2_CFG_ADDR 0x01F8 ++#define BCMA_CORE_PCIE2_CFG_DATA 0x01FC ++#define BCMA_CORE_PCIE2_SYS_EQ_PAGE 0x0200 ++#define BCMA_CORE_PCIE2_SYS_MSI_PAGE 0x0204 ++#define BCMA_CORE_PCIE2_SYS_MSI_INTREN 0x0208 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL0 0x0210 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL1 0x0214 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL2 0x0218 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL3 0x021C ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL4 0x0220 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL5 0x0224 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD0 0x0250 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL0 0x0254 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD1 0x0258 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL1 0x025C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD2 0x0260 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL2 0x0264 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD3 0x0268 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL3 0x026C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD4 0x0270 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL4 0x0274 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD5 0x0278 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL5 0x027C ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_EN 0x0330 ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_CSR 0x0334 ++#define BCMA_CORE_PCIE2_SYS_MSI_REQ 0x0340 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_EN 0x0344 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_CSR 0x0348 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR0 0x0350 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR1 0x0354 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR2 0x0358 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR3 0x035C ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN0 0x0360 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN1 0x0364 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR0 0x0370 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR1 0x0374 ++#define BCMA_CORE_PCIE2_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_0 0x0C00 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_1 0x0C04 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_2 0x0C08 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_3 0x0C0C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_4 0x0C10 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_5 0x0C14 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_6 0x0C18 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_7 0x0C1C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_0 0x0C20 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_1 0x0C24 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_2 0x0C28 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_3 0x0C2C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_4 0x0C30 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_5 0x0C34 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_6 0x0C38 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_7 0x0C3C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP1 0x0C80 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP1 0x0C88 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP2 0x0CC0 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP2 0x0CC8 ++#define BCMA_CORE_PCIE2_IARR0_LOWER 0x0D00 ++#define BCMA_CORE_PCIE2_IARR0_UPPER 0x0D04 ++#define BCMA_CORE_PCIE2_IARR1_LOWER 0x0D08 ++#define BCMA_CORE_PCIE2_IARR1_UPPER 0x0D0C ++#define BCMA_CORE_PCIE2_IARR2_LOWER 0x0D10 ++#define BCMA_CORE_PCIE2_IARR2_UPPER 0x0D14 ++#define BCMA_CORE_PCIE2_OARR0 0x0D20 ++#define BCMA_CORE_PCIE2_OARR1 0x0D28 ++#define BCMA_CORE_PCIE2_OARR2 0x0D30 ++#define BCMA_CORE_PCIE2_OMAP0_LOWER 0x0D40 ++#define BCMA_CORE_PCIE2_OMAP0_UPPER 0x0D44 ++#define BCMA_CORE_PCIE2_OMAP1_LOWER 0x0D48 ++#define BCMA_CORE_PCIE2_OMAP1_UPPER 0x0D4C ++#define BCMA_CORE_PCIE2_OMAP2_LOWER 0x0D50 ++#define BCMA_CORE_PCIE2_OMAP2_UPPER 0x0D54 ++#define BCMA_CORE_PCIE2_FUNC1_IARR1_SIZE 0x0D58 ++#define BCMA_CORE_PCIE2_FUNC1_IARR2_SIZE 0x0D5C ++#define BCMA_CORE_PCIE2_MEM_CONTROL 0x0F00 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG0 0x0F04 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG1 0x0F08 ++#define BCMA_CORE_PCIE2_LINK_STATUS 0x0F0C ++#define BCMA_CORE_PCIE2_STRAP_STATUS 0x0F10 ++#define BCMA_CORE_PCIE2_RESET_STATUS 0x0F14 ++#define BCMA_CORE_PCIE2_RESETEN_IN_LINKDOWN 0x0F18 ++#define BCMA_CORE_PCIE2_MISC_INTR_EN 0x0F1C ++#define BCMA_CORE_PCIE2_TX_DEBUG_CFG 0x0F20 ++#define BCMA_CORE_PCIE2_MISC_CONFIG 0x0F24 ++#define BCMA_CORE_PCIE2_MISC_STATUS 0x0F28 ++#define BCMA_CORE_PCIE2_INTR_EN 0x0F30 ++#define BCMA_CORE_PCIE2_INTR_CLEAR 0x0F34 ++#define BCMA_CORE_PCIE2_INTR_STATUS 0x0F38 ++ ++/* PCIE gen2 config regs */ ++#define PCIE2_INTSTATUS 0x090 ++#define PCIE2_INTMASK 0x094 ++#define PCIE2_SBMBX 0x098 ++ ++#define PCIE2_PMCR_REFUP 0x1814 /* Trefup time */ ++ ++#define PCIE2_CAP_DEVSTSCTRL2_OFFSET 0xD4 ++#define PCIE2_CAP_DEVSTSCTRL2_LTRENAB 0x400 ++#define PCIE2_PVT_REG_PM_CLK_PERIOD 0x184c ++ ++struct bcma_drv_pcie2 { ++ struct bcma_device *core; ++}; ++ ++#define pcie2_read16(pcie2, offset) bcma_read16((pcie2)->core, offset) ++#define pcie2_read32(pcie2, offset) bcma_read32((pcie2)->core, offset) ++#define pcie2_write16(pcie2, offset, val) bcma_write16((pcie2)->core, offset, val) ++#define pcie2_write32(pcie2, offset, val) bcma_write32((pcie2)->core, offset, val) ++ ++#define pcie2_set32(pcie2, offset, set) bcma_set32((pcie2)->core, offset, set) ++#define pcie2_mask32(pcie2, offset, mask) bcma_mask32((pcie2)->core, offset, mask) ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2); ++ ++#endif /* LINUX_BCMA_DRIVER_PCIE2_H_ */ diff --git a/target/linux/generic/patches-3.14/020-ssb_update.patch b/target/linux/generic/patches-3.14/020-ssb_update.patch index eb0bc5227e..742460290a 100644 --- a/target/linux/generic/patches-3.14/020-ssb_update.patch +++ b/target/linux/generic/patches-3.14/020-ssb_update.patch @@ -1,29 +1,158 @@ -commit 4f4aa2ec24dc45881849833a439558d3a378028c -Author: Rafał Miłecki -Date: Sun May 18 00:22:38 2014 +0200 - - ssb: sprom: add dev_id field for value overriding standard ID - - Some devices may have different features despite sharing the same ID - (e.g. PCI ID). For example 14e4:4331 is usually a dual band, but this - can be "limited". Device with "pci/x/y/devid=0x4332" supports 2.4 GHz - only. Similarly 0x4333 will mean support for 5 GHz only. - Add entry in SPROM so info described above can be extracted and stored. - - Signed-off-by: Rafał Miłecki - Acked-by: Hauke Mehrtens - Signed-off-by: John W. Linville - ---- a/arch/mips/bcm47xx/sprom.c -+++ b/arch/mips/bcm47xx/sprom.c -@@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char - static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, - const char *prefix, bool fallback) +--- a/drivers/ssb/pci.c ++++ b/drivers/ssb/pci.c +@@ -326,13 +326,13 @@ err_ctlreg: + return err; + } + +-static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, +- u16 mask, u16 shift) ++static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, ++ u16 mask, u16 shift) { -+ nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback); - nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback); - nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback); - nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback); + u16 v; + u8 gain; + +- v = in[SPOFF(SSB_SPROM1_AGAIN)]; ++ v = in[SPOFF(offset)]; + gain = (v & mask) >> shift; + if (gain == 0xFF) + gain = 2; /* If unset use 2dBm */ +@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ss + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + + /* Extract the antenna gain values. */ +- out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_BG, +- SSB_SPROM1_AGAIN_BG_SHIFT); +- out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, +- SSB_SPROM1_AGAIN_A, +- SSB_SPROM1_AGAIN_A_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_BG, ++ SSB_SPROM1_AGAIN_BG_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM1_AGAIN, ++ SSB_SPROM1_AGAIN_A, ++ SSB_SPROM1_AGAIN_A_SHIFT); + if (out->revision >= 2) + sprom_extract_r23(out, in); + } +@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ss + + static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) + { ++ static const u16 pwr_info_offset[] = { ++ SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, ++ SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 ++ }; + u16 il0mac_offset; ++ int i; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != ++ ARRAY_SIZE(out->core_pwr_info)); + + if (out->revision == 4) + il0mac_offset = SSB_SPROM4_IL0MAC; +@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb + } + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, +- SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, +- SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN0, ++ SSB_SPROM4_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN01, ++ SSB_SPROM4_AGAIN1, ++ SSB_SPROM4_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN2, ++ SSB_SPROM4_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM4_AGAIN23, ++ SSB_SPROM4_AGAIN3, ++ SSB_SPROM4_AGAIN3_SHIFT); ++ ++ /* Extract cores power info info */ ++ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { ++ u16 o = pwr_info_offset[i]; ++ ++ SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, ++ SSB_SPROM4_2G_MAXP, 0); ++ ++ SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); ++ ++ SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); ++ SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, ++ SSB_SPROM4_5G_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GH_MAXP, 0); ++ SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, ++ SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); ++ ++ SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); ++ SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); ++ } + + sprom_extract_r458(out, in); + +@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_ + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -33,6 +33,7 @@ struct ssb_sprom { @@ -34,3 +163,59 @@ Date: Sun May 18 00:22:38 2014 +0200 u16 board_rev; /* Board revision number from SPROM. */ u16 board_num; /* Board number from SPROM. */ u16 board_type; /* Board type from SPROM. */ +--- a/include/linux/ssb/ssb_regs.h ++++ b/include/linux/ssb/ssb_regs.h +@@ -345,6 +345,43 @@ + #define SSB_SPROM4_TXPID5GH2_SHIFT 0 + #define SSB_SPROM4_TXPID5GH3 0xFF00 + #define SSB_SPROM4_TXPID5GH3_SHIFT 8 ++ ++/* There are 4 blocks with power info sharing the same layout */ ++#define SSB_SPROM4_PWR_INFO_CORE0 0x0080 ++#define SSB_SPROM4_PWR_INFO_CORE1 0x00AE ++#define SSB_SPROM4_PWR_INFO_CORE2 0x00DC ++#define SSB_SPROM4_PWR_INFO_CORE3 0x010A ++ ++#define SSB_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */ ++#define SSB_SPROM4_2G_MAXP 0x00FF ++#define SSB_SPROM4_2G_ITSSI 0xFF00 ++#define SSB_SPROM4_2G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */ ++#define SSB_SPROM4_2G_PA_1 0x04 ++#define SSB_SPROM4_2G_PA_2 0x06 ++#define SSB_SPROM4_2G_PA_3 0x08 ++#define SSB_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */ ++#define SSB_SPROM4_5G_MAXP 0x00FF ++#define SSB_SPROM4_5G_ITSSI 0xFF00 ++#define SSB_SPROM4_5G_ITSSI_SHIFT 8 ++#define SSB_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */ ++#define SSB_SPROM4_5GH_MAXP 0x00FF ++#define SSB_SPROM4_5GL_MAXP 0xFF00 ++#define SSB_SPROM4_5GL_MAXP_SHIFT 8 ++#define SSB_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */ ++#define SSB_SPROM4_5G_PA_1 0x10 ++#define SSB_SPROM4_5G_PA_2 0x12 ++#define SSB_SPROM4_5G_PA_3 0x14 ++#define SSB_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */ ++#define SSB_SPROM4_5GL_PA_1 0x18 ++#define SSB_SPROM4_5GL_PA_2 0x1A ++#define SSB_SPROM4_5GL_PA_3 0x1C ++#define SSB_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */ ++#define SSB_SPROM4_5GH_PA_1 0x20 ++#define SSB_SPROM4_5GH_PA_2 0x22 ++#define SSB_SPROM4_5GH_PA_3 0x24 ++ ++/* TODO: Make it deprecated */ + #define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */ + #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ + #define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ +--- a/arch/mips/bcm47xx/sprom.c ++++ b/arch/mips/bcm47xx/sprom.c +@@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char + static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, + const char *prefix, bool fallback) + { ++ nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback); + nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback); + nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback); + nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback); diff --git a/target/linux/generic/patches-3.14/025-bcma_backport.patch b/target/linux/generic/patches-3.14/025-bcma_backport.patch index b49d345473..0dad074221 100644 --- a/target/linux/generic/patches-3.14/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.14/025-bcma_backport.patch @@ -1,12 +1,33 @@ +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver + bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o + bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o + bcma-y += driver_pci.o ++bcma-y += driver_pcie2.o + bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -603,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct + tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; + break; + ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c -@@ -218,7 +218,14 @@ int bcma_gpio_init(struct bcma_drv_cc *c +@@ -218,7 +218,15 @@ int bcma_gpio_init(struct bcma_drv_cc *c #if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) chip->to_irq = bcma_gpio_to_irq; #endif - chip->ngpio = 16; + switch (cc->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM5357: ++ case BCMA_CHIP_ID_BCM53572: + chip->ngpio = 32; + break; + default: @@ -16,3 +37,468 @@ /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get * a random base number. */ +--- /dev/null ++++ b/drivers/bcma/driver_pcie2.c +@@ -0,0 +1,175 @@ ++/* ++ * Broadcom specific AMBA ++ * PCIe Gen 2 Core ++ * ++ * Copyright 2014, Broadcom Corporation ++ * Copyright 2014, Rafał Miłecki ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include ++ ++/************************************************** ++ * R/W ops. ++ **************************************************/ ++ ++#if 0 ++static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++} ++#endif ++ ++static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, ++ u32 val) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); ++} ++ ++/************************************************** ++ * Init. ++ **************************************************/ ++ ++static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, ++ bool enable) ++{ ++ u32 val; ++ ++ /* restore back to default */ ++ val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++ val |= PCIE2_CLKC_DLYPERST; ++ val &= ~PCIE2_CLKC_DISSPROMLD; ++ if (enable) { ++ val &= ~PCIE2_CLKC_DLYPERST; ++ val |= PCIE2_CLKC_DISSPROMLD; ++ } ++ pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); ++ /* flush */ ++ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); ++} ++ ++static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) ++{ ++ /* LTR0 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); ++ /* LTR1 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); ++ /* LTR2 */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); ++} ++ ++static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ u32 devstsctr2; ++ ++ if (core_rev < 2 || core_rev == 10 || core_rev > 13) ++ return; ++ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); ++ if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { ++ /* force the right LTR values */ ++ bcma_core_pcie2_set_ltr_vals(pcie2); ++ ++ /* TODO: ++ si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */ ++ ++ /* enable the LTR */ ++ devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_CAP_DEVSTSCTRL2_OFFSET); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); ++ ++ /* set the LTR state to be active */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_ACTIVE); ++ usleep_range(1000, 2000); ++ ++ /* set the LTR state to be sleep */ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, ++ PCIE2_LTR_SLEEP); ++ usleep_range(1000, 2000); ++ } ++} ++ ++static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) ++{ ++ u8 core_rev = pcie2->core->id.rev; ++ bool pciewar160, pciewar162; ++ ++ pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; ++ pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || ++ core_rev == 9 || core_rev == 11; ++ ++ if (!pciewar160 && !pciewar162) ++ return; ++ ++/* TODO */ ++#if 0 ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, ++ PCIE_DISABLE_L1CLK_GATING); ++#if 0 ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIEGEN2_COE_PVT_TL_CTRL_0); ++ pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, ++ ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); ++#endif ++#endif ++} ++ ++static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); ++ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); ++} ++ ++static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) ++{ ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); ++} ++ ++static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; ++ u8 core_rev = pcie2->core->id.rev; ++ u32 alp_khz, pm_value; ++ ++ if (core_rev <= 13) { ++ alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; ++ pm_value = (1000000 * 2) / alp_khz; ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ PCIE2_PVT_REG_PM_CLK_PERIOD); ++ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); ++ } ++} ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) ++{ ++ struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo; ++ u32 tmp; ++ ++ tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); ++ if ((tmp & 0xe) >> 1 == 2) ++ bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); ++ ++ /* TODO: Do we need pcie_reqsize? */ ++ ++ if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) ++ bcma_core_pcie2_war_delay_perst_enab(pcie2, true); ++ bcma_core_pcie2_hw_ltr_war(pcie2); ++ pciedev_crwlpciegen2(pcie2); ++ pciedev_reg_pm_clk_period(pcie2); ++ pciedev_crwlpciegen2_180(pcie2); ++ pciedev_crwlpciegen2_182(pcie2); ++} +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -279,6 +279,7 @@ static const struct pci_device_id bcma_p + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, + { 0, }, + }; +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bc + case BCMA_CORE_CHIPCOMMON: + case BCMA_CORE_PCI: + case BCMA_CORE_PCIE: ++ case BCMA_CORE_PCIE2: + case BCMA_CORE_MIPS_74K: + case BCMA_CORE_4706_MAC_GBIT_COMMON: + continue; +@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_pci_init(&bus->drv_pci[1]); + } + ++ /* Init PCIe Gen 2 core */ ++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0); ++ if (core) { ++ bus->drv_pcie2.core = core; ++ bcma_core_pcie2_init(&bus->drv_pcie2); ++ } ++ + /* Init GBIT MAC COMMON core */ + core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); + if (core) { +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_ + SPEX(_field[7], _offset + 14, _mask, _shift); \ + } while (0) + ++static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) ++{ ++ u16 v; ++ u8 gain; ++ ++ v = in[SPOFF(offset)]; ++ gain = (v & mask) >> shift; ++ if (gain == 0xFF) { ++ gain = 8; /* If unset use 2dBm */ ++ } else { ++ /* Q5.2 Fractional part is stored in 0xC0 */ ++ gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); ++ } ++ ++ return (s8)gain; ++} ++ + static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) + { + u16 v, o; +@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); + + /* Extract the antenna gain values. */ +- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); +- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, +- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); +- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); +- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, +- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); ++ bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN0, ++ SSB_SPROM8_AGAIN0_SHIFT); ++ bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN01, ++ SSB_SPROM8_AGAIN1, ++ SSB_SPROM8_AGAIN1_SHIFT); ++ bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN2, ++ SSB_SPROM8_AGAIN2_SHIFT); ++ bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom, ++ SSB_SPROM8_AGAIN23, ++ SSB_SPROM8_AGAIN3, ++ SSB_SPROM8_AGAIN3_SHIFT); + + SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, + SSB_SPROM8_LEDDC_ON_SHIFT); +@@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available( + /* for these chips OTP is always available */ + present = true; + break; ++ case BCMA_CHIP_ID_BCM43217: + case BCMA_CHIP_ID_BCM43227: + case BCMA_CHIP_ID_BCM43228: + case BCMA_CHIP_ID_BCM43428: +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include + #include + #include + #include /* SPROM sharing */ +@@ -157,6 +158,8 @@ struct bcma_host_ops { + /* Chip IDs of PCIe devices */ + #define BCMA_CHIP_ID_BCM4313 0x4313 + #define BCMA_CHIP_ID_BCM43142 43142 ++#define BCMA_CHIP_ID_BCM43217 43217 ++#define BCMA_CHIP_ID_BCM43222 43222 + #define BCMA_CHIP_ID_BCM43224 43224 + #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 + #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa +@@ -333,6 +336,7 @@ struct bcma_bus { + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci[2]; ++ struct bcma_drv_pcie2 drv_pcie2; + struct bcma_drv_mips drv_mips; + struct bcma_drv_gmac_cmn drv_gmac_cmn; + +--- /dev/null ++++ b/include/linux/bcma/bcma_driver_pcie2.h +@@ -0,0 +1,158 @@ ++#ifndef LINUX_BCMA_DRIVER_PCIE2_H_ ++#define LINUX_BCMA_DRIVER_PCIE2_H_ ++ ++#define BCMA_CORE_PCIE2_CLK_CONTROL 0x0000 ++#define PCIE2_CLKC_RST_OE 0x0001 /* When set, drives PCI_RESET out to pin */ ++#define PCIE2_CLKC_RST 0x0002 /* Value driven out to pin */ ++#define PCIE2_CLKC_SPERST 0x0004 /* SurvivePeRst */ ++#define PCIE2_CLKC_DISABLE_L1CLK_GATING 0x0010 ++#define PCIE2_CLKC_DLYPERST 0x0100 /* Delay PeRst to CoE Core */ ++#define PCIE2_CLKC_DISSPROMLD 0x0200 /* DisableSpromLoadOnPerst */ ++#define PCIE2_CLKC_WAKE_MODE_L2 0x1000 /* Wake on L2 */ ++#define BCMA_CORE_PCIE2_RC_PM_CONTROL 0x0004 ++#define BCMA_CORE_PCIE2_RC_PM_STATUS 0x0008 ++#define BCMA_CORE_PCIE2_EP_PM_CONTROL 0x000C ++#define BCMA_CORE_PCIE2_EP_PM_STATUS 0x0010 ++#define BCMA_CORE_PCIE2_EP_LTR_CONTROL 0x0014 ++#define BCMA_CORE_PCIE2_EP_LTR_STATUS 0x0018 ++#define BCMA_CORE_PCIE2_EP_OBFF_STATUS 0x001C ++#define BCMA_CORE_PCIE2_PCIE_ERR_STATUS 0x0020 ++#define BCMA_CORE_PCIE2_RC_AXI_CONFIG 0x0100 ++#define BCMA_CORE_PCIE2_EP_AXI_CONFIG 0x0104 ++#define BCMA_CORE_PCIE2_RXDEBUG_STATUS0 0x0108 ++#define BCMA_CORE_PCIE2_RXDEBUG_CONTROL0 0x010C ++#define BCMA_CORE_PCIE2_CONFIGINDADDR 0x0120 ++#define BCMA_CORE_PCIE2_CONFIGINDDATA 0x0124 ++#define BCMA_CORE_PCIE2_MDIOCONTROL 0x0128 ++#define BCMA_CORE_PCIE2_MDIOWRDATA 0x012C ++#define BCMA_CORE_PCIE2_MDIORDDATA 0x0130 ++#define BCMA_CORE_PCIE2_DATAINTF 0x0180 ++#define BCMA_CORE_PCIE2_D2H_INTRLAZY_0 0x0188 ++#define BCMA_CORE_PCIE2_H2D_INTRLAZY_0 0x018c ++#define BCMA_CORE_PCIE2_H2D_INTSTAT_0 0x0190 ++#define BCMA_CORE_PCIE2_H2D_INTMASK_0 0x0194 ++#define BCMA_CORE_PCIE2_D2H_INTSTAT_0 0x0198 ++#define BCMA_CORE_PCIE2_D2H_INTMASK_0 0x019c ++#define BCMA_CORE_PCIE2_LTR_STATE 0x01A0 /* Latency Tolerance Reporting */ ++#define PCIE2_LTR_ACTIVE 2 ++#define PCIE2_LTR_ACTIVE_IDLE 1 ++#define PCIE2_LTR_SLEEP 0 ++#define PCIE2_LTR_FINAL_MASK 0x300 ++#define PCIE2_LTR_FINAL_SHIFT 8 ++#define BCMA_CORE_PCIE2_PWR_INT_STATUS 0x01A4 ++#define BCMA_CORE_PCIE2_PWR_INT_MASK 0x01A8 ++#define BCMA_CORE_PCIE2_CFG_ADDR 0x01F8 ++#define BCMA_CORE_PCIE2_CFG_DATA 0x01FC ++#define BCMA_CORE_PCIE2_SYS_EQ_PAGE 0x0200 ++#define BCMA_CORE_PCIE2_SYS_MSI_PAGE 0x0204 ++#define BCMA_CORE_PCIE2_SYS_MSI_INTREN 0x0208 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL0 0x0210 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL1 0x0214 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL2 0x0218 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL3 0x021C ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL4 0x0220 ++#define BCMA_CORE_PCIE2_SYS_MSI_CTRL5 0x0224 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD0 0x0250 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL0 0x0254 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD1 0x0258 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL1 0x025C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD2 0x0260 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL2 0x0264 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD3 0x0268 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL3 0x026C ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD4 0x0270 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL4 0x0274 ++#define BCMA_CORE_PCIE2_SYS_EQ_HEAD5 0x0278 ++#define BCMA_CORE_PCIE2_SYS_EQ_TAIL5 0x027C ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_EN 0x0330 ++#define BCMA_CORE_PCIE2_SYS_RC_INTX_CSR 0x0334 ++#define BCMA_CORE_PCIE2_SYS_MSI_REQ 0x0340 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_EN 0x0344 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR_CSR 0x0348 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR0 0x0350 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR1 0x0354 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR2 0x0358 ++#define BCMA_CORE_PCIE2_SYS_HOST_INTR3 0x035C ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN0 0x0360 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_EN1 0x0364 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR0 0x0370 ++#define BCMA_CORE_PCIE2_SYS_EP_INT_CSR1 0x0374 ++#define BCMA_CORE_PCIE2_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_0 0x0C00 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_1 0x0C04 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_2 0x0C08 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_3 0x0C0C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_4 0x0C10 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_5 0x0C14 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_6 0x0C18 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP0_7 0x0C1C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_0 0x0C20 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_1 0x0C24 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_2 0x0C28 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_3 0x0C2C ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_4 0x0C30 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_5 0x0C34 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_6 0x0C38 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP0_7 0x0C3C ++#define BCMA_CORE_PCIE2_FUNC0_IMAP1 0x0C80 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP1 0x0C88 ++#define BCMA_CORE_PCIE2_FUNC0_IMAP2 0x0CC0 ++#define BCMA_CORE_PCIE2_FUNC1_IMAP2 0x0CC8 ++#define BCMA_CORE_PCIE2_IARR0_LOWER 0x0D00 ++#define BCMA_CORE_PCIE2_IARR0_UPPER 0x0D04 ++#define BCMA_CORE_PCIE2_IARR1_LOWER 0x0D08 ++#define BCMA_CORE_PCIE2_IARR1_UPPER 0x0D0C ++#define BCMA_CORE_PCIE2_IARR2_LOWER 0x0D10 ++#define BCMA_CORE_PCIE2_IARR2_UPPER 0x0D14 ++#define BCMA_CORE_PCIE2_OARR0 0x0D20 ++#define BCMA_CORE_PCIE2_OARR1 0x0D28 ++#define BCMA_CORE_PCIE2_OARR2 0x0D30 ++#define BCMA_CORE_PCIE2_OMAP0_LOWER 0x0D40 ++#define BCMA_CORE_PCIE2_OMAP0_UPPER 0x0D44 ++#define BCMA_CORE_PCIE2_OMAP1_LOWER 0x0D48 ++#define BCMA_CORE_PCIE2_OMAP1_UPPER 0x0D4C ++#define BCMA_CORE_PCIE2_OMAP2_LOWER 0x0D50 ++#define BCMA_CORE_PCIE2_OMAP2_UPPER 0x0D54 ++#define BCMA_CORE_PCIE2_FUNC1_IARR1_SIZE 0x0D58 ++#define BCMA_CORE_PCIE2_FUNC1_IARR2_SIZE 0x0D5C ++#define BCMA_CORE_PCIE2_MEM_CONTROL 0x0F00 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG0 0x0F04 ++#define BCMA_CORE_PCIE2_MEM_ECC_ERRLOG1 0x0F08 ++#define BCMA_CORE_PCIE2_LINK_STATUS 0x0F0C ++#define BCMA_CORE_PCIE2_STRAP_STATUS 0x0F10 ++#define BCMA_CORE_PCIE2_RESET_STATUS 0x0F14 ++#define BCMA_CORE_PCIE2_RESETEN_IN_LINKDOWN 0x0F18 ++#define BCMA_CORE_PCIE2_MISC_INTR_EN 0x0F1C ++#define BCMA_CORE_PCIE2_TX_DEBUG_CFG 0x0F20 ++#define BCMA_CORE_PCIE2_MISC_CONFIG 0x0F24 ++#define BCMA_CORE_PCIE2_MISC_STATUS 0x0F28 ++#define BCMA_CORE_PCIE2_INTR_EN 0x0F30 ++#define BCMA_CORE_PCIE2_INTR_CLEAR 0x0F34 ++#define BCMA_CORE_PCIE2_INTR_STATUS 0x0F38 ++ ++/* PCIE gen2 config regs */ ++#define PCIE2_INTSTATUS 0x090 ++#define PCIE2_INTMASK 0x094 ++#define PCIE2_SBMBX 0x098 ++ ++#define PCIE2_PMCR_REFUP 0x1814 /* Trefup time */ ++ ++#define PCIE2_CAP_DEVSTSCTRL2_OFFSET 0xD4 ++#define PCIE2_CAP_DEVSTSCTRL2_LTRENAB 0x400 ++#define PCIE2_PVT_REG_PM_CLK_PERIOD 0x184c ++ ++struct bcma_drv_pcie2 { ++ struct bcma_device *core; ++}; ++ ++#define pcie2_read16(pcie2, offset) bcma_read16((pcie2)->core, offset) ++#define pcie2_read32(pcie2, offset) bcma_read32((pcie2)->core, offset) ++#define pcie2_write16(pcie2, offset, val) bcma_write16((pcie2)->core, offset, val) ++#define pcie2_write32(pcie2, offset, val) bcma_write32((pcie2)->core, offset, val) ++ ++#define pcie2_set32(pcie2, offset, set) bcma_set32((pcie2)->core, offset, set) ++#define pcie2_mask32(pcie2, offset, mask) bcma_mask32((pcie2)->core, offset, mask) ++ ++void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2); ++ ++#endif /* LINUX_BCMA_DRIVER_PCIE2_H_ */ -- cgit v1.2.3