xref: /freebsd/sys/dev/bhnd/bhndb/bhnd_bhndb.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
19d292ea1SAdrian Chadd /*-
29d292ea1SAdrian Chadd  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
38e35bf83SLandon J. Fuller  * Copyright (c) 2017 The FreeBSD Foundation
49d292ea1SAdrian Chadd  * All rights reserved.
59d292ea1SAdrian Chadd  *
68e35bf83SLandon J. Fuller  * Portions of this software were developed by Landon Fuller
78e35bf83SLandon J. Fuller  * under sponsorship from the FreeBSD Foundation.
88e35bf83SLandon J. Fuller  *
99d292ea1SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
109d292ea1SAdrian Chadd  * modification, are permitted provided that the following conditions
119d292ea1SAdrian Chadd  * are met:
129d292ea1SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
139d292ea1SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
149d292ea1SAdrian Chadd  *    without modification.
159d292ea1SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
169d292ea1SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
179d292ea1SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
189d292ea1SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
199d292ea1SAdrian Chadd  *
209d292ea1SAdrian Chadd  * NO WARRANTY
219d292ea1SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
229d292ea1SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
239d292ea1SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
249d292ea1SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
259d292ea1SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
269d292ea1SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
279d292ea1SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
289d292ea1SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
299d292ea1SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309d292ea1SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
319d292ea1SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
329d292ea1SAdrian Chadd  */
339d292ea1SAdrian Chadd 
349d292ea1SAdrian Chadd #include <sys/param.h>
359d292ea1SAdrian Chadd #include <sys/kernel.h>
369d292ea1SAdrian Chadd #include <sys/bus.h>
379d292ea1SAdrian Chadd #include <sys/module.h>
389d292ea1SAdrian Chadd 
399d292ea1SAdrian Chadd #include <dev/bhnd/bhnd_ids.h>
409d292ea1SAdrian Chadd #include <dev/bhnd/bhnd.h>
419d292ea1SAdrian Chadd 
42*4e96bf3aSLandon J. Fuller #include "bhnd_pwrctl_hostb_if.h"
43*4e96bf3aSLandon J. Fuller 
449d292ea1SAdrian Chadd #include "bhndbvar.h"
459d292ea1SAdrian Chadd 
469d292ea1SAdrian Chadd /*
479d292ea1SAdrian Chadd  * bhnd(4) driver mix-in providing a shared common methods for
489d292ea1SAdrian Chadd  * bhnd devices attached via a bhndb bridge.
499d292ea1SAdrian Chadd  */
509d292ea1SAdrian Chadd 
519d292ea1SAdrian Chadd static int
bhnd_bhndb_read_board_info(device_t dev,device_t child,struct bhnd_board_info * info)529d292ea1SAdrian Chadd bhnd_bhndb_read_board_info(device_t dev, device_t child,
539d292ea1SAdrian Chadd     struct bhnd_board_info *info)
549d292ea1SAdrian Chadd {
559d292ea1SAdrian Chadd 	int	error;
569d292ea1SAdrian Chadd 
579d292ea1SAdrian Chadd 	/* Initialize with NVRAM-derived values */
589d292ea1SAdrian Chadd 	if ((error = bhnd_bus_generic_read_board_info(dev, child, info)))
599d292ea1SAdrian Chadd 		return (error);
609d292ea1SAdrian Chadd 
619d292ea1SAdrian Chadd 	/* Let the bridge fill in any additional data */
629d292ea1SAdrian Chadd 	return (BHNDB_POPULATE_BOARD_INFO(device_get_parent(dev), dev, info));
639d292ea1SAdrian Chadd }
649d292ea1SAdrian Chadd 
659d292ea1SAdrian Chadd static bhnd_attach_type
bhnd_bhndb_get_attach_type(device_t dev,device_t child)669d292ea1SAdrian Chadd bhnd_bhndb_get_attach_type(device_t dev, device_t child)
679d292ea1SAdrian Chadd {
689d292ea1SAdrian Chadd 	/* It's safe to assume that a bridged device is always an adapter */
699d292ea1SAdrian Chadd 	return (BHND_ATTACH_ADAPTER);
709d292ea1SAdrian Chadd }
719d292ea1SAdrian Chadd 
7263fb0e82SLandon J. Fuller static bool
bhnd_bhndb_is_hw_disabled(device_t dev,device_t child)7363fb0e82SLandon J. Fuller bhnd_bhndb_is_hw_disabled(device_t dev, device_t child)
7463fb0e82SLandon J. Fuller {
7563fb0e82SLandon J. Fuller 	struct bhnd_core_info core = bhnd_get_core_info(child);
7663fb0e82SLandon J. Fuller 
7763fb0e82SLandon J. Fuller 	/* Delegate to parent bridge */
7863fb0e82SLandon J. Fuller 	return (BHNDB_IS_CORE_DISABLED(device_get_parent(dev), dev, &core));
7963fb0e82SLandon J. Fuller }
8063fb0e82SLandon J. Fuller 
81111d7cb2SLandon J. Fuller static device_t
bhnd_bhndb_find_hostb_device(device_t dev)82111d7cb2SLandon J. Fuller bhnd_bhndb_find_hostb_device(device_t dev)
83111d7cb2SLandon J. Fuller {
84111d7cb2SLandon J. Fuller 	struct bhnd_core_info	 core;
85111d7cb2SLandon J. Fuller 	struct bhnd_core_match	 md;
86111d7cb2SLandon J. Fuller 	int			 error;
87111d7cb2SLandon J. Fuller 
88111d7cb2SLandon J. Fuller 	/* Ask the bridge for the hostb core info */
89111d7cb2SLandon J. Fuller 	if ((error = BHNDB_GET_HOSTB_CORE(device_get_parent(dev), dev, &core)))
90111d7cb2SLandon J. Fuller 		return (NULL);
91111d7cb2SLandon J. Fuller 
92111d7cb2SLandon J. Fuller 	/* Find the corresponding bus device */
93111d7cb2SLandon J. Fuller 	md = bhnd_core_get_match_desc(&core);
948e35bf83SLandon J. Fuller 	return (bhnd_bus_match_child(dev, &md));
95111d7cb2SLandon J. Fuller }
96111d7cb2SLandon J. Fuller 
97824b48efSLandon J. Fuller static int
bhnd_bhndb_map_intr(device_t dev,device_t child,u_int intr,rman_res_t * irq)98caeff9a3SLandon J. Fuller bhnd_bhndb_map_intr(device_t dev, device_t child, u_int intr, rman_res_t *irq)
99824b48efSLandon J. Fuller {
100824b48efSLandon J. Fuller 	/* Delegate to parent bridge */
101caeff9a3SLandon J. Fuller 	return (BHND_BUS_MAP_INTR(device_get_parent(dev), child, intr, irq));
102caeff9a3SLandon J. Fuller }
103caeff9a3SLandon J. Fuller 
104caeff9a3SLandon J. Fuller static void
bhnd_bhndb_unmap_intr(device_t dev,device_t child,rman_res_t irq)105caeff9a3SLandon J. Fuller bhnd_bhndb_unmap_intr(device_t dev, device_t child, rman_res_t irq)
106caeff9a3SLandon J. Fuller {
107caeff9a3SLandon J. Fuller 	/* Delegate to parent bridge */
108caeff9a3SLandon J. Fuller 	return (BHND_BUS_UNMAP_INTR(device_get_parent(dev), child, irq));
109824b48efSLandon J. Fuller }
110824b48efSLandon J. Fuller 
111f90f4b65SLandon J. Fuller static bhnd_clksrc
bhnd_bhndb_pwrctl_get_clksrc(device_t dev,device_t child,bhnd_clock clock)112f90f4b65SLandon J. Fuller bhnd_bhndb_pwrctl_get_clksrc(device_t dev, device_t child,
113f90f4b65SLandon J. Fuller 	bhnd_clock clock)
114f90f4b65SLandon J. Fuller {
115f90f4b65SLandon J. Fuller 	/* Delegate to parent bridge */
116*4e96bf3aSLandon J. Fuller 	return (BHND_PWRCTL_HOSTB_GET_CLKSRC(device_get_parent(dev), child,
117f90f4b65SLandon J. Fuller 	    clock));
118f90f4b65SLandon J. Fuller }
119f90f4b65SLandon J. Fuller 
120f90f4b65SLandon J. Fuller static int
bhnd_bhndb_pwrctl_gate_clock(device_t dev,device_t child,bhnd_clock clock)121f90f4b65SLandon J. Fuller bhnd_bhndb_pwrctl_gate_clock(device_t dev, device_t child,
122f90f4b65SLandon J. Fuller 	bhnd_clock clock)
123f90f4b65SLandon J. Fuller {
124f90f4b65SLandon J. Fuller 	/* Delegate to parent bridge */
125*4e96bf3aSLandon J. Fuller 	return (BHND_PWRCTL_HOSTB_GATE_CLOCK(device_get_parent(dev), child,
126f90f4b65SLandon J. Fuller 	    clock));
127f90f4b65SLandon J. Fuller }
128f90f4b65SLandon J. Fuller 
129f90f4b65SLandon J. Fuller static int
bhnd_bhndb_pwrctl_ungate_clock(device_t dev,device_t child,bhnd_clock clock)130f90f4b65SLandon J. Fuller bhnd_bhndb_pwrctl_ungate_clock(device_t dev, device_t child,
131f90f4b65SLandon J. Fuller 	bhnd_clock clock)
132f90f4b65SLandon J. Fuller {
133f90f4b65SLandon J. Fuller 	/* Delegate to parent bridge */
134*4e96bf3aSLandon J. Fuller 	return (BHND_PWRCTL_HOSTB_UNGATE_CLOCK(device_get_parent(dev), child,
135f90f4b65SLandon J. Fuller 	    clock));
136f90f4b65SLandon J. Fuller }
137f90f4b65SLandon J. Fuller 
138caeff9a3SLandon J. Fuller static int
bhnd_bhndb_setup_intr(device_t dev,device_t child,struct resource * irq,int flags,driver_filter_t * filter,driver_intr_t * intr,void * arg,void ** cookiep)139caeff9a3SLandon J. Fuller bhnd_bhndb_setup_intr(device_t dev, device_t child, struct resource *irq,
140caeff9a3SLandon J. Fuller     int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
141caeff9a3SLandon J. Fuller     void **cookiep)
142caeff9a3SLandon J. Fuller {
143caeff9a3SLandon J. Fuller 	device_t	core, bus;
144caeff9a3SLandon J. Fuller 	int		error;
145caeff9a3SLandon J. Fuller 
146caeff9a3SLandon J. Fuller 	/* Find the actual bus-attached child core */
147caeff9a3SLandon J. Fuller 	core = child;
148caeff9a3SLandon J. Fuller 	while ((bus = device_get_parent(core)) != NULL) {
149caeff9a3SLandon J. Fuller 		if (bus == dev)
150caeff9a3SLandon J. Fuller 			break;
151caeff9a3SLandon J. Fuller 
152caeff9a3SLandon J. Fuller 		core = bus;
153caeff9a3SLandon J. Fuller 	}
154caeff9a3SLandon J. Fuller 
155caeff9a3SLandon J. Fuller 	KASSERT(core != NULL, ("%s is not a child of %s",
156caeff9a3SLandon J. Fuller 	    device_get_nameunit(child), device_get_nameunit(dev)));
157caeff9a3SLandon J. Fuller 
158caeff9a3SLandon J. Fuller 	/* Ask our bridge to enable interrupt routing for the child core */
159caeff9a3SLandon J. Fuller 	error = BHNDB_ROUTE_INTERRUPTS(device_get_parent(dev), core);
160caeff9a3SLandon J. Fuller 	if (error)
161caeff9a3SLandon J. Fuller 		return (error);
162caeff9a3SLandon J. Fuller 
163caeff9a3SLandon J. Fuller 	/* Delegate actual interrupt setup to the default bhnd bus
164caeff9a3SLandon J. Fuller 	 * implementation */
165caeff9a3SLandon J. Fuller 	return (bhnd_generic_setup_intr(dev, child, irq, flags, filter, intr,
166caeff9a3SLandon J. Fuller 	    arg, cookiep));
167caeff9a3SLandon J. Fuller }
168caeff9a3SLandon J. Fuller 
1699d292ea1SAdrian Chadd static device_method_t bhnd_bhndb_methods[] = {
170caeff9a3SLandon J. Fuller 	/* Bus interface */
171caeff9a3SLandon J. Fuller 	DEVMETHOD(bus_setup_intr,			bhnd_bhndb_setup_intr),
172caeff9a3SLandon J. Fuller 
1739d292ea1SAdrian Chadd 	/* BHND interface */
1749d292ea1SAdrian Chadd 	DEVMETHOD(bhnd_bus_get_attach_type,		bhnd_bhndb_get_attach_type),
17563fb0e82SLandon J. Fuller 	DEVMETHOD(bhnd_bus_is_hw_disabled,		bhnd_bhndb_is_hw_disabled),
176111d7cb2SLandon J. Fuller 	DEVMETHOD(bhnd_bus_find_hostb_device,		bhnd_bhndb_find_hostb_device),
1779d292ea1SAdrian Chadd 	DEVMETHOD(bhnd_bus_read_board_info,		bhnd_bhndb_read_board_info),
178caeff9a3SLandon J. Fuller 	DEVMETHOD(bhnd_bus_map_intr,			bhnd_bhndb_map_intr),
179caeff9a3SLandon J. Fuller 	DEVMETHOD(bhnd_bus_unmap_intr,			bhnd_bhndb_unmap_intr),
1809d292ea1SAdrian Chadd 
181*4e96bf3aSLandon J. Fuller 	/* BHND PWRCTL hostb interface */
182*4e96bf3aSLandon J. Fuller 	DEVMETHOD(bhnd_pwrctl_hostb_get_clksrc,		bhnd_bhndb_pwrctl_get_clksrc),
183*4e96bf3aSLandon J. Fuller 	DEVMETHOD(bhnd_pwrctl_hostb_gate_clock,		bhnd_bhndb_pwrctl_gate_clock),
184*4e96bf3aSLandon J. Fuller 	DEVMETHOD(bhnd_pwrctl_hostb_ungate_clock,	bhnd_bhndb_pwrctl_ungate_clock),
185f90f4b65SLandon J. Fuller 
1869d292ea1SAdrian Chadd 	DEVMETHOD_END
1879d292ea1SAdrian Chadd };
1889d292ea1SAdrian Chadd 
1899d292ea1SAdrian Chadd DEFINE_CLASS_0(bhnd, bhnd_bhndb_driver, bhnd_bhndb_methods, 0);
190