]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bwn/if_bwn_siba_compat.c
MFV r328231: 8897 zpool online -e fails assertion when run on non-leaf vdevs
[FreeBSD/FreeBSD.git] / sys / dev / bwn / if_bwn_siba_compat.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
5  * Copyright (c) 2017 The FreeBSD Foundation
6  * All rights reserved.
7  * 
8  * Portions of this software were developed by Landon Fuller
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/gpio.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
43
44 #include <machine/bus.h>
45 #include <sys/rman.h>
46 #include <machine/resource.h>
47
48 #include <net/ethernet.h>
49 #include <net/if.h>
50 #include <net/if_var.h>
51 #include <net/if_arp.h>
52 #include <net/if_dl.h>
53 #include <net/if_llc.h>
54 #include <net/if_media.h>
55 #include <net/if_types.h>
56
57 #include <dev/pci/pcireg.h>
58 #include <dev/pci/pcivar.h>
59
60 #include <net80211/ieee80211_var.h>
61 #include <net80211/ieee80211_radiotap.h>
62 #include <net80211/ieee80211_regdomain.h>
63 #include <net80211/ieee80211_phy.h>
64 #include <net80211/ieee80211_ratectl.h>
65
66 #include <dev/bhnd/bhnd.h>
67 #include <dev/bhnd/siba/sibareg.h>
68
69 #include <dev/bhnd/cores/chipc/chipc.h>
70 #include <dev/bhnd/cores/pci/bhnd_pcireg.h>
71 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
72
73 #include "gpio_if.h"
74
75 #include "bhnd_nvram_map.h"
76
77 #include "if_bwn_siba_compat.h"
78
79 static int              bwn_bhnd_populate_nvram_data(device_t dev,
80                             struct bwn_bhnd_ctx *ctx);
81 static inline bool      bwn_bhnd_is_siba_reg(device_t dev, uint16_t offset);
82
83 #define BWN_ASSERT_VALID_REG(_dev, _offset)                             \
84         KASSERT(!bwn_bhnd_is_siba_reg(_dev, _offset),                   \
85             ("%s: accessing siba-specific register %#jx", __FUNCTION__, \
86                 (uintmax_t)(_offset)));
87
88 static int
89 bwn_bhnd_bus_ops_init(device_t dev)
90 {
91         struct bwn_bhnd_ctx     *ctx;
92         struct bwn_softc        *sc;
93         const struct chipc_caps *ccaps;
94         int                      error;
95
96         sc = device_get_softc(dev);
97         ctx = NULL;
98
99         sc->sc_mem_rid = 0;
100         sc->sc_mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY,
101             &sc->sc_mem_rid, RF_ACTIVE);
102         if (sc->sc_mem_res == NULL) {
103                 return (ENXIO);
104         }
105
106         /* Allocate PMU state */
107         if ((error = bhnd_alloc_pmu(dev))) {
108                 device_printf(dev, "PMU allocation failed: %d\n", error);
109                 goto failed;
110         }
111
112         /* Allocate our context */
113         ctx = malloc(sizeof(struct bwn_bhnd_ctx), M_DEVBUF, M_WAITOK|M_ZERO);
114
115         /* Locate the ChipCommon device */
116         ctx->chipc_dev = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC);
117         if (ctx->chipc_dev == NULL) {
118                 device_printf(dev, "ChipCommon not found\n");
119                 error = ENXIO;
120                 goto failed;
121         }
122
123         /* Locate the GPIO device */
124         ctx->gpio_dev = bhnd_retain_provider(dev, BHND_SERVICE_GPIO);
125         if (ctx->gpio_dev == NULL) {
126                 device_printf(dev, "GPIO not found\n");
127                 error = ENXIO;
128                 goto failed;
129         }
130
131         /* Locate the PMU device (if any) */
132         ccaps = BHND_CHIPC_GET_CAPS(ctx->chipc_dev);
133         if (ccaps->pmu) {
134                 ctx->pmu_dev = bhnd_retain_provider(dev, BHND_SERVICE_PMU);
135                 if (ctx->pmu_dev == NULL) {
136                         device_printf(dev, "PMU not found\n");
137                         error = ENXIO;
138                         goto failed;
139                 }
140         }
141
142         /* Populate NVRAM data */
143         if ((error = bwn_bhnd_populate_nvram_data(dev, ctx)))
144                 goto failed;
145
146         /* Initialize bwn_softc */
147         sc->sc_bus_ctx = ctx;
148         return (0);
149
150 failed:
151         bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
152             sc->sc_mem_res);
153
154         if (ctx != NULL) {
155                 if (ctx->chipc_dev != NULL) {
156                         bhnd_release_provider(dev, ctx->chipc_dev,
157                             BHND_SERVICE_CHIPC);
158                 }
159
160                 if (ctx->gpio_dev != NULL) {
161                         bhnd_release_provider(dev, ctx->gpio_dev,
162                             BHND_SERVICE_GPIO);
163                 }
164
165                 if (ctx->pmu_dev != NULL) {
166                         bhnd_release_provider(dev, ctx->pmu_dev,
167                             BHND_SERVICE_PMU);
168                 }
169
170                 free(ctx, M_DEVBUF);
171         }
172
173         return (error);
174 }
175
176 static void
177 bwn_bhnd_bus_ops_fini(device_t dev)
178 {
179         struct bwn_bhnd_ctx     *ctx;
180         struct bwn_softc        *sc;
181
182         sc = device_get_softc(dev);
183         ctx = sc->sc_bus_ctx;
184
185         bhnd_release_pmu(dev);
186         bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
187             sc->sc_mem_res);
188
189         bhnd_release_provider(dev, ctx->chipc_dev, BHND_SERVICE_CHIPC);
190         bhnd_release_provider(dev, ctx->gpio_dev, BHND_SERVICE_GPIO);
191
192         if (ctx->pmu_dev != NULL)
193                 bhnd_release_provider(dev, ctx->pmu_dev, BHND_SERVICE_PMU);
194
195         free(ctx, M_DEVBUF);
196         sc->sc_bus_ctx = NULL;
197 }
198
199
200 /**
201  * Return true if @p offset is within a siba-specific configuration register
202  * block.
203  */
204 static inline bool
205 bwn_bhnd_is_siba_reg(device_t dev, uint16_t offset)
206 {
207         if (offset >= SIBA_CFG0_OFFSET &&
208             offset <= SIBA_CFG0_OFFSET + SIBA_CFG_SIZE)
209                 return (true);
210
211         if (offset >= SIBA_CFG1_OFFSET &&
212             offset <= SIBA_CFG1_OFFSET + SIBA_CFG_SIZE)
213                 return (true);
214         
215         return (false);
216 }
217
218 /* Populate SPROM values from NVRAM */
219 static int
220 bwn_bhnd_populate_nvram_data(device_t dev, struct bwn_bhnd_ctx *ctx)
221 {
222         const char      *mac_80211bg_var, *mac_80211a_var;
223         int     error;
224
225         /* Fetch SROM revision */
226         error = bhnd_nvram_getvar_uint8(dev, BHND_NVAR_SROMREV, &ctx->sromrev);
227         if (error) {
228                 device_printf(dev, "error reading %s: %d\n", BHND_NVAR_SROMREV,
229                     error);
230                 return (error);
231         }
232
233         /* Fetch board flags */
234         error = bhnd_nvram_getvar_uint32(dev, BHND_NVAR_BOARDFLAGS,
235             &ctx->boardflags);
236         if (error) {
237                 device_printf(dev, "error reading %s: %d\n",
238                     BHND_NVAR_BOARDFLAGS, error);
239                 return (error);
240         }
241
242         /* Fetch macaddrs if available; bwn(4) expects any missing macaddr
243          * values to be initialized with 0xFF octets */
244         memset(ctx->mac_80211bg, 0xFF, sizeof(ctx->mac_80211bg));
245         memset(ctx->mac_80211a, 0xFF, sizeof(ctx->mac_80211a));
246
247         if (ctx->sromrev <= 2) {
248                 mac_80211bg_var = BHND_NVAR_IL0MACADDR;
249                 mac_80211a_var = BHND_NVAR_ET1MACADDR;
250         } else {
251                 mac_80211bg_var = BHND_NVAR_MACADDR;
252                 mac_80211a_var = NULL;
253         }
254
255         /* Fetch required D11 core 0 macaddr */
256         error = bhnd_nvram_getvar_array(dev, mac_80211bg_var, ctx->mac_80211bg,
257             sizeof(ctx->mac_80211bg), BHND_NVRAM_TYPE_UINT8_ARRAY);
258         if (error) {
259                 device_printf(dev, "error reading %s: %d\n", mac_80211bg_var,
260                     error);
261                 return (error);
262         }
263
264         /* Fetch optional D11 core 1 macaddr */
265         if (mac_80211a_var != NULL) {
266                 error = bhnd_nvram_getvar_array(dev, mac_80211a_var,
267                     ctx->mac_80211a, sizeof(ctx->mac_80211a),
268                     BHND_NVRAM_TYPE_UINT8_ARRAY);
269
270                 if (error && error != ENOENT) {
271                         device_printf(dev, "error reading %s: %d\n",
272                             mac_80211a_var, error);
273                         return (error);
274                 }
275         };
276
277         /* Fetch pa0maxpwr; bwn(4) expects to be able to modify it */
278         if ((ctx->sromrev >= 1 && ctx->sromrev <= 3) ||
279             (ctx->sromrev >= 8 && ctx->sromrev <= 10))
280         {
281                 error = bhnd_nvram_getvar_uint8(dev, BHND_NVAR_PA0MAXPWR,
282                      &ctx->pa0maxpwr);
283                 if (error) {
284                         device_printf(dev, "error reading %s: %d\n",
285                             BHND_NVAR_PA0MAXPWR, error);
286                         return (error);
287                 }
288         }
289
290         return (0);
291 }
292
293 /*
294  * Disable PCI-specific MSI interrupt allocation handling
295  */
296
297 /*
298  * pci_find_cap()
299  *
300  * Referenced by:
301  *   bwn_attach()
302  */
303 static int
304 bhnd_compat_pci_find_cap(device_t dev, int capability, int *capreg)
305 {
306         return (ENODEV);
307 }
308
309 /*
310  * pci_alloc_msi()
311  *
312  * Referenced by:
313  *   bwn_attach()
314  */
315 static int
316 bhnd_compat_pci_alloc_msi(device_t dev, int *count)
317 {
318         return (ENODEV);
319 }
320
321 /*
322  * pci_release_msi()
323  *
324  * Referenced by:
325  *   bwn_attach()
326  *   bwn_detach()
327  */
328 static int
329 bhnd_compat_pci_release_msi(device_t dev)
330 {
331         return (ENODEV);
332 }
333
334 /*
335  * pci_msi_count()
336  *
337  * Referenced by:
338  *   bwn_attach()
339  */
340 static int
341 bhnd_compat_pci_msi_count(device_t dev)
342 {
343         return (0);
344 }
345
346 /*
347  * siba_get_vendor()
348  *
349  * Referenced by:
350  *   bwn_probe()
351  */
352 static uint16_t
353 bhnd_compat_get_vendor(device_t dev)
354 {
355         uint16_t vendor = bhnd_get_vendor(dev);
356
357         switch (vendor) {
358         case BHND_MFGID_BCM:
359                 return (SIBA_VID_BROADCOM);
360         default:
361                 return (0x0000);
362         }
363 }
364
365 /*
366  * siba_get_device()
367  *
368  * Referenced by:
369  *   bwn_probe()
370  */
371 static uint16_t
372 bhnd_compat_get_device(device_t dev)
373 {
374         return (bhnd_get_device(dev));
375 }
376
377 /*
378  * siba_get_revid()
379  *
380  * Referenced by:
381  *   bwn_attach()
382  *   bwn_attach_core()
383  *   bwn_chip_init()
384  *   bwn_chiptest()
385  *   bwn_core_init()
386  *   bwn_core_start()
387  *   bwn_pio_idx2base()
388  *   bwn_pio_set_txqueue()
389  *   bwn_pio_tx_start()
390  *   bwn_probe()
391  * ... and 19 others
392  * 
393  */
394 static uint8_t
395 bhnd_compat_get_revid(device_t dev)
396 {
397         return (bhnd_get_hwrev(dev));
398 }
399
400 /**
401  * Return the PCI bridge root device.
402  * 
403  * Will panic if a PCI bridge root device is not found.
404  */
405 static device_t
406 bwn_bhnd_get_pci_dev(device_t dev)
407 {       device_t bridge_root;
408
409         bridge_root = bhnd_find_bridge_root(dev, devclass_find("pci"));
410         if (bridge_root == NULL)
411                 panic("not a PCI device");
412
413         return (bridge_root);
414 }
415
416 /*
417  * siba_get_pci_vendor()
418  *
419  * Referenced by:
420  *   bwn_sprom_bugfixes()
421  */
422 static uint16_t
423 bhnd_compat_get_pci_vendor(device_t dev)
424 {
425         return (pci_get_vendor(bwn_bhnd_get_pci_dev(dev)));
426 }
427
428 /*
429  * siba_get_pci_device()
430  *
431  * Referenced by:
432  *   bwn_attach()
433  *   bwn_attach_core()
434  *   bwn_nphy_op_prepare_structs()
435  *   bwn_sprom_bugfixes()
436  */
437 static uint16_t
438 bhnd_compat_get_pci_device(device_t dev)
439 {
440         return (pci_get_device(bwn_bhnd_get_pci_dev(dev)));
441 }
442
443 /*
444  * siba_get_pci_subvendor()
445  *
446  * Referenced by:
447  *   bwn_led_attach()
448  *   bwn_nphy_op_prepare_structs()
449  *   bwn_phy_g_prepare_hw()
450  *   bwn_phy_hwpctl_init()
451  *   bwn_phy_init_b5()
452  *   bwn_phy_initn()
453  *   bwn_phy_txpower_check()
454  *   bwn_radio_init2055_post()
455  *   bwn_sprom_bugfixes()
456  *   bwn_wa_init()
457  */
458 static uint16_t
459 bhnd_compat_get_pci_subvendor(device_t dev)
460 {
461         return (pci_get_subvendor(bwn_bhnd_get_pci_dev(dev)));
462 }
463
464 /*
465  * siba_get_pci_subdevice()
466  *
467  * Referenced by:
468  *   bwn_nphy_workarounds_rev1_2()
469  *   bwn_phy_g_prepare_hw()
470  *   bwn_phy_hwpctl_init()
471  *   bwn_phy_init_b5()
472  *   bwn_phy_initn()
473  *   bwn_phy_lp_bbinit_r01()
474  *   bwn_phy_txpower_check()
475  *   bwn_radio_init2055_post()
476  *   bwn_sprom_bugfixes()
477  *   bwn_wa_init()
478  */
479 static uint16_t
480 bhnd_compat_get_pci_subdevice(device_t dev)
481 {
482         return (pci_get_subdevice(bwn_bhnd_get_pci_dev(dev)));
483 }
484
485 /*
486  * siba_get_pci_revid()
487  *
488  * Referenced by:
489  *   bwn_phy_g_prepare_hw()
490  *   bwn_phy_lp_bbinit_r2()
491  *   bwn_sprom_bugfixes()
492  *   bwn_wa_init()
493  */
494 static uint8_t
495 bhnd_compat_get_pci_revid(device_t dev)
496 {
497         return (pci_get_revid(bwn_bhnd_get_pci_dev(dev)));
498 }
499
500 /*
501  * siba_get_chipid()
502  *
503  * Referenced by:
504  *   bwn_attach()
505  *   bwn_gpio_init()
506  *   bwn_mac_switch_freq()
507  *   bwn_phy_g_attach()
508  *   bwn_phy_g_init_sub()
509  *   bwn_phy_g_prepare_hw()
510  *   bwn_phy_getinfo()
511  *   bwn_phy_lp_calib()
512  *   bwn_set_opmode()
513  *   bwn_sprom_bugfixes()
514  * ... and 9 others
515  * 
516  */
517 static uint16_t
518 bhnd_compat_get_chipid(device_t dev)
519 {
520         return (bhnd_get_chipid(dev)->chip_id);
521 }
522
523 /*
524  * siba_get_chiprev()
525  *
526  * Referenced by:
527  *   bwn_phy_getinfo()
528  *   bwn_phy_lp_bbinit_r2()
529  *   bwn_phy_lp_tblinit_r2()
530  *   bwn_set_opmode()
531  */
532 static uint16_t
533 bhnd_compat_get_chiprev(device_t dev)
534 {
535         return (bhnd_get_chipid(dev)->chip_rev);
536 }
537
538 /*
539  * siba_get_chippkg()
540  *
541  * Referenced by:
542  *   bwn_phy_g_init_sub()
543  *   bwn_phy_lp_bbinit_r01()
544  *   bwn_radio_2056_setup()
545  */
546 static uint8_t
547 bhnd_compat_get_chippkg(device_t dev)
548 {
549         return (bhnd_get_chipid(dev)->chip_pkg);
550 }
551
552 /*
553  * siba_get_type()
554  *
555  * Referenced by:
556  *   bwn_core_init()
557  *   bwn_dma_attach()
558  *   bwn_nphy_op_prepare_structs()
559  *   bwn_sprom_bugfixes()
560  */
561 static enum siba_type
562 bhnd_compat_get_type(device_t dev)
563 {
564         device_t                bus, hostb;
565         bhnd_devclass_t         hostb_devclass;
566
567         bus = device_get_parent(dev);
568         hostb = bhnd_bus_find_hostb_device(bus);
569
570         if (hostb == NULL)
571                 return (SIBA_TYPE_SSB);
572
573         hostb_devclass = bhnd_get_class(hostb);
574         switch (hostb_devclass) {
575         case BHND_DEVCLASS_PCCARD:
576                 return (SIBA_TYPE_PCMCIA);
577         case BHND_DEVCLASS_PCI:
578         case BHND_DEVCLASS_PCIE:
579                 return (SIBA_TYPE_PCI);
580         default:
581                 panic("unsupported hostb devclass: %d\n", hostb_devclass);
582         }
583 }
584
585 /*
586  * siba_get_cc_pmufreq()
587  *
588  * Referenced by:
589  *   bwn_phy_lp_b2062_init()
590  *   bwn_phy_lp_b2062_switch_channel()
591  *   bwn_phy_lp_b2063_switch_channel()
592  *   bwn_phy_lp_rxcal_r2()
593  */
594 static uint32_t
595 bhnd_compat_get_cc_pmufreq(device_t dev)
596 {
597         u_int   freq;
598         int     error;
599
600         if ((error = bhnd_get_clock_freq(dev, BHND_CLOCK_ALP, &freq)))
601                 panic("failed to fetch clock frequency: %d", error);
602
603         /* TODO: bwn(4) immediately multiplies the result by 1000 (MHz -> Hz) */
604         return (freq / 1000);
605 }
606
607 /*
608  * siba_get_cc_caps()
609  *
610  * Referenced by:
611  *   bwn_phy_lp_b2062_init()
612  */
613 static uint32_t
614 bhnd_compat_get_cc_caps(device_t dev)
615 {
616         device_t                 chipc;
617         const struct chipc_caps *ccaps;
618         uint32_t                 result;
619
620         /* Fetch our ChipCommon device */
621         chipc = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC);
622         if (chipc == NULL)
623                 panic("missing ChipCommon device");
624
625         /*
626          * The ChipCommon capability flags are only used in one LP-PHY function,
627          * to assert that a PMU is in fact available.
628          *
629          * We can support this by producing a value containing just that flag. 
630          */
631         result = 0;
632         ccaps = BHND_CHIPC_GET_CAPS(chipc);
633         if (ccaps->pmu)
634                 result |= SIBA_CC_CAPS_PMU;
635
636         bhnd_release_provider(dev, chipc, BHND_SERVICE_CHIPC);
637
638         return (result);
639 }
640
641 /*
642  * siba_get_cc_powerdelay()
643  *
644  * Referenced by:
645  *   bwn_chip_init()
646  */
647 static uint16_t
648 bhnd_compat_get_cc_powerdelay(device_t dev)
649 {
650         u_int    delay;
651         int      error;
652
653         if ((error = bhnd_get_clock_latency(dev, BHND_CLOCK_HT, &delay)))
654                 panic("failed to fetch clock latency: %d", error);
655
656         if (delay > UINT16_MAX)
657                 panic("%#x would overflow", delay);
658
659         return (delay);
660 }
661
662 /*
663  * siba_get_pcicore_revid()
664  *
665  * Referenced by:
666  *   bwn_core_init()
667  */
668 static uint8_t
669 bhnd_compat_get_pcicore_revid(device_t dev)
670 {
671         device_t        hostb;
672         uint8_t         nomatch_revid;
673
674         /* 
675          * This is used by bwn(4) in only bwn_core_init(), where a revid <= 10
676          * results in the BWN_HF_PCI_SLOWCLOCK_WORKAROUND workaround being
677          * enabled.
678          * 
679          * The quirk should only be applied on siba(4) devices using a PCI
680          * core; we handle around this by returning a bogus value >= 10 here.
681          * 
682          * TODO: bwn(4) should match this quirk on:
683          *      - BHND_CHIPTYPE_SIBA
684          *      - BHND_COREID_PCI
685          *      - HWREV_LTE(10)
686          */
687         nomatch_revid = 0xFF;
688
689         hostb = bhnd_bus_find_hostb_device(device_get_parent(dev));
690         if (hostb == NULL) {
691                 /* Not a bridged device */
692                 return (nomatch_revid);
693         }
694
695         if (bhnd_get_device(hostb) != BHND_COREID_PCI) {
696                 /* Not a PCI core */
697                 return (nomatch_revid);
698         }
699
700         /* This is a PCI core; we can return the real core revision */
701         return (bhnd_get_hwrev(hostb));
702 }
703
704 /*
705  * siba_sprom_get_rev()
706  *
707  * Referenced by:
708  *   bwn_nphy_op_prepare_structs()
709  *   bwn_nphy_tx_power_ctl_setup()
710  *   bwn_nphy_tx_power_fix()
711  *   bwn_nphy_workarounds_rev7plus()
712  */
713 static uint8_t
714 bhnd_compat_sprom_get_rev(device_t dev)
715 {
716         return (bwn_bhnd_get_ctx(dev)->sromrev);
717 }
718
719 /*
720  * siba_sprom_get_mac_80211bg()
721  *
722  * Referenced by:
723  *   bwn_attach_post()
724  */
725 static uint8_t *
726 bhnd_compat_sprom_get_mac_80211bg(device_t dev)
727 {
728         /* 'MAC_80211BG' is il0macaddr or macaddr*/
729         return (bwn_bhnd_get_ctx(dev)->mac_80211bg);
730 }
731
732 /*
733  * siba_sprom_get_mac_80211a()
734  *
735  * Referenced by:
736  *   bwn_attach_post()
737  */
738 static uint8_t *
739 bhnd_compat_sprom_get_mac_80211a(device_t dev)
740 {
741         /* 'MAC_80211A' is et1macaddr */
742         return (bwn_bhnd_get_ctx(dev)->mac_80211a);
743 }
744
745 /*
746  * siba_sprom_get_brev()
747  *
748  * Referenced by:
749  *   bwn_radio_init2055_post()
750  */
751 static uint8_t
752 bhnd_compat_sprom_get_brev(device_t dev)
753 {
754         /* TODO: bwn(4) needs to switch to uint16_t */
755         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_BOARDREV);
756 }
757
758 /*
759  * siba_sprom_get_ccode()
760  *
761  * Referenced by:
762  *   bwn_phy_g_switch_chan()
763  */
764 static uint8_t
765 bhnd_compat_sprom_get_ccode(device_t dev)
766 {
767         /* This has been replaced with 'ccode' in later SPROM
768          * revisions, but this API is only called on devices with
769          * spromrev 1. */
770         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_CC);
771 }
772
773 /*
774  * siba_sprom_get_ant_a()
775  *
776  * Referenced by:
777  *   bwn_antenna_sanitize()
778  */
779 static uint8_t
780 bhnd_compat_sprom_get_ant_a(device_t dev)
781 {
782         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_AA5G);
783 }
784
785 /*
786  * siba_sprom_get_ant_bg()
787  *
788  * Referenced by:
789  *   bwn_antenna_sanitize()
790  */
791 static uint8_t
792 bhnd_compat_sprom_get_ant_bg(device_t dev)
793 {
794         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_AA2G);
795 }
796
797 /*
798  * siba_sprom_get_pa0b0()
799  *
800  * Referenced by:
801  *   bwn_phy_g_attach()
802  */
803 static uint16_t
804 bhnd_compat_sprom_get_pa0b0(device_t dev)
805 {
806         int16_t value;
807
808         BWN_BHND_NVRAM_FETCH_VAR(dev, int16, BHND_NVAR_PA0B0, &value);
809
810         /* TODO: bwn(4) immediately casts this back to int16_t */
811         return ((uint16_t)value);
812 }
813
814 /*
815  * siba_sprom_get_pa0b1()
816  *
817  * Referenced by:
818  *   bwn_phy_g_attach()
819  */
820 static uint16_t
821 bhnd_compat_sprom_get_pa0b1(device_t dev)
822 {
823         int16_t value;
824
825         BWN_BHND_NVRAM_FETCH_VAR(dev, int16, BHND_NVAR_PA0B1, &value);
826
827         /* TODO: bwn(4) immediately casts this back to int16_t */
828         return ((uint16_t)value);
829 }
830
831 /*
832  * siba_sprom_get_pa0b2()
833  *
834  * Referenced by:
835  *   bwn_phy_g_attach()
836  */
837 static uint16_t
838 bhnd_compat_sprom_get_pa0b2(device_t dev)
839 {
840         int16_t value;
841
842         BWN_BHND_NVRAM_FETCH_VAR(dev, int16, BHND_NVAR_PA0B2, &value);
843
844         /* TODO: bwn(4) immediately casts this back to int16_t */
845         return ((uint16_t)value);
846 }
847
848 /**
849  * Fetch an led behavior (ledbhX) NVRAM variable value, for use by
850  * siba_sprom_get_gpioX().
851  * 
852  * ('gpioX' are actually the ledbhX NVRAM variables).
853  */
854 static uint8_t
855 bhnd_compat_sprom_get_ledbh(device_t dev, const char *name)
856 {
857         uint8_t value;
858         int     error;
859
860         error = bhnd_nvram_getvar_uint8(dev, name, &value);
861         if (error && error != ENOENT)
862                 panic("NVRAM variable %s unreadable: %d", name, error);
863
864         /* For some variables (including ledbhX), a value with all bits set is
865          * treated as uninitialized in the SPROM format; our SPROM parser
866          * detects this case and returns ENOENT, but bwn(4) actually expects
867          * to read the raw value 0xFF value. */
868         if (error == ENOENT)
869                 value = 0xFF;
870
871         return (value);
872 }
873
874 /*
875  * siba_sprom_get_gpio0()
876  *
877  * 'gpioX' are actually the led behavior (ledbh) NVRAM variables.
878  *
879  * Referenced by:
880  *   bwn_led_attach()
881  */
882 static uint8_t
883 bhnd_compat_sprom_get_gpio0(device_t dev)
884 {
885         return (bhnd_compat_sprom_get_ledbh(dev, BHND_NVAR_LEDBH0));
886 }
887
888 /*
889  * siba_sprom_get_gpio1()
890  *
891  * Referenced by:
892  *   bwn_led_attach()
893  */
894 static uint8_t
895 bhnd_compat_sprom_get_gpio1(device_t dev)
896 {
897         return (bhnd_compat_sprom_get_ledbh(dev, BHND_NVAR_LEDBH1));
898 }
899
900 /*
901  * siba_sprom_get_gpio2()
902  *
903  * Referenced by:
904  *   bwn_led_attach()
905  */
906 static uint8_t
907 bhnd_compat_sprom_get_gpio2(device_t dev)
908 {
909         return (bhnd_compat_sprom_get_ledbh(dev, BHND_NVAR_LEDBH2));
910 }
911
912 /*
913  * siba_sprom_get_gpio3()
914  *
915  * Referenced by:
916  *   bwn_led_attach()
917  */
918 static uint8_t
919 bhnd_compat_sprom_get_gpio3(device_t dev)
920 {
921         return (bhnd_compat_sprom_get_ledbh(dev, BHND_NVAR_LEDBH3));
922 }
923
924 /*
925  * siba_sprom_get_maxpwr_bg()
926  *
927  * Referenced by:
928  *   bwn_phy_g_recalc_txpwr()
929  */
930 static uint16_t
931 bhnd_compat_sprom_get_maxpwr_bg(device_t dev)
932 {
933         return (bwn_bhnd_get_ctx(dev)->pa0maxpwr);
934 }
935
936 /*
937  * siba_sprom_set_maxpwr_bg()
938  *
939  * Referenced by:
940  *   bwn_phy_g_recalc_txpwr()
941  */
942 static void
943 bhnd_compat_sprom_set_maxpwr_bg(device_t dev, uint16_t t)
944 {
945         KASSERT(t <= UINT8_MAX, ("invalid maxpwr value %hu", t));
946         bwn_bhnd_get_ctx(dev)->pa0maxpwr = t;
947 }
948
949 /*
950  * siba_sprom_get_rxpo2g()
951  *
952  * Referenced by:
953  *   bwn_phy_lp_readsprom()
954  */
955 static uint8_t
956 bhnd_compat_sprom_get_rxpo2g(device_t dev)
957 {
958         /* Should be signed, but bwn(4) expects an unsigned value */
959         BWN_BHND_NVRAM_RETURN_VAR(dev, int8, BHND_NVAR_RXPO2G);
960 }
961
962 /*
963  * siba_sprom_get_rxpo5g()
964  *
965  * Referenced by:
966  *   bwn_phy_lp_readsprom()
967  */
968 static uint8_t
969 bhnd_compat_sprom_get_rxpo5g(device_t dev)
970 {
971         /* Should be signed, but bwn(4) expects an unsigned value */
972         BWN_BHND_NVRAM_RETURN_VAR(dev, int8, BHND_NVAR_RXPO5G);
973 }
974
975 /*
976  * siba_sprom_get_tssi_bg()
977  *
978  * Referenced by:
979  *   bwn_phy_g_attach()
980  */
981 static uint8_t
982 bhnd_compat_sprom_get_tssi_bg(device_t dev)
983 {
984         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_PA0ITSSIT);
985 }
986
987 /*
988  * siba_sprom_get_tri2g()
989  *
990  * Referenced by:
991  *   bwn_phy_lp_readsprom()
992  */
993 static uint8_t
994 bhnd_compat_sprom_get_tri2g(device_t dev)
995 {
996         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TRI2G);
997 }
998
999 /*
1000  * siba_sprom_get_tri5gl()
1001  *
1002  * Referenced by:
1003  *   bwn_phy_lp_readsprom()
1004  */
1005 static uint8_t
1006 bhnd_compat_sprom_get_tri5gl(device_t dev)
1007 {
1008         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TRI5GL);
1009 }
1010
1011 /*
1012  * siba_sprom_get_tri5g()
1013  *
1014  * Referenced by:
1015  *   bwn_phy_lp_readsprom()
1016  */
1017 static uint8_t
1018 bhnd_compat_sprom_get_tri5g(device_t dev)
1019 {
1020         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TRI5G);
1021 }
1022
1023 /*
1024  * siba_sprom_get_tri5gh()
1025  *
1026  * Referenced by:
1027  *   bwn_phy_lp_readsprom()
1028  */
1029 static uint8_t
1030 bhnd_compat_sprom_get_tri5gh(device_t dev)
1031 {
1032         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TRI5GH);
1033 }
1034
1035 /*
1036  * siba_sprom_get_rssisav2g()
1037  *
1038  * Referenced by:
1039  *   bwn_phy_lp_readsprom()
1040  */
1041 static uint8_t
1042 bhnd_compat_sprom_get_rssisav2g(device_t dev)
1043 {
1044         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISAV2G);
1045 }
1046
1047 /*
1048  * siba_sprom_get_rssismc2g()
1049  *
1050  * Referenced by:
1051  *   bwn_phy_lp_readsprom()
1052  */
1053 static uint8_t
1054 bhnd_compat_sprom_get_rssismc2g(device_t dev)
1055 {
1056         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISMC2G);
1057 }
1058
1059 /*
1060  * siba_sprom_get_rssismf2g()
1061  *
1062  * Referenced by:
1063  *   bwn_phy_lp_readsprom()
1064  */
1065 static uint8_t
1066 bhnd_compat_sprom_get_rssismf2g(device_t dev)
1067 {
1068         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISMF2G);
1069 }
1070
1071 /*
1072  * siba_sprom_get_bxa2g()
1073  *
1074  * Referenced by:
1075  *   bwn_phy_lp_readsprom()
1076  */
1077 static uint8_t
1078 bhnd_compat_sprom_get_bxa2g(device_t dev)
1079 {
1080         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_BXA2G);
1081 }
1082
1083 /*
1084  * siba_sprom_get_rssisav5g()
1085  *
1086  * Referenced by:
1087  *   bwn_phy_lp_readsprom()
1088  */
1089 static uint8_t
1090 bhnd_compat_sprom_get_rssisav5g(device_t dev)
1091 {
1092         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISAV5G);
1093 }
1094
1095 /*
1096  * siba_sprom_get_rssismc5g()
1097  *
1098  * Referenced by:
1099  *   bwn_phy_lp_readsprom()
1100  */
1101 static uint8_t
1102 bhnd_compat_sprom_get_rssismc5g(device_t dev)
1103 {
1104         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISMC5G);
1105 }
1106
1107 /*
1108  * siba_sprom_get_rssismf5g()
1109  *
1110  * Referenced by:
1111  *   bwn_phy_lp_readsprom()
1112  */
1113 static uint8_t
1114 bhnd_compat_sprom_get_rssismf5g(device_t dev)
1115 {
1116         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_RSSISMF5G);
1117 }
1118
1119 /*
1120  * siba_sprom_get_bxa5g()
1121  *
1122  * Referenced by:
1123  *   bwn_phy_lp_readsprom()
1124  */
1125 static uint8_t
1126 bhnd_compat_sprom_get_bxa5g(device_t dev)
1127 {
1128         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_BXA5G);
1129 }
1130
1131 /*
1132  * siba_sprom_get_cck2gpo()
1133  *
1134  * Referenced by:
1135  *   bwn_ppr_load_max_from_sprom()
1136  */
1137 static uint16_t
1138 bhnd_compat_sprom_get_cck2gpo(device_t dev)
1139 {
1140         BWN_BHND_NVRAM_RETURN_VAR(dev, uint16, BHND_NVAR_CCK2GPO);
1141 }
1142
1143 /*
1144  * siba_sprom_get_ofdm2gpo()
1145  *
1146  * Referenced by:
1147  *   bwn_ppr_load_max_from_sprom()
1148  */
1149 static uint32_t
1150 bhnd_compat_sprom_get_ofdm2gpo(device_t dev)
1151 {
1152         BWN_BHND_NVRAM_RETURN_VAR(dev, uint32, BHND_NVAR_OFDM2GPO);
1153 }
1154
1155 /*
1156  * siba_sprom_get_ofdm5glpo()
1157  *
1158  * Referenced by:
1159  *   bwn_ppr_load_max_from_sprom()
1160  */
1161 static uint32_t
1162 bhnd_compat_sprom_get_ofdm5glpo(device_t dev)
1163 {
1164         BWN_BHND_NVRAM_RETURN_VAR(dev, uint32, BHND_NVAR_OFDM5GLPO);
1165 }
1166
1167 /*
1168  * siba_sprom_get_ofdm5gpo()
1169  *
1170  * Referenced by:
1171  *   bwn_ppr_load_max_from_sprom()
1172  */
1173 static uint32_t
1174 bhnd_compat_sprom_get_ofdm5gpo(device_t dev)
1175 {
1176         BWN_BHND_NVRAM_RETURN_VAR(dev, uint32, BHND_NVAR_OFDM5GPO);
1177 }
1178
1179 /*
1180  * siba_sprom_get_ofdm5ghpo()
1181  *
1182  * Referenced by:
1183  *   bwn_ppr_load_max_from_sprom()
1184  */
1185 static uint32_t
1186 bhnd_compat_sprom_get_ofdm5ghpo(device_t dev)
1187 {
1188         BWN_BHND_NVRAM_RETURN_VAR(dev, uint32, BHND_NVAR_OFDM5GHPO);
1189 }
1190
1191 /*
1192  * siba_sprom_set_bf_lo()
1193  *
1194  * Referenced by:
1195  *   bwn_sprom_bugfixes()
1196  */
1197 static void
1198 bhnd_compat_sprom_set_bf_lo(device_t dev, uint16_t t)
1199 {
1200         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
1201         ctx->boardflags &= ~0xFFFF;
1202         ctx->boardflags |= t;
1203 }
1204
1205 /*
1206  * siba_sprom_get_bf_lo()
1207  *
1208  * Referenced by:
1209  *   bwn_bt_enable()
1210  *   bwn_core_init()
1211  *   bwn_gpio_init()
1212  *   bwn_loopback_calcgain()
1213  *   bwn_phy_g_init_sub()
1214  *   bwn_phy_g_recalc_txpwr()
1215  *   bwn_phy_g_set_txpwr()
1216  *   bwn_phy_g_task_60s()
1217  *   bwn_rx_rssi_calc()
1218  *   bwn_sprom_bugfixes()
1219  * ... and 11 others
1220  * 
1221  */
1222 static uint16_t
1223 bhnd_compat_sprom_get_bf_lo(device_t dev)
1224 {
1225         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
1226         return (ctx->boardflags & UINT16_MAX);
1227 }
1228
1229 /*
1230  * siba_sprom_get_bf_hi()
1231  *
1232  * Referenced by:
1233  *   bwn_nphy_gain_ctl_workarounds_rev3()
1234  *   bwn_phy_lp_bbinit_r01()
1235  *   bwn_phy_lp_tblinit_txgain()
1236  */
1237 static uint16_t
1238 bhnd_compat_sprom_get_bf_hi(device_t dev)
1239 {
1240         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
1241         return (ctx->boardflags >> 16);
1242 }
1243
1244 /*
1245  * siba_sprom_get_bf2_lo()
1246  *
1247  * Referenced by:
1248  *   bwn_nphy_op_prepare_structs()
1249  *   bwn_nphy_workarounds_rev1_2()
1250  *   bwn_nphy_workarounds_rev3plus()
1251  *   bwn_phy_initn()
1252  *   bwn_radio_2056_setup()
1253  *   bwn_radio_init2055_post()
1254  */
1255 static uint16_t
1256 bhnd_compat_sprom_get_bf2_lo(device_t dev)
1257 {
1258         uint32_t bf2;
1259
1260         BWN_BHND_NVRAM_FETCH_VAR(dev, uint32, BHND_NVAR_BOARDFLAGS2, &bf2);
1261         return (bf2 & UINT16_MAX);
1262 }
1263
1264 /*
1265  * siba_sprom_get_bf2_hi()
1266  *
1267  * Referenced by:
1268  *   bwn_nphy_workarounds_rev7plus()
1269  *   bwn_phy_initn()
1270  *   bwn_radio_2056_setup()
1271  */
1272 static uint16_t
1273 bhnd_compat_sprom_get_bf2_hi(device_t dev)
1274 {
1275         uint32_t bf2;
1276
1277         BWN_BHND_NVRAM_FETCH_VAR(dev, uint32, BHND_NVAR_BOARDFLAGS2, &bf2);
1278         return (bf2 >> 16);
1279 }
1280
1281 /*
1282  * siba_sprom_get_fem_2ghz_tssipos()
1283  *
1284  * Referenced by:
1285  *   bwn_nphy_tx_power_ctl_setup()
1286  */
1287 static uint8_t
1288 bhnd_compat_sprom_get_fem_2ghz_tssipos(device_t dev)
1289 {
1290         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TSSIPOS2G);
1291 }
1292
1293 /*
1294  * siba_sprom_get_fem_2ghz_extpa_gain()
1295  *
1296  * Referenced by:
1297  *   bwn_nphy_op_prepare_structs()
1298  */
1299 static uint8_t
1300 bhnd_compat_sprom_get_fem_2ghz_extpa_gain(device_t dev)
1301 {
1302         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_EXTPAGAIN2G);
1303 }
1304
1305 /*
1306  * siba_sprom_get_fem_2ghz_pdet_range()
1307  *
1308  * Referenced by:
1309  *   bwn_nphy_workarounds_rev3plus()
1310  */
1311 static uint8_t
1312 bhnd_compat_sprom_get_fem_2ghz_pdet_range(device_t dev)
1313 {
1314         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_PDETRANGE2G);
1315 }
1316
1317 /*
1318  * siba_sprom_get_fem_2ghz_tr_iso()
1319  *
1320  * Referenced by:
1321  *   bwn_nphy_get_gain_ctl_workaround_ent()
1322  */
1323 static uint8_t
1324 bhnd_compat_sprom_get_fem_2ghz_tr_iso(device_t dev)
1325 {
1326         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TRISO2G);
1327 }
1328
1329 /*
1330  * siba_sprom_get_fem_2ghz_antswlut()
1331  *
1332  * Referenced by:
1333  *   bwn_nphy_tables_init_rev3()
1334  *   bwn_nphy_tables_init_rev7_volatile()
1335  */
1336 static uint8_t
1337 bhnd_compat_sprom_get_fem_2ghz_antswlut(device_t dev)
1338 {
1339         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_ANTSWCTL2G);
1340 }
1341
1342 /*
1343  * siba_sprom_get_fem_5ghz_extpa_gain()
1344  *
1345  * Referenced by:
1346  *   bwn_nphy_get_tx_gain_table()
1347  *   bwn_nphy_op_prepare_structs()
1348  */
1349 static uint8_t
1350 bhnd_compat_sprom_get_fem_5ghz_extpa_gain(device_t dev)
1351 {
1352         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_EXTPAGAIN5G);
1353 }
1354
1355 /*
1356  * siba_sprom_get_fem_5ghz_pdet_range()
1357  *
1358  * Referenced by:
1359  *   bwn_nphy_workarounds_rev3plus()
1360  */
1361 static uint8_t
1362 bhnd_compat_sprom_get_fem_5ghz_pdet_range(device_t dev)
1363 {
1364         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_PDETRANGE5G);
1365 }
1366
1367 /*
1368  * siba_sprom_get_fem_5ghz_antswlut()
1369  *
1370  * Referenced by:
1371  *   bwn_nphy_tables_init_rev3()
1372  *   bwn_nphy_tables_init_rev7_volatile()
1373  */
1374 static uint8_t
1375 bhnd_compat_sprom_get_fem_5ghz_antswlut(device_t dev)
1376 {
1377         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_ANTSWCTL5G);
1378 }
1379
1380 /*
1381  * siba_sprom_get_txpid_2g_0()
1382  *
1383  * Referenced by:
1384  *   bwn_nphy_tx_power_fix()
1385  */
1386 static uint8_t
1387 bhnd_compat_sprom_get_txpid_2g_0(device_t dev)
1388 {
1389         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID2GA0);
1390 }
1391
1392 /*
1393  * siba_sprom_get_txpid_2g_1()
1394  *
1395  * Referenced by:
1396  *   bwn_nphy_tx_power_fix()
1397  */
1398 static uint8_t
1399 bhnd_compat_sprom_get_txpid_2g_1(device_t dev)
1400 {
1401         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID2GA1);
1402 }
1403
1404 /*
1405  * siba_sprom_get_txpid_5gl_0()
1406  *
1407  * Referenced by:
1408  *   bwn_nphy_tx_power_fix()
1409  */
1410 static uint8_t
1411 bhnd_compat_sprom_get_txpid_5gl_0(device_t dev)
1412 {
1413         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GLA0);
1414 }
1415
1416 /*
1417  * siba_sprom_get_txpid_5gl_1()
1418  *
1419  * Referenced by:
1420  *   bwn_nphy_tx_power_fix()
1421  */
1422 static uint8_t
1423 bhnd_compat_sprom_get_txpid_5gl_1(device_t dev)
1424 {
1425         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GLA1);
1426 }
1427
1428 /*
1429  * siba_sprom_get_txpid_5g_0()
1430  *
1431  * Referenced by:
1432  *   bwn_nphy_tx_power_fix()
1433  */
1434 static uint8_t
1435 bhnd_compat_sprom_get_txpid_5g_0(device_t dev)
1436 {
1437         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GA0);
1438 }
1439
1440 /*
1441  * siba_sprom_get_txpid_5g_1()
1442  *
1443  * Referenced by:
1444  *   bwn_nphy_tx_power_fix()
1445  */
1446 static uint8_t
1447 bhnd_compat_sprom_get_txpid_5g_1(device_t dev)
1448 {
1449         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GA1);
1450 }
1451
1452 /*
1453  * siba_sprom_get_txpid_5gh_0()
1454  *
1455  * Referenced by:
1456  *   bwn_nphy_tx_power_fix()
1457  */
1458 static uint8_t
1459 bhnd_compat_sprom_get_txpid_5gh_0(device_t dev)
1460 {
1461         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GHA0);
1462 }
1463
1464 /*
1465  * siba_sprom_get_txpid_5gh_1()
1466  *
1467  * Referenced by:
1468  *   bwn_nphy_tx_power_fix()
1469  */
1470 static uint8_t
1471 bhnd_compat_sprom_get_txpid_5gh_1(device_t dev)
1472 {
1473         BWN_BHND_NVRAM_RETURN_VAR(dev, uint8, BHND_NVAR_TXPID5GHA1);
1474 }
1475
1476 /*
1477  * siba_sprom_get_stbcpo()
1478  *
1479  * Referenced by:
1480  *   bwn_ppr_load_max_from_sprom()
1481  */
1482 static uint16_t
1483 bhnd_compat_sprom_get_stbcpo(device_t dev)
1484 {
1485         BWN_BHND_NVRAM_RETURN_VAR(dev, uint16, BHND_NVAR_STBCPO);
1486 }
1487
1488 /*
1489  * siba_sprom_get_cddpo()
1490  *
1491  * Referenced by:
1492  *   bwn_ppr_load_max_from_sprom()
1493  */
1494 static uint16_t
1495 bhnd_compat_sprom_get_cddpo(device_t dev)
1496 {
1497         BWN_BHND_NVRAM_RETURN_VAR(dev, uint16, BHND_NVAR_CDDPO);
1498 }
1499
1500 /*
1501  * siba_powerup()
1502  *
1503  * Referenced by:
1504  *   bwn_attach_core()
1505  *   bwn_core_init()
1506  */
1507 static void
1508 bhnd_compat_powerup(device_t dev, int dynamic)
1509 {
1510         struct bwn_bhnd_ctx     *ctx;
1511         bhnd_clock               clock;
1512         int                      error;
1513
1514         ctx = bwn_bhnd_get_ctx(dev);
1515
1516         /* On PMU equipped devices, we do not need to issue a clock request
1517          * at powerup */
1518         if (ctx->pmu_dev != NULL)
1519                 return;
1520
1521         /* Issue a PMU clock request */
1522         if (dynamic)
1523                 clock = BHND_CLOCK_DYN;
1524         else
1525                 clock = BHND_CLOCK_HT;
1526
1527         if ((error = bhnd_request_clock(dev, clock))) {
1528                 device_printf(dev, "%d clock request failed: %d\n",
1529                     clock, error);
1530         }
1531
1532 }
1533
1534 /*
1535  * siba_powerdown()
1536  *
1537  * Referenced by:
1538  *   bwn_attach_core()
1539  *   bwn_core_exit()
1540  *   bwn_core_init()
1541  */
1542 static int
1543 bhnd_compat_powerdown(device_t dev)
1544 {
1545         int     error;
1546
1547         /* Suspend the core */
1548         if ((error = bhnd_suspend_hw(dev, 0)))
1549                 return (error);
1550
1551         return (0);
1552 }
1553
1554 /*
1555  * siba_read_2()
1556  *
1557  * Referenced by:
1558  *   bwn_chip_init()
1559  *   bwn_chiptest()
1560  *   bwn_dummy_transmission()
1561  *   bwn_gpio_init()
1562  *   bwn_phy_getinfo()
1563  *   bwn_pio_read_2()
1564  *   bwn_shm_read_2()
1565  *   bwn_shm_read_4()
1566  *   bwn_wme_init()
1567  *   bwn_wme_loadparams()
1568  * ... and 23 others
1569  * 
1570  */
1571 static uint16_t
1572 bhnd_compat_read_2(device_t dev, uint16_t offset)
1573 {
1574         struct bwn_softc *sc = device_get_softc(dev);
1575
1576         BWN_ASSERT_VALID_REG(dev, offset);
1577
1578         return (bhnd_bus_read_2(sc->sc_mem_res, offset));
1579 }
1580
1581 /*
1582  * siba_write_2()
1583  *
1584  * Referenced by:
1585  *   bwn_chip_init()
1586  *   bwn_chiptest()
1587  *   bwn_crypt_init()
1588  *   bwn_gpio_init()
1589  *   bwn_phy_getinfo()
1590  *   bwn_pio_tx_start()
1591  *   bwn_set_opmode()
1592  *   bwn_shm_write_2()
1593  *   bwn_shm_write_4()
1594  *   bwn_wme_init()
1595  * ... and 43 others
1596  * 
1597  */
1598 static void
1599 bhnd_compat_write_2(device_t dev, uint16_t offset, uint16_t value)
1600 {
1601         struct bwn_softc *sc = device_get_softc(dev);
1602
1603         BWN_ASSERT_VALID_REG(dev, offset);
1604
1605         return (bhnd_bus_write_2(sc->sc_mem_res, offset, value));
1606 }
1607
1608 /*
1609  * siba_read_4()
1610  *
1611  * Referenced by:
1612  *   bwn_attach_core()
1613  *   bwn_chip_init()
1614  *   bwn_chiptest()
1615  *   bwn_core_exit()
1616  *   bwn_core_init()
1617  *   bwn_core_start()
1618  *   bwn_pio_init()
1619  *   bwn_pio_tx_start()
1620  *   bwn_reset_core()
1621  *   bwn_shm_read_4()
1622  * ... and 42 others
1623  * 
1624  */
1625 static uint32_t
1626 bhnd_compat_read_4(device_t dev, uint16_t offset)
1627 {
1628         struct bwn_softc        *sc = device_get_softc(dev);
1629         uint16_t                 ioreg;
1630         int                      error;
1631
1632         /* bwn(4) fetches IOCTL/IOST values directly from siba-specific target
1633          * state registers; we map these directly to bhnd_read_(ioctl|iost) */
1634         switch (offset) {
1635         case SB0_REG_ABS(SIBA_CFG0_TMSTATELOW):
1636                 if ((error = bhnd_read_ioctl(dev, &ioreg)))
1637                         panic("error reading IOCTL: %d\n", error);
1638
1639                 return (((uint32_t)ioreg) << SIBA_TML_SICF_SHIFT);
1640
1641         case SB0_REG_ABS(SIBA_CFG0_TMSTATEHIGH):
1642                 if ((error = bhnd_read_iost(dev, &ioreg)))
1643                         panic("error reading IOST: %d\n", error);
1644
1645                 return (((uint32_t)ioreg) << SIBA_TMH_SISF_SHIFT);
1646         }
1647
1648         /* Otherwise, perform a standard bus read */
1649         BWN_ASSERT_VALID_REG(dev, offset);
1650         return (bhnd_bus_read_4(sc->sc_mem_res, offset));
1651 }
1652
1653 /*
1654  * siba_write_4()
1655  *
1656  * Referenced by:
1657  *   bwn_chip_init()
1658  *   bwn_chiptest()
1659  *   bwn_core_exit()
1660  *   bwn_core_start()
1661  *   bwn_dma_mask()
1662  *   bwn_dma_rxdirectfifo()
1663  *   bwn_pio_init()
1664  *   bwn_reset_core()
1665  *   bwn_shm_ctlword()
1666  *   bwn_shm_write_4()
1667  * ... and 37 others
1668  * 
1669  */
1670 static void
1671 bhnd_compat_write_4(device_t dev, uint16_t offset, uint32_t value)
1672 {
1673         struct bwn_softc        *sc = device_get_softc(dev);
1674         uint16_t                 ioctl;
1675         int                      error;
1676
1677         /* bwn(4) writes IOCTL values directly to siba-specific target state
1678          * registers; we map these directly to bhnd_write_ioctl() */
1679         if (offset == SB0_REG_ABS(SIBA_CFG0_TMSTATELOW)) {
1680                 /* shift IOCTL flags back down to their original values */
1681                 if (value & ~SIBA_TML_SICF_MASK)
1682                         panic("%s: non-IOCTL flags provided", __FUNCTION__);
1683
1684                 ioctl = (value & SIBA_TML_SICF_MASK) >> SIBA_TML_SICF_SHIFT;
1685
1686                 if ((error = bhnd_write_ioctl(dev, ioctl, UINT16_MAX)))
1687                         panic("error writing IOCTL: %d\n", error);
1688         } else {
1689                 /* Otherwise, perform a standard bus write */
1690                 BWN_ASSERT_VALID_REG(dev, offset);
1691
1692                 bhnd_bus_write_4(sc->sc_mem_res, offset, value);
1693         }
1694
1695         return;
1696 }
1697
1698 /*
1699  * siba_dev_up()
1700  *
1701  * Referenced by:
1702  *   bwn_reset_core()
1703  */
1704 static void
1705 bhnd_compat_dev_up(device_t dev, uint32_t flags)
1706 {
1707         uint16_t        ioctl;
1708         int             error;
1709
1710         /* shift IOCTL flags back down to their original values */
1711         if (flags & ~SIBA_TML_SICF_MASK)
1712                 panic("%s: non-IOCTL flags provided", __FUNCTION__);
1713
1714         ioctl = (flags & SIBA_TML_SICF_MASK) >> SIBA_TML_SICF_SHIFT;
1715
1716         /* Perform core reset; note that bwn(4) incorrectly assumes that both
1717          * RESET and post-RESET ioctl flags should be identical */
1718         if ((error = bhnd_reset_hw(dev, ioctl, ioctl)))
1719                 panic("%s: core reset failed: %d", __FUNCTION__, error);
1720 }
1721
1722 /*
1723  * siba_dev_down()
1724  *
1725  * Referenced by:
1726  *   bwn_attach_core()
1727  *   bwn_core_exit()
1728  */
1729 static void
1730 bhnd_compat_dev_down(device_t dev, uint32_t flags)
1731 {
1732         uint16_t        ioctl;
1733         int             error;
1734
1735         /* shift IOCTL flags back down to their original values */
1736         if (flags & ~SIBA_TML_SICF_MASK)
1737                 panic("%s: non-IOCTL flags provided", __FUNCTION__);
1738
1739         ioctl = (flags & SIBA_TML_SICF_MASK) >> SIBA_TML_SICF_SHIFT;
1740
1741         /* Put core into RESET state */
1742         if ((error = bhnd_suspend_hw(dev, ioctl)))
1743                 panic("%s: core suspend failed: %d", __FUNCTION__, error);
1744 }
1745
1746 /*
1747  * siba_dev_isup()
1748  *
1749  * Referenced by:
1750  *   bwn_core_init()
1751  */
1752 static int
1753 bhnd_compat_dev_isup(device_t dev)
1754 {
1755         return (!bhnd_is_hw_suspended(dev));
1756 }
1757
1758 /*
1759  * siba_pcicore_intr()
1760  *
1761  * Referenced by:
1762  *   bwn_core_init()
1763  */
1764 static void
1765 bhnd_compat_pcicore_intr(device_t dev)
1766 {
1767         /* This is handled by bhnd_bhndb on the first call to
1768          * bus_setup_intr() */
1769 }
1770
1771 /*
1772  * siba_dma_translation()
1773  *
1774  * Referenced by:
1775  *   bwn_dma_32_setdesc()
1776  *   bwn_dma_64_setdesc()
1777  *   bwn_dma_setup()
1778  */
1779 static uint32_t
1780 bhnd_compat_dma_translation(device_t dev)
1781 {
1782         struct bhnd_dma_translation      dt;
1783         struct bwn_softc                *sc;
1784         struct bwn_mac                  *mac;
1785         u_int                            width;
1786         int                              error;
1787
1788         sc = device_get_softc(dev);
1789         mac = sc->sc_curmac;
1790         KASSERT(mac != NULL, ("no MAC"));
1791
1792         /*
1793          * Use the DMA engine's maximum host address width to determine the
1794          * supported device address width.
1795          */
1796         switch (mac->mac_method.dma.dmatype) {
1797                 case BWN_DMA_32BIT:
1798                 case BWN_DMA_30BIT:
1799                         /* The 32-bit engine is always capable of addressing
1800                          * a full 32-bit device address */
1801                         width = BHND_DMA_ADDR_32BIT;
1802                         break;
1803
1804                 case BWN_DMA_64BIT:
1805                         width = BHND_DMA_ADDR_64BIT;
1806                         break;
1807
1808                 default:
1809                         panic("unknown dma type %d",
1810                             mac->mac_method.dma.dmatype);
1811         }
1812
1813
1814         /* Fetch our DMA translation */
1815         if ((error = bhnd_get_dma_translation(dev, width, 0, NULL, &dt)))
1816                 panic("error requesting DMA translation: %d\n", error);
1817
1818         /*
1819          * TODO: bwn(4) needs to switch to bhnd_get_dma_translation().
1820          *
1821          * Currently, bwn(4) incorrectly assumes that:
1822          *  - The 32-bit translation mask is always SIBA_DMA_TRANSLATION_MASK.
1823          *  - The 32-bit mask can simply be applied to the top 32-bits of a
1824          *    64-bit DMA address.
1825          *  - The 64-bit address translation is always derived by shifting the
1826          *    32-bit siba_dma_translation() left by 1 bit.
1827          *
1828          * In practice, these assumptions won't result in any bugs on known
1829          * PCI/PCIe Wi-Fi hardware:
1830          *  - The 32-bit mask _is_ always SIBA_DMA_TRANSLATION_MASK on
1831          *    the subset of devices supported by bwn(4).
1832          *  - The 64-bit mask used by bwn(4) is a superset of the real
1833          *    mask, and thus:
1834          *      - Our DMA tag will still have valid constraints.
1835          *      - Our address translation will not be corrupted by
1836          *        applying the mask.
1837          *  - The mask falls within the top 16 address bits, and our
1838          *    supported 64-bit architectures are all still limited
1839          *    to 48-bit addresses anyway; we don't need to worry about
1840          *    addressing >= 48-bit host memory.
1841          *
1842          * However, we will need to resolve these issues in bwn(4) if DMA is to
1843          * work on new hardware (e.g. WiSoCs).
1844          */
1845         switch (width) {
1846         case BHND_DMA_ADDR_32BIT:
1847                 KASSERT((~dt.addr_mask & BHND_DMA_ADDR_BITMASK(32)) ==
1848                     SIBA_DMA_TRANSLATION_MASK, ("unexpected DMA mask: %#jx",
1849                     (uintmax_t)dt.addr_mask));
1850
1851                 return (dt.base_addr);
1852
1853         case BHND_DMA_ADDR_64BIT:
1854                 /* bwn(4) will shift this left by 32+1 bits before applying it
1855                  * to the top 32-bits of the DMA address */
1856                 KASSERT((~dt.addr_mask & BHND_DMA_ADDR_BITMASK(33)) == 0,
1857                     ("DMA64 translation %#jx masks low 33-bits",
1858                      (uintmax_t)dt.addr_mask));
1859
1860                 return (dt.base_addr >> 33);
1861
1862         default:
1863                 panic("unsupported address width: %u", width);
1864         }
1865 }
1866
1867 /*
1868  * siba_read_multi_2()
1869  *
1870  * Referenced by:
1871  *   bwn_pio_rxeof()
1872  */
1873 static void
1874 bhnd_compat_read_multi_2(device_t dev, void *buffer, size_t count,
1875     uint16_t offset)
1876 {
1877         struct bwn_softc *sc = device_get_softc(dev);
1878
1879         BWN_ASSERT_VALID_REG(dev, offset);
1880         return (bhnd_bus_read_multi_2(sc->sc_mem_res, offset, buffer, count));
1881 }
1882
1883 /*
1884  * siba_read_multi_4()
1885  *
1886  * Referenced by:
1887  *   bwn_pio_rxeof()
1888  */
1889 static void
1890 bhnd_compat_read_multi_4(device_t dev, void *buffer, size_t count,
1891     uint16_t offset)
1892 {
1893         struct bwn_softc *sc = device_get_softc(dev);
1894
1895         BWN_ASSERT_VALID_REG(dev, offset);
1896         return (bhnd_bus_read_multi_4(sc->sc_mem_res, offset, buffer, count));
1897 }
1898
1899 /*
1900  * siba_write_multi_2()
1901  *
1902  * Referenced by:
1903  *   bwn_pio_write_multi_2()
1904  */
1905 static void
1906 bhnd_compat_write_multi_2(device_t dev, const void *buffer, size_t count,
1907     uint16_t offset)
1908 {
1909         struct bwn_softc *sc = device_get_softc(dev);
1910
1911         BWN_ASSERT_VALID_REG(dev, offset);
1912
1913         /* XXX discarding const to maintain API compatibility with
1914          * siba_write_multi_2() */
1915         bhnd_bus_write_multi_2(sc->sc_mem_res, offset,
1916             __DECONST(void *, buffer), count);
1917 }
1918
1919 /*
1920  * siba_write_multi_4()
1921  *
1922  * Referenced by:
1923  *   bwn_pio_write_multi_4()
1924  */
1925 static void
1926 bhnd_compat_write_multi_4(device_t dev, const void *buffer, size_t count,
1927     uint16_t offset)
1928 {
1929         struct bwn_softc *sc = device_get_softc(dev);
1930
1931         BWN_ASSERT_VALID_REG(dev, offset);
1932
1933         /* XXX discarding const to maintain API compatibility with
1934          * siba_write_multi_4() */
1935         bhnd_bus_write_multi_4(sc->sc_mem_res, offset,
1936             __DECONST(void *, buffer), count);
1937 }
1938
1939 /*
1940  * siba_barrier()
1941  *
1942  * Referenced by:
1943  *   bwn_intr()
1944  *   bwn_intrtask()
1945  *   bwn_ram_write()
1946  */
1947 static void
1948 bhnd_compat_barrier(device_t dev, int flags)
1949 {
1950         struct bwn_softc *sc = device_get_softc(dev);
1951
1952         /* XXX is siba_barrier()'s use of an offset and length of 0
1953          * correct? */
1954         BWN_ASSERT_VALID_REG(dev, 0);
1955         bhnd_bus_barrier(sc->sc_mem_res, 0, 0, flags);
1956 }
1957
1958 /*
1959  * siba_cc_pmu_set_ldovolt()
1960  *
1961  * Referenced by:
1962  *   bwn_phy_lp_bbinit_r01()
1963  */
1964 static void
1965 bhnd_compat_cc_pmu_set_ldovolt(device_t dev, int id, uint32_t volt)
1966 {
1967         struct bwn_bhnd_ctx     *ctx;
1968         int                      error;
1969
1970         ctx = bwn_bhnd_get_ctx(dev);
1971
1972         /* Only ever used to set the PAREF LDO voltage */
1973         if (id != SIBA_LDO_PAREF)
1974                 panic("invalid LDO id: %d", id);
1975
1976         /* Configuring regulator voltage requires a PMU */
1977         if (ctx->pmu_dev == NULL)
1978                 panic("no PMU; cannot set LDO voltage");
1979
1980         error = bhnd_pmu_set_voltage_raw(ctx->pmu_dev, BHND_REGULATOR_PAREF_LDO,
1981             volt);
1982         if (error)
1983                 panic("failed to set LDO voltage: %d", error);
1984 }
1985
1986 /*
1987  * siba_cc_pmu_set_ldoparef()
1988  *
1989  * Referenced by:
1990  *   bwn_phy_lp_bbinit_r01()
1991  */
1992 static void
1993 bhnd_compat_cc_pmu_set_ldoparef(device_t dev, uint8_t on)
1994 {
1995         struct bwn_bhnd_ctx     *ctx;
1996         int                      error;
1997
1998         ctx = bwn_bhnd_get_ctx(dev);
1999
2000         /* Enabling/disabling regulators requires a PMU */
2001         if (ctx->pmu_dev == NULL)
2002                 panic("no PMU; cannot set LDO voltage");
2003
2004         if (on) {
2005                 error = bhnd_pmu_enable_regulator(ctx->pmu_dev,
2006                     BHND_REGULATOR_PAREF_LDO);
2007         } else {
2008                 error = bhnd_pmu_disable_regulator(ctx->pmu_dev,
2009                     BHND_REGULATOR_PAREF_LDO);
2010         }
2011
2012         if (error) {
2013                 panic("failed to %s PAREF_LDO: %d", on ? "enable" : "disable",
2014                     error);
2015         }
2016 }
2017
2018 /*
2019  * siba_gpio_set()
2020  *
2021  * Referenced by:
2022  *   bwn_chip_exit()
2023  *   bwn_chip_init()
2024  *   bwn_gpio_init()
2025  *   bwn_nphy_superswitch_init()
2026  */
2027 static void
2028 bhnd_compat_gpio_set(device_t dev, uint32_t value)
2029 {
2030         struct bwn_bhnd_ctx     *ctx;
2031         uint32_t                 flags[32];
2032         int                      error;
2033
2034         ctx = bwn_bhnd_get_ctx(dev);
2035
2036         for (size_t i = 0; i < nitems(flags); i++) {
2037                 if (value & (1 << i)) {
2038                         /* Tristate pin */
2039                         flags[i] = (GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
2040                 } else {
2041                         /* Leave unmodified */
2042                         flags[i] = 0;
2043                 }
2044         }
2045
2046         error = GPIO_PIN_CONFIG_32(ctx->gpio_dev, 0, nitems(flags), flags);
2047         if (error)
2048                 panic("error configuring pin flags: %d", error);
2049 }
2050
2051 /*
2052  * siba_gpio_get()
2053  *
2054  * Referenced by:
2055  *   bwn_gpio_init()
2056  */
2057 static uint32_t
2058 bhnd_compat_gpio_get(device_t dev)
2059 {
2060         struct bwn_bhnd_ctx     *ctx;
2061         uint32_t                 ctrl;
2062         int                      npin;
2063         int                      error;
2064
2065         /*
2066          * We recreate the expected GPIOCTRL register value for bwn_gpio_init()
2067          * by querying pins individually for GPIO_PIN_TRISTATE.
2068          * 
2069          * Once we drop these compatibility shims, the GPIO_PIN_CONFIG_32 method
2070          * can be used to set pin configuration without bwn(4) externally
2071          * implementing RMW.
2072          */
2073
2074         /* Fetch the total pin count */
2075         ctx = bwn_bhnd_get_ctx(dev);
2076         if ((error = GPIO_PIN_MAX(ctx->gpio_dev, &npin)))
2077                 panic("failed to fetch max pin: %d", error);
2078
2079         /* Must be representable within a 32-bit GPIOCTRL register value */
2080         KASSERT(npin <= 32, ("unsupported pin count: %u", npin));
2081
2082         ctrl = 0;
2083         for (uint32_t pin = 0; pin < npin; pin++) {
2084                 uint32_t flags;
2085
2086                 if ((error = GPIO_PIN_GETFLAGS(ctx->gpio_dev, pin, &flags)))
2087                         panic("error fetching pin%u flags: %d", pin, error);
2088
2089                 if (flags & GPIO_PIN_TRISTATE)
2090                         ctrl |= (1 << pin);
2091         }
2092
2093         return (ctrl);
2094 }
2095
2096 /*
2097  * siba_fix_imcfglobug()
2098  *
2099  * Referenced by:
2100  *   bwn_core_init()
2101  */
2102 static void
2103 bhnd_compat_fix_imcfglobug(device_t dev)
2104 {
2105         /* This is handled by siba_bhndb during attach/resume */
2106 }
2107
2108
2109 /* Core power NVRAM variables, indexed by D11 core unit number */
2110 static const struct bwn_power_vars {
2111         const char *itt2ga;
2112         const char *itt5ga;
2113         const char *maxp2ga;
2114         const char *pa2ga;
2115         const char *pa5ga;
2116 } bwn_power_vars[BWN_BHND_NUM_CORE_PWR] = {
2117 #define BHND_POWER_NVAR(_idx)                                   \
2118         { BHND_NVAR_ITT2GA ## _idx, BHND_NVAR_ITT5GA ## _idx,   \
2119           BHND_NVAR_MAXP2GA ## _idx, BHND_NVAR_PA2GA ## _idx,   \
2120           BHND_NVAR_PA5GA ## _idx }
2121         BHND_POWER_NVAR(0),
2122         BHND_POWER_NVAR(1),
2123         BHND_POWER_NVAR(2),
2124         BHND_POWER_NVAR(3)
2125 #undef BHND_POWER_NVAR
2126 };
2127
2128 static int
2129 bwn_get_core_power_info_r11(device_t dev, const struct bwn_power_vars *v,
2130     struct siba_sprom_core_pwr_info *c)
2131 {
2132         int16_t pa5ga[12];
2133         int     error;
2134
2135         /* BHND_NVAR_PA2GA[core] */
2136         error = bhnd_nvram_getvar_array(dev, v->pa2ga, c->pa_2g,
2137             sizeof(c->pa_2g), BHND_NVRAM_TYPE_INT16);
2138         if (error)
2139                 return (error);
2140
2141         /* 
2142          * BHND_NVAR_PA5GA
2143          * 
2144          * The NVRAM variable is defined as a single pa5ga[12] array; we have
2145          * to split this into pa_5gl[4], pa_5g[4], and pa_5gh[4] for use
2146          * by bwn(4);
2147          */
2148         _Static_assert(nitems(pa5ga) == nitems(c->pa_5g) + nitems(c->pa_5gh) +
2149             nitems(c->pa_5gl), "cannot split pa5ga into pa_5gl/pa_5g/pa_5gh");
2150
2151         error = bhnd_nvram_getvar_array(dev, v->pa5ga, pa5ga, sizeof(pa5ga),
2152             BHND_NVRAM_TYPE_INT16);
2153         if (error)
2154                 return (error);
2155
2156         memcpy(c->pa_5gl, &pa5ga[0], sizeof(c->pa_5gl));
2157         memcpy(c->pa_5g, &pa5ga[4], sizeof(c->pa_5g));
2158         memcpy(c->pa_5gh, &pa5ga[8], sizeof(c->pa_5gh));
2159         return (0);
2160 }
2161
2162 static int
2163 bwn_get_core_power_info_r4_r10(device_t dev,
2164     const struct bwn_power_vars *v, struct siba_sprom_core_pwr_info *c)
2165 {
2166         int error;
2167
2168         /* BHND_NVAR_ITT2GA[core] */
2169         if ((error = bhnd_nvram_getvar_uint8(dev, v->itt2ga, &c->itssi_2g)))
2170                 return (error);
2171
2172         /* BHND_NVAR_ITT5GA[core] */
2173         if ((error = bhnd_nvram_getvar_uint8(dev, v->itt5ga, &c->itssi_5g)))
2174                 return (error);
2175
2176         return (0);
2177 }
2178
2179 /*
2180  * siba_sprom_get_core_power_info()
2181  *
2182  * Referenced by:
2183  *   bwn_nphy_tx_power_ctl_setup()
2184  *   bwn_ppr_load_max_from_sprom()
2185  */
2186 static int
2187 bhnd_compat_sprom_get_core_power_info(device_t dev, int core,
2188     struct siba_sprom_core_pwr_info *c)
2189 {
2190         struct bwn_bhnd_ctx             *ctx;
2191         const struct bwn_power_vars     *v;
2192         int                              error;
2193
2194         if (core < 0 || core >= nitems(bwn_power_vars))
2195                 return (EINVAL);
2196
2197         ctx = bwn_bhnd_get_ctx(dev);
2198         if (ctx->sromrev < 4)
2199                 return (ENXIO);
2200
2201         v = &bwn_power_vars[core];
2202
2203         /* Any power variables not found in NVRAM (or returning a
2204          * shorter array for a particular NVRAM revision) should be zero
2205          * initialized */
2206         memset(c, 0x0, sizeof(*c));
2207
2208         /* Populate SPROM revision-independent values */
2209         if ((error = bhnd_nvram_getvar_uint8(dev, v->maxp2ga, &c->maxpwr_2g)))
2210                 return (error);
2211
2212         /* Populate SPROM revision-specific values */
2213         if (ctx->sromrev >= 4 && ctx->sromrev <= 10)
2214                 return (bwn_get_core_power_info_r4_r10(dev, v, c));
2215         else
2216                 return (bwn_get_core_power_info_r11(dev, v, c));
2217 }
2218
2219 /*
2220  * siba_sprom_get_mcs2gpo()
2221  *
2222  * Referenced by:
2223  *   bwn_ppr_load_max_from_sprom()
2224  */
2225 static int
2226 bhnd_compat_sprom_get_mcs2gpo(device_t dev, uint16_t *c)
2227 {
2228         static const char *varnames[] = {
2229                 BHND_NVAR_MCS2GPO0,
2230                 BHND_NVAR_MCS2GPO1,
2231                 BHND_NVAR_MCS2GPO2,
2232                 BHND_NVAR_MCS2GPO3,
2233                 BHND_NVAR_MCS2GPO4,
2234                 BHND_NVAR_MCS2GPO5,
2235                 BHND_NVAR_MCS2GPO6,
2236                 BHND_NVAR_MCS2GPO7
2237         };
2238
2239         for (size_t i = 0; i < nitems(varnames); i++) {
2240                 const char *name = varnames[i];
2241                 BWN_BHND_NVRAM_FETCH_VAR(dev, uint16, name, &c[i]);
2242         }
2243
2244         return (0);
2245 }
2246
2247 /*
2248  * siba_sprom_get_mcs5glpo()
2249  *
2250  * Referenced by:
2251  *   bwn_ppr_load_max_from_sprom()
2252  */
2253 static int
2254 bhnd_compat_sprom_get_mcs5glpo(device_t dev, uint16_t *c)
2255 {
2256         static const char *varnames[] = {
2257                 BHND_NVAR_MCS5GLPO0,
2258                 BHND_NVAR_MCS5GLPO1,
2259                 BHND_NVAR_MCS5GLPO2,
2260                 BHND_NVAR_MCS5GLPO3,
2261                 BHND_NVAR_MCS5GLPO4,
2262                 BHND_NVAR_MCS5GLPO5,
2263                 BHND_NVAR_MCS5GLPO6,
2264                 BHND_NVAR_MCS5GLPO7
2265         };
2266
2267         for (size_t i = 0; i < nitems(varnames); i++) {
2268                 const char *name = varnames[i];
2269                 BWN_BHND_NVRAM_FETCH_VAR(dev, uint16, name, &c[i]);
2270         }
2271
2272         return (0);
2273 }
2274
2275 /*
2276  * siba_sprom_get_mcs5gpo()
2277  *
2278  * Referenced by:
2279  *   bwn_ppr_load_max_from_sprom()
2280  */
2281 static int
2282 bhnd_compat_sprom_get_mcs5gpo(device_t dev, uint16_t *c)
2283 {
2284         static const char *varnames[] = {
2285                 BHND_NVAR_MCS5GPO0,
2286                 BHND_NVAR_MCS5GPO1,
2287                 BHND_NVAR_MCS5GPO2,
2288                 BHND_NVAR_MCS5GPO3,
2289                 BHND_NVAR_MCS5GPO4,
2290                 BHND_NVAR_MCS5GPO5,
2291                 BHND_NVAR_MCS5GPO6,
2292                 BHND_NVAR_MCS5GPO7
2293         };
2294
2295         for (size_t i = 0; i < nitems(varnames); i++) {
2296                 const char *name = varnames[i];
2297                 BWN_BHND_NVRAM_FETCH_VAR(dev, uint16, name, &c[i]);
2298         }
2299
2300         return (0);
2301 }
2302
2303 /*
2304  * siba_sprom_get_mcs5ghpo()
2305  *
2306  * Referenced by:
2307  *   bwn_ppr_load_max_from_sprom()
2308  */
2309 static int
2310 bhnd_compat_sprom_get_mcs5ghpo(device_t dev, uint16_t *c)
2311 {
2312         static const char *varnames[] = {
2313                 BHND_NVAR_MCS5GHPO0,
2314                 BHND_NVAR_MCS5GHPO1,
2315                 BHND_NVAR_MCS5GHPO2,
2316                 BHND_NVAR_MCS5GHPO3,
2317                 BHND_NVAR_MCS5GHPO4,
2318                 BHND_NVAR_MCS5GHPO5,
2319                 BHND_NVAR_MCS5GHPO6,
2320                 BHND_NVAR_MCS5GHPO7
2321         };
2322
2323         for (size_t i = 0; i < nitems(varnames); i++) {
2324                 const char *name = varnames[i];
2325                 BWN_BHND_NVRAM_FETCH_VAR(dev, uint16, name, &c[i]);
2326         }
2327
2328         return (0);
2329 }
2330
2331 /*
2332  * siba_pmu_spuravoid_pllupdate()
2333  *
2334  * Referenced by:
2335  *   bwn_nphy_pmu_spur_avoid()
2336  */
2337 static void
2338 bhnd_compat_pmu_spuravoid_pllupdate(device_t dev, int spur_avoid)
2339 {
2340         struct bwn_bhnd_ctx     *ctx;
2341         bhnd_pmu_spuravoid       mode;
2342         int                      error;
2343
2344         ctx = bwn_bhnd_get_ctx(dev);
2345
2346         if (ctx->pmu_dev == NULL)
2347                 panic("requested spuravoid on non-PMU device");
2348
2349         switch (spur_avoid) {
2350         case 0:
2351                 mode = BHND_PMU_SPURAVOID_NONE;
2352                 break;
2353         case 1:
2354                 mode = BHND_PMU_SPURAVOID_M1;
2355                 break;
2356         default:
2357                 panic("unknown spur_avoid: %d", spur_avoid);
2358         }
2359
2360         if ((error = bhnd_pmu_request_spuravoid(ctx->pmu_dev, mode)))
2361                 panic("spuravoid request failed: %d", error);
2362 }
2363
2364 /*
2365  * siba_cc_set32()
2366  *
2367  * Referenced by:
2368  *   bwn_phy_initn()
2369  *   bwn_wireless_core_phy_pll_reset()
2370  */
2371 static void
2372 bhnd_compat_cc_set32(device_t dev, uint32_t reg, uint32_t val)
2373 {
2374         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
2375         
2376         /*
2377          * OR with the current value.
2378          *
2379          * This function is only ever used to write to either ChipCommon's
2380          * chipctrl register or chipctl_data register. Note that chipctl_data
2381          * is actually a PMU register; it is not actually mapped by ChipCommon
2382          * on Always-on-Bus (AOB) devices with a standalone PMU core.
2383          */
2384         if (dev != ctx->chipc_dev)
2385                 panic("unsupported device: %s", device_get_nameunit(dev));
2386
2387         switch (reg) {
2388         case SIBA_CC_CHIPCTL:
2389                 BHND_CHIPC_WRITE_CHIPCTRL(ctx->chipc_dev, val, val);
2390                 break;
2391         case SIBA_CC_CHIPCTL_DATA:
2392                 bhnd_pmu_write_chipctrl(ctx->pmu_dev, ctx->pmu_cctl_addr, val,
2393                     val);
2394                 break;
2395         default:
2396                 panic("unsupported register: %#x", reg);
2397         }
2398 }
2399
2400 /*
2401  * siba_cc_mask32()
2402  *
2403  * Referenced by:
2404  *   bwn_wireless_core_phy_pll_reset()
2405  */
2406 static void
2407 bhnd_compat_cc_mask32(device_t dev, uint32_t reg, uint32_t mask)
2408 {
2409         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
2410
2411         /*
2412          * AND with the current value.
2413          *
2414          * This function is only ever used to write to ChipCommon's chipctl_data
2415          * register. Note that chipctl_data is actually a PMU register; it is
2416          * not actually mapped by ChipCommon on Always-on-Bus (AOB) devices with
2417          * a standalone PMU core.
2418          */
2419         if (dev != ctx->chipc_dev)
2420                 panic("unsupported device: %s", device_get_nameunit(dev));
2421
2422         switch (reg) {
2423         case SIBA_CC_CHIPCTL_DATA:
2424                 bhnd_pmu_write_chipctrl(ctx->pmu_dev, ctx->pmu_cctl_addr, 0,
2425                     ~mask);
2426                 break;
2427         default:
2428                 panic("unsupported register: %#x", reg);
2429         }
2430 }
2431
2432 /*
2433  * siba_cc_write32()
2434  *
2435  * Referenced by:
2436  *   bwn_wireless_core_phy_pll_reset()
2437  */
2438 static void
2439 bhnd_compat_cc_write32(device_t dev, uint32_t reg, uint32_t val)
2440 {
2441         struct bwn_bhnd_ctx *ctx = bwn_bhnd_get_ctx(dev);
2442
2443         /*
2444          * This function is only ever used to write to ChipCommon's chipctl_addr
2445          * register; setting chipctl_addr is handled atomically by
2446          * bhnd_pmu_write_chipctrl(), so we merely cache the intended address
2447          * for later use when chipctl_data is written.
2448          *
2449          * Also, note that chipctl_addr is actually a PMU register; it is
2450          * not actually mapped by ChipCommon on Always-on-Bus (AOB) devices with
2451          * a standalone PMU core.
2452          */
2453         if (dev != ctx->chipc_dev)
2454                 panic("unsupported device: %s", device_get_nameunit(dev));
2455
2456         switch (reg) {
2457         case SIBA_CC_CHIPCTL_ADDR:
2458                 ctx->pmu_cctl_addr = val;
2459                 break;
2460         default:
2461                 panic("unsupported register: %#x", reg);
2462         }
2463 }
2464
2465 const struct bwn_bus_ops bwn_bhnd_bus_ops = {
2466         .init                           = bwn_bhnd_bus_ops_init,
2467         .fini                           = bwn_bhnd_bus_ops_fini,
2468         .pci_find_cap                   = bhnd_compat_pci_find_cap,
2469         .pci_alloc_msi                  = bhnd_compat_pci_alloc_msi,
2470         .pci_release_msi                = bhnd_compat_pci_release_msi,
2471         .pci_msi_count                  = bhnd_compat_pci_msi_count,
2472         .get_vendor                     = bhnd_compat_get_vendor,
2473         .get_device                     = bhnd_compat_get_device,
2474         .get_revid                      = bhnd_compat_get_revid,
2475         .get_pci_vendor                 = bhnd_compat_get_pci_vendor,
2476         .get_pci_device                 = bhnd_compat_get_pci_device,
2477         .get_pci_subvendor              = bhnd_compat_get_pci_subvendor,
2478         .get_pci_subdevice              = bhnd_compat_get_pci_subdevice,
2479         .get_pci_revid                  = bhnd_compat_get_pci_revid,
2480         .get_chipid                     = bhnd_compat_get_chipid,
2481         .get_chiprev                    = bhnd_compat_get_chiprev,
2482         .get_chippkg                    = bhnd_compat_get_chippkg,
2483         .get_type                       = bhnd_compat_get_type,
2484         .get_cc_pmufreq                 = bhnd_compat_get_cc_pmufreq,
2485         .get_cc_caps                    = bhnd_compat_get_cc_caps,
2486         .get_cc_powerdelay              = bhnd_compat_get_cc_powerdelay,
2487         .get_pcicore_revid              = bhnd_compat_get_pcicore_revid,
2488         .sprom_get_rev                  = bhnd_compat_sprom_get_rev,
2489         .sprom_get_mac_80211bg          = bhnd_compat_sprom_get_mac_80211bg,
2490         .sprom_get_mac_80211a           = bhnd_compat_sprom_get_mac_80211a,
2491         .sprom_get_brev                 = bhnd_compat_sprom_get_brev,
2492         .sprom_get_ccode                = bhnd_compat_sprom_get_ccode,
2493         .sprom_get_ant_a                = bhnd_compat_sprom_get_ant_a,
2494         .sprom_get_ant_bg               = bhnd_compat_sprom_get_ant_bg,
2495         .sprom_get_pa0b0                = bhnd_compat_sprom_get_pa0b0,
2496         .sprom_get_pa0b1                = bhnd_compat_sprom_get_pa0b1,
2497         .sprom_get_pa0b2                = bhnd_compat_sprom_get_pa0b2,
2498         .sprom_get_gpio0                = bhnd_compat_sprom_get_gpio0,
2499         .sprom_get_gpio1                = bhnd_compat_sprom_get_gpio1,
2500         .sprom_get_gpio2                = bhnd_compat_sprom_get_gpio2,
2501         .sprom_get_gpio3                = bhnd_compat_sprom_get_gpio3,
2502         .sprom_get_maxpwr_bg            = bhnd_compat_sprom_get_maxpwr_bg,
2503         .sprom_set_maxpwr_bg            = bhnd_compat_sprom_set_maxpwr_bg,
2504         .sprom_get_rxpo2g               = bhnd_compat_sprom_get_rxpo2g,
2505         .sprom_get_rxpo5g               = bhnd_compat_sprom_get_rxpo5g,
2506         .sprom_get_tssi_bg              = bhnd_compat_sprom_get_tssi_bg,
2507         .sprom_get_tri2g                = bhnd_compat_sprom_get_tri2g,
2508         .sprom_get_tri5gl               = bhnd_compat_sprom_get_tri5gl,
2509         .sprom_get_tri5g                = bhnd_compat_sprom_get_tri5g,
2510         .sprom_get_tri5gh               = bhnd_compat_sprom_get_tri5gh,
2511         .sprom_get_rssisav2g            = bhnd_compat_sprom_get_rssisav2g,
2512         .sprom_get_rssismc2g            = bhnd_compat_sprom_get_rssismc2g,
2513         .sprom_get_rssismf2g            = bhnd_compat_sprom_get_rssismf2g,
2514         .sprom_get_bxa2g                = bhnd_compat_sprom_get_bxa2g,
2515         .sprom_get_rssisav5g            = bhnd_compat_sprom_get_rssisav5g,
2516         .sprom_get_rssismc5g            = bhnd_compat_sprom_get_rssismc5g,
2517         .sprom_get_rssismf5g            = bhnd_compat_sprom_get_rssismf5g,
2518         .sprom_get_bxa5g                = bhnd_compat_sprom_get_bxa5g,
2519         .sprom_get_cck2gpo              = bhnd_compat_sprom_get_cck2gpo,
2520         .sprom_get_ofdm2gpo             = bhnd_compat_sprom_get_ofdm2gpo,
2521         .sprom_get_ofdm5glpo            = bhnd_compat_sprom_get_ofdm5glpo,
2522         .sprom_get_ofdm5gpo             = bhnd_compat_sprom_get_ofdm5gpo,
2523         .sprom_get_ofdm5ghpo            = bhnd_compat_sprom_get_ofdm5ghpo,
2524         .sprom_get_bf_lo                = bhnd_compat_sprom_get_bf_lo,
2525         .sprom_set_bf_lo                = bhnd_compat_sprom_set_bf_lo,
2526         .sprom_get_bf_hi                = bhnd_compat_sprom_get_bf_hi,
2527         .sprom_get_bf2_lo               = bhnd_compat_sprom_get_bf2_lo,
2528         .sprom_get_bf2_hi               = bhnd_compat_sprom_get_bf2_hi,
2529         .sprom_get_fem_2ghz_tssipos     = bhnd_compat_sprom_get_fem_2ghz_tssipos,
2530         .sprom_get_fem_2ghz_extpa_gain  = bhnd_compat_sprom_get_fem_2ghz_extpa_gain,
2531         .sprom_get_fem_2ghz_pdet_range  = bhnd_compat_sprom_get_fem_2ghz_pdet_range,
2532         .sprom_get_fem_2ghz_tr_iso      = bhnd_compat_sprom_get_fem_2ghz_tr_iso,
2533         .sprom_get_fem_2ghz_antswlut    = bhnd_compat_sprom_get_fem_2ghz_antswlut,
2534         .sprom_get_fem_5ghz_extpa_gain  = bhnd_compat_sprom_get_fem_5ghz_extpa_gain,
2535         .sprom_get_fem_5ghz_pdet_range  = bhnd_compat_sprom_get_fem_5ghz_pdet_range,
2536         .sprom_get_fem_5ghz_antswlut    = bhnd_compat_sprom_get_fem_5ghz_antswlut,
2537         .sprom_get_txpid_2g_0           = bhnd_compat_sprom_get_txpid_2g_0,
2538         .sprom_get_txpid_2g_1           = bhnd_compat_sprom_get_txpid_2g_1,
2539         .sprom_get_txpid_5gl_0          = bhnd_compat_sprom_get_txpid_5gl_0,
2540         .sprom_get_txpid_5gl_1          = bhnd_compat_sprom_get_txpid_5gl_1,
2541         .sprom_get_txpid_5g_0           = bhnd_compat_sprom_get_txpid_5g_0,
2542         .sprom_get_txpid_5g_1           = bhnd_compat_sprom_get_txpid_5g_1,
2543         .sprom_get_txpid_5gh_0          = bhnd_compat_sprom_get_txpid_5gh_0,
2544         .sprom_get_txpid_5gh_1          = bhnd_compat_sprom_get_txpid_5gh_1,
2545         .sprom_get_stbcpo               = bhnd_compat_sprom_get_stbcpo,
2546         .sprom_get_cddpo                = bhnd_compat_sprom_get_cddpo,
2547         .powerup                        = bhnd_compat_powerup,
2548         .powerdown                      = bhnd_compat_powerdown,
2549         .read_2                         = bhnd_compat_read_2,
2550         .write_2                        = bhnd_compat_write_2,
2551         .read_4                         = bhnd_compat_read_4,
2552         .write_4                        = bhnd_compat_write_4,
2553         .dev_up                         = bhnd_compat_dev_up,
2554         .dev_down                       = bhnd_compat_dev_down,
2555         .dev_isup                       = bhnd_compat_dev_isup,
2556         .pcicore_intr                   = bhnd_compat_pcicore_intr,
2557         .dma_translation                = bhnd_compat_dma_translation,
2558         .read_multi_2                   = bhnd_compat_read_multi_2,
2559         .read_multi_4                   = bhnd_compat_read_multi_4,
2560         .write_multi_2                  = bhnd_compat_write_multi_2,
2561         .write_multi_4                  = bhnd_compat_write_multi_4,
2562         .barrier                        = bhnd_compat_barrier,
2563         .cc_pmu_set_ldovolt             = bhnd_compat_cc_pmu_set_ldovolt,
2564         .cc_pmu_set_ldoparef            = bhnd_compat_cc_pmu_set_ldoparef,
2565         .gpio_set                       = bhnd_compat_gpio_set,
2566         .gpio_get                       = bhnd_compat_gpio_get,
2567         .fix_imcfglobug                 = bhnd_compat_fix_imcfglobug,
2568         .sprom_get_core_power_info      = bhnd_compat_sprom_get_core_power_info,
2569         .sprom_get_mcs2gpo              = bhnd_compat_sprom_get_mcs2gpo,
2570         .sprom_get_mcs5glpo             = bhnd_compat_sprom_get_mcs5glpo,
2571         .sprom_get_mcs5gpo              = bhnd_compat_sprom_get_mcs5gpo,
2572         .sprom_get_mcs5ghpo             = bhnd_compat_sprom_get_mcs5ghpo,
2573         .pmu_spuravoid_pllupdate        = bhnd_compat_pmu_spuravoid_pllupdate,
2574         .cc_set32                       = bhnd_compat_cc_set32,
2575         .cc_mask32                      = bhnd_compat_cc_mask32,
2576         .cc_write32                     = bhnd_compat_cc_write32,
2577 };