162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Broadcom specific AMBA 362306a36Sopenharmony_ci * PCIe Gen 2 Core 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2014, Broadcom Corporation 662306a36Sopenharmony_ci * Copyright 2014, Rafał Miłecki <zajec5@gmail.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "bcma_private.h" 1262306a36Sopenharmony_ci#include <linux/bcma/bcma.h> 1362306a36Sopenharmony_ci#include <linux/pci.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/************************************************** 1662306a36Sopenharmony_ci * R/W ops. 1762306a36Sopenharmony_ci **************************************************/ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#if 0 2062306a36Sopenharmony_cistatic u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); 2362306a36Sopenharmony_ci pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); 2462306a36Sopenharmony_ci return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci#endif 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, 2962306a36Sopenharmony_ci u32 val) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); 3262306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/************************************************** 3662306a36Sopenharmony_ci * Init. 3762306a36Sopenharmony_ci **************************************************/ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, 4062306a36Sopenharmony_ci bool enable) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u32 val; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* restore back to default */ 4562306a36Sopenharmony_ci val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); 4662306a36Sopenharmony_ci val |= PCIE2_CLKC_DLYPERST; 4762306a36Sopenharmony_ci val &= ~PCIE2_CLKC_DISSPROMLD; 4862306a36Sopenharmony_ci if (enable) { 4962306a36Sopenharmony_ci val &= ~PCIE2_CLKC_DLYPERST; 5062306a36Sopenharmony_ci val |= PCIE2_CLKC_DISSPROMLD; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); 5362306a36Sopenharmony_ci /* flush */ 5462306a36Sopenharmony_ci return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci /* LTR0 */ 6062306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); 6162306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); 6262306a36Sopenharmony_ci /* LTR1 */ 6362306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); 6462306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); 6562306a36Sopenharmony_ci /* LTR2 */ 6662306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); 6762306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci u8 core_rev = pcie2->core->id.rev; 7362306a36Sopenharmony_ci u32 devstsctr2; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (core_rev < 2 || core_rev == 10 || core_rev > 13) 7662306a36Sopenharmony_ci return; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 7962306a36Sopenharmony_ci PCIE2_CAP_DEVSTSCTRL2_OFFSET); 8062306a36Sopenharmony_ci devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); 8162306a36Sopenharmony_ci if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { 8262306a36Sopenharmony_ci /* force the right LTR values */ 8362306a36Sopenharmony_ci bcma_core_pcie2_set_ltr_vals(pcie2); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* TODO: 8662306a36Sopenharmony_ci *si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* enable the LTR */ 9062306a36Sopenharmony_ci devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; 9162306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 9262306a36Sopenharmony_ci PCIE2_CAP_DEVSTSCTRL2_OFFSET); 9362306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* set the LTR state to be active */ 9662306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, 9762306a36Sopenharmony_ci PCIE2_LTR_ACTIVE); 9862306a36Sopenharmony_ci usleep_range(1000, 2000); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* set the LTR state to be sleep */ 10162306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, 10262306a36Sopenharmony_ci PCIE2_LTR_SLEEP); 10362306a36Sopenharmony_ci usleep_range(1000, 2000); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci u8 core_rev = pcie2->core->id.rev; 11062306a36Sopenharmony_ci bool pciewar160, pciewar162; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; 11362306a36Sopenharmony_ci pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || 11462306a36Sopenharmony_ci core_rev == 9 || core_rev == 11; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!pciewar160 && !pciewar162) 11762306a36Sopenharmony_ci return; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* TODO */ 12062306a36Sopenharmony_ci#if 0 12162306a36Sopenharmony_ci pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, 12262306a36Sopenharmony_ci PCIE_DISABLE_L1CLK_GATING); 12362306a36Sopenharmony_ci#if 0 12462306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 12562306a36Sopenharmony_ci PCIEGEN2_COE_PVT_TL_CTRL_0); 12662306a36Sopenharmony_ci pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 12762306a36Sopenharmony_ci ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci#endif 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); 13562306a36Sopenharmony_ci pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); 14162306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; 14762306a36Sopenharmony_ci u8 core_rev = pcie2->core->id.rev; 14862306a36Sopenharmony_ci u32 alp_khz, pm_value; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (core_rev <= 13) { 15162306a36Sopenharmony_ci alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; 15262306a36Sopenharmony_ci pm_value = (1000000 * 2) / alp_khz; 15362306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 15462306a36Sopenharmony_ci PCIE2_PVT_REG_PM_CLK_PERIOD); 15562306a36Sopenharmony_ci pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_civoid bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct bcma_bus *bus = pcie2->core->bus; 16262306a36Sopenharmony_ci struct bcma_chipinfo *ci = &bus->chipinfo; 16362306a36Sopenharmony_ci u32 tmp; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); 16662306a36Sopenharmony_ci if ((tmp & 0xe) >> 1 == 2) 16762306a36Sopenharmony_ci bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci switch (bus->chipinfo.id) { 17062306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4360: 17162306a36Sopenharmony_ci case BCMA_CHIP_ID_BCM4352: 17262306a36Sopenharmony_ci pcie2->reqsize = 1024; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci default: 17562306a36Sopenharmony_ci pcie2->reqsize = 128; 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) 18062306a36Sopenharmony_ci bcma_core_pcie2_war_delay_perst_enab(pcie2, true); 18162306a36Sopenharmony_ci bcma_core_pcie2_hw_ltr_war(pcie2); 18262306a36Sopenharmony_ci pciedev_crwlpciegen2(pcie2); 18362306a36Sopenharmony_ci pciedev_reg_pm_clk_period(pcie2); 18462306a36Sopenharmony_ci pciedev_crwlpciegen2_180(pcie2); 18562306a36Sopenharmony_ci pciedev_crwlpciegen2_182(pcie2); 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/************************************************** 18962306a36Sopenharmony_ci * Runtime ops. 19062306a36Sopenharmony_ci **************************************************/ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_civoid bcma_core_pcie2_up(struct bcma_drv_pcie2 *pcie2) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct bcma_bus *bus = pcie2->core->bus; 19562306a36Sopenharmony_ci struct pci_dev *dev = bus->host_pci; 19662306a36Sopenharmony_ci int err; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci err = pcie_set_readrq(dev, pcie2->reqsize); 19962306a36Sopenharmony_ci if (err) 20062306a36Sopenharmony_ci bcma_err(bus, "Error setting PCI_EXP_DEVCTL_READRQ: %d\n", err); 20162306a36Sopenharmony_ci} 202