diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2014-07-22 21:40:41 +0000 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2014-07-22 21:40:41 +0000 |
commit | 0d3690a202894a87e4cb1a1ba7542917f0b29a8d (patch) | |
tree | 8ca27050505b3eca1431c1e488d2661c39ab9fe7 /target/linux/generic/patches-3.14 | |
parent | 1e710a93ebe1110e356af2bb1b71c78b51c10607 (diff) | |
download | upstream-0d3690a202894a87e4cb1a1ba7542917f0b29a8d.tar.gz upstream-0d3690a202894a87e4cb1a1ba7542917f0b29a8d.tar.bz2 upstream-0d3690a202894a87e4cb1a1ba7542917f0b29a8d.zip |
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 <hauke@hauke-m.de>
SVN-Revision: 41804
Diffstat (limited to 'target/linux/generic/patches-3.14')
-rw-r--r-- | target/linux/generic/patches-3.14/020-ssb_update.patch | 235 | ||||
-rw-r--r-- | target/linux/generic/patches-3.14/025-bcma_backport.patch | 488 |
2 files changed, 697 insertions, 26 deletions
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 <zajec5@gmail.com> -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 <zajec5@gmail.com> - Acked-by: Hauke Mehrtens <hauke@hauke-m.de> - Signed-off-by: John W. Linville <linville@tuxdriver.com> - ---- 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 <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include <linux/bcma/bcma.h> ++ ++/************************************************** ++ * 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 <linux/bcma/bcma_driver_chipcommon.h> + #include <linux/bcma/bcma_driver_pci.h> ++#include <linux/bcma/bcma_driver_pcie2.h> + #include <linux/bcma/bcma_driver_mips.h> + #include <linux/bcma/bcma_driver_gmac_cmn.h> + #include <linux/ssb/ssb.h> /* 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_ */ |