diff --git a/.gitignore b/.gitignore index c1959ff..0ff204c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ src/ pkg/ apple-bce/ apple-ibridge/ -t2linux-linux diff --git a/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch new file mode 100644 index 0000000..24750e6 --- /dev/null +++ b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch @@ -0,0 +1,154 @@ +From f615330c6169a5fe5750706f1db7cbdd520f9534 Mon Sep 17 00:00:00 2001 +From: "Jan Alexander Steffens (heftig)" +Date: Mon, 16 Sep 2019 04:53:20 +0200 +Subject: [PATCH 1/2] ZEN: Add sysctl and CONFIG to disallow unprivileged + CLONE_NEWUSER + +Our default behavior continues to match the vanilla kernel. +--- + include/linux/user_namespace.h | 4 ++++ + init/Kconfig | 16 ++++++++++++++++ + kernel/fork.c | 14 ++++++++++++++ + kernel/sysctl.c | 12 ++++++++++++ + kernel/user_namespace.c | 7 +++++++ + 5 files changed, 53 insertions(+) + +diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h +index 6ef1c7109fc4..2140091b0b8d 100644 +--- a/include/linux/user_namespace.h ++++ b/include/linux/user_namespace.h +@@ -106,6 +106,8 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type); + + #ifdef CONFIG_USER_NS + ++extern int unprivileged_userns_clone; ++ + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) + { + if (ns) +@@ -139,6 +141,8 @@ extern bool current_in_userns(const struct user_namespace *target_ns); + struct ns_common *ns_get_owner(struct ns_common *ns); + #else + ++#define unprivileged_userns_clone 0 ++ + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) + { + return &init_user_ns; +diff --git a/init/Kconfig b/init/Kconfig +index 0872a5a2e759..a40d8afeb1bb 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1173,6 +1173,22 @@ config USER_NS + + If unsure, say N. + ++config USER_NS_UNPRIVILEGED ++ bool "Allow unprivileged users to create namespaces" ++ default y ++ depends on USER_NS ++ help ++ When disabled, unprivileged users will not be able to create ++ new namespaces. Allowing users to create their own namespaces ++ has been part of several recent local privilege escalation ++ exploits, so if you need user namespaces but are ++ paranoid^Wsecurity-conscious you want to disable this. ++ ++ This setting can be overridden at runtime via the ++ kernel.unprivileged_userns_clone sysctl. ++ ++ If unsure, say Y. ++ + config PID_NS + bool "PID Namespaces" + default y +diff --git a/kernel/fork.c b/kernel/fork.c +index c675fdbd3dce..9266039e28e4 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -97,6 +97,10 @@ + #include + #include + ++#ifdef CONFIG_USER_NS ++#include ++#endif ++ + #include + #include + #include +@@ -1863,6 +1867,10 @@ static __latent_entropy struct task_struct *copy_process( + if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) + return ERR_PTR(-EINVAL); + ++ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) ++ if (!capable(CAP_SYS_ADMIN)) ++ return ERR_PTR(-EPERM); ++ + /* + * Thread groups must share signals as well, and detached threads + * can only be started up within the thread group. +@@ -2928,6 +2936,12 @@ int ksys_unshare(unsigned long unshare_flags) + if (unshare_flags & CLONE_NEWNS) + unshare_flags |= CLONE_FS; + ++ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) { ++ err = -EPERM; ++ if (!capable(CAP_SYS_ADMIN)) ++ goto bad_unshare_out; ++ } ++ + err = check_unshare_flags(unshare_flags); + if (err) + goto bad_unshare_out; +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index afad085960b8..a94828fb31c2 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -103,6 +103,9 @@ + #ifdef CONFIG_LOCKUP_DETECTOR + #include + #endif ++#ifdef CONFIG_USER_NS ++#include ++#endif + + #if defined(CONFIG_SYSCTL) + +@@ -1902,6 +1905,15 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dointvec, + }, + #endif ++#ifdef CONFIG_USER_NS ++ { ++ .procname = "unprivileged_userns_clone", ++ .data = &unprivileged_userns_clone, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, ++#endif + #ifdef CONFIG_PROC_SYSCTL + { + .procname = "tainted", +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index e703d5d9cbe8..5758274feaee 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -21,6 +21,13 @@ + #include + #include + ++/* sysctl */ ++#ifdef CONFIG_USER_NS_UNPRIVILEGED ++int unprivileged_userns_clone = 1; ++#else ++int unprivileged_userns_clone; ++#endif ++ + static struct kmem_cache *user_ns_cachep __read_mostly; + static DEFINE_MUTEX(userns_state_mutex); + +-- +2.31.1 + diff --git a/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_sp.patch b/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_sp.patch new file mode 100644 index 0000000..9f457ba --- /dev/null +++ b/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_sp.patch @@ -0,0 +1,36 @@ +From 3df6111e2ffaf7a57dd245a9df1997f773840b74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Felix=20H=C3=A4dicke?= +Date: Thu, 19 Nov 2020 09:22:32 +0100 +Subject: [PATCH 2/2] HID: quirks: Add Apple Magic Trackpad 2 to + hid_have_special_driver list +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Apple Magic Trackpad 2 is handled by the magicmouse driver. And +there were severe stability issues when both drivers (hid-generic and +hid-magicmouse) were loaded for this device. + +Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=210241 + +Signed-off-by: Felix Hädicke +--- + drivers/hid/hid-quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index bf7ecab5d9e5..142e9dae2837 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -478,6 +478,8 @@ static const struct hid_device_id hid_have_special_driver[] = { + #if IS_ENABLED(CONFIG_HID_MAGICMOUSE) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, ++ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) }, + #endif + #if IS_ENABLED(CONFIG_HID_MAYFLASH) + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, +-- +2.31.1 + diff --git a/2001-drm-amd-display-Force-link_rate-as-LINK_RATE_RBR2-fo.patch b/2001-drm-amd-display-Force-link_rate-as-LINK_RATE_RBR2-fo.patch new file mode 100644 index 0000000..144dd35 --- /dev/null +++ b/2001-drm-amd-display-Force-link_rate-as-LINK_RATE_RBR2-fo.patch @@ -0,0 +1,59 @@ +From b6740001d1adbfe84768b859bee038ceeccdc50c Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Wed, 12 Jan 2022 22:38:15 +1100 +Subject: [PATCH] drm/amd/display: Force link_rate as LINK_RATE_RBR2 for 2018 15" Apple Retina panels + +The eDP link rate reported by the DP_MAX_LINK_RATE dpcd register (0xa) is +contradictory to the highest rate supported reported by +EDID (0xc = LINK_RATE_RBR2). The effects of this compounded with commit +'4a8ca46bae8a ("drm/amd/display: Default max bpc to 16 for eDP")' results +in no display modes being found and a dark panel. + +For now, simply force the maximum supported link rate for the eDP attached +2018 15" Apple Retina panels. + +Additionally, we must also check the firmware revision since the device ID +reported by the DPCD is identical to that of the more capable 16,1, +incorrectly quirking it. We also use said firmware check to quirk the +refreshed 15,1 models with Vega graphics as they use a slightly newer +firmware version. + +Tested-by: Aun-Ali Zaidi +Signed-off-by: Aun-Ali Zaidi +Signed-off-by: Aditya Garg +--- + .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +index 05e216524..17939ad17 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +@@ -5597,6 +5597,25 @@ static bool retrieve_link_cap(struct dc_link *link) + dp_hw_fw_revision.ieee_fw_rev, + sizeof(dp_hw_fw_revision.ieee_fw_rev)); + ++ /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */ ++ { ++ uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 }; ++ uint8_t fwrev_mbp_2018[] = { 7, 4 }; ++ uint8_t fwrev_mbp_2018_vega[] = { 8, 4 }; ++ ++ // We also check for the firmware revision as 16,1 models have an ++ // identical device id and are incorrectly quirked otherwise. ++ if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && ++ !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018, ++ sizeof(str_mbp_2018)) && ++ (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018, ++ sizeof(fwrev_mbp_2018)) || ++ !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega, ++ sizeof(fwrev_mbp_2018_vega)))) { ++ link->reported_link_cap.link_rate = LINK_RATE_RBR2; ++ } ++ } ++ + memset(&link->dpcd_caps.dsc_caps, '\0', + sizeof(link->dpcd_caps.dsc_caps)); + memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); +-- +2.25.1 diff --git a/3001-applesmc-convert-static-structures-to-drvdata.patch b/3001-applesmc-convert-static-structures-to-drvdata.patch new file mode 100644 index 0000000..ead6e81 --- /dev/null +++ b/3001-applesmc-convert-static-structures-to-drvdata.patch @@ -0,0 +1,1218 @@ +From 09dd6c563cd73d72e917de07e8d59358c41e051d Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sun, 17 Nov 2019 23:12:55 +0100 +Subject: [PATCH 1/6] applesmc: convert static structures to drvdata + +All static data structures have been moved to an applesmc_device struct, +which is then associated with the platform device. +This change is intended to ease the migration to an acpi_device, where +static data would preferably be avoided. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 540 +++++++++++++++++++++++---------------- + 1 file changed, 319 insertions(+), 221 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index 79b498f816fe..62211b590a61 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -6,6 +6,7 @@ + * + * Copyright (C) 2007 Nicolas Boichat + * Copyright (C) 2010 Henrik Rydberg ++ * Copyright (C) 2019 Paul Pawlowski + * + * Based on hdaps.c driver: + * Copyright (C) 2005 Robert Love +@@ -119,7 +120,7 @@ struct applesmc_entry { + }; + + /* Register lookup and registers common to all SMCs */ +-static struct applesmc_registers { ++struct applesmc_registers { + struct mutex mutex; /* register read/write mutex */ + unsigned int key_count; /* number of SMC registers */ + unsigned int fan_count; /* number of fans */ +@@ -133,26 +134,32 @@ static struct applesmc_registers { + bool init_complete; /* true when fully initialized */ + struct applesmc_entry *cache; /* cached key entries */ + const char **index; /* temperature key index */ +-} smcreg = { +- .mutex = __MUTEX_INITIALIZER(smcreg.mutex), + }; + +-static const int debug; +-static struct platform_device *pdev; +-static s16 rest_x; +-static s16 rest_y; +-static u8 backlight_state[2]; ++struct applesmc_device { ++ struct platform_device *dev; ++ struct applesmc_registers reg; + +-static struct device *hwmon_dev; +-static struct input_dev *applesmc_idev; ++ s16 rest_x; ++ s16 rest_y; + +-/* +- * Last index written to key_at_index sysfs file, and value to use for all other +- * key_at_index_* sysfs files. +- */ +-static unsigned int key_at_index; ++ u8 backlight_state[2]; ++ ++ struct device *hwmon_dev; ++ struct input_dev *idev; ++ ++ /* ++ * Last index written to key_at_index sysfs file, and value to use for all other ++ * key_at_index_* sysfs files. ++ */ ++ unsigned int key_at_index; ++ ++ struct workqueue_struct *backlight_wq; ++ struct work_struct backlight_work; ++ struct led_classdev backlight_dev; ++}; + +-static struct workqueue_struct *applesmc_led_wq; ++static const int debug; + + /* + * Wait for specific status bits with a mask on the SMC. +@@ -338,36 +345,37 @@ static int read_register_count(unsigned int *count) + * All functions below are concurrency safe - callers should NOT hold lock. + */ + +-static int applesmc_read_entry(const struct applesmc_entry *entry, +- u8 *buf, u8 len) ++static int applesmc_read_entry(struct applesmc_device *smc, ++ const struct applesmc_entry *entry, u8 *buf, u8 len) + { + int ret; + + if (entry->len != len) + return -EINVAL; +- mutex_lock(&smcreg.mutex); ++ mutex_lock(&smc->reg.mutex); + ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); +- mutex_unlock(&smcreg.mutex); ++ mutex_unlock(&smc->reg.mutex); + + return ret; + } + +-static int applesmc_write_entry(const struct applesmc_entry *entry, +- const u8 *buf, u8 len) ++static int applesmc_write_entry(struct applesmc_device *smc, ++ const struct applesmc_entry *entry, const u8 *buf, u8 len) + { + int ret; + + if (entry->len != len) + return -EINVAL; +- mutex_lock(&smcreg.mutex); ++ mutex_lock(&smc->reg.mutex); + ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); +- mutex_unlock(&smcreg.mutex); ++ mutex_unlock(&smc->reg.mutex); + return ret; + } + +-static const struct applesmc_entry *applesmc_get_entry_by_index(int index) ++static const struct applesmc_entry *applesmc_get_entry_by_index( ++ struct applesmc_device *smc, int index) + { +- struct applesmc_entry *cache = &smcreg.cache[index]; ++ struct applesmc_entry *cache = &smc->reg.cache[index]; + u8 key[4], info[6]; + __be32 be; + int ret = 0; +@@ -375,7 +383,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) + if (cache->valid) + return cache; + +- mutex_lock(&smcreg.mutex); ++ mutex_lock(&smc->reg.mutex); + + if (cache->valid) + goto out; +@@ -394,20 +402,21 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) + cache->valid = true; + + out: +- mutex_unlock(&smcreg.mutex); ++ mutex_unlock(&smc->reg.mutex); + if (ret) + return ERR_PTR(ret); + return cache; + } + +-static int applesmc_get_lower_bound(unsigned int *lo, const char *key) ++static int applesmc_get_lower_bound(struct applesmc_device *smc, ++ unsigned int *lo, const char *key) + { +- int begin = 0, end = smcreg.key_count; ++ int begin = 0, end = smc->reg.key_count; + const struct applesmc_entry *entry; + + while (begin != end) { + int middle = begin + (end - begin) / 2; +- entry = applesmc_get_entry_by_index(middle); ++ entry = applesmc_get_entry_by_index(smc, middle); + if (IS_ERR(entry)) { + *lo = 0; + return PTR_ERR(entry); +@@ -422,16 +431,17 @@ static int applesmc_get_lower_bound(unsigned int *lo, const char *key) + return 0; + } + +-static int applesmc_get_upper_bound(unsigned int *hi, const char *key) ++static int applesmc_get_upper_bound(struct applesmc_device *smc, ++ unsigned int *hi, const char *key) + { +- int begin = 0, end = smcreg.key_count; ++ int begin = 0, end = smc->reg.key_count; + const struct applesmc_entry *entry; + + while (begin != end) { + int middle = begin + (end - begin) / 2; +- entry = applesmc_get_entry_by_index(middle); ++ entry = applesmc_get_entry_by_index(smc, middle); + if (IS_ERR(entry)) { +- *hi = smcreg.key_count; ++ *hi = smc->reg.key_count; + return PTR_ERR(entry); + } + if (strcmp(key, entry->key) < 0) +@@ -444,50 +454,54 @@ static int applesmc_get_upper_bound(unsigned int *hi, const char *key) + return 0; + } + +-static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) ++static const struct applesmc_entry *applesmc_get_entry_by_key( ++ struct applesmc_device *smc, const char *key) + { + int begin, end; + int ret; + +- ret = applesmc_get_lower_bound(&begin, key); ++ ret = applesmc_get_lower_bound(smc, &begin, key); + if (ret) + return ERR_PTR(ret); +- ret = applesmc_get_upper_bound(&end, key); ++ ret = applesmc_get_upper_bound(smc, &end, key); + if (ret) + return ERR_PTR(ret); + if (end - begin != 1) + return ERR_PTR(-EINVAL); + +- return applesmc_get_entry_by_index(begin); ++ return applesmc_get_entry_by_index(smc, begin); + } + +-static int applesmc_read_key(const char *key, u8 *buffer, u8 len) ++static int applesmc_read_key(struct applesmc_device *smc, ++ const char *key, u8 *buffer, u8 len) + { + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_key(key); ++ entry = applesmc_get_entry_by_key(smc, key); + if (IS_ERR(entry)) + return PTR_ERR(entry); + +- return applesmc_read_entry(entry, buffer, len); ++ return applesmc_read_entry(smc, entry, buffer, len); + } + +-static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) ++static int applesmc_write_key(struct applesmc_device *smc, ++ const char *key, const u8 *buffer, u8 len) + { + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_key(key); ++ entry = applesmc_get_entry_by_key(smc, key); + if (IS_ERR(entry)) + return PTR_ERR(entry); + +- return applesmc_write_entry(entry, buffer, len); ++ return applesmc_write_entry(smc, entry, buffer, len); + } + +-static int applesmc_has_key(const char *key, bool *value) ++static int applesmc_has_key(struct applesmc_device *smc, ++ const char *key, bool *value) + { + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_key(key); ++ entry = applesmc_get_entry_by_key(smc, key); + if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL) + return PTR_ERR(entry); + +@@ -498,12 +512,13 @@ static int applesmc_has_key(const char *key, bool *value) + /* + * applesmc_read_s16 - Read 16-bit signed big endian register + */ +-static int applesmc_read_s16(const char *key, s16 *value) ++static int applesmc_read_s16(struct applesmc_device *smc, ++ const char *key, s16 *value) + { + u8 buffer[2]; + int ret; + +- ret = applesmc_read_key(key, buffer, 2); ++ ret = applesmc_read_key(smc, key, buffer, 2); + if (ret) + return ret; + +@@ -514,28 +529,29 @@ static int applesmc_read_s16(const char *key, s16 *value) + /* + * applesmc_device_init - initialize the accelerometer. Can sleep. + */ +-static void applesmc_device_init(void) ++static void applesmc_device_init(struct applesmc_device *smc) + { + int total; + u8 buffer[2]; + +- if (!smcreg.has_accelerometer) ++ if (!smc->reg.has_accelerometer) + return; + + for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { +- if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && ++ if (!applesmc_read_key(smc, MOTION_SENSOR_KEY, buffer, 2) && + (buffer[0] != 0x00 || buffer[1] != 0x00)) + return; + buffer[0] = 0xe0; + buffer[1] = 0x00; +- applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); ++ applesmc_write_key(smc, MOTION_SENSOR_KEY, buffer, 2); + msleep(INIT_WAIT_MSECS); + } + + pr_warn("failed to init the device\n"); + } + +-static int applesmc_init_index(struct applesmc_registers *s) ++static int applesmc_init_index(struct applesmc_device *smc, ++ struct applesmc_registers *s) + { + const struct applesmc_entry *entry; + unsigned int i; +@@ -548,7 +564,7 @@ static int applesmc_init_index(struct applesmc_registers *s) + return -ENOMEM; + + for (i = s->temp_begin; i < s->temp_end; i++) { +- entry = applesmc_get_entry_by_index(i); ++ entry = applesmc_get_entry_by_index(smc, i); + if (IS_ERR(entry)) + continue; + if (strcmp(entry->type, TEMP_SENSOR_TYPE)) +@@ -562,9 +578,9 @@ static int applesmc_init_index(struct applesmc_registers *s) + /* + * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. + */ +-static int applesmc_init_smcreg_try(void) ++static int applesmc_init_smcreg_try(struct applesmc_device *smc) + { +- struct applesmc_registers *s = &smcreg; ++ struct applesmc_registers *s = &smc->reg; + bool left_light_sensor = false, right_light_sensor = false; + unsigned int count; + u8 tmp[1]; +@@ -590,35 +606,35 @@ static int applesmc_init_smcreg_try(void) + if (!s->cache) + return -ENOMEM; + +- ret = applesmc_read_key(FANS_COUNT, tmp, 1); ++ ret = applesmc_read_key(smc, FANS_COUNT, tmp, 1); + if (ret) + return ret; + s->fan_count = tmp[0]; + if (s->fan_count > 10) + s->fan_count = 10; + +- ret = applesmc_get_lower_bound(&s->temp_begin, "T"); ++ ret = applesmc_get_lower_bound(smc, &s->temp_begin, "T"); + if (ret) + return ret; +- ret = applesmc_get_lower_bound(&s->temp_end, "U"); ++ ret = applesmc_get_lower_bound(smc, &s->temp_end, "U"); + if (ret) + return ret; + s->temp_count = s->temp_end - s->temp_begin; + +- ret = applesmc_init_index(s); ++ ret = applesmc_init_index(smc, s); + if (ret) + return ret; + +- ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); ++ ret = applesmc_has_key(smc, LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); + if (ret) + return ret; +- ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); ++ ret = applesmc_has_key(smc, LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); + if (ret) + return ret; +- ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer); ++ ret = applesmc_has_key(smc, MOTION_SENSOR_KEY, &s->has_accelerometer); + if (ret) + return ret; +- ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight); ++ ret = applesmc_has_key(smc, BACKLIGHT_KEY, &s->has_key_backlight); + if (ret) + return ret; + +@@ -634,13 +650,13 @@ static int applesmc_init_smcreg_try(void) + return 0; + } + +-static void applesmc_destroy_smcreg(void) ++static void applesmc_destroy_smcreg(struct applesmc_device *smc) + { +- kfree(smcreg.index); +- smcreg.index = NULL; +- kfree(smcreg.cache); +- smcreg.cache = NULL; +- smcreg.init_complete = false; ++ kfree(smc->reg.index); ++ smc->reg.index = NULL; ++ kfree(smc->reg.cache); ++ smc->reg.cache = NULL; ++ smc->reg.init_complete = false; + } + + /* +@@ -649,12 +665,12 @@ static void applesmc_destroy_smcreg(void) + * Retries until initialization is successful, or the operation times out. + * + */ +-static int applesmc_init_smcreg(void) ++static int applesmc_init_smcreg(struct applesmc_device *smc) + { + int ms, ret; + + for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) { +- ret = applesmc_init_smcreg_try(); ++ ret = applesmc_init_smcreg_try(smc); + if (!ret) { + if (ms) + pr_info("init_smcreg() took %d ms\n", ms); +@@ -663,21 +679,58 @@ static int applesmc_init_smcreg(void) + msleep(INIT_WAIT_MSECS); + } + +- applesmc_destroy_smcreg(); ++ applesmc_destroy_smcreg(smc); + + return ret; + } + + /* Device model stuff */ ++static int applesmc_create_modules(struct applesmc_device *smc); ++static void applesmc_destroy_modules(struct applesmc_device *smc); + static int applesmc_probe(struct platform_device *dev) + { ++ struct applesmc_device *smc; + int ret; + +- ret = applesmc_init_smcreg(); ++ smc = kzalloc(sizeof(struct applesmc_device), GFP_KERNEL); ++ if (!smc) ++ return -ENOMEM; ++ smc->dev = dev; ++ mutex_init(&smc->reg.mutex); ++ ++ platform_set_drvdata(dev, smc); ++ ++ ret = applesmc_init_smcreg(smc); + if (ret) +- return ret; ++ goto out_mem; ++ ++ applesmc_device_init(smc); ++ ++ ret = applesmc_create_modules(smc); ++ if (ret) ++ goto out_reg; ++ ++ return 0; ++ ++out_reg: ++ applesmc_destroy_smcreg(smc); ++out_mem: ++ platform_set_drvdata(dev, NULL); ++ mutex_destroy(&smc->reg.mutex); ++ kfree(smc); + +- applesmc_device_init(); ++ return ret; ++} ++ ++static int applesmc_remove(struct platform_device *dev) ++{ ++ struct applesmc_device *smc = platform_get_drvdata(dev); ++ ++ applesmc_destroy_modules(smc); ++ applesmc_destroy_smcreg(smc); ++ ++ mutex_destroy(&smc->reg.mutex); ++ kfree(smc); + + return 0; + } +@@ -685,15 +738,21 @@ static int applesmc_probe(struct platform_device *dev) + /* Synchronize device with memorized backlight state */ + static int applesmc_pm_resume(struct device *dev) + { +- if (smcreg.has_key_backlight) +- applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ ++ if (smc->reg.has_key_backlight) ++ applesmc_write_key(smc, BACKLIGHT_KEY, smc->backlight_state, 2); ++ + return 0; + } + + /* Reinitialize device on resume from hibernation */ + static int applesmc_pm_restore(struct device *dev) + { +- applesmc_device_init(); ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ ++ applesmc_device_init(smc); ++ + return applesmc_pm_resume(dev); + } + +@@ -704,6 +763,7 @@ static const struct dev_pm_ops applesmc_pm_ops = { + + static struct platform_driver applesmc_driver = { + .probe = applesmc_probe, ++ .remove = applesmc_remove, + .driver = { + .name = "applesmc", + .pm = &applesmc_pm_ops, +@@ -714,25 +774,26 @@ static struct platform_driver applesmc_driver = { + * applesmc_calibrate - Set our "resting" values. Callers must + * hold applesmc_lock. + */ +-static void applesmc_calibrate(void) ++static void applesmc_calibrate(struct applesmc_device *smc) + { +- applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x); +- applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y); +- rest_x = -rest_x; ++ applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &smc->rest_x); ++ applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &smc->rest_y); ++ smc->rest_x = -smc->rest_x; + } + + static void applesmc_idev_poll(struct input_dev *idev) + { ++ struct applesmc_device *smc = dev_get_drvdata(&idev->dev); + s16 x, y; + +- if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x)) ++ if (applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &x)) + return; +- if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y)) ++ if (applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &y)) + return; + + x = -x; +- input_report_abs(idev, ABS_X, x - rest_x); +- input_report_abs(idev, ABS_Y, y - rest_y); ++ input_report_abs(idev, ABS_X, x - smc->rest_x); ++ input_report_abs(idev, ABS_Y, y - smc->rest_y); + input_sync(idev); + } + +@@ -747,16 +808,17 @@ static ssize_t applesmc_name_show(struct device *dev, + static ssize_t applesmc_position_show(struct device *dev, + struct device_attribute *attr, char *buf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + s16 x, y, z; + +- ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x); ++ ret = applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &x); + if (ret) + goto out; +- ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y); ++ ret = applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &y); + if (ret) + goto out; +- ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z); ++ ret = applesmc_read_s16(smc, MOTION_SENSOR_Z_KEY, &z); + if (ret) + goto out; + +@@ -770,6 +832,7 @@ static ssize_t applesmc_position_show(struct device *dev, + static ssize_t applesmc_light_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + const struct applesmc_entry *entry; + static int data_length; + int ret; +@@ -777,7 +840,7 @@ static ssize_t applesmc_light_show(struct device *dev, + u8 buffer[10]; + + if (!data_length) { +- entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); ++ entry = applesmc_get_entry_by_key(smc, LIGHT_SENSOR_LEFT_KEY); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (entry->len > 10) +@@ -786,7 +849,7 @@ static ssize_t applesmc_light_show(struct device *dev, + pr_info("light sensor data length set to %d\n", data_length); + } + +- ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); ++ ret = applesmc_read_key(smc, LIGHT_SENSOR_LEFT_KEY, buffer, data_length); + if (ret) + goto out; + /* newer macbooks report a single 10-bit bigendian value */ +@@ -796,7 +859,7 @@ static ssize_t applesmc_light_show(struct device *dev, + } + left = buffer[2]; + +- ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); ++ ret = applesmc_read_key(smc, LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); + if (ret) + goto out; + right = buffer[2]; +@@ -812,7 +875,8 @@ static ssize_t applesmc_light_show(struct device *dev, + static ssize_t applesmc_show_sensor_label(struct device *dev, + struct device_attribute *devattr, char *sysfsbuf) + { +- const char *key = smcreg.index[to_index(devattr)]; ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ const char *key = smc->reg.index[to_index(devattr)]; + + return sysfs_emit(sysfsbuf, "%s\n", key); + } +@@ -821,12 +885,13 @@ static ssize_t applesmc_show_sensor_label(struct device *dev, + static ssize_t applesmc_show_temperature(struct device *dev, + struct device_attribute *devattr, char *sysfsbuf) + { +- const char *key = smcreg.index[to_index(devattr)]; ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ const char *key = smc->reg.index[to_index(devattr)]; + int ret; + s16 value; + int temp; + +- ret = applesmc_read_s16(key, &value); ++ ret = applesmc_read_s16(smc, key, &value); + if (ret) + return ret; + +@@ -838,6 +903,7 @@ static ssize_t applesmc_show_temperature(struct device *dev, + static ssize_t applesmc_show_fan_speed(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + unsigned int speed = 0; + char newkey[5]; +@@ -846,7 +912,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, + scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], + to_index(attr)); + +- ret = applesmc_read_key(newkey, buffer, 2); ++ ret = applesmc_read_key(smc, newkey, buffer, 2); + if (ret) + return ret; + +@@ -858,6 +924,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, + struct device_attribute *attr, + const char *sysfsbuf, size_t count) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + unsigned long speed; + char newkey[5]; +@@ -871,7 +938,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, + + buffer[0] = (speed >> 6) & 0xff; + buffer[1] = (speed << 2) & 0xff; +- ret = applesmc_write_key(newkey, buffer, 2); ++ ret = applesmc_write_key(smc, newkey, buffer, 2); + + if (ret) + return ret; +@@ -882,11 +949,12 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, + static ssize_t applesmc_show_fan_manual(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + u16 manual = 0; + u8 buffer[2]; + +- ret = applesmc_read_key(FANS_MANUAL, buffer, 2); ++ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); + if (ret) + return ret; + +@@ -898,6 +966,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, + struct device_attribute *attr, + const char *sysfsbuf, size_t count) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + u8 buffer[2]; + unsigned long input; +@@ -906,7 +975,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, + if (kstrtoul(sysfsbuf, 10, &input) < 0) + return -EINVAL; + +- ret = applesmc_read_key(FANS_MANUAL, buffer, 2); ++ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); + if (ret) + goto out; + +@@ -920,7 +989,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, + buffer[0] = (val >> 8) & 0xFF; + buffer[1] = val & 0xFF; + +- ret = applesmc_write_key(FANS_MANUAL, buffer, 2); ++ ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); + + out: + if (ret) +@@ -932,13 +1001,14 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, + static ssize_t applesmc_show_fan_position(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + char newkey[5]; + u8 buffer[17]; + + scnprintf(newkey, sizeof(newkey), FAN_ID_FMT, to_index(attr)); + +- ret = applesmc_read_key(newkey, buffer, 16); ++ ret = applesmc_read_key(smc, newkey, buffer, 16); + buffer[16] = 0; + + if (ret) +@@ -950,30 +1020,36 @@ static ssize_t applesmc_show_fan_position(struct device *dev, + static ssize_t applesmc_calibrate_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { +- return sysfs_emit(sysfsbuf, "(%d,%d)\n", rest_x, rest_y); ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ ++ return sysfs_emit(sysfsbuf, "(%d,%d)\n", smc->rest_x, smc->rest_y); + } + + static ssize_t applesmc_calibrate_store(struct device *dev, + struct device_attribute *attr, const char *sysfsbuf, size_t count) + { +- applesmc_calibrate(); ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ ++ applesmc_calibrate(smc); + + return count; + } + + static void applesmc_backlight_set(struct work_struct *work) + { +- applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); ++ struct applesmc_device *smc = container_of(work, struct applesmc_device, backlight_work); ++ ++ applesmc_write_key(smc, BACKLIGHT_KEY, smc->backlight_state, 2); + } +-static DECLARE_WORK(backlight_work, &applesmc_backlight_set); + + static void applesmc_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) + { ++ struct applesmc_device *smc = dev_get_drvdata(led_cdev->dev); + int ret; + +- backlight_state[0] = value; +- ret = queue_work(applesmc_led_wq, &backlight_work); ++ smc->backlight_state[0] = value; ++ ret = queue_work(smc->backlight_wq, &smc->backlight_work); + + if (debug && (!ret)) + dev_dbg(led_cdev->dev, "work was already on the queue.\n"); +@@ -982,11 +1058,12 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev, + static ssize_t applesmc_key_count_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + u8 buffer[4]; + u32 count; + +- ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); ++ ret = applesmc_read_key(smc, KEY_COUNT_KEY, buffer, 4); + if (ret) + return ret; + +@@ -998,13 +1075,14 @@ static ssize_t applesmc_key_count_show(struct device *dev, + static ssize_t applesmc_key_at_index_read_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + const struct applesmc_entry *entry; + int ret; + +- entry = applesmc_get_entry_by_index(key_at_index); ++ entry = applesmc_get_entry_by_index(smc, smc->key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); +- ret = applesmc_read_entry(entry, sysfsbuf, entry->len); ++ ret = applesmc_read_entry(smc, entry, sysfsbuf, entry->len); + if (ret) + return ret; + +@@ -1014,9 +1092,10 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev, + static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_index(key_at_index); ++ entry = applesmc_get_entry_by_index(smc, smc->key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + +@@ -1026,9 +1105,10 @@ static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, + static ssize_t applesmc_key_at_index_type_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_index(key_at_index); ++ entry = applesmc_get_entry_by_index(smc, smc->key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + +@@ -1038,9 +1118,10 @@ static ssize_t applesmc_key_at_index_type_show(struct device *dev, + static ssize_t applesmc_key_at_index_name_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + const struct applesmc_entry *entry; + +- entry = applesmc_get_entry_by_index(key_at_index); ++ entry = applesmc_get_entry_by_index(smc, smc->key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + +@@ -1050,28 +1131,25 @@ static ssize_t applesmc_key_at_index_name_show(struct device *dev, + static ssize_t applesmc_key_at_index_show(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { +- return sysfs_emit(sysfsbuf, "%d\n", key_at_index); ++ struct applesmc_device *smc = dev_get_drvdata(dev); ++ ++ return sysfs_emit(sysfsbuf, PAGE_SIZE, "%d\n", smc->key_at_index); + } + + static ssize_t applesmc_key_at_index_store(struct device *dev, + struct device_attribute *attr, const char *sysfsbuf, size_t count) + { ++ struct applesmc_device *smc = dev_get_drvdata(dev); + unsigned long newkey; + + if (kstrtoul(sysfsbuf, 10, &newkey) < 0 +- || newkey >= smcreg.key_count) ++ || newkey >= smc->reg.key_count) + return -EINVAL; + +- key_at_index = newkey; ++ smc->key_at_index = newkey; + return count; + } + +-static struct led_classdev applesmc_backlight = { +- .name = "smc::kbd_backlight", +- .default_trigger = "nand-disk", +- .brightness_set = applesmc_brightness_set, +-}; +- + static struct applesmc_node_group info_group[] = { + { "name", applesmc_name_show }, + { "key_count", applesmc_key_count_show }, +@@ -1116,14 +1194,15 @@ static struct applesmc_node_group temp_group[] = { + /* + * applesmc_destroy_nodes - remove files and free associated memory + */ +-static void applesmc_destroy_nodes(struct applesmc_node_group *groups) ++static void applesmc_destroy_nodes(struct applesmc_device *smc, ++ struct applesmc_node_group *groups) + { + struct applesmc_node_group *grp; + struct applesmc_dev_attr *node; + + for (grp = groups; grp->nodes; grp++) { + for (node = grp->nodes; node->sda.dev_attr.attr.name; node++) +- sysfs_remove_file(&pdev->dev.kobj, ++ sysfs_remove_file(&smc->dev->dev.kobj, + &node->sda.dev_attr.attr); + kfree(grp->nodes); + grp->nodes = NULL; +@@ -1133,7 +1212,8 @@ static void applesmc_destroy_nodes(struct applesmc_node_group *groups) + /* + * applesmc_create_nodes - create a two-dimensional group of sysfs files + */ +-static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) ++static int applesmc_create_nodes(struct applesmc_device *smc, ++ struct applesmc_node_group *groups, int num) + { + struct applesmc_node_group *grp; + struct applesmc_dev_attr *node; +@@ -1157,7 +1237,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) + sysfs_attr_init(attr); + attr->name = node->name; + attr->mode = 0444 | (grp->store ? 0200 : 0); +- ret = sysfs_create_file(&pdev->dev.kobj, attr); ++ ret = sysfs_create_file(&smc->dev->dev.kobj, attr); + if (ret) { + attr->name = NULL; + goto out; +@@ -1167,57 +1247,57 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) + + return 0; + out: +- applesmc_destroy_nodes(groups); ++ applesmc_destroy_nodes(smc, groups); + return ret; + } + + /* Create accelerometer resources */ +-static int applesmc_create_accelerometer(void) ++static int applesmc_create_accelerometer(struct applesmc_device *smc) + { + int ret; + +- if (!smcreg.has_accelerometer) ++ if (!smc->reg.has_accelerometer) + return 0; + +- ret = applesmc_create_nodes(accelerometer_group, 1); ++ ret = applesmc_create_nodes(smc, accelerometer_group, 1); + if (ret) + goto out; + +- applesmc_idev = input_allocate_device(); +- if (!applesmc_idev) { ++ smc->idev = input_allocate_device(); ++ if (!smc->idev) { + ret = -ENOMEM; + goto out_sysfs; + } + + /* initial calibrate for the input device */ +- applesmc_calibrate(); ++ applesmc_calibrate(smc); + + /* initialize the input device */ +- applesmc_idev->name = "applesmc"; +- applesmc_idev->id.bustype = BUS_HOST; +- applesmc_idev->dev.parent = &pdev->dev; +- input_set_abs_params(applesmc_idev, ABS_X, ++ smc->idev->name = "applesmc"; ++ smc->idev->id.bustype = BUS_HOST; ++ smc->idev->dev.parent = &smc->dev->dev; ++ input_set_abs_params(smc->idev, ABS_X, + -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); +- input_set_abs_params(applesmc_idev, ABS_Y, ++ input_set_abs_params(smc->idev, ABS_Y, + -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); + +- ret = input_setup_polling(applesmc_idev, applesmc_idev_poll); ++ ret = input_setup_polling(smc->idev, applesmc_idev_poll); + if (ret) + goto out_idev; + +- input_set_poll_interval(applesmc_idev, APPLESMC_POLL_INTERVAL); ++ input_set_poll_interval(smc->idev, APPLESMC_POLL_INTERVAL); + +- ret = input_register_device(applesmc_idev); ++ ret = input_register_device(smc->idev); + if (ret) + goto out_idev; + + return 0; + + out_idev: +- input_free_device(applesmc_idev); ++ input_free_device(smc->idev); + + out_sysfs: +- applesmc_destroy_nodes(accelerometer_group); ++ applesmc_destroy_nodes(smc, accelerometer_group); + + out: + pr_warn("driver init failed (ret=%d)!\n", ret); +@@ -1225,44 +1305,55 @@ static int applesmc_create_accelerometer(void) + } + + /* Release all resources used by the accelerometer */ +-static void applesmc_release_accelerometer(void) ++static void applesmc_release_accelerometer(struct applesmc_device *smc) + { +- if (!smcreg.has_accelerometer) ++ if (!smc->reg.has_accelerometer) + return; +- input_unregister_device(applesmc_idev); +- applesmc_destroy_nodes(accelerometer_group); ++ input_unregister_device(smc->idev); ++ applesmc_destroy_nodes(smc, accelerometer_group); + } + +-static int applesmc_create_light_sensor(void) ++static int applesmc_create_light_sensor(struct applesmc_device *smc) + { +- if (!smcreg.num_light_sensors) ++ if (!smc->reg.num_light_sensors) + return 0; +- return applesmc_create_nodes(light_sensor_group, 1); ++ return applesmc_create_nodes(smc, light_sensor_group, 1); + } + +-static void applesmc_release_light_sensor(void) ++static void applesmc_release_light_sensor(struct applesmc_device *smc) + { +- if (!smcreg.num_light_sensors) ++ if (!smc->reg.num_light_sensors) + return; +- applesmc_destroy_nodes(light_sensor_group); ++ applesmc_destroy_nodes(smc, light_sensor_group); + } + +-static int applesmc_create_key_backlight(void) ++static int applesmc_create_key_backlight(struct applesmc_device *smc) + { +- if (!smcreg.has_key_backlight) ++ int ret; ++ ++ if (!smc->reg.has_key_backlight) + return 0; +- applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); +- if (!applesmc_led_wq) ++ smc->backlight_wq = create_singlethread_workqueue("applesmc-led"); ++ if (!smc->backlight_wq) + return -ENOMEM; +- return led_classdev_register(&pdev->dev, &applesmc_backlight); ++ ++ INIT_WORK(&smc->backlight_work, applesmc_backlight_set); ++ smc->backlight_dev.name = "smc::kbd_backlight"; ++ smc->backlight_dev.default_trigger = "nand-disk"; ++ smc->backlight_dev.brightness_set = applesmc_brightness_set; ++ ret = led_classdev_register(&smc->dev->dev, &smc->backlight_dev); ++ if (ret) ++ destroy_workqueue(smc->backlight_wq); ++ ++ return ret; + } + +-static void applesmc_release_key_backlight(void) ++static void applesmc_release_key_backlight(struct applesmc_device *smc) + { +- if (!smcreg.has_key_backlight) ++ if (!smc->reg.has_key_backlight) + return; +- led_classdev_unregister(&applesmc_backlight); +- destroy_workqueue(applesmc_led_wq); ++ led_classdev_unregister(&smc->backlight_dev); ++ destroy_workqueue(smc->backlight_wq); + } + + static int applesmc_dmi_match(const struct dmi_system_id *id) +@@ -1302,86 +1393,100 @@ static const struct dmi_system_id applesmc_whitelist[] __initconst = { + { .ident = NULL } + }; + +-static int __init applesmc_init(void) ++static int applesmc_create_modules(struct applesmc_device *smc) + { + int ret; + +- if (!dmi_check_system(applesmc_whitelist)) { +- pr_warn("supported laptop not found!\n"); +- ret = -ENODEV; +- goto out; +- } +- +- if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, +- "applesmc")) { +- ret = -ENXIO; +- goto out; +- } +- +- ret = platform_driver_register(&applesmc_driver); +- if (ret) +- goto out_region; +- +- pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, +- NULL, 0); +- if (IS_ERR(pdev)) { +- ret = PTR_ERR(pdev); +- goto out_driver; +- } +- +- /* create register cache */ +- ret = applesmc_init_smcreg(); +- if (ret) +- goto out_device; +- +- ret = applesmc_create_nodes(info_group, 1); ++ ret = applesmc_create_nodes(smc, info_group, 1); + if (ret) +- goto out_smcreg; ++ goto out; + +- ret = applesmc_create_nodes(fan_group, smcreg.fan_count); ++ ret = applesmc_create_nodes(smc, fan_group, smc->reg.fan_count); + if (ret) + goto out_info; + +- ret = applesmc_create_nodes(temp_group, smcreg.index_count); ++ ret = applesmc_create_nodes(smc, temp_group, smc->reg.index_count); + if (ret) + goto out_fans; + +- ret = applesmc_create_accelerometer(); ++ ret = applesmc_create_accelerometer(smc); + if (ret) + goto out_temperature; + +- ret = applesmc_create_light_sensor(); ++ ret = applesmc_create_light_sensor(smc); + if (ret) + goto out_accelerometer; + +- ret = applesmc_create_key_backlight(); ++ ret = applesmc_create_key_backlight(smc); + if (ret) + goto out_light_sysfs; + +- hwmon_dev = hwmon_device_register(&pdev->dev); +- if (IS_ERR(hwmon_dev)) { +- ret = PTR_ERR(hwmon_dev); ++ smc->hwmon_dev = hwmon_device_register(&smc->dev->dev); ++ if (IS_ERR(smc->hwmon_dev)) { ++ ret = PTR_ERR(smc->hwmon_dev); + goto out_light_ledclass; + } + + return 0; + + out_light_ledclass: +- applesmc_release_key_backlight(); ++ applesmc_release_key_backlight(smc); + out_light_sysfs: +- applesmc_release_light_sensor(); ++ applesmc_release_light_sensor(smc); + out_accelerometer: +- applesmc_release_accelerometer(); ++ applesmc_release_accelerometer(smc); + out_temperature: +- applesmc_destroy_nodes(temp_group); ++ applesmc_destroy_nodes(smc, temp_group); + out_fans: +- applesmc_destroy_nodes(fan_group); ++ applesmc_destroy_nodes(smc, fan_group); + out_info: +- applesmc_destroy_nodes(info_group); +-out_smcreg: +- applesmc_destroy_smcreg(); +-out_device: +- platform_device_unregister(pdev); ++ applesmc_destroy_nodes(smc, info_group); ++out: ++ return ret; ++} ++ ++static void applesmc_destroy_modules(struct applesmc_device *smc) ++{ ++ hwmon_device_unregister(smc->hwmon_dev); ++ applesmc_release_key_backlight(smc); ++ applesmc_release_light_sensor(smc); ++ applesmc_release_accelerometer(smc); ++ applesmc_destroy_nodes(smc, temp_group); ++ applesmc_destroy_nodes(smc, fan_group); ++ applesmc_destroy_nodes(smc, info_group); ++} ++ ++static struct platform_device *pdev; ++ ++static int __init applesmc_init(void) ++{ ++ int ret; ++ ++ if (!dmi_check_system(applesmc_whitelist)) { ++ pr_warn("supported laptop not found!\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, ++ "applesmc")) { ++ ret = -ENXIO; ++ goto out; ++ } ++ ++ ret = platform_driver_register(&applesmc_driver); ++ if (ret) ++ goto out_region; ++ ++ pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, ++ NULL, 0); ++ if (IS_ERR(pdev)) { ++ ret = PTR_ERR(pdev); ++ goto out_driver; ++ } ++ ++ return 0; ++ + out_driver: + platform_driver_unregister(&applesmc_driver); + out_region: +@@ -1393,14 +1498,6 @@ static int __init applesmc_init(void) + + static void __exit applesmc_exit(void) + { +- hwmon_device_unregister(hwmon_dev); +- applesmc_release_key_backlight(); +- applesmc_release_light_sensor(); +- applesmc_release_accelerometer(); +- applesmc_destroy_nodes(temp_group); +- applesmc_destroy_nodes(fan_group); +- applesmc_destroy_nodes(info_group); +- applesmc_destroy_smcreg(); + platform_device_unregister(pdev); + platform_driver_unregister(&applesmc_driver); + release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); +@@ -1410,6 +1507,7 @@ module_init(applesmc_init); + module_exit(applesmc_exit); + + MODULE_AUTHOR("Nicolas Boichat"); ++MODULE_AUTHOR("Paul Pawlowski"); + MODULE_DESCRIPTION("Apple SMC"); + MODULE_LICENSE("GPL v2"); + MODULE_DEVICE_TABLE(dmi, applesmc_whitelist); +-- +2.30.0 + diff --git a/3002-applesmc-make-io-port-base-addr-dynamic.patch b/3002-applesmc-make-io-port-base-addr-dynamic.patch new file mode 100644 index 0000000..cc332c7 --- /dev/null +++ b/3002-applesmc-make-io-port-base-addr-dynamic.patch @@ -0,0 +1,312 @@ +From 713e78b8dbb8adb92d4ee09ea11e726b05577689 Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sun, 17 Nov 2019 23:11:56 +0100 +Subject: [PATCH 2/6] applesmc: make io port base addr dynamic + +This change makes the port base runtime configurable. +The reason why this change is made is so that when we switch to an +acpi_device we can resolve the port base addr from ACPI. + +This change is not strictly required for T2 support - the base +address is still 0x300 on T2 Macs. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 91 +++++++++++++++++++++------------------- + 1 file changed, 49 insertions(+), 42 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index 62211b590a61..39ed0bb21365 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -35,10 +35,11 @@ + #include + #include + ++#define APPLESMC_PORT_BASE 0x300 + /* data port used by Apple SMC */ +-#define APPLESMC_DATA_PORT 0x300 ++#define APPLESMC_DATA_PORT 0 + /* command/status port used by Apple SMC */ +-#define APPLESMC_CMD_PORT 0x304 ++#define APPLESMC_CMD_PORT 4 + + #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */ + +@@ -140,6 +141,8 @@ struct applesmc_device { + struct platform_device *dev; + struct applesmc_registers reg; + ++ u16 port_base; ++ + s16 rest_x; + s16 rest_y; + +@@ -169,7 +172,7 @@ static const int debug; + * run out past 500ms. + */ + +-static int wait_status(u8 val, u8 mask) ++static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) + { + u8 status; + int us; +@@ -177,7 +180,7 @@ static int wait_status(u8 val, u8 mask) + + us = APPLESMC_MIN_WAIT; + for (i = 0; i < 24 ; i++) { +- status = inb(APPLESMC_CMD_PORT); ++ status = inb(smc->port_base + APPLESMC_CMD_PORT); + if ((status & mask) == val) + return 0; + usleep_range(us, us * 2); +@@ -189,11 +192,11 @@ static int wait_status(u8 val, u8 mask) + + /* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ + +-static int send_byte(u8 cmd, u16 port) ++static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) + { + int status; + +- status = wait_status(0, SMC_STATUS_IB_CLOSED); ++ status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); + if (status) + return status; + /* +@@ -202,24 +205,24 @@ static int send_byte(u8 cmd, u16 port) + * this extra read may not happen if status returns both + * simultaneously and this would appear to be required. + */ +- status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY); ++ status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); + if (status) + return status; + +- outb(cmd, port); ++ outb(cmd, smc->port_base + port); + return 0; + } + + /* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ + +-static int send_command(u8 cmd) ++static int send_command(struct applesmc_device *smc, u8 cmd) + { + int ret; + +- ret = wait_status(0, SMC_STATUS_IB_CLOSED); ++ ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); + if (ret) + return ret; +- outb(cmd, APPLESMC_CMD_PORT); ++ outb(cmd, smc->port_base + APPLESMC_CMD_PORT); + return 0; + } + +@@ -229,108 +232,112 @@ static int send_command(u8 cmd) + * If busy is stuck high after the command then the SMC is jammed. + */ + +-static int smc_sane(void) ++static int smc_sane(struct applesmc_device *smc) + { + int ret; + +- ret = wait_status(0, SMC_STATUS_BUSY); ++ ret = wait_status(smc, 0, SMC_STATUS_BUSY); + if (!ret) + return ret; +- ret = send_command(APPLESMC_READ_CMD); ++ ret = send_command(smc, APPLESMC_READ_CMD); + if (ret) + return ret; +- return wait_status(0, SMC_STATUS_BUSY); ++ return wait_status(smc, 0, SMC_STATUS_BUSY); + } + +-static int send_argument(const char *key) ++static int send_argument(struct applesmc_device *smc, const char *key) + { + int i; + + for (i = 0; i < 4; i++) +- if (send_byte(key[i], APPLESMC_DATA_PORT)) ++ if (send_byte(smc, key[i], APPLESMC_DATA_PORT)) + return -EIO; + return 0; + } + +-static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) ++static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++ u8 *buffer, u8 len) + { + u8 status, data = 0; + int i; + int ret; + +- ret = smc_sane(); ++ ret = smc_sane(smc); + if (ret) + return ret; + +- if (send_command(cmd) || send_argument(key)) { ++ if (send_command(smc, cmd) || send_argument(smc, key)) { + pr_warn("%.4s: read arg fail\n", key); + return -EIO; + } + + /* This has no effect on newer (2012) SMCs */ +- if (send_byte(len, APPLESMC_DATA_PORT)) { ++ if (send_byte(smc, len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: read len fail\n", key); + return -EIO; + } + + for (i = 0; i < len; i++) { +- if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, ++ if (wait_status(smc, ++ SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, + SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) { + pr_warn("%.4s: read data[%d] fail\n", key, i); + return -EIO; + } +- buffer[i] = inb(APPLESMC_DATA_PORT); ++ buffer[i] = inb(smc->port_base + APPLESMC_DATA_PORT); + } + + /* Read the data port until bit0 is cleared */ + for (i = 0; i < 16; i++) { + udelay(APPLESMC_MIN_WAIT); +- status = inb(APPLESMC_CMD_PORT); ++ status = inb(smc->port_base + APPLESMC_CMD_PORT); + if (!(status & SMC_STATUS_AWAITING_DATA)) + break; +- data = inb(APPLESMC_DATA_PORT); ++ data = inb(smc->port_base + APPLESMC_DATA_PORT); + } + if (i) + pr_warn("flushed %d bytes, last value is: %d\n", i, data); + +- return wait_status(0, SMC_STATUS_BUSY); ++ return wait_status(smc, 0, SMC_STATUS_BUSY); + } + +-static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) ++static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++ const u8 *buffer, u8 len) + { + int i; + int ret; + +- ret = smc_sane(); ++ ret = smc_sane(smc); + if (ret) + return ret; + +- if (send_command(cmd) || send_argument(key)) { ++ if (send_command(smc, cmd) || send_argument(smc, key)) { + pr_warn("%s: write arg fail\n", key); + return -EIO; + } + +- if (send_byte(len, APPLESMC_DATA_PORT)) { ++ if (send_byte(smc, len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: write len fail\n", key); + return -EIO; + } + + for (i = 0; i < len; i++) { +- if (send_byte(buffer[i], APPLESMC_DATA_PORT)) { ++ if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { + pr_warn("%s: write data fail\n", key); + return -EIO; + } + } + +- return wait_status(0, SMC_STATUS_BUSY); ++ return wait_status(smc, 0, SMC_STATUS_BUSY); + } + +-static int read_register_count(unsigned int *count) ++static int read_register_count(struct applesmc_device *smc, ++ unsigned int *count) + { + __be32 be; + int ret; + +- ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); ++ ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); + if (ret) + return ret; + +@@ -353,7 +360,7 @@ static int applesmc_read_entry(struct applesmc_device *smc, + if (entry->len != len) + return -EINVAL; + mutex_lock(&smc->reg.mutex); +- ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); ++ ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len); + mutex_unlock(&smc->reg.mutex); + + return ret; +@@ -367,7 +374,7 @@ static int applesmc_write_entry(struct applesmc_device *smc, + if (entry->len != len) + return -EINVAL; + mutex_lock(&smc->reg.mutex); +- ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); ++ ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len); + mutex_unlock(&smc->reg.mutex); + return ret; + } +@@ -388,10 +395,10 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( + if (cache->valid) + goto out; + be = cpu_to_be32(index); +- ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); ++ ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); + if (ret) + goto out; +- ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); ++ ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); + if (ret) + goto out; + +@@ -589,7 +596,7 @@ static int applesmc_init_smcreg_try(struct applesmc_device *smc) + if (s->init_complete) + return 0; + +- ret = read_register_count(&count); ++ ret = read_register_count(smc, &count); + if (ret) + return ret; + +@@ -1468,7 +1475,7 @@ static int __init applesmc_init(void) + goto out; + } + +- if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, ++ if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS, + "applesmc")) { + ret = -ENXIO; + goto out; +@@ -1490,7 +1497,7 @@ static int __init applesmc_init(void) + out_driver: + platform_driver_unregister(&applesmc_driver); + out_region: +- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); ++ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); + out: + pr_warn("driver init failed (ret=%d)!\n", ret); + return ret; +@@ -1500,7 +1507,7 @@ static void __exit applesmc_exit(void) + { + platform_device_unregister(pdev); + platform_driver_unregister(&applesmc_driver); +- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); ++ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); + } + + module_init(applesmc_init); +-- +2.30.0 + diff --git a/3003-applesmc-switch-to-acpi_device-from-platform.patch b/3003-applesmc-switch-to-acpi_device-from-platform.patch new file mode 100644 index 0000000..f8f7f82 --- /dev/null +++ b/3003-applesmc-switch-to-acpi_device-from-platform.patch @@ -0,0 +1,267 @@ +From ee3d4bf4a01bc94553bde2ae3e806a63a13faa12 Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sun, 17 Nov 2019 23:12:08 +0100 +Subject: [PATCH 3/6] applesmc: switch to acpi_device (from platform) + +This change makes the change from platform_device +to acpi_device. The rationale for this change is +that on T2 Macs, an additional FixedMemory32 +region is needed for device operation, and it can +be easily resolved via ACPI tables (this will be +done in another commit). + +Additionally, on older Macs, the OS X driver also +looks for the specified ACPI device to resolve +its memory regions, and therefore this change +should not result in any incompatibilities. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 125 ++++++++++++++++++++++++++------------- + 1 file changed, 85 insertions(+), 40 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index 39ed0bb21365..bdaaf696f7b6 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -19,7 +19,7 @@ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +-#include ++#include + #include + #include + #include +@@ -35,7 +35,6 @@ + #include + #include + +-#define APPLESMC_PORT_BASE 0x300 + /* data port used by Apple SMC */ + #define APPLESMC_DATA_PORT 0 + /* command/status port used by Apple SMC */ +@@ -138,9 +137,10 @@ struct applesmc_registers { + }; + + struct applesmc_device { +- struct platform_device *dev; ++ struct acpi_device *dev; + struct applesmc_registers reg; + ++ bool port_base_set; + u16 port_base; + + s16 rest_x; +@@ -692,9 +692,13 @@ static int applesmc_init_smcreg(struct applesmc_device *smc) + } + + /* Device model stuff */ ++ ++static int applesmc_init_resources(struct applesmc_device *smc); ++static void applesmc_free_resources(struct applesmc_device *smc); + static int applesmc_create_modules(struct applesmc_device *smc); + static void applesmc_destroy_modules(struct applesmc_device *smc); +-static int applesmc_probe(struct platform_device *dev) ++ ++static int applesmc_add(struct acpi_device *dev) + { + struct applesmc_device *smc; + int ret; +@@ -705,12 +709,16 @@ static int applesmc_probe(struct platform_device *dev) + smc->dev = dev; + mutex_init(&smc->reg.mutex); + +- platform_set_drvdata(dev, smc); ++ dev_set_drvdata(&dev->dev, smc); + +- ret = applesmc_init_smcreg(smc); ++ ret = applesmc_init_resources(smc); + if (ret) + goto out_mem; + ++ ret = applesmc_init_smcreg(smc); ++ if (ret) ++ goto out_res; ++ + applesmc_device_init(smc); + + ret = applesmc_create_modules(smc); +@@ -721,20 +729,23 @@ static int applesmc_probe(struct platform_device *dev) + + out_reg: + applesmc_destroy_smcreg(smc); ++out_res: ++ applesmc_free_resources(smc); + out_mem: +- platform_set_drvdata(dev, NULL); ++ dev_set_drvdata(&dev->dev, NULL); + mutex_destroy(&smc->reg.mutex); + kfree(smc); + + return ret; + } + +-static int applesmc_remove(struct platform_device *dev) ++static int applesmc_remove(struct acpi_device *dev) + { +- struct applesmc_device *smc = platform_get_drvdata(dev); ++ struct applesmc_device *smc = dev_get_drvdata(&dev->dev); + + applesmc_destroy_modules(smc); + applesmc_destroy_smcreg(smc); ++ applesmc_free_resources(smc); + + mutex_destroy(&smc->reg.mutex); + kfree(smc); +@@ -742,6 +753,52 @@ static int applesmc_remove(struct platform_device *dev) + return 0; + } + ++static acpi_status applesmc_walk_resources(struct acpi_resource *res, ++ void *data) ++{ ++ struct applesmc_device *smc = data; ++ ++ switch (res->type) { ++ case ACPI_RESOURCE_TYPE_IO: ++ if (!smc->port_base_set) { ++ if (res->data.io.address_length < APPLESMC_NR_PORTS) ++ return AE_ERROR; ++ smc->port_base = res->data.io.minimum; ++ smc->port_base_set = true; ++ } ++ return AE_OK; ++ ++ case ACPI_RESOURCE_TYPE_END_TAG: ++ if (smc->port_base_set) ++ return AE_OK; ++ else ++ return AE_NOT_FOUND; ++ ++ default: ++ return AE_OK; ++ } ++} ++ ++static int applesmc_init_resources(struct applesmc_device *smc) ++{ ++ int ret; ++ ++ ret = acpi_walk_resources(smc->dev->handle, METHOD_NAME__CRS, ++ applesmc_walk_resources, smc); ++ if (ACPI_FAILURE(ret)) ++ return -ENXIO; ++ ++ if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc")) ++ return -ENXIO; ++ ++ return 0; ++} ++ ++static void applesmc_free_resources(struct applesmc_device *smc) ++{ ++ release_region(smc->port_base, APPLESMC_NR_PORTS); ++} ++ + /* Synchronize device with memorized backlight state */ + static int applesmc_pm_resume(struct device *dev) + { +@@ -763,18 +820,28 @@ static int applesmc_pm_restore(struct device *dev) + return applesmc_pm_resume(dev); + } + ++static const struct acpi_device_id applesmc_ids[] = { ++ {"APP0001", 0}, ++ {"", 0}, ++}; ++ + static const struct dev_pm_ops applesmc_pm_ops = { + .resume = applesmc_pm_resume, + .restore = applesmc_pm_restore, + }; + +-static struct platform_driver applesmc_driver = { +- .probe = applesmc_probe, +- .remove = applesmc_remove, +- .driver = { +- .name = "applesmc", +- .pm = &applesmc_pm_ops, ++static struct acpi_driver applesmc_driver = { ++ .name = "applesmc", ++ .class = "applesmc", ++ .ids = applesmc_ids, ++ .ops = { ++ .add = applesmc_add, ++ .remove = applesmc_remove + }, ++ .drv = { ++ .pm = &applesmc_pm_ops ++ }, ++ .owner = THIS_MODULE + }; + + /* +@@ -1262,7 +1329,6 @@ static int applesmc_create_nodes(struct applesmc_device *smc, + static int applesmc_create_accelerometer(struct applesmc_device *smc) + { + int ret; +- + if (!smc->reg.has_accelerometer) + return 0; + +@@ -1463,8 +1529,6 @@ static void applesmc_destroy_modules(struct applesmc_device *smc) + applesmc_destroy_nodes(smc, info_group); + } + +-static struct platform_device *pdev; +- + static int __init applesmc_init(void) + { + int ret; +@@ -1475,29 +1539,12 @@ static int __init applesmc_init(void) + goto out; + } + +- if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS, +- "applesmc")) { +- ret = -ENXIO; +- goto out; +- } +- +- ret = platform_driver_register(&applesmc_driver); ++ ret = acpi_bus_register_driver(&applesmc_driver); + if (ret) +- goto out_region; +- +- pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, +- NULL, 0); +- if (IS_ERR(pdev)) { +- ret = PTR_ERR(pdev); +- goto out_driver; +- } ++ goto out; + + return 0; + +-out_driver: +- platform_driver_unregister(&applesmc_driver); +-out_region: +- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); + out: + pr_warn("driver init failed (ret=%d)!\n", ret); + return ret; +@@ -1505,9 +1552,7 @@ static int __init applesmc_init(void) + + static void __exit applesmc_exit(void) + { +- platform_device_unregister(pdev); +- platform_driver_unregister(&applesmc_driver); +- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); ++ acpi_bus_unregister_driver(&applesmc_driver); + } + + module_init(applesmc_init); +-- +2.30.0 + diff --git a/3004-applesmc-key-interface-wrappers.patch b/3004-applesmc-key-interface-wrappers.patch new file mode 100644 index 0000000..eeea1c2 --- /dev/null +++ b/3004-applesmc-key-interface-wrappers.patch @@ -0,0 +1,298 @@ +From 43df89a1377782788760808d8ea4bcf0730effbb Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sun, 17 Nov 2019 23:12:14 +0100 +Subject: [PATCH 4/6] applesmc: key interface wrappers + +This change replaces the read_smc and write_smc +methods with wrappers, additionally removing the +command id parameter from them (and introducing +get_smc_key_by_index and get_smc_key_info). + +This is done as to allow simple implementation +replacement on T2 Macs. The newly introduced +methods mentioned in the previous paragraph need +special handling on T2 and as such had to be +separated. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 119 ++++++++++++++++++++++++++------------- + 1 file changed, 79 insertions(+), 40 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index bdaaf696f7b6..3017d8ca2c79 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -172,7 +172,7 @@ static const int debug; + * run out past 500ms. + */ + +-static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) ++static int port_wait_status(struct applesmc_device *smc, u8 val, u8 mask) + { + u8 status; + int us; +@@ -190,13 +190,13 @@ static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) + return -EIO; + } + +-/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ ++/* port_send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ + +-static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) ++static int port_send_byte(struct applesmc_device *smc, u8 cmd, u16 port) + { + int status; + +- status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); ++ status = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED); + if (status) + return status; + /* +@@ -205,7 +205,7 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) + * this extra read may not happen if status returns both + * simultaneously and this would appear to be required. + */ +- status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); ++ status = port_wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); + if (status) + return status; + +@@ -213,15 +213,16 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) + return 0; + } + +-/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ ++/* port_send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ + +-static int send_command(struct applesmc_device *smc, u8 cmd) ++static int port_send_command(struct applesmc_device *smc, u8 cmd) + { + int ret; + +- ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); ++ ret = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED); + if (ret) + return ret; ++ + outb(cmd, smc->port_base + APPLESMC_CMD_PORT); + return 0; + } +@@ -232,53 +233,53 @@ static int send_command(struct applesmc_device *smc, u8 cmd) + * If busy is stuck high after the command then the SMC is jammed. + */ + +-static int smc_sane(struct applesmc_device *smc) ++static int port_smc_sane(struct applesmc_device *smc) + { + int ret; + +- ret = wait_status(smc, 0, SMC_STATUS_BUSY); ++ ret = port_wait_status(smc, 0, SMC_STATUS_BUSY); + if (!ret) + return ret; +- ret = send_command(smc, APPLESMC_READ_CMD); ++ ret = port_send_command(smc, APPLESMC_READ_CMD); + if (ret) + return ret; +- return wait_status(smc, 0, SMC_STATUS_BUSY); ++ return port_wait_status(smc, 0, SMC_STATUS_BUSY); + } + +-static int send_argument(struct applesmc_device *smc, const char *key) ++static int port_send_argument(struct applesmc_device *smc, const char *key) + { + int i; + + for (i = 0; i < 4; i++) +- if (send_byte(smc, key[i], APPLESMC_DATA_PORT)) ++ if (port_send_byte(smc, key[i], APPLESMC_DATA_PORT)) + return -EIO; + return 0; + } + +-static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++static int port_read_smc(struct applesmc_device *smc, u8 cmd, const char *key, + u8 *buffer, u8 len) + { + u8 status, data = 0; + int i; + int ret; + +- ret = smc_sane(smc); ++ ret = port_smc_sane(smc); + if (ret) + return ret; + +- if (send_command(smc, cmd) || send_argument(smc, key)) { ++ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) { + pr_warn("%.4s: read arg fail\n", key); + return -EIO; + } + + /* This has no effect on newer (2012) SMCs */ +- if (send_byte(smc, len, APPLESMC_DATA_PORT)) { ++ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: read len fail\n", key); + return -EIO; + } + + for (i = 0; i < len; i++) { +- if (wait_status(smc, ++ if (port_wait_status(smc, + SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, + SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) { + pr_warn("%.4s: read data[%d] fail\n", key, i); +@@ -298,37 +299,80 @@ static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, + if (i) + pr_warn("flushed %d bytes, last value is: %d\n", i, data); + +- return wait_status(smc, 0, SMC_STATUS_BUSY); ++ return port_wait_status(smc, 0, SMC_STATUS_BUSY); + } + +-static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++static int port_write_smc(struct applesmc_device *smc, u8 cmd, const char *key, + const u8 *buffer, u8 len) + { + int i; + int ret; + +- ret = smc_sane(smc); ++ ret = port_smc_sane(smc); + if (ret) + return ret; + +- if (send_command(smc, cmd) || send_argument(smc, key)) { ++ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) { + pr_warn("%s: write arg fail\n", key); + return -EIO; + } + +- if (send_byte(smc, len, APPLESMC_DATA_PORT)) { ++ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: write len fail\n", key); + return -EIO; + } + + for (i = 0; i < len; i++) { +- if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { ++ if (port_send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { + pr_warn("%s: write data fail\n", key); + return -EIO; + } + } + +- return wait_status(smc, 0, SMC_STATUS_BUSY); ++ return port_wait_status(smc, 0, SMC_STATUS_BUSY); ++} ++ ++static int port_get_smc_key_info(struct applesmc_device *smc, ++ const char *key, struct applesmc_entry *info) ++{ ++ int ret; ++ u8 raw[6]; ++ ++ ret = port_read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, raw, 6); ++ if (ret) ++ return ret; ++ info->len = raw[0]; ++ memcpy(info->type, &raw[1], 4); ++ info->flags = raw[5]; ++ return 0; ++} ++ ++static int read_smc(struct applesmc_device *smc, const char *key, ++ u8 *buffer, u8 len) ++{ ++ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); ++} ++ ++static int write_smc(struct applesmc_device *smc, const char *key, ++ const u8 *buffer, u8 len) ++{ ++ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); ++} ++ ++static int get_smc_key_by_index(struct applesmc_device *smc, ++ unsigned int index, char *key) ++{ ++ __be32 be; ++ ++ be = cpu_to_be32(index); ++ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, ++ (const char *) &be, (u8 *) key, 4); ++} ++ ++static int get_smc_key_info(struct applesmc_device *smc, const char *key, ++ struct applesmc_entry *info) ++{ ++ return port_get_smc_key_info(smc, key, info); + } + + static int read_register_count(struct applesmc_device *smc, +@@ -337,8 +381,8 @@ static int read_register_count(struct applesmc_device *smc, + __be32 be; + int ret; + +- ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); +- if (ret) ++ ret = read_smc(smc, KEY_COUNT_KEY, (u8 *)&be, 4); ++ if (ret < 0) + return ret; + + *count = be32_to_cpu(be); +@@ -360,7 +404,7 @@ static int applesmc_read_entry(struct applesmc_device *smc, + if (entry->len != len) + return -EINVAL; + mutex_lock(&smc->reg.mutex); +- ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len); ++ ret = read_smc(smc, entry->key, buf, len); + mutex_unlock(&smc->reg.mutex); + + return ret; +@@ -374,7 +418,7 @@ static int applesmc_write_entry(struct applesmc_device *smc, + if (entry->len != len) + return -EINVAL; + mutex_lock(&smc->reg.mutex); +- ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len); ++ ret = write_smc(smc, entry->key, buf, len); + mutex_unlock(&smc->reg.mutex); + return ret; + } +@@ -383,8 +427,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( + struct applesmc_device *smc, int index) + { + struct applesmc_entry *cache = &smc->reg.cache[index]; +- u8 key[4], info[6]; +- __be32 be; ++ char key[4]; + int ret = 0; + + if (cache->valid) +@@ -394,18 +437,14 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( + + if (cache->valid) + goto out; +- be = cpu_to_be32(index); +- ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); ++ ret = get_smc_key_by_index(smc, index, key); + if (ret) + goto out; +- ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); ++ memcpy(cache->key, key, 4); ++ ++ ret = get_smc_key_info(smc, key, cache); + if (ret) + goto out; +- +- memcpy(cache->key, key, 4); +- cache->len = info[0]; +- memcpy(cache->type, &info[1], 4); +- cache->flags = info[5]; + cache->valid = true; + + out: +-- +2.30.0 + diff --git a/3005-applesmc-basic-mmio-interface-implementation.patch b/3005-applesmc-basic-mmio-interface-implementation.patch new file mode 100644 index 0000000..c370d05 --- /dev/null +++ b/3005-applesmc-basic-mmio-interface-implementation.patch @@ -0,0 +1,343 @@ +From 799e7a54c62a36007f7874c58d7dac87c9651759 Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 17 Nov 2019 23:12:16 +0100 +Subject: [PATCH 5/6] applesmc: basic mmio interface implementation + +This change introduces a basic MMIO-based +interface implementation required to communicate +with the SMC on T2 Macs. The MMIO interface is +enabled only when it's supported on the running +system. + +The MMIO interface replaces legacy port-based SMC +key reads, writes and metadata requests (getting +key by index and getting key info). + +(Based on patch by @mcmrarm) + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 237 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 231 insertions(+), 6 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index 3017d8ca2c79..2d23bb9ad9dd 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -42,6 +42,18 @@ + + #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */ + ++#define APPLESMC_IOMEM_KEY_DATA 0 ++#define APPLESMC_IOMEM_KEY_STATUS 0x4005 ++#define APPLESMC_IOMEM_KEY_NAME 0x78 ++#define APPLESMC_IOMEM_KEY_DATA_LEN 0x7D ++#define APPLESMC_IOMEM_KEY_SMC_ID 0x7E ++#define APPLESMC_IOMEM_KEY_CMD 0x7F ++#define APPLESMC_IOMEM_MIN_SIZE 0x4006 ++ ++#define APPLESMC_IOMEM_KEY_TYPE_CODE 0 ++#define APPLESMC_IOMEM_KEY_TYPE_DATA_LEN 5 ++#define APPLESMC_IOMEM_KEY_TYPE_FLAGS 6 ++ + #define APPLESMC_MAX_DATA_LENGTH 32 + + /* Apple SMC status bits */ +@@ -138,10 +150,13 @@ struct applesmc_registers { + + struct applesmc_device { + struct acpi_device *dev; ++ struct device *ldev; + struct applesmc_registers reg; + +- bool port_base_set; ++ bool port_base_set, iomem_base_set; + u16 port_base; ++ u8 *__iomem iomem_base; ++ u32 iomem_base_addr, iomem_base_size; + + s16 rest_x; + s16 rest_y; +@@ -347,16 +362,156 @@ static int port_get_smc_key_info(struct applesmc_device *smc, + return 0; + } + ++ ++/* ++ * MMIO based communication. ++ * TODO: Use updated mechanism for cmd timeout/retry ++ */ ++ ++static void iomem_clear_status(struct applesmc_device *smc) ++{ ++ if (ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS)) ++ iowrite8(0, smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); ++} ++ ++static int iomem_wait_read(struct applesmc_device *smc) ++{ ++ u8 status; ++ int us; ++ int i; ++ ++ us = APPLESMC_MIN_WAIT; ++ for (i = 0; i < 24 ; i++) { ++ status = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); ++ if (status & 0x20) ++ return 0; ++ usleep_range(us, us * 2); ++ if (i > 9) ++ us <<= 1; ++ } ++ ++ dev_warn(smc->ldev, "%s... timeout\n", __func__); ++ return -EIO; ++} ++ ++static int iomem_read_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++ u8 *buffer, u8 len) ++{ ++ u8 err, remote_len; ++ u32 key_int = *((u32 *) key); ++ ++ iomem_clear_status(smc); ++ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); ++ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); ++ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ ++ if (iomem_wait_read(smc)) ++ return -EIO; ++ ++ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ if (err != 0) { ++ dev_warn(smc->ldev, "read_smc_mmio(%x %8x/%.4s) failed: %u\n", ++ cmd, key_int, key, err); ++ return -EIO; ++ } ++ ++ if (cmd == APPLESMC_READ_CMD) { ++ remote_len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN); ++ if (remote_len != len) { ++ dev_warn(smc->ldev, ++ "read_smc_mmio(%x %8x/%.4s) failed: buffer length mismatch (remote = %u, requested = %u)\n", ++ cmd, key_int, key, remote_len, len); ++ return -EINVAL; ++ } ++ } else { ++ remote_len = len; ++ } ++ ++ memcpy_fromio(buffer, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, ++ remote_len); ++ ++ dev_dbg(smc->ldev, "read_smc_mmio(%x %8x/%.4s): buflen=%u reslen=%u\n", ++ cmd, key_int, key, len, remote_len); ++ print_hex_dump_bytes("read_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, remote_len); ++ return 0; ++} ++ ++static int iomem_get_smc_key_type(struct applesmc_device *smc, const char *key, ++ struct applesmc_entry *e) ++{ ++ u8 err; ++ u8 cmd = APPLESMC_GET_KEY_TYPE_CMD; ++ u32 key_int = *((u32 *) key); ++ ++ iomem_clear_status(smc); ++ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); ++ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); ++ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ ++ if (iomem_wait_read(smc)) ++ return -EIO; ++ ++ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ if (err != 0) { ++ dev_warn(smc->ldev, "get_smc_key_type_mmio(%.4s) failed: %u\n", key, err); ++ return -EIO; ++ } ++ ++ e->len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_DATA_LEN); ++ *((uint32_t *) e->type) = ioread32( ++ smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_CODE); ++ e->flags = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_FLAGS); ++ ++ dev_dbg(smc->ldev, "get_smc_key_type_mmio(%.4s): len=%u type=%.4s flags=%x\n", ++ key, e->len, e->type, e->flags); ++ return 0; ++} ++ ++static int iomem_write_smc(struct applesmc_device *smc, u8 cmd, const char *key, ++ const u8 *buffer, u8 len) ++{ ++ u8 err; ++ u32 key_int = *((u32 *) key); ++ ++ iomem_clear_status(smc); ++ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); ++ memcpy_toio(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, buffer, len); ++ iowrite32(len, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN); ++ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); ++ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ ++ if (iomem_wait_read(smc)) ++ return -EIO; ++ ++ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); ++ if (err != 0) { ++ dev_warn(smc->ldev, "write_smc_mmio(%x %.4s) failed: %u\n", cmd, key, err); ++ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len); ++ return -EIO; ++ } ++ ++ dev_dbg(smc->ldev, "write_smc_mmio(%x %.4s): buflen=%u\n", cmd, key, len); ++ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len); ++ return 0; ++} ++ ++ + static int read_smc(struct applesmc_device *smc, const char *key, + u8 *buffer, u8 len) + { +- return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); ++ if (smc->iomem_base_set) ++ return iomem_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); ++ else ++ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); + } + + static int write_smc(struct applesmc_device *smc, const char *key, + const u8 *buffer, u8 len) + { +- return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); ++ if (smc->iomem_base_set) ++ return iomem_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); ++ else ++ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); + } + + static int get_smc_key_by_index(struct applesmc_device *smc, +@@ -365,14 +520,21 @@ static int get_smc_key_by_index(struct applesmc_device *smc, + __be32 be; + + be = cpu_to_be32(index); +- return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, +- (const char *) &be, (u8 *) key, 4); ++ if (smc->iomem_base_set) ++ return iomem_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, ++ (const char *) &be, (u8 *) key, 4); ++ else ++ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, ++ (const char *) &be, (u8 *) key, 4); + } + + static int get_smc_key_info(struct applesmc_device *smc, const char *key, + struct applesmc_entry *info) + { +- return port_get_smc_key_info(smc, key, info); ++ if (smc->iomem_base_set) ++ return iomem_get_smc_key_type(smc, key, info); ++ else ++ return port_get_smc_key_info(smc, key, info); + } + + static int read_register_count(struct applesmc_device *smc, +@@ -746,6 +908,7 @@ static int applesmc_add(struct acpi_device *dev) + if (!smc) + return -ENOMEM; + smc->dev = dev; ++ smc->ldev = &dev->dev; + mutex_init(&smc->reg.mutex); + + dev_set_drvdata(&dev->dev, smc); +@@ -807,6 +970,20 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res, + } + return AE_OK; + ++ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: ++ if (!smc->iomem_base_set) { ++ if (res->data.fixed_memory32.address_length < ++ APPLESMC_IOMEM_MIN_SIZE) { ++ dev_warn(smc->ldev, "found iomem but it's too small: %u\n", ++ res->data.fixed_memory32.address_length); ++ return AE_OK; ++ } ++ smc->iomem_base_addr = res->data.fixed_memory32.address; ++ smc->iomem_base_size = res->data.fixed_memory32.address_length; ++ smc->iomem_base_set = true; ++ } ++ return AE_OK; ++ + case ACPI_RESOURCE_TYPE_END_TAG: + if (smc->port_base_set) + return AE_OK; +@@ -818,6 +995,8 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res, + } + } + ++static int applesmc_try_enable_iomem(struct applesmc_device *smc); ++ + static int applesmc_init_resources(struct applesmc_device *smc) + { + int ret; +@@ -830,11 +1009,57 @@ static int applesmc_init_resources(struct applesmc_device *smc) + if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc")) + return -ENXIO; + ++ if (smc->iomem_base_set) { ++ if (applesmc_try_enable_iomem(smc)) ++ smc->iomem_base_set = false; ++ } ++ + return 0; + } + ++static int applesmc_try_enable_iomem(struct applesmc_device *smc) ++{ ++ u8 test_val, ldkn_version; ++ ++ dev_dbg(smc->ldev, "Trying to enable iomem based communication\n"); ++ smc->iomem_base = ioremap(smc->iomem_base_addr, smc->iomem_base_size); ++ if (!smc->iomem_base) ++ goto out; ++ ++ /* Apple's driver does this check for some reason */ ++ test_val = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); ++ if (test_val == 0xff) { ++ dev_warn(smc->ldev, ++ "iomem enable failed: initial status is 0xff (is %x)\n", ++ test_val); ++ goto out_iomem; ++ } ++ ++ if (read_smc(smc, "LDKN", &ldkn_version, 1)) { ++ dev_warn(smc->ldev, "iomem enable failed: ldkn read failed\n"); ++ goto out_iomem; ++ } ++ ++ if (ldkn_version < 2) { ++ dev_warn(smc->ldev, ++ "iomem enable failed: ldkn version %u is less than minimum (2)\n", ++ ldkn_version); ++ goto out_iomem; ++ } ++ ++ return 0; ++ ++out_iomem: ++ iounmap(smc->iomem_base); ++ ++out: ++ return -ENXIO; ++} ++ + static void applesmc_free_resources(struct applesmc_device *smc) + { ++ if (smc->iomem_base_set) ++ iounmap(smc->iomem_base); + release_region(smc->port_base, APPLESMC_NR_PORTS); + } + +-- +2.30.0 + diff --git a/3006-applesmc-fan-support-on-T2-Macs.patch b/3006-applesmc-fan-support-on-T2-Macs.patch new file mode 100644 index 0000000..31b8205 --- /dev/null +++ b/3006-applesmc-fan-support-on-T2-Macs.patch @@ -0,0 +1,227 @@ +From 4e63e9b77422aae8e7411ddc7a8458c2585c86df Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sun, 17 Nov 2019 23:12:18 +0100 +Subject: [PATCH 6/6] applesmc: fan support on T2 Macs + +T2 Macs changed the fan values from shorts to +floats, and changed the fan manual override +setting from a bitmask to a per-fan boolean +named F0Md (thanks to @kleuter for mentioning +it). + +A minimal soft-float implementation has been +written for convert floats to integers (and vice +versa). + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hwmon/applesmc.c | 119 +++++++++++++++++++++++++++++++++------ + 1 file changed, 102 insertions(+), 17 deletions(-) + +diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c +index 2d23bb9ad9dd..0938227be612 100644 +--- a/drivers/hwmon/applesmc.c ++++ b/drivers/hwmon/applesmc.c +@@ -87,6 +87,7 @@ + #define FAN_ID_FMT "F%dID" /* r-o char[16] */ + + #define TEMP_SENSOR_TYPE "sp78" ++#define FLOAT_TYPE "flt " + + /* List of keys used to read/write fan speeds */ + static const char *const fan_speed_fmt[] = { +@@ -96,6 +97,7 @@ static const char *const fan_speed_fmt[] = { + "F%dSf", /* safe speed - not all models */ + "F%dTg", /* target speed (manual: rw) */ + }; ++#define FAN_MANUAL_FMT "F%dMd" + + #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ + #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ +@@ -734,6 +736,42 @@ static int applesmc_read_s16(struct applesmc_device *smc, + return 0; + } + ++/** ++ * applesmc_float_to_u32 - Retrieve the integral part of a float. ++ * This is needed because Apple made fans use float values in the T2. ++ * The fractional point is not significantly useful though, and the integral ++ * part can be easily extracted. ++ */ ++static inline u32 applesmc_float_to_u32(u32 d) ++{ ++ u8 sign = (u8) ((d >> 31) & 1); ++ s32 exp = (s32) ((d >> 23) & 0xff) - 0x7f; ++ u32 fr = d & ((1u << 23) - 1); ++ ++ if (sign || exp < 0) ++ return 0; ++ ++ return (u32) ((1u << exp) + (fr >> (23 - exp))); ++} ++ ++/** ++ * applesmc_u32_to_float - Convert an u32 into a float. ++ * See applesmc_float_to_u32 for a rationale. ++ */ ++static inline u32 applesmc_u32_to_float(u32 d) ++{ ++ u32 dc = d, bc = 0, exp; ++ ++ if (!d) ++ return 0; ++ ++ while (dc >>= 1) ++ ++bc; ++ exp = 0x7f + bc; ++ ++ return (u32) ((exp << 23) | ++ ((d << (23 - (exp - 0x7f))) & ((1u << 23) - 1))); ++} + /* + * applesmc_device_init - initialize the accelerometer. Can sleep. + */ +@@ -1242,6 +1280,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, + struct device_attribute *attr, char *sysfsbuf) + { + struct applesmc_device *smc = dev_get_drvdata(dev); ++ const struct applesmc_entry *entry; + int ret; + unsigned int speed = 0; + char newkey[5]; +@@ -1250,11 +1289,21 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, + scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], + to_index(attr)); + +- ret = applesmc_read_key(smc, newkey, buffer, 2); ++ entry = applesmc_get_entry_by_key(smc, newkey); ++ if (IS_ERR(entry)) ++ return PTR_ERR(entry); ++ ++ if (!strcmp(entry->type, FLOAT_TYPE)) { ++ ret = applesmc_read_entry(smc, entry, (u8 *) &speed, 4); ++ speed = applesmc_float_to_u32(speed); ++ } else { ++ ret = applesmc_read_entry(smc, entry, buffer, 2); ++ speed = ((buffer[0] << 8 | buffer[1]) >> 2); ++ } ++ + if (ret) + return ret; + +- speed = ((buffer[0] << 8 | buffer[1]) >> 2); + return sysfs_emit(sysfsbuf, "%u\n", speed); + } + +@@ -1263,6 +1312,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, + const char *sysfsbuf, size_t count) + { + struct applesmc_device *smc = dev_get_drvdata(dev); ++ const struct applesmc_entry *entry; + int ret; + unsigned long speed; + char newkey[5]; +@@ -1274,9 +1324,18 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, + scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], + to_index(attr)); + +- buffer[0] = (speed >> 6) & 0xff; +- buffer[1] = (speed << 2) & 0xff; +- ret = applesmc_write_key(smc, newkey, buffer, 2); ++ entry = applesmc_get_entry_by_key(smc, newkey); ++ if (IS_ERR(entry)) ++ return PTR_ERR(entry); ++ ++ if (!strcmp(entry->type, FLOAT_TYPE)) { ++ speed = applesmc_u32_to_float(speed); ++ ret = applesmc_write_entry(smc, entry, (u8 *) &speed, 4); ++ } else { ++ buffer[0] = (speed >> 6) & 0xff; ++ buffer[1] = (speed << 2) & 0xff; ++ ret = applesmc_write_key(smc, newkey, buffer, 2); ++ } + + if (ret) + return ret; +@@ -1291,12 +1350,26 @@ static ssize_t applesmc_show_fan_manual(struct device *dev, + int ret; + u16 manual = 0; + u8 buffer[2]; ++ char newkey[5]; ++ bool has_newkey = false; ++ ++ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr)); ++ ++ ret = applesmc_has_key(smc, newkey, &has_newkey); ++ if (ret) ++ return ret; ++ ++ if (has_newkey) { ++ ret = applesmc_read_key(smc, newkey, buffer, 1); ++ manual = buffer[0]; ++ } else { ++ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); ++ manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; ++ } + +- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); + if (ret) + return ret; + +- manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; + return sysfs_emit(sysfsbuf, "%d\n", manual); + } + +@@ -1307,27 +1380,39 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, + struct applesmc_device *smc = dev_get_drvdata(dev); + int ret; + u8 buffer[2]; ++ char newkey[5]; ++ bool has_newkey = false; + unsigned long input; + u16 val; + + if (kstrtoul(sysfsbuf, 10, &input) < 0) + return -EINVAL; + +- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); ++ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr)); ++ ++ ret = applesmc_has_key(smc, newkey, &has_newkey); + if (ret) +- goto out; ++ return ret; + +- val = (buffer[0] << 8 | buffer[1]); ++ if (has_newkey) { ++ buffer[0] = input & 1; ++ ret = applesmc_write_key(smc, newkey, buffer, 1); ++ } else { ++ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); ++ val = (buffer[0] << 8 | buffer[1]); ++ if (ret) ++ goto out; + +- if (input) +- val = val | (0x01 << to_index(attr)); +- else +- val = val & ~(0x01 << to_index(attr)); ++ if (input) ++ val = val | (0x01 << to_index(attr)); ++ else ++ val = val & ~(0x01 << to_index(attr)); + +- buffer[0] = (val >> 8) & 0xFF; +- buffer[1] = val & 0xFF; ++ buffer[0] = (val >> 8) & 0xFF; ++ buffer[1] = val & 0xFF; + +- ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); ++ ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); ++ } + + out: + if (ret) +-- +2.30.0 + diff --git a/4001-HID-apple-Add-support-for-keyboard-backlight-on-supp.patch b/4001-HID-apple-Add-support-for-keyboard-backlight-on-supp.patch new file mode 100644 index 0000000..582d68f --- /dev/null +++ b/4001-HID-apple-Add-support-for-keyboard-backlight-on-supp.patch @@ -0,0 +1,195 @@ +From a6bf93712831ea518fcd342c3720b34f96afcd78 Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Sat, 30 Jan 2021 23:42:14 -0600 +Subject: [PATCH 1/9] HID: apple: Add support for keyboard backlight on + supported models + +This commit introduces the requisite plumbing for supporting keyboard +backlight on T2-attached, USB exposed models. The quirk mechanism was +used to reuse the existing hid-apple driver. + +Devices that support this feature will be added in subsequent patches. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 124 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 124 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 6b8f0d004d34..e03a621bc741 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -7,6 +7,7 @@ + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2008 Jiri Slaby ++ * Copyright (c) 2019 Paul Pawlowski + */ + + /* +@@ -30,6 +31,7 @@ + #define APPLE_INVERT_HWHEEL 0x0040 + /* 0x0080 reserved, was: APPLE_IGNORE_HIDINPUT */ + #define APPLE_NUMLOCK_EMULATION 0x0100 ++#define APPLE_BACKLIGHT_CTL 0x0200 + + #define APPLE_FLAG_FKEY 0x01 + +@@ -57,11 +59,18 @@ MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. " + "(For people who want to keep PC keyboard muscle memory. " + "[0] = as-is, Mac layout, 1 = swapped, PC layout)"); + ++struct apple_sc_backlight { ++ struct led_classdev cdev; ++ struct hid_device *hdev; ++ unsigned short backlight_off, backlight_on_min, backlight_on_max; ++}; ++ + struct apple_sc { + unsigned long quirks; + unsigned int fn_on; + unsigned int fn_found; + DECLARE_BITMAP(pressed_numlock, KEY_CNT); ++ struct apple_sc_backlight *backlight; + }; + + struct apple_key_translation { +@@ -70,6 +79,19 @@ struct apple_key_translation { + u8 flags; + }; + ++struct apple_backlight_config_report { ++ u8 report_id; ++ u8 version; ++ u16 backlight_off, backlight_on_min, backlight_on_max; ++}; ++ ++struct apple_backlight_set_report { ++ u8 report_id; ++ u8 version; ++ u16 backlight; ++ u16 rate; ++}; ++ + static const struct apple_key_translation macbookair_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, +@@ -414,6 +436,105 @@ static int apple_input_configured(struct hid_device *hdev, + return 0; + } + ++static bool apple_backlight_check_support(struct hid_device *hdev) ++{ ++ int i; ++ unsigned int hid; ++ struct hid_report *report; ++ ++ list_for_each_entry(report, &hdev->report_enum[HID_INPUT_REPORT].report_list, list) { ++ for (i = 0; i < report->maxfield; i++) { ++ hid = report->field[i]->usage->hid; ++ if ((hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR && (hid & HID_USAGE) == 0xf) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static int apple_backlight_set(struct hid_device *hdev, u16 value, u16 rate) ++{ ++ int ret = 0; ++ struct apple_backlight_set_report *rep; ++ ++ rep = kmalloc(sizeof(*rep), GFP_KERNEL); ++ if (rep == NULL) ++ return -ENOMEM; ++ ++ rep->report_id = 0xB0; ++ rep->version = 1; ++ rep->backlight = value; ++ rep->rate = rate; ++ ++ ret = hid_hw_raw_request(hdev, 0xB0u, (u8 *) rep, sizeof(*rep), ++ HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); ++ ++ kfree(rep); ++ return ret; ++} ++ ++static int apple_backlight_led_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct apple_sc_backlight *backlight = container_of(led_cdev, ++ struct apple_sc_backlight, cdev); ++ ++ return apple_backlight_set(backlight->hdev, brightness, 0); ++} ++ ++static int apple_backlight_init(struct hid_device *hdev) ++{ ++ int ret; ++ struct apple_sc *asc = hid_get_drvdata(hdev); ++ struct apple_backlight_config_report *rep; ++ ++ if (!apple_backlight_check_support(hdev)) ++ return -EINVAL; ++ ++ rep = kmalloc(0x200, GFP_KERNEL); ++ if (rep == NULL) ++ return -ENOMEM; ++ ++ ret = hid_hw_raw_request(hdev, 0xBFu, (u8 *) rep, sizeof(*rep), ++ HID_FEATURE_REPORT, HID_REQ_GET_REPORT); ++ if (ret < 0) { ++ hid_err(hdev, "backlight request failed: %d\n", ret); ++ goto cleanup_and_exit; ++ } ++ if (ret < 8 || rep->version != 1) { ++ hid_err(hdev, "backlight config struct: bad version %i\n", rep->version); ++ ret = -EINVAL; ++ goto cleanup_and_exit; ++ } ++ ++ hid_dbg(hdev, "backlight config: off=%u, on_min=%u, on_max=%u\n", ++ rep->backlight_off, rep->backlight_on_min, rep->backlight_on_max); ++ ++ asc->backlight = devm_kzalloc(&hdev->dev, sizeof(*asc->backlight), GFP_KERNEL); ++ if (!asc->backlight) { ++ ret = -ENOMEM; ++ goto cleanup_and_exit; ++ } ++ ++ asc->backlight->hdev = hdev; ++ asc->backlight->cdev.name = "apple::kbd_backlight"; ++ asc->backlight->cdev.max_brightness = rep->backlight_on_max; ++ asc->backlight->cdev.brightness_set_blocking = apple_backlight_led_set; ++ ++ ret = apple_backlight_set(hdev, 0, 0); ++ if (ret < 0) { ++ hid_err(hdev, "backlight set request failed: %d\n", ret); ++ goto cleanup_and_exit; ++ } ++ ++ ret = devm_led_classdev_register(&hdev->dev, &asc->backlight->cdev); ++ ++cleanup_and_exit: ++ kfree(rep); ++ return ret; ++} ++ + static int apple_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +@@ -449,6 +570,9 @@ static int apple_probe(struct hid_device *hdev, + return ret; + } + ++ if (quirks & APPLE_BACKLIGHT_CTL) ++ apple_backlight_init(hdev); ++ + return 0; + } + +-- +2.30.1 + diff --git a/4002-HID-apple-Add-support-for-MacbookAir8-1-keyboard-tra.patch b/4002-HID-apple-Add-support-for-MacbookAir8-1-keyboard-tra.patch new file mode 100644 index 0000000..b37733b --- /dev/null +++ b/4002-HID-apple-Add-support-for-MacbookAir8-1-keyboard-tra.patch @@ -0,0 +1,112 @@ +From 7d6971c788f4c89fdc43f370943bd4082be74279 Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 00:39:07 -0600 +Subject: [PATCH 2/9] HID: apple: Add support for MacbookAir8,1 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Air +(Retina, 13-inch, 2018) [MacBookAir8,1 J140K iBridge2,8]. + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 19 +++++++++++++++++++ + 4 files changed, 24 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index e03a621bc741..1f923565f9e9 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -731,6 +731,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 94180c63571e..3d22da749aa3 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -165,6 +165,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 + #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 + #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 142e9dae2837..fdd0b212cfcb 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -289,6 +289,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -923,6 +924,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index 59a14505b9cd..bf610d2d8c69 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -83,6 +83,10 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 + #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 + ++/* T2-Attached Devices */ ++/* MacbookAir8,1 (2018) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a ++ + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS | \ +@@ -147,6 +151,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), ++ /* MacbookAir8,1 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), + /* Terminating entry */ + {} + }; +@@ -483,6 +489,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -203, 6803 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4003-HID-apple-Add-support-for-MacBookPro15-2-keyboard-tr.patch b/4003-HID-apple-Add-support-for-MacBookPro15-2-keyboard-tr.patch new file mode 100644 index 0000000..bcc1246 --- /dev/null +++ b/4003-HID-apple-Add-support-for-MacBookPro15-2-keyboard-tr.patch @@ -0,0 +1,110 @@ +From af20038d6da35329434a447d1e70c3f18a532a33 Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 01:04:22 -0600 +Subject: [PATCH 3/9] HID: apple: Add support for MacBookPro15,2 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(13-inch, 2019, Four Thunderbolt 3 ports) [MacBookPro15,2 J132 iBridge2,4] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 1f923565f9e9..76d6535fc663 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -733,6 +733,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 3d22da749aa3..9741153715ff 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -166,6 +166,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 + #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index fdd0b212cfcb..7df65c99e984 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -290,6 +290,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -925,6 +926,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index bf610d2d8c69..81c1dac1da81 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -86,6 +86,8 @@ + /* T2-Attached Devices */ + /* MacbookAir8,1 (2018) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a ++/* MacbookPro15,2 (2018) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -153,6 +155,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), + /* MacbookAir8,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), ++ /* MacbookPro15,2 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), + /* Terminating entry */ + {} + }; +@@ -502,6 +506,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4004-HID-apple-Add-support-for-MacBookPro15-1-keyboard-tr.patch b/4004-HID-apple-Add-support-for-MacBookPro15-1-keyboard-tr.patch new file mode 100644 index 0000000..9740acf --- /dev/null +++ b/4004-HID-apple-Add-support-for-MacBookPro15-1-keyboard-tr.patch @@ -0,0 +1,110 @@ +From 2e8c510fb3fe48deec46fd3be7c5838c6cd9ed74 Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 01:16:37 -0600 +Subject: [PATCH 4/9] HID: apple: Add support for MacBookPro15,1 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(15-inch, 2018) [MacBookPro15,1 J680 iBridge2,3] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 76d6535fc663..9ee795dcfa83 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -735,6 +735,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 9741153715ff..b3e37a63e47e 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -167,6 +167,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 7df65c99e984..32419a34a64d 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -291,6 +291,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -927,6 +928,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index 81c1dac1da81..e7280b3c1a08 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -88,6 +88,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a + /* MacbookPro15,2 (2018) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b ++/* MacbookPro15,1 (2018) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -157,6 +159,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), + /* MacbookPro15,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), ++ /* MacbookPro15,1 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), + /* Terminating entry */ + {} + }; +@@ -519,6 +523,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -7456, 7976 }, ++ { SN_COORD, -1768, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4005-HID-apple-Add-support-for-MacBookPro15-4-keyboard-tr.patch b/4005-HID-apple-Add-support-for-MacBookPro15-4-keyboard-tr.patch new file mode 100644 index 0000000..ea9ad94 --- /dev/null +++ b/4005-HID-apple-Add-support-for-MacBookPro15-4-keyboard-tr.patch @@ -0,0 +1,110 @@ +From f00e6b0e89c89233ca43348f2c74b93757cd7deb Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 01:56:59 -0600 +Subject: [PATCH 5/9] HID: apple: Add support for MacBookPro15,4 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(13-inch, 2019, Two Thunderbolt 3 ports) [MacBookPro15,4 J213 iBridge2,10] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 9ee795dcfa83..d59d6de017d6 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -737,6 +737,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index b3e37a63e47e..aaa7cdf96481 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -168,6 +168,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 32419a34a64d..ee698d275427 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -292,6 +292,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -929,6 +930,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index e7280b3c1a08..3964f58fb870 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -90,6 +90,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b + /* MacbookPro15,1 (2018) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c ++/* MacbookPro15,4 (2019) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -161,6 +163,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), + /* MacbookPro15,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), ++ /* MacbookPro15,4 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), + /* Terminating entry */ + {} + }; +@@ -536,6 +540,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -1768, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4006-HID-apple-Add-support-for-MacBookPro16-2-keyboard-tr.patch b/4006-HID-apple-Add-support-for-MacBookPro16-2-keyboard-tr.patch new file mode 100644 index 0000000..ee55ca9 --- /dev/null +++ b/4006-HID-apple-Add-support-for-MacBookPro16-2-keyboard-tr.patch @@ -0,0 +1,111 @@ +From 6ebbc10ae708e487bca63bbc59f1ba51a90e4f4c Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 02:00:14 -0600 +Subject: [PATCH 6/9] HID: apple: Add support for MacBookPro16,2 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(13-inch, 2020, Four Thunderbolt 3 ports) [MacBookPro16,2 J214K +iBridge2,16] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index d59d6de017d6..4d1b88b57142 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -739,6 +739,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index aaa7cdf96481..861069c765c7 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -169,6 +169,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index ee698d275427..d15b6fe0c8c2 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -293,6 +293,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -931,6 +932,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index 3964f58fb870..00116c57d6cd 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -92,6 +92,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c + /* MacbookPro15,4 (2019) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d ++/* MacbookPro16,2 (2020) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -165,6 +167,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), + /* MacbookPro15,4 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), ++ /* MacbookPro16,2 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), + /* Terminating entry */ + {} + }; +@@ -553,6 +557,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4007-HID-apple-Add-support-for-MacBookPro16-3-keyboard-tr.patch b/4007-HID-apple-Add-support-for-MacBookPro16-3-keyboard-tr.patch new file mode 100644 index 0000000..5f2bbf6 --- /dev/null +++ b/4007-HID-apple-Add-support-for-MacBookPro16-3-keyboard-tr.patch @@ -0,0 +1,110 @@ +From 019200008a92c81db744f30ed5087633c48409ff Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sat, 13 Feb 2021 21:06:50 -0500 +Subject: [PATCH 7/9] HID: apple: Add support for MacBookPro16,3 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(13-inch, 2020, Two Thunderbolt 3 ports) [MacBookPro16,3 J223 iBridge2,21] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 4d1b88b57142..65e4137497b3 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -741,6 +741,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 861069c765c7..2a50ffd71e4e 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -170,6 +170,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index d15b6fe0c8c2..73e07b1b8bf5 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -294,6 +294,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -933,6 +934,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index 00116c57d6cd..e50aec0c865e 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -94,6 +94,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d + /* MacbookPro16,2 (2020) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e ++/* MacbookPro16,3 (2020) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -169,6 +171,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), + /* MacbookPro16,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), ++ /* MacbookPro16,3 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), + /* Terminating entry */ + {} + }; +@@ -570,6 +574,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4008-HID-apple-Add-support-for-MacBookAir9-1-keyboard-tra.patch b/4008-HID-apple-Add-support-for-MacBookAir9-1-keyboard-tra.patch new file mode 100644 index 0000000..8cc7118 --- /dev/null +++ b/4008-HID-apple-Add-support-for-MacBookAir9-1-keyboard-tra.patch @@ -0,0 +1,110 @@ +From 8e1462a94ac6c6e2fe407c88084beb03aa5a485f Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 02:16:15 -0600 +Subject: [PATCH 8/9] HID: apple: Add support for MacBookAir9,1 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Air +(Retina, 13-inch, 2020) [MacBookAir9,1 J230K iBridge2,15] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 65e4137497b3..2585986250d3 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -743,6 +743,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 2a50ffd71e4e..a113c30f3898 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -171,6 +171,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 73e07b1b8bf5..d9707ba949ee 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -295,6 +295,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -935,6 +936,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index e50aec0c865e..861afa9ac300 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -96,6 +96,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e + /* MacbookPro16,3 (2020) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f ++/* MacbookAir9,1 (2020) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -173,6 +175,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), + /* MacbookPro16,3 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), ++ /* MacbookAir9,1 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), + /* Terminating entry */ + {} + }; +@@ -587,6 +591,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -6243, 6749 }, ++ { SN_COORD, -170, 7685 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4009-HID-apple-Add-support-for-MacBookPro16-1-keyboard-tr.patch b/4009-HID-apple-Add-support-for-MacBookPro16-1-keyboard-tr.patch new file mode 100644 index 0000000..fc29866 --- /dev/null +++ b/4009-HID-apple-Add-support-for-MacBookPro16-1-keyboard-tr.patch @@ -0,0 +1,110 @@ +From 3aec4416855e679c6e64c4f92428680def85d03f Mon Sep 17 00:00:00 2001 +From: Aun-Ali Zaidi +Date: Sun, 31 Jan 2021 02:26:18 -0600 +Subject: [PATCH 9/9] HID: apple: Add support for MacBookPro16,1 + keyboard/trackpad + +This commit adds the necessary IDs and configuration for the MacBook Pro +(16-inch, 2019) [MacBookPro16,1 J152F iBridge2,14] + +This model uses the APPLE_BACKLIGHT_CTL quirk to expose keyboard +backlight controls. + +Signed-off-by: Aun-Ali Zaidi +--- + drivers/hid/hid-apple.c | 2 ++ + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-quirks.c | 2 ++ + drivers/input/mouse/bcm5974.c | 17 +++++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 2585986250d3..e68fe6855d3f 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -745,6 +745,8 @@ static const struct hid_device_id apple_devices[] = { + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index a113c30f3898..c15ed9687f97 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -172,6 +172,7 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 + #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a + #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b + #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index d9707ba949ee..62f85c976759 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -296,6 +296,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -937,6 +938,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c +index 861afa9ac300..83f08e4b47d0 100644 +--- a/drivers/input/mouse/bcm5974.c ++++ b/drivers/input/mouse/bcm5974.c +@@ -98,6 +98,8 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f + /* MacbookAir9,1 (2020) */ + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 ++/* MacbookPro16,1 (2019)*/ ++#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -177,6 +179,8 @@ static const struct usb_device_id bcm5974_table[] = { + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), + /* MacbookAir9,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), ++ /* MacbookPro16,1 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), + /* Terminating entry */ + {} + }; +@@ -604,6 +608,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { + { SN_COORD, -170, 7685 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F, ++ 0, ++ 0, ++ HAS_INTEGRATED_BUTTON, ++ 0, sizeof(struct bt_data), ++ 0x83, DATAFORMAT(TYPE4), ++ { SN_PRESSURE, 0, 300 }, ++ { SN_WIDTH, 0, 2048 }, ++ { SN_COORD, -8916, 9918 }, ++ { SN_COORD, -1934, 9835 }, ++ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } ++ }, + {} + }; + +-- +2.30.1 + diff --git a/4010-HID-apple-Add-ability-to-use-numbers-as-function-key.patch b/4010-HID-apple-Add-ability-to-use-numbers-as-function-key.patch new file mode 100644 index 0000000..7d07fc6 --- /dev/null +++ b/4010-HID-apple-Add-ability-to-use-numbers-as-function-key.patch @@ -0,0 +1,101 @@ +From: Aditya Garg + +This patch adds the Fn mapping for keyboards on certain T2 Macs. + +Signed-off-by: Aditya Garg +--- + drivers/hid/hid-apple.c | 64 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 63 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index b6e1a29a2..70e9f6f74 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -113,6 +113,51 @@ static const struct apple_key_translation macbookair_fn_keys[] = { + { } + }; + ++static const struct apple_key_translation macbookpro_no_esc_fn_keys[] = { ++ { KEY_BACKSPACE, KEY_DELETE }, ++ { KEY_ENTER, KEY_INSERT }, ++ { KEY_GRAVE, KEY_ESC }, ++ { KEY_1, KEY_F1 }, ++ { KEY_2, KEY_F2 }, ++ { KEY_3, KEY_F3 }, ++ { KEY_4, KEY_F4 }, ++ { KEY_5, KEY_F5 }, ++ { KEY_6, KEY_F6 }, ++ { KEY_7, KEY_F7 }, ++ { KEY_8, KEY_F8 }, ++ { KEY_9, KEY_F9 }, ++ { KEY_0, KEY_F10 }, ++ { KEY_MINUS, KEY_F11 }, ++ { KEY_EQUAL, KEY_F12 }, ++ { KEY_UP, KEY_PAGEUP }, ++ { KEY_DOWN, KEY_PAGEDOWN }, ++ { KEY_LEFT, KEY_HOME }, ++ { KEY_RIGHT, KEY_END }, ++ { } ++}; ++ ++static const struct apple_key_translation macbookpro_dedicated_esc_fn_keys[] = { ++ { KEY_BACKSPACE, KEY_DELETE }, ++ { KEY_ENTER, KEY_INSERT }, ++ { KEY_1, KEY_F1 }, ++ { KEY_2, KEY_F2 }, ++ { KEY_3, KEY_F3 }, ++ { KEY_4, KEY_F4 }, ++ { KEY_5, KEY_F5 }, ++ { KEY_6, KEY_F6 }, ++ { KEY_7, KEY_F7 }, ++ { KEY_8, KEY_F8 }, ++ { KEY_9, KEY_F9 }, ++ { KEY_0, KEY_F10 }, ++ { KEY_MINUS, KEY_F11 }, ++ { KEY_EQUAL, KEY_F12 }, ++ { KEY_UP, KEY_PAGEUP }, ++ { KEY_DOWN, KEY_PAGEDOWN }, ++ { KEY_LEFT, KEY_HOME }, ++ { KEY_RIGHT, KEY_END }, ++ { } ++}; ++ + static const struct apple_key_translation apple_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, +@@ -236,7 +281,18 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, + } + + if (fnmode) { +- if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && ++ if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 || ++ hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 || ++ hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) ++ table = macbookpro_no_esc_fn_keys; ++ else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K || ++ hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 || ++ hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) ++ table = macbookpro_dedicated_esc_fn_keys; ++ else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K || ++ hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) ++ table = apple_fn_keys; ++ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) + table = macbookair_fn_keys; + else if (hid->product < 0x21d || hid->product >= 0x300) +@@ -386,6 +442,12 @@ static void apple_setup_input(struct input_dev *input) + set_bit(KEY_NUMLOCK, input->keybit); + + /* Enable all needed keys */ ++ for (trans = macbookpro_no_esc_fn_keys; trans->from; trans++) ++ set_bit(trans->to, input->keybit); ++ ++ for (trans = macbookpro_dedicated_esc_fn_keys; trans->from; trans++) ++ set_bit(trans->to, input->keybit); ++ + for (trans = apple_fn_keys; trans->from; trans++) + set_bit(trans->to, input->keybit); + +-- +2.25.1 + diff --git a/5001-Fix-for-touchbar.patch b/5001-Fix-for-touchbar.patch new file mode 100644 index 0000000..1d25fbf --- /dev/null +++ b/5001-Fix-for-touchbar.patch @@ -0,0 +1,39 @@ +From 75e93e9689b4e0b24ddd4367d241cfd90183f7d7 Mon Sep 17 00:00:00 2001 +From: Aditya Garg +Date: Mon, 31 Jan 2022 19:10:18 +0530 +Subject: [PATCH] Fix for touchbar + +--- + drivers/hid/hid-ids.h | 2 ++ + drivers/hid/hid-quirks.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 859750313..94aaf8777 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -177,6 +177,8 @@ + #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 + #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c ++#define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 ++#define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302 + + #define USB_VENDOR_ID_ASUS 0x0486 + #define USB_DEVICE_ID_ASUS_T91MT 0x0185 +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 9af1dc8ae..2f5c54edc 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -305,6 +305,8 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) }, + #endif + #if IS_ENABLED(CONFIG_HID_APPLEIR) + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, +-- +2.25.1 + diff --git a/6001-media-uvcvideo-Add-support-for-Apple-T2-attached-iSi.patch b/6001-media-uvcvideo-Add-support-for-Apple-T2-attached-iSi.patch new file mode 100644 index 0000000..763847e --- /dev/null +++ b/6001-media-uvcvideo-Add-support-for-Apple-T2-attached-iSi.patch @@ -0,0 +1,38 @@ +From b6740001d1adbfe84768b859bee038ceeccdc50c Mon Sep 17 00:00:00 2001 +From: Paul Pawlowski +Date: Thu, 13 Jan 2022 00:13:01 +1100 +Subject: [PATCH] media: uvcvideo: Add support for Apple T2-attached FaceTime HD Camera + +Adds the requisite device id to support detection of the Apple FaceTime +HD webcam exposed over the T2 BCE VHCI interface. + +Tested-by: Aun-Ali Zaidi +Signed-off-by: Paul Pawlowski +Signed-off-by: Aun-Ali Zaidi +Signed-off-by: Aditya Garg +--- + drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 7c007426e..88dc9e7aa 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2848,6 +2848,15 @@ static const struct usb_device_id uvc_ids[] = { + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX + | UVC_QUIRK_BUILTIN_ISIGHT) }, ++ /* Apple FaceTime HD Camera (Built-In) */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x05ac, ++ .idProduct = 0x8514, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = (kernel_ulong_t)&uvc_quirk_probe_def }, + /* Apple Built-In iSight via iBridge */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +-- +2.25.1 diff --git a/7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch b/7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch new file mode 100644 index 0000000..5ea1736 --- /dev/null +++ b/7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch @@ -0,0 +1,32 @@ +From: Ashish Arora +Subject: Re: [PATCH] drm/i915: Discard large BIOS framebuffers causing display corruption. +Date: Sat, 08 Jan 2022 21:43:18 +1100 + +On certain 4k panels, the BIOS framebuffer is larger than what panel +requires causing display corruption. Introduce a check for the same. + +Signed-off-by: Ashish Arora +--- + drivers/gpu/drm/i915/display/intel_fbdev.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c +index adc3a81be..0a64184df 100644 +--- a/drivers/gpu/drm/i915/display/intel_fbdev.c ++++ b/drivers/gpu/drm/i915/display/intel_fbdev.c +@@ -194,10 +194,10 @@ static int intelfb_create(struct drm_fb_helper *helper, + int ret; + + if (intel_fb && +- (sizes->fb_width > intel_fb->base.width || +- sizes->fb_height > intel_fb->base.height)) { ++ (sizes->fb_width != intel_fb->base.width || ++ sizes->fb_height != intel_fb->base.height)) { + drm_dbg_kms(&dev_priv->drm, +- "BIOS fb too small (%dx%d), we require (%dx%d)," ++ "BIOS fb not valid (%dx%d), we require (%dx%d)," + " releasing it\n", + intel_fb->base.width, intel_fb->base.height, + sizes->fb_width, sizes->fb_height); +-- +2.25.1 diff --git a/8001-brcmfmac-pcie-Declare-missing-firmware-files-in-pcie.patch b/8001-brcmfmac-pcie-Declare-missing-firmware-files-in-pcie.patch new file mode 100644 index 0000000..3aa14c8 --- /dev/null +++ b/8001-brcmfmac-pcie-Declare-missing-firmware-files-in-pcie.patch @@ -0,0 +1,49 @@ +From 3f43bc112ea442739258e2c6b143408c7c45e2e9 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 19:32:16 +0900 +Subject: [PATCH 01/34] brcmfmac: pcie: Declare missing firmware files in + pcie.c + +Move one of the declarations from sdio.c to pcie.c, since it makes no +sense in the former (SDIO support is optional), and add missing ones. + +Signed-off-by: Hector Martin +Fixes: 75729e110e68 ("brcmfmac: expose firmware config files through modinfo") +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 7 +++++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 - + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 8b149996f..aed49416c 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -59,6 +59,13 @@ BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); + BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); + BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); + ++/* firmware config files */ ++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt"); ++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt"); ++ ++/* per-board firmware binaries */ ++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin"); ++ + static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602), + BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C), +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 8effeb7a7..5d156e591 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -629,7 +629,6 @@ BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-sdio"); + + /* firmware config files */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt"); +-MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt"); + + /* per-board firmware binaries */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin"); +-- +2.34.1 + diff --git a/8002-brcmfmac-firmware-Support-having-multiple-alt-paths.patch b/8002-brcmfmac-firmware-Support-having-multiple-alt-paths.patch new file mode 100644 index 0000000..fda0a3b --- /dev/null +++ b/8002-brcmfmac-firmware-Support-having-multiple-alt-paths.patch @@ -0,0 +1,166 @@ +From 59c61aa5ad2e12fdbccb5712d35c203cf9079230 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sat, 18 Dec 2021 20:38:34 +0900 +Subject: [PATCH 02/34] brcmfmac: firmware: Support having multiple alt paths + +Apple platforms have firmware and config files identified with multiple +dimensions. We want to be able to find the most specific firmware +available for any given platform, progressively trying more general +firmwares. + +First, add support for having multiple alternate firmware paths. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/firmware.c | 74 ++++++++++++++----- + 1 file changed, 55 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index 0eb13e5df..dff974955 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -427,6 +427,8 @@ void brcmf_fw_nvram_free(void *nvram) + struct brcmf_fw { + struct device *dev; + struct brcmf_fw_request *req; ++ const char **alt_paths; ++ int alt_index; + u32 curpos; + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); + }; +@@ -592,9 +594,10 @@ static int brcmf_fw_complete_request(const struct firmware *fw, + return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret; + } + +-static char *brcm_alt_fw_path(const char *path, const char *board_type) ++static const char **brcm_alt_fw_paths(const char *path, const char *board_type) + { + char alt_path[BRCMF_FW_NAME_LEN]; ++ char **alt_paths; + char suffix[5]; + + strscpy(alt_path, path, BRCMF_FW_NAME_LEN); +@@ -609,27 +612,45 @@ static char *brcm_alt_fw_path(const char *path, const char *board_type) + strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN); + strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); + +- return kstrdup(alt_path, GFP_KERNEL); ++ alt_paths = kzalloc(sizeof(char *) * 2, GFP_KERNEL); ++ alt_paths[0] = kstrdup(alt_path, GFP_KERNEL); ++ ++ return (const char **)alt_paths; ++} ++ ++static void brcm_free_alt_fw_paths(const char **alt_paths) ++{ ++ int i; ++ ++ if (!alt_paths) ++ return; ++ ++ for (i = 0; alt_paths[i]; i++) ++ kfree(alt_paths[i]); ++ ++ kfree(alt_paths); + } + + static int brcmf_fw_request_firmware(const struct firmware **fw, + struct brcmf_fw *fwctx) + { + struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos]; +- int ret; ++ int ret, i; + + /* Files can be board-specific, first try a board-specific path */ + if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) { +- char *alt_path; +- +- alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type); +- if (!alt_path) ++ const char **alt_paths = brcm_alt_fw_paths(cur->path, fwctx); ++ if (!alt_paths) + goto fallback; + +- ret = request_firmware(fw, alt_path, fwctx->dev); +- kfree(alt_path); +- if (ret == 0) +- return ret; ++ for (i = 0; alt_paths[i]; i++) { ++ ret = firmware_request_nowarn(fw, alt_paths[i], fwctx->dev); ++ if (ret == 0) { ++ brcm_free_alt_fw_paths(alt_paths); ++ return ret; ++ } ++ } ++ brcm_free_alt_fw_paths(alt_paths); + } + + fallback: +@@ -641,6 +662,9 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) + struct brcmf_fw *fwctx = ctx; + int ret; + ++ brcm_free_alt_fw_paths(fwctx->alt_paths); ++ fwctx->alt_paths = NULL; ++ + ret = brcmf_fw_complete_request(fw, fwctx); + + while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) { +@@ -662,13 +686,26 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx) + struct brcmf_fw_item *first = &fwctx->req->items[0]; + int ret = 0; + +- /* Fall back to canonical path if board firmware not found */ +- if (!fw) ++ if (fw) { ++ brcmf_fw_request_done(fw, ctx); ++ return; ++ } ++ ++ fwctx->alt_index++; ++ if (fwctx->alt_paths[fwctx->alt_index]) { ++ /* Try the next alt firmware */ ++ ret = request_firmware_nowait(THIS_MODULE, true, ++ fwctx->alt_paths[fwctx->alt_index], ++ fwctx->dev, GFP_KERNEL, fwctx, ++ brcmf_fw_request_done_alt_path); ++ } else { ++ /* Fall back to canonical path if board firmware not found */ + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done); ++ } + +- if (fw || ret < 0) ++ if (ret < 0) + brcmf_fw_request_done(fw, ctx); + } + +@@ -693,7 +730,6 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, + { + struct brcmf_fw_item *first = &req->items[0]; + struct brcmf_fw *fwctx; +- char *alt_path; + int ret; + + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); +@@ -712,12 +748,12 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, + fwctx->done = fw_cb; + + /* First try alternative board-specific path if any */ +- alt_path = brcm_alt_fw_path(first->path, fwctx->req->board_type); +- if (alt_path) { +- ret = request_firmware_nowait(THIS_MODULE, true, alt_path, ++ fwctx->alt_paths = brcm_alt_fw_paths(first->path, fwctx); ++ if (fwctx->alt_paths) { ++ fwctx->alt_index = 0; ++ ret = request_firmware_nowait(THIS_MODULE, true, fwctx->alt_paths[0], + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done_alt_path); +- kfree(alt_path); + } else { + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, +-- +2.34.1 + diff --git a/8003-brcmfmac-firmware-Handle-per-board-clm_blob-files.patch b/8003-brcmfmac-firmware-Handle-per-board-clm_blob-files.patch new file mode 100644 index 0000000..1698bfc --- /dev/null +++ b/8003-brcmfmac-firmware-Handle-per-board-clm_blob-files.patch @@ -0,0 +1,56 @@ +From 637e3946944e25c98c8955ec2a84133b79afca4d Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sat, 18 Dec 2021 20:52:04 +0900 +Subject: [PATCH 03/34] brcmfmac: firmware: Handle per-board clm_blob files + +Teach brcm_alt_fw_paths to correctly split off variable length +extensions, and enable alt firmware lookups for the CLM blob firmware +requests. + +Apple platforms have per-board CLM blob files. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/firmware.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index dff974955..16f342bc5 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -598,16 +598,16 @@ static const char **brcm_alt_fw_paths(const char *path, const char *board_type) + { + char alt_path[BRCMF_FW_NAME_LEN]; + char **alt_paths; +- char suffix[5]; ++ const char *suffix; + +- strscpy(alt_path, path, BRCMF_FW_NAME_LEN); +- /* At least one character + suffix */ +- if (strlen(alt_path) < 5) ++ suffix = strrchr(path, '.'); ++ if (!suffix || suffix == path) + return NULL; + +- /* strip .txt or .bin at the end */ +- strscpy(suffix, alt_path + strlen(alt_path) - 4, 5); +- alt_path[strlen(alt_path) - 4] = 0; ++ /* strip extension at the end */ ++ strscpy(alt_path, path, BRCMF_FW_NAME_LEN); ++ alt_path[suffix - path] = 0; ++ + strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); + strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN); + strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); +@@ -638,7 +638,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw, + int ret, i; + + /* Files can be board-specific, first try a board-specific path */ +- if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) { ++ if (fwctx->req->board_type) { + const char **alt_paths = brcm_alt_fw_paths(cur->path, fwctx); + if (!alt_paths) + goto fallback; +-- +2.34.1 + diff --git a/8004-brcmfmac-pcie-sdio-usb-Get-CLM-blob-via-standard-fir.patch b/8004-brcmfmac-pcie-sdio-usb-Get-CLM-blob-via-standard-fir.patch new file mode 100644 index 0000000..a7b4088 --- /dev/null +++ b/8004-brcmfmac-pcie-sdio-usb-Get-CLM-blob-via-standard-fir.patch @@ -0,0 +1,374 @@ +From 10ae20866cddd7ba8421dfa331d617c36e1510f6 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:13:49 +0900 +Subject: [PATCH 04/34] brcmfmac: pcie/sdio/usb: Get CLM blob via standard + firmware mechanism + +Now that the firmware fetcher can handle per-board CLM files, load the +CLM blob alongside the other firmware files and change the bus API to +just return the existing blob, instead of fetching the filename. + +This enables per-board CLM blobs, which are required on Apple platforms. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/bus.h | 19 ++++++--- + .../broadcom/brcm80211/brcmfmac/common.c | 12 +----- + .../broadcom/brcm80211/brcmfmac/pcie.c | 39 ++++++++++++------- + .../broadcom/brcm80211/brcmfmac/sdio.c | 36 ++++++++++------- + .../broadcom/brcm80211/brcmfmac/sdio.h | 2 + + .../broadcom/brcm80211/brcmfmac/usb.c | 23 +++-------- + 6 files changed, 69 insertions(+), 62 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +index 3f5da3bb6..b13af8f63 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -7,6 +7,8 @@ + #define BRCMFMAC_BUS_H + + #include "debug.h" ++#include ++#include + + /* IDs of the 6 default common rings of msgbuf protocol */ + #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 +@@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type { + BRCMF_PROTO_MSGBUF + }; + ++/* Firmware blobs that may be available */ ++enum brcmf_blob_type { ++ BRCMF_BLOB_CLM, ++}; ++ + struct brcmf_mp_device; + + struct brcmf_bus_dcmd { +@@ -60,7 +67,7 @@ struct brcmf_bus_dcmd { + * @wowl_config: specify if dongle is configured for wowl when going to suspend + * @get_ramsize: obtain size of device memory. + * @get_memdump: obtain device memory dump in provided buffer. +- * @get_fwname: obtain firmware name. ++ * @get_blob: obtain a firmware blob. + * + * This structure provides an abstract interface towards the + * bus specific driver. For control messages to common driver +@@ -77,8 +84,8 @@ struct brcmf_bus_ops { + void (*wowl_config)(struct device *dev, bool enabled); + size_t (*get_ramsize)(struct device *dev); + int (*get_memdump)(struct device *dev, void *data, size_t len); +- int (*get_fwname)(struct device *dev, const char *ext, +- unsigned char *fw_name); ++ int (*get_blob)(struct device *dev, const struct firmware **fw, ++ enum brcmf_blob_type type); + void (*debugfs_create)(struct device *dev); + int (*reset)(struct device *dev); + }; +@@ -220,10 +227,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) + } + + static inline +-int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext, +- unsigned char *fw_name) ++int brcmf_bus_get_blob(struct brcmf_bus *bus, const struct firmware **fw, ++ enum brcmf_blob_type type) + { +- return bus->ops->get_fwname(bus->dev, ext, fw_name); ++ return bus->ops->get_blob(bus->dev, fw, type); + } + + static inline +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index e3758bd86..b8ed85112 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) + struct brcmf_bus *bus = drvr->bus_if; + struct brcmf_dload_data_le *chunk_buf; + const struct firmware *clm = NULL; +- u8 clm_name[BRCMF_FW_NAME_LEN]; + u32 chunk_len; + u32 datalen; + u32 cumulative_len; +@@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) + + brcmf_dbg(TRACE, "Enter\n"); + +- memset(clm_name, 0, sizeof(clm_name)); +- err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name); +- if (err) { +- bphy_err(drvr, "get CLM blob file name failed (%d)\n", err); +- return err; +- } +- +- err = firmware_request_nowarn(&clm, clm_name, bus->dev); +- if (err) { ++ err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM); ++ if (err || !clm) { + brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", + err); + return 0; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index aed49416c..ab0503c6f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -65,6 +65,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt"); + + /* per-board firmware binaries */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin"); ++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob"); + + static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602), +@@ -260,6 +261,8 @@ struct brcmf_pciedev_info { + struct pci_dev *pdev; + char fw_name[BRCMF_FW_NAME_LEN]; + char nvram_name[BRCMF_FW_NAME_LEN]; ++ char clm_name[BRCMF_FW_NAME_LEN]; ++ const struct firmware *clm_fw; + void __iomem *regs; + void __iomem *tcm; + u32 ram_base; +@@ -1408,23 +1411,25 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) + return 0; + } + +-static +-int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name) ++static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw, ++ enum brcmf_blob_type type) + { + struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_fw_request *fwreq; +- struct brcmf_fw_name fwnames[] = { +- { ext, fw_name }, +- }; ++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; ++ struct brcmf_pciedev_info *devinfo = buspub->devinfo; + +- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev, +- brcmf_pcie_fwnames, +- ARRAY_SIZE(brcmf_pcie_fwnames), +- fwnames, ARRAY_SIZE(fwnames)); +- if (!fwreq) +- return -ENOMEM; ++ switch (type) { ++ case BRCMF_BLOB_CLM: ++ *fw = devinfo->clm_fw; ++ devinfo->clm_fw = NULL; ++ break; ++ default: ++ return -ENOENT; ++ } ++ ++ if (!*fw) ++ return -ENOENT; + +- kfree(fwreq); + return 0; + } + +@@ -1470,7 +1475,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { + .wowl_config = brcmf_pcie_wowl_config, + .get_ramsize = brcmf_pcie_get_ramsize, + .get_memdump = brcmf_pcie_get_memdump, +- .get_fwname = brcmf_pcie_get_fwname, ++ .get_blob = brcmf_pcie_get_blob, + .reset = brcmf_pcie_reset, + }; + +@@ -1755,6 +1760,7 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { + + #define BRCMF_PCIE_FW_CODE 0 + #define BRCMF_PCIE_FW_NVRAM 1 ++#define BRCMF_PCIE_FW_CLM 2 + + static void brcmf_pcie_setup(struct device *dev, int ret, + struct brcmf_fw_request *fwreq) +@@ -1779,6 +1785,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret, + fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary; + nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data; + nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len; ++ devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary; + kfree(fwreq); + + ret = brcmf_chip_get_raminfo(devinfo->ci); +@@ -1855,6 +1862,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + struct brcmf_fw_name fwnames[] = { + { ".bin", devinfo->fw_name }, + { ".txt", devinfo->nvram_name }, ++ { ".clm_blob", devinfo->clm_name }, + }; + + fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev, +@@ -1867,6 +1875,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL; ++ fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY; ++ fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->board_type = devinfo->settings->board_type; + /* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */ + fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1; +@@ -2005,6 +2015,7 @@ brcmf_pcie_remove(struct pci_dev *pdev) + brcmf_pcie_release_ringbuffers(devinfo); + brcmf_pcie_reset_device(devinfo); + brcmf_pcie_release_resource(devinfo); ++ release_firmware(devinfo->clm_fw); + + if (devinfo->ci) + brcmf_chip_detach(devinfo->ci); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 5d156e591..7466e6fd6 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4129,23 +4129,24 @@ brcmf_sdio_watchdog(struct timer_list *t) + } + } + +-static +-int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name) ++static int brcmf_sdio_get_blob(struct device *dev, const struct firmware **fw, ++ enum brcmf_blob_type type) + { + struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_fw_request *fwreq; +- struct brcmf_fw_name fwnames[] = { +- { ext, fw_name }, +- }; ++ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + +- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev, +- brcmf_sdio_fwnames, +- ARRAY_SIZE(brcmf_sdio_fwnames), +- fwnames, ARRAY_SIZE(fwnames)); +- if (!fwreq) +- return -ENOMEM; ++ switch (type) { ++ case BRCMF_BLOB_CLM: ++ *fw = sdiodev->clm_fw; ++ sdiodev->clm_fw = NULL; ++ break; ++ default: ++ return -ENOENT; ++ } ++ ++ if (!*fw) ++ return -ENOENT; + +- kfree(fwreq); + return 0; + } + +@@ -4188,13 +4189,14 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { + .wowl_config = brcmf_sdio_wowl_config, + .get_ramsize = brcmf_sdio_bus_get_ramsize, + .get_memdump = brcmf_sdio_bus_get_memdump, +- .get_fwname = brcmf_sdio_get_fwname, ++ .get_blob = brcmf_sdio_get_blob, + .debugfs_create = brcmf_sdio_debugfs_create, + .reset = brcmf_sdio_bus_reset + }; + + #define BRCMF_SDIO_FW_CODE 0 + #define BRCMF_SDIO_FW_NVRAM 1 ++#define BRCMF_SDIO_FW_CLM 2 + + static void brcmf_sdio_firmware_callback(struct device *dev, int err, + struct brcmf_fw_request *fwreq) +@@ -4217,6 +4219,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, + code = fwreq->items[BRCMF_SDIO_FW_CODE].binary; + nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data; + nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len; ++ sdiod->clm_fw = fwreq->items[BRCMF_SDIO_FW_CLM].binary; + kfree(fwreq); + + /* try to download image and nvram to the dongle */ +@@ -4415,6 +4418,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) + struct brcmf_fw_name fwnames[] = { + { ".bin", bus->sdiodev->fw_name }, + { ".txt", bus->sdiodev->nvram_name }, ++ { ".clm_blob", bus->sdiodev->clm_name }, + }; + + fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, +@@ -4426,6 +4430,8 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) + + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; ++ fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY; ++ fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->board_type = bus->sdiodev->settings->board_type; + + return fwreq; +@@ -4582,6 +4588,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) + if (bus->sdiodev->settings) + brcmf_release_module_param(bus->sdiodev->settings); + ++ release_firmware(bus->sdiodev->clm_fw); ++ bus->sdiodev->clm_fw = NULL; + kfree(bus->rxbuf); + kfree(bus->hdrbuf); + kfree(bus); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +index 15d2c02fa..7b74c295e 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -186,9 +186,11 @@ struct brcmf_sdio_dev { + struct sg_table sgtable; + char fw_name[BRCMF_FW_NAME_LEN]; + char nvram_name[BRCMF_FW_NAME_LEN]; ++ char clm_name[BRCMF_FW_NAME_LEN]; + bool wowl_enabled; + enum brcmf_sdiod_state state; + struct brcmf_sdiod_freezer *freezer; ++ const struct firmware *clm_fw; + }; + + /* sdio core registers */ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +index 9fb68c2dc..85e18fb9c 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1154,24 +1154,11 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, + return NULL; + } + +-static +-int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name) ++static int brcmf_usb_get_blob(struct device *dev, const struct firmware **fw, ++ enum brcmf_blob_type type) + { +- struct brcmf_bus *bus = dev_get_drvdata(dev); +- struct brcmf_fw_request *fwreq; +- struct brcmf_fw_name fwnames[] = { +- { ext, fw_name }, +- }; +- +- fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev, +- brcmf_usb_fwnames, +- ARRAY_SIZE(brcmf_usb_fwnames), +- fwnames, ARRAY_SIZE(fwnames)); +- if (!fwreq) +- return -ENOMEM; +- +- kfree(fwreq); +- return 0; ++ /* No blobs for USB devices... */ ++ return -ENOENT; + } + + static const struct brcmf_bus_ops brcmf_usb_bus_ops = { +@@ -1180,7 +1167,7 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = { + .txdata = brcmf_usb_tx, + .txctl = brcmf_usb_tx_ctlpkt, + .rxctl = brcmf_usb_rx_ctlpkt, +- .get_fwname = brcmf_usb_get_fwname, ++ .get_blob = brcmf_usb_get_blob, + }; + + #define BRCMF_USB_FW_CODE 0 +-- +2.34.1 + diff --git a/8005-brcmfmac-firmware-Support-passing-in-multiple-board_.patch b/8005-brcmfmac-firmware-Support-passing-in-multiple-board_.patch new file mode 100644 index 0000000..d4108a5 --- /dev/null +++ b/8005-brcmfmac-firmware-Support-passing-in-multiple-board_.patch @@ -0,0 +1,135 @@ +From 880d3f98041005210a332974c3b19e0116e14053 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:38:37 +0900 +Subject: [PATCH 05/34] brcmfmac: firmware: Support passing in multiple + board_types + +In order to make use of the multiple alt_path functionality, change +board_type to an array. Bus drivers can pass in a NULL-terminated list +of board type strings to try for the firmware fetch. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/firmware.c | 35 +++++++++++++------ + .../broadcom/brcm80211/brcmfmac/firmware.h | 2 +- + .../broadcom/brcm80211/brcmfmac/pcie.c | 7 +++- + .../broadcom/brcm80211/brcmfmac/sdio.c | 4 ++- + 4 files changed, 35 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index 16f342bc5..02e36fa3d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -594,26 +594,41 @@ static int brcmf_fw_complete_request(const struct firmware *fw, + return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret; + } + +-static const char **brcm_alt_fw_paths(const char *path, const char *board_type) ++static const char **brcm_alt_fw_paths(const char *path, struct brcmf_fw *fwctx) + { ++ const char **board_types = fwctx->req->board_types; ++ int board_type_count = 0; ++ int i; + char alt_path[BRCMF_FW_NAME_LEN]; + char **alt_paths; + const char *suffix; + ++ if (!board_types || !board_types[0]) ++ return NULL; ++ ++ while (*board_types++) ++ board_type_count++; ++ + suffix = strrchr(path, '.'); + if (!suffix || suffix == path) + return NULL; + +- /* strip extension at the end */ +- strscpy(alt_path, path, BRCMF_FW_NAME_LEN); +- alt_path[suffix - path] = 0; ++ alt_paths = kzalloc(sizeof(char *) * (board_type_count + 1), ++ GFP_KERNEL); ++ ++ board_types = fwctx->req->board_types; ++ for (i = 0; i < board_type_count; i++) { ++ /* strip extension at the end */ ++ strscpy(alt_path, path, BRCMF_FW_NAME_LEN); ++ alt_path[suffix - path] = 0; + +- strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); +- strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN); +- strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); ++ strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); ++ strlcat(alt_path, board_types[i], BRCMF_FW_NAME_LEN); ++ strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); + +- alt_paths = kzalloc(sizeof(char *) * 2, GFP_KERNEL); +- alt_paths[0] = kstrdup(alt_path, GFP_KERNEL); ++ alt_paths[i] = kstrdup(alt_path, GFP_KERNEL); ++ brcmf_dbg(TRACE, "FW alt path: %s\n", alt_paths[i]); ++ } + + return (const char **)alt_paths; + } +@@ -638,7 +653,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw, + int ret, i; + + /* Files can be board-specific, first try a board-specific path */ +- if (fwctx->req->board_type) { ++ if (fwctx->req->board_types) { + const char **alt_paths = brcm_alt_fw_paths(cur->path, fwctx); + if (!alt_paths) + goto fallback; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +index e290dec9c..d94a1d5be 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +@@ -66,7 +66,7 @@ struct brcmf_fw_request { + u16 domain_nr; + u16 bus_nr; + u32 n_items; +- const char *board_type; ++ const char **board_types; + struct brcmf_fw_item items[]; + }; + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index ab0503c6f..0e4ba33fb 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1877,11 +1877,16 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; +- fwreq->board_type = devinfo->settings->board_type; + /* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */ + fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1; + fwreq->bus_nr = devinfo->pdev->bus->number; + ++ brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type); ++ fwreq->board_types = devm_kzalloc(&devinfo->pdev->dev, ++ sizeof(const char *) * 2, ++ GFP_KERNEL); ++ fwreq->board_types[0] = devinfo->settings->board_type; ++ + return fwreq; + } + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 7466e6fd6..32f457bf0 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4432,7 +4432,9 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) + fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; +- fwreq->board_type = bus->sdiodev->settings->board_type; ++ fwreq->board_types = devm_kzalloc(bus->sdiodev->dev, ++ sizeof(const char *) * 2, GFP_KERNEL); ++ fwreq->board_types[0] = bus->sdiodev->settings->board_type; + + return fwreq; + } +-- +2.34.1 + diff --git a/8006-brcmfmac-pcie-Read-Apple-OTP-information.patch b/8006-brcmfmac-pcie-Read-Apple-OTP-information.patch new file mode 100644 index 0000000..71ec737 --- /dev/null +++ b/8006-brcmfmac-pcie-Read-Apple-OTP-information.patch @@ -0,0 +1,301 @@ +From 18b840ed5dc7084d4ba83345a63a7f5f33cec013 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:26:34 +0900 +Subject: [PATCH 06/34] brcmfmac: pcie: Read Apple OTP information + +On Apple platforms, the One Time Programmable ROM in the Broadcom chips +contains information about the specific board design (module, vendor, +version) that is required to select the correct NVRAM file. Parse this +OTP ROM and extract the required strings. + +Note that the user OTP offset/size is per-chip. This patch does not add +any chips yet. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 221 ++++++++++++++++++ + include/linux/bcma/bcma_driver_chipcommon.h | 1 + + 2 files changed, 222 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 0e4ba33fb..0f19fc9b1 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -255,6 +255,15 @@ struct brcmf_pcie_core_info { + u32 wrapbase; + }; + ++#define BRCMF_OTP_MAX_PARAM_LEN 16 ++ ++struct brcmf_otp_params { ++ char module[BRCMF_OTP_MAX_PARAM_LEN]; ++ char vendor[BRCMF_OTP_MAX_PARAM_LEN]; ++ char version[BRCMF_OTP_MAX_PARAM_LEN]; ++ bool valid; ++}; ++ + struct brcmf_pciedev_info { + enum brcmf_pcie_state state; + bool in_irq; +@@ -282,6 +291,7 @@ struct brcmf_pciedev_info { + void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + u16 value); + struct brcmf_mp_device *settings; ++ struct brcmf_otp_params otp; + }; + + struct brcmf_pcie_ringbuf { +@@ -353,6 +363,15 @@ static void brcmf_pcie_setup(struct device *dev, int ret, + static struct brcmf_fw_request * + brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo); + ++static u16 ++brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset) ++{ ++ void __iomem *address = devinfo->regs + reg_offset; ++ ++ return (ioread16(address)); ++} ++ ++ + static u32 + brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset) + { +@@ -539,6 +558,8 @@ brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + } + + ++#define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \ ++ CHIPCREGOFFS(reg)) + #define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \ + CHIPCREGOFFS(reg), value) + +@@ -1758,6 +1779,200 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { + .write32 = brcmf_pcie_buscore_write32, + }; + ++#define BRCMF_OTP_SYS_VENDOR 0x15 ++#define BRCMF_OTP_BRCM_CIS 0x80 ++ ++#define BRCMF_OTP_VENDOR_HDR 0x00000008 ++ ++static int ++brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo, ++ u8 *data, size_t size) ++{ ++ int idx = 4; ++ const char *chip_params; ++ const char *module_params; ++ const char *p; ++ ++ /* 4-byte header and two empty strings */ ++ if (size < 6) ++ return -EINVAL; ++ ++ if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR) ++ return -EINVAL; ++ ++ chip_params = &data[idx]; ++ ++ /* Skip first string, including terminator */ ++ idx += strnlen(chip_params, size - idx) + 1; ++ if (idx >= size) ++ return -EINVAL; ++ ++ module_params = &data[idx]; ++ ++ /* Skip to terminator of second string */ ++ idx += strnlen(module_params, size - idx); ++ if (idx >= size) ++ return -EINVAL; ++ ++ /* At this point both strings are guaranteed NUL-terminated */ ++ brcmf_dbg(PCIE, "OTP: chip_params='%s' module_params='%s'\n", ++ chip_params, module_params); ++ ++ p = module_params; ++ while (*p) { ++ char tag = *p++; ++ const char *end; ++ size_t len; ++ ++ if (tag == ' ') /* Skip extra spaces */ ++ continue; ++ ++ if (*p++ != '=') /* implicit NUL check */ ++ return -EINVAL; ++ ++ /* *p might be NUL here, if so end == p and len == 0 */ ++ end = strchrnul(p, ' '); ++ len = end - p; ++ ++ /* leave 1 byte for NUL in destination string */ ++ if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1)) ++ return -EINVAL; ++ ++ /* Copy len characters plus a NUL terminator */ ++ switch (tag) { ++ case 'M': ++ strlcpy(devinfo->otp.module, p, len + 1); ++ break; ++ case 'V': ++ strlcpy(devinfo->otp.vendor, p, len + 1); ++ break; ++ case 'm': ++ strlcpy(devinfo->otp.version, p, len + 1); ++ break; ++ } ++ ++ /* Skip to space separator or NUL */ ++ p = end; ++ } ++ ++ brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n", ++ devinfo->otp.module, devinfo->otp.vendor, ++ devinfo->otp.version); ++ ++ if (!devinfo->otp.module || ++ !devinfo->otp.vendor || ++ !devinfo->otp.version) ++ return -EINVAL; ++ ++ devinfo->otp.valid = true; ++ return 0; ++} ++ ++static int ++brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size) ++{ ++ int p = 0; ++ int ret = -1; ++ ++ brcmf_dbg(PCIE, "parse_otp size=%ld\n", size); ++ ++ while (p < (size - 1)) { ++ u8 type = otp[p]; ++ u8 length = otp[p + 1]; ++ ++ if (type == 0) ++ break; ++ ++ if ((p + 2 + length) > size) ++ break; ++ ++ switch (type) { ++ case BRCMF_OTP_SYS_VENDOR: ++ brcmf_dbg(PCIE, "OTP @ 0x%x (0x%x): SYS_VENDOR\n", ++ p, length); ++ ret = brcmf_pcie_parse_otp_sys_vendor(devinfo, ++ &otp[p + 2], ++ length); ++ break; ++ case BRCMF_OTP_BRCM_CIS: ++ brcmf_dbg(PCIE, "OTP @ 0x%x (0x%x): BRCM_CIS\n", ++ p, length); ++ break; ++ default: ++ brcmf_dbg(PCIE, "OTP @ 0x%x (0x%x): Unknown type 0x%x\n", ++ p, length, type); ++ break; ++ } ++ ++ p += 2 + length; ++ } ++ ++ return ret; ++} ++ ++static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) ++{ ++ const struct pci_dev *pdev = devinfo->pdev; ++ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); ++ u32 coreid, base, words, idx, sromctl; ++ u16 *otp; ++ struct brcmf_core *core; ++ int ret; ++ ++ switch (devinfo->ci->chip) { ++ default: ++ /* OTP not supported on this chip */ ++ return 0; ++ } ++ ++ core = brcmf_chip_get_core(devinfo->ci, coreid); ++ if (!core) { ++ brcmf_err(bus, "No OTP core\n"); ++ return -ENODEV; ++ } ++ ++ if (coreid == BCMA_CORE_CHIPCOMMON) { ++ /* ++ * Chips with OTP accessed via ChipCommon need additional ++ * handling to access the OTP ++ */ ++ brcmf_pcie_select_core(devinfo, coreid); ++ sromctl = READCC32(devinfo, sromcontrol); ++ ++ if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) { ++ /* Chip lacks OTP, try without it... */ ++ brcmf_err(bus, ++ "OTP unavailable, using default firmware\n"); ++ return 0; ++ } ++ ++ /* Map OTP to shadow area */ ++ WRITECC32(devinfo, sromcontrol, ++ sromctl | BCMA_CC_SROM_CONTROL_OTPSEL); ++ } ++ ++ otp = kzalloc(sizeof(u16) * words, GFP_KERNEL); ++ ++ /* Map bus window to SROM/OTP shadow area in core */ ++ base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base); ++ ++ brcmf_dbg(PCIE, "OTP data:\n"); ++ for (idx = 0; idx < words; idx++) { ++ otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx); ++ brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]); ++ } ++ ++ if (coreid == BCMA_CORE_CHIPCOMMON) { ++ brcmf_pcie_select_core(devinfo, coreid); ++ WRITECC32(devinfo, sromcontrol, sromctl); ++ } ++ ++ ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words); ++ kfree(otp); ++ ++ return ret; ++} ++ + #define BRCMF_PCIE_FW_CODE 0 + #define BRCMF_PCIE_FW_NVRAM 1 + #define BRCMF_PCIE_FW_CLM 2 +@@ -1958,6 +2173,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (ret) + goto fail_bus; + ++ ret = brcmf_pcie_read_otp(devinfo); ++ if (ret) { ++ brcmf_err(bus, "failed to parse OTP\n"); ++ goto fail_brcmf; ++ } ++ + fwreq = brcmf_pcie_prepare_fw_request(devinfo); + if (!fwreq) { + ret = -ENOMEM; +diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h +index d35b92060..c91db7460 100644 +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -270,6 +270,7 @@ + #define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000 + #define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000 + #define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010 ++#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020 + #define BCMA_CC_SROM_CONTROL_LOCK 0x00000008 + #define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006 + #define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000 +-- +2.34.1 + diff --git a/8007-brcmfmac-of-Fetch-Apple-properties.patch b/8007-brcmfmac-of-Fetch-Apple-properties.patch new file mode 100644 index 0000000..76dde1e --- /dev/null +++ b/8007-brcmfmac-of-Fetch-Apple-properties.patch @@ -0,0 +1,76 @@ +From c42886eecdf0752c2525bb9f24a4a1db862fdd18 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:27:19 +0900 +Subject: [PATCH 07/34] brcmfmac: of: Fetch Apple properties + +On Apple ARM64 platforms, firmware selection requires two properties +that come from system firmware: the module-instance (aka "island", a +codename representing a given hardware platform) and the antenna-sku. + +The module-instance is hard-coded in per-board DTS files, while the +antenna-sku is forwarded by our bootloader from the Apple Device Tree +into the FDT. Grab them from the DT so firmware selection can use +them. + +The module-instance is used to construct a board_type by prepending it +with "apple,". + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/common.h | 1 + + .../wireless/broadcom/brcm80211/brcmfmac/of.c | 20 ++++++++++++++++++- + 2 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +index 8b5f49997..d4aa25d64 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -50,6 +50,7 @@ struct brcmf_mp_device { + bool ignore_probe_fail; + struct brcmfmac_pd_cc *country_codes; + const char *board_type; ++ const char *antenna_sku; + union { + struct brcmfmac_sdio_pd sdio; + } bus; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +index 513c7e642..31407d3a1 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -63,14 +63,32 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + { + struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; + struct device_node *root, *np = dev->of_node; ++ const char *prop; + int irq; + int err; + u32 irqf; + u32 val; + ++ /* ++ * Apple ARM64 platforms have their own idea of board type, passed in ++ * via the device tree. They also have an antenna SKU parameter ++ */ ++ if (!of_property_read_string(np, "apple,module-instance", &prop)) { ++ const char *prefix = "apple,"; ++ int len = strlen(prefix) + strlen(prop) + 1; ++ char *board_type = devm_kzalloc(dev, len, GFP_KERNEL); ++ ++ strlcpy(board_type, prefix, len); ++ strlcat(board_type, prop, len); ++ settings->board_type = board_type; ++ } ++ ++ if (!of_property_read_string(np, "apple,antenna-sku", &prop)) ++ settings->antenna_sku = devm_kstrdup(dev, prop, GFP_KERNEL); ++ + /* Set board-type to the first string of the machine compatible prop */ + root = of_find_node_by_path("/"); +- if (root) { ++ if (root && !settings->board_type) { + int i, len; + char *board_type; + const char *tmp; +-- +2.34.1 + diff --git a/8008-brcmfmac-pcie-Perform-firmware-selection-for-Apple-p.patch b/8008-brcmfmac-pcie-Perform-firmware-selection-for-Apple-p.patch new file mode 100644 index 0000000..fddac07 --- /dev/null +++ b/8008-brcmfmac-pcie-Perform-firmware-selection-for-Apple-p.patch @@ -0,0 +1,160 @@ +From 2ea0163cdf39c28e923961180b8dd158467a3751 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:45:21 +0900 +Subject: [PATCH 08/34] brcmfmac: pcie: Perform firmware selection for Apple + platforms + +On Apple platforms, firmware selection uses the following elements: + + Property Example Source + ============== ======= ======================== +* Chip name 4378 Device ID +* Chip revision B1 OTP +* Platform shikoku DT (ARM64) or ACPI (x86) +* Module type RASP OTP +* Module vendor m OTP +* Module version 6.11 OTP +* Antenna SKU X3 DT (ARM64) or ??? (x86) + +In macOS, these firmwares are stored using filenames in this format +under /usr/share/firmware/wifi: + + C-4378__s-B1/P-shikoku-X3_M-RASP_V-m__m-6.11.txt + +To prepare firmwares for Linux, we rename these to a scheme following +the existing brcmfmac convention: + + brcmfmac-pcie.apple,--\ + --.txt + +The NVRAM uses all the components, while the firmware and CLM blob only +use the chip/revision/platform/antenna_sku: + + brcmfmac-pcie.apple,-.bin + +e.g. + + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.bin + +In addition, since there are over 1000 files in total, many of which are +symlinks or outright duplicates, we deduplicate and prune the firmware +tree to reduce firmware filenames to fewer dimensions. For example, the +shikoku platform (MacBook Air M1 2020) simplifies to just 4 files: + + brcm/brcmfmac4378b1-pcie.apple,shikoku.clm_blob + brcm/brcmfmac4378b1-pcie.apple,shikoku.bin + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-u.txt + +This reduces the total file count to around 170, of which 75 are +symlinks and 95 are regular files: 7 firmware blobs, 27 CLM blobs, and +61 NVRAM config files. We also slightly process NVRAM files to correct +some formatting issues and add a missing default macaddr= property. + +To handle this, the driver must try the following path formats when +looking for firmware files: + + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP.txt + brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.txt * + brcm/brcmfmac4378b1-pcie.apple,shikoku.txt + +* Not relevant for NVRAM, only for for firmware/CLM. + +The chip revision nominally comes from OTP on Apple platforms, but it +can be mapped to the PCI revision number, so we ignore the OTP revision +and continue to use the existing PCI revision mechanism to identify chip +revisions, as the driver already does for other chips. Unfortunately, +the mapping is not consistent between different chip types, so this has +to be determined experimentally. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 68 +++++++++++++++++-- + 1 file changed, 63 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 0f19fc9b1..4f14b261a 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -2096,11 +2096,69 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1; + fwreq->bus_nr = devinfo->pdev->bus->number; + +- brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type); +- fwreq->board_types = devm_kzalloc(&devinfo->pdev->dev, +- sizeof(const char *) * 2, +- GFP_KERNEL); +- fwreq->board_types[0] = devinfo->settings->board_type; ++ /* Apple platforms with fancy firmware/NVRAM selection */ ++ if (devinfo->settings->board_type && ++ devinfo->settings->antenna_sku && ++ devinfo->otp.valid) { ++ char *buf; ++ int len; ++ ++ brcmf_dbg(PCIE, "Apple board: %s\n", ++ devinfo->settings->board_type); ++ ++ /* Example: apple,shikoku-RASP-m-6.11-X3 */ ++ len = (strlen(devinfo->settings->board_type) + 1 + ++ strlen(devinfo->otp.module) + 1 + ++ strlen(devinfo->otp.vendor) + 1 + ++ strlen(devinfo->otp.version) + 1 + ++ strlen(devinfo->settings->antenna_sku) + 1); ++ ++ fwreq->board_types = devm_kzalloc(&devinfo->pdev->dev, ++ sizeof(const char *) * 7, ++ GFP_KERNEL); ++ ++ /* apple,shikoku */ ++ fwreq->board_types[5] = devinfo->settings->board_type; ++ ++ buf = devm_kzalloc(&devinfo->pdev->dev, len, GFP_KERNEL); ++ ++ strlcpy(buf, devinfo->settings->board_type, len); ++ strlcat(buf, "-", len); ++ strlcat(buf, devinfo->settings->antenna_sku, len); ++ /* apple,shikoku-X3 */ ++ fwreq->board_types[4] = devm_kstrdup(&devinfo->pdev->dev, buf, ++ GFP_KERNEL); ++ ++ strlcpy(buf, devinfo->settings->board_type, len); ++ strlcat(buf, "-", len); ++ strlcat(buf, devinfo->otp.module, len); ++ /* apple,shikoku-RASP */ ++ fwreq->board_types[3] = devm_kstrdup(&devinfo->pdev->dev, buf, ++ GFP_KERNEL); ++ ++ strlcat(buf, "-", len); ++ strlcat(buf, devinfo->otp.vendor, len); ++ /* apple,shikoku-RASP-m */ ++ fwreq->board_types[2] = devm_kstrdup(&devinfo->pdev->dev, buf, ++ GFP_KERNEL); ++ ++ strlcat(buf, "-", len); ++ strlcat(buf, devinfo->otp.version, len); ++ /* apple,shikoku-RASP-m-6.11 */ ++ fwreq->board_types[1] = devm_kstrdup(&devinfo->pdev->dev, buf, ++ GFP_KERNEL); ++ ++ strlcat(buf, "-", len); ++ strlcat(buf, devinfo->settings->antenna_sku, len); ++ /* apple,shikoku-RASP-m-6.11-X3 */ ++ fwreq->board_types[0] = buf; ++ } else { ++ brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type); ++ fwreq->board_types = devm_kzalloc(&devinfo->pdev->dev, ++ sizeof(const char *) * 2, ++ GFP_KERNEL); ++ fwreq->board_types[0] = devinfo->settings->board_type; ++ } + + return fwreq; + } +-- +2.34.1 + diff --git a/8009-brcmfmac-firmware-Allow-platform-to-override-macaddr.patch b/8009-brcmfmac-firmware-Allow-platform-to-override-macaddr.patch new file mode 100644 index 0000000..92cecd8 --- /dev/null +++ b/8009-brcmfmac-firmware-Allow-platform-to-override-macaddr.patch @@ -0,0 +1,125 @@ +From dd4b327a30697ddad3819ca145d4ce319b7cf528 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Thu, 23 Dec 2021 22:32:08 +0900 +Subject: [PATCH 09/34] brcmfmac: firmware: Allow platform to override macaddr + +On Device Tree platforms, it is customary to be able to set the MAC +address via the Device Tree, as it is often stored in system firmware. +This is particularly relevant for Apple ARM64 platforms, where this +information comes from system configuration and passed through by the +bootloader into the DT. + +Implement support for this by fetching the platform MAC address and +adding or replacing the macaddr= property in nvram. This becomes the +dongle's default MAC address. + +On platforms with an SROM MAC address, this overrides it. On platforms +without one, such as Apple ARM64 devices, this is required for the +firmware to boot (it will fail if it does not have a valid MAC at all). + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/firmware.c | 30 +++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index 02e36fa3d..dc4151bcc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -21,6 +21,8 @@ + #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ + #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ + #define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff" ++#define BRCMF_FW_MACADDR_FMT "macaddr=%pM" ++#define BRCMF_FW_MACADDR_LEN (7 + ETH_ALEN * 3) + + enum nvram_parser_state { + IDLE, +@@ -57,6 +59,7 @@ struct nvram_parser { + bool multi_dev_v1; + bool multi_dev_v2; + bool boardrev_found; ++ bool strip_mac; + }; + + /* +@@ -121,6 +124,10 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) + nvp->multi_dev_v2 = true; + if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0) + nvp->boardrev_found = true; ++ /* strip macaddr if platform MAC overrides */ ++ if (nvp->strip_mac && ++ strncmp(&nvp->data[nvp->entry], "macaddr", 7) == 0) ++ st = COMMENT; + } else if (!is_nvram_char(c) || c == ' ') { + brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", + nvp->line, nvp->column); +@@ -207,6 +214,9 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp, + size = BRCMF_FW_MAX_NVRAM_SIZE; + else + size = data_len; ++ /* Add space for properties we may add */ ++ size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1; ++ size += BRCMF_FW_MACADDR_LEN + 1; + /* Alloc for extra 0 byte + roundup by 4 + length field */ + size += 1 + 3 + sizeof(u32); + nvp->nvram = kzalloc(size, GFP_KERNEL); +@@ -366,22 +376,34 @@ static void brcmf_fw_add_defaults(struct nvram_parser *nvp) + nvp->nvram_len++; + } + ++static void brcmf_fw_add_macaddr(struct nvram_parser *nvp, u8 *mac) ++{ ++ snprintf(&nvp->nvram[nvp->nvram_len], BRCMF_FW_MACADDR_LEN + 1, ++ BRCMF_FW_MACADDR_FMT, mac); ++ nvp->nvram_len += BRCMF_FW_MACADDR_LEN + 1; ++} ++ + /* brcmf_nvram_strip :Takes a buffer of "=\n" lines read from a fil + * and ending in a NUL. Removes carriage returns, empty lines, comment lines, + * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. + * End of buffer is completed with token identifying length of buffer. + */ + static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, +- u32 *new_length, u16 domain_nr, u16 bus_nr) ++ u32 *new_length, u16 domain_nr, u16 bus_nr, ++ struct device *dev) + { + struct nvram_parser nvp; + u32 pad; + u32 token; + __le32 token_le; ++ u8 mac[ETH_ALEN]; + + if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0) + return NULL; + ++ if (eth_platform_get_mac_address(dev, mac) == 0) ++ nvp.strip_mac = true; ++ + while (nvp.pos < data_len) { + nvp.state = nv_parser_states[nvp.state](&nvp); + if (nvp.state == END) +@@ -402,6 +424,9 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, + + brcmf_fw_add_defaults(&nvp); + ++ if (nvp.strip_mac) ++ brcmf_fw_add_macaddr(&nvp, mac); ++ + pad = nvp.nvram_len; + *new_length = roundup(nvp.nvram_len + 1, 4); + while (pad != *new_length) { +@@ -546,7 +571,8 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) + if (data) + nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, + fwctx->req->domain_nr, +- fwctx->req->bus_nr); ++ fwctx->req->bus_nr, ++ fwctx->dev); + + if (free_bcm47xx_nvram) + bcm47xx_nvram_release_contents(data); +-- +2.34.1 + diff --git a/8010-brcmfmac-msgbuf-Increase-RX-ring-sizes-to-1024.patch b/8010-brcmfmac-msgbuf-Increase-RX-ring-sizes-to-1024.patch new file mode 100644 index 0000000..c653193 --- /dev/null +++ b/8010-brcmfmac-msgbuf-Increase-RX-ring-sizes-to-1024.patch @@ -0,0 +1,34 @@ +From 531b129464e6f498270c8283f547d65fad32b1fb Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:39:04 +0900 +Subject: [PATCH 10/34] brcmfmac: msgbuf: Increase RX ring sizes to 1024 + +Newer chips used on Apple platforms have more than max_rxbufpost greater +than 512, which causes warnings when brcmf_msgbuf_rxbuf_data_fill tries +to put more in the ring than fit. Increase the ring sizes to 1024. + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +index 2e322edbb..6a849f4a9 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +@@ -8,10 +8,10 @@ + #ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF + + #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64 +-#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512 ++#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 1024 + #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64 + #define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024 +-#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512 ++#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 1024 + #define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512 + + #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40 +-- +2.34.1 + diff --git a/8011-brcmfmac-pcie-Fix-crashes-due-to-early-IRQs.patch b/8011-brcmfmac-pcie-Fix-crashes-due-to-early-IRQs.patch new file mode 100644 index 0000000..3650e06 --- /dev/null +++ b/8011-brcmfmac-pcie-Fix-crashes-due-to-early-IRQs.patch @@ -0,0 +1,62 @@ +From 60efee55336f83bb968713686bfd2c90d9b23733 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:44:00 +0900 +Subject: [PATCH 11/34] brcmfmac: pcie: Fix crashes due to early IRQs + +The driver was enabling IRQs before the message processing was +initialized. This could cause IRQs to come in too early and crash the +driver. Instead, move the IRQ enable and hostready to a bus preinit +function, at which point everything is properly initialized. + +Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.") +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 4f14b261a..7190b7b80 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1380,6 +1380,20 @@ static void brcmf_pcie_down(struct device *dev) + } + + ++static int brcmf_pcie_preinit(struct device *dev) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; ++ ++ brcmf_dbg(PCIE, "Enter\n"); ++ ++ brcmf_pcie_intr_enable(buspub->devinfo); ++ brcmf_pcie_hostready(buspub->devinfo); ++ ++ return 0; ++} ++ ++ + static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb) + { + return 0; +@@ -1489,6 +1503,7 @@ static int brcmf_pcie_reset(struct device *dev) + } + + static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { ++ .preinit = brcmf_pcie_preinit, + .txdata = brcmf_pcie_tx, + .stop = brcmf_pcie_down, + .txctl = brcmf_pcie_tx_ctlpkt, +@@ -2055,9 +2070,6 @@ static void brcmf_pcie_setup(struct device *dev, int ret, + + init_waitqueue_head(&devinfo->mbdata_resp_wait); + +- brcmf_pcie_intr_enable(devinfo); +- brcmf_pcie_hostready(devinfo); +- + ret = brcmf_attach(&devinfo->pdev->dev); + if (ret) + goto fail; +-- +2.34.1 + diff --git a/8012-brcmfmac-pcie-Support-PCIe-core-revisions-64.patch b/8012-brcmfmac-pcie-Support-PCIe-core-revisions-64.patch new file mode 100644 index 0000000..4aa472f --- /dev/null +++ b/8012-brcmfmac-pcie-Support-PCIe-core-revisions-64.patch @@ -0,0 +1,266 @@ +From 6de1197eadd384f977934fb85061db7108f0c86d Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:25:35 +0900 +Subject: [PATCH 12/34] brcmfmac: pcie: Support PCIe core revisions >= 64 + +These newer PCIe core revisions include new sets of registers that must +be used instead of the legacy ones. Introduce a brcmf_pcie_reginfo to +hold the specific register offsets and values to use for a given +platform, and change all the register accesses to indirect through it. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 127 +++++++++++++++--- + 1 file changed, 107 insertions(+), 20 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 7190b7b80..01c7b2703 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -117,6 +117,14 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + #define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124 + #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140 + #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144 ++#define BRCMF_PCIE_PCIE2REG_D2H_MAILBOX_0 0x148 ++#define BRCMF_PCIE_PCIE2REG_D2H_MAILBOX_1 0x14c ++ ++#define BRCMF_PCIE_64_PCIE2REG_INTMASK 0xC14 ++#define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT 0xC30 ++#define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK 0xC34 ++#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 0xA20 ++#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 0xA24 + + #define BRCMF_PCIE2_INTA 0x01 + #define BRCMF_PCIE2_INTB 0x02 +@@ -137,6 +145,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + #define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000 + #define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000 + ++#define BRCMF_PCIE_MB_INT_FN0 (BRCMF_PCIE_MB_INT_FN0_0 | \ ++ BRCMF_PCIE_MB_INT_FN0_1) + #define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \ + BRCMF_PCIE_MB_INT_D2H0_DB1 | \ + BRCMF_PCIE_MB_INT_D2H1_DB0 | \ +@@ -146,6 +156,40 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_PCIE_MB_INT_D2H3_DB0 | \ + BRCMF_PCIE_MB_INT_D2H3_DB1) + ++#define BRCMF_PCIE_64_MB_INT_D2H0_DB0 0x1 ++#define BRCMF_PCIE_64_MB_INT_D2H0_DB1 0x2 ++#define BRCMF_PCIE_64_MB_INT_D2H1_DB0 0x4 ++#define BRCMF_PCIE_64_MB_INT_D2H1_DB1 0x8 ++#define BRCMF_PCIE_64_MB_INT_D2H2_DB0 0x10 ++#define BRCMF_PCIE_64_MB_INT_D2H2_DB1 0x20 ++#define BRCMF_PCIE_64_MB_INT_D2H3_DB0 0x40 ++#define BRCMF_PCIE_64_MB_INT_D2H3_DB1 0x80 ++#define BRCMF_PCIE_64_MB_INT_D2H4_DB0 0x100 ++#define BRCMF_PCIE_64_MB_INT_D2H4_DB1 0x200 ++#define BRCMF_PCIE_64_MB_INT_D2H5_DB0 0x400 ++#define BRCMF_PCIE_64_MB_INT_D2H5_DB1 0x800 ++#define BRCMF_PCIE_64_MB_INT_D2H6_DB0 0x1000 ++#define BRCMF_PCIE_64_MB_INT_D2H6_DB1 0x2000 ++#define BRCMF_PCIE_64_MB_INT_D2H7_DB0 0x4000 ++#define BRCMF_PCIE_64_MB_INT_D2H7_DB1 0x8000 ++ ++#define BRCMF_PCIE_64_MB_INT_D2H_DB (BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \ ++ BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \ ++ BRCMF_PCIE_64_MB_INT_D2H7_DB1) ++ + #define BRCMF_PCIE_SHARED_VERSION_7 7 + #define BRCMF_PCIE_MIN_SHARED_VERSION 5 + #define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7 +@@ -272,6 +316,7 @@ struct brcmf_pciedev_info { + char nvram_name[BRCMF_FW_NAME_LEN]; + char clm_name[BRCMF_FW_NAME_LEN]; + const struct firmware *clm_fw; ++ const struct brcmf_pcie_reginfo *reginfo; + void __iomem *regs; + void __iomem *tcm; + u32 ram_base; +@@ -358,6 +403,36 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = { + BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE + }; + ++struct brcmf_pcie_reginfo { ++ u32 intmask; ++ u32 mailboxint; ++ u32 mailboxmask; ++ u32 h2d_mailbox_0; ++ u32 h2d_mailbox_1; ++ u32 int_d2h_db; ++ u32 int_fn0; ++}; ++ ++static const struct brcmf_pcie_reginfo brcmf_reginfo_default = { ++ .intmask = BRCMF_PCIE_PCIE2REG_INTMASK, ++ .mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT, ++ .mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK, ++ .h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, ++ .h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, ++ .int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB, ++ .int_fn0 = BRCMF_PCIE_MB_INT_FN0, ++}; ++ ++static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = { ++ .intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK, ++ .mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT, ++ .mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK, ++ .h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, ++ .h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, ++ .int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB, ++ .int_fn0 = 0, ++}; ++ + static void brcmf_pcie_setup(struct device *dev, int ret, + struct brcmf_fw_request *fwreq); + static struct brcmf_fw_request * +@@ -841,30 +916,29 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, + + static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo) + { +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0); ++ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0); + } + + + static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo) + { +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, +- BRCMF_PCIE_MB_INT_D2H_DB | +- BRCMF_PCIE_MB_INT_FN0_0 | +- BRCMF_PCIE_MB_INT_FN0_1); ++ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, ++ devinfo->reginfo->int_d2h_db | ++ devinfo->reginfo->int_fn0); + } + + static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo) + { + if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) + brcmf_pcie_write_reg32(devinfo, +- BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1); ++ devinfo->reginfo->h2d_mailbox_1, 1); + } + + static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg) + { + struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; + +- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) { ++ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) { + brcmf_pcie_intr_disable(devinfo); + brcmf_dbg(PCIE, "Enter\n"); + return IRQ_WAKE_THREAD; +@@ -879,15 +953,14 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg) + u32 status; + + devinfo->in_irq = true; +- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); ++ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint); + brcmf_dbg(PCIE, "Enter %x\n", status); + if (status) { +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, ++ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, + status); +- if (status & (BRCMF_PCIE_MB_INT_FN0_0 | +- BRCMF_PCIE_MB_INT_FN0_1)) ++ if (status & devinfo->reginfo->int_fn0) + brcmf_pcie_handle_mb_data(devinfo); +- if (status & BRCMF_PCIE_MB_INT_D2H_DB) { ++ if (status & devinfo->reginfo->int_d2h_db) { + if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) + brcmf_proto_msgbuf_rx_trigger( + &devinfo->pdev->dev); +@@ -946,8 +1019,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) + if (devinfo->in_irq) + brcmf_err(bus, "Still in IRQ (processing) !!!\n"); + +- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status); ++ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint); ++ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status); + + devinfo->irq_allocated = false; + } +@@ -999,7 +1072,7 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx) + + brcmf_dbg(PCIE, "RING !\n"); + /* Any arbitrary value will do, lets use 1 */ +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1); ++ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1); + + return 0; + } +@@ -1763,15 +1836,22 @@ static int brcmf_pcie_buscoreprep(void *ctx) + static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) + { + struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; +- u32 val; ++ struct brcmf_core *core; ++ u32 val, reg; + + devinfo->ci = chip; + brcmf_pcie_reset_device(devinfo); + +- val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); ++ /* reginfo is not ready yet */ ++ core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2); ++ if (core->rev >= 64) ++ reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT; ++ else ++ reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT; ++ ++ val = brcmf_pcie_read_reg32(devinfo, reg); + if (val != 0xffffffff) +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, +- val); ++ brcmf_pcie_write_reg32(devinfo, reg, val); + + return 0; + } +@@ -2183,6 +2263,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) + struct brcmf_pciedev_info *devinfo; + struct brcmf_pciedev *pcie_bus_dev; + struct brcmf_bus *bus; ++ struct brcmf_core *core; + + brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device); + +@@ -2201,6 +2282,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto fail; + } + ++ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); ++ if (core->rev >= 64) ++ devinfo->reginfo = &brcmf_reginfo_64; ++ else ++ devinfo->reginfo = &brcmf_reginfo_default; ++ + pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL); + if (pcie_bus_dev == NULL) { + ret = -ENOMEM; +@@ -2369,7 +2456,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev) + brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus); + + /* Check if device is still up and running, if so we are ready */ +- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) { ++ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) { + brcmf_dbg(PCIE, "Try to wakeup device....\n"); + if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM)) + goto cleanup; +-- +2.34.1 + diff --git a/8013-brcmfmac-pcie-Add-IDs-properties-for-BCM4378.patch b/8013-brcmfmac-pcie-Add-IDs-properties-for-BCM4378.patch new file mode 100644 index 0000000..e7a874b --- /dev/null +++ b/8013-brcmfmac-pcie-Add-IDs-properties-for-BCM4378.patch @@ -0,0 +1,96 @@ +From d37f0e2bd8a981c82aaec33c4916b216a245d87c Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:46:40 +0900 +Subject: [PATCH 13/34] brcmfmac: pcie: Add IDs/properties for BCM4378 + +This chip is present on Apple M1 (t8103) platforms: + +* atlantisb (apple,j274): Mac mini (M1, 2020) +* honshu (apple,j293): MacBook Pro (13-inch, M1, 2020) +* shikoku (apple,j313): MacBook Air (M1, 2020) +* capri (apple,j456): iMac (24-inch, 4x USB-C, M1, 2020) +* santorini (apple,j457): iMac (24-inch, 2x USB-C, M1, 2020) + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++ + .../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ + 3 files changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index 1ee49f9e3..56a6f4168 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -731,6 +731,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) + return 0x160000; + case CY_CC_43752_CHIP_ID: + return 0x170000; ++ case BRCM_CC_4378_CHIP_ID: ++ return 0x352000; + default: + brcmf_err("unknown chip: %s\n", ci->pub.name); + break; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 01c7b2703..e1bc7e4a9 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -58,6 +58,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); + BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); + BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); + BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); ++BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie"); + + /* firmware config files */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt"); +@@ -87,6 +88,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), ++ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* 3 */ + }; + + #define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */ +@@ -2015,6 +2017,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + int ret; + + switch (devinfo->ci->chip) { ++ case BRCM_CC_4378_CHIP_ID: ++ coreid = BCMA_CORE_GCI; ++ base = 0x1120; ++ words = 0x170; ++ break; + default: + /* OTP not supported on this chip */ + return 0; +@@ -2522,6 +2529,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID), ++ BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID), + { /* end: all zeroes */ } + }; + +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 9d8132016..8f552b53f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -50,6 +50,7 @@ + #define BRCM_CC_43664_CHIP_ID 43664 + #define BRCM_CC_43666_CHIP_ID 43666 + #define BRCM_CC_4371_CHIP_ID 0x4371 ++#define BRCM_CC_4378_CHIP_ID 0x4378 + #define CY_CC_4373_CHIP_ID 0x4373 + #define CY_CC_43012_CHIP_ID 43012 + #define CY_CC_43752_CHIP_ID 43752 +@@ -85,6 +86,7 @@ + #define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4 + #define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 + #define BRCM_PCIE_4371_DEVICE_ID 0x440d ++#define BRCM_PCIE_4378_DEVICE_ID 0x4425 + + + /* brcmsmac IDs */ +-- +2.34.1 + diff --git a/8014-ACPI-property-Support-strings-in-Apple-_DSM-props.patch b/8014-ACPI-property-Support-strings-in-Apple-_DSM-props.patch new file mode 100644 index 0000000..5cb777d --- /dev/null +++ b/8014-ACPI-property-Support-strings-in-Apple-_DSM-props.patch @@ -0,0 +1,53 @@ +From 599bfcd71c7c6b995db7a4453e03244d032b4317 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Thu, 23 Dec 2021 19:51:11 +0900 +Subject: [PATCH 14/34] ACPI / property: Support strings in Apple _DSM props + +The Wi-Fi module in Apple machines has a "module-instance" device +property that specifies the platform type and is used for firmware +selection. Its value is a string, so add support for string values in +acpi_extract_apple_properties(). + +Signed-off-by: Hector Martin +--- + drivers/acpi/x86/apple.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/acpi/x86/apple.c b/drivers/acpi/x86/apple.c +index c285c91a5..1f5a0694c 100644 +--- a/drivers/acpi/x86/apple.c ++++ b/drivers/acpi/x86/apple.c +@@ -70,13 +70,16 @@ void acpi_extract_apple_properties(struct acpi_device *adev) + + if ( key->type != ACPI_TYPE_STRING || + (val->type != ACPI_TYPE_INTEGER && +- val->type != ACPI_TYPE_BUFFER)) ++ val->type != ACPI_TYPE_BUFFER && ++ val->type != ACPI_TYPE_STRING)) + continue; /* skip invalid properties */ + + __set_bit(i, valid); + newsize += key->string.length + 1; + if ( val->type == ACPI_TYPE_BUFFER) + newsize += val->buffer.length; ++ else if ( val->type == ACPI_TYPE_STRING) ++ newsize += val->string.length + 1; + } + + numvalid = bitmap_weight(valid, numprops); +@@ -118,6 +121,12 @@ void acpi_extract_apple_properties(struct acpi_device *adev) + newprops[v].type = val->type; + if (val->type == ACPI_TYPE_INTEGER) { + newprops[v].integer.value = val->integer.value; ++ } else if (val->type == ACPI_TYPE_STRING) { ++ newprops[v].string.length = val->string.length; ++ newprops[v].string.pointer = free_space; ++ memcpy(free_space, val->string.pointer, ++ val->string.length); ++ free_space += val->string.length + 1; + } else { + newprops[v].buffer.length = val->buffer.length; + newprops[v].buffer.pointer = free_space; +-- +2.34.1 + diff --git a/8015-brcmfmac-acpi-Add-support-for-fetching-Apple-ACPI-pr.patch b/8015-brcmfmac-acpi-Add-support-for-fetching-Apple-ACPI-pr.patch new file mode 100644 index 0000000..14f0f98 --- /dev/null +++ b/8015-brcmfmac-acpi-Add-support-for-fetching-Apple-ACPI-pr.patch @@ -0,0 +1,127 @@ +From ebdaee11be6e18ea1952a72a4a9ef80ca4228b7d Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Thu, 23 Dec 2021 19:51:36 +0900 +Subject: [PATCH 15/34] 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: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/Makefile | 2 + + .../broadcom/brcm80211/brcmfmac/acpi.c | 52 +++++++++++++++++++ + .../broadcom/brcm80211/brcmfmac/common.c | 1 + + .../broadcom/brcm80211/brcmfmac/common.h | 9 ++++ + 4 files changed, 64 insertions(+) + create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +index 13c13504a..19009eb9d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +@@ -47,3 +47,5 @@ brcmfmac-$(CONFIG_OF) += \ + of.o + brcmfmac-$(CONFIG_DMI) += \ + dmi.o ++brcmfmac-$(CONFIG_ACPI) += \ ++ acpi.o +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c +new file mode 100644 +index 000000000..b70cd6970 +--- /dev/null ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: ISC ++/* ++ * Copyright The Asahi Linux Contributors ++ */ ++ ++#include ++#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; ++ struct acpi_device *adev = ACPI_COMPANION(dev); ++ const union acpi_object *o; ++ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; ++ ++ if (!adev) { ++ return; ++ } ++ ++ if (!ACPI_FAILURE(acpi_dev_get_property(adev, "module-instance", ++ ACPI_TYPE_STRING, &o))) { ++ const char *prefix = "apple,"; ++ int len = strlen(prefix) + o->string.length + 1; ++ char *board_type = devm_kzalloc(dev, len, GFP_KERNEL); ++ ++ strlcpy(board_type, prefix, len); ++ strlcat(board_type, o->string.pointer, len); ++ brcmf_dbg(INFO, "ACPI module-instance=%s\n", o->string.pointer); ++ settings->board_type = board_type; ++ } else { ++ brcmf_dbg(INFO, "No ACPI module-instance\n"); ++ } ++ ++ 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); ++ ++ 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; ++ } else { ++ brcmf_dbg(INFO, "No ACPI antenna-sku\n"); ++ } ++} +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index b8ed85112..c84c48e49 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -437,6 +437,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; + } +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +index d4aa25d64..a88c4a931 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -73,6 +73,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); +-- +2.34.1 + diff --git a/8016-brcmfmac-pcie-Provide-a-buffer-of-random-bytes-to-th.patch b/8016-brcmfmac-pcie-Provide-a-buffer-of-random-bytes-to-th.patch new file mode 100644 index 0000000..ab7fba4 --- /dev/null +++ b/8016-brcmfmac-pcie-Provide-a-buffer-of-random-bytes-to-th.patch @@ -0,0 +1,83 @@ +From 3ecb57b6628211ef42a6267f17a1d5c5fcecd012 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Thu, 23 Dec 2021 19:30:17 +0900 +Subject: [PATCH 16/34] brcmfmac: pcie: Provide a buffer of random bytes to the + device + +Newer Apple firmwares on chipsets without a hardware RNG require the +host to provide a buffer of 256 random bytes to the device on +initialization. This buffer is present immediately before NVRAM, +suffixed by a footer containing a magic number and the buffer length. + +This won't affect chips/firmwares that do not use this feature, so do it +unconditionally. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index e1bc7e4a9..b71952254 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -1667,6 +1668,13 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, + return 0; + } + ++struct brcmf_random_seed_footer { ++ __le32 length; ++ __le32 magic; ++}; ++ ++#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de ++#define BRCMF_RANDOM_SEED_LENGTH 0x100 + + static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + const struct firmware *fw, void *nvram, +@@ -1698,11 +1706,34 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0); + + if (nvram) { ++ size_t rand_len = BRCMF_RANDOM_SEED_LENGTH; ++ struct brcmf_random_seed_footer footer = { ++ .length = cpu_to_le32(rand_len), ++ .magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC), ++ }; ++ void *randbuf; ++ + brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name); + address = devinfo->ci->rambase + devinfo->ci->ramsize - + nvram_len; + brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len); + brcmf_fw_nvram_free(nvram); ++ ++ /* ++ * Some Apple chips/firmwares expect a buffer of random data ++ * to be present before NVRAM ++ */ ++ brcmf_dbg(PCIE, "Download random seed\n"); ++ ++ address -= sizeof(footer); ++ brcmf_pcie_copy_mem_todev(devinfo, address, &footer, ++ sizeof(footer)); ++ ++ address -= rand_len; ++ randbuf = kzalloc(rand_len, GFP_KERNEL); ++ get_random_bytes(randbuf, rand_len); ++ brcmf_pcie_copy_mem_todev(devinfo, address, randbuf, rand_len); ++ kfree(randbuf); + } else { + brcmf_dbg(PCIE, "No matching NVRAM file found %s\n", + devinfo->nvram_name); +-- +2.34.1 + diff --git a/8017-brcmfmac-pcie-Add-IDs-properties-for-BCM4355.patch b/8017-brcmfmac-pcie-Add-IDs-properties-for-BCM4355.patch new file mode 100644 index 0000000..fd724aa --- /dev/null +++ b/8017-brcmfmac-pcie-Add-IDs-properties-for-BCM4355.patch @@ -0,0 +1,92 @@ +From e46046ce92838278ec265de9d662ca3ee0be8cef Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:50:15 +0900 +Subject: [PATCH 17/34] brcmfmac: pcie: Add IDs/properties for BCM4355 + +This chip is present on at least these Apple T2 Macs: + +* hawaii: MacBook Air 13" (Late 2018) +* hawaii: MacBook Air 13" (True Tone, 2019) + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++ + .../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ + 3 files changed, 11 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index 56a6f4168..fdff7f5fc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -726,6 +726,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) + return 0x200000; + case BRCM_CC_4359_CHIP_ID: + return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; ++ case BRCM_CC_4355_CHIP_ID: + case BRCM_CC_4364_CHIP_ID: + case CY_CC_4373_CHIP_ID: + return 0x160000; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index b71952254..6d95c704f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -49,6 +49,7 @@ enum brcmf_pcie_state { + BRCMF_FW_DEF(43602, "brcmfmac43602-pcie"); + BRCMF_FW_DEF(4350, "brcmfmac4350-pcie"); + BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie"); ++BRCMF_FW_CLM_DEF(4355C1, "brcmfmac4355c1-pcie"); + BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-pcie"); + BRCMF_FW_CLM_DEF(43570, "brcmfmac43570-pcie"); + BRCMF_FW_DEF(4358, "brcmfmac4358-pcie"); +@@ -75,6 +76,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C), + BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350), + BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C), ++ BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0xFFFFFFFF, 4355C1), /* 12 */ + BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), + BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570), + BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570), +@@ -2048,6 +2050,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + int ret; + + switch (devinfo->ci->chip) { ++ case BRCM_CC_4355_CHIP_ID: ++ coreid = BCMA_CORE_CHIPCOMMON; ++ base = 0x8c0; ++ words = 0xb2; ++ break; + case BRCM_CC_4378_CHIP_ID: + coreid = BCMA_CORE_GCI; + base = 0x1120; +@@ -2542,6 +2549,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID), + BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID), ++ BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 8f552b53f..9636ab4dd 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -36,6 +36,7 @@ + #define BRCM_CC_4350_CHIP_ID 0x4350 + #define BRCM_CC_43525_CHIP_ID 43525 + #define BRCM_CC_4354_CHIP_ID 0x4354 ++#define BRCM_CC_4355_CHIP_ID 0x4355 + #define BRCM_CC_4356_CHIP_ID 0x4356 + #define BRCM_CC_43566_CHIP_ID 43566 + #define BRCM_CC_43567_CHIP_ID 43567 +@@ -69,6 +70,7 @@ + #define BRCM_PCIE_4350_DEVICE_ID 0x43a3 + #define BRCM_PCIE_4354_DEVICE_ID 0x43df + #define BRCM_PCIE_4354_RAW_DEVICE_ID 0x4354 ++#define BRCM_PCIE_4355_DEVICE_ID 0x43dc + #define BRCM_PCIE_4356_DEVICE_ID 0x43ec + #define BRCM_PCIE_43567_DEVICE_ID 0x43d3 + #define BRCM_PCIE_43570_DEVICE_ID 0x43d9 +-- +2.34.1 + diff --git a/8018-brcmfmac-pcie-Add-IDs-properties-for-BCM4377.patch b/8018-brcmfmac-pcie-Add-IDs-properties-for-BCM4377.patch new file mode 100644 index 0000000..b66d097 --- /dev/null +++ b/8018-brcmfmac-pcie-Add-IDs-properties-for-BCM4377.patch @@ -0,0 +1,89 @@ +From a014d5ec01f8b9084b55a368f5847105c5a87758 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:51:31 +0900 +Subject: [PATCH 18/34] brcmfmac: pcie: Add IDs/properties for BCM4377 + +This chip is present on at least these Apple T2 Macs: + +* tahiti: MacBook Pro 13" (2020, 2 TB3) +* formosa: MacBook Pro 13" (Touch/2019) +* fiji: MacBook Air 13" (Scissor, 2020) + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++ + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ + 3 files changed, 7 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index fdff7f5fc..73ab96968 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -731,6 +731,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) + case CY_CC_4373_CHIP_ID: + return 0x160000; + case CY_CC_43752_CHIP_ID: ++ case BRCM_CC_4377_CHIP_ID: + return 0x170000; + case BRCM_CC_4378_CHIP_ID: + return 0x352000; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 6d95c704f..5b4a4cb33 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -60,6 +60,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); + BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); + BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); + BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); ++BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); + BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie"); + + /* firmware config files */ +@@ -91,6 +92,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), ++ BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* 4 */ + BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* 3 */ + }; + +@@ -2055,6 +2057,7 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + base = 0x8c0; + words = 0xb2; + break; ++ case BRCM_CC_4377_CHIP_ID: + case BRCM_CC_4378_CHIP_ID: + coreid = BCMA_CORE_GCI; + base = 0x1120; +@@ -2568,6 +2571,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID), ++ BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID), + { /* end: all zeroes */ } + }; +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 9636ab4dd..54d7ec515 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -51,6 +51,7 @@ + #define BRCM_CC_43664_CHIP_ID 43664 + #define BRCM_CC_43666_CHIP_ID 43666 + #define BRCM_CC_4371_CHIP_ID 0x4371 ++#define BRCM_CC_4377_CHIP_ID 0x4377 + #define BRCM_CC_4378_CHIP_ID 0x4378 + #define CY_CC_4373_CHIP_ID 0x4373 + #define CY_CC_43012_CHIP_ID 43012 +@@ -88,6 +89,7 @@ + #define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4 + #define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 + #define BRCM_PCIE_4371_DEVICE_ID 0x440d ++#define BRCM_PCIE_4377_DEVICE_ID 0x4488 + #define BRCM_PCIE_4378_DEVICE_ID 0x4425 + + +-- +2.34.1 + diff --git a/8019-brcmfmac-pcie-Perform-correct-BCM4364-firmware-selec.patch b/8019-brcmfmac-pcie-Perform-correct-BCM4364-firmware-selec.patch new file mode 100644 index 0000000..f493ec5 --- /dev/null +++ b/8019-brcmfmac-pcie-Perform-correct-BCM4364-firmware-selec.patch @@ -0,0 +1,78 @@ +From 680ef41dd2e00b3e891e62f5ed8a746e96b8567d Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:51:52 +0900 +Subject: [PATCH 19/34] brcmfmac: pcie: Perform correct BCM4364 firmware + selection + +This chip exists in two revisions (B2=r3 and B3=r4) on different +platforms, and was added without regard to doing proper firmware +selection or differentiating between them. Fix this to have proper +per-revision firmwares and support Apple NVRAM selection. + +Revision B2 is present on at least these Apple T2 Macs: + +kauai: MacBook Pro 15" (Touch/2018-2019) +maui: MacBook Pro 13" (Touch/2018-2019) +lanai: Mac mini (Late 2018) +ekans: iMac Pro 27" (5K, Late 2017) + +And these non-T2 Macs: + +nihau: iMac 27" (5K, 2019) + +Revision B3 is present on at least these Apple T2 Macs: + +bali: MacBook Pro 16" (2019) +trinidad: MacBook Pro 13" (2020, 4 TB3) +borneo: MacBook Pro 16" (2019, 5600M) +kahana: Mac Pro (2019) +kahana: Mac Pro (2019, Rack) +hanauma: iMac 27" (5K, 2020) +kure: iMac 27" (5K, 2020, 5700/XT) + +Cc: brian m. carlson +Fixes: 24f0bd136264 ("brcmfmac: add the BRCM 4364 found in MacBook Pro 15,2") +Signed-off-by: Hector Martin +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 5b4a4cb33..b6b789b49 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -54,7 +54,8 @@ BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-pcie"); + BRCMF_FW_CLM_DEF(43570, "brcmfmac43570-pcie"); + BRCMF_FW_DEF(4358, "brcmfmac4358-pcie"); + BRCMF_FW_DEF(4359, "brcmfmac4359-pcie"); +-BRCMF_FW_DEF(4364, "brcmfmac4364-pcie"); ++BRCMF_FW_CLM_DEF(4364B2, "brcmfmac4364b2-pcie"); ++BRCMF_FW_CLM_DEF(4364B3, "brcmfmac4364b3-pcie"); + BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie"); + BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); + BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); +@@ -84,7 +85,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570), + BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), + BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), +- BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFFF, 4364), ++ BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0x0000000F, 4364B2), /* 3 */ ++ BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFF0, 4364B3), /* 4 */ + BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B), + BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C), + BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), +@@ -2057,6 +2059,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + base = 0x8c0; + words = 0xb2; + break; ++ case BRCM_CC_4364_CHIP_ID: ++ coreid = BCMA_CORE_CHIPCOMMON; ++ base = 0x8c0; ++ words = 0x1a0; ++ break; + case BRCM_CC_4377_CHIP_ID: + case BRCM_CC_4378_CHIP_ID: + coreid = BCMA_CORE_GCI; +-- +2.34.1 + diff --git a/8020-brcmfmac-chip-Only-disable-D11-cores-handle-an-arbit.patch b/8020-brcmfmac-chip-Only-disable-D11-cores-handle-an-arbit.patch new file mode 100644 index 0000000..45afc59 --- /dev/null +++ b/8020-brcmfmac-chip-Only-disable-D11-cores-handle-an-arbit.patch @@ -0,0 +1,53 @@ +From 9600a63e7c36866faac8c458dc48ba9eb19032bc Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Mon, 20 Dec 2021 20:00:57 +0900 +Subject: [PATCH 20/34] brcmfmac: chip: Only disable D11 cores; handle an + arbitrary number + +At least on BCM4387, the D11 cores are held in reset on cold startup and +firmware expects to release reset itself. Just assert reset here and let +firmware deassert it. Premature deassertion results in the firmware +failing to initialize properly some of the time, with strange AXI bus +errors. + +Also, BCM4387 has 3 cores, up from 2. The logic for handling that is in +brcmf_chip_ai_resetcore(), but since we aren't using that any more, just +handle it here. + +Signed-off-by: Hector Martin +--- + .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index 73ab96968..15a1211f0 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -1289,15 +1289,19 @@ static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) + static inline void + brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) + { ++ int i; + struct brcmf_core *core; + + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); + +- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); +- brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | +- D11_BCMA_IOCTL_PHYCLOCKEN, +- D11_BCMA_IOCTL_PHYCLOCKEN, +- D11_BCMA_IOCTL_PHYCLOCKEN); ++ /* ++ * Disable the cores only and let the firmware enable them. ++ * Releasing reset ourselves breaks BCM4387 in weird ways. ++ */ ++ for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++) ++ brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET | ++ D11_BCMA_IOCTL_PHYCLOCKEN, ++ D11_BCMA_IOCTL_PHYCLOCKEN); + } + + static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) +-- +2.34.1 + diff --git a/8021-brcmfmac-chip-Handle-1024-unit-sizes-for-TCM-blocks.patch b/8021-brcmfmac-chip-Handle-1024-unit-sizes-for-TCM-blocks.patch new file mode 100644 index 0000000..00552b7 --- /dev/null +++ b/8021-brcmfmac-chip-Handle-1024-unit-sizes-for-TCM-blocks.patch @@ -0,0 +1,73 @@ +From 505a2532e3795409d3f179ade118845992c30a14 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:14:59 +0900 +Subject: [PATCH 21/34] brcmfmac: chip: Handle 1024-unit sizes for TCM blocks + +BCM4387 has trailing odd-sized blocks as part of TCM which have +their size described as a multiple of 1024 instead of 8192. Handle this +so we can compute the TCM size properly. + +Signed-off-by: Hector Martin +--- + .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index 15a1211f0..c4c80664b 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -212,8 +212,8 @@ struct sbsocramregs { + #define ARMCR4_TCBANB_MASK 0xf + #define ARMCR4_TCBANB_SHIFT 0 + +-#define ARMCR4_BSZ_MASK 0x3f +-#define ARMCR4_BSZ_MULT 8192 ++#define ARMCR4_BSZ_MASK 0x7f ++#define ARMCR4_BLK_1K_MASK 0x200 + + struct brcmf_core_priv { + struct brcmf_core pub; +@@ -675,7 +675,8 @@ static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) + } + + /** Return the TCM-RAM size of the ARMCR4 core. */ +-static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) ++static u32 brcmf_chip_tcm_ramsize(struct brcmf_chip_priv *ci, ++ struct brcmf_core_priv *cr4) + { + u32 corecap; + u32 memsize = 0; +@@ -683,6 +684,7 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) + u32 nbb; + u32 totb; + u32 bxinfo; ++ u32 blksize; + u32 idx; + + corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); +@@ -694,7 +696,12 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) + for (idx = 0; idx < totb; idx++) { + brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); + bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); +- memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; ++ if (bxinfo & ARMCR4_BLK_1K_MASK) ++ blksize = 1024; ++ else ++ blksize = 8192; ++ ++ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize; + } + + return memsize; +@@ -752,7 +759,7 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub) + mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); + if (mem) { + mem_core = container_of(mem, struct brcmf_core_priv, pub); +- ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); ++ ci->pub.ramsize = brcmf_chip_tcm_ramsize(ci, mem_core); + ci->pub.rambase = brcmf_chip_tcm_rambase(ci); + if (ci->pub.rambase == INVALID_RAMBASE) { + brcmf_err("RAM base not provided with ARM CR4 core\n"); +-- +2.34.1 + diff --git a/8022-brcmfmac-cfg80211-Add-support-for-scan-params-v2.patch b/8022-brcmfmac-cfg80211-Add-support-for-scan-params-v2.patch new file mode 100644 index 0000000..e65acf3 --- /dev/null +++ b/8022-brcmfmac-cfg80211-Add-support-for-scan-params-v2.patch @@ -0,0 +1,335 @@ +From db9e401c2913bb2f8055ace80e99d1a5578a08b1 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Mon, 20 Dec 2021 03:39:44 +0900 +Subject: [PATCH 22/34] brcmfmac: cfg80211: Add support for scan params v2 + +This new API version is required for at least the BCM4387 firmware. Add +support for it, with a fallback to the v1 API. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 113 ++++++++++++++---- + .../broadcom/brcm80211/brcmfmac/feature.c | 1 + + .../broadcom/brcm80211/brcmfmac/feature.h | 4 +- + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 49 +++++++- + 4 files changed, 145 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index ba5231861..f9de22f77 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -769,12 +769,50 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc) + } + } + ++static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, ++ struct brcmf_scan_params_v2_le *params_le, ++ struct cfg80211_scan_request *request); ++ ++static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le, ++ struct brcmf_scan_params_le *params_le) ++{ ++ size_t params_size; ++ uint32_t ch; ++ int n_channels, n_ssids; ++ ++ memcpy(¶ms_le->ssid_le, ¶ms_v2_le->ssid_le, ++ sizeof(params_le->ssid_le)); ++ memcpy(¶ms_le->bssid, ¶ms_v2_le->bssid, ++ sizeof(params_le->bssid)); ++ ++ params_le->bss_type = params_v2_le->bss_type; ++ params_le->scan_type = params_v2_le->scan_type; ++ params_le->nprobes = params_v2_le->nprobes; ++ params_le->active_time = params_v2_le->active_time; ++ params_le->passive_time = params_v2_le->passive_time; ++ params_le->home_time = params_v2_le->home_time; ++ params_le->channel_num = params_v2_le->channel_num; ++ ++ ch = le32_to_cpu(params_v2_le->channel_num); ++ n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK; ++ n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT; ++ ++ params_size = sizeof(u16) * n_channels; ++ if (n_ssids > 0) { ++ params_size = roundup(params_size, sizeof(u32)); ++ params_size += sizeof(struct brcmf_ssid_le) * n_ssids; ++ } ++ ++ memcpy(¶ms_le->channel_list[0], ++ ¶ms_v2_le->channel_list[0], params_size); ++} ++ + s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, + struct brcmf_if *ifp, bool aborted, + bool fw_abort) + { + struct brcmf_pub *drvr = cfg->pub; +- struct brcmf_scan_params_le params_le; ++ struct brcmf_scan_params_v2_le params_v2_le; + struct cfg80211_scan_request *scan_request; + u64 reqid; + u32 bucket; +@@ -793,20 +831,23 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, + if (fw_abort) { + /* Do a scan abort to stop the driver's scan engine */ + brcmf_dbg(SCAN, "ABORT scan in firmware\n"); +- memset(¶ms_le, 0, sizeof(params_le)); +- eth_broadcast_addr(params_le.bssid); +- params_le.bss_type = DOT11_BSSTYPE_ANY; +- params_le.scan_type = 0; +- params_le.channel_num = cpu_to_le32(1); +- params_le.nprobes = cpu_to_le32(1); +- params_le.active_time = cpu_to_le32(-1); +- params_le.passive_time = cpu_to_le32(-1); +- params_le.home_time = cpu_to_le32(-1); +- /* Scan is aborted by setting channel_list[0] to -1 */ +- params_le.channel_list[0] = cpu_to_le16(-1); ++ ++ brcmf_escan_prep(cfg, ¶ms_v2_le, NULL); ++ + /* E-Scan (or anyother type) can be aborted by SCAN */ +- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, +- ¶ms_le, sizeof(params_le)); ++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) { ++ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, ++ ¶ms_v2_le, ++ sizeof(params_v2_le)); ++ } else { ++ struct brcmf_scan_params_le params_le; ++ ++ brcmf_scan_params_v2_to_v1(¶ms_v2_le, ¶ms_le); ++ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, ++ ¶ms_le, ++ sizeof(params_le)); ++ } ++ + if (err) + bphy_err(drvr, "Scan abort failed\n"); + } +@@ -1026,7 +1067,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + } + + static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, +- struct brcmf_scan_params_le *params_le, ++ struct brcmf_scan_params_v2_le *params_le, + struct cfg80211_scan_request *request) + { + u32 n_ssids; +@@ -1035,9 +1076,14 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, + s32 offset; + u16 chanspec; + char *ptr; ++ int length; + struct brcmf_ssid_le ssid_le; + + eth_broadcast_addr(params_le->bssid); ++ ++ length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE; ++ ++ params_le->version = BRCMF_SCAN_PARAMS_VERSION_V2; + params_le->bss_type = DOT11_BSSTYPE_ANY; + params_le->scan_type = BRCMF_SCANTYPE_ACTIVE; + params_le->channel_num = 0; +@@ -1047,6 +1093,15 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, + params_le->home_time = cpu_to_le32(-1); + memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le)); + ++ /* Scan abort */ ++ if (!request) { ++ length += sizeof(u16); ++ params_le->channel_num = cpu_to_le32(1); ++ params_le->channel_list[0] = cpu_to_le16(-1); ++ params_le->length = cpu_to_le16(length); ++ return; ++ } ++ + n_ssids = request->n_ssids; + n_channels = request->n_channels; + +@@ -1054,6 +1109,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, + brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n", + n_channels); + if (n_channels > 0) { ++ length += roundup(sizeof(u16) * n_channels, sizeof(u32)); + for (i = 0; i < n_channels; i++) { + chanspec = channel_to_chanspec(&cfg->d11inf, + request->channels[i]); +@@ -1064,12 +1120,14 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, + } else { + brcmf_dbg(SCAN, "Scanning all channels\n"); + } ++ + /* Copy ssid array if applicable */ + brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids); + if (n_ssids > 0) { +- offset = offsetof(struct brcmf_scan_params_le, channel_list) + ++ offset = offsetof(struct brcmf_scan_params_v2_le, channel_list) + + n_channels * sizeof(u16); + offset = roundup(offset, sizeof(u32)); ++ length += sizeof(ssid_le) * n_ssids, + ptr = (char *)params_le + offset; + for (i = 0; i < n_ssids; i++) { + memset(&ssid_le, 0, sizeof(ssid_le)); +@@ -1089,6 +1147,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, + brcmf_dbg(SCAN, "Performing passive scan\n"); + params_le->scan_type = BRCMF_SCANTYPE_PASSIVE; + } ++ params_le->length = cpu_to_le16(length); + /* Adding mask to channel numbers */ + params_le->channel_num = + cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) | +@@ -1100,8 +1159,8 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, + struct cfg80211_scan_request *request) + { + struct brcmf_pub *drvr = cfg->pub; +- s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + +- offsetof(struct brcmf_escan_params_le, params_le); ++ s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE + ++ offsetof(struct brcmf_escan_params_le, params_v2_le); + struct brcmf_escan_params_le *params; + s32 err = 0; + +@@ -1121,8 +1180,22 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, + goto exit; + } + BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN); +- brcmf_escan_prep(cfg, ¶ms->params_le, request); +- params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); ++ brcmf_escan_prep(cfg, ¶ms->params_v2_le, request); ++ ++ params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2); ++ ++ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) { ++ struct brcmf_escan_params_le *params_v1; ++ ++ params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE; ++ params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE; ++ params_v1 = kzalloc(params_size, GFP_KERNEL); ++ params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); ++ brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le); ++ kfree(params); ++ params = params_v1; ++ } ++ + params->action = cpu_to_le16(WL_ESCAN_ACTION_START); + params->sync_id = cpu_to_le16(0x1234); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +index 7c68d9849..d0fada88f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -287,6 +287,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) + ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC); + + brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa"); ++ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_SCAN_V2, "scan_ver"); + + if (drvr->settings->feature_disable) { + brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n", +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +index d1f4257af..9d098a068 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +@@ -29,6 +29,7 @@ + * DOT11H: firmware supports 802.11h + * SAE: simultaneous authentication of equals + * FWAUTH: Firmware authenticator ++ * SCAN_V2: Version 2 scan params + */ + #define BRCMF_FEAT_LIST \ + BRCMF_FEAT_DEF(MBSS) \ +@@ -51,7 +52,8 @@ + BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \ + BRCMF_FEAT_DEF(DOT11H) \ + BRCMF_FEAT_DEF(SAE) \ +- BRCMF_FEAT_DEF(FWAUTH) ++ BRCMF_FEAT_DEF(FWAUTH) \ ++ BRCMF_FEAT_DEF(SCAN_V2) + + /* + * Quirks: +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +index e69d1e569..9b794d20f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -48,6 +48,10 @@ + + /* size of brcmf_scan_params not including variable length array */ + #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 ++#define BRCMF_SCAN_PARAMS_V2_FIXED_SIZE 72 ++ ++/* version of of brcmf_scan_params structure */ ++#define BRCMF_SCAN_PARAMS_VERSION_V2 2 + + /* masks for channel and ssid count */ + #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff +@@ -67,6 +71,7 @@ + #define BRCMF_PRIMARY_KEY (1 << 1) + #define DOT11_BSSTYPE_ANY 2 + #define BRCMF_ESCAN_REQ_VERSION 1 ++#define BRCMF_ESCAN_REQ_VERSION_V2 2 + + #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ + +@@ -386,6 +391,45 @@ struct brcmf_scan_params_le { + __le16 channel_list[1]; /* list of chanspecs */ + }; + ++struct brcmf_scan_params_v2_le { ++ __le16 version; /* structure version */ ++ __le16 length; /* structure length */ ++ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ ++ u8 bssid[ETH_ALEN]; /* default: bcast */ ++ s8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ u8 pad; ++ __le32 scan_type; /* flags, 0 use default */ ++ __le32 nprobes; /* -1 use default, number of probes per channel */ ++ __le32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ __le32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ __le32 home_time; /* -1 use default, dwell time for the ++ * home channel between channel scans ++ */ ++ __le32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in ++ * channel_list, 0 means default (use all ++ * available channels) ++ * ++ * high half is entries in struct brcmf_ssid ++ * array that follows channel_list, aligned for ++ * s32 (4 bytes) meaning an odd channel count ++ * implies a 2-byte pad between end of ++ * channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the ++ * fixed parameter portion is assumed, otherwise ++ * ssid in the fixed portion is ignored ++ */ ++ __le16 channel_list[1]; /* list of chanspecs */ ++}; ++ + struct brcmf_scan_results { + u32 buflen; + u32 version; +@@ -397,7 +441,10 @@ struct brcmf_escan_params_le { + __le32 version; + __le16 action; + __le16 sync_id; +- struct brcmf_scan_params_le params_le; ++ union { ++ struct brcmf_scan_params_le params_le; ++ struct brcmf_scan_params_v2_le params_v2_le; ++ }; + }; + + struct brcmf_escan_result_le { +-- +2.34.1 + diff --git a/8023-brcmfmac-feature-Add-support-for-setting-feats-based.patch b/8023-brcmfmac-feature-Add-support-for-setting-feats-based.patch new file mode 100644 index 0000000..5b6ee01 --- /dev/null +++ b/8023-brcmfmac-feature-Add-support-for-setting-feats-based.patch @@ -0,0 +1,137 @@ +From 150f44fdb2184e9bd9ceed6a05dcdfb9334d8924 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Mon, 20 Dec 2021 18:15:10 +0900 +Subject: [PATCH 23/34] brcmfmac: feature: Add support for setting feats based + on WLC version + +The "wlc_ver" iovar returns information on the WLC and EPI versions. +This can be used to determine whether the PMKID_V2 and _V3 features are +supported. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/feature.c | 48 +++++++++++++++++++ + .../broadcom/brcm80211/brcmfmac/feature.h | 4 +- + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 25 ++++++++++ + 3 files changed, 76 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +index d0fada88f..2ade1d86c 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -126,6 +126,53 @@ static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv) + drv->feat_flags |= feat_flags; + } + ++struct brcmf_feat_wlcfeat { ++ u16 min_ver_major; ++ u16 min_ver_minor; ++ u32 feat_flags; ++}; ++ ++static const struct brcmf_feat_wlcfeat brcmf_feat_wlcfeat_map[] = { ++ { 12, 0, BIT(BRCMF_FEAT_PMKID_V2) }, ++ { 13, 0, BIT(BRCMF_FEAT_PMKID_V3) }, ++}; ++ ++static void brcmf_feat_wlc_version_overrides(struct brcmf_pub *drv) ++{ ++ struct brcmf_if *ifp = brcmf_get_ifp(drv, 0); ++ const struct brcmf_feat_wlcfeat *e; ++ struct brcmf_wlc_version_le ver; ++ u32 feat_flags = 0; ++ int i, err, major, minor; ++ ++ err = brcmf_fil_iovar_data_get(ifp, "wlc_ver", &ver, sizeof(ver)); ++ if (err) ++ return; ++ ++ major = le16_to_cpu(ver.wlc_ver_major); ++ minor = le16_to_cpu(ver.wlc_ver_minor); ++ ++ brcmf_dbg(INFO, "WLC version: %d.%d\n", major, minor); ++ ++ for (i = 0; i < ARRAY_SIZE(brcmf_feat_wlcfeat_map); i++) { ++ e = &brcmf_feat_wlcfeat_map[i]; ++ if ((major > e->min_ver_major) || ++ ((major == e->min_ver_major) && ++ (minor >= e->min_ver_minor))) { ++ feat_flags |= e->feat_flags; ++ } ++ } ++ ++ if (!feat_flags) ++ return; ++ ++ for (i = 0; i < BRCMF_FEAT_LAST; i++) ++ if (feat_flags & BIT(i)) ++ brcmf_dbg(INFO, "enabling firmware feature: %s\n", ++ brcmf_feat_names[i]); ++ drv->feat_flags |= feat_flags; ++} ++ + /** + * brcmf_feat_iovar_int_get() - determine feature through iovar query. + * +@@ -296,6 +343,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) + ifp->drvr->feat_flags &= ~drvr->settings->feature_disable; + } + ++ brcmf_feat_wlc_version_overrides(drvr); + brcmf_feat_firmware_overrides(drvr); + + /* set chip related quirks */ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +index 9d098a068..becbcc50d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +@@ -53,7 +53,9 @@ + BRCMF_FEAT_DEF(DOT11H) \ + BRCMF_FEAT_DEF(SAE) \ + BRCMF_FEAT_DEF(FWAUTH) \ +- BRCMF_FEAT_DEF(SCAN_V2) ++ BRCMF_FEAT_DEF(SCAN_V2) \ ++ BRCMF_FEAT_DEF(PMKID_V2) \ ++ BRCMF_FEAT_DEF(PMKID_V3) + + /* + * Quirks: +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +index 9b794d20f..7be1f4ca5 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -788,6 +788,31 @@ struct brcmf_rev_info_le { + __le32 nvramrev; + }; + ++/** ++ * struct brcmf_wlc_version_le - firwmare revision info. ++ * ++ * @version: structure version. ++ * @length: structure length. ++ * @epi_ver_major: EPI major version ++ * @epi_ver_minor: EPI minor version ++ * @epi_ver_rc: EPI rc version ++ * @epi_ver_incr: EPI increment version ++ * @wlc_ver_major: WLC major version ++ * @wlc_ver_minor: WLC minor version ++ */ ++struct brcmf_wlc_version_le { ++ __le16 version; ++ __le16 length; ++ ++ __le16 epi_ver_major; ++ __le16 epi_ver_minor; ++ __le16 epi_ver_rc; ++ __le16 epi_ver_incr; ++ ++ __le16 wlc_ver_major; ++ __le16 wlc_ver_minor; ++}; ++ + /** + * struct brcmf_assoclist_le - request assoc list. + * +-- +2.34.1 + diff --git a/8024-brcmfmac-cfg80211-Add-support-for-PMKID_V3-operation.patch b/8024-brcmfmac-cfg80211-Add-support-for-PMKID_V3-operation.patch new file mode 100644 index 0000000..91e551c --- /dev/null +++ b/8024-brcmfmac-cfg80211-Add-support-for-PMKID_V3-operation.patch @@ -0,0 +1,223 @@ +From b9bed13f0ee89343529d7d0cce615cffdbea972b Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Mon, 20 Dec 2021 18:16:33 +0900 +Subject: [PATCH 24/34] brcmfmac: cfg80211: Add support for PMKID_V3 operations + +Add support for the new PMKID_V3 API, which allows performing PMKID +mutations individually, instead of requiring the driver to keep track of +the full list. This new API is required by at least BCM4387. + +Note that PMKID_V2 is not implemented yet. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 49 ++++++++++- + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 83 +++++++++++++++++++ + 2 files changed, 129 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index f9de22f77..ccda7ce39 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -4050,6 +4050,34 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, + return 0; + } + ++static s32 ++brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa, ++ bool alive) ++{ ++ struct brcmf_pmk_op_v3_le pmk_op; ++ int length = offsetof(struct brcmf_pmk_op_v3_le, pmk); ++ ++ memset(&pmk_op, 0, sizeof(pmk_op)); ++ pmk_op.version = cpu_to_le16(BRCMF_PMKSA_VER_3); ++ ++ if (!pmksa) { ++ /* Flush operation, operate on entire list */ ++ pmk_op.count = cpu_to_le16(0); ++ } else { ++ /* Single PMK operation */ ++ pmk_op.count = cpu_to_le16(1); ++ length += sizeof(struct brcmf_pmksa_v3); ++ memcpy(pmk_op.pmk[0].bssid, pmksa->bssid, ETH_ALEN); ++ memcpy(pmk_op.pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); ++ pmk_op.pmk[0].pmkid_len = WLAN_PMKID_LEN; ++ pmk_op.pmk[0].time_left = alive ? BRCMF_PMKSA_NO_EXPIRY : 0; ++ } ++ ++ pmk_op.length = cpu_to_le16(length); ++ ++ return brcmf_fil_iovar_data_set(ifp, "pmkid_info", &pmk_op, sizeof(pmk_op)); ++} ++ + static __used s32 + brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) + { +@@ -4086,6 +4114,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, + if (!check_vif_up(ifp->vif)) + return -EIO; + ++ brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmksa->bssid); ++ brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmksa->pmkid); ++ ++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3)) ++ return brcmf_pmksa_v3_op(ifp, pmksa, true); ++ ++ /* TODO: implement PMKID_V2 */ ++ + npmk = le32_to_cpu(cfg->pmk_list.npmk); + for (i = 0; i < npmk; i++) + if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN)) +@@ -4102,9 +4138,6 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, + return -EINVAL; + } + +- brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid); +- brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmk[npmk].pmkid); +- + err = brcmf_update_pmklist(cfg, ifp); + + brcmf_dbg(TRACE, "Exit\n"); +@@ -4128,6 +4161,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, + + brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid); + ++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3)) ++ return brcmf_pmksa_v3_op(ifp, pmksa, false); ++ ++ /* TODO: implement PMKID_V2 */ ++ + npmk = le32_to_cpu(cfg->pmk_list.npmk); + for (i = 0; i < npmk; i++) + if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN)) +@@ -4164,6 +4202,11 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) + if (!check_vif_up(ifp->vif)) + return -EIO; + ++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3)) ++ return brcmf_pmksa_v3_op(ifp, NULL, false); ++ ++ /* TODO: implement PMKID_V2 */ ++ + memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list)); + err = brcmf_update_pmklist(cfg, ifp); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +index 7be1f4ca5..bc936c181 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -174,6 +174,10 @@ + + #define BRCMF_HE_CAP_MCS_MAP_NSS_MAX 8 + ++#define BRCMF_PMKSA_VER_2 2 ++#define BRCMF_PMKSA_VER_3 3 ++#define BRCMF_PMKSA_NO_EXPIRY 0xffffffff ++ + /* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each + * ioctl. It is relatively small because firmware has small maximum size input + * playload restriction for ioctls. +@@ -355,6 +359,12 @@ struct brcmf_ssid_le { + unsigned char SSID[IEEE80211_MAX_SSID_LEN]; + }; + ++/* Alternate SSID structure used in some places... */ ++struct brcmf_ssid8_le { ++ u8 SSID_len; ++ unsigned char SSID[IEEE80211_MAX_SSID_LEN]; ++}; ++ + struct brcmf_scan_params_le { + struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ + u8 bssid[ETH_ALEN]; /* default: bcast */ +@@ -875,6 +885,51 @@ struct brcmf_pmksa { + u8 pmkid[WLAN_PMKID_LEN]; + }; + ++/** ++ * struct brcmf_pmksa_v2 - PMK Security Association ++ * ++ * @length: Length of the structure. ++ * @bssid: The AP's BSSID. ++ * @pmkid: The PMK ID. ++ * @pmk: PMK material for FILS key derivation. ++ * @pmk_len: Length of PMK data. ++ * @ssid: The AP's SSID. ++ * @fils_cache_id: FILS cache identifier ++ */ ++struct brcmf_pmksa_v2 { ++ __le16 length; ++ u8 bssid[ETH_ALEN]; ++ u8 pmkid[WLAN_PMKID_LEN]; ++ u8 pmk[WLAN_PMK_LEN_SUITE_B_192]; ++ __le16 pmk_len; ++ struct brcmf_ssid8_le ssid; ++ u16 fils_cache_id; ++}; ++ ++/** ++ * struct brcmf_pmksa_v3 - PMK Security Association ++ * ++ * @bssid: The AP's BSSID. ++ * @pmkid: The PMK ID. ++ * @pmkid_len: The length of the PMK ID. ++ * @pmk: PMK material for FILS key derivation. ++ * @pmk_len: Length of PMK data. ++ * @fils_cache_id: FILS cache identifier ++ * @ssid: The AP's SSID. ++ * @time_left: Remaining time until expiry. 0 = expired, ~0 = no expiry. ++ */ ++struct brcmf_pmksa_v3 { ++ u8 bssid[ETH_ALEN]; ++ u8 pmkid[WLAN_PMKID_LEN]; ++ u8 pmkid_len; ++ u8 pmk[WLAN_PMK_LEN_SUITE_B_192]; ++ u8 pmk_len; ++ __le16 fils_cache_id; ++ u8 pad; ++ struct brcmf_ssid8_le ssid; ++ __le32 time_left; ++}; ++ + /** + * struct brcmf_pmk_list_le - List of pmksa's. + * +@@ -886,6 +941,34 @@ struct brcmf_pmk_list_le { + struct brcmf_pmksa pmk[BRCMF_MAXPMKID]; + }; + ++/** ++ * struct brcmf_pmk_list_v2_le - List of pmksa's. ++ * ++ * @version: Request version. ++ * @length: Length of this structure. ++ * @pmk: PMK SA information. ++ */ ++struct brcmf_pmk_list_v2_le { ++ __le16 version; ++ __le16 length; ++ struct brcmf_pmksa_v2 pmk[BRCMF_MAXPMKID]; ++}; ++ ++/** ++ * struct brcmf_pmk_op_v3_le - Operation on PMKSA list. ++ * ++ * @version: Request version. ++ * @length: Length of this structure. ++ * @pmk: PMK SA information. ++ */ ++struct brcmf_pmk_op_v3_le { ++ __le16 version; ++ __le16 length; ++ __le16 count; ++ __le16 pad; ++ struct brcmf_pmksa_v3 pmk[BRCMF_MAXPMKID]; ++}; ++ + /** + * struct brcmf_pno_param_le - PNO scan configuration parameters + * +-- +2.34.1 + diff --git a/8025-brcmfmac-cfg80211-Pass-the-PMK-in-binary-instead-of-.patch b/8025-brcmfmac-cfg80211-Pass-the-PMK-in-binary-instead-of-.patch new file mode 100644 index 0000000..2662165 --- /dev/null +++ b/8025-brcmfmac-cfg80211-Pass-the-PMK-in-binary-instead-of-.patch @@ -0,0 +1,49 @@ +From bc717842356e7739ee9b58838592ef0e540d0b39 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Mon, 20 Dec 2021 19:15:58 +0900 +Subject: [PATCH 25/34] brcmfmac: cfg80211: Pass the PMK in binary instead of + hex + +Apparently the hex passphrase mechanism does not work on newer +chips/firmware (e.g. BCM4387). It seems there was a simple way of +passing it in binary all along, so use that and avoid the hexification. + +OpenBSD has been doing it like this from the beginning, so this should +work on all chips. + +Also clear the structure before setting the PMK. This was leaking +uninitialized stack contents to the device. + +Signed-off-by: Hector Martin +--- + .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index ccda7ce39..d6d34e079 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1420,13 +1420,14 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) + { + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_wsec_pmk_le pmk; +- int i, err; ++ int err; ++ ++ memset(&pmk, 0, sizeof(pmk)); + +- /* convert to firmware key format */ +- pmk.key_len = cpu_to_le16(pmk_len << 1); +- pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE); +- for (i = 0; i < pmk_len; i++) +- snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]); ++ /* pass pmk directly */ ++ pmk.key_len = cpu_to_le16(pmk_len); ++ pmk.flags = cpu_to_le16(0); ++ memcpy(pmk.key, pmk_data, pmk_len); + + /* store psk in firmware */ + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK, +-- +2.34.1 + diff --git a/8026-brcmfmac-pcie-Add-IDs-properties-for-BCM4387.patch b/8026-brcmfmac-pcie-Add-IDs-properties-for-BCM4387.patch new file mode 100644 index 0000000..a2bddae --- /dev/null +++ b/8026-brcmfmac-pcie-Add-IDs-properties-for-BCM4387.patch @@ -0,0 +1,95 @@ +From 534075f8cc83a2d5b57af7622e0bc03277e2aa84 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:52:03 +0900 +Subject: [PATCH 26/34] brcmfmac: pcie: Add IDs/properties for BCM4387 + +This chip is present on Apple M1 Pro/Max (t600x) platforms: + +* maldives (apple,j314s): MacBook Pro (14-inch, M1 Pro, 2021) +* maldives (apple,j314c): MacBook Pro (14-inch, M1 Max, 2021) +* madagascar (apple,j316s): MacBook Pro (16-inch, M1 Pro, 2021) +* madagascar (apple,j316c): MacBook Pro (16-inch, M1 Max, 2021) + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++ + .../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ + 3 files changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index c4c80664b..f7ca9ff29 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -742,6 +742,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) + return 0x170000; + case BRCM_CC_4378_CHIP_ID: + return 0x352000; ++ case BRCM_CC_4387_CHIP_ID: ++ return 0x740000; + default: + brcmf_err("unknown chip: %s\n", ci->pub.name); + break; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index b6b789b49..bc2a53812 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -63,6 +63,7 @@ BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); + BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); + BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); + BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie"); ++BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie"); + + /* firmware config files */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt"); +@@ -96,6 +97,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), + BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* 4 */ + BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* 3 */ ++ BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* 7 */ + }; + + #define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */ +@@ -2070,6 +2072,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + base = 0x1120; + words = 0x170; + break; ++ case BRCM_CC_4387_CHIP_ID: ++ coreid = BCMA_CORE_GCI; ++ base = 0x113c; ++ words = 0x170; ++ break; + default: + /* OTP not supported on this chip */ + return 0; +@@ -2580,6 +2587,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID), ++ BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID), + { /* end: all zeroes */ } + }; + +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 54d7ec515..3d6c803fb 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -53,6 +53,7 @@ + #define BRCM_CC_4371_CHIP_ID 0x4371 + #define BRCM_CC_4377_CHIP_ID 0x4377 + #define BRCM_CC_4378_CHIP_ID 0x4378 ++#define BRCM_CC_4387_CHIP_ID 0x4387 + #define CY_CC_4373_CHIP_ID 0x4373 + #define CY_CC_43012_CHIP_ID 43012 + #define CY_CC_43752_CHIP_ID 43752 +@@ -91,6 +92,7 @@ + #define BRCM_PCIE_4371_DEVICE_ID 0x440d + #define BRCM_PCIE_4377_DEVICE_ID 0x4488 + #define BRCM_PCIE_4378_DEVICE_ID 0x4425 ++#define BRCM_PCIE_4387_DEVICE_ID 0x4433 + + + /* brcmsmac IDs */ +-- +2.34.1 + diff --git a/8027-brcmfmac-pcie-Replace-brcmf_pcie_copy_mem_todev-with.patch b/8027-brcmfmac-pcie-Replace-brcmf_pcie_copy_mem_todev-with.patch new file mode 100644 index 0000000..8453929 --- /dev/null +++ b/8027-brcmfmac-pcie-Replace-brcmf_pcie_copy_mem_todev-with.patch @@ -0,0 +1,119 @@ +From e5278ec18dc59d4c01afb60e706df41d7e83f1cf Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:39:28 +0900 +Subject: [PATCH 27/34] brcmfmac: pcie: Replace brcmf_pcie_copy_mem_todev with + memcpy_toio + +The alignment check was wrong (e.g. & 4 instead of & 3), and the logic +was also inefficient if the length was not a multiple of 4, since it +would needlessly fall back to copying the entire buffer bytewise. + +We already have a perfectly good memcpy_toio function, so just call that +instead of rolling our own copy logic here. brcmf_pcie_init_ringbuffers +was already using it anyway. + +Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.") +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/pcie.c | 53 +++---------------- + 1 file changed, 6 insertions(+), 47 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index bc2a53812..865e3f28c 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -562,47 +563,6 @@ brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + } + + +-static void +-brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset, +- void *srcaddr, u32 len) +-{ +- void __iomem *address = devinfo->tcm + mem_offset; +- __le32 *src32; +- __le16 *src16; +- u8 *src8; +- +- if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) { +- if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) { +- src8 = (u8 *)srcaddr; +- while (len) { +- iowrite8(*src8, address); +- address++; +- src8++; +- len--; +- } +- } else { +- len = len / 2; +- src16 = (__le16 *)srcaddr; +- while (len) { +- iowrite16(le16_to_cpu(*src16), address); +- address += 2; +- src16++; +- len--; +- } +- } +- } else { +- len = len / 4; +- src32 = (__le32 *)srcaddr; +- while (len) { +- iowrite32(le32_to_cpu(*src32), address); +- address += 4; +- src32++; +- len--; +- } +- } +-} +- +- + static void + brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + void *dstaddr, u32 len) +@@ -1702,8 +1662,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + return err; + + brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name); +- brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase, +- (void *)fw->data, fw->size); ++ memcpy_toio(devinfo->tcm + devinfo->ci->rambase, ++ (void *)fw->data, fw->size); + + resetintr = get_unaligned_le32(fw->data); + release_firmware(fw); +@@ -1724,7 +1684,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name); + address = devinfo->ci->rambase + devinfo->ci->ramsize - + nvram_len; +- brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len); ++ memcpy_toio(devinfo->tcm + address, nvram, nvram_len); + brcmf_fw_nvram_free(nvram); + + /* +@@ -1734,13 +1694,12 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + brcmf_dbg(PCIE, "Download random seed\n"); + + address -= sizeof(footer); +- brcmf_pcie_copy_mem_todev(devinfo, address, &footer, +- sizeof(footer)); ++ memcpy_toio(devinfo->tcm + address, &footer, sizeof(footer)); + + address -= rand_len; + randbuf = kzalloc(rand_len, GFP_KERNEL); + get_random_bytes(randbuf, rand_len); +- brcmf_pcie_copy_mem_todev(devinfo, address, randbuf, rand_len); ++ memcpy_toio(devinfo->tcm + address, randbuf, rand_len); + kfree(randbuf); + } else { + brcmf_dbg(PCIE, "No matching NVRAM file found %s\n", +-- +2.34.1 + diff --git a/8028-brcmfmac-pcie-Read-the-console-on-init-and-shutdown.patch b/8028-brcmfmac-pcie-Read-the-console-on-init-and-shutdown.patch new file mode 100644 index 0000000..56b0723 --- /dev/null +++ b/8028-brcmfmac-pcie-Read-the-console-on-init-and-shutdown.patch @@ -0,0 +1,45 @@ +From f6f42c43e1301ba77fe6b4480007871b3a2da85c Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:43:03 +0900 +Subject: [PATCH 28/34] brcmfmac: pcie: Read the console on init and shutdown + +This allows us to get console messages if the firmware crashed during +early init, or if an operation failed and we're about to shut down. + +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 865e3f28c..8b67cddb7 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -854,6 +854,8 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, + return; + + console = &devinfo->shared.console; ++ if (!console->base_addr) ++ return; + addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET; + newidx = brcmf_pcie_read_tcm32(devinfo, addr); + while (newidx != console->read_idx) { +@@ -1632,6 +1634,7 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, + shared->max_rxbufpost, shared->rx_dataoffset); + + brcmf_pcie_bus_console_init(devinfo); ++ brcmf_pcie_bus_console_read(devinfo, false); + + return 0; + } +@@ -2401,6 +2404,7 @@ brcmf_pcie_remove(struct pci_dev *pdev) + return; + + devinfo = bus->bus_priv.pcie->devinfo; ++ brcmf_pcie_bus_console_read(devinfo, false); + + devinfo->state = BRCMFMAC_PCIE_STATE_DOWN; + if (devinfo->ci) +-- +2.34.1 + diff --git a/8029-brcmfmac-pcie-Release-firmwares-in-the-brcmf_pcie_se.patch b/8029-brcmfmac-pcie-Release-firmwares-in-the-brcmf_pcie_se.patch new file mode 100644 index 0000000..4b32887 --- /dev/null +++ b/8029-brcmfmac-pcie-Release-firmwares-in-the-brcmf_pcie_se.patch @@ -0,0 +1,31 @@ +From fbf132e816fb5ab9fc5e44be8a3ba78cdc5bb1e1 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Tue, 21 Dec 2021 17:44:51 +0900 +Subject: [PATCH 29/34] brcmfmac: pcie: Release firmwares in the + brcmf_pcie_setup error path + +This avoids leaking memory if brcmf_chip_get_raminfo fails. Note that +the CLM blob is released in the device remove path. + +Fixes: 82f93cf46d60 ("brcmfmac: get chip's default RAM info during PCIe setup") +Signed-off-by: Hector Martin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 8b67cddb7..f1b90b5e7 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -2125,6 +2125,8 @@ static void brcmf_pcie_setup(struct device *dev, int ret, + ret = brcmf_chip_get_raminfo(devinfo->ci); + if (ret) { + brcmf_err(bus, "Failed to get RAM info\n"); ++ release_firmware(fw); ++ brcmf_fw_nvram_free(nvram); + goto fail; + } + +-- +2.34.1 + diff --git a/8031-brcmfmac-fwil-Constify-iovar-name-arguments.patch b/8031-brcmfmac-fwil-Constify-iovar-name-arguments.patch new file mode 100644 index 0000000..f8996cd --- /dev/null +++ b/8031-brcmfmac-fwil-Constify-iovar-name-arguments.patch @@ -0,0 +1,215 @@ +From 540d5a24c9b0c9a14dce5b59167628b9f18c27cd Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sun, 26 Dec 2021 00:24:02 +0900 +Subject: [PATCH 31/34] brcmfmac: fwil: Constify iovar name arguments + +Make all the iovar name arguments const char * instead of just char *. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/fwil.c | 34 +++++++++---------- + .../broadcom/brcm80211/brcmfmac/fwil.h | 28 +++++++-------- + 2 files changed, 31 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +index d5578ca68..72fe8bce6 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -192,7 +192,7 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) + } + + static u32 +-brcmf_create_iovar(char *name, const char *data, u32 datalen, ++brcmf_create_iovar(const char *name, const char *data, u32 datalen, + char *buf, u32 buflen) + { + u32 len; +@@ -213,7 +213,7 @@ brcmf_create_iovar(char *name, const char *data, u32 datalen, + + + s32 +-brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, ++brcmf_fil_iovar_data_set(struct brcmf_if *ifp, const char *name, const void *data, + u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -241,7 +241,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, + } + + s32 +-brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, ++brcmf_fil_iovar_data_get(struct brcmf_if *ifp, const char *name, void *data, + u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -272,7 +272,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, + } + + s32 +-brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) ++brcmf_fil_iovar_int_set(struct brcmf_if *ifp, const char *name, u32 data) + { + __le32 data_le = cpu_to_le32(data); + +@@ -280,7 +280,7 @@ brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) + } + + s32 +-brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data) ++brcmf_fil_iovar_int_get(struct brcmf_if *ifp, const char *name, u32 *data) + { + __le32 data_le = cpu_to_le32(*data); + s32 err; +@@ -292,7 +292,7 @@ brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data) + } + + static u32 +-brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen, ++brcmf_create_bsscfg(s32 bsscfgidx, const char *name, char *data, u32 datalen, + char *buf, u32 buflen) + { + const s8 *prefix = "bsscfg:"; +@@ -337,7 +337,7 @@ brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen, + } + + s32 +-brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, ++brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, const char *name, + void *data, u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -366,7 +366,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, + } + + s32 +-brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, ++brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, const char *name, + void *data, u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -396,7 +396,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, + } + + s32 +-brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data) ++brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, const char *name, u32 data) + { + __le32 data_le = cpu_to_le32(data); + +@@ -405,7 +405,7 @@ brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data) + } + + s32 +-brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) ++brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, const char *name, u32 *data) + { + __le32 data_le = cpu_to_le32(*data); + s32 err; +@@ -417,7 +417,7 @@ brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) + return err; + } + +-static u32 brcmf_create_xtlv(char *name, u16 id, char *data, u32 len, ++static u32 brcmf_create_xtlv(const char *name, u16 id, char *data, u32 len, + char *buf, u32 buflen) + { + u32 iolen; +@@ -438,7 +438,7 @@ static u32 brcmf_create_xtlv(char *name, u16 id, char *data, u32 len, + return iolen; + } + +-s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, char *name, u16 id, ++s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, const char *name, u16 id, + void *data, u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -466,7 +466,7 @@ s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, char *name, u16 id, + return err; + } + +-s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, char *name, u16 id, ++s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, const char *name, u16 id, + void *data, u32 len) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -495,7 +495,7 @@ s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, char *name, u16 id, + return err; + } + +-s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, char *name, u16 id, u32 data) ++s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, const char *name, u16 id, u32 data) + { + __le32 data_le = cpu_to_le32(data); + +@@ -503,7 +503,7 @@ s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, char *name, u16 id, u32 data) + sizeof(data_le)); + } + +-s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, char *name, u16 id, u32 *data) ++s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, const char *name, u16 id, u32 *data) + { + __le32 data_le = cpu_to_le32(*data); + s32 err; +@@ -514,12 +514,12 @@ s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, char *name, u16 id, u32 *data) + return err; + } + +-s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, char *name, u16 id, u8 *data) ++s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, const char *name, u16 id, u8 *data) + { + return brcmf_fil_xtlv_data_get(ifp, name, id, data, sizeof(*data)); + } + +-s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, char *name, u16 id, u16 *data) ++s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, const char *name, u16 id, u16 *data) + { + __le16 data_le = cpu_to_le16(*data); + s32 err; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +index cb26f8c59..bc693157c 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +@@ -84,26 +84,26 @@ s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); + s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); + s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data); + +-s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, ++s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, const char *name, const void *data, + u32 len); +-s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, ++s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, const char *name, void *data, + u32 len); +-s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data); +-s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data); ++s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, const char *name, u32 data); ++s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, const char *name, u32 *data); + +-s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data, ++s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, const char *name, void *data, + u32 len); +-s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data, ++s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, const char *name, void *data, + u32 len); +-s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data); +-s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data); +-s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, char *name, u16 id, ++s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, const char *name, u32 data); ++s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, const char *name, u32 *data); ++s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, const char *name, u16 id, + void *data, u32 len); +-s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, char *name, u16 id, ++s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, const char *name, u16 id, + void *data, u32 len); +-s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, char *name, u16 id, u32 data); +-s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, char *name, u16 id, u32 *data); +-s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, char *name, u16 id, u8 *data); +-s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, char *name, u16 id, u16 *data); ++s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, const char *name, u16 id, u32 data); ++s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, const char *name, u16 id, u32 *data); ++s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, const char *name, u16 id, u8 *data); ++s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, const char *name, u16 id, u16 *data); + + #endif /* _fwil_h_ */ +-- +2.34.1 + diff --git a/8032-brcmfmac-common-Add-support-for-downloading-TxCap-bl.patch b/8032-brcmfmac-common-Add-support-for-downloading-TxCap-bl.patch new file mode 100644 index 0000000..9a2eb9a --- /dev/null +++ b/8032-brcmfmac-common-Add-support-for-downloading-TxCap-bl.patch @@ -0,0 +1,189 @@ +From 4c496f67db9939ac2be78a91c483d3afd4960f08 Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sun, 26 Dec 2021 00:25:00 +0900 +Subject: [PATCH 32/34] brcmfmac: common: Add support for downloading TxCap + blobs + +The TxCap blobs are additional data blobs used on Apple devices, and +are uploaded analogously to CLM blobs. Add core support for doing this. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/bus.h | 1 + + .../broadcom/brcm80211/brcmfmac/common.c | 97 +++++++++++++------ + 2 files changed, 71 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +index b13af8f63..f4bd98da9 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -39,6 +39,7 @@ enum brcmf_bus_protocol_type { + /* Firmware blobs that may be available */ + enum brcmf_blob_type { + BRCMF_BLOB_CLM, ++ BRCMF_BLOB_TXCAP, + }; + + struct brcmf_mp_device; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index c84c48e49..d65308c3f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -101,7 +101,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) + + static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, +- u32 len) ++ u32 len, const char *var) + { + s32 err; + +@@ -112,17 +112,17 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + dload_buf->crc = cpu_to_le32(0); + len = sizeof(*dload_buf) + len - 1; + +- err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); ++ err = brcmf_fil_iovar_data_set(ifp, var, dload_buf, len); + + return err; + } + +-static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) ++static int brcmf_c_download_blob(struct brcmf_if *ifp, ++ const void *data, size_t size, ++ const char *loadvar, const char *statvar) + { + struct brcmf_pub *drvr = ifp->drvr; +- struct brcmf_bus *bus = drvr->bus_if; + struct brcmf_dload_data_le *chunk_buf; +- const struct firmware *clm = NULL; + u32 chunk_len; + u32 datalen; + u32 cumulative_len; +@@ -132,20 +132,11 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) + + brcmf_dbg(TRACE, "Enter\n"); + +- err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM); +- if (err || !clm) { +- brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", +- err); +- return 0; +- } +- + chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); +- if (!chunk_buf) { +- err = -ENOMEM; +- goto done; +- } ++ if (!chunk_buf) ++ return -ENOMEM; + +- datalen = clm->size; ++ datalen = size; + cumulative_len = 0; + do { + if (datalen > MAX_CHUNK_LEN) { +@@ -154,9 +145,10 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) + chunk_len = datalen; + dl_flag |= DL_END; + } +- memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len); ++ memcpy(chunk_buf->data, data + cumulative_len, chunk_len); + +- err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len); ++ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len, ++ loadvar); + + dl_flag &= ~DL_BEGIN; + +@@ -165,20 +157,64 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) + } while ((datalen > 0) && (err == 0)); + + if (err) { +- bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n", +- clm->size, err); +- /* Retrieve clmload_status and print */ +- err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status); ++ bphy_err(drvr, "%s (%zu byte file) failed (%d)\n", ++ loadvar, size, err); ++ /* Retrieve status and print */ ++ err = brcmf_fil_iovar_int_get(ifp, statvar, &status); + if (err) +- bphy_err(drvr, "get clmload_status failed (%d)\n", err); ++ bphy_err(drvr, "get %s failed (%d)\n", statvar, err); + else +- brcmf_dbg(INFO, "clmload_status=%d\n", status); ++ brcmf_dbg(INFO, "%s=%d\n", statvar, status); + err = -EIO; + } + + kfree(chunk_buf); +-done: +- release_firmware(clm); ++ return err; ++} ++ ++static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) ++{ ++ struct brcmf_pub *drvr = ifp->drvr; ++ struct brcmf_bus *bus = drvr->bus_if; ++ const struct firmware *fw = NULL; ++ s32 err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_CLM); ++ if (err || !fw) { ++ brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", ++ err); ++ return 0; ++ } ++ ++ err = brcmf_c_download_blob(ifp, fw->data, fw->size, ++ "clmload", "clmload_status"); ++ ++ release_firmware(fw); ++ return err; ++} ++ ++static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp) ++{ ++ struct brcmf_pub *drvr = ifp->drvr; ++ struct brcmf_bus *bus = drvr->bus_if; ++ const struct firmware *fw = NULL; ++ s32 err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_TXCAP); ++ if (err || !fw) { ++ brcmf_info("no txcap_blob available (err=%d)\n", err); ++ return 0; ++ } ++ ++ brcmf_info("TxCap blob found, loading\n"); ++ err = brcmf_c_download_blob(ifp, fw->data, fw->size, ++ "txcapload", "txcapload_status"); ++ ++ release_firmware(fw); + return err; + } + +@@ -248,6 +284,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + goto done; + } + ++ /* Do TxCap downloading, if needed */ ++ err = brcmf_c_process_txcap_blob(ifp); ++ if (err < 0) { ++ bphy_err(drvr, "download TxCap blob file failed, %d\n", err); ++ goto done; ++ } ++ + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); +-- +2.34.1 + diff --git a/8033-brcmfmac-pcie-Load-and-provide-TxCap-blobs.patch b/8033-brcmfmac-pcie-Load-and-provide-TxCap-blobs.patch new file mode 100644 index 0000000..f90b461 --- /dev/null +++ b/8033-brcmfmac-pcie-Load-and-provide-TxCap-blobs.patch @@ -0,0 +1,91 @@ +From de52f6bca772503aa189136b565584c1fbf6b43a Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sun, 26 Dec 2021 00:26:10 +0900 +Subject: [PATCH 33/34] brcmfmac: pcie: Load and provide TxCap blobs + +These blobs are named .txcap_blob, and exist alongside the existing +.clm_blob files. Use the existing firmware machinery to provide them to +the core. + +Signed-off-by: Hector Martin +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index f1b90b5e7..b16bab061 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -73,6 +73,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt"); + /* per-board firmware binaries */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin"); + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob"); ++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txcap_blob"); + + static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602), +@@ -327,7 +328,9 @@ struct brcmf_pciedev_info { + char fw_name[BRCMF_FW_NAME_LEN]; + char nvram_name[BRCMF_FW_NAME_LEN]; + char clm_name[BRCMF_FW_NAME_LEN]; ++ char txcap_name[BRCMF_FW_NAME_LEN]; + const struct firmware *clm_fw; ++ const struct firmware *txcap_fw; + const struct brcmf_pcie_reginfo *reginfo; + void __iomem *regs; + void __iomem *tcm; +@@ -1504,6 +1507,10 @@ static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw, + *fw = devinfo->clm_fw; + devinfo->clm_fw = NULL; + break; ++ case BRCMF_BLOB_TXCAP: ++ *fw = devinfo->txcap_fw; ++ devinfo->txcap_fw = NULL; ++ break; + default: + return -ENOENT; + } +@@ -2095,6 +2102,7 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo) + #define BRCMF_PCIE_FW_CODE 0 + #define BRCMF_PCIE_FW_NVRAM 1 + #define BRCMF_PCIE_FW_CLM 2 ++#define BRCMF_PCIE_FW_TXCAP 3 + + static void brcmf_pcie_setup(struct device *dev, int ret, + struct brcmf_fw_request *fwreq) +@@ -2120,6 +2128,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret, + nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data; + nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len; + devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary; ++ devinfo->txcap_fw = fwreq->items[BRCMF_PCIE_FW_TXCAP].binary; + kfree(fwreq); + + ret = brcmf_chip_get_raminfo(devinfo->ci); +@@ -2196,6 +2205,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + { ".bin", devinfo->fw_name }, + { ".txt", devinfo->nvram_name }, + { ".clm_blob", devinfo->clm_name }, ++ { ".txcap_blob", devinfo->txcap_name }, + }; + + fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev, +@@ -2210,6 +2220,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) + fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; ++ fwreq->items[BRCMF_PCIE_FW_TXCAP].type = BRCMF_FW_TYPE_BINARY; ++ fwreq->items[BRCMF_PCIE_FW_TXCAP].flags = BRCMF_FW_REQF_OPTIONAL; + /* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */ + fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1; + fwreq->bus_nr = devinfo->pdev->bus->number; +@@ -2426,6 +2438,7 @@ brcmf_pcie_remove(struct pci_dev *pdev) + brcmf_pcie_reset_device(devinfo); + brcmf_pcie_release_resource(devinfo); + release_firmware(devinfo->clm_fw); ++ release_firmware(devinfo->txcap_fw); + + if (devinfo->ci) + brcmf_chip_detach(devinfo->ci); +-- +2.34.1 + diff --git a/8034-brcmfmac-common-Add-support-for-external-calibration.patch b/8034-brcmfmac-common-Add-support-for-external-calibration.patch new file mode 100644 index 0000000..c31da1b --- /dev/null +++ b/8034-brcmfmac-common-Add-support-for-external-calibration.patch @@ -0,0 +1,100 @@ +From f92aef8679038a4d0b055babf368f8f43bdd072b Mon Sep 17 00:00:00 2001 +From: Hector Martin +Date: Sun, 26 Dec 2021 00:53:37 +0900 +Subject: [PATCH 34/34] brcmfmac: common: Add support for external calibration + blobs + +The calibration blob for a chip is normally stored in SROM and loaded +internally by the firmware. However, Apple ARM64 platforms instead store +it as part of platform configuration data, and provide it via the Apple +Device Tree. We forward this into the Linux DT in the bootloader. + +Add support for taking this blob from the DT and loading it into the +dongle. The loading mechanism is the same as used for the CLM and TxCap +blobs. + +Signed-off-by: Hector Martin +--- + .../broadcom/brcm80211/brcmfmac/common.c | 24 +++++++++++++++++++ + .../broadcom/brcm80211/brcmfmac/common.h | 2 ++ + .../wireless/broadcom/brcm80211/brcmfmac/of.c | 9 +++++++ + 3 files changed, 35 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index d65308c3f..ad36e6b5d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -218,6 +218,23 @@ static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp) + return err; + } + ++static int brcmf_c_process_cal_blob(struct brcmf_if *ifp) ++{ ++ struct brcmf_pub *drvr = ifp->drvr; ++ struct brcmf_mp_device *settings = drvr->settings; ++ s32 err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (!settings->cal_blob || !settings->cal_size) ++ return 0; ++ ++ brcmf_info("Calibration blob provided by platform, loading\n"); ++ err = brcmf_c_download_blob(ifp, settings->cal_blob, settings->cal_size, ++ "calload", "calload_status"); ++ return err; ++} ++ + int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + { + struct brcmf_pub *drvr = ifp->drvr; +@@ -291,6 +308,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + goto done; + } + ++ /* Download external calibration blob, if available */ ++ err = brcmf_c_process_cal_blob(ifp); ++ if (err < 0) { ++ bphy_err(drvr, "download calibration blob file failed, %d\n", err); ++ goto done; ++ } ++ + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +index a88c4a931..f321346ed 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -51,6 +51,8 @@ struct brcmf_mp_device { + struct brcmfmac_pd_cc *country_codes; + const char *board_type; + const char *antenna_sku; ++ void *cal_blob; ++ int cal_size; + union { + struct brcmfmac_sdio_pd sdio; + } bus; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +index 31407d3a1..9db5fa106 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -86,6 +86,15 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + if (!of_property_read_string(np, "apple,antenna-sku", &prop)) + settings->antenna_sku = devm_kstrdup(dev, prop, GFP_KERNEL); + ++ /* ++ * The WLAN calibration blob is normally stored in SROM, but Apple ++ * ARM64 platforms pass it via the DT instead. ++ */ ++ prop = of_get_property(np, "brcm,cal-blob", &settings->cal_size); ++ if (prop && settings->cal_size) ++ settings->cal_blob = devm_kmemdup(dev, prop, settings->cal_size, ++ GFP_KERNEL); ++ + /* Set board-type to the first string of the machine compatible prop */ + root = of_find_node_by_path("/"); + if (root && !settings->board_type) { +-- +2.34.1 + diff --git a/PKGBUILD b/PKGBUILD index c8fa019..3cdc4c3 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -4,11 +4,12 @@ # Contributor: Jan Alexander Steffens (heftig) pkgbase=linux-t2 -pkgver=5.16.12 +pkgver=5.16.10 +_srcname=linux-${pkgver} pkgrel=1 pkgdesc='Linux kernel for T2 Macs' -_srctag=v${pkgver}-${pkgrel} -url="https://github.com/t2linux/kernel/commits/arch-t2-$_srctag" +_srctag=v${pkgver%.*}-${pkgver##*.} +url="https://git.archlinux.org/linux.git/log/?h=v$_srctag" arch=(x86_64) license=(GPL2) makedepends=( @@ -17,11 +18,16 @@ makedepends=( git ) options=('!strip') -_srcname=t2linux-linux + source=( - "$_srcname::git+https://github.com/t2linux/kernel#tag=arch-t2-$_srctag" + https://www.kernel.org/pub/linux/kernel/v${pkgver//.*}.x/linux-${pkgver}.tar.xz + https://www.kernel.org/pub/linux/kernel/v${pkgver//.*}.x/linux-${pkgver}.tar.sign config # the main kernel config file + # Arch Linux patches + 0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch + 0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_sp.patch + # apple-bce, apple-ibridge apple-bce::git+https://github.com/t2linux/apple-bce-drv#commit=f93c6566f98b3c95677de8010f7445fa19f75091 # Redecorating fork has kbd bl working on mbp16,*. Code quality of those changes could be better. @@ -29,15 +35,80 @@ source=( 1001-Put-apple-bce-and-apple-ibridge-in-drivers-staging.patch 1002-add-modalias-to-apple-bce.patch + # Hack for AMD DC eDP link rate bug + 2001-drm-amd-display-Force-link_rate-as-LINK_RATE_RBR2-fo.patch + # Apple SMC ACPI support + 3001-applesmc-convert-static-structures-to-drvdata.patch + 3002-applesmc-make-io-port-base-addr-dynamic.patch + 3003-applesmc-switch-to-acpi_device-from-platform.patch + 3004-applesmc-key-interface-wrappers.patch + 3005-applesmc-basic-mmio-interface-implementation.patch + 3006-applesmc-fan-support-on-T2-Macs.patch 3007-applesmc-Add-iMacPro-to-applesmc_whitelist.patch + + # T2 USB Keyboard/Touchpad support + 4001-HID-apple-Add-support-for-keyboard-backlight-on-supp.patch + 4002-HID-apple-Add-support-for-MacbookAir8-1-keyboard-tra.patch + 4003-HID-apple-Add-support-for-MacBookPro15-2-keyboard-tr.patch + 4004-HID-apple-Add-support-for-MacBookPro15-1-keyboard-tr.patch + 4005-HID-apple-Add-support-for-MacBookPro15-4-keyboard-tr.patch + 4006-HID-apple-Add-support-for-MacBookPro16-2-keyboard-tr.patch + 4007-HID-apple-Add-support-for-MacBookPro16-3-keyboard-tr.patch + 4008-HID-apple-Add-support-for-MacBookAir9-1-keyboard-tra.patch + 4009-HID-apple-Add-support-for-MacBookPro16-1-keyboard-tr.patch + 4010-HID-apple-Add-ability-to-use-numbers-as-function-key.patch + + # make hid not touch tb to avoid `vhci: [00] URB failed: 3` + 5001-Fix-for-touchbar.patch + # UVC Camera support + 6001-media-uvcvideo-Add-support-for-Apple-T2-attached-iSi.patch + + # Hack for i915 overscan issues + 7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch + + # Broadcom WIFI device support + 8001-brcmfmac-pcie-Declare-missing-firmware-files-in-pcie.patch + 8002-brcmfmac-firmware-Support-having-multiple-alt-paths.patch + 8003-brcmfmac-firmware-Handle-per-board-clm_blob-files.patch + 8004-brcmfmac-pcie-sdio-usb-Get-CLM-blob-via-standard-fir.patch + 8005-brcmfmac-firmware-Support-passing-in-multiple-board_.patch + 8006-brcmfmac-pcie-Read-Apple-OTP-information.patch + 8007-brcmfmac-of-Fetch-Apple-properties.patch + 8008-brcmfmac-pcie-Perform-firmware-selection-for-Apple-p.patch + 8009-brcmfmac-firmware-Allow-platform-to-override-macaddr.patch + 8010-brcmfmac-msgbuf-Increase-RX-ring-sizes-to-1024.patch + 8011-brcmfmac-pcie-Fix-crashes-due-to-early-IRQs.patch + 8012-brcmfmac-pcie-Support-PCIe-core-revisions-64.patch + 8013-brcmfmac-pcie-Add-IDs-properties-for-BCM4378.patch + 8014-ACPI-property-Support-strings-in-Apple-_DSM-props.patch + 8015-brcmfmac-acpi-Add-support-for-fetching-Apple-ACPI-pr.patch + 8016-brcmfmac-pcie-Provide-a-buffer-of-random-bytes-to-th.patch + 8017-brcmfmac-pcie-Add-IDs-properties-for-BCM4355.patch + 8018-brcmfmac-pcie-Add-IDs-properties-for-BCM4377.patch + 8019-brcmfmac-pcie-Perform-correct-BCM4364-firmware-selec.patch + 8020-brcmfmac-chip-Only-disable-D11-cores-handle-an-arbit.patch + 8021-brcmfmac-chip-Handle-1024-unit-sizes-for-TCM-blocks.patch + 8022-brcmfmac-cfg80211-Add-support-for-scan-params-v2.patch + 8023-brcmfmac-feature-Add-support-for-setting-feats-based.patch + 8024-brcmfmac-cfg80211-Add-support-for-PMKID_V3-operation.patch + 8025-brcmfmac-cfg80211-Pass-the-PMK-in-binary-instead-of-.patch + 8026-brcmfmac-pcie-Add-IDs-properties-for-BCM4387.patch + 8027-brcmfmac-pcie-Replace-brcmf_pcie_copy_mem_todev-with.patch + 8028-brcmfmac-pcie-Read-the-console-on-init-and-shutdown.patch + 8029-brcmfmac-pcie-Release-firmwares-in-the-brcmf_pcie_se.patch + # 8030 only applies to the linux-asahi tree and is only for M1 Macs + 8031-brcmfmac-fwil-Constify-iovar-name-arguments.patch + 8032-brcmfmac-common-Add-support-for-downloading-TxCap-bl.patch + 8033-brcmfmac-pcie-Load-and-provide-TxCap-blobs.patch + 8034-brcmfmac-common-Add-support-for-external-calibration.patch + ) + validpgpkeys=( 'ABAF11C65A2970B130ABE3C479BE3E4300411886' # Linus Torvalds '647F28654894E3BD457199BE38DBBDC86092693E' # Greg Kroah-Hartman - 'A2FF3A36AAA56654109064AB19802F8B0D70FC30' # Jan Alexander Steffens (heftig) - 'C7E7849466FE2358343588377258734B41C31549' # David Runge ) export KBUILD_BUILD_HOST=archlinux @@ -221,11 +292,67 @@ for _p in "${pkgname[@]}"; do }" done -sha256sums=('SKIP' +sha256sums=('0c4d6f0081800593852eb155b01e09b78b5bc69d7a553fc58f5ad2070f90239e' + 'SKIP' '7cbba374356a189faac71001c5344ce8f02434684b1ce1accefc0cc4bd6718e5' + '6b4da532421cac5600d09c0c52742aa52d848af098f7853abe60c02e9d0a3752' + '2184069ab00ef43d9674756e9b7a56d15188bc4494d34425f04ddc779c52acd8' 'SKIP' 'SKIP' 'b7c987889d92a48d638d5258842b10f6c856e57f29ad23475aa507c7b4ad5710' 'a3a43feaffccbcd119f4a1b4e1299ef07ae36ef9bffc17767bf10e447fa02a2a' - 'd4ca5a01da5468a1d2957b8eb4a819e1b867a3bcd1cd47389d7c9ac9154b5430') + '114ed15a4769aa4c7f9bdf2e4f892119c7f033462f0fe1a7cfd544f110e3d034' + 'cfd23a06797ac86575044428a393dd7f10f06eff7648d0b78aedad82cbe41279' + '8d8401a99a9dfbc41aa2dc5b6a409a19860b1b918465e19de4a4ff18de075ea3' + '08d165106fe35b68a7b48f216566951a5db0baac19098c015bcc81c5fcba678d' + '62f6d63815d4843ca893ca76b84a9d32590a50358ca0962017ccd75a40884ba8' + '2827dab6eeb2d2a08034938024f902846b5813e967a0ea253dc1ea88315da383' + '398dec7d54c6122ae2263cd5a6d52353800a1a60fd85e52427c372ea9974a625' + 'd4ca5a01da5468a1d2957b8eb4a819e1b867a3bcd1cd47389d7c9ac9154b5430' + '1366719f62b2d698693b31916569f1178f3d1b0a66e747b7f40f1389edceff07' + '83f4be6849ba4d5f9fad647ad2eb78bf6409ee98a40ac62e8a5b80496233d70a' + '44bd3643b2b22fedc59d79511199f30ce6759fa0acdd9a66262a53c5e046da6b' + 'eb04a492197783643b3e72b1d0cf0e856290381997bd165a14fbc63ac1489c25' + '69d56d42473526f7dbd4fb18c5e1baafe4e6d32995b2506bd48ff981c53b5385' + '1deeacae1875cf9075b858a8bfb2463ebc531c9030b7c2ab46bbb8e4c3b974db' + '40eff5e88bb30c51c6b97e85c2e7b8dec5f97916f768e6c07618d9c5afe68574' + 'cac035fe07663a319185c644c5b39b34bef89ada348881fa4a02d15290260445' + '9dfa9f02d17c5cd9620fa2c1d43ca967b81b6a56d33c2bafae14e0c64e498baa' + 'a0a190edc937e70f48b436b5fa69395f45f6135639438eaea0722e0310ecdc71' + '59426d41ff7414fb28b43307227d1df3906739b8b255063868ebe7f03d5905b5' + '31e65ffa0ec2a998de6a806f931a9ca684a9be5933918a94b0e79ef6456e0821' + '9ede98eceb69e9c93e25fdb2c567466963bdd2f81c0ecb9fb9e5107f6142ff26' + '862f631ef9f25453ce38d9ed0197e62d85f9f5a0625ed77237e643297fb42f75' + '2f7899b70d5c55aea3f6385385fea01ce21b48f9441982a94f36c842cceec083' + '2b126cda3863f49b8d3a6de8fa8cca979d87bd9e66812531be5c02c9e5840d82' + '70a277c9ad4fba624b3916e397624e557135b269c34eb704ace29aa1a6b8e430' + '42ae52b93ea0cbd0d1859512b88e0c290e3500b8e52f8de3be7398cb6039d0b4' + '300d926bac23b81d267e73433d668581ec1e3b12fa76462ba3d0b1cf2728b82d' + '01f3185e551dd49007b533d4bae37774131820a51715e1f1a391220e055afc66' + 'db55305b8e3c2a8fa0a85aeaad661717ae745d5dabc7735221adb184e89a2d1b' + '82f679f3736e09ee9ea8a8b53c052e84bb40df8a05f21a2082224184ad3cf162' + '9907f67d099a2b6243747350a2c057d82c39e822107ca57cbfdc32baf378d2cb' + 'd25cd32de8c74ba8bcb430c21f9d84deae1174594d00ea94e1fd1e2ab70ea5cb' + '823d35349844605dadf381ae7c6097379a23c72da59e3cf393fcf3e5d466dafd' + 'ed6e84bc03cd6adfc3f8def843f150b71470df6d6a88fc348d5e1b36f133f424' + '23d9018c90d02389f2ddeb0821e581d354184b3b38d4488fbc0f3363463a0c9e' + 'd2e2b0f0c80fb5b4da36d3a7a87b10c2419255c0e38e0faa1d7478eaab1b9a35' + 'ecef58f944bf61950b3211e88acd104b0006a177e76f59a47b8253aaf5e6acc6' + '1eb6e14b5504efbad7911aabc801a265e9ba13cb2fd6ce8e029af55bf97cec86' + 'f2b553e11240bb88e5d0ffd7883d808c069ede544e5c578c22975466a5c9d26a' + 'ac4b200dadbb88179bf37dcea280efe25bf42b420a90ab1399c3bd9c7905f592' + 'e12726162b868435081a215f04d921cd8b9307de71738c41090ec93a267725de' + 'bfa3bb8d16b6c26831f9b5e833d46ea2c60854f016540a051f96c418be1a728f' + 'e9df13adedefd0043ea6678c19a9de608aa69fe83929a13213c528052096ed3c' + 'b51a916bb0048d7cb57ed2afc25394ec72664efe2a8c5705b0dcfe62384e34ed' + '2ec5dddd41327b5018d41b920955182bc3f220f692a32b061d8797c8fee99dbc' + 'a8596e6180a895515cbc1f361edc8fca460f630dd15bbd161037d84717717ba8' + '55b6981468b489f5bb7c59d5f9a6b479c0d96bb1018efa209ed8506d54de8399' + '2339acd32f020db66f2a3190910d925a030798e3fd57006a09dda56e5acbf279' + 'f41ab41dd9445dee28699c1af7909723514f9d41d30a5c148d4f99617ed2d46e' + '0e6cd10376f13873a9226d233161a0dab6b1d3c6a7d66bc3c4e8d3cc0f0397d0' + '8f9a6d47eaec7d9df9a822a146ab15ca7bee906866545493cac8621570237060' + 'ecede30aa68ea4646d3efb0a7190466ff1784f4e93756a04bb58756536f28035' + '0bed877897873ae86e512d711b86fa11adc5b8e7fe35139e290e8d0a0133f6a5' + '23f4a7002632f95abb1ed75a4df0570b7a81e5cf4067a16da7101b16eb582a01') # vim:set ts=8 sts=2 sw=2 et: