1296077Sadrian/*-
2296077Sadrian * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3296077Sadrian * All rights reserved.
4296077Sadrian *
5296077Sadrian * Redistribution and use in source and binary forms, with or without
6296077Sadrian * modification, are permitted provided that the following conditions
7296077Sadrian * are met:
8296077Sadrian * 1. Redistributions of source code must retain the above copyright
9296077Sadrian *    notice, this list of conditions and the following disclaimer,
10296077Sadrian *    without modification.
11296077Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12296077Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13296077Sadrian *    redistribution must be conditioned upon including a substantially
14296077Sadrian *    similar Disclaimer requirement for further binary redistribution.
15296077Sadrian *
16296077Sadrian * NO WARRANTY
17296077Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18296077Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19296077Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20296077Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21296077Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22296077Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23296077Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24296077Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25296077Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26296077Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27296077Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28296077Sadrian */
29296077Sadrian
30296077Sadrian#include <sys/cdefs.h>
31296077Sadrian__FBSDID("$FreeBSD$");
32296077Sadrian
33296077Sadrian/*
34298479Sadrian * Broadcom BHND PCI/PCIe-Gen1 PCI-Host Bridge.
35296077Sadrian *
36298479Sadrian * This driver handles all interactions with PCI bridge cores operating in
37298479Sadrian * endpoint mode.
38298479Sadrian *
39298479Sadrian * Host-level PCI operations are handled at the bhndb bridge level by the
40298479Sadrian * bhndb_pci driver.
41296077Sadrian */
42296077Sadrian
43296077Sadrian#include <sys/param.h>
44296077Sadrian#include <sys/kernel.h>
45298479Sadrian
46298479Sadrian#include <sys/malloc.h>
47298479Sadrian
48296077Sadrian#include <sys/bus.h>
49296077Sadrian#include <sys/module.h>
50298479Sadrian
51296077Sadrian#include <sys/systm.h>
52296077Sadrian
53296077Sadrian#include <machine/bus.h>
54296077Sadrian#include <sys/rman.h>
55296077Sadrian#include <machine/resource.h>
56296077Sadrian
57296077Sadrian#include <dev/bhnd/bhnd.h>
58296077Sadrian
59300015Sadrian#include <dev/pci/pcireg.h>
60300015Sadrian#include <dev/pci/pcivar.h>
61300015Sadrian
62300015Sadrian#include <dev/bhnd/cores/chipc/chipc.h>
63300015Sadrian#include <dev/bhnd/cores/chipc/chipcreg.h>
64300015Sadrian
65298479Sadrian#include "bhnd_pcireg.h"
66298479Sadrian#include "bhnd_pci_hostbvar.h"
67298479Sadrian
68298479Sadrianstatic const struct bhnd_device_quirk bhnd_pci_quirks[];
69298479Sadrianstatic const struct bhnd_device_quirk bhnd_pcie_quirks[];
70298479Sadrian
71300015Sadrian/* Device driver work-around variations */
72300015Sadriantypedef enum {
73300015Sadrian	BHND_PCI_WAR_ATTACH,	/**< apply attach workarounds */
74300015Sadrian	BHND_PCI_WAR_RESUME,	/**< apply resume workarounds */
75300015Sadrian	BHND_PCI_WAR_SUSPEND,	/**< apply suspend workarounds */
76300015Sadrian	BHND_PCI_WAR_DETACH	/**< apply detach workarounds */
77300015Sadrian} bhnd_pci_war_state;
78300015Sadrian
79298479Sadrianstatic int	bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc);
80300015Sadrianstatic int	bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc,
81300015Sadrian		    bhnd_pci_war_state state);
82300015Sadrianstatic int	bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc,
83300015Sadrian		    bhnd_pci_war_state state);
84298479Sadrian
85298479Sadrian/*
86298479Sadrian * device/quirk tables
87298479Sadrian */
88300015Sadrian
89300628Sadrian#define	BHND_PCI_DEV(_core, _quirks)		\
90301697Slandonf	BHND_DEVICE(BCM, _core, NULL, _quirks, BHND_DF_HOSTB)
91300015Sadrian
92298479Sadrianstatic const struct bhnd_device bhnd_pci_devs[] = {
93300628Sadrian	BHND_PCI_DEV(PCI,	bhnd_pci_quirks),
94300628Sadrian	BHND_PCI_DEV(PCIE,	bhnd_pcie_quirks),
95298479Sadrian	BHND_DEVICE_END
96296077Sadrian};
97296077Sadrian
98298479Sadrianstatic const struct bhnd_device_quirk bhnd_pci_quirks[] = {
99300628Sadrian	/* core revision quirks */
100300628Sadrian	BHND_CORE_QUIRK	(HWREV_ANY,	BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST),
101300628Sadrian	BHND_CORE_QUIRK	(HWREV_GTE(11),	BHND_PCI_QUIRK_SBTOPCI2_READMULTI |
102300628Sadrian					BHND_PCI_QUIRK_CLKRUN_DSBL),
103298479Sadrian
104300015Sadrian	/* BCM4321CB2 boards that require 960ns latency timer override */
105300628Sadrian	BHND_BOARD_QUIRK(BCM4321CB2,	BHND_PCI_QUIRK_960NS_LATTIM_OVR),
106300628Sadrian	BHND_BOARD_QUIRK(BCM4321CB2_AG,	BHND_PCI_QUIRK_960NS_LATTIM_OVR),
107300015Sadrian
108300628Sadrian	BHND_DEVICE_QUIRK_END
109300015Sadrian};
110300015Sadrian
111298479Sadrianstatic const struct bhnd_device_quirk bhnd_pcie_quirks[] = {
112300628Sadrian	/* core revision quirks */
113300628Sadrian	BHND_CORE_QUIRK	(HWREV_EQ (0),	BHND_PCIE_QUIRK_SDR9_L0s_HANG),
114300628Sadrian	BHND_CORE_QUIRK	(HWREV_RANGE(0,1),
115300628Sadrian	    BHND_PCIE_QUIRK_UR_STATUS_FIX),
116298479Sadrian
117300628Sadrian	BHND_CORE_QUIRK	(HWREV_EQ (1),	BHND_PCIE_QUIRK_PCIPM_REQEN),
118298479Sadrian
119300628Sadrian	BHND_CORE_QUIRK	(HWREV_RANGE(3,5),
120300628Sadrian	    BHND_PCIE_QUIRK_ASPM_OVR | BHND_PCIE_QUIRK_SDR9_POLARITY |
121300628Sadrian	    BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY),
122300015Sadrian
123300628Sadrian	BHND_CORE_QUIRK	(HWREV_LTE(6),	BHND_PCIE_QUIRK_L1_IDLE_THRESH),
124300628Sadrian	BHND_CORE_QUIRK	(HWREV_GTE(6),	BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET),
125300628Sadrian	BHND_CORE_QUIRK	(HWREV_EQ (7),	BHND_PCIE_QUIRK_SERDES_NOPLLDOWN),
126300628Sadrian	BHND_CORE_QUIRK	(HWREV_GTE(8),	BHND_PCIE_QUIRK_L1_TIMER_PERF),
127300015Sadrian
128300628Sadrian	BHND_CORE_QUIRK	(HWREV_LTE(17),	BHND_PCIE_QUIRK_MAX_MRRS_128),
129298479Sadrian
130299996Sadrian	/* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed
131299996Sadrian	 * to be set. */
132300628Sadrian	{{ BHND_MATCH_BOARD_VENDOR	(PCI_VENDOR_APPLE),
133300628Sadrian	   BHND_MATCH_BOARD_REV		(HWREV_LTE(0x71)),
134300628Sadrian	   BHND_MATCH_SROMREV		(EQ(4)) },
135300628Sadrian		BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN },
136299996Sadrian
137300015Sadrian	/* Apple BCM4322 boards that require 700mV SerDes TX drive strength. */
138300628Sadrian	{{ BHND_CHIP_ID(BCM4322),
139300628Sadrian	   BHND_MATCH_BOARD(PCI_VENDOR_APPLE, BCM94322X9), },
140300628Sadrian		BHND_PCIE_QUIRK_SERDES_TXDRV_700MV },
141300015Sadrian
142300015Sadrian	/* Apple BCM4331 board-specific quirks */
143300628Sadrian#define	BHND_A4331_QUIRK(_board, ...)	\
144300628Sadrian	{{ BHND_CHIP_ID(BCM4331),		\
145300628Sadrian	    BHND_MATCH_BOARD(PCI_VENDOR_APPLE, _board) }, __VA_ARGS__ }
146300015Sadrian
147300628Sadrian	BHND_A4331_QUIRK(BCM94331X19,	BHND_PCIE_QUIRK_SERDES_TXDRV_MAX |
148300628Sadrian					BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
149300015Sadrian
150300628Sadrian	BHND_A4331_QUIRK(BCM94331X28,	BHND_PCIE_QUIRK_SERDES_TXDRV_MAX |
151300628Sadrian					BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
152300015Sadrian
153300628Sadrian	BHND_A4331_QUIRK(BCM94331X28B,	BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
154300628Sadrian
155300628Sadrian	BHND_A4331_QUIRK(BCM94331X29B,	BHND_PCIE_QUIRK_SERDES_TXDRV_MAX |
156300628Sadrian					BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
157300628Sadrian
158300628Sadrian	BHND_A4331_QUIRK(BCM94331X19C,	BHND_PCIE_QUIRK_SERDES_TXDRV_MAX |
159300628Sadrian					BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
160300015Sadrian
161300628Sadrian	BHND_A4331_QUIRK(BCM94331X29D,	BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
162300015Sadrian
163300628Sadrian	BHND_A4331_QUIRK(BCM94331X33,	BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
164300628Sadrian
165300628Sadrian#undef BHND_A4331_QUIRK
166300628Sadrian
167300628Sadrian	BHND_DEVICE_QUIRK_END
168299996Sadrian};
169299996Sadrian
170300628Sadrian
171298479Sadrian#define	BHND_PCI_SOFTC(_sc)	(&((_sc)->common))
172298479Sadrian
173298479Sadrian#define	BHND_PCI_READ_2(_sc, _reg)		\
174298479Sadrian	bhnd_bus_read_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg))
175298479Sadrian
176298479Sadrian#define	BHND_PCI_READ_4(_sc, _reg)		\
177298479Sadrian	bhnd_bus_read_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg))
178298479Sadrian
179298479Sadrian#define	BHND_PCI_WRITE_2(_sc, _reg, _val)	\
180298479Sadrian	bhnd_bus_write_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val))
181298479Sadrian
182298479Sadrian#define	BHND_PCI_WRITE_4(_sc, _reg, _val)	\
183298479Sadrian	bhnd_bus_write_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val))
184298479Sadrian
185298479Sadrian#define	BHND_PCI_PROTO_READ_4(_sc, _reg)	\
186298479Sadrian	bhnd_pcie_read_proto_reg(BHND_PCI_SOFTC(_sc), (_reg))
187298479Sadrian
188298479Sadrian#define	BHND_PCI_PROTO_WRITE_4(_sc, _reg, _val)	\
189298479Sadrian	bhnd_pcie_write_proto_reg(BHND_PCI_SOFTC(_sc), (_reg), (_val))
190298479Sadrian
191298479Sadrian#define	BHND_PCI_MDIO_READ(_sc, _phy, _reg)	\
192298479Sadrian	bhnd_pcie_mdio_read(BHND_PCI_SOFTC(_sc), (_phy), (_reg))
193298479Sadrian
194298479Sadrian#define	BHND_PCI_MDIO_WRITE(_sc, _phy, _reg, _val)		\
195298479Sadrian	bhnd_pcie_mdio_write(BHND_PCI_SOFTC(_sc), (_phy), (_reg), (_val))
196298479Sadrian
197300015Sadrian#define	BHND_PCI_MDIO_READ_EXT(_sc, _phy, _devaddr, _reg)		\
198300015Sadrian	bhnd_pcie_mdio_read_ext(BHND_PCI_SOFTC(_sc), (_phy), (_devaddr), (_reg))
199300015Sadrian
200300015Sadrian#define	BHND_PCI_MDIO_WRITE_EXT(_sc, _phy, _devaddr, _reg, _val)	\
201300015Sadrian	bhnd_pcie_mdio_write_ext(BHND_PCI_SOFTC(_sc), (_phy),		\
202300015Sadrian	    (_devaddr), (_reg), (_val))
203300015Sadrian
204298479Sadrian#define	BPCI_REG_SET(_regv, _attr, _val)	\
205298479Sadrian	BHND_PCI_REG_SET((_regv), BHND_ ## _attr, (_val))
206298479Sadrian
207298479Sadrian#define	BPCI_REG_GET(_regv, _attr)	\
208298479Sadrian	BHND_PCI_REG_GET((_regv), BHND_ ## _attr)
209298479Sadrian
210298479Sadrian#define	BPCI_CMN_REG_SET(_regv, _attr, _val)			\
211298479Sadrian	BHND_PCI_CMN_REG_SET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv),	\
212298479Sadrian	    BHND_ ## _attr, (_val))
213298479Sadrian
214298479Sadrian#define	BPCI_CMN_REG_GET(_regv, _attr)				\
215298479Sadrian	BHND_PCI_CMN_REG_GET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv),	\
216298479Sadrian	    BHND_ ## _attr)
217298479Sadrian
218296077Sadrianstatic int
219298479Sadrianbhnd_pci_hostb_attach(device_t dev)
220296077Sadrian{
221298479Sadrian	struct bhnd_pcihb_softc	*sc;
222298479Sadrian	int			 error;
223298479Sadrian
224298479Sadrian	sc = device_get_softc(dev);
225300015Sadrian	sc->dev = dev;
226298479Sadrian	sc->quirks = bhnd_device_quirks(dev, bhnd_pci_devs,
227298479Sadrian	    sizeof(bhnd_pci_devs[0]));
228298479Sadrian
229300015Sadrian	/* Find the host PCI bridge device */
230300015Sadrian	sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci"));
231300015Sadrian	if (sc->pci_dev == NULL) {
232300015Sadrian		device_printf(dev, "parent pci bridge device not found\n");
233300015Sadrian		return (ENXIO);
234300015Sadrian	}
235300015Sadrian
236300015Sadrian	/* Common setup */
237298479Sadrian	if ((error = bhnd_pci_generic_attach(dev)))
238298479Sadrian		return (error);
239298479Sadrian
240298479Sadrian	/* Apply early single-shot work-arounds */
241300015Sadrian	if ((error = bhnd_pci_wars_early_once(sc)))
242300015Sadrian		goto failed;
243296077Sadrian
244298479Sadrian	/* Apply attach/resume work-arounds */
245300015Sadrian	if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_ATTACH)))
246300015Sadrian		goto failed;
247296077Sadrian
248298479Sadrian	return (0);
249300015Sadrian
250300015Sadrianfailed:
251300015Sadrian	bhnd_pci_generic_detach(dev);
252300015Sadrian	return (error);
253296077Sadrian}
254296077Sadrian
255296077Sadrianstatic int
256298479Sadrianbhnd_pci_hostb_detach(device_t dev)
257296077Sadrian{
258298479Sadrian	struct bhnd_pcihb_softc *sc;
259298479Sadrian	int			 error;
260298479Sadrian
261298479Sadrian	sc = device_get_softc(dev);
262298479Sadrian
263298479Sadrian	/* Apply suspend/detach work-arounds */
264300015Sadrian	if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_DETACH)))
265298479Sadrian		return (error);
266298479Sadrian
267298479Sadrian	return (bhnd_pci_generic_detach(dev));
268296077Sadrian}
269296077Sadrian
270296077Sadrianstatic int
271298479Sadrianbhnd_pci_hostb_suspend(device_t dev)
272296077Sadrian{
273298479Sadrian	struct bhnd_pcihb_softc *sc;
274298479Sadrian	int			 error;
275298479Sadrian
276298479Sadrian	sc = device_get_softc(dev);
277298479Sadrian
278298479Sadrian	/* Apply suspend/detach work-arounds */
279300015Sadrian	if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_SUSPEND)))
280298479Sadrian		return (error);
281298479Sadrian
282298479Sadrian	return (bhnd_pci_generic_suspend(dev));
283298479Sadrian}
284298479Sadrian
285298479Sadrianstatic int
286298479Sadrianbhnd_pci_hostb_resume(device_t dev)
287298479Sadrian{
288298479Sadrian	struct bhnd_pcihb_softc	*sc;
289298479Sadrian	int			 error;
290298479Sadrian
291298479Sadrian	sc = device_get_softc(dev);
292298479Sadrian
293298479Sadrian	if ((error = bhnd_pci_generic_resume(dev)))
294298479Sadrian		return (error);
295298479Sadrian
296298479Sadrian	/* Apply attach/resume work-arounds */
297300015Sadrian	if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_RESUME))) {
298298479Sadrian		bhnd_pci_generic_detach(dev);
299298479Sadrian		return (error);
300298479Sadrian	}
301298479Sadrian
302296077Sadrian	return (0);
303296077Sadrian}
304296077Sadrian
305298479Sadrian/**
306298479Sadrian * Apply any hardware work-arounds that must be executed exactly once, early in
307298479Sadrian * the attach process.
308298479Sadrian *
309298479Sadrian * This must be called after core enumeration and discovery of all applicable
310298479Sadrian * quirks, but prior to probe/attach of any cores, parsing of
311298479Sadrian * SPROM, etc.
312298479Sadrian */
313296077Sadrianstatic int
314298479Sadrianbhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc)
315296077Sadrian{
316300015Sadrian	int error;
317300015Sadrian
318300015Sadrian	/* Set PCI latency timer */
319300015Sadrian	if (sc->quirks & BHND_PCI_QUIRK_960NS_LATTIM_OVR) {
320300015Sadrian		pci_write_config(sc->pci_dev, PCIR_LATTIMER, 0x20 /* 960ns */,
321300015Sadrian		    1);
322300015Sadrian	}
323300015Sadrian
324300015Sadrian	/* Determine whether ASPM/CLKREQ should be forced on, or forced off. */
325300015Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
326300015Sadrian		struct bhnd_board_info	board;
327300015Sadrian		bool			aspm_en;
328300015Sadrian
329300015Sadrian		/* Fetch board info */
330300015Sadrian		if ((error = bhnd_read_board_info(sc->dev, &board)))
331300015Sadrian			return (error);
332300015Sadrian
333300015Sadrian		/* Check board flags */
334300015Sadrian		aspm_en = true;
335300015Sadrian		if (board.board_flags2 & BHND_BFL2_PCIEWAR_OVR)
336300015Sadrian			aspm_en = false;
337300015Sadrian
338300015Sadrian		/* Early Apple devices did not (but should have) set
339300015Sadrian		 * BHND_BFL2_PCIEWAR_OVR in SPROM. */
340300015Sadrian		if (sc->quirks & BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN)
341300015Sadrian			aspm_en = false;
342300015Sadrian
343300015Sadrian		sc->aspm_quirk_override.aspm_en = aspm_en;
344300015Sadrian	}
345300015Sadrian
346298479Sadrian	/* Determine correct polarity by observing the attach-time PCIe PHY
347298479Sadrian	 * link status. This is used later to reset/force the SerDes
348298479Sadrian	 * polarity */
349298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) {
350298479Sadrian		uint32_t st;
351298479Sadrian		bool inv;
352298479Sadrian
353298479Sadrian		st = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_PLP_STATUSREG);
354298479Sadrian		inv = ((st & BHND_PCIE_PLP_POLARITY_INV) != 0);
355298479Sadrian		sc->sdr9_quirk_polarity.inv = inv;
356298479Sadrian	}
357298479Sadrian
358300015Sadrian	/* Override maximum read request size */
359300015Sadrian	if (bhnd_get_class(sc->dev) == BHND_DEVCLASS_PCIE) {
360300015Sadrian		int	msize;
361300015Sadrian
362300015Sadrian		msize = 128; /* compatible with all PCIe-G1 core revisions */
363300015Sadrian		if (sc->quirks & BHND_PCIE_QUIRK_DEFAULT_MRRS_512)
364300015Sadrian			msize = 512;
365300015Sadrian
366300015Sadrian		if (pci_set_max_read_req(sc->pci_dev, msize) == 0)
367300015Sadrian			panic("set mrrs on non-PCIe device");
368300015Sadrian	}
369300015Sadrian
370296077Sadrian	return (0);
371296077Sadrian}
372296077Sadrian
373298479Sadrian/**
374298479Sadrian * Apply any hardware workarounds that are required upon attach or resume
375298479Sadrian * of the bridge device.
376298479Sadrian */
377296077Sadrianstatic int
378300015Sadrianbhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state)
379296077Sadrian{
380298479Sadrian	/* Note that the order here matters; these work-arounds
381298479Sadrian	 * should not be re-ordered without careful review of their
382298479Sadrian	 * interdependencies */
383298479Sadrian
384298479Sadrian	/* Enable PCI prefetch/burst/readmulti flags */
385298479Sadrian	if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST ||
386298479Sadrian	    sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI)
387298479Sadrian	{
388298479Sadrian		uint32_t sbp2;
389298479Sadrian		sbp2 = BHND_PCI_READ_4(sc, BHND_PCI_SBTOPCI2);
390298479Sadrian
391298479Sadrian		if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST)
392298479Sadrian			sbp2 |= (BHND_PCI_SBTOPCI_PREF|BHND_PCI_SBTOPCI_BURST);
393298479Sadrian
394298479Sadrian		if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI)
395298479Sadrian			sbp2 |= BHND_PCI_SBTOPCI_RC_READMULTI;
396298479Sadrian
397298479Sadrian		BHND_PCI_WRITE_4(sc, BHND_PCI_SBTOPCI2, sbp2);
398298479Sadrian	}
399298479Sadrian
400298479Sadrian	/* Disable PCI CLKRUN# */
401298479Sadrian	if (sc->quirks & BHND_PCI_QUIRK_CLKRUN_DSBL) {
402298479Sadrian		uint32_t ctl;
403298479Sadrian
404298479Sadrian		ctl = BHND_PCI_READ_4(sc, BHND_PCI_CLKRUN_CTL);
405298479Sadrian		ctl |= BHND_PCI_CLKRUN_DSBL;
406298479Sadrian		BHND_PCI_WRITE_4(sc, BHND_PCI_CLKRUN_CTL, ctl);
407298479Sadrian	}
408298479Sadrian
409298479Sadrian	/* Enable TLP unmatched address handling work-around */
410298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_UR_STATUS_FIX) {
411298479Sadrian		uint32_t wrs;
412298479Sadrian		wrs = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG);
413298479Sadrian		wrs |= BHND_PCIE_TLP_WORKAROUND_URBIT;
414298479Sadrian		BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG, wrs);
415298479Sadrian	}
416298479Sadrian
417298479Sadrian	/* Adjust SerDes CDR tuning to ensure that CDR is stable before sending
418298479Sadrian	 * data during L0s to L0 exit transitions. */
419298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SDR9_L0s_HANG) {
420298479Sadrian		uint16_t sdv;
421298479Sadrian
422298479Sadrian		/* Set RX track/acquire timers to 2.064us/40.96us */
423298479Sadrian		sdv = BPCI_REG_SET(0, PCIE_SDR9_RX_TIMER1_LKTRK, (2064/16));
424298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_TIMER1_LKACQ,
425298479Sadrian		    (40960/1024));
426298479Sadrian		BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX,
427298479Sadrian		    BHND_PCIE_SDR9_RX_TIMER1, sdv);
428298479Sadrian
429298479Sadrian		/* Apply CDR frequency workaround */
430298479Sadrian		sdv = BHND_PCIE_SDR9_RX_CDR_FREQ_OVR_EN;
431298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDR_FREQ_OVR, 0x0);
432298479Sadrian		BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX,
433298479Sadrian		    BHND_PCIE_SDR9_RX_CDR, sdv);
434298479Sadrian
435298479Sadrian		/* Apply CDR BW tunings */
436298479Sadrian		sdv = 0;
437298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGTRK, 0x2);
438298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGACQ, 0x4);
439298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPTRK, 0x6);
440298479Sadrian		sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPACQ, 0x6);
441298479Sadrian		BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX,
442298479Sadrian		    BHND_PCIE_SDR9_RX_CDRBW, sdv);
443298479Sadrian	}
444298479Sadrian
445298479Sadrian	/* Force correct SerDes polarity */
446298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) {
447298479Sadrian		uint16_t	rxctl;
448298479Sadrian
449298479Sadrian		rxctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_TXRX,
450298479Sadrian		    BHND_PCIE_SDR9_RX_CTRL);
451298479Sadrian
452298479Sadrian		rxctl |= BHND_PCIE_SDR9_RX_CTRL_FORCE;
453298479Sadrian		if (sc->sdr9_quirk_polarity.inv)
454298479Sadrian			rxctl |= BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV;
455298479Sadrian		else
456298479Sadrian			rxctl &= ~BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV;
457298479Sadrian
458298479Sadrian		BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX,
459298479Sadrian		    BHND_PCIE_SDR9_RX_CTRL, rxctl);
460298479Sadrian	}
461298479Sadrian
462298479Sadrian	/* Disable startup retry on PLL frequency detection failure */
463298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY) {
464298479Sadrian		uint16_t	pctl;
465298479Sadrian
466298479Sadrian		pctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_PLL,
467298479Sadrian		    BHND_PCIE_SDR9_PLL_CTRL);
468298479Sadrian
469298479Sadrian		pctl &= ~BHND_PCIE_SDR9_PLL_CTRL_FREQDET_EN;
470298479Sadrian		BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_PLL,
471298479Sadrian		    BHND_PCIE_SDR9_PLL_CTRL, pctl);
472298479Sadrian	}
473298479Sadrian
474298479Sadrian	/* Explicitly enable PCI-PM */
475298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_PCIPM_REQEN) {
476298479Sadrian		uint32_t lcreg;
477298479Sadrian		lcreg = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_LCREG);
478298479Sadrian		lcreg |= BHND_PCIE_DLLP_LCREG_PCIPM_EN;
479298479Sadrian		BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_LCREG, lcreg);
480298479Sadrian	}
481298479Sadrian
482298479Sadrian	/* Adjust L1 timer to fix slow L1->L0 transitions */
483298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_L1_IDLE_THRESH) {
484298479Sadrian		uint32_t pmt;
485298479Sadrian		pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG);
486298479Sadrian		pmt = BPCI_REG_SET(pmt, PCIE_L1THRESHOLDTIME,
487298479Sadrian		    BHND_PCIE_L1THRESHOLD_WARVAL);
488298479Sadrian		BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt);
489298479Sadrian	}
490298479Sadrian
491298479Sadrian	/* Extend L1 timer for better performance.
492298479Sadrian	 * TODO: We could enable/disable this on demand for better power
493298479Sadrian	 * savings if we tie this to HT clock request handling */
494298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) {
495298479Sadrian		uint32_t pmt;
496298479Sadrian		pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG);
497298479Sadrian		pmt |= BHND_PCIE_ASPMTIMER_EXTEND;
498298479Sadrian		BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt);
499298479Sadrian	}
500298479Sadrian
501300015Sadrian	/* Override ASPM/ECPM settings in SPROM shadow and PCIER_LINK_CTL */
502300015Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
503300015Sadrian		bus_size_t	reg;
504300015Sadrian		uint16_t	cfg;
505300015Sadrian
506300015Sadrian		/* Set ASPM L1/L0s flags in SPROM shadow */
507300015Sadrian		reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_ASPM_OFFSET;
508300015Sadrian		cfg = BHND_PCI_READ_2(sc, reg);
509300015Sadrian
510300015Sadrian		if (sc->aspm_quirk_override.aspm_en)
511300015Sadrian			cfg |= BHND_PCIE_SRSH_ASPM_ENB;
512300015Sadrian		else
513300015Sadrian			cfg &= ~BHND_PCIE_SRSH_ASPM_ENB;
514300015Sadrian
515300015Sadrian		BHND_PCI_WRITE_2(sc, reg, cfg);
516300015Sadrian
517300015Sadrian
518300015Sadrian		/* Set ASPM/ECPM (CLKREQ) flags in PCIe link control register */
519300015Sadrian		cfg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2);
520300015Sadrian
521300015Sadrian		if (sc->aspm_quirk_override.aspm_en)
522300015Sadrian			cfg |= PCIEM_LINK_CTL_ASPMC;
523300015Sadrian		else
524300015Sadrian			cfg &= ~PCIEM_LINK_CTL_ASPMC;
525300015Sadrian
526300015Sadrian		cfg &= ~PCIEM_LINK_CTL_ECPM;		/* CLKREQ# */
527300015Sadrian
528300015Sadrian		pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, cfg, 2);
529300015Sadrian
530300015Sadrian		/* Set CLKREQ (ECPM) flags in SPROM shadow */
531300015Sadrian		reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_CLKREQ_OFFSET_R5;
532300015Sadrian		cfg = BHND_PCI_READ_2(sc, reg);
533300015Sadrian
534300015Sadrian		if (sc->aspm_quirk_override.aspm_en)
535300015Sadrian			cfg |= BHND_PCIE_SRSH_CLKREQ_ENB;
536300015Sadrian		else
537300015Sadrian			cfg &= ~BHND_PCIE_SRSH_CLKREQ_ENB;
538300015Sadrian
539300015Sadrian		BHND_PCI_WRITE_2(sc, reg, cfg);
540300015Sadrian	}
541300015Sadrian
542298479Sadrian	/* Enable L23READY_EXIT_NOPRST if not already set in SPROM. */
543298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET) {
544298479Sadrian		bus_size_t	reg;
545298479Sadrian		uint16_t	cfg;
546298479Sadrian
547298479Sadrian		/* Fetch the misc cfg flags from SPROM */
548298479Sadrian		reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_PCIE_MISC_CONFIG;
549298479Sadrian		cfg = BHND_PCI_READ_2(sc, reg);
550298479Sadrian
551298479Sadrian		/* Write EXIT_NOPRST flag if not already set in SPROM */
552298479Sadrian		if (!(cfg & BHND_PCIE_SRSH_L23READY_EXIT_NOPRST)) {
553298479Sadrian			cfg |= BHND_PCIE_SRSH_L23READY_EXIT_NOPRST;
554298479Sadrian			BHND_PCI_WRITE_2(sc, reg, cfg);
555298479Sadrian		}
556298479Sadrian	}
557298479Sadrian
558300015Sadrian	/* Disable SerDes PLL down */
559300015Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SERDES_NOPLLDOWN) {
560300015Sadrian		device_t	bhnd, chipc;
561300015Sadrian		bus_size_t	reg;
562300015Sadrian
563300015Sadrian		bhnd = device_get_parent(sc->dev);
564300015Sadrian		chipc = bhnd_find_child(bhnd, BHND_DEVCLASS_CC, 0);
565300015Sadrian		KASSERT(chipc != NULL, ("missing chipcommon device"));
566300015Sadrian
567300015Sadrian		/* Write SerDes PLL disable flag to the ChipCommon core */
568300015Sadrian		BHND_CHIPC_WRITE_CHIPCTRL(chipc, CHIPCTRL_4321_PLL_DOWN,
569300015Sadrian		    CHIPCTRL_4321_PLL_DOWN);
570300015Sadrian
571300015Sadrian		/* Clear SPROM shadow backdoor register */
572300015Sadrian		reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_BD_OFFSET;
573300015Sadrian		BHND_PCI_WRITE_2(sc, reg, 0);
574300015Sadrian	}
575300015Sadrian
576300015Sadrian	/* Adjust TX drive strength and pre-emphasis coefficient */
577300015Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST) {
578300015Sadrian		uint16_t txdrv;
579300015Sadrian
580300015Sadrian		/* Fetch current TX driver parameters */
581300015Sadrian		txdrv = BHND_PCI_MDIO_READ_EXT(sc, BHND_PCIE_PHYADDR_SD,
582300015Sadrian		    BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER);
583300015Sadrian
584300015Sadrian		/* Set 700mV drive strength */
585300015Sadrian		if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_700MV) {
586300015Sadrian			txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF,
587300015Sadrian			    BHND_PCIE_APPLE_TX_P2_COEFF_700MV);
588300015Sadrian
589300015Sadrian			txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER,
590300015Sadrian			    BHND_PCIE_APPLE_TX_IDRIVER_700MV);
591300015Sadrian		}
592300015Sadrian
593300015Sadrian		/* ... or, set max drive strength */
594300015Sadrian		if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_MAX) {
595300015Sadrian			txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF,
596300015Sadrian			    BHND_PCIE_APPLE_TX_P2_COEFF_MAX);
597300015Sadrian
598300015Sadrian			txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER,
599300015Sadrian			    BHND_PCIE_APPLE_TX_IDRIVER_MAX);
600300015Sadrian		}
601300015Sadrian
602300015Sadrian		BHND_PCI_MDIO_WRITE_EXT(sc, BHND_PCIE_PHYADDR_SD,
603300015Sadrian		    BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER, txdrv);
604300015Sadrian	}
605300015Sadrian
606296077Sadrian	return (0);
607296077Sadrian}
608296077Sadrian
609298479Sadrian/**
610298479Sadrian * Apply any hardware workarounds that are required upon detach or suspend
611298479Sadrian * of the bridge device.
612298479Sadrian */
613298479Sadrianstatic int
614300015Sadrianbhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state)
615300015Sadrian{
616298479Sadrian	/* Reduce L1 timer for better power savings.
617298479Sadrian	 * TODO: We could enable/disable this on demand for better power
618298479Sadrian	 * savings if we tie this to HT clock request handling */
619298479Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) {
620298479Sadrian		uint32_t pmt;
621298479Sadrian		pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG);
622298479Sadrian		pmt &= ~BHND_PCIE_ASPMTIMER_EXTEND;
623298479Sadrian		BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt);
624298479Sadrian	}
625298479Sadrian
626300015Sadrian	/* Enable CLKREQ (ECPM). If suspending, also disable ASPM L1 entry */
627300015Sadrian	if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
628300015Sadrian		uint16_t	lcreg;
629300015Sadrian
630300015Sadrian		lcreg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2);
631300015Sadrian
632300015Sadrian		lcreg |= PCIEM_LINK_CTL_ECPM;	/* CLKREQ# */
633300015Sadrian		if (state == BHND_PCI_WAR_SUSPEND)
634300015Sadrian			lcreg &= ~PCIEM_LINK_CTL_ASPMC_L1;
635300015Sadrian
636300015Sadrian		pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, lcreg, 2);
637300015Sadrian	}
638300015Sadrian
639298479Sadrian	return (0);
640298479Sadrian}
641298479Sadrian
642296077Sadrianstatic device_method_t bhnd_pci_hostb_methods[] = {
643296077Sadrian	/* Device interface */
644298479Sadrian	DEVMETHOD(device_attach,		bhnd_pci_hostb_attach),
645298479Sadrian	DEVMETHOD(device_detach,		bhnd_pci_hostb_detach),
646298479Sadrian	DEVMETHOD(device_suspend,		bhnd_pci_hostb_suspend),
647298479Sadrian	DEVMETHOD(device_resume,		bhnd_pci_hostb_resume),
648296077Sadrian
649296077Sadrian	DEVMETHOD_END
650296077Sadrian};
651296077Sadrian
652300015SadrianDEFINE_CLASS_1(bhnd_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods,
653298479Sadrian    sizeof(struct bhnd_pcihb_softc), bhnd_pci_driver);
654300015SadrianDRIVER_MODULE(bhnd_pci_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0);
655296077Sadrian
656296077SadrianMODULE_VERSION(bhnd_pci_hostb, 1);
657298947SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd, 1, 1, 1);
658298479SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd_pci, 1, 1, 1);
659