git: 902136e0fe11 - main - brcm80211: add LinuxKPI files and module Makefiles

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Tue, 10 Feb 2026 21:54:30 UTC
The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=902136e0fe112383ec64d2ef43a446063b5e6417

commit 902136e0fe112383ec64d2ef43a446063b5e6417
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-02-10 21:33:09 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-02-10 21:36:29 +0000

    brcm80211: add LinuxKPI files and module Makefiles
    
    sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h
    is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    e5f0a698b34ed76002dc5cff3804a61c80233a7a ( tag: v6.17 ).
    
    Currently only PCIe is made to compile.
    It does load firmware (if needed, e.g., on arm64 with an alignment
    issue fixed), and starts to come up.
    
    To make it work there is a cfg80211 layer and netdevice integration
    to do, so do not hold your breath just yet.
---
 .../linuxkpi/common/include/linux/bcm47xx_nvram.h  |  21 +++
 .../linuxkpi/common/include/linux/bcma/bcma.h      |  29 ++++
 .../linuxkpi/common/include/linux/bcma/bcma_regs.h |  17 ++
 .../common/include/linux/platform_data/brcmfmac.h  | 185 ++++++++++++++++++++
 .../linuxkpi/common/include/linux/ssb/ssb_regs.h   |  25 +++
 .../dev/broadcom/brcm80211/brcmfmac/cfg80211.c     | 190 +++++++++++++++++++++
 .../dev/broadcom/brcm80211/brcmfmac/common.c       |  35 ++++
 .../dev/broadcom/brcm80211/brcmfmac/commonring.c   |  15 ++
 .../dev/broadcom/brcm80211/brcmfmac/debug.c        |   8 +
 .../dev/broadcom/brcm80211/brcmfmac/debug.h        |  24 +++
 .../dev/broadcom/brcm80211/brcmfmac/firmware.c     |  24 +++
 .../dev/broadcom/brcm80211/brcmfmac/flowring.c     |  24 +++
 .../dev/broadcom/brcm80211/brcmfmac/flowring.h     |   8 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fwil.c |   8 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fwil.h |   4 +
 .../dev/broadcom/brcm80211/brcmfmac/fwvid.c        |  18 ++
 .../dev/broadcom/brcm80211/brcmfmac/msgbuf.c       |  34 ++++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/p2p.c  |  23 +++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pcie.c | 117 +++++++++++++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pno.c  |  21 +++
 .../dev/broadcom/brcm80211/brcmfmac/proto.h        |  16 ++
 .../dev/broadcom/brcm80211/brcmfmac/tracepoint.h   |  18 ++
 .../dev/broadcom/brcm80211/brcmfmac/vendor.c       |   9 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/xtlv.c |   4 +
 .../dev/broadcom/brcm80211/brcmutil/utils.c        |   9 +
 sys/modules/brcm80211/Makefile                     |   4 +
 sys/modules/brcm80211/brcmfmac/Makefile            |  89 ++++++++++
 sys/modules/brcm80211/brcmutil/Makefile            |  28 +++
 28 files changed, 1007 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h b/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h
new file mode 100644
index 000000000000..744101a2f8b1
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef	_LINUXKPI_LINUX_BCM47XX_NVRAM_H
+#define	_LINUXKPI_LINUX_BCM47XX_NVRAM_H
+
+static inline char *
+bcm47xx_nvram_get_contents(size_t *x __unused)
+{
+	return (NULL);
+};
+
+static inline void
+bcm47xx_nvram_release_contents(const char *x __unused)
+{
+};
+
+#endif	/* _LINUXKPI_LINUX_BCM47XX_NVRAM_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h b/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h
new file mode 100644
index 000000000000..3840c3a420e5
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef	_LINUXKPI_LINUX_BCMA_BCMA_H
+#define	_LINUXKPI_LINUX_BCMA_BCMA_H
+
+#define	BCMA_CORE_80211			0x812
+#define	BCMA_CORE_ARM_CA7		0x847
+#define	BCMA_CORE_ARM_CM3		0x82A
+#define	BCMA_CORE_ARM_CR4		0x83E
+#define	BCMA_CORE_CHIPCOMMON		0x800
+#define	BCMA_CORE_GCI			0x840
+#define	BCMA_CORE_INTERNAL_MEM		0x80E
+#define	BCMA_CORE_PCIE2			0x83C
+#define	BCMA_CORE_PMU			0x827
+#define	BCMA_CORE_SDIO_DEV		0x829
+#define	BCMA_CORE_SYS_MEM		0x849
+
+/* XXX not sure where these belong. */
+#define	BCMA_CC_CAP_EXT_AOB_PRESENT	0x00000040
+#define	BCMA_CC_PMU_CTL_RES_SHIFT	13
+#define	BCMA_CC_PMU_CTL_RES_RELOAD	0x2
+#define	BCMA_CC_SROM_CONTROL_OTPSEL	0x00000010
+#define	BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
+
+#endif	/* _LINUXKPI_LINUX_BCMA_BCMA_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h b/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h
new file mode 100644
index 000000000000..0a4cdddf7a73
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef	_LINUXKPI_LINUX_BCMA_BCMA_REGS_H
+#define	_LINUXKPI_LINUX_BCMA_BCMA_REGS_H
+
+#define	BCMA_IOCTL			0x0408
+#define	BCMA_IOCTL_CLK			0x0001
+#define	BCMA_IOCTL_FGC			0x0002
+
+#define	BCMA_RESET_CTL			0x0800
+#define	BCMA_RESET_CTL_RESET		0x0001
+
+#endif	/* _LINUXKPI_LINUX_BCMA_BCMA_REGS_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h b/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h
new file mode 100644
index 000000000000..ec99b7b73d1d
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_BRCMFMAC_PLATFORM_H
+#define _LINUX_BRCMFMAC_PLATFORM_H
+
+
+#define BRCMFMAC_PDATA_NAME		"brcmfmac"
+
+#define BRCMFMAC_COUNTRY_BUF_SZ		4
+
+
+/*
+ * Platform specific driver functions and data. Through the platform specific
+ * device data functions and data can be provided to help the brcmfmac driver to
+ * operate with the device in combination with the used platform.
+ */
+
+
+/**
+ * Note: the brcmfmac can be loaded as module or be statically built-in into
+ * the kernel. If built-in then do note that it uses module_init (and
+ * module_exit) routines which equal device_initcall. So if you intend to
+ * create a module with the platform specific data for the brcmfmac and have
+ * it built-in to the kernel then use a higher initcall then device_initcall
+ * (see init.h). If this is not done then brcmfmac will load without problems
+ * but will not pickup the platform data.
+ *
+ * When the driver does not "detect" platform driver data then it will continue
+ * without reporting anything and just assume there is no data needed. Which is
+ * probably true for most platforms.
+ */
+
+/**
+ * enum brcmf_bus_type - Bus type identifier. Currently SDIO, USB and PCIE are
+ *			 supported.
+ */
+enum brcmf_bus_type {
+	BRCMF_BUSTYPE_SDIO,
+	BRCMF_BUSTYPE_USB,
+	BRCMF_BUSTYPE_PCIE
+};
+
+
+/**
+ * struct brcmfmac_sdio_pd - SDIO Device specific platform data.
+ *
+ * @txglomsz:		SDIO txglom size. Use 0 if default of driver is to be
+ *			used.
+ * @drive_strength:	is the preferred drive_strength to be used for the SDIO
+ *			pins. If 0 then a default value will be used. This is
+ *			the target drive strength, the exact drive strength
+ *			which will be used depends on the capabilities of the
+ *			device.
+ * @oob_irq_supported:	does the board have support for OOB interrupts. SDIO
+ *			in-band interrupts are relatively slow and for having
+ *			less overhead on interrupt processing an out of band
+ *			interrupt can be used. If the HW supports this then
+ *			enable this by setting this field to true and configure
+ *			the oob related fields.
+ * @oob_irq_nr,
+ * @oob_irq_flags:	the OOB interrupt information. The values are used for
+ *			registering the irq using request_irq function.
+ * @broken_sg_support:	flag for broken sg list support of SDIO host controller.
+ *			Set this to true if the SDIO host controller has higher
+ *			align requirement than 32 bytes for each scatterlist
+ *			item.
+ * @sd_head_align:	alignment requirement for start of data buffer.
+ * @sd_sgentry_align:	length alignment requirement for each sg entry.
+ * @reset:		This function can get called if the device communication
+ *			broke down. This functionality is particularly useful in
+ *			case of SDIO type devices. It is possible to reset a
+ *			dongle via sdio data interface, but it requires that
+ *			this is fully functional. This function is chip/module
+ *			specific and this function should return only after the
+ *			complete reset has completed.
+ */
+struct brcmfmac_sdio_pd {
+	int		txglomsz;
+	unsigned int	drive_strength;
+	bool		oob_irq_supported;
+	unsigned int	oob_irq_nr;
+	unsigned long	oob_irq_flags;
+	bool		broken_sg_support;
+	unsigned short	sd_head_align;
+	unsigned short	sd_sgentry_align;
+	void		(*reset)(void);
+};
+
+/**
+ * struct brcmfmac_pd_cc_entry - Struct for translating user space country code
+ *				 (iso3166) to firmware country code and
+ *				 revision.
+ *
+ * @iso3166:	iso3166 alpha 2 country code string.
+ * @cc:		firmware country code string.
+ * @rev:	firmware country code revision.
+ */
+struct brcmfmac_pd_cc_entry {
+	char	iso3166[BRCMFMAC_COUNTRY_BUF_SZ];
+	char	cc[BRCMFMAC_COUNTRY_BUF_SZ];
+	s32	rev;
+};
+
+/**
+ * struct brcmfmac_pd_cc - Struct for translating country codes as set by user
+ *			   space to a country code and rev which can be used by
+ *			   firmware.
+ *
+ * @table_size:	number of entries in table (> 0)
+ * @table:	array of 1 or more elements with translation information.
+ */
+struct brcmfmac_pd_cc {
+	int				table_size;
+	struct brcmfmac_pd_cc_entry	table[];
+};
+
+/**
+ * struct brcmfmac_pd_device - Device specific platform data. (id/rev/bus_type)
+ *			       is the unique identifier of the device.
+ *
+ * @id:			ID of the device for which this data is. In case of SDIO
+ *			or PCIE this is the chipid as identified by chip.c In
+ *			case of USB this is the chipid as identified by the
+ *			device query.
+ * @rev:		chip revision, see id.
+ * @bus_type:		The type of bus. Some chipid/rev exist for different bus
+ *			types. Each bus type has its own set of settings.
+ * @feature_disable:	Bitmask of features to disable (override), See feature.c
+ *			in brcmfmac for details.
+ * @country_codes:	If available, pointer to struct for translating country
+ *			codes.
+ * @bus:		Bus specific (union) device settings. Currently only
+ *			SDIO.
+ */
+struct brcmfmac_pd_device {
+	unsigned int		id;
+	unsigned int		rev;
+	enum brcmf_bus_type	bus_type;
+	unsigned int		feature_disable;
+	struct brcmfmac_pd_cc	*country_codes;
+	union {
+		struct brcmfmac_sdio_pd sdio;
+	} bus;
+};
+
+/**
+ * struct brcmfmac_platform_data - BRCMFMAC specific platform data.
+ *
+ * @power_on:	This function is called by the brcmfmac driver when the module
+ *		gets loaded. This can be particularly useful for low power
+ *		devices. The platform spcific routine may for example decide to
+ *		power up the complete device. If there is no use-case for this
+ *		function then provide NULL.
+ * @power_off:	This function is called by the brcmfmac when the module gets
+ *		unloaded. At this point the devices can be powered down or
+ *		otherwise be reset. So if an actual power_off is not supported
+ *		but reset is supported by the devices then reset the devices
+ *		when this function gets called. This can be particularly useful
+ *		for low power devices. If there is no use-case for this
+ *		function then provide NULL.
+ */
+struct brcmfmac_platform_data {
+	void	(*power_on)(void);
+	void	(*power_off)(void);
+	char	*fw_alternative_path;
+	int	device_count;
+	struct brcmfmac_pd_device devices[];
+};
+
+
+#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h b/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h
new file mode 100644
index 000000000000..e1c18b6b632a
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef	_LINUXKPI_LINUX_SSB_SSB_REGS_H
+#define	_LINUXKPI_LINUX_SSB_SSB_REGS_H
+
+#define	SSB_IDHIGH_RCHI		0x00007000
+#define	SSB_IDHIGH_RCHI_SHIFT	8
+#define	SSB_IDHIGH_RCLO		0x0000000F
+#define	SSB_IDLOW_INITIATOR	0x00000080
+#define	SSB_IMSTATE_BUSY	0x01800000
+#define	SSB_IMSTATE_IBE		0x00020000
+#define	SSB_IMSTATE_REJECT	0x02000000
+#define	SSB_IMSTATE_TO		0x00040000
+#define	SSB_TMSHIGH_BUSY	0x00000004
+#define	SSB_TMSHIGH_SERR	0x00000001
+#define	SSB_TMSLOW_CLOCK	0x00010000
+#define	SSB_TMSLOW_FGC		0x00020000
+#define	SSB_TMSLOW_REJECT	0x00000002
+#define	SSB_TMSLOW_RESET	0x00000001
+
+#endif	/* _LINUXKPI_LINUX_SSB_SSB_REGS_H */
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/cfg80211.c b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/cfg80211.c
index 8af402555b5e..35f68b370714 100644
--- a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -5,13 +5,21 @@
 
 /* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
 
+#if defined(__FreeBSD__)
+#include <net/cfg80211.h>
+#endif
 #include <linux/kernel.h>
 #include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#if defined(__linux__)
 #include <net/cfg80211.h>
+#endif
 #include <net/netlink.h>
 #include <uapi/linux/if_arp.h>
+#if defined(__FreeBSD__)
+#include <linux/delay.h>
+#endif
 
 #include <brcmu_utils.h>
 #include <defs.h>
@@ -36,6 +44,24 @@
 
 #define BRCMF_SCAN_IE_LEN_MAX		2048
 
+#if defined(__FreeBSD__)
+#ifdef WPA_OUI
+#undef WPA_OUI
+#endif
+#ifdef WPA_OUI_TYPE
+#undef WPA_OUI_TYPE
+#endif
+#ifdef RSN_OUI
+#undef RSN_OUI
+#endif
+#ifdef WME_OUI_TYPE
+#undef WME_OUI_TYPE
+#endif
+#ifdef WPS_OUI_TYPE
+#undef WPS_OUI_TYPE
+#endif
+#endif
+
 #define WPA_OUI				"\x00\x50\xF2"	/* WPA OUI */
 #define WPA_OUI_TYPE			1
 #define RSN_OUI				"\x00\x0F\xAC"	/* RSN OUI */
@@ -257,7 +283,11 @@ struct brcmf_vs_tlv {
 };
 
 struct parsed_vndr_ie_info {
+#if defined(__linux__)
 	u8 *ie_ptr;
+#elif defined(__FreeBSD__)
+	const u8 *ie_ptr;
+#endif
 	u32 ie_len;	/* total length including id & length field */
 	struct brcmf_vs_tlv vndrie;
 };
@@ -429,7 +459,11 @@ brcmf_parse_tlvs(const void *buf, int buflen, uint key)
 		if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
 			return elt;
 
+#if defined(__linux__)
 		elt = (struct brcmf_tlv *)((u8 *)elt + (len + TLV_HDR_LEN));
+#elif defined(__FreeBSD__)
+		elt = (const struct brcmf_tlv *)((const u8 *)elt + (len + TLV_HDR_LEN));
+#endif
 		totlen -= (len + TLV_HDR_LEN);
 	}
 
@@ -462,7 +496,11 @@ brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
 	return false;
 }
 
+#if defined(__linux__)
 static struct brcmf_vs_tlv *
+#elif defined(__FreeBSD__)
+static const struct brcmf_vs_tlv *
+#endif
 brcmf_find_wpaie(const u8 *parse, u32 len)
 {
 	const struct brcmf_tlv *ie;
@@ -470,20 +508,34 @@ brcmf_find_wpaie(const u8 *parse, u32 len)
 	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
 		if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
 				     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
+#if defined(__linux__)
 			return (struct brcmf_vs_tlv *)ie;
+#elif defined(__FreeBSD__)
+			return (const struct brcmf_vs_tlv *)ie;
+#endif
 	}
 	return NULL;
 }
 
+#if defined(__linux__)
 static struct brcmf_vs_tlv *
+#elif defined(__FreeBSD__)
+static const struct brcmf_vs_tlv *
+#endif
 brcmf_find_wpsie(const u8 *parse, u32 len)
 {
 	const struct brcmf_tlv *ie;
 
 	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
+#if defined(__linux__)
 		if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
 				     WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE))
 			return (struct brcmf_vs_tlv *)ie;
+#elif defined(__FreeBSD__)
+		if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
+				     WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE))
+			return (const struct brcmf_vs_tlv *)ie;
+#endif
 	}
 	return NULL;
 }
@@ -1239,8 +1291,13 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 			reqid = brcmf_pno_find_reqid_by_bucket(cfg->pno,
 							       bucket);
 			if (!aborted) {
+#if defined(__linux__)
 				brcmf_dbg(SCAN, "report results: reqid=%llu\n",
 					  reqid);
+#elif defined(__FreeBSD__)
+				brcmf_dbg(SCAN, "report results: reqid=%ju\n",
+					  (uintmax_t)reqid);
+#endif
 				cfg80211_sched_scan_results(cfg_to_wiphy(cfg),
 							    reqid);
 			}
@@ -2413,7 +2470,11 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 		ie = NULL;
 		ie_len = 0;
 		/* find the WPA_IE */
+#if defined(__linux__)
 		wpa_ie = brcmf_find_wpaie((u8 *)sme->ie, sme->ie_len);
+#elif defined(__FreeBSD__)
+		wpa_ie = brcmf_find_wpaie(sme->ie, sme->ie_len);
+#endif
 		if (wpa_ie) {
 			ie = wpa_ie;
 			ie_len = wpa_ie->len + TLV_HDR_LEN;
@@ -2450,7 +2511,11 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 		chanspec = 0;
 	}
 
+#if defined(__linux__)
 	brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
+#elif defined(__FreeBSD__)
+	brcmf_dbg(INFO, "ie (%p), ie_len (%u)\n", sme->ie, sme->ie_len);
+#endif
 
 	err = brcmf_set_wpa_version(ndev, sme);
 	if (err) {
@@ -2840,7 +2905,11 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 	key = &ifp->vif->profile.key[key_idx];
 	memset(key, 0, sizeof(*key));
 	if ((ext_key) && (!is_multicast_ether_addr(mac_addr)))
+#if defined(__linux__)
 		memcpy((char *)&key->ea, (void *)mac_addr, ETH_ALEN);
+#elif defined(__FreeBSD__)
+		memcpy((char *)&key->ea, mac_addr, ETH_ALEN);
+#endif
 	key->len = params->key_len;
 	key->index = key_idx;
 	memcpy(key->data, params->key, key->len);
@@ -2849,9 +2918,15 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 
 	if (params->seq && params->seq_len == 6) {
 		/* rx iv */
+#if defined(__linux__)
 		u8 *ivptr;
 
 		ivptr = (u8 *)params->seq;
+#elif defined(__FreeBSD__)
+		const u8 *ivptr;
+
+		ivptr = params->seq;
+#endif
 		key->rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
 			(ivptr[3] << 8) | ivptr[2];
 		key->rxiv.lo = (ivptr[1] << 8) | ivptr[0];
@@ -3758,8 +3833,13 @@ brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
 	req = kzalloc(req_size, GFP_KERNEL);
 	if (req) {
 		req->wiphy = wiphy;
+#if defined(__linux__)
 		req->ssids = (void *)(&req->channels[0]) +
 			     n_netinfo * sizeof(req->channels[0]);
+#elif defined(__FreeBSD__)
+		req->ssids = (void *)((&req->channels[0]) +
+			     n_netinfo * sizeof(req->channels[0]));
+#endif
 	}
 	return req;
 }
@@ -3902,7 +3982,11 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
 	}
 
 	netinfo_start = brcmf_get_netinfo_array(pfn_result);
+#if defined(__linux__)
 	datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
+#elif defined(__FreeBSD__)
+	datalen = e->datalen - ((u8 *)netinfo_start - (u8 *)pfn_result);
+#endif
 	if (datalen < result_count * sizeof(*netinfo)) {
 		bphy_err(drvr, "insufficient event data\n");
 		goto out_err;
@@ -3992,7 +4076,11 @@ static __always_inline void brcmf_delay(u32 ms)
 		cond_resched();
 		mdelay(ms);
 	} else {
+#if defined(__linux__)
 		msleep(ms);
+#elif defined(__FreeBSD__)
+		linux_msleep(ms);
+#endif
 	}
 }
 
@@ -4529,7 +4617,11 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
 	return 0;
 }
 
+#if defined(__linux__)
 static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
+#elif defined(__FreeBSD__)
+static bool brcmf_valid_wpa_oui(const u8 *oui, bool is_rsn_ie)
+#endif
 {
 	if (is_rsn_ie)
 		return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
@@ -4553,7 +4645,11 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
 	u32 gval = 0;
 	u32 wpa_auth = 0;
 	u32 offset;
+#if defined(__linux__)
 	u8 *data;
+#elif defined(__FreeBSD__)
+	const u8 *data;
+#endif
 	u16 rsn_cap;
 	u32 wme_bss_disable;
 	u32 mfp;
@@ -4563,7 +4659,11 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
 		goto exit;
 
 	len = wpa_ie->len + TLV_HDR_LEN;
+#if defined(__linux__)
 	data = (u8 *)wpa_ie;
+#elif defined(__FreeBSD__)
+	data = (const u8 *)wpa_ie;
+#endif
 	offset = TLV_HDR_LEN;
 	if (!is_rsn_ie)
 		offset += VS_IE_FIXED_HDR_LEN;
@@ -4786,19 +4886,32 @@ static s32
 brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
 		     struct parsed_vndr_ies *vndr_ies)
 {
+#if defined(__linux__)
 	struct brcmf_vs_tlv *vndrie;
 	struct brcmf_tlv *ie;
+#elif defined(__FreeBSD__)
+	const struct brcmf_vs_tlv *vndrie;
+	const struct brcmf_tlv *ie;
+#endif
 	struct parsed_vndr_ie_info *parsed_info;
 	s32 remaining_len;
 
 	remaining_len = (s32)vndr_ie_len;
 	memset(vndr_ies, 0, sizeof(*vndr_ies));
 
+#if defined(__linux__)
 	ie = (struct brcmf_tlv *)vndr_ie_buf;
+#elif defined(__FreeBSD__)
+	ie = (const struct brcmf_tlv *)vndr_ie_buf;
+#endif
 	while (ie) {
 		if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
 			goto next;
+#if defined(__linux__)
 		vndrie = (struct brcmf_vs_tlv *)ie;
+#elif defined(__FreeBSD__)
+		vndrie = (const struct brcmf_vs_tlv *)ie;
+#endif
 		/* len should be bigger than OUI length + one */
 		if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
 			brcmf_err("invalid vndr ie. length is too small %d\n",
@@ -4816,7 +4929,11 @@ brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
 		parsed_info = &vndr_ies->ie_info[vndr_ies->count];
 
 		/* save vndr ie information */
+#if defined(__linux__)
 		parsed_info->ie_ptr = (char *)vndrie;
+#elif defined(__FreeBSD__)
+		parsed_info->ie_ptr = (const char *)vndrie;
+#endif
 		parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
 		memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
 
@@ -4833,14 +4950,22 @@ next:
 		if (remaining_len <= TLV_HDR_LEN)
 			ie = NULL;
 		else
+#if defined(__linux__)
 			ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
+#elif defined(__FreeBSD__)
+			ie = (const struct brcmf_tlv *)(((const u8 *)ie) + ie->len +
+#endif
 				TLV_HDR_LEN);
 	}
 	return 0;
 }
 
 static u32
+#if defined(__linux__)
 brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
+#elif defined(__FreeBSD__)
+brcmf_vndr_ie(u8 *iebuf, s32 pktflag, const u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
+#endif
 {
 	strscpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN);
 
@@ -5085,11 +5210,19 @@ brcmf_parse_configure_security(struct brcmf_if *ifp,
 	s32 err = 0;
 
 	/* find the RSN_IE */
+#if defined(__linux__)
 	rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
+#elif defined(__FreeBSD__)
+	rsn_ie = brcmf_parse_tlvs(settings->beacon.tail,
+#endif
 				  settings->beacon.tail_len, WLAN_EID_RSN);
 
 	/* find the WPA_IE */
+#if defined(__linux__)
 	wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
+#elif defined(__FreeBSD__)
+	wpa_ie = brcmf_find_wpaie(settings->beacon.tail,
+#endif
 				  settings->beacon.tail_len);
 
 	if (wpa_ie || rsn_ie) {
@@ -5100,9 +5233,16 @@ brcmf_parse_configure_security(struct brcmf_if *ifp,
 			if (err < 0)
 				return err;
 		} else {
+#if defined(__linux__)
 			struct brcmf_vs_tlv *tmp_ie;
 
 			tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;
+#elif defined(__FreeBSD__)
+			const struct brcmf_vs_tlv *tmp_ie;
+
+			tmp_ie = (const struct brcmf_vs_tlv *)rsn_ie;
+#endif
+
 
 			/* RSN IE */
 			err = brcmf_configure_wpaie(ifp, tmp_ie, true);
@@ -5155,7 +5295,11 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 				  &ifp->vif->is_11d)) {
 		is_11d = supports_11d = false;
 	} else {
+#if defined(__linux__)
 		country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
+#elif defined(__FreeBSD__)
+		country_ie = brcmf_parse_tlvs(settings->beacon.tail,
+#endif
 					      settings->beacon.tail_len,
 					      WLAN_EID_COUNTRY);
 		is_11d = country_ie ? 1 : 0;
@@ -5166,7 +5310,11 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 	if (settings->ssid == NULL || settings->ssid_len == 0) {
 		ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
 		ssid_ie = brcmf_parse_tlvs(
+#if defined(__linux__)
 				(u8 *)&settings->beacon.head[ie_offset],
+#elif defined(__FreeBSD__)
+				&settings->beacon.head[ie_offset],
+#endif
 				settings->beacon.head_len - ie_offset,
 				WLAN_EID_SSID);
 		if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)
@@ -5382,7 +5530,11 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev,
 	if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) {
 		/* Due to most likely deauths outstanding we sleep */
 		/* first to make sure they get processed by fw. */
+#if defined(__linux__)
 		msleep(400);
+#elif defined(__FreeBSD__)
+		linux_msleep(400);
+#endif
 
 		if (profile->use_fwauth != BIT(BRCMF_PROFILE_FWAUTH_NONE)) {
 			struct cfg80211_crypto_settings crypto = {};
@@ -5504,10 +5656,18 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
 
 	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
 		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_AUTHORIZE,
+#if defined(__linux__)
 					     (void *)mac, ETH_ALEN);
+#elif defined(__FreeBSD__)
+					     __DECONST(u8 *, mac), ETH_ALEN);
+#endif
 	else
 		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE,
+#if defined(__linux__)
 					     (void *)mac, ETH_ALEN);
+#elif defined(__FreeBSD__)
+					     __DECONST(u8 *, mac), ETH_ALEN);
+#endif
 	if (err < 0)
 		bphy_err(drvr, "Setting SCB (de-)authorize failed, %d\n", err);
 
@@ -5623,8 +5783,13 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 		memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],
 		       le16_to_cpu(action_frame->len));
 
+#if defined(__linux__)
 		brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, channel=%d\n",
 			  *cookie, le16_to_cpu(action_frame->len),
+#elif defined(__FreeBSD__)
+		brcmf_dbg(TRACE, "Action frame, cookie=%ju, len=%d, channel=%d\n",
+			  (uintmax_t)*cookie, le16_to_cpu(action_frame->len),
+#endif
 			  le32_to_cpu(af_params->channel));
 
 		ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),
@@ -5815,11 +5980,19 @@ brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,
 		break;
 	case BRCMF_E_REASON_TDLS_PEER_CONNECTED:
 		brcmf_dbg(TRACE, "TDLS Peer Connected\n");
+#if defined(__linux__)
 		brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+#elif defined(__FreeBSD__)
+		brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, e->addr);
+#endif
 		break;
 	case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:
 		brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");
+#if defined(__linux__)
 		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+#elif defined(__FreeBSD__)
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, e->addr);
+#endif
 		break;
 	}
 
@@ -6553,7 +6726,11 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
 	    (e->event_code == BRCMF_E_DEAUTH_IND) ||
 	    (e->event_code == BRCMF_E_DISASSOC_IND) ||
 	    ((e->event_code == BRCMF_E_LINK) && (!e->flags))) {
+#if defined(__linux__)
 		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+#elif defined(__FreeBSD__)
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, e->addr);
+#endif
 	}
 
 	if (brcmf_is_apmode(ifp->vif)) {
@@ -6640,7 +6817,11 @@ brcmf_notify_mic_status(struct brcmf_if *ifp,
 	else
 		key_type = NL80211_KEYTYPE_PAIRWISE;
 
+#if defined(__linux__)
 	cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
+#elif defined(__FreeBSD__)
+	cfg80211_michael_mic_failure(ifp->ndev, e->addr, key_type, -1,
+#endif
 				     NULL, GFP_KERNEL);
 
 	return 0;
@@ -8183,7 +8364,11 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
 		goto exit;
 
 	/* Add 10 ms for IOVAR completion */
+#if defined(__linux__)
 	msleep(ACS_MSRMNT_DELAY + 10);
+#elif defined(__FreeBSD__)
+	linux_msleep(ACS_MSRMNT_DELAY + 10);
+#endif
 
 	/* Issue IOVAR to collect measurement results */
 	req.msrmnt_query = 1;
@@ -8204,8 +8389,13 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
 	brcmf_dbg(INFO, "OBSS dump: channel %d: survey duration %d\n",
 		  ieee80211_frequency_to_channel(info->channel->center_freq),
 		  ACS_MSRMNT_DELAY);
+#if defined(__linux__)
 	brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n",
 		  info->noise, info->time_busy, info->time_rx, info->time_tx);
+#elif defined(__FreeBSD__)
+	brcmf_dbg(INFO, "noise(%d) busy(%ju) rx(%ju) tx(%ju)\n",
+		  info->noise, (uintmax_t)info->time_busy, (uintmax_t)info->time_rx, (uintmax_t)info->time_tx);
+#endif
 
 exit:
 	if (!brcmf_is_apmode(ifp->vif))
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/common.c b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/common.c
index 688f16c51319..17e408b7fa23 100644
--- a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/common.c
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/common.c
@@ -3,6 +3,10 @@
  * Copyright (c) 2010 Broadcom Corporation
  */
 
+#if defined(__FreeBSD__)
+#define	LINUXKPI_PARAM_PREFIX	brcmfmac_
+#endif
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/netdevice.h>
@@ -24,6 +28,12 @@
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
 MODULE_LICENSE("Dual BSD/GPL");
+#if defined(__FreeBSD__)
+MODULE_DEPEND(brcmfmac, brcmutil, 1, 1, 1);
+MODULE_DEPEND(brcmfmac, linuxkpi, 1, 1, 1);
+MODULE_DEPEND(brcmfmac, linuxkpi_wlan, 1, 1, 1);
+MODULE_DEPEND(brcmfmac, lindebugfs, 1, 1, 1);   /* XXX-BZ someone should fix this */
+#endif
 
 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
@@ -118,7 +128,11 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
 }
 
 static int brcmf_c_download_blob(struct brcmf_if *ifp,
+#if defined(__linux__)
 				 const void *data, size_t size,
+#elif defined(__FreeBSD__)
+				 const u8 *data, size_t size,
+#endif
 				 const char *loadvar, const char *statvar)
 {
 	struct brcmf_pub *drvr = ifp->drvr;
@@ -467,10 +481,22 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...)
 
 	vaf.fmt = fmt;
 	vaf.va = &args;
+#if defined(__linux__)
 	if (bus)
 		dev_err(bus->dev, "%s: %pV", func, &vaf);
 	else
 		pr_err("%s: %pV", func, &vaf);
+#elif defined(__FreeBSD__)
+	{
+	char *str;
+	vasprintf(&str, M_KMALLOC, vaf.fmt, args);
+	if (bus)
+		dev_err(bus->dev, "ERROR: %s: %s", func, str);
+	else
+		pr_err("ERROR: %s: %s", func, str);
+	free(str, M_KMALLOC);
+	}
+#endif
 
 	va_end(args);
 }
@@ -487,7 +513,16 @@ void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
 	va_start(args, fmt);
 	vaf.va = &args;
 	if (brcmf_msg_level & level)
+#if defined(__linux__)
 		pr_debug("%s %pV", func, &vaf);
+#elif defined(__FreeBSD__)
+	{
+		char *str;
+		vasprintf(&str, M_KMALLOC, vaf.fmt, args);
+		pr_debug("%s %s", func, str);
+		free(str, M_KMALLOC);
+	}
+#endif
 	trace_brcmf_dbg(level, func, &vaf);
 	va_end(args);
 }
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/commonring.c b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/commonring.c
index e44236cb210e..c0880fa12f57 100644
--- a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/commonring.c
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/commonring.c
@@ -119,8 +119,13 @@ again:
 		available = commonring->r_ptr - commonring->w_ptr;
 
 	if (available > 1) {
+#if defined(__linux__)
 		ret_ptr = commonring->buf_addr +
 			  (commonring->w_ptr * commonring->item_len);
+#elif defined(__FreeBSD__)
+		ret_ptr = (void *)((uintptr_t)commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len));
+#endif
 		commonring->w_ptr++;
 		if (commonring->w_ptr == commonring->depth)
 			commonring->w_ptr = 0;
@@ -155,8 +160,13 @@ again:
 		available = commonring->r_ptr - commonring->w_ptr;
 
 	if (available > 1) {
+#if defined(__linux__)
 		ret_ptr = commonring->buf_addr +
 			  (commonring->w_ptr * commonring->item_len);
+#elif defined(__FreeBSD__)
+		ret_ptr = (void *)((uintptr_t)commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len));
+#endif
 		*alloced = min_t(u16, n_items, available - 1);
 		if (*alloced + commonring->w_ptr > commonring->depth)
 			*alloced = commonring->depth - commonring->w_ptr;
@@ -217,8 +227,13 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
 	if (*n_items == 0)
 		return NULL;
 
+#if defined(__linux__)
 	return commonring->buf_addr +
 	       (commonring->r_ptr * commonring->item_len);
+#elif defined(__FreeBSD__)
*** 1217 LINES SKIPPED ***