xref: /freebsd/sys/dev/bhnd/bcma/bcma.c (revision 512bd18d)
1 /*-
2  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
3  * Copyright (c) 2017 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Landon Fuller
7  * under sponsorship from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer,
14  *    without modification.
15  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
17  *    redistribution must be conditioned upon including a substantially
18  *    similar Disclaimer requirement for further binary redistribution.
19  *
20  * NO WARRANTY
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
24  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
26  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGES.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/systm.h>
43 
44 #include <machine/bus.h>
45 
46 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
47 
48 #include "bcma_dmp.h"
49 
50 #include "bcma_eromreg.h"
51 #include "bcma_eromvar.h"
52 
53 #include "bcmavar.h"
54 
55 /* RID used when allocating EROM table */
56 #define	BCMA_EROM_RID	0
57 
58 static bhnd_erom_class_t *
59 bcma_get_erom_class(driver_t *driver)
60 {
61 	return (&bcma_erom_parser);
62 }
63 
64 int
65 bcma_probe(device_t dev)
66 {
67 	device_set_desc(dev, "BCMA BHND bus");
68 	return (BUS_PROBE_DEFAULT);
69 }
70 
71 /**
72  * Default bcma(4) bus driver implementation of DEVICE_ATTACH().
73  *
74  * This implementation initializes internal bcma(4) state and performs
75  * bus enumeration, and must be called by subclassing drivers in
76  * DEVICE_ATTACH() before any other bus methods.
77  */
78 int
79 bcma_attach(device_t dev)
80 {
81 	int error;
82 
83 	/* Enumerate children */
84 	if ((error = bcma_add_children(dev))) {
85 		device_delete_children(dev);
86 		return (error);
87 	}
88 
89 	return (0);
90 }
91 
92 int
93 bcma_detach(device_t dev)
94 {
95 	return (bhnd_generic_detach(dev));
96 }
97 
98 static device_t
99 bcma_add_child(device_t dev, u_int order, const char *name, int unit)
100 {
101 	struct bcma_devinfo	*dinfo;
102 	device_t		 child;
103 
104 	child = device_add_child_ordered(dev, order, name, unit);
105 	if (child == NULL)
106 		return (NULL);
107 
108 	if ((dinfo = bcma_alloc_dinfo(dev)) == NULL) {
109 		device_delete_child(dev, child);
110 		return (NULL);
111 	}
112 
113 	device_set_ivars(child, dinfo);
114 
115 	return (child);
116 }
117 
118 static void
119 bcma_child_deleted(device_t dev, device_t child)
120 {
121 	struct bhnd_softc	*sc;
122 	struct bcma_devinfo	*dinfo;
123 
124 	sc = device_get_softc(dev);
125 
126 	/* Call required bhnd(4) implementation */
127 	bhnd_generic_child_deleted(dev, child);
128 
129 	/* Free bcma device info */
130 	if ((dinfo = device_get_ivars(child)) != NULL)
131 		bcma_free_dinfo(dev, child, dinfo);
132 
133 	device_set_ivars(child, NULL);
134 }
135 
136 static int
137 bcma_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
138 {
139 	const struct bcma_devinfo *dinfo;
140 	const struct bhnd_core_info *ci;
141 
142 	dinfo = device_get_ivars(child);
143 	ci = &dinfo->corecfg->core_info;
144 
145 	switch (index) {
146 	case BHND_IVAR_VENDOR:
147 		*result = ci->vendor;
148 		return (0);
149 	case BHND_IVAR_DEVICE:
150 		*result = ci->device;
151 		return (0);
152 	case BHND_IVAR_HWREV:
153 		*result = ci->hwrev;
154 		return (0);
155 	case BHND_IVAR_DEVICE_CLASS:
156 		*result = bhnd_core_class(ci);
157 		return (0);
158 	case BHND_IVAR_VENDOR_NAME:
159 		*result = (uintptr_t) bhnd_vendor_name(ci->vendor);
160 		return (0);
161 	case BHND_IVAR_DEVICE_NAME:
162 		*result = (uintptr_t) bhnd_core_name(ci);
163 		return (0);
164 	case BHND_IVAR_CORE_INDEX:
165 		*result = ci->core_idx;
166 		return (0);
167 	case BHND_IVAR_CORE_UNIT:
168 		*result = ci->unit;
169 		return (0);
170 	case BHND_IVAR_PMU_INFO:
171 		*result = (uintptr_t) dinfo->pmu_info;
172 		return (0);
173 	default:
174 		return (ENOENT);
175 	}
176 }
177 
178 static int
179 bcma_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
180 {
181 	struct bcma_devinfo *dinfo;
182 
183 	dinfo = device_get_ivars(child);
184 
185 	switch (index) {
186 	case BHND_IVAR_VENDOR:
187 	case BHND_IVAR_DEVICE:
188 	case BHND_IVAR_HWREV:
189 	case BHND_IVAR_DEVICE_CLASS:
190 	case BHND_IVAR_VENDOR_NAME:
191 	case BHND_IVAR_DEVICE_NAME:
192 	case BHND_IVAR_CORE_INDEX:
193 	case BHND_IVAR_CORE_UNIT:
194 		return (EINVAL);
195 	case BHND_IVAR_PMU_INFO:
196 		dinfo->pmu_info = (struct bhnd_core_pmu_info *) value;
197 		return (0);
198 	default:
199 		return (ENOENT);
200 	}
201 }
202 
203 static struct resource_list *
204 bcma_get_resource_list(device_t dev, device_t child)
205 {
206 	struct bcma_devinfo *dinfo = device_get_ivars(child);
207 	return (&dinfo->resources);
208 }
209 
210 static int
211 bcma_read_iost(device_t dev, device_t child, uint16_t *iost)
212 {
213 	uint32_t	value;
214 	int		error;
215 
216 	if ((error = bhnd_read_config(child, BCMA_DMP_IOSTATUS, &value, 4)))
217 		return (error);
218 
219 	/* Return only the bottom 16 bits */
220 	*iost = (value & BCMA_DMP_IOST_MASK);
221 	return (0);
222 }
223 
224 static int
225 bcma_read_ioctl(device_t dev, device_t child, uint16_t *ioctl)
226 {
227 	uint32_t	value;
228 	int		error;
229 
230 	if ((error = bhnd_read_config(child, BCMA_DMP_IOCTRL, &value, 4)))
231 		return (error);
232 
233 	/* Return only the bottom 16 bits */
234 	*ioctl = (value & BCMA_DMP_IOCTRL_MASK);
235 	return (0);
236 }
237 
238 static int
239 bcma_write_ioctl(device_t dev, device_t child, uint16_t value, uint16_t mask)
240 {
241 	struct bcma_devinfo	*dinfo;
242 	struct bhnd_resource	*r;
243 	uint32_t		 ioctl;
244 
245 	if (device_get_parent(child) != dev)
246 		return (EINVAL);
247 
248 	dinfo = device_get_ivars(child);
249 	if ((r = dinfo->res_agent) == NULL)
250 		return (ENODEV);
251 
252 	/* Write new value */
253 	ioctl = bhnd_bus_read_4(r, BCMA_DMP_IOCTRL);
254 	ioctl &= ~(BCMA_DMP_IOCTRL_MASK & mask);
255 	ioctl |= (value & mask);
256 
257 	bhnd_bus_write_4(r, BCMA_DMP_IOCTRL, ioctl);
258 
259 	/* Perform read-back and wait for completion */
260 	bhnd_bus_read_4(r, BCMA_DMP_IOCTRL);
261 	DELAY(10);
262 
263 	return (0);
264 }
265 
266 static bool
267 bcma_is_hw_suspended(device_t dev, device_t child)
268 {
269 	uint32_t	rst;
270 	uint16_t	ioctl;
271 	int		error;
272 
273 	/* Is core held in RESET? */
274 	error = bhnd_read_config(child, BCMA_DMP_RESETCTRL, &rst, 4);
275 	if (error) {
276 		device_printf(child, "error reading HW reset state: %d\n",
277 		    error);
278 		return (true);
279 	}
280 
281 	if (rst & BCMA_DMP_RC_RESET)
282 		return (true);
283 
284 	/* Is core clocked? */
285 	error = bhnd_read_ioctl(child, &ioctl);
286 	if (error) {
287 		device_printf(child, "error reading HW ioctl register: %d\n",
288 		    error);
289 		return (true);
290 	}
291 
292 	if (!(ioctl & BHND_IOCTL_CLK_EN))
293 		return (true);
294 
295 	return (false);
296 }
297 
298 static int
299 bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl)
300 {
301 	struct bcma_devinfo		*dinfo;
302 	struct bhnd_core_pmu_info	*pm;
303 	struct bhnd_resource		*r;
304 	int				 error;
305 
306 	if (device_get_parent(child) != dev)
307 		return (EINVAL);
308 
309 	dinfo = device_get_ivars(child);
310 	pm = dinfo->pmu_info;
311 
312 	/* We require exclusive control over BHND_IOCTL_CLK_EN and
313 	 * BHND_IOCTL_CLK_FORCE. */
314 	if (ioctl & (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE))
315 		return (EINVAL);
316 
317 	/* Can't suspend the core without access to the agent registers */
318 	if ((r = dinfo->res_agent) == NULL)
319 		return (ENODEV);
320 
321 	/* Place core into known RESET state */
322 	if ((error = BHND_BUS_SUSPEND_HW(dev, child)))
323 		return (error);
324 
325 	/*
326 	 * Leaving the core in reset:
327 	 * - Set the caller's IOCTL flags
328 	 * - Enable clocks
329 	 * - Force clock distribution to ensure propagation throughout the
330 	 *   core.
331 	 */
332 	error = bhnd_write_ioctl(child,
333 	    ioctl | BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE, UINT16_MAX);
334 	if (error)
335 		return (error);
336 
337 	/* Bring the core out of reset */
338 	if ((error = bcma_dmp_write_reset(child, dinfo, 0x0)))
339 		return (error);
340 
341 	/* Disable forced clock gating (leaving clock enabled) */
342 	error = bhnd_write_ioctl(child, 0x0, BHND_IOCTL_CLK_FORCE);
343 	if (error)
344 		return (error);
345 
346 	return (0);
347 }
348 
349 static int
350 bcma_suspend_hw(device_t dev, device_t child)
351 {
352 	struct bcma_devinfo		*dinfo;
353 	struct bhnd_core_pmu_info	*pm;
354 	struct bhnd_resource		*r;
355 	uint32_t			 rst;
356 	int				 error;
357 
358 	if (device_get_parent(child) != dev)
359 		return (EINVAL);
360 
361 	dinfo = device_get_ivars(child);
362 	pm = dinfo->pmu_info;
363 
364 	/* Can't suspend the core without access to the agent registers */
365 	if ((r = dinfo->res_agent) == NULL)
366 		return (ENODEV);
367 
368 	/* Wait for any pending reset operations to clear */
369 	if ((error = bcma_dmp_wait_reset(child, dinfo)))
370 		return (error);
371 
372 	/* Already in reset? */
373 	rst = bhnd_bus_read_4(r, BCMA_DMP_RESETCTRL);
374 	if (rst & BCMA_DMP_RC_RESET)
375 		return (0);
376 
377 	/* Put core into reset */
378 	if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET)))
379 		return (error);
380 
381 	/* Clear core flags */
382 	if ((error = bhnd_write_ioctl(child, 0x0, UINT16_MAX)))
383 		return (error);
384 
385 	/* Inform PMU that all outstanding request state should be discarded */
386 	if (pm != NULL) {
387 		if ((error = BHND_PMU_CORE_RELEASE(pm->pm_pmu, pm)))
388 			return (error);
389 	}
390 
391 	return (0);
392 }
393 
394 static int
395 bcma_read_config(device_t dev, device_t child, bus_size_t offset, void *value,
396     u_int width)
397 {
398 	struct bcma_devinfo	*dinfo;
399 	struct bhnd_resource	*r;
400 
401 	/* Must be a directly attached child core */
402 	if (device_get_parent(child) != dev)
403 		return (EINVAL);
404 
405 	/* Fetch the agent registers */
406 	dinfo = device_get_ivars(child);
407 	if ((r = dinfo->res_agent) == NULL)
408 		return (ENODEV);
409 
410 	/* Verify bounds */
411 	if (offset > rman_get_size(r->res))
412 		return (EFAULT);
413 
414 	if (rman_get_size(r->res) - offset < width)
415 		return (EFAULT);
416 
417 	switch (width) {
418 	case 1:
419 		*((uint8_t *)value) = bhnd_bus_read_1(r, offset);
420 		return (0);
421 	case 2:
422 		*((uint16_t *)value) = bhnd_bus_read_2(r, offset);
423 		return (0);
424 	case 4:
425 		*((uint32_t *)value) = bhnd_bus_read_4(r, offset);
426 		return (0);
427 	default:
428 		return (EINVAL);
429 	}
430 }
431 
432 static int
433 bcma_write_config(device_t dev, device_t child, bus_size_t offset,
434     const void *value, u_int width)
435 {
436 	struct bcma_devinfo	*dinfo;
437 	struct bhnd_resource	*r;
438 
439 	/* Must be a directly attached child core */
440 	if (device_get_parent(child) != dev)
441 		return (EINVAL);
442 
443 	/* Fetch the agent registers */
444 	dinfo = device_get_ivars(child);
445 	if ((r = dinfo->res_agent) == NULL)
446 		return (ENODEV);
447 
448 	/* Verify bounds */
449 	if (offset > rman_get_size(r->res))
450 		return (EFAULT);
451 
452 	if (rman_get_size(r->res) - offset < width)
453 		return (EFAULT);
454 
455 	switch (width) {
456 	case 1:
457 		bhnd_bus_write_1(r, offset, *(const uint8_t *)value);
458 		return (0);
459 	case 2:
460 		bhnd_bus_write_2(r, offset, *(const uint16_t *)value);
461 		return (0);
462 	case 4:
463 		bhnd_bus_write_4(r, offset, *(const uint32_t *)value);
464 		return (0);
465 	default:
466 		return (EINVAL);
467 	}
468 }
469 
470 static u_int
471 bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type)
472 {
473 	struct bcma_devinfo *dinfo;
474 
475 	/* delegate non-bus-attached devices to our parent */
476 	if (device_get_parent(child) != dev)
477 		return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
478 		    type));
479 
480 	dinfo = device_get_ivars(child);
481 	switch (type) {
482 	case BHND_PORT_DEVICE:
483 		return (dinfo->corecfg->num_dev_ports);
484 	case BHND_PORT_BRIDGE:
485 		return (dinfo->corecfg->num_bridge_ports);
486 	case BHND_PORT_AGENT:
487 		return (dinfo->corecfg->num_wrapper_ports);
488 	default:
489 		device_printf(dev, "%s: unknown type (%d)\n",
490 		    __func__,
491 		    type);
492 		return (0);
493 	}
494 }
495 
496 static u_int
497 bcma_get_region_count(device_t dev, device_t child, bhnd_port_type type,
498     u_int port_num)
499 {
500 	struct bcma_devinfo	*dinfo;
501 	struct bcma_sport_list	*ports;
502 	struct bcma_sport	*port;
503 
504 	/* delegate non-bus-attached devices to our parent */
505 	if (device_get_parent(child) != dev)
506 		return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
507 		    type, port_num));
508 
509 	dinfo = device_get_ivars(child);
510 	ports = bcma_corecfg_get_port_list(dinfo->corecfg, type);
511 
512 	STAILQ_FOREACH(port, ports, sp_link) {
513 		if (port->sp_num == port_num)
514 			return (port->sp_num_maps);
515 	}
516 
517 	/* not found */
518 	return (0);
519 }
520 
521 static int
522 bcma_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
523     u_int port_num, u_int region_num)
524 {
525 	struct bcma_devinfo	*dinfo;
526 	struct bcma_map		*map;
527 	struct bcma_sport_list	*ports;
528 	struct bcma_sport	*port;
529 
530 	dinfo = device_get_ivars(child);
531 	ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type);
532 
533 	STAILQ_FOREACH(port, ports, sp_link) {
534 		if (port->sp_num != port_num)
535 			continue;
536 
537 		STAILQ_FOREACH(map, &port->sp_maps, m_link)
538 			if (map->m_region_num == region_num)
539 				return map->m_rid;
540 	}
541 
542 	return -1;
543 }
544 
545 static int
546 bcma_decode_port_rid(device_t dev, device_t child, int type, int rid,
547     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
548 {
549 	struct bcma_devinfo	*dinfo;
550 	struct bcma_map		*map;
551 	struct bcma_sport_list	*ports;
552 	struct bcma_sport	*port;
553 
554 	dinfo = device_get_ivars(child);
555 
556 	/* Ports are always memory mapped */
557 	if (type != SYS_RES_MEMORY)
558 		return (EINVAL);
559 
560 	/* Starting with the most likely device list, search all three port
561 	 * lists */
562 	bhnd_port_type types[] = {
563 	    BHND_PORT_DEVICE,
564 	    BHND_PORT_AGENT,
565 	    BHND_PORT_BRIDGE
566 	};
567 
568 	for (int i = 0; i < nitems(types); i++) {
569 		ports = bcma_corecfg_get_port_list(dinfo->corecfg, types[i]);
570 
571 		STAILQ_FOREACH(port, ports, sp_link) {
572 			STAILQ_FOREACH(map, &port->sp_maps, m_link) {
573 				if (map->m_rid != rid)
574 					continue;
575 
576 				*port_type = port->sp_type;
577 				*port_num = port->sp_num;
578 				*region_num = map->m_region_num;
579 				return (0);
580 			}
581 		}
582 	}
583 
584 	return (ENOENT);
585 }
586 
587 static int
588 bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
589     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
590 {
591 	struct bcma_devinfo	*dinfo;
592 	struct bcma_map		*map;
593 	struct bcma_sport_list	*ports;
594 	struct bcma_sport	*port;
595 
596 	dinfo = device_get_ivars(child);
597 	ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type);
598 
599 	/* Search the port list */
600 	STAILQ_FOREACH(port, ports, sp_link) {
601 		if (port->sp_num != port_num)
602 			continue;
603 
604 		STAILQ_FOREACH(map, &port->sp_maps, m_link) {
605 			if (map->m_region_num != region_num)
606 				continue;
607 
608 			/* Found! */
609 			*addr = map->m_base;
610 			*size = map->m_size;
611 			return (0);
612 		}
613 	}
614 
615 	return (ENOENT);
616 }
617 
618 /**
619  * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT().
620  */
621 u_int
622 bcma_get_intr_count(device_t dev, device_t child)
623 {
624 	struct bcma_devinfo *dinfo;
625 
626 	/* delegate non-bus-attached devices to our parent */
627 	if (device_get_parent(child) != dev)
628 		return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child));
629 
630 	dinfo = device_get_ivars(child);
631 	return (dinfo->num_intrs);
632 }
633 
634 /**
635  * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_IVEC().
636  */
637 int
638 bcma_get_intr_ivec(device_t dev, device_t child, u_int intr, u_int *ivec)
639 {
640 	struct bcma_devinfo	*dinfo;
641 	struct bcma_intr	*desc;
642 
643 	/* delegate non-bus-attached devices to our parent */
644 	if (device_get_parent(child) != dev) {
645 		return (BHND_BUS_GET_INTR_IVEC(device_get_parent(dev), child,
646 		    intr, ivec));
647 	}
648 
649 	dinfo = device_get_ivars(child);
650 
651 	STAILQ_FOREACH(desc, &dinfo->intrs, i_link) {
652 		if (desc->i_sel == intr) {
653 			*ivec = desc->i_busline;
654 			return (0);
655 		}
656 	}
657 
658 	/* Not found */
659 	return (ENXIO);
660 }
661 
662 /**
663  * Scan the device enumeration ROM table, adding all valid discovered cores to
664  * the bus.
665  *
666  * @param bus The bcma bus.
667  */
668 int
669 bcma_add_children(device_t bus)
670 {
671 	bhnd_erom_t			*erom;
672 	struct bcma_erom		*bcma_erom;
673 	struct bhnd_erom_io		*eio;
674 	const struct bhnd_chipid	*cid;
675 	struct bcma_corecfg		*corecfg;
676 	struct bcma_devinfo		*dinfo;
677 	device_t			 child;
678 	int				 error;
679 
680 	cid = BHND_BUS_GET_CHIPID(bus, bus);
681 	corecfg = NULL;
682 
683 	/* Allocate our EROM parser */
684 	eio = bhnd_erom_iores_new(bus, BCMA_EROM_RID);
685 	erom = bhnd_erom_alloc(&bcma_erom_parser, cid, eio);
686 	if (erom == NULL) {
687 		bhnd_erom_io_fini(eio);
688 		return (ENODEV);
689 	}
690 
691 	/* Add all cores. */
692 	bcma_erom = (struct bcma_erom *)erom;
693 	while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) {
694 		/* Add the child device */
695 		child = BUS_ADD_CHILD(bus, 0, NULL, -1);
696 		if (child == NULL) {
697 			error = ENXIO;
698 			goto cleanup;
699 		}
700 
701 		/* Initialize device ivars */
702 		dinfo = device_get_ivars(child);
703 		if ((error = bcma_init_dinfo(bus, child, dinfo, corecfg)))
704 			goto cleanup;
705 
706 		/* The dinfo instance now owns the corecfg value */
707 		corecfg = NULL;
708 
709 		/* If pins are floating or the hardware is otherwise
710 		 * unpopulated, the device shouldn't be used. */
711 		if (bhnd_is_hw_disabled(child))
712 			device_disable(child);
713 
714 		/* Issue bus callback for fully initialized child. */
715 		BHND_BUS_CHILD_ADDED(bus, child);
716 	}
717 
718 	/* EOF while parsing cores is expected */
719 	if (error == ENOENT)
720 		error = 0;
721 
722 cleanup:
723 	bhnd_erom_free(erom);
724 
725 	if (corecfg != NULL)
726 		bcma_free_corecfg(corecfg);
727 
728 	if (error)
729 		device_delete_children(bus);
730 
731 	return (error);
732 }
733 
734 
735 static device_method_t bcma_methods[] = {
736 	/* Device interface */
737 	DEVMETHOD(device_probe,			bcma_probe),
738 	DEVMETHOD(device_attach,		bcma_attach),
739 	DEVMETHOD(device_detach,		bcma_detach),
740 
741 	/* Bus interface */
742 	DEVMETHOD(bus_add_child,		bcma_add_child),
743 	DEVMETHOD(bus_child_deleted,		bcma_child_deleted),
744 	DEVMETHOD(bus_read_ivar,		bcma_read_ivar),
745 	DEVMETHOD(bus_write_ivar,		bcma_write_ivar),
746 	DEVMETHOD(bus_get_resource_list,	bcma_get_resource_list),
747 
748 	/* BHND interface */
749 	DEVMETHOD(bhnd_bus_get_erom_class,	bcma_get_erom_class),
750 	DEVMETHOD(bhnd_bus_read_ioctl,		bcma_read_ioctl),
751 	DEVMETHOD(bhnd_bus_write_ioctl,		bcma_write_ioctl),
752 	DEVMETHOD(bhnd_bus_read_iost,		bcma_read_iost),
753 	DEVMETHOD(bhnd_bus_is_hw_suspended,	bcma_is_hw_suspended),
754 	DEVMETHOD(bhnd_bus_reset_hw,		bcma_reset_hw),
755 	DEVMETHOD(bhnd_bus_suspend_hw,		bcma_suspend_hw),
756 	DEVMETHOD(bhnd_bus_read_config,		bcma_read_config),
757 	DEVMETHOD(bhnd_bus_write_config,	bcma_write_config),
758 	DEVMETHOD(bhnd_bus_get_port_count,	bcma_get_port_count),
759 	DEVMETHOD(bhnd_bus_get_region_count,	bcma_get_region_count),
760 	DEVMETHOD(bhnd_bus_get_port_rid,	bcma_get_port_rid),
761 	DEVMETHOD(bhnd_bus_decode_port_rid,	bcma_decode_port_rid),
762 	DEVMETHOD(bhnd_bus_get_region_addr,	bcma_get_region_addr),
763 	DEVMETHOD(bhnd_bus_get_intr_count,	bcma_get_intr_count),
764 	DEVMETHOD(bhnd_bus_get_intr_ivec,	bcma_get_intr_ivec),
765 
766 	DEVMETHOD_END
767 };
768 
769 DEFINE_CLASS_1(bhnd, bcma_driver, bcma_methods, sizeof(struct bcma_softc), bhnd_driver);
770 MODULE_VERSION(bcma, 1);
771 MODULE_DEPEND(bcma, bhnd, 1, 1, 1);
772