1300015Sadrian/*-
2300015Sadrian * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3300015Sadrian * All rights reserved.
4300015Sadrian *
5300015Sadrian * Redistribution and use in source and binary forms, with or without
6300015Sadrian * modification, are permitted provided that the following conditions
7300015Sadrian * are met:
8300015Sadrian * 1. Redistributions of source code must retain the above copyright
9300015Sadrian *    notice, this list of conditions and the following disclaimer,
10300015Sadrian *    without modification.
11300015Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12300015Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13300015Sadrian *    redistribution must be conditioned upon including a substantially
14300015Sadrian *    similar Disclaimer requirement for further binary redistribution.
15300015Sadrian *
16300015Sadrian * NO WARRANTY
17300015Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18300015Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19300015Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20300015Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21300015Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22300015Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23300015Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24300015Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25300015Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26300015Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27300015Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28300015Sadrian */
29300015Sadrian
30300015Sadrian#include <sys/cdefs.h>
31300015Sadrian__FBSDID("$FreeBSD$");
32300015Sadrian
33300015Sadrian/*
34300015Sadrian * Broadcom Common PCIe-G2 Support.
35300015Sadrian *
36300015Sadrian * This base driver implementation is shared by the bhnd_pcib_g2 (root complex)
37300015Sadrian * and bhnd_pci_hostb_g2 (host bridge) drivers.
38300015Sadrian */
39300015Sadrian
40300015Sadrian#include <sys/param.h>
41300015Sadrian#include <sys/malloc.h>
42300015Sadrian#include <sys/kernel.h>
43300015Sadrian#include <sys/bus.h>
44300015Sadrian#include <sys/module.h>
45300015Sadrian#include <sys/systm.h>
46300015Sadrian
47300015Sadrian#include <machine/bus.h>
48300015Sadrian#include <sys/rman.h>
49300015Sadrian#include <machine/resource.h>
50300015Sadrian
51300015Sadrian#include <dev/bhnd/bhnd.h>
52300015Sadrian#include <dev/mdio/mdio.h>
53300015Sadrian
54300015Sadrian#include "bhnd_pcie2_reg.h"
55300015Sadrian#include "bhnd_pcie2_var.h"
56300015Sadrian
57300015Sadrianstatic struct bhnd_device_quirk bhnd_pcie2_quirks[];
58300015Sadrian
59300015Sadrian#define	BHND_PCIE_DEV(_core, _desc, ...)				\
60301697Slandonf	BHND_DEVICE(BCM, _core, _desc, bhnd_pcie2_quirks, ## __VA_ARGS__)
61300015Sadrian
62300015Sadrianstatic const struct bhnd_device bhnd_pcie2_devs[] = {
63300015Sadrian	BHND_PCIE_DEV(PCIE2,	"PCIe-G2 Host-PCI bridge",	BHND_DF_HOSTB),
64300628Sadrian	BHND_PCIE_DEV(PCIE2,	"PCIe-G2 PCI-BHND bridge",	BHND_DF_SOC),
65300015Sadrian
66300015Sadrian	BHND_DEVICE_END
67300015Sadrian};
68300015Sadrian
69300015Sadrian/* Device quirks tables */
70300015Sadrianstatic struct bhnd_device_quirk bhnd_pcie2_quirks[] = {
71300015Sadrian	BHND_DEVICE_QUIRK_END
72300015Sadrian};
73300015Sadrian
74300015Sadrianint
75300015Sadrianbhnd_pcie2_generic_probe(device_t dev)
76300015Sadrian{
77300015Sadrian	const struct bhnd_device	*id;
78300015Sadrian
79300015Sadrian	id = bhnd_device_lookup(dev, bhnd_pcie2_devs,
80300015Sadrian	    sizeof(bhnd_pcie2_devs[0]));
81300015Sadrian	if (id == NULL)
82300015Sadrian		return (ENXIO);
83300015Sadrian
84300015Sadrian	bhnd_set_custom_core_desc(dev, id->desc);
85300015Sadrian	return (BUS_PROBE_DEFAULT);
86300015Sadrian}
87300015Sadrian
88300015Sadrianint
89300015Sadrianbhnd_pcie2_generic_attach(device_t dev)
90300015Sadrian{
91300015Sadrian	struct bhnd_pcie2_softc	*sc;
92300015Sadrian	int			 error;
93300015Sadrian
94300015Sadrian	sc = device_get_softc(dev);
95300015Sadrian	sc->dev = dev;
96300015Sadrian	sc->quirks = bhnd_device_quirks(dev, bhnd_pcie2_devs,
97300015Sadrian	    sizeof(bhnd_pcie2_devs[0]));
98300015Sadrian
99300015Sadrian	/* Allocate bus resources */
100300015Sadrian	sc->mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
101300015Sadrian	    RF_ACTIVE);
102300015Sadrian	if (sc->mem_res == NULL)
103300015Sadrian		return (ENXIO);
104300015Sadrian
105300015Sadrian	BHND_PCIE2_LOCK_INIT(sc);
106300015Sadrian
107300015Sadrian	/* Probe and attach children */
108300015Sadrian	if ((error = bus_generic_attach(dev)))
109300015Sadrian		goto cleanup;
110300015Sadrian
111300015Sadrian	return (0);
112300015Sadrian
113300015Sadriancleanup:
114300015Sadrian	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
115300015Sadrian	BHND_PCIE2_LOCK_DESTROY(sc);
116300015Sadrian
117300015Sadrian	return (error);
118300015Sadrian}
119300015Sadrian
120300015Sadrianint
121300015Sadrianbhnd_pcie2_generic_detach(device_t dev)
122300015Sadrian{
123300015Sadrian	struct bhnd_pcie2_softc	*sc;
124300015Sadrian	int			 error;
125300015Sadrian
126300015Sadrian	sc = device_get_softc(dev);
127300015Sadrian
128300015Sadrian	if ((error = bus_generic_detach(dev)))
129300015Sadrian		return (error);
130300015Sadrian
131300015Sadrian	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
132300015Sadrian
133300015Sadrian	BHND_PCIE2_LOCK_DESTROY(sc);
134300015Sadrian
135300015Sadrian	return (0);
136300015Sadrian}
137300015Sadrian
138300015Sadrianstatic struct resource_list *
139300015Sadrianbhnd_pcie2_get_resource_list(device_t dev, device_t child)
140300015Sadrian{
141300015Sadrian	struct bhnd_pcie2_devinfo *dinfo;
142300015Sadrian
143300015Sadrian	if (device_get_parent(child) != dev)
144300015Sadrian		return (NULL);
145300015Sadrian
146300015Sadrian	dinfo = device_get_ivars(child);
147300015Sadrian	return (&dinfo->resources);
148300015Sadrian}
149300015Sadrian
150300015Sadrianstatic device_t
151300015Sadrianbhnd_pcie2_add_child(device_t dev, u_int order, const char *name, int unit)
152300015Sadrian{
153300015Sadrian	struct bhnd_pcie2_devinfo	*dinfo;
154300015Sadrian	device_t			 child;
155300015Sadrian
156300015Sadrian	child = device_add_child_ordered(dev, order, name, unit);
157300015Sadrian	if (child == NULL)
158300015Sadrian		return (NULL);
159300015Sadrian
160300015Sadrian	dinfo = malloc(sizeof(struct bhnd_pcie2_devinfo), M_DEVBUF, M_NOWAIT);
161300015Sadrian	if (dinfo == NULL) {
162300015Sadrian		device_delete_child(dev, child);
163300015Sadrian		return (NULL);
164300015Sadrian	}
165300015Sadrian
166300015Sadrian	resource_list_init(&dinfo->resources);
167300015Sadrian
168300015Sadrian	device_set_ivars(child, dinfo);
169300015Sadrian	return (child);
170300015Sadrian}
171300015Sadrian
172300015Sadrianstatic void
173300015Sadrianbhnd_pcie2_child_deleted(device_t dev, device_t child)
174300015Sadrian{
175300015Sadrian	struct bhnd_pcie2_devinfo *dinfo;
176300015Sadrian
177300015Sadrian	if (device_get_parent(child) != dev)
178300015Sadrian		return;
179300015Sadrian
180300015Sadrian	dinfo = device_get_ivars(child);
181300015Sadrian	if (dinfo != NULL) {
182300015Sadrian		resource_list_free(&dinfo->resources);
183300015Sadrian		free(dinfo, M_DEVBUF);
184300015Sadrian	}
185300015Sadrian
186300015Sadrian	device_set_ivars(child, NULL);
187300015Sadrian}
188300015Sadrian
189300015Sadrianint
190300015Sadrianbhnd_pcie2_generic_suspend(device_t dev)
191300015Sadrian{
192300015Sadrian	return (bus_generic_suspend(dev));
193300015Sadrian}
194300015Sadrian
195300015Sadrianint
196300015Sadrianbhnd_pcie2_generic_resume(device_t dev)
197300015Sadrian{
198300015Sadrian	return (bus_generic_resume(dev));
199300015Sadrian}
200300015Sadrian
201300015Sadrian/**
202300015Sadrian * Read a 32-bit PCIe TLP/DLLP/PLP protocol register.
203300015Sadrian *
204300015Sadrian * @param sc The bhndb_pci driver state.
205300015Sadrian * @param addr The protocol register offset.
206300015Sadrian */
207300015Sadrianuint32_t
208300015Sadrianbhnd_pcie2_read_proto_reg(struct bhnd_pcie2_softc *sc, uint32_t addr)
209300015Sadrian{
210300015Sadrian	// TODO
211300015Sadrian	return (ENXIO);
212300015Sadrian}
213300015Sadrian
214300015Sadrian/**
215300015Sadrian * Write a 32-bit PCIe TLP/DLLP/PLP protocol register value.
216300015Sadrian *
217300015Sadrian * @param sc The bhndb_pci driver state.
218300015Sadrian * @param addr The protocol register offset.
219300015Sadrian * @param val The value to write to @p addr.
220300015Sadrian */
221300015Sadrianvoid
222300015Sadrianbhnd_pcie2_write_proto_reg(struct bhnd_pcie2_softc *sc, uint32_t addr,
223300015Sadrian    uint32_t val)
224300015Sadrian{
225300015Sadrian	// TODO
226300015Sadrian	panic("unimplemented");
227300015Sadrian}
228300015Sadrian
229300015Sadrianint
230300015Sadrianbhnd_pcie2_mdio_read(struct bhnd_pcie2_softc *sc, int phy, int reg)
231300015Sadrian{
232300015Sadrian	// TODO
233300015Sadrian	return (ENXIO);
234300015Sadrian}
235300015Sadrian
236300015Sadrianint
237300015Sadrianbhnd_pcie2_mdio_write(struct bhnd_pcie2_softc *sc, int phy, int reg, int val)
238300015Sadrian{
239300015Sadrian	// TODO
240300015Sadrian	return (ENXIO);
241300015Sadrian}
242300015Sadrian
243300015Sadrianint
244300015Sadrianbhnd_pcie2_mdio_read_ext(struct bhnd_pcie2_softc *sc, int phy, int devaddr,
245300015Sadrian    int reg)
246300015Sadrian{
247300015Sadrian	// TODO
248300015Sadrian	return (ENXIO);
249300015Sadrian}
250300015Sadrian
251300015Sadrianint
252300015Sadrianbhnd_pcie2_mdio_write_ext(struct bhnd_pcie2_softc *sc, int phy, int devaddr,
253300015Sadrian    int reg, int val)
254300015Sadrian{
255300015Sadrian	// TODO
256300015Sadrian	return (ENXIO);
257300015Sadrian}
258300015Sadrian
259300015Sadrianstatic device_method_t bhnd_pcie2_methods[] = {
260300015Sadrian	/* Device interface */
261300015Sadrian	DEVMETHOD(device_probe,			bhnd_pcie2_generic_probe),
262300015Sadrian	DEVMETHOD(device_attach,		bhnd_pcie2_generic_attach),
263300015Sadrian	DEVMETHOD(device_detach,		bhnd_pcie2_generic_detach),
264300015Sadrian	DEVMETHOD(device_suspend,		bhnd_pcie2_generic_suspend),
265300015Sadrian	DEVMETHOD(device_resume,		bhnd_pcie2_generic_resume),
266300015Sadrian
267300015Sadrian	/* Bus interface */
268300015Sadrian	DEVMETHOD(bus_add_child,		bhnd_pcie2_add_child),
269300015Sadrian	DEVMETHOD(bus_child_deleted,		bhnd_pcie2_child_deleted),
270300015Sadrian	DEVMETHOD(bus_print_child,		bus_generic_print_child),
271300015Sadrian	DEVMETHOD(bus_get_resource_list,	bhnd_pcie2_get_resource_list),
272300015Sadrian	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
273300015Sadrian	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
274300015Sadrian	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
275300015Sadrian
276300015Sadrian	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
277300015Sadrian	DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
278300015Sadrian	DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
279300015Sadrian	DEVMETHOD(bus_adjust_resource,          bus_generic_adjust_resource),
280300015Sadrian	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
281300015Sadrian
282300015Sadrian	DEVMETHOD_END
283300015Sadrian};
284300015Sadrian
285300015SadrianDEFINE_CLASS_0(bhnd_pcie2, bhnd_pcie2_driver, bhnd_pcie2_methods,
286300015Sadrian   sizeof(struct bhnd_pcie2_softc));
287300015SadrianMODULE_DEPEND(bhnd_pcie2, bhnd, 1, 1, 1);
288300015SadrianMODULE_DEPEND(bhnd_pcie2, pci, 1, 1, 1);
289300015SadrianMODULE_VERSION(bhnd_pcie2, 1);
290