Commit 0f485805 authored by Hector Martin's avatar Hector Martin Committed by Kalle Valo
Browse files

wifi: brcmfmac: acpi: Add support for fetching Apple ACPI properties



On DT platforms, the module-instance and antenna-sku-info properties
are passed in the DT. On ACPI platforms, module-instance is passed via
the analogous Apple device property mechanism, while the antenna SKU
info is instead obtained via an ACPI method that grabs it from
non-volatile storage.

Add support for this, to allow proper firmware selection on Apple
platforms.

Signed-off-by: default avatarHector Martin <marcan@marcan.st>
Reviewed-by: default avatarJulian Calaby <julian.calaby@gmail.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230214080034.3828-2-marcan@marcan.st
parent 0d1f7ff1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ brcmfmac-$(CONFIG_OF) += \
		of.o
brcmfmac-$(CONFIG_DMI) += \
		dmi.o
brcmfmac-$(CONFIG_ACPI) += \
		acpi.o

ifeq ($(CONFIG_BRCMFMAC),m)
obj-m += wcc/
+51 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: ISC
/*
 * Copyright The Asahi Linux Contributors
 */

#include <linux/acpi.h>
#include "debug.h"
#include "core.h"
#include "common.h"

void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
		      struct brcmf_mp_device *settings)
{
	acpi_status status;
	const union acpi_object *o;
	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
	struct acpi_device *adev = ACPI_COMPANION(dev);

	if (!adev)
		return;

	if (!ACPI_FAILURE(acpi_dev_get_property(adev, "module-instance",
						ACPI_TYPE_STRING, &o))) {
		brcmf_dbg(INFO, "ACPI module-instance=%s\n", o->string.pointer);
		settings->board_type = devm_kasprintf(dev, GFP_KERNEL,
						      "apple,%s",
						      o->string.pointer);
	} else {
		brcmf_dbg(INFO, "No ACPI module-instance\n");
		return;
	}

	status = acpi_evaluate_object(adev->handle, "RWCV", NULL, &buf);
	o = buf.pointer;
	if (!ACPI_FAILURE(status) && o && o->type == ACPI_TYPE_BUFFER &&
	    o->buffer.length >= 2) {
		char *antenna_sku = devm_kzalloc(dev, 3, GFP_KERNEL);

		if (antenna_sku) {
			memcpy(antenna_sku, o->buffer.pointer, 2);
			brcmf_dbg(INFO, "ACPI RWCV data=%*phN antenna-sku=%s\n",
				  (int)o->buffer.length, o->buffer.pointer,
				  antenna_sku);
			settings->antenna_sku = antenna_sku;
		}

		kfree(buf.pointer);
	} else {
		brcmf_dbg(INFO, "No ACPI antenna-sku\n");
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -487,6 +487,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
		/* No platform data for this device, try OF and DMI data */
		brcmf_dmi_probe(settings, chip, chiprev);
		brcmf_of_probe(dev, bus_type, settings);
		brcmf_acpi_probe(dev, bus_type, settings);
	}
	return settings;
}
+9 −0
Original line number Diff line number Diff line
@@ -77,6 +77,15 @@ static inline void
brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {}
#endif

#ifdef CONFIG_ACPI
void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
		      struct brcmf_mp_device *settings);
#else
static inline void brcmf_acpi_probe(struct device *dev,
				    enum brcmf_bus_type bus_type,
				    struct brcmf_mp_device *settings) {}
#endif

u8 brcmf_map_prio_to_prec(void *cfg, u8 prio);

u8 brcmf_map_prio_to_aci(void *cfg, u8 prio);