1/** @file pcie_core.c
2 *
3 * Contains PCIe related functions that are shared between different driver models (e.g. firmware
4 * builds, DHD builds, BMAC builds), in order to avoid code duplication.
5 *
6 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
17 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 * $Id: pcie_core.c 444841 2013-12-21 04:32:29Z $
21 */
22
23#include <bcm_cfg.h>
24#include <typedefs.h>
25#include <bcmutils.h>
26#include <bcmdefs.h>
27#include <osl.h>
28#include <siutils.h>
29#include <hndsoc.h>
30#include <sbchipc.h>
31
32#include "pcie_core.h"
33
34/* local prototypes */
35
36/* local variables */
37
38/* function definitions */
39
40
41void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs)
42{
43	uint32 val, i, lsc;
44	uint16 cfg_offset[] = {PCIECFGREG_STATUS_CMD, PCIECFGREG_PM_CSR,
45		PCIECFGREG_MSI_CAP, PCIECFGREG_MSI_ADDR_L,
46		PCIECFGREG_MSI_ADDR_H, PCIECFGREG_MSI_DATA,
47		PCIECFGREG_LINK_STATUS_CTRL2, PCIECFGREG_RBAR_CTRL,
48		PCIECFGREG_PML1_SUB_CTRL1, PCIECFGREG_REG_BAR2_CONFIG,
49		PCIECFGREG_REG_BAR3_CONFIG};
50	uint32 origidx = si_coreidx(sih);
51
52	/* Disable/restore ASPM Control to protect the watchdog reset */
53	W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
54	lsc = R_REG(osh, &sbpcieregs->configdata);
55	val = lsc & (~PCIE_ASPM_ENAB);
56	W_REG(osh, &sbpcieregs->configdata, val);
57
58	si_setcore(sih, PCIE2_CORE_ID, 0);
59	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4);
60	OSL_DELAY(100000);
61#ifdef BCMQT
62	OSL_DELAY(200000);
63#endif /* BCMQT */
64
65	W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
66	W_REG(osh, &sbpcieregs->configdata, lsc);
67
68	/* Write configuration registers back to the shadow registers
69	 * cause shadow registers are cleared out after watchdog reset.
70	 */
71	for (i = 0; i < ARRAYSIZE(cfg_offset); i++) {
72		W_REG(osh, &sbpcieregs->configaddr, cfg_offset[i]);
73		val = R_REG(osh, &sbpcieregs->configdata);
74		W_REG(osh, &sbpcieregs->configdata, val);
75	}
76	si_setcoreidx(sih, origidx);
77}
78
79