]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/siba/siba.c
MFV r337200:
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / siba / siba.c
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/refcount.h>
43 #include <sys/systm.h>
44
45 #include <machine/bus.h>
46
47 #include <dev/bhnd/cores/chipc/chipc.h>
48 #include <dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.h>
49
50 #include "siba_eromvar.h"
51
52 #include "sibareg.h"
53 #include "sibavar.h"
54
55 /* RID used when allocating EROM resources */
56 #define SIBA_EROM_RID   0
57
58 static bhnd_erom_class_t *
59 siba_get_erom_class(driver_t *driver)
60 {
61         return (&siba_erom_parser);
62 }
63
64 int
65 siba_probe(device_t dev)
66 {
67         device_set_desc(dev, "SIBA BHND bus");
68         return (BUS_PROBE_DEFAULT);
69 }
70
71 /**
72  * Default siba(4) bus driver implementation of DEVICE_ATTACH().
73  * 
74  * This implementation initializes internal siba(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 siba_attach(device_t dev)
80 {
81         struct siba_softc       *sc;
82         int                      error;
83
84         sc = device_get_softc(dev);
85         sc->dev = dev;
86
87         SIBA_LOCK_INIT(sc);
88
89         /* Enumerate children */
90         if ((error = siba_add_children(dev))) {
91                 device_delete_children(dev);
92                 SIBA_LOCK_DESTROY(sc);
93                 return (error);
94         }
95
96         return (0);
97 }
98
99 int
100 siba_detach(device_t dev)
101 {
102         struct siba_softc       *sc;
103         int                      error;
104
105         sc = device_get_softc(dev);
106
107         if ((error = bhnd_generic_detach(dev)))
108                 return (error);
109
110         SIBA_LOCK_DESTROY(sc);
111
112         return (0);
113 }
114
115 int
116 siba_resume(device_t dev)
117 {
118         return (bhnd_generic_resume(dev));
119 }
120
121 int
122 siba_suspend(device_t dev)
123 {
124         return (bhnd_generic_suspend(dev));
125 }
126
127 static int
128 siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
129 {
130         struct siba_softc               *sc;
131         const struct siba_devinfo       *dinfo;
132         const struct bhnd_core_info     *cfg;
133
134         sc = device_get_softc(dev);
135         dinfo = device_get_ivars(child);
136         cfg = &dinfo->core_id.core_info;
137         
138         switch (index) {
139         case BHND_IVAR_VENDOR:
140                 *result = cfg->vendor;
141                 return (0);
142         case BHND_IVAR_DEVICE:
143                 *result = cfg->device;
144                 return (0);
145         case BHND_IVAR_HWREV:
146                 *result = cfg->hwrev;
147                 return (0);
148         case BHND_IVAR_DEVICE_CLASS:
149                 *result = bhnd_core_class(cfg);
150                 return (0);
151         case BHND_IVAR_VENDOR_NAME:
152                 *result = (uintptr_t) bhnd_vendor_name(cfg->vendor);
153                 return (0);
154         case BHND_IVAR_DEVICE_NAME:
155                 *result = (uintptr_t) bhnd_core_name(cfg);
156                 return (0);
157         case BHND_IVAR_CORE_INDEX:
158                 *result = cfg->core_idx;
159                 return (0);
160         case BHND_IVAR_CORE_UNIT:
161                 *result = cfg->unit;
162                 return (0);
163         case BHND_IVAR_PMU_INFO:
164                 SIBA_LOCK(sc);
165                 switch (dinfo->pmu_state) {
166                 case SIBA_PMU_NONE:
167                         *result = (uintptr_t)NULL;
168                         SIBA_UNLOCK(sc);
169                         return (0);
170
171                 case SIBA_PMU_BHND:
172                         *result = (uintptr_t)dinfo->pmu.bhnd_info;
173                         SIBA_UNLOCK(sc);
174                         return (0);
175
176                 case SIBA_PMU_PWRCTL:
177                 case SIBA_PMU_FIXED:
178                         *result = (uintptr_t)NULL;
179                         SIBA_UNLOCK(sc);
180                         return (0);
181                 }
182
183                 panic("invalid PMU state: %d", dinfo->pmu_state);
184                 return (ENXIO);
185
186         default:
187                 return (ENOENT);
188         }
189 }
190
191 static int
192 siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
193 {
194         struct siba_softc       *sc;
195         struct siba_devinfo     *dinfo;
196
197         sc = device_get_softc(dev);
198         dinfo = device_get_ivars(child);
199
200         switch (index) {
201         case BHND_IVAR_VENDOR:
202         case BHND_IVAR_DEVICE:
203         case BHND_IVAR_HWREV:
204         case BHND_IVAR_DEVICE_CLASS:
205         case BHND_IVAR_VENDOR_NAME:
206         case BHND_IVAR_DEVICE_NAME:
207         case BHND_IVAR_CORE_INDEX:
208         case BHND_IVAR_CORE_UNIT:
209                 return (EINVAL);
210         case BHND_IVAR_PMU_INFO:
211                 SIBA_LOCK(sc);
212                 switch (dinfo->pmu_state) {
213                 case SIBA_PMU_NONE:
214                 case SIBA_PMU_BHND:
215                         dinfo->pmu.bhnd_info = (void *)value;
216                         dinfo->pmu_state = SIBA_PMU_BHND;
217                         SIBA_UNLOCK(sc);
218                         return (0);
219
220                 case SIBA_PMU_PWRCTL:
221                 case SIBA_PMU_FIXED:
222                         panic("bhnd_set_pmu_info() called with siba PMU state "
223                             "%d", dinfo->pmu_state);
224                         return (ENXIO);
225                 }
226
227                 panic("invalid PMU state: %d", dinfo->pmu_state);
228                 return (ENXIO);
229
230         default:
231                 return (ENOENT);
232         }
233 }
234
235 static struct resource_list *
236 siba_get_resource_list(device_t dev, device_t child)
237 {
238         struct siba_devinfo *dinfo = device_get_ivars(child);
239         return (&dinfo->resources);
240 }
241
242 /* BHND_BUS_ALLOC_PMU() */
243 static int
244 siba_alloc_pmu(device_t dev, device_t child)
245 {
246         struct siba_softc       *sc;
247         struct siba_devinfo     *dinfo;
248         device_t                 chipc;
249         device_t                 pwrctl;
250         struct chipc_caps        ccaps;
251         siba_pmu_state           pmu_state;
252         int                      error;
253
254         if (device_get_parent(child) != dev)
255                 return (EINVAL);
256
257         sc = device_get_softc(dev);
258         dinfo = device_get_ivars(child);
259         pwrctl = NULL;
260
261         /* Fetch ChipCommon capability flags */
262         chipc = bhnd_retain_provider(child, BHND_SERVICE_CHIPC);
263         if (chipc != NULL) {
264                 ccaps = *BHND_CHIPC_GET_CAPS(chipc);
265                 bhnd_release_provider(child, chipc, BHND_SERVICE_CHIPC);
266         } else {
267                 memset(&ccaps, 0, sizeof(ccaps));
268         }
269
270         /* Defer to bhnd(4)'s PMU implementation if ChipCommon exists and
271          * advertises PMU support */
272         if (ccaps.pmu) {
273                 if ((error = bhnd_generic_alloc_pmu(dev, child)))
274                         return (error);
275
276                 KASSERT(dinfo->pmu_state == SIBA_PMU_BHND,
277                     ("unexpected PMU state: %d", dinfo->pmu_state));
278
279                 return (0);
280         }
281
282         /*
283          * This is either a legacy PWRCTL chipset, or the device does not
284          * support dynamic clock control.
285          * 
286          * We need to map all bhnd(4) bus PMU to PWRCTL or no-op operations.
287          */
288         if (ccaps.pwr_ctrl) {
289                 pmu_state = SIBA_PMU_PWRCTL;
290                 pwrctl = bhnd_retain_provider(child, BHND_SERVICE_PWRCTL);
291                 if (pwrctl == NULL) {
292                         device_printf(dev, "PWRCTL not found\n");
293                         return (ENODEV);
294                 }
295         } else {
296                 pmu_state = SIBA_PMU_FIXED;
297                 pwrctl = NULL;
298         }
299
300         SIBA_LOCK(sc);
301
302         /* Per-core PMU state already allocated? */
303         if (dinfo->pmu_state != SIBA_PMU_NONE) {
304                 panic("duplicate PMU allocation for %s",
305                     device_get_nameunit(child));
306         }
307
308         /* Update the child's PMU allocation state, and transfer ownership of
309          * the PWRCTL provider reference (if any) */
310         dinfo->pmu_state = pmu_state;
311         dinfo->pmu.pwrctl = pwrctl;
312
313         SIBA_UNLOCK(sc);
314
315         return (0);
316 }
317
318 /* BHND_BUS_RELEASE_PMU() */
319 static int
320 siba_release_pmu(device_t dev, device_t child)
321 {
322         struct siba_softc       *sc;
323         struct siba_devinfo     *dinfo;
324         device_t                 pwrctl;
325         int                      error;
326
327         if (device_get_parent(child) != dev)
328                 return (EINVAL);
329
330         sc = device_get_softc(dev);
331         dinfo = device_get_ivars(child);
332
333         SIBA_LOCK(sc);
334         switch(dinfo->pmu_state) {
335         case SIBA_PMU_NONE:
336                 panic("pmu over-release for %s", device_get_nameunit(child));
337                 SIBA_UNLOCK(sc);
338                 return (ENXIO);
339
340         case SIBA_PMU_BHND:
341                 SIBA_UNLOCK(sc);
342                 return (bhnd_generic_release_pmu(dev, child));
343
344         case SIBA_PMU_PWRCTL:
345                 /* Requesting BHND_CLOCK_DYN releases any outstanding clock
346                  * reservations */
347                 pwrctl = dinfo->pmu.pwrctl;
348                 error = bhnd_pwrctl_request_clock(pwrctl, child,
349                     BHND_CLOCK_DYN);
350                 if (error) {
351                         SIBA_UNLOCK(sc);
352                         return (error);
353                 }
354
355                 /* Clean up the child's PMU state */
356                 dinfo->pmu_state = SIBA_PMU_NONE;
357                 dinfo->pmu.pwrctl = NULL;
358                 SIBA_UNLOCK(sc);
359
360                 /* Release the provider reference */
361                 bhnd_release_provider(child, pwrctl, BHND_SERVICE_PWRCTL);
362                 return (0);
363
364         case SIBA_PMU_FIXED:
365                 /* Clean up the child's PMU state */
366                 KASSERT(dinfo->pmu.pwrctl == NULL,
367                     ("PWRCTL reference with FIXED state"));
368
369                 dinfo->pmu_state = SIBA_PMU_NONE;
370                 dinfo->pmu.pwrctl = NULL;
371                 SIBA_UNLOCK(sc);
372         }
373
374         panic("invalid PMU state: %d", dinfo->pmu_state);
375 }
376
377 /* BHND_BUS_GET_CLOCK_LATENCY() */
378 static int
379 siba_get_clock_latency(device_t dev, device_t child, bhnd_clock clock,
380     u_int *latency)
381 {
382         struct siba_softc       *sc;
383         struct siba_devinfo     *dinfo;
384         int                      error;
385
386         if (device_get_parent(child) != dev)
387                 return (EINVAL);
388
389         sc = device_get_softc(dev);
390         dinfo = device_get_ivars(child);
391
392         SIBA_LOCK(sc);
393         switch(dinfo->pmu_state) {
394         case SIBA_PMU_NONE:
395                 panic("no active PMU request state");
396
397                 SIBA_UNLOCK(sc);
398                 return (ENXIO);
399
400         case SIBA_PMU_BHND:
401                 SIBA_UNLOCK(sc);
402                 return (bhnd_generic_get_clock_latency(dev, child, clock,
403                     latency));
404
405         case SIBA_PMU_PWRCTL:
406                  error = bhnd_pwrctl_get_clock_latency(dinfo->pmu.pwrctl, clock,
407                     latency);
408                  SIBA_UNLOCK(sc);
409
410                  return (error);
411
412         case SIBA_PMU_FIXED:
413                 SIBA_UNLOCK(sc);
414
415                 /* HT clock is always available, and incurs no transition
416                  * delay. */
417                 switch (clock) {
418                 case BHND_CLOCK_HT:
419                         *latency = 0;
420                         return (0);
421
422                 default:
423                         return (ENODEV);
424                 }
425
426                 return (ENODEV);
427         }
428
429         panic("invalid PMU state: %d", dinfo->pmu_state);
430 }
431
432 /* BHND_BUS_GET_CLOCK_FREQ() */
433 static int
434 siba_get_clock_freq(device_t dev, device_t child, bhnd_clock clock,
435     u_int *freq)
436 {
437         struct siba_softc       *sc;
438         struct siba_devinfo     *dinfo;
439         int                      error;
440
441         if (device_get_parent(child) != dev)
442                 return (EINVAL);
443
444         sc = device_get_softc(dev);
445         dinfo = device_get_ivars(child);
446
447         SIBA_LOCK(sc);
448         switch(dinfo->pmu_state) {
449         case SIBA_PMU_NONE:
450                 panic("no active PMU request state");
451
452                 SIBA_UNLOCK(sc);
453                 return (ENXIO);
454
455         case SIBA_PMU_BHND:
456                 SIBA_UNLOCK(sc);
457                 return (bhnd_generic_get_clock_freq(dev, child, clock, freq));
458
459         case SIBA_PMU_PWRCTL:
460                 error = bhnd_pwrctl_get_clock_freq(dinfo->pmu.pwrctl, clock,
461                     freq);
462                 SIBA_UNLOCK(sc);
463
464                 return (error);
465
466         case SIBA_PMU_FIXED:
467                 SIBA_UNLOCK(sc);
468
469                 return (ENODEV);
470         }
471
472         panic("invalid PMU state: %d", dinfo->pmu_state);
473 }
474
475 /* BHND_BUS_REQUEST_EXT_RSRC() */
476 static int
477 siba_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
478 {
479         struct siba_softc       *sc;
480         struct siba_devinfo     *dinfo;
481
482         if (device_get_parent(child) != dev)
483                 return (EINVAL);
484
485         sc = device_get_softc(dev);
486         dinfo = device_get_ivars(child);
487
488         SIBA_LOCK(sc);
489         switch(dinfo->pmu_state) {
490         case SIBA_PMU_NONE:
491                 panic("no active PMU request state");
492
493                 SIBA_UNLOCK(sc);
494                 return (ENXIO);
495
496         case SIBA_PMU_BHND:
497                 SIBA_UNLOCK(sc);
498                 return (bhnd_generic_request_ext_rsrc(dev, child, rsrc));
499
500         case SIBA_PMU_PWRCTL:
501         case SIBA_PMU_FIXED:
502                 /* HW does not support per-core external resources */
503                 SIBA_UNLOCK(sc);
504                 return (ENODEV);
505         }
506
507         panic("invalid PMU state: %d", dinfo->pmu_state);
508 }
509
510 /* BHND_BUS_RELEASE_EXT_RSRC() */
511 static int
512 siba_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
513 {
514         struct siba_softc       *sc;
515         struct siba_devinfo     *dinfo;
516
517         if (device_get_parent(child) != dev)
518                 return (EINVAL);
519
520         sc = device_get_softc(dev);
521         dinfo = device_get_ivars(child);
522
523         SIBA_LOCK(sc);
524         switch(dinfo->pmu_state) {
525         case SIBA_PMU_NONE:
526                 panic("no active PMU request state");
527
528                 SIBA_UNLOCK(sc);
529                 return (ENXIO);
530
531         case SIBA_PMU_BHND:
532                 SIBA_UNLOCK(sc);
533                 return (bhnd_generic_release_ext_rsrc(dev, child, rsrc));
534
535         case SIBA_PMU_PWRCTL:
536         case SIBA_PMU_FIXED:
537                 /* HW does not support per-core external resources */
538                 SIBA_UNLOCK(sc);
539                 return (ENODEV);
540         }
541
542         panic("invalid PMU state: %d", dinfo->pmu_state);
543 }
544
545 /* BHND_BUS_REQUEST_CLOCK() */
546 static int
547 siba_request_clock(device_t dev, device_t child, bhnd_clock clock)
548 {
549         struct siba_softc       *sc;
550         struct siba_devinfo     *dinfo;
551         int                      error;
552
553         if (device_get_parent(child) != dev)
554                 return (EINVAL);
555
556         sc = device_get_softc(dev);
557         dinfo = device_get_ivars(child);
558
559         SIBA_LOCK(sc);
560         switch(dinfo->pmu_state) {
561         case SIBA_PMU_NONE:
562                 panic("no active PMU request state");
563
564                 SIBA_UNLOCK(sc);
565                 return (ENXIO);
566
567         case SIBA_PMU_BHND:
568                 SIBA_UNLOCK(sc);
569                 return (bhnd_generic_request_clock(dev, child, clock));
570
571         case SIBA_PMU_PWRCTL:
572                 error = bhnd_pwrctl_request_clock(dinfo->pmu.pwrctl, child,
573                     clock);
574                 SIBA_UNLOCK(sc);
575
576                 return (error);
577
578         case SIBA_PMU_FIXED:
579                 SIBA_UNLOCK(sc);
580
581                 /* HT clock is always available, and fulfills any of the
582                  * following clock requests */
583                 switch (clock) {
584                 case BHND_CLOCK_DYN:
585                 case BHND_CLOCK_ILP:
586                 case BHND_CLOCK_ALP:
587                 case BHND_CLOCK_HT:
588                         return (0);
589
590                 default:
591                         return (ENODEV);
592                 }
593         }
594
595         panic("invalid PMU state: %d", dinfo->pmu_state);
596 }
597
598 /* BHND_BUS_ENABLE_CLOCKS() */
599 static int
600 siba_enable_clocks(device_t dev, device_t child, uint32_t clocks)
601 {
602         struct siba_softc       *sc;
603         struct siba_devinfo     *dinfo;
604
605         if (device_get_parent(child) != dev)
606                 return (EINVAL);
607
608         sc = device_get_softc(dev);
609         dinfo = device_get_ivars(child);
610
611         SIBA_LOCK(sc);
612         switch(dinfo->pmu_state) {
613         case SIBA_PMU_NONE:
614                 panic("no active PMU request state");
615
616                 SIBA_UNLOCK(sc);
617                 return (ENXIO);
618
619         case SIBA_PMU_BHND:
620                 SIBA_UNLOCK(sc);
621                 return (bhnd_generic_enable_clocks(dev, child, clocks));
622
623         case SIBA_PMU_PWRCTL:
624         case SIBA_PMU_FIXED:
625                 SIBA_UNLOCK(sc);
626
627                 /* All (supported) clocks are already enabled by default */
628                 clocks &= ~(BHND_CLOCK_DYN |
629                             BHND_CLOCK_ILP |
630                             BHND_CLOCK_ALP |
631                             BHND_CLOCK_HT);
632
633                 if (clocks != 0) {
634                         device_printf(dev, "%s requested unknown clocks: %#x\n",
635                             device_get_nameunit(child), clocks);
636                         return (ENODEV);
637                 }
638
639                 return (0);
640         }
641
642         panic("invalid PMU state: %d", dinfo->pmu_state);
643 }
644
645 static int
646 siba_read_iost(device_t dev, device_t child, uint16_t *iost)
647 {
648         uint32_t        tmhigh;
649         int             error;
650
651         error = bhnd_read_config(child, SIBA_CFG0_TMSTATEHIGH, &tmhigh, 4);
652         if (error)
653                 return (error);
654
655         *iost = (SIBA_REG_GET(tmhigh, TMH_SISF));
656         return (0);
657 }
658
659 static int
660 siba_read_ioctl(device_t dev, device_t child, uint16_t *ioctl)
661 {
662         uint32_t        ts_low;
663         int             error;
664
665         if ((error = bhnd_read_config(child, SIBA_CFG0_TMSTATELOW, &ts_low, 4)))
666                 return (error);
667
668         *ioctl = (SIBA_REG_GET(ts_low, TML_SICF));
669         return (0);
670 }
671
672 static int
673 siba_write_ioctl(device_t dev, device_t child, uint16_t value, uint16_t mask)
674 {
675         struct siba_devinfo     *dinfo;
676         struct bhnd_resource    *r;
677         uint32_t                 ts_low, ts_mask;
678
679         if (device_get_parent(child) != dev)
680                 return (EINVAL);
681
682         /* Fetch CFG0 mapping */
683         dinfo = device_get_ivars(child);
684         if ((r = dinfo->cfg_res[0]) == NULL)
685                 return (ENODEV);
686
687         /* Mask and set TMSTATELOW core flag bits */
688         ts_mask = (mask << SIBA_TML_SICF_SHIFT) & SIBA_TML_SICF_MASK;
689         ts_low = (value << SIBA_TML_SICF_SHIFT) & ts_mask;
690
691         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
692             ts_low, ts_mask);
693         return (0);
694 }
695
696 static bool
697 siba_is_hw_suspended(device_t dev, device_t child)
698 {
699         uint32_t                ts_low;
700         uint16_t                ioctl;
701         int                     error;
702
703         /* Fetch target state */
704         error = bhnd_read_config(child, SIBA_CFG0_TMSTATELOW, &ts_low, 4);
705         if (error) {
706                 device_printf(child, "error reading HW reset state: %d\n",
707                     error);
708                 return (true);
709         }
710
711         /* Is core held in RESET? */
712         if (ts_low & SIBA_TML_RESET)
713                 return (true);
714
715         /* Is target reject enabled? */
716         if (ts_low & SIBA_TML_REJ_MASK)
717                 return (true);
718
719         /* Is core clocked? */
720         ioctl = SIBA_REG_GET(ts_low, TML_SICF);
721         if (!(ioctl & BHND_IOCTL_CLK_EN))
722                 return (true);
723
724         return (false);
725 }
726
727 static int
728 siba_reset_hw(device_t dev, device_t child, uint16_t ioctl,
729     uint16_t reset_ioctl)
730 {
731         struct siba_devinfo             *dinfo;
732         struct bhnd_resource            *r;
733         uint32_t                         ts_low, imstate;
734         uint16_t                         clkflags;
735         int                              error;
736
737         if (device_get_parent(child) != dev)
738                 return (EINVAL);
739
740         dinfo = device_get_ivars(child);
741
742         /* Can't suspend the core without access to the CFG0 registers */
743         if ((r = dinfo->cfg_res[0]) == NULL)
744                 return (ENODEV);
745
746         /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
747         clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
748         if (ioctl & clkflags)
749                 return (EINVAL);
750
751         /* Place core into known RESET state */
752         if ((error = bhnd_suspend_hw(child, reset_ioctl)))
753                 return (error);
754
755         /* Set RESET, clear REJ, set the caller's IOCTL flags, and
756          * force clocks to ensure the signal propagates throughout the
757          * core. */
758         ts_low = SIBA_TML_RESET |
759                  (ioctl << SIBA_TML_SICF_SHIFT) |
760                  (BHND_IOCTL_CLK_EN << SIBA_TML_SICF_SHIFT) |
761                  (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT);
762
763         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
764             ts_low, UINT32_MAX);
765
766         /* Clear any target errors */
767         if (bhnd_bus_read_4(r, SIBA_CFG0_TMSTATEHIGH) & SIBA_TMH_SERR) {
768                 siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATEHIGH,
769                     0x0, SIBA_TMH_SERR);
770         }
771
772         /* Clear any initiator errors */
773         imstate = bhnd_bus_read_4(r, SIBA_CFG0_IMSTATE);
774         if (imstate & (SIBA_IM_IBE|SIBA_IM_TO)) {
775                 siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE, 0x0,
776                     SIBA_IM_IBE|SIBA_IM_TO);
777         }
778
779         /* Release from RESET while leaving clocks forced, ensuring the
780          * signal propagates throughout the core */
781         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
782             SIBA_TML_RESET);
783
784         /* The core should now be active; we can clear the BHND_IOCTL_CLK_FORCE
785          * bit and allow the core to manage clock gating. */
786         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
787             (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT));
788
789         return (0);
790 }
791
792 static int
793 siba_suspend_hw(device_t dev, device_t child, uint16_t ioctl)
794 {
795         struct siba_softc               *sc;
796         struct siba_devinfo             *dinfo;
797         struct bhnd_resource            *r;
798         uint32_t                         idl, ts_low, ts_mask;
799         uint16_t                         cflags, clkflags;
800         int                              error;
801
802         if (device_get_parent(child) != dev)
803                 return (EINVAL);
804
805         sc = device_get_softc(dev);
806         dinfo = device_get_ivars(child);
807
808         /* Can't suspend the core without access to the CFG0 registers */
809         if ((r = dinfo->cfg_res[0]) == NULL)
810                 return (ENODEV);
811
812         /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
813         clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
814         if (ioctl & clkflags)
815                 return (EINVAL);
816
817         /* Already in RESET? */
818         ts_low = bhnd_bus_read_4(r, SIBA_CFG0_TMSTATELOW);
819         if (ts_low & SIBA_TML_RESET)
820                 return (0);
821
822         /* If clocks are already disabled, we can place the core directly
823          * into RESET|REJ while setting the caller's IOCTL flags. */
824         cflags = SIBA_REG_GET(ts_low, TML_SICF);
825         if (!(cflags & BHND_IOCTL_CLK_EN)) {
826                 ts_low = SIBA_TML_RESET | SIBA_TML_REJ |
827                          (ioctl << SIBA_TML_SICF_SHIFT);
828                 ts_mask = SIBA_TML_RESET | SIBA_TML_REJ | SIBA_TML_SICF_MASK;
829
830                 siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
831                     ts_low, ts_mask);
832                 return (0);
833         }
834
835         /* Reject further transactions reaching this core */
836         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
837             SIBA_TML_REJ, SIBA_TML_REJ);
838
839         /* Wait for transaction busy flag to clear for all transactions
840          * initiated by this core */
841         error = siba_wait_target_state(child, dinfo, SIBA_CFG0_TMSTATEHIGH,
842             0x0, SIBA_TMH_BUSY, 100000);
843         if (error)
844                 return (error);
845
846         /* If this is an initiator core, we need to reject initiator
847          * transactions too. */
848         idl = bhnd_bus_read_4(r, SIBA_CFG0_IDLOW);
849         if (idl & SIBA_IDL_INIT) {
850                 /* Reject further initiator transactions */
851                 siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
852                     SIBA_IM_RJ, SIBA_IM_RJ);
853
854                 /* Wait for initiator busy flag to clear */
855                 error = siba_wait_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
856                     0x0, SIBA_IM_BY, 100000);
857                 if (error)
858                         return (error);
859         }
860
861         /* Put the core into RESET, set the caller's IOCTL flags, and
862          * force clocks to ensure the RESET signal propagates throughout the
863          * core. */
864         ts_low = SIBA_TML_RESET |
865                  (ioctl << SIBA_TML_SICF_SHIFT) |
866                  (BHND_IOCTL_CLK_EN << SIBA_TML_SICF_SHIFT) |
867                  (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT);
868         ts_mask = SIBA_TML_RESET |
869                   SIBA_TML_SICF_MASK;
870
871         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, ts_low,
872             ts_mask);
873
874         /* Give RESET ample time */
875         DELAY(10);
876
877         /* Clear previously asserted initiator reject */
878         if (idl & SIBA_IDL_INIT) {
879                 siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE, 0x0,
880                     SIBA_IM_RJ);
881         }
882
883         /* Disable all clocks, leaving RESET and REJ asserted */
884         siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
885             (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE) << SIBA_TML_SICF_SHIFT);
886
887         /*
888          * Core is now in RESET.
889          *
890          * If the core holds any PWRCTL clock reservations, we need to release
891          * those now. This emulates the standard bhnd(4) PMU behavior of RESET
892          * automatically clearing clkctl
893          */
894         SIBA_LOCK(sc);
895         if (dinfo->pmu_state == SIBA_PMU_PWRCTL) {
896                 error = bhnd_pwrctl_request_clock(dinfo->pmu.pwrctl, child,
897                     BHND_CLOCK_DYN);
898                 SIBA_UNLOCK(sc);
899
900                 if (error) {
901                         device_printf(child, "failed to release clock request: "
902                             "%d", error);
903                         return (error);
904                 }
905
906                 return (0);
907         } else {
908                 SIBA_UNLOCK(sc);
909                 return (0);
910         }
911 }
912
913 static int
914 siba_read_config(device_t dev, device_t child, bus_size_t offset, void *value,
915     u_int width)
916 {
917         struct siba_devinfo     *dinfo;
918         rman_res_t               r_size;
919
920         /* Must be directly attached */
921         if (device_get_parent(child) != dev)
922                 return (EINVAL);
923
924         /* CFG0 registers must be available */
925         dinfo = device_get_ivars(child);
926         if (dinfo->cfg_res[0] == NULL)
927                 return (ENODEV);
928
929         /* Offset must fall within CFG0 */
930         r_size = rman_get_size(dinfo->cfg_res[0]->res);
931         if (r_size < offset || r_size - offset < width)
932                 return (EFAULT);
933
934         switch (width) {
935         case 1:
936                 *((uint8_t *)value) = bhnd_bus_read_1(dinfo->cfg_res[0],
937                     offset);
938                 return (0);
939         case 2:
940                 *((uint16_t *)value) = bhnd_bus_read_2(dinfo->cfg_res[0],
941                     offset);
942                 return (0);
943         case 4:
944                 *((uint32_t *)value) = bhnd_bus_read_4(dinfo->cfg_res[0],
945                     offset);
946                 return (0);
947         default:
948                 return (EINVAL);
949         }
950 }
951
952 static int
953 siba_write_config(device_t dev, device_t child, bus_size_t offset,
954     const void *value, u_int width)
955 {
956         struct siba_devinfo     *dinfo;
957         struct bhnd_resource    *r;
958         rman_res_t               r_size;
959
960         /* Must be directly attached */
961         if (device_get_parent(child) != dev)
962                 return (EINVAL);
963
964         /* CFG0 registers must be available */
965         dinfo = device_get_ivars(child);
966         if ((r = dinfo->cfg_res[0]) == NULL)
967                 return (ENODEV);
968
969         /* Offset must fall within CFG0 */
970         r_size = rman_get_size(r->res);
971         if (r_size < offset || r_size - offset < width)
972                 return (EFAULT);
973
974         switch (width) {
975         case 1:
976                 bhnd_bus_write_1(r, offset, *(const uint8_t *)value);
977                 return (0);
978         case 2:
979                 bhnd_bus_write_2(r, offset, *(const uint8_t *)value);
980                 return (0);
981         case 4:
982                 bhnd_bus_write_4(r, offset, *(const uint8_t *)value);
983                 return (0);
984         default:
985                 return (EINVAL);
986         }
987 }
988
989 static u_int
990 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
991 {
992         struct siba_devinfo *dinfo;
993
994         /* delegate non-bus-attached devices to our parent */
995         if (device_get_parent(child) != dev)
996                 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
997                     type));
998
999         dinfo = device_get_ivars(child);
1000         return (siba_port_count(&dinfo->core_id, type));
1001 }
1002
1003 static u_int
1004 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
1005     u_int port)
1006 {
1007         struct siba_devinfo     *dinfo;
1008
1009         /* delegate non-bus-attached devices to our parent */
1010         if (device_get_parent(child) != dev)
1011                 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
1012                     type, port));
1013
1014         dinfo = device_get_ivars(child);
1015         return (siba_port_region_count(&dinfo->core_id, type, port));
1016 }
1017
1018 static int
1019 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
1020     u_int port_num, u_int region_num)
1021 {
1022         struct siba_devinfo     *dinfo;
1023         struct siba_addrspace   *addrspace;
1024         struct siba_cfg_block   *cfg;
1025
1026         /* delegate non-bus-attached devices to our parent */
1027         if (device_get_parent(child) != dev)
1028                 return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
1029                     port_type, port_num, region_num));
1030
1031         dinfo = device_get_ivars(child);
1032
1033         /* Look for a matching addrspace entry */
1034         addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
1035         if (addrspace != NULL)
1036                 return (addrspace->sa_rid);
1037
1038         /* Try the config blocks */
1039         cfg = siba_find_cfg_block(dinfo, port_type, port_num, region_num);
1040         if (cfg != NULL)
1041                 return (cfg->cb_rid);
1042
1043         /* Not found */
1044         return (-1);
1045 }
1046
1047 static int
1048 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
1049     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
1050 {
1051         struct siba_devinfo     *dinfo;
1052
1053         /* delegate non-bus-attached devices to our parent */
1054         if (device_get_parent(child) != dev)
1055                 return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
1056                     type, rid, port_type, port_num, region_num));
1057
1058         dinfo = device_get_ivars(child);
1059
1060         /* Ports are always memory mapped */
1061         if (type != SYS_RES_MEMORY)
1062                 return (EINVAL);
1063
1064         /* Look for a matching addrspace entry */
1065         for (u_int i = 0; i < dinfo->core_id.num_admatch; i++) {
1066                 if (dinfo->addrspace[i].sa_rid != rid)
1067                         continue;
1068
1069                 *port_type = BHND_PORT_DEVICE;
1070                 *port_num = siba_addrspace_device_port(i);
1071                 *region_num = siba_addrspace_device_region(i);
1072                 return (0);
1073         }
1074
1075         /* Try the config blocks */
1076         for (u_int i = 0; i < dinfo->core_id.num_cfg_blocks; i++) {
1077                 if (dinfo->cfg[i].cb_rid != rid)
1078                         continue;
1079
1080                 *port_type = BHND_PORT_AGENT;
1081                 *port_num = siba_cfg_agent_port(i);
1082                 *region_num = siba_cfg_agent_region(i);
1083                 return (0);
1084         }
1085
1086         /* Not found */
1087         return (ENOENT);
1088 }
1089
1090 static int
1091 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
1092     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
1093 {
1094         struct siba_devinfo     *dinfo;
1095         struct siba_addrspace   *addrspace;
1096         struct siba_cfg_block   *cfg;
1097
1098         /* delegate non-bus-attached devices to our parent */
1099         if (device_get_parent(child) != dev) {
1100                 return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
1101                     port_type, port_num, region_num, addr, size));
1102         }
1103
1104         dinfo = device_get_ivars(child);
1105
1106         /* Look for a matching addrspace */
1107         addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
1108         if (addrspace != NULL) {
1109                 *addr = addrspace->sa_base;
1110                 *size = addrspace->sa_size - addrspace->sa_bus_reserved;
1111                 return (0);
1112         }
1113
1114         /* Look for a matching cfg block */
1115         cfg = siba_find_cfg_block(dinfo, port_type, port_num, region_num);
1116         if (cfg != NULL) {
1117                 *addr = cfg->cb_base;
1118                 *size = cfg->cb_size;
1119                 return (0);
1120         }
1121
1122         /* Not found */
1123         return (ENOENT);
1124 }
1125
1126 /**
1127  * Default siba(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT().
1128  */
1129 u_int
1130 siba_get_intr_count(device_t dev, device_t child)
1131 {
1132         struct siba_devinfo     *dinfo;
1133
1134         /* delegate non-bus-attached devices to our parent */
1135         if (device_get_parent(child) != dev)
1136                 return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child));
1137
1138         dinfo = device_get_ivars(child);
1139         if (!dinfo->core_id.intr_en) {
1140                 /* No interrupts */
1141                 return (0);
1142         } else {
1143                 /* One assigned interrupt */
1144                 return (1);
1145         }
1146 }
1147
1148 /**
1149  * Default siba(4) bus driver implementation of BHND_BUS_GET_INTR_IVEC().
1150  */
1151 int
1152 siba_get_intr_ivec(device_t dev, device_t child, u_int intr, u_int *ivec)
1153 {
1154         struct siba_devinfo     *dinfo;
1155
1156         /* delegate non-bus-attached devices to our parent */
1157         if (device_get_parent(child) != dev)
1158                 return (BHND_BUS_GET_INTR_IVEC(device_get_parent(dev), child,
1159                     intr, ivec));
1160
1161         /* Must be a valid interrupt ID */
1162         if (intr >= siba_get_intr_count(dev, child))
1163                 return (ENXIO);
1164
1165         KASSERT(intr == 0, ("invalid ivec %u", intr));
1166
1167         dinfo = device_get_ivars(child);
1168
1169         KASSERT(dinfo->core_id.intr_en,
1170             ("core does not have an interrupt assigned"));
1171
1172         *ivec = dinfo->core_id.intr_flag;
1173         return (0);
1174 }
1175
1176 /**
1177  * Map per-core configuration blocks for @p dinfo.
1178  *
1179  * @param dev The siba bus device.
1180  * @param dinfo The device info instance on which to map all per-core
1181  * configuration blocks.
1182  */
1183 static int
1184 siba_map_cfg_resources(device_t dev, struct siba_devinfo *dinfo)
1185 {
1186         struct siba_addrspace   *addrspace;
1187         rman_res_t               r_start, r_count, r_end;
1188         uint8_t                  num_cfg;
1189         int                      rid;
1190
1191         num_cfg = dinfo->core_id.num_cfg_blocks;
1192         if (num_cfg > SIBA_MAX_CFG) {
1193                 device_printf(dev, "config block count %hhu out of range\n",
1194                     num_cfg);
1195                 return (ENXIO);
1196         }
1197         
1198         /* Fetch the core register address space */
1199         addrspace = siba_find_addrspace(dinfo, BHND_PORT_DEVICE, 0, 0);
1200         if (addrspace == NULL) {
1201                 device_printf(dev, "missing device registers\n");
1202                 return (ENXIO);
1203         }
1204
1205         /*
1206          * Map the per-core configuration blocks
1207          */
1208         for (uint8_t i = 0; i < num_cfg; i++) {
1209                 /* Add to child's resource list */
1210                 r_start = addrspace->sa_base + SIBA_CFG_OFFSET(i);
1211                 r_count = SIBA_CFG_SIZE;
1212                 r_end = r_start + r_count - 1;
1213
1214                 rid = resource_list_add_next(&dinfo->resources, SYS_RES_MEMORY,
1215                     r_start, r_end, r_count);
1216
1217                 /* Initialize config block descriptor */
1218                 dinfo->cfg[i] = ((struct siba_cfg_block) {
1219                         .cb_base = r_start,
1220                         .cb_size = SIBA_CFG_SIZE,
1221                         .cb_rid = rid
1222                 });
1223
1224                 /* Map the config resource for bus-level access */
1225                 dinfo->cfg_rid[i] = SIBA_CFG_RID(dinfo, i);
1226                 dinfo->cfg_res[i] = BHND_BUS_ALLOC_RESOURCE(dev, dev,
1227                     SYS_RES_MEMORY, &dinfo->cfg_rid[i], r_start, r_end,
1228                     r_count, RF_ACTIVE|RF_SHAREABLE);
1229
1230                 if (dinfo->cfg_res[i] == NULL) {
1231                         device_printf(dev, "failed to allocate SIBA_CFG%hhu\n",
1232                             i);
1233                         return (ENXIO);
1234                 }
1235         }
1236
1237         return (0);
1238 }
1239
1240 static device_t
1241 siba_add_child(device_t dev, u_int order, const char *name, int unit)
1242 {
1243         struct siba_devinfo     *dinfo;
1244         device_t                 child;
1245
1246         child = device_add_child_ordered(dev, order, name, unit);
1247         if (child == NULL)
1248                 return (NULL);
1249
1250         if ((dinfo = siba_alloc_dinfo(dev)) == NULL) {
1251                 device_delete_child(dev, child);
1252                 return (NULL);
1253         }
1254
1255         device_set_ivars(child, dinfo);
1256
1257         return (child);
1258 }
1259
1260 static void
1261 siba_child_deleted(device_t dev, device_t child)
1262 {
1263         struct bhnd_softc       *sc;
1264         struct siba_devinfo     *dinfo;
1265
1266         sc = device_get_softc(dev);
1267
1268         /* Call required bhnd(4) implementation */
1269         bhnd_generic_child_deleted(dev, child);
1270
1271         /* Free siba device info */
1272         if ((dinfo = device_get_ivars(child)) != NULL)
1273                 siba_free_dinfo(dev, child, dinfo);
1274
1275         device_set_ivars(child, NULL);
1276 }
1277
1278 /**
1279  * Scan the core table and add all valid discovered cores to
1280  * the bus.
1281  * 
1282  * @param dev The siba bus device.
1283  */
1284 int
1285 siba_add_children(device_t dev)
1286 {
1287         bhnd_erom_t                     *erom;
1288         struct siba_erom                *siba_erom;
1289         struct bhnd_erom_io             *eio;
1290         const struct bhnd_chipid        *cid;
1291         struct siba_core_id             *cores;
1292         device_t                        *children;
1293         int                              error;
1294
1295         cid = BHND_BUS_GET_CHIPID(dev, dev);
1296
1297         /* Allocate our EROM parser */
1298         eio = bhnd_erom_iores_new(dev, SIBA_EROM_RID);
1299         erom = bhnd_erom_alloc(&siba_erom_parser, cid, eio);
1300         if (erom == NULL) {
1301                 bhnd_erom_io_fini(eio);
1302                 return (ENODEV);
1303         }
1304
1305         /* Allocate our temporary core and device table */
1306         cores = malloc(sizeof(*cores) * cid->ncores, M_BHND, M_WAITOK);
1307         children = malloc(sizeof(*children) * cid->ncores, M_BHND,
1308             M_WAITOK | M_ZERO);
1309
1310         /*
1311          * Add child devices for all discovered cores.
1312          * 
1313          * On bridged devices, we'll exhaust our available register windows if
1314          * we map config blocks on unpopulated/disabled cores. To avoid this, we
1315          * defer mapping of the per-core siba(4) config blocks until all cores
1316          * have been enumerated and otherwise configured.
1317          */
1318         siba_erom = (struct siba_erom *)erom;
1319         for (u_int i = 0; i < cid->ncores; i++) {
1320                 struct siba_devinfo     *dinfo;
1321                 device_t                 child;
1322
1323                 if ((error = siba_erom_get_core_id(siba_erom, i, &cores[i])))
1324                         goto failed;
1325
1326                 /* Add the child device */
1327                 child = BUS_ADD_CHILD(dev, 0, NULL, -1);
1328                 if (child == NULL) {
1329                         error = ENXIO;
1330                         goto failed;
1331                 }
1332
1333                 children[i] = child;
1334
1335                 /* Initialize per-device bus info */
1336                 if ((dinfo = device_get_ivars(child)) == NULL) {
1337                         error = ENXIO;
1338                         goto failed;
1339                 }
1340
1341                 if ((error = siba_init_dinfo(dev, child, dinfo, &cores[i])))
1342                         goto failed;
1343
1344                 /* If pins are floating or the hardware is otherwise
1345                  * unpopulated, the device shouldn't be used. */
1346                 if (bhnd_is_hw_disabled(child))
1347                         device_disable(child);
1348         }
1349
1350         /* Free EROM (and any bridge register windows it might hold) */
1351         bhnd_erom_free(erom);
1352         erom = NULL;
1353
1354         /* Map all valid core's config register blocks and perform interrupt
1355          * assignment */
1356         for (u_int i = 0; i < cid->ncores; i++) {
1357                 struct siba_devinfo     *dinfo;
1358                 device_t                 child;
1359
1360                 child = children[i];
1361
1362                 /* Skip if core is disabled */
1363                 if (bhnd_is_hw_disabled(child))
1364                         continue;
1365
1366                 dinfo = device_get_ivars(child);
1367
1368                 /* Map the core's config blocks */
1369                 if ((error = siba_map_cfg_resources(dev, dinfo)))
1370                         goto failed;
1371
1372                 /* Issue bus callback for fully initialized child. */
1373                 BHND_BUS_CHILD_ADDED(dev, child);
1374         }
1375
1376         free(cores, M_BHND);
1377         free(children, M_BHND);
1378
1379         return (0);
1380
1381 failed:
1382         for (u_int i = 0; i < cid->ncores; i++) {
1383                 if (children[i] == NULL)
1384                         continue;
1385
1386                 device_delete_child(dev, children[i]);
1387         }
1388
1389         free(cores, M_BHND);
1390         free(children, M_BHND);
1391         if (erom != NULL)
1392                 bhnd_erom_free(erom);
1393
1394         return (error);
1395 }
1396
1397 static device_method_t siba_methods[] = {
1398         /* Device interface */
1399         DEVMETHOD(device_probe,                 siba_probe),
1400         DEVMETHOD(device_attach,                siba_attach),
1401         DEVMETHOD(device_detach,                siba_detach),
1402         DEVMETHOD(device_resume,                siba_resume),
1403         DEVMETHOD(device_suspend,               siba_suspend),
1404         
1405         /* Bus interface */
1406         DEVMETHOD(bus_add_child,                siba_add_child),
1407         DEVMETHOD(bus_child_deleted,            siba_child_deleted),
1408         DEVMETHOD(bus_read_ivar,                siba_read_ivar),
1409         DEVMETHOD(bus_write_ivar,               siba_write_ivar),
1410         DEVMETHOD(bus_get_resource_list,        siba_get_resource_list),
1411
1412         /* BHND interface */
1413         DEVMETHOD(bhnd_bus_get_erom_class,      siba_get_erom_class),
1414         DEVMETHOD(bhnd_bus_alloc_pmu,           siba_alloc_pmu),
1415         DEVMETHOD(bhnd_bus_release_pmu,         siba_release_pmu),
1416         DEVMETHOD(bhnd_bus_request_clock,       siba_request_clock),
1417         DEVMETHOD(bhnd_bus_enable_clocks,       siba_enable_clocks),
1418         DEVMETHOD(bhnd_bus_request_ext_rsrc,    siba_request_ext_rsrc),
1419         DEVMETHOD(bhnd_bus_release_ext_rsrc,    siba_release_ext_rsrc),
1420         DEVMETHOD(bhnd_bus_get_clock_freq,      siba_get_clock_freq),
1421         DEVMETHOD(bhnd_bus_get_clock_latency,   siba_get_clock_latency),
1422         DEVMETHOD(bhnd_bus_read_ioctl,          siba_read_ioctl),
1423         DEVMETHOD(bhnd_bus_write_ioctl,         siba_write_ioctl),
1424         DEVMETHOD(bhnd_bus_read_iost,           siba_read_iost),
1425         DEVMETHOD(bhnd_bus_is_hw_suspended,     siba_is_hw_suspended),
1426         DEVMETHOD(bhnd_bus_reset_hw,            siba_reset_hw),
1427         DEVMETHOD(bhnd_bus_suspend_hw,          siba_suspend_hw),
1428         DEVMETHOD(bhnd_bus_read_config,         siba_read_config),
1429         DEVMETHOD(bhnd_bus_write_config,        siba_write_config),
1430         DEVMETHOD(bhnd_bus_get_port_count,      siba_get_port_count),
1431         DEVMETHOD(bhnd_bus_get_region_count,    siba_get_region_count),
1432         DEVMETHOD(bhnd_bus_get_port_rid,        siba_get_port_rid),
1433         DEVMETHOD(bhnd_bus_decode_port_rid,     siba_decode_port_rid),
1434         DEVMETHOD(bhnd_bus_get_region_addr,     siba_get_region_addr),
1435         DEVMETHOD(bhnd_bus_get_intr_count,      siba_get_intr_count),
1436         DEVMETHOD(bhnd_bus_get_intr_ivec,       siba_get_intr_ivec),
1437
1438         DEVMETHOD_END
1439 };
1440
1441 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
1442
1443 MODULE_VERSION(siba, 1);
1444 MODULE_DEPEND(siba, bhnd, 1, 1, 1);