siba_bhndb.c revision 296077
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: head/sys/dev/bhnd/siba/siba_bhndb.c 296077 2016-02-26 03:34:08Z adrian $");
32296077Sadrian
33296077Sadrian#include <sys/param.h>
34296077Sadrian#include <sys/kernel.h>
35296077Sadrian#include <sys/bus.h>
36296077Sadrian#include <sys/module.h>
37296077Sadrian
38296077Sadrian#include <dev/bhnd/bhnd_ids.h>
39296077Sadrian#include <dev/bhnd/bhndb/bhndbvar.h>
40296077Sadrian#include <dev/bhnd/bhndb/bhndb_hwdata.h>
41296077Sadrian
42296077Sadrian#include "sibavar.h"
43296077Sadrian
44296077Sadrian/*
45296077Sadrian * Supports attachment of siba(4) bus devices via a bhndb bridge.
46296077Sadrian */
47296077Sadrian
48296077Sadrianstatic int
49296077Sadriansiba_bhndb_probe(device_t dev)
50296077Sadrian{
51296077Sadrian	const struct bhnd_chipid *cid;
52296077Sadrian
53296077Sadrian	/* Check bus type */
54296077Sadrian	cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev);
55296077Sadrian	if (cid->chip_type != BHND_CHIPTYPE_SIBA)
56296077Sadrian		return (ENXIO);
57296077Sadrian
58296077Sadrian	/* Delegate to default probe implementation */
59296077Sadrian	return (siba_probe(dev));
60296077Sadrian}
61296077Sadrian
62296077Sadrianstatic int
63296077Sadriansiba_bhndb_attach(device_t dev)
64296077Sadrian{
65296077Sadrian	const struct bhnd_chipid	*chipid;
66296077Sadrian	int				 error;
67296077Sadrian
68296077Sadrian	/* Enumerate our children. */
69296077Sadrian	chipid = BHNDB_GET_CHIPID(device_get_parent(dev), dev);
70296077Sadrian	if ((error = siba_add_children(dev, chipid)))
71296077Sadrian		return (error);
72296077Sadrian
73296077Sadrian	/* Initialize full bridge configuration */
74296077Sadrian	error = BHNDB_INIT_FULL_CONFIG(device_get_parent(dev), dev,
75296077Sadrian	    bhndb_siba_priority_table);
76296077Sadrian	if (error)
77296077Sadrian		return (error);
78296077Sadrian
79296077Sadrian	/* Call our superclass' implementation */
80296077Sadrian	return (siba_attach(dev));
81296077Sadrian}
82296077Sadrian
83296077Sadrian/* Suspend all references to the device's cfg register blocks */
84296077Sadrianstatic void
85296077Sadriansiba_bhndb_suspend_cfgblocks(device_t dev, struct siba_devinfo *dinfo) {
86296077Sadrian	for (u_int i = 0; i < dinfo->core_id.num_cfg_blocks; i++) {
87296077Sadrian		if (dinfo->cfg[i] == NULL)
88296077Sadrian			continue;
89296077Sadrian
90296077Sadrian		BHNDB_SUSPEND_RESOURCE(device_get_parent(dev), dev,
91296077Sadrian		    SYS_RES_MEMORY, dinfo->cfg[i]->res);
92296077Sadrian	}
93296077Sadrian}
94296077Sadrian
95296077Sadrianstatic int
96296077Sadriansiba_bhndb_suspend_child(device_t dev, device_t child)
97296077Sadrian{
98296077Sadrian	struct siba_devinfo	*dinfo;
99296077Sadrian	int			 error;
100296077Sadrian
101296077Sadrian	if (device_get_parent(child) != dev)
102296077Sadrian		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
103296077Sadrian
104296077Sadrian	dinfo = device_get_ivars(child);
105296077Sadrian
106296077Sadrian	/* Suspend the child */
107296077Sadrian	if ((error = bhnd_generic_br_suspend_child(dev, child)))
108296077Sadrian		return (error);
109296077Sadrian
110296077Sadrian	/* Suspend resource references to the child's config registers */
111296077Sadrian	siba_bhndb_suspend_cfgblocks(dev, dinfo);
112296077Sadrian
113296077Sadrian	return (0);
114296077Sadrian}
115296077Sadrian
116296077Sadrianstatic int
117296077Sadriansiba_bhndb_resume_child(device_t dev, device_t child)
118296077Sadrian{
119296077Sadrian	struct siba_devinfo	*dinfo;
120296077Sadrian	int			 error;
121296077Sadrian
122296077Sadrian	if (device_get_parent(child) != dev)
123296077Sadrian		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
124296077Sadrian
125296077Sadrian	if (!device_is_suspended(child))
126296077Sadrian		return (EBUSY);
127296077Sadrian
128296077Sadrian	dinfo = device_get_ivars(child);
129296077Sadrian
130296077Sadrian	/* Resume all resource references to the child's config registers */
131296077Sadrian	for (u_int i = 0; i < dinfo->core_id.num_cfg_blocks; i++) {
132296077Sadrian		if (dinfo->cfg[i] == NULL)
133296077Sadrian			continue;
134296077Sadrian
135296077Sadrian		error = BHNDB_RESUME_RESOURCE(device_get_parent(dev), dev,
136296077Sadrian		    SYS_RES_MEMORY, dinfo->cfg[i]->res);
137296077Sadrian		if (error) {
138296077Sadrian			siba_bhndb_suspend_cfgblocks(dev, dinfo);
139296077Sadrian			return (error);
140296077Sadrian		}
141296077Sadrian	}
142296077Sadrian
143296077Sadrian	/* Resume the child */
144296077Sadrian	if ((error = bhnd_generic_br_resume_child(dev, child))) {
145296077Sadrian		siba_bhndb_suspend_cfgblocks(dev, dinfo);
146296077Sadrian		return (error);
147296077Sadrian	}
148296077Sadrian
149296077Sadrian	return (0);
150296077Sadrian}
151296077Sadrian
152296077Sadrianstatic device_method_t siba_bhndb_methods[] = {
153296077Sadrian	/* Device interface */
154296077Sadrian	DEVMETHOD(device_probe,			siba_bhndb_probe),
155296077Sadrian	DEVMETHOD(device_attach,		siba_bhndb_attach),
156296077Sadrian
157296077Sadrian	/* Bus interface */
158296077Sadrian	DEVMETHOD(bus_suspend_child,		siba_bhndb_suspend_child),
159296077Sadrian	DEVMETHOD(bus_resume_child,		siba_bhndb_resume_child),
160296077Sadrian
161296077Sadrian	DEVMETHOD_END
162296077Sadrian};
163296077Sadrian
164296077SadrianDEFINE_CLASS_1(bhnd, siba_bhndb_driver, siba_bhndb_methods,
165296077Sadrian    sizeof(struct siba_softc), siba_driver);
166296077Sadrian
167296077SadrianDRIVER_MODULE(siba_bhndb, bhndb, siba_bhndb_driver, bhnd_devclass, NULL, NULL);
168296077Sadrian
169296077SadrianMODULE_VERSION(siba_bhndb, 1);
170296077SadrianMODULE_DEPEND(siba_bhndb, siba, 1, 1, 1);
171296077SadrianMODULE_DEPEND(siba_bhndb, bhndb, 1, 1, 1);