1b70f530bSAdrian Chadd /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4b70f530bSAdrian Chadd * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
5b70f530bSAdrian Chadd * All rights reserved.
6b70f530bSAdrian Chadd *
7b70f530bSAdrian Chadd * Redistribution and use in source and binary forms, with or without
8b70f530bSAdrian Chadd * modification, are permitted provided that the following conditions
9b70f530bSAdrian Chadd * are met:
10b70f530bSAdrian Chadd * 1. Redistributions of source code must retain the above copyright
11b70f530bSAdrian Chadd * notice, this list of conditions and the following disclaimer,
12b70f530bSAdrian Chadd * without modification.
13b70f530bSAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14b70f530bSAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15b70f530bSAdrian Chadd * redistribution must be conditioned upon including a substantially
16b70f530bSAdrian Chadd * similar Disclaimer requirement for further binary redistribution.
17b70f530bSAdrian Chadd *
18b70f530bSAdrian Chadd * NO WARRANTY
19b70f530bSAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20b70f530bSAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21b70f530bSAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22b70f530bSAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23b70f530bSAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24b70f530bSAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b70f530bSAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b70f530bSAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27b70f530bSAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b70f530bSAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29b70f530bSAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES.
30b70f530bSAdrian Chadd */
31b70f530bSAdrian Chadd #include <sys/cdefs.h>
32b70f530bSAdrian Chadd /*
33b70f530bSAdrian Chadd * This implements some very basic bluetooth coexistence methods for
34b70f530bSAdrian Chadd * the ath(4) hardware.
35b70f530bSAdrian Chadd */
36b70f530bSAdrian Chadd #include "opt_ath.h"
37b70f530bSAdrian Chadd #include "opt_inet.h"
38b70f530bSAdrian Chadd #include "opt_wlan.h"
39b70f530bSAdrian Chadd
40b70f530bSAdrian Chadd #include <sys/param.h>
41b70f530bSAdrian Chadd #include <sys/systm.h>
42b70f530bSAdrian Chadd #include <sys/sysctl.h>
43b70f530bSAdrian Chadd #include <sys/kernel.h>
44b70f530bSAdrian Chadd #include <sys/lock.h>
4576039bc8SGleb Smirnoff #include <sys/malloc.h>
46b70f530bSAdrian Chadd #include <sys/mutex.h>
47b70f530bSAdrian Chadd #include <sys/errno.h>
48b70f530bSAdrian Chadd #include <machine/bus.h>
49b70f530bSAdrian Chadd #include <machine/resource.h>
50bcf5fc49SAdrian Chadd
51b70f530bSAdrian Chadd #include <sys/bus.h>
52b70f530bSAdrian Chadd
53b70f530bSAdrian Chadd #include <sys/socket.h>
54b70f530bSAdrian Chadd
55b70f530bSAdrian Chadd #include <net/if.h>
5676039bc8SGleb Smirnoff #include <net/if_var.h>
57b70f530bSAdrian Chadd #include <net/if_media.h>
58b70f530bSAdrian Chadd #include <net/if_arp.h>
59b70f530bSAdrian Chadd #include <net/ethernet.h> /* XXX for ether_sprintf */
60b70f530bSAdrian Chadd
61b70f530bSAdrian Chadd #include <net80211/ieee80211_var.h>
62b70f530bSAdrian Chadd
63b70f530bSAdrian Chadd #include <net/bpf.h>
64b70f530bSAdrian Chadd
65b70f530bSAdrian Chadd #ifdef INET
66b70f530bSAdrian Chadd #include <netinet/in.h>
67b70f530bSAdrian Chadd #include <netinet/if_ether.h>
68b70f530bSAdrian Chadd #endif
69b70f530bSAdrian Chadd
70b70f530bSAdrian Chadd #include <dev/ath/if_athvar.h>
71b70f530bSAdrian Chadd #include <dev/ath/if_ath_btcoex.h>
72bcf5fc49SAdrian Chadd #include <dev/ath/if_ath_btcoex_mci.h>
73bcf5fc49SAdrian Chadd
74bcf5fc49SAdrian Chadd MALLOC_DECLARE(M_ATHDEV);
75b70f530bSAdrian Chadd
76b70f530bSAdrian Chadd /*
77b70f530bSAdrian Chadd * Initial AR9285 / (WB195) bluetooth coexistence settings,
78b70f530bSAdrian Chadd * just for experimentation.
79b70f530bSAdrian Chadd *
80b70f530bSAdrian Chadd * Return 0 for OK; errno for error.
81b70f530bSAdrian Chadd *
82b70f530bSAdrian Chadd * XXX TODO: There needs to be a PCIe workaround to disable ASPM if
83b70f530bSAdrian Chadd * bluetooth coexistence is enabled.
84b70f530bSAdrian Chadd */
85b70f530bSAdrian Chadd static int
ath_btcoex_cfg_wb195(struct ath_softc * sc)86b70f530bSAdrian Chadd ath_btcoex_cfg_wb195(struct ath_softc *sc)
87b70f530bSAdrian Chadd {
88b70f530bSAdrian Chadd HAL_BT_COEX_INFO btinfo;
89b70f530bSAdrian Chadd HAL_BT_COEX_CONFIG btconfig;
90b70f530bSAdrian Chadd struct ath_hal *ah = sc->sc_ah;
91b70f530bSAdrian Chadd
92b70f530bSAdrian Chadd if (! ath_hal_btcoex_supported(ah))
93b70f530bSAdrian Chadd return (EINVAL);
94b70f530bSAdrian Chadd
95b70f530bSAdrian Chadd bzero(&btinfo, sizeof(btinfo));
96b70f530bSAdrian Chadd bzero(&btconfig, sizeof(btconfig));
97b70f530bSAdrian Chadd
98b70f530bSAdrian Chadd device_printf(sc->sc_dev, "Enabling WB195 BTCOEX\n");
99b70f530bSAdrian Chadd
100b70f530bSAdrian Chadd btinfo.bt_module = HAL_BT_MODULE_JANUS;
101b70f530bSAdrian Chadd btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE;
102b70f530bSAdrian Chadd /*
103b70f530bSAdrian Chadd * These are the three GPIO pins hooked up between the AR9285 and
104b70f530bSAdrian Chadd * the AR3011.
105b70f530bSAdrian Chadd */
106b70f530bSAdrian Chadd btinfo.bt_gpio_bt_active = 6;
107b70f530bSAdrian Chadd btinfo.bt_gpio_bt_priority = 7;
108b70f530bSAdrian Chadd btinfo.bt_gpio_wlan_active = 5;
109b70f530bSAdrian Chadd btinfo.bt_active_polarity = 1; /* XXX not used */
110b70f530bSAdrian Chadd btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */
111b70f530bSAdrian Chadd btinfo.bt_isolation = 0; /* in dB, not used */
112b70f530bSAdrian Chadd
113b70f530bSAdrian Chadd ath_hal_btcoex_set_info(ah, &btinfo);
114b70f530bSAdrian Chadd
115b70f530bSAdrian Chadd btconfig.bt_time_extend = 0;
116b70f530bSAdrian Chadd btconfig.bt_txstate_extend = 1; /* true */
117b70f530bSAdrian Chadd btconfig.bt_txframe_extend = 1; /* true */
118b70f530bSAdrian Chadd btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED;
119b70f530bSAdrian Chadd btconfig.bt_quiet_collision = 1; /* true */
120b70f530bSAdrian Chadd btconfig.bt_rxclear_polarity = 1; /* true */
121b70f530bSAdrian Chadd btconfig.bt_priority_time = 2;
122b70f530bSAdrian Chadd btconfig.bt_first_slot_time = 5;
123b70f530bSAdrian Chadd btconfig.bt_hold_rxclear = 1; /* true */
124b70f530bSAdrian Chadd
125b70f530bSAdrian Chadd ath_hal_btcoex_set_config(ah, &btconfig);
126b70f530bSAdrian Chadd
127b70f530bSAdrian Chadd /*
128b70f530bSAdrian Chadd * Enable antenna diversity.
129b70f530bSAdrian Chadd */
130b70f530bSAdrian Chadd ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1);
131b70f530bSAdrian Chadd
132b70f530bSAdrian Chadd return (0);
133b70f530bSAdrian Chadd }
134b70f530bSAdrian Chadd
1358d6235fbSAdrian Chadd /*
1368d6235fbSAdrian Chadd * Initial AR9485 / (WB225) bluetooth coexistence settings,
1378d6235fbSAdrian Chadd * just for experimentation.
1388d6235fbSAdrian Chadd *
1398d6235fbSAdrian Chadd * Return 0 for OK; errno for error.
1408d6235fbSAdrian Chadd */
1418d6235fbSAdrian Chadd static int
ath_btcoex_cfg_wb225(struct ath_softc * sc)1428d6235fbSAdrian Chadd ath_btcoex_cfg_wb225(struct ath_softc *sc)
1438d6235fbSAdrian Chadd {
1448d6235fbSAdrian Chadd HAL_BT_COEX_INFO btinfo;
1458d6235fbSAdrian Chadd HAL_BT_COEX_CONFIG btconfig;
1468d6235fbSAdrian Chadd struct ath_hal *ah = sc->sc_ah;
1478d6235fbSAdrian Chadd
1488d6235fbSAdrian Chadd if (! ath_hal_btcoex_supported(ah))
1498d6235fbSAdrian Chadd return (EINVAL);
1508d6235fbSAdrian Chadd
1518d6235fbSAdrian Chadd bzero(&btinfo, sizeof(btinfo));
1528d6235fbSAdrian Chadd bzero(&btconfig, sizeof(btconfig));
1538d6235fbSAdrian Chadd
1548d6235fbSAdrian Chadd device_printf(sc->sc_dev, "Enabling WB225 BTCOEX\n");
1558d6235fbSAdrian Chadd
1568d6235fbSAdrian Chadd btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */
1578d6235fbSAdrian Chadd btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE;
1588d6235fbSAdrian Chadd /*
1598d6235fbSAdrian Chadd * These are the three GPIO pins hooked up between the AR9485 and
1608d6235fbSAdrian Chadd * the bluetooth module.
1618d6235fbSAdrian Chadd */
1628d6235fbSAdrian Chadd btinfo.bt_gpio_bt_active = 4;
1638d6235fbSAdrian Chadd btinfo.bt_gpio_bt_priority = 8;
1648d6235fbSAdrian Chadd btinfo.bt_gpio_wlan_active = 5;
1658d6235fbSAdrian Chadd
1668d6235fbSAdrian Chadd btinfo.bt_active_polarity = 1; /* XXX not used */
1678d6235fbSAdrian Chadd btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */
1688d6235fbSAdrian Chadd btinfo.bt_isolation = 0; /* in dB, not used */
1698d6235fbSAdrian Chadd
1708d6235fbSAdrian Chadd ath_hal_btcoex_set_info(ah, &btinfo);
1718d6235fbSAdrian Chadd
1728d6235fbSAdrian Chadd btconfig.bt_time_extend = 0;
1738d6235fbSAdrian Chadd btconfig.bt_txstate_extend = 1; /* true */
1748d6235fbSAdrian Chadd btconfig.bt_txframe_extend = 1; /* true */
1758d6235fbSAdrian Chadd btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED;
1768d6235fbSAdrian Chadd btconfig.bt_quiet_collision = 1; /* true */
1778d6235fbSAdrian Chadd btconfig.bt_rxclear_polarity = 1; /* true */
1788d6235fbSAdrian Chadd btconfig.bt_priority_time = 2;
1798d6235fbSAdrian Chadd btconfig.bt_first_slot_time = 5;
1808d6235fbSAdrian Chadd btconfig.bt_hold_rxclear = 1; /* true */
1818d6235fbSAdrian Chadd
1828d6235fbSAdrian Chadd ath_hal_btcoex_set_config(ah, &btconfig);
1838d6235fbSAdrian Chadd
1848d6235fbSAdrian Chadd /*
1858d6235fbSAdrian Chadd * Enable antenna diversity.
1868d6235fbSAdrian Chadd */
1878d6235fbSAdrian Chadd ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1);
1888d6235fbSAdrian Chadd
1898d6235fbSAdrian Chadd return (0);
1908d6235fbSAdrian Chadd }
1918d6235fbSAdrian Chadd
192e21928d3SAdrian Chadd static int
ath_btcoex_cfg_mci(struct ath_softc * sc,uint32_t mci_cfg,int do_btdiv)193bcf5fc49SAdrian Chadd ath_btcoex_cfg_mci(struct ath_softc *sc, uint32_t mci_cfg, int do_btdiv)
194e21928d3SAdrian Chadd {
195e21928d3SAdrian Chadd HAL_BT_COEX_INFO btinfo;
196e21928d3SAdrian Chadd HAL_BT_COEX_CONFIG btconfig;
197e21928d3SAdrian Chadd struct ath_hal *ah = sc->sc_ah;
198e21928d3SAdrian Chadd
199e21928d3SAdrian Chadd if (! ath_hal_btcoex_supported(ah))
200e21928d3SAdrian Chadd return (EINVAL);
201e21928d3SAdrian Chadd
202e21928d3SAdrian Chadd bzero(&btinfo, sizeof(btinfo));
203e21928d3SAdrian Chadd bzero(&btconfig, sizeof(btconfig));
204e21928d3SAdrian Chadd
205bcf5fc49SAdrian Chadd sc->sc_ah->ah_config.ath_hal_mci_config = mci_cfg;
206e21928d3SAdrian Chadd
207bcf5fc49SAdrian Chadd if (ath_btcoex_mci_attach(sc) != 0) {
208bcf5fc49SAdrian Chadd device_printf(sc->sc_dev, "Failed to setup btcoex\n");
209bcf5fc49SAdrian Chadd return (EINVAL);
210e21928d3SAdrian Chadd }
211e21928d3SAdrian Chadd
21238c4fdf4SAdrian Chadd btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */
21338c4fdf4SAdrian Chadd btinfo.bt_coex_config = HAL_BT_COEX_CFG_MCI;
21438c4fdf4SAdrian Chadd
21538c4fdf4SAdrian Chadd /*
21638c4fdf4SAdrian Chadd * MCI uses a completely different interface to speak
21738c4fdf4SAdrian Chadd * to the bluetooth module - it's a command based
21838c4fdf4SAdrian Chadd * thing over a serial line, rather than
21938c4fdf4SAdrian Chadd * state pins to/from the bluetooth module.
22038c4fdf4SAdrian Chadd *
22138c4fdf4SAdrian Chadd * So, the GPIO configuration, polarity, etc
22238c4fdf4SAdrian Chadd * doesn't matter on MCI devices; it's just
22338c4fdf4SAdrian Chadd * completely ignored by the HAL.
22438c4fdf4SAdrian Chadd */
22538c4fdf4SAdrian Chadd btinfo.bt_gpio_bt_active = 4;
22638c4fdf4SAdrian Chadd btinfo.bt_gpio_bt_priority = 8;
22738c4fdf4SAdrian Chadd btinfo.bt_gpio_wlan_active = 5;
22838c4fdf4SAdrian Chadd
22938c4fdf4SAdrian Chadd btinfo.bt_active_polarity = 1; /* XXX not used */
23038c4fdf4SAdrian Chadd btinfo.bt_single_ant = 0; /* 2 antenna on WB335 */
23138c4fdf4SAdrian Chadd btinfo.bt_isolation = 0; /* in dB, not used */
23238c4fdf4SAdrian Chadd
23338c4fdf4SAdrian Chadd ath_hal_btcoex_set_info(ah, &btinfo);
23438c4fdf4SAdrian Chadd
23538c4fdf4SAdrian Chadd btconfig.bt_time_extend = 0;
23638c4fdf4SAdrian Chadd btconfig.bt_txstate_extend = 1; /* true */
23738c4fdf4SAdrian Chadd btconfig.bt_txframe_extend = 1; /* true */
23838c4fdf4SAdrian Chadd btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED;
23938c4fdf4SAdrian Chadd btconfig.bt_quiet_collision = 1; /* true */
24038c4fdf4SAdrian Chadd btconfig.bt_rxclear_polarity = 1; /* true */
24138c4fdf4SAdrian Chadd btconfig.bt_priority_time = 2;
24238c4fdf4SAdrian Chadd btconfig.bt_first_slot_time = 5;
24338c4fdf4SAdrian Chadd btconfig.bt_hold_rxclear = 1; /* true */
24438c4fdf4SAdrian Chadd
24538c4fdf4SAdrian Chadd ath_hal_btcoex_set_config(ah, &btconfig);
24638c4fdf4SAdrian Chadd
247bcf5fc49SAdrian Chadd /* Enable */
248bcf5fc49SAdrian Chadd ath_hal_btcoex_enable(sc->sc_ah);
249bcf5fc49SAdrian Chadd
250bcf5fc49SAdrian Chadd /* Stomp */
251bcf5fc49SAdrian Chadd ath_hal_btcoex_set_weights(ah, HAL_BT_COEX_STOMP_NONE);
252bcf5fc49SAdrian Chadd
25338c4fdf4SAdrian Chadd /*
25438c4fdf4SAdrian Chadd * Enable antenna diversity.
25538c4fdf4SAdrian Chadd */
256bcf5fc49SAdrian Chadd ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY,
257bcf5fc49SAdrian Chadd do_btdiv);
25838c4fdf4SAdrian Chadd
25938c4fdf4SAdrian Chadd return (0);
26038c4fdf4SAdrian Chadd }
261e21928d3SAdrian Chadd
262bcf5fc49SAdrian Chadd /*
263bcf5fc49SAdrian Chadd * Initial AR9462 / (WB222) bluetooth coexistence settings.
264bcf5fc49SAdrian Chadd *
265bcf5fc49SAdrian Chadd * Return 0 for OK; errno for error.
266bcf5fc49SAdrian Chadd */
267bcf5fc49SAdrian Chadd static int
ath_btcoex_cfg_wb222(struct ath_softc * sc)268bcf5fc49SAdrian Chadd ath_btcoex_cfg_wb222(struct ath_softc *sc)
269bcf5fc49SAdrian Chadd {
270bcf5fc49SAdrian Chadd
271bcf5fc49SAdrian Chadd device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n");
272bcf5fc49SAdrian Chadd /* XXX from ath9k */
273bcf5fc49SAdrian Chadd return (ath_btcoex_cfg_mci(sc, 0x2201, 1));
274bcf5fc49SAdrian Chadd }
275bcf5fc49SAdrian Chadd
276bcf5fc49SAdrian Chadd /*
277bcf5fc49SAdrian Chadd * Initial QCA9565 / (WB335B) bluetooth coexistence settings.
278bcf5fc49SAdrian Chadd *
279bcf5fc49SAdrian Chadd * Return 0 for OK; errno for error.
280bcf5fc49SAdrian Chadd */
281bcf5fc49SAdrian Chadd static int
ath_btcoex_cfg_wb335b(struct ath_softc * sc)282bcf5fc49SAdrian Chadd ath_btcoex_cfg_wb335b(struct ath_softc *sc)
283bcf5fc49SAdrian Chadd {
284bcf5fc49SAdrian Chadd uint32_t flags;
285bcf5fc49SAdrian Chadd int do_btdiv = 0;
286bcf5fc49SAdrian Chadd
287bcf5fc49SAdrian Chadd /* ath9k default */
288bcf5fc49SAdrian Chadd flags = 0xa4c1;
289bcf5fc49SAdrian Chadd
290bcf5fc49SAdrian Chadd /* 1-ant and 2-ant AR9565 */
291bcf5fc49SAdrian Chadd /*
292bcf5fc49SAdrian Chadd * XXX TODO: ensure these actually make it down to the
293bcf5fc49SAdrian Chadd * HAL correctly!
294bcf5fc49SAdrian Chadd */
295bcf5fc49SAdrian Chadd if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT) {
296b28e96d6SAdrian Chadd flags &= ~ATH_MCI_CONFIG_ANT_ARCH;
297b28e96d6SAdrian Chadd flags |= ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED <<
298b28e96d6SAdrian Chadd ATH_MCI_CONFIG_ANT_ARCH_S;
299bcf5fc49SAdrian Chadd } else if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT) {
300b28e96d6SAdrian Chadd flags &= ~ATH_MCI_CONFIG_ANT_ARCH;
301b28e96d6SAdrian Chadd flags |= ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_NON_SHARED <<
302b28e96d6SAdrian Chadd ATH_MCI_CONFIG_ANT_ARCH_S;
303bcf5fc49SAdrian Chadd }
304bcf5fc49SAdrian Chadd
305bcf5fc49SAdrian Chadd if (sc->sc_pci_devinfo & ATH_PCI_BT_ANT_DIV) {
306bcf5fc49SAdrian Chadd do_btdiv = 1;
307bcf5fc49SAdrian Chadd }
308bcf5fc49SAdrian Chadd
309bcf5fc49SAdrian Chadd device_printf(sc->sc_dev, "Enabling WB335 BTCOEX\n");
310bcf5fc49SAdrian Chadd /* XXX from ath9k */
311bcf5fc49SAdrian Chadd return (ath_btcoex_cfg_mci(sc, flags, do_btdiv));
312bcf5fc49SAdrian Chadd }
3138d6235fbSAdrian Chadd
314b70f530bSAdrian Chadd #if 0
315b70f530bSAdrian Chadd /*
316b70f530bSAdrian Chadd * When using bluetooth coexistence, ASPM needs to be disabled
317b70f530bSAdrian Chadd * otherwise the sleeping interferes with the bluetooth (USB)
318b70f530bSAdrian Chadd * operation and the MAC sleep/wakeup hardware.
319b6745945SAdrian Chadd *
320b6745945SAdrian Chadd * The PCIe powersave routine also needs to not be called
321b6745945SAdrian Chadd * by the driver during suspend/resume, else things will get
322b6745945SAdrian Chadd * a little odd. Check Linux ath9k for more details.
323b70f530bSAdrian Chadd */
324b70f530bSAdrian Chadd static int
325b70f530bSAdrian Chadd ath_btcoex_aspm_wb195(struct ath_softc *sc)
326b70f530bSAdrian Chadd {
327b70f530bSAdrian Chadd
328b70f530bSAdrian Chadd /* XXX TODO: clear device ASPM L0S and L1 */
329b70f530bSAdrian Chadd /* XXX TODO: clear _parent_ ASPM L0S and L1 */
330b70f530bSAdrian Chadd }
331b70f530bSAdrian Chadd #endif
332b70f530bSAdrian Chadd
333b70f530bSAdrian Chadd /*
334b70f530bSAdrian Chadd * Methods which are required
335b70f530bSAdrian Chadd */
336b70f530bSAdrian Chadd
337b70f530bSAdrian Chadd /*
338b70f530bSAdrian Chadd * Attach btcoex to the given interface
339b70f530bSAdrian Chadd */
340b70f530bSAdrian Chadd int
ath_btcoex_attach(struct ath_softc * sc)341b70f530bSAdrian Chadd ath_btcoex_attach(struct ath_softc *sc)
342b70f530bSAdrian Chadd {
343b70f530bSAdrian Chadd int ret;
344b70f530bSAdrian Chadd struct ath_hal *ah = sc->sc_ah;
345b70f530bSAdrian Chadd const char *profname;
346b70f530bSAdrian Chadd
347b70f530bSAdrian Chadd /*
348b70f530bSAdrian Chadd * No chipset bluetooth coexistence? Then do nothing.
349b70f530bSAdrian Chadd */
350b70f530bSAdrian Chadd if (! ath_hal_btcoex_supported(ah))
351b70f530bSAdrian Chadd return (0);
352b70f530bSAdrian Chadd
353b70f530bSAdrian Chadd /*
354b70f530bSAdrian Chadd * Look at the hints to determine which bluetooth
355b70f530bSAdrian Chadd * profile to configure.
356b70f530bSAdrian Chadd */
357b70f530bSAdrian Chadd ret = resource_string_value(device_get_name(sc->sc_dev),
358b70f530bSAdrian Chadd device_get_unit(sc->sc_dev),
359b70f530bSAdrian Chadd "btcoex_profile",
360b70f530bSAdrian Chadd &profname);
361b70f530bSAdrian Chadd if (ret != 0) {
362b70f530bSAdrian Chadd /* nothing to do */
363b70f530bSAdrian Chadd return (0);
364b70f530bSAdrian Chadd }
365b70f530bSAdrian Chadd
366b70f530bSAdrian Chadd if (strncmp(profname, "wb195", 5) == 0) {
367b70f530bSAdrian Chadd ret = ath_btcoex_cfg_wb195(sc);
368e21928d3SAdrian Chadd } else if (strncmp(profname, "wb222", 5) == 0) {
369e21928d3SAdrian Chadd ret = ath_btcoex_cfg_wb222(sc);
3708d6235fbSAdrian Chadd } else if (strncmp(profname, "wb225", 5) == 0) {
3718d6235fbSAdrian Chadd ret = ath_btcoex_cfg_wb225(sc);
37238c4fdf4SAdrian Chadd } else if (strncmp(profname, "wb335", 5) == 0) {
37338c4fdf4SAdrian Chadd ret = ath_btcoex_cfg_wb335b(sc);
374b70f530bSAdrian Chadd } else {
375b70f530bSAdrian Chadd return (0);
376b70f530bSAdrian Chadd }
377b70f530bSAdrian Chadd
378b70f530bSAdrian Chadd /*
379b70f530bSAdrian Chadd * Propagate up failure from the actual attach phase.
380b70f530bSAdrian Chadd */
381b70f530bSAdrian Chadd if (ret != 0)
382b70f530bSAdrian Chadd return (ret);
383b70f530bSAdrian Chadd
384b70f530bSAdrian Chadd return (0);
385b70f530bSAdrian Chadd }
386b70f530bSAdrian Chadd
387b70f530bSAdrian Chadd /*
388b70f530bSAdrian Chadd * Detach btcoex from the given interface
389b70f530bSAdrian Chadd */
390b70f530bSAdrian Chadd int
ath_btcoex_detach(struct ath_softc * sc)391b70f530bSAdrian Chadd ath_btcoex_detach(struct ath_softc *sc)
392b70f530bSAdrian Chadd {
393bcf5fc49SAdrian Chadd if (sc->sc_btcoex_mci) {
394bcf5fc49SAdrian Chadd ath_btcoex_mci_detach(sc);
395bcf5fc49SAdrian Chadd }
396b70f530bSAdrian Chadd
397b70f530bSAdrian Chadd return (0);
398b70f530bSAdrian Chadd }
399b70f530bSAdrian Chadd
400b70f530bSAdrian Chadd /*
401b70f530bSAdrian Chadd * Configure or disable bluetooth coexistence on the given channel.
402b70f530bSAdrian Chadd *
403b70f530bSAdrian Chadd * For AR9285/AR9287/AR9485, we'll never see a 5GHz channel, so we just
404b70f530bSAdrian Chadd * assume bluetooth coexistence is always on.
405b70f530bSAdrian Chadd *
406b70f530bSAdrian Chadd * For AR9462, we may see a 5GHz channel; bluetooth coexistence should
407b70f530bSAdrian Chadd * not be enabled on those channels.
408b70f530bSAdrian Chadd */
409b70f530bSAdrian Chadd int
ath_btcoex_enable(struct ath_softc * sc,const struct ieee80211_channel * chan)410b70f530bSAdrian Chadd ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan)
411b70f530bSAdrian Chadd {
412bcf5fc49SAdrian Chadd if (sc->sc_btcoex_mci) {
413bcf5fc49SAdrian Chadd ath_btcoex_mci_enable(sc, chan);
414bcf5fc49SAdrian Chadd }
415b70f530bSAdrian Chadd
416b70f530bSAdrian Chadd return (0);
417b70f530bSAdrian Chadd }
418b70f530bSAdrian Chadd
419b70f530bSAdrian Chadd /*
420b70f530bSAdrian Chadd * Handle ioctl requests from the diagnostic interface.
421b70f530bSAdrian Chadd *
422b70f530bSAdrian Chadd * The initial part of this code resembles ath_ioctl_diag();
423b70f530bSAdrian Chadd * it's likely a good idea to reduce duplication between
424b70f530bSAdrian Chadd * these two routines.
425b70f530bSAdrian Chadd */
426b70f530bSAdrian Chadd int
ath_btcoex_ioctl(struct ath_softc * sc,struct ath_diag * ad)427b70f530bSAdrian Chadd ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad)
428b70f530bSAdrian Chadd {
429b70f530bSAdrian Chadd unsigned int id = ad->ad_id & ATH_DIAG_ID;
430b70f530bSAdrian Chadd void *indata = NULL;
431b70f530bSAdrian Chadd void *outdata = NULL;
432b70f530bSAdrian Chadd u_int32_t insize = ad->ad_in_size;
433b70f530bSAdrian Chadd u_int32_t outsize = ad->ad_out_size;
434b70f530bSAdrian Chadd int error = 0;
435b70f530bSAdrian Chadd // int val;
436b70f530bSAdrian Chadd
437b70f530bSAdrian Chadd if (ad->ad_id & ATH_DIAG_IN) {
438b70f530bSAdrian Chadd /*
439b70f530bSAdrian Chadd * Copy in data.
440b70f530bSAdrian Chadd */
441b70f530bSAdrian Chadd indata = malloc(insize, M_TEMP, M_NOWAIT);
442b70f530bSAdrian Chadd if (indata == NULL) {
443b70f530bSAdrian Chadd error = ENOMEM;
444b70f530bSAdrian Chadd goto bad;
445b70f530bSAdrian Chadd }
446b70f530bSAdrian Chadd error = copyin(ad->ad_in_data, indata, insize);
447b70f530bSAdrian Chadd if (error)
448b70f530bSAdrian Chadd goto bad;
449b70f530bSAdrian Chadd }
450b70f530bSAdrian Chadd if (ad->ad_id & ATH_DIAG_DYN) {
451b70f530bSAdrian Chadd /*
452b70f530bSAdrian Chadd * Allocate a buffer for the results (otherwise the HAL
453b70f530bSAdrian Chadd * returns a pointer to a buffer where we can read the
454b70f530bSAdrian Chadd * results). Note that we depend on the HAL leaving this
455b70f530bSAdrian Chadd * pointer for us to use below in reclaiming the buffer;
456b70f530bSAdrian Chadd * may want to be more defensive.
457b70f530bSAdrian Chadd */
45885f385b9SEd Maste outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO);
459b70f530bSAdrian Chadd if (outdata == NULL) {
460b70f530bSAdrian Chadd error = ENOMEM;
461b70f530bSAdrian Chadd goto bad;
462b70f530bSAdrian Chadd }
463b70f530bSAdrian Chadd }
464b70f530bSAdrian Chadd switch (id) {
465b70f530bSAdrian Chadd default:
466b70f530bSAdrian Chadd error = EINVAL;
46785f385b9SEd Maste goto bad;
468b70f530bSAdrian Chadd }
469b70f530bSAdrian Chadd if (outsize < ad->ad_out_size)
470b70f530bSAdrian Chadd ad->ad_out_size = outsize;
471b70f530bSAdrian Chadd if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
472b70f530bSAdrian Chadd error = EFAULT;
473b70f530bSAdrian Chadd bad:
474b70f530bSAdrian Chadd if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
475b70f530bSAdrian Chadd free(indata, M_TEMP);
476b70f530bSAdrian Chadd if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
477b70f530bSAdrian Chadd free(outdata, M_TEMP);
478b70f530bSAdrian Chadd return (error);
479b70f530bSAdrian Chadd }
480