hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* SPDX-License-Identifier: GPL-2.0 */
/** @file pcie_core.c
 *
 * Contains PCIe related functions that are shared between different driver models (e.g. firmware
 * builds, DHD builds, BMAC builds), in order to avoid code duplication.
 *
 * Copyright (C) 1999-2017, Broadcom Corporation
 * 
 *      Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2 (the "GPL"),
 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
 * following added to such license:
 * 
 *      As a special exception, the copyright holders of this software give you
 * permission to link this software with independent modules, and to copy and
 * distribute the resulting executable under terms of your choice, provided that
 * you also meet, for each linked independent module, the terms and conditions of
 * the license of that module.  An independent module is a module which is not
 * derived from this software.  The special exception does not apply to any
 * modifications of the software.
 * 
 *      Notwithstanding the above, under no circumstances may you combine this
 * software in any way with any other Broadcom software provided under a license
 * other than the GPL, without Broadcom's express prior written consent.
 *
 *
 * <<Broadcom-WL-IPTag/Open:>>
 *
 * $Id: pcie_core.c 658668 2016-09-09 00:42:11Z $
 */
 
#include <bcm_cfg.h>
#include <typedefs.h>
#include <bcmutils.h>
#include <bcmdefs.h>
#include <osl.h>
#include <siutils.h>
#include <hndsoc.h>
#include <sbchipc.h>
#include <pcicfg.h>
 
#include "pcie_core.h"
 
/* local prototypes */
 
/* local variables */
 
/* function definitions */
 
#ifdef BCMDRIVER
 
void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs)
{
   uint32 val, i, lsc;
   uint16 cfg_offset[] = {PCIECFGREG_STATUS_CMD, PCIECFGREG_PM_CSR,
       PCIECFGREG_MSI_CAP, PCIECFGREG_MSI_ADDR_L,
       PCIECFGREG_MSI_ADDR_H, PCIECFGREG_MSI_DATA,
       PCIECFGREG_LINK_STATUS_CTRL2, PCIECFGREG_RBAR_CTRL,
       PCIECFGREG_PML1_SUB_CTRL1, PCIECFGREG_REG_BAR2_CONFIG,
       PCIECFGREG_REG_BAR3_CONFIG};
   sbpcieregs_t *pcie = NULL;
   uint32 origidx = si_coreidx(sih);
 
   /* Switch to PCIE2 core */
   pcie = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0);
   BCM_REFERENCE(pcie);
   ASSERT(pcie != NULL);
 
   /* Disable/restore ASPM Control to protect the watchdog reset */
   W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
   lsc = R_REG(osh, &sbpcieregs->configdata);
   val = lsc & (~PCIE_ASPM_ENAB);
   W_REG(osh, &sbpcieregs->configdata, val);
 
   si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4);
   OSL_DELAY(100000);
 
   W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
   W_REG(osh, &sbpcieregs->configdata, lsc);
 
   if (sih->buscorerev <= 13) {
       /* Write configuration registers back to the shadow registers
        * cause shadow registers are cleared out after watchdog reset.
        */
       for (i = 0; i < ARRAYSIZE(cfg_offset); i++) {
           W_REG(osh, &sbpcieregs->configaddr, cfg_offset[i]);
           val = R_REG(osh, &sbpcieregs->configdata);
           W_REG(osh, &sbpcieregs->configdata, val);
       }
   }
   si_setcoreidx(sih, origidx);
}
 
 
/* CRWLPCIEGEN2-117 pcie_pipe_Iddq should be controlled
 * by the L12 state from MAC to save power by putting the
 * SerDes analog in IDDQ mode
 */
void  pcie_serdes_iddqdisable(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs)
{
   sbpcieregs_t *pcie = NULL;
   uint crwlpciegen2_117_disable = 0;
   uint32 origidx = si_coreidx(sih);
 
   crwlpciegen2_117_disable = PCIE_PipeIddqDisable0 | PCIE_PipeIddqDisable1;
   /* Switch to PCIE2 core */
   pcie = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0);
   BCM_REFERENCE(pcie);
   ASSERT(pcie != NULL);
 
   OR_REG(osh, &sbpcieregs->control,
       crwlpciegen2_117_disable);
 
   si_setcoreidx(sih, origidx);
}
 
#define PCIE_PMCR_REFUP_MASK 0x3f0001e0
#define PCIE_PMCR_REFEXT_MASK 0x400000
#define PCIE_PMCR_REFUP_100US 0x38000080
#define PCIE_PMCR_REFEXT_100US 0x400000
 
/* Set PCIE TRefUp time to 100us */
void pcie_set_trefup_time_100us(si_t *sih)
{
   si_corereg(sih, sih->buscoreidx,
       OFFSETOF(sbpcieregs_t, configaddr), ~0, PCI_PMCR_REFUP);
   si_corereg(sih, sih->buscoreidx,
       OFFSETOF(sbpcieregs_t, configdata), PCIE_PMCR_REFUP_MASK, PCIE_PMCR_REFUP_100US);
 
   si_corereg(sih, sih->buscoreidx,
       OFFSETOF(sbpcieregs_t, configaddr), ~0, PCI_PMCR_REFUP_EXT);
   si_corereg(sih, sih->buscoreidx,
       OFFSETOF(sbpcieregs_t, configdata), PCIE_PMCR_REFEXT_MASK, PCIE_PMCR_REFEXT_100US);
}
#endif /* BCMDRIVER */