├── .github ├── dependabot.yml └── workflows │ ├── apfs.yml │ └── compile_test.yml ├── .gitignore ├── 1001-Add-apple-bce-driver.patch ├── 1002-Put-apple-bce-in-drivers-staging.patch ├── 1007-HID-multitouch-support-getting-the-contact-ID-from.patch ├── 1008-HID-multitouch-support-getting-the-tip-state-from-HI.patch ├── 1009-HID-multitouch-take-cls-maxcontacts-into-account-for.patch ├── 1010-HID-multitouch-allow-specifying-if-a-device-is-direc.patch ├── 1011-HID-multitouch-add-device-ID-for-Apple-Touch-Bars.patch ├── 1013-lib-vsprintf-Add-support-for-generic-FourCCs-by-exte.patch ├── 1014-printf-add-tests-for-generic-FourCCs.patch ├── 1015-drm-appletbdrm-use-p4cl-instead-of-p4cc.patch ├── 1016-vsprintf-Use-p4chR-instead-of-p4cn-for-reading-data-.patch ├── 1017-checkpatch-remove-p4cn.patch ├── 2008-i915-4-lane-quirk-for-mbp15-1.patch ├── 2009-apple-gmux-allow-switching-to-igpu-at-probe.patch ├── 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 ├── 3008-applesmc-make-applesmc_remove-void.patch ├── 3009-applesmc-battery-charge-limiter.patch ├── 4001-asahi-trackpad.patch ├── 4002-HID-quirks-remove-T2-devices-from-hid_mouse_ignore_l.patch ├── 4003-HID-apple-ignore-the-trackpad-on-T2-Macs.patch ├── 4004-HID-magicmouse-Add-support-for-trackpads-found-on-T2.patch ├── 4005-HID-apple-Add-necessary-IDs-and-support-for-replacem.patch ├── 4006-HID-magicmouse-Add-MacBookPro15-1-replacement-trackp.patch ├── 7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch ├── 8001-Add-APFS-driver.patch ├── 8002-Necessary-modifications-to-build-APFS-with-the-kerne.patch ├── README.md ├── apfs_ver ├── extra_config └── version /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | target-branch: "6.6" 13 | -------------------------------------------------------------------------------- /.github/workflows/apfs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: APFS driver update 3 | 4 | on: 5 | schedule: 6 | - cron: '30 18 * * *' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | Publish-Mainline: 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: 'Checkout Repo' 15 | uses: actions/checkout@v4 16 | with: 17 | persist-credentials: false 18 | fetch-depth: 0 19 | 20 | - name: Get the latest driver 21 | id: publish 22 | run: | 23 | source ${{ github.workspace }}/apfs_ver 24 | source ${{ github.workspace }}/version 25 | 26 | echo "currenthash=${CURRENT_HASH}" >> $GITHUB_ENV 27 | echo "releasever=${RELEASE_VER}" >> $GITHUB_ENV 28 | 29 | git clone --depth 1 --single-branch --branch "v${KVER}" https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 30 | git clone --depth 1 https://github.com/linux-apfs/linux-apfs-rw.git ${{ github.workspace }}/linux-stable/fs/apfs 31 | cd linux-stable/fs/apfs 32 | LATEST_HASH=$(git rev-parse HEAD) 33 | echo "latesthash=${LATEST_HASH}" >> $GITHUB_ENV 34 | DKMS_VER=$(cat ./dkms.conf | grep PACKAGE_VERSION | cut -d "\"" -f 2) 35 | DKMS_NAME=$(cat ./dkms.conf | grep PACKAGE_NAME | cut -d "\"" -f 2) 36 | bash ./genver.sh 37 | rm -r -v .git 38 | rm -v .gitignore 39 | rm -v README.rst 40 | rm -v LICENSE 41 | rm -v dkms.conf 42 | rm -v genver.sh 43 | 44 | if [[ ${CURRENT_HASH} = ${LATEST_HASH} ]] 45 | then 46 | echo "publish=no" >> $GITHUB_ENV 47 | exit 0 48 | else 49 | echo "publish=yes" >> $GITHUB_ENV 50 | RELEASE_VER_MAIN=$(echo ${RELEASE_VER} | cut -d "-" -f 1) 51 | if [[ ${RELEASE_VER_MAIN} != ${DKMS_VER} ]] 52 | then 53 | NEW_RELEASE_VER=${DKMS_VER}-1 54 | else 55 | RELEASE_VER_SUB=$(echo ${RELEASE_VER} | cut -d "-" -f 2) 56 | NEW_RELEASE_VER_SUB=$((${RELEASE_VER_SUB} + 1)) 57 | NEW_RELEASE_VER=${DKMS_VER}-${NEW_RELEASE_VER_SUB} 58 | fi 59 | echo "ver=${NEW_RELEASE_VER}" >> $GITHUB_ENV 60 | cd ${{ github.workspace }}/linux-stable 61 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 62 | git config --local user.name "github-actions[bot]" 63 | git add . 64 | git commit -m "Add APFS driver" 65 | git format-patch -1 HEAD 66 | mv -v 0001-Add-APFS-driver.patch ${{ github.workspace }}/8001-Add-APFS-driver.patch 67 | fi 68 | - name: Cleanup and update the repo 69 | if: env.publish == 'yes' 70 | id: clean 71 | run: | 72 | cd ${{ github.workspace }} 73 | rm -r linux-stable 74 | sed -i "s/${{ env.releasever }}/${{ env.ver }}/g" ${{ github.workspace }}/apfs_ver 75 | sed -i "s/${{ env.currenthash }}/${{ env.latesthash }}/g" ${{ github.workspace }}/apfs_ver 76 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 77 | git config --local user.name "github-actions[bot]" 78 | git add . 79 | git commit -m "Update APFS driver to v${{ env.ver }}" 80 | - name: Push changes to the repo 81 | if: env.publish == 'yes' 82 | uses: ad-m/github-push-action@master 83 | with: 84 | github_token: ${{ secrets.GITHUB_TOKEN }} 85 | branch: ${{ github.ref }} 86 | Publish-LTS: 87 | runs-on: ubuntu-latest 88 | steps: 89 | 90 | - name: 'Checkout Repo' 91 | uses: actions/checkout@v4 92 | with: 93 | ref: 6.12 94 | persist-credentials: false 95 | fetch-depth: 0 96 | 97 | - name: Get the latest driver 98 | id: publish 99 | run: | 100 | source ${{ github.workspace }}/apfs_ver 101 | source ${{ github.workspace }}/version 102 | 103 | echo "currenthash=${CURRENT_HASH}" >> $GITHUB_ENV 104 | echo "releasever=${RELEASE_VER}" >> $GITHUB_ENV 105 | 106 | git clone --depth 1 --single-branch --branch "v${KVER}" https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 107 | git clone --depth 1 https://github.com/linux-apfs/linux-apfs-rw.git ${{ github.workspace }}/linux-stable/fs/apfs 108 | cd linux-stable/fs/apfs 109 | LATEST_HASH=$(git rev-parse HEAD) 110 | echo "latesthash=${LATEST_HASH}" >> $GITHUB_ENV 111 | DKMS_VER=$(cat ./dkms.conf | grep PACKAGE_VERSION | cut -d "\"" -f 2) 112 | DKMS_NAME=$(cat ./dkms.conf | grep PACKAGE_NAME | cut -d "\"" -f 2) 113 | bash ./genver.sh 114 | rm -r -v .git 115 | rm -v .gitignore 116 | rm -v README.rst 117 | rm -v LICENSE 118 | rm -v dkms.conf 119 | rm -v genver.sh 120 | 121 | if [[ ${CURRENT_HASH} = ${LATEST_HASH} ]] 122 | then 123 | echo "publish=no" >> $GITHUB_ENV 124 | exit 0 125 | else 126 | echo "publish=yes" >> $GITHUB_ENV 127 | RELEASE_VER_MAIN=$(echo ${RELEASE_VER} | cut -d "-" -f 1) 128 | if [[ ${RELEASE_VER_MAIN} != ${DKMS_VER} ]] 129 | then 130 | NEW_RELEASE_VER=${DKMS_VER}-1 131 | else 132 | RELEASE_VER_SUB=$(echo ${RELEASE_VER} | cut -d "-" -f 2) 133 | NEW_RELEASE_VER_SUB=$((${RELEASE_VER_SUB} + 1)) 134 | NEW_RELEASE_VER=${DKMS_VER}-${NEW_RELEASE_VER_SUB} 135 | fi 136 | echo "ver=${NEW_RELEASE_VER}" >> $GITHUB_ENV 137 | cd ${{ github.workspace }}/linux-stable 138 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 139 | git config --local user.name "github-actions[bot]" 140 | git add . 141 | git commit -m "Add APFS driver" 142 | git format-patch -1 HEAD 143 | mv -v 0001-Add-APFS-driver.patch ${{ github.workspace }}/8001-Add-APFS-driver.patch 144 | fi 145 | - name: Cleanup and update the repo 146 | if: env.publish == 'yes' 147 | id: clean 148 | run: | 149 | cd ${{ github.workspace }} 150 | rm -r linux-stable 151 | sed -i "s/${{ env.releasever }}/${{ env.ver }}/g" ${{ github.workspace }}/apfs_ver 152 | sed -i "s/${{ env.currenthash }}/${{ env.latesthash }}/g" ${{ github.workspace }}/apfs_ver 153 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 154 | git config --local user.name "github-actions[bot]" 155 | git add . 156 | git commit -m "Update APFS driver to v${{ env.ver }}" 157 | - name: Push changes to the repo 158 | if: env.publish == 'yes' 159 | uses: ad-m/github-push-action@master 160 | with: 161 | github_token: ${{ secrets.GITHUB_TOKEN }} 162 | branch: 6.12 163 | -------------------------------------------------------------------------------- /.github/workflows/compile_test.yml: -------------------------------------------------------------------------------- 1 | name: Compile Test 2 | on: [push, workflow_dispatch] 3 | jobs: 4 | compiletest: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout Repo 8 | uses: actions/checkout@v4 9 | - name: Download Kernel Source 10 | run: | 11 | source ./version 12 | _RC=$(echo $KVER | tr -d 1234567890.) 13 | 14 | if [ -n "$_RC" ]; then 15 | KSRC_URL=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-${KVER}.tar.gz 16 | curl $KSRC_URL | tar -xz 17 | else 18 | KSRC_URL=https://cdn.kernel.org/pub/linux/kernel/v${KVER//.*}.x/linux-${KVER}.tar.xz 19 | curl $KSRC_URL | tar -xJ 20 | fi 21 | 22 | 23 | - name: Install Build Dependencies 24 | run: | 25 | sudo apt-get update 26 | sudo apt-get install -y build-essential fakeroot libncurses-dev bison flex libssl-dev libelf-dev \ 27 | openssl dkms libudev-dev libpci-dev libiberty-dev autoconf wget xz-utils git \ 28 | libcap-dev bc rsync cpio dh-modaliases debhelper kernel-wedge curl gawk dwarves zstd 29 | - name: Checkpatch 30 | run: | 31 | source ./version 32 | cd linux-$KVER 33 | # Skip apple-bce because it needs a lot of formatting changes, and 34 | # modules that we won't be sending upstream. 35 | scripts/checkpatch.pl --no-signoff --terse --no-summary \ 36 | $(echo ../*.patch | tr " " "\n" | grep -v -e "apple-bce" -e asahi -e applesmc -e bcm5974 ) || true 37 | - name: Apply Patches 38 | id: apply-patches 39 | run: | 40 | source ./version 41 | cd linux-$KVER 42 | 43 | for patch in ../*.patch; do 44 | echo "Applying patch $patch..." 45 | patch -Np1 < $patch 46 | done 47 | - name: Print reject hunks 48 | run: | 49 | source ./version 50 | cd linux-$KVER 51 | cat $(find . -type f -name '*.rej') /dev/null 52 | if: always() && (steps.apply-patches.outcome == 'failure') 53 | 54 | - name: Setting Config 55 | run: | 56 | source ./version 57 | cd linux-$KVER 58 | 59 | cp arch/x86/configs/x86_64_defconfig ./.config 60 | cat ../extra_config >> .config 61 | make olddefconfig 62 | 63 | - name: Building Kernel 64 | run: | 65 | source ./version 66 | cd linux-$KVER 67 | 68 | make 69 | 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | linux-*/ 2 | -------------------------------------------------------------------------------- /1002-Put-apple-bce-in-drivers-staging.patch: -------------------------------------------------------------------------------- 1 | From dc27d4db5787546ae5eacf3483f3b87f2d4fb1c1 Mon Sep 17 00:00:00 2001 2 | From: Redecorating <69827514+Redecorating@users.noreply.github.com> 3 | Date: Mon, 7 Nov 2022 14:56:34 +0530 4 | Subject: [PATCH] Put apple-bce in drivers/staging 5 | 6 | --- 7 | drivers/staging/Kconfig | 2 ++ 8 | drivers/staging/Makefile | 1 + 9 | drivers/staging/apple-bce/Kconfig | 18 ++++++++++++++++++ 10 | drivers/staging/apple-bce/Makefile | 2 +- 11 | 4 files changed, 22 insertions(+), 1 deletion(-) 12 | create mode 100644 drivers/staging/apple-bce/Kconfig 13 | 14 | diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig 15 | index 5cfabd537..3b8e61d26 100644 16 | --- a/drivers/staging/Kconfig 17 | +++ b/drivers/staging/Kconfig 18 | @@ -50,4 +50,6 @@ source "drivers/staging/vme_user/Kconfig" 19 | 20 | source "drivers/staging/gpib/Kconfig" 21 | 22 | +source "drivers/staging/apple-bce/Kconfig" 23 | + 24 | endif # STAGING 25 | diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile 26 | index f8c3aa9c2..1e148d6c3 100644 27 | --- a/drivers/staging/Makefile 28 | +++ b/drivers/staging/Makefile 29 | @@ -29,3 +29,4 @@ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ 30 | obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ 31 | obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ 32 | obj-$(CONFIG_GPIB) += gpib/ 33 | +obj-$(CONFIG_APPLE_BCE) += apple-bce/ 34 | diff --git a/drivers/staging/apple-bce/Kconfig b/drivers/staging/apple-bce/Kconfig 35 | new file mode 100644 36 | index 000000000..fe92bc441 37 | --- /dev/null 38 | +++ b/drivers/staging/apple-bce/Kconfig 39 | @@ -0,0 +1,18 @@ 40 | +config APPLE_BCE 41 | + tristate "Apple BCE driver (VHCI and Audio support)" 42 | + default m 43 | + depends on X86 44 | + select SOUND 45 | + select SND 46 | + select SND_PCM 47 | + select SND_JACK 48 | + help 49 | + VHCI and audio support on Apple MacBooks with the T2 Chip. 50 | + This driver is divided in three components: 51 | + - BCE (Buffer Copy Engine): which establishes a basic communication 52 | + channel with the T2 chip. This component is required by the other two: 53 | + - VHCI (Virtual Host Controller Interface): Access to keyboard, mouse 54 | + and other system devices depend on this virtual USB host controller 55 | + - Audio: a driver for the T2 audio interface. 56 | + 57 | + If "M" is selected, the module will be called apple-bce.' 58 | diff --git a/drivers/staging/apple-bce/Makefile b/drivers/staging/apple-bce/Makefile 59 | index a6a656f06..8cfbd3f64 100644 60 | --- a/drivers/staging/apple-bce/Makefile 61 | +++ b/drivers/staging/apple-bce/Makefile 62 | @@ -1,5 +1,5 @@ 63 | modname := apple-bce 64 | -obj-m += $(modname).o 65 | +obj-$(CONFIG_APPLE_BCE) += $(modname).o 66 | 67 | apple-bce-objs := apple_bce.o mailbox.o queue.o queue_dma.o vhci/vhci.o vhci/queue.o vhci/transfer.o audio/audio.o audio/protocol.o audio/protocol_bce.o audio/pcm.o 68 | 69 | -- 70 | 2.34.1 71 | -------------------------------------------------------------------------------- /1007-HID-multitouch-support-getting-the-contact-ID-from.patch: -------------------------------------------------------------------------------- 1 | From 2f9be28549307b4ac51e8d66bf3b8d5e0621466d Mon Sep 17 00:00:00 2001 2 | From: Kerem Karabay 3 | Date: Wed, 19 Jul 2023 19:37:14 +0300 4 | Subject: [PATCH 04/12] HID: multitouch: support getting the contact ID from 5 | HID_DG_TRANSDUCER_INDEX fields 6 | 7 | This is needed to support Apple Touch Bars, where the contact ID is 8 | contained in fields with the HID_DG_TRANSDUCER_INDEX usage. 9 | 10 | Signed-off-by: Kerem Karabay 11 | --- 12 | drivers/hid/hid-multitouch.c | 5 ++++- 13 | 1 file changed, 4 insertions(+), 1 deletion(-) 14 | 15 | diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c 16 | index e31be0cb8..902a59928 100644 17 | --- a/drivers/hid/hid-multitouch.c 18 | +++ b/drivers/hid/hid-multitouch.c 19 | @@ -636,7 +636,9 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, 20 | 21 | if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { 22 | for (n = 0; n < field->report_count; n++) { 23 | - if (field->usage[n].hid == HID_DG_CONTACTID) { 24 | + unsigned int hid = field->usage[n].hid; 25 | + 26 | + if (hid == HID_DG_CONTACTID || hid == HID_DG_TRANSDUCER_INDEX) { 27 | rdata->is_mt_collection = true; 28 | break; 29 | } 30 | @@ -815,6 +817,7 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, 31 | MT_STORE_FIELD(tip_state); 32 | return 1; 33 | case HID_DG_CONTACTID: 34 | + case HID_DG_TRANSDUCER_INDEX: 35 | MT_STORE_FIELD(contactid); 36 | app->touches_by_report++; 37 | return 1; 38 | -- 39 | 2.42.0 40 | 41 | -------------------------------------------------------------------------------- /1008-HID-multitouch-support-getting-the-tip-state-from-HI.patch: -------------------------------------------------------------------------------- 1 | From 6162d328fe7b2cf5a3ee8c29bdb229e9528c7a6c Mon Sep 17 00:00:00 2001 2 | From: Kerem Karabay 3 | Date: Wed, 19 Jul 2023 19:44:10 +0300 4 | Subject: [PATCH 05/12] HID: multitouch: support getting the tip state from 5 | HID_DG_TOUCH fields 6 | 7 | This is necessary on Apple Touch Bars, where the tip state is contained 8 | in fields with the HID_DG_TOUCH usage. This feature is gated by a quirk 9 | in order to prevent breaking other devices, see commit c2ef8f21ea8f 10 | ("HID: multitouch: add support for trackpads"). 11 | 12 | Signed-off-by: Kerem Karabay 13 | --- 14 | drivers/hid/hid-multitouch.c | 14 ++++++++++---- 15 | 1 file changed, 10 insertions(+), 4 deletions(-) 16 | 17 | diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c 18 | index 902a59928..dd5509eeb 100644 19 | --- a/drivers/hid/hid-multitouch.c 20 | +++ b/drivers/hid/hid-multitouch.c 21 | @@ -72,6 +72,7 @@ MODULE_LICENSE("GPL"); 22 | #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) 23 | #define MT_QUIRK_DISABLE_WAKEUP BIT(21) 24 | #define MT_QUIRK_ORIENTATION_INVERT BIT(22) 25 | +#define MT_QUIRK_TOUCH_IS_TIPSTATE BIT(23) 26 | 27 | #define MT_INPUTMODE_TOUCHSCREEN 0x02 28 | #define MT_INPUTMODE_TOUCHPAD 0x03 29 | @@ -810,6 +811,15 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, 30 | 31 | MT_STORE_FIELD(confidence_state); 32 | return 1; 33 | + case HID_DG_TOUCH: 34 | + /* 35 | + * Legacy devices use TIPSWITCH and not TOUCH. 36 | + * Let's just ignore this field unless the quirk is set. 37 | + */ 38 | + if (!(cls->quirks & MT_QUIRK_TOUCH_IS_TIPSTATE)) 39 | + return -1; 40 | + 41 | + fallthrough; 42 | case HID_DG_TIPSWITCH: 43 | if (field->application != HID_GD_SYSTEM_MULTIAXIS) 44 | input_set_capability(hi->input, 45 | @@ -873,10 +883,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, 46 | case HID_DG_CONTACTMAX: 47 | /* contact max are global to the report */ 48 | return -1; 49 | - case HID_DG_TOUCH: 50 | - /* Legacy devices use TIPSWITCH and not TOUCH. 51 | - * Let's just ignore this field. */ 52 | - return -1; 53 | } 54 | /* let hid-input decide for the others */ 55 | return 0; 56 | -- 57 | 2.42.0 58 | 59 | -------------------------------------------------------------------------------- /1009-HID-multitouch-take-cls-maxcontacts-into-account-for.patch: -------------------------------------------------------------------------------- 1 | From e923c6e1a5a508e341851ae020cdb3e7333ccd18 Mon Sep 17 00:00:00 2001 2 | From: Kerem Karabay 3 | Date: Wed, 19 Jul 2023 19:26:57 +0300 4 | Subject: [PATCH 06/12] HID: multitouch: take cls->maxcontacts into account for 5 | devices without a HID_DG_CONTACTMAX field too 6 | 7 | This is needed for Apple Touch Bars, where no HID_DG_CONTACTMAX field is 8 | present and the maximum contact count is greater than the default. 9 | 10 | Signed-off-by: Kerem Karabay 11 | --- 12 | drivers/hid/hid-multitouch.c | 7 ++++--- 13 | 1 file changed, 4 insertions(+), 3 deletions(-) 14 | 15 | diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c 16 | index dd5509eeb..624c1d3cc 100644 17 | --- a/drivers/hid/hid-multitouch.c 18 | +++ b/drivers/hid/hid-multitouch.c 19 | @@ -491,9 +491,6 @@ static void mt_feature_mapping(struct hid_device *hdev, 20 | if (!td->maxcontacts && 21 | field->logical_maximum <= MT_MAX_MAXCONTACT) 22 | td->maxcontacts = field->logical_maximum; 23 | - if (td->mtclass.maxcontacts) 24 | - /* check if the maxcontacts is given by the class */ 25 | - td->maxcontacts = td->mtclass.maxcontacts; 26 | 27 | break; 28 | case HID_DG_BUTTONTYPE: 29 | @@ -1310,6 +1307,10 @@ static int mt_touch_input_configured(struct hid_device *hdev, 30 | struct input_dev *input = hi->input; 31 | int ret; 32 | 33 | + /* check if the maxcontacts is given by the class */ 34 | + if (cls->maxcontacts) 35 | + td->maxcontacts = cls->maxcontacts; 36 | + 37 | if (!td->maxcontacts) 38 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; 39 | 40 | -- 41 | 2.42.0 42 | 43 | -------------------------------------------------------------------------------- /1010-HID-multitouch-allow-specifying-if-a-device-is-direc.patch: -------------------------------------------------------------------------------- 1 | From b9f7232d2696b91ae98fadd7b14c531aa8edceb5 Mon Sep 17 00:00:00 2001 2 | From: Kerem Karabay 3 | Date: Wed, 19 Jul 2023 19:39:53 +0300 4 | Subject: [PATCH 07/12] HID: multitouch: allow specifying if a device is direct 5 | in a class 6 | 7 | Currently the driver determines the device type based on the 8 | application, but this value is not reliable on Apple Touch Bars, where 9 | the application is HID_DG_TOUCHPAD even though the devices are direct, 10 | so allow setting it in classes. 11 | 12 | Signed-off-by: Kerem Karabay 13 | --- 14 | drivers/hid/hid-multitouch.c | 8 ++++++-- 15 | 1 file changed, 6 insertions(+), 2 deletions(-) 16 | 17 | diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c 18 | index 624c1d3cc..f98fb36ff 100644 19 | --- a/drivers/hid/hid-multitouch.c 20 | +++ b/drivers/hid/hid-multitouch.c 21 | @@ -147,6 +147,7 @@ struct mt_class { 22 | __s32 sn_height; /* Signal/noise ratio for height events */ 23 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ 24 | __u8 maxcontacts; 25 | + bool is_direct; /* true for touchscreens */ 26 | bool is_indirect; /* true for touchpads */ 27 | bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */ 28 | }; 29 | @@ -564,13 +565,13 @@ static struct mt_application *mt_allocate_application(struct mt_device *td, 30 | mt_application->application = application; 31 | INIT_LIST_HEAD(&mt_application->mt_usages); 32 | 33 | - if (application == HID_DG_TOUCHSCREEN) 34 | + if (application == HID_DG_TOUCHSCREEN && !td->mtclass.is_indirect) 35 | mt_application->mt_flags |= INPUT_MT_DIRECT; 36 | 37 | /* 38 | * Model touchscreens providing buttons as touchpads. 39 | */ 40 | - if (application == HID_DG_TOUCHPAD) { 41 | + if (application == HID_DG_TOUCHPAD && !td->mtclass.is_direct) { 42 | mt_application->mt_flags |= INPUT_MT_POINTER; 43 | td->inputmode_value = MT_INPUTMODE_TOUCHPAD; 44 | } 45 | @@ -1318,6 +1319,9 @@ static int mt_touch_input_configured(struct hid_device *hdev, 46 | if (td->serial_maybe) 47 | mt_post_parse_default_settings(td, app); 48 | 49 | + if (cls->is_direct) 50 | + app->mt_flags |= INPUT_MT_DIRECT; 51 | + 52 | if (cls->is_indirect) 53 | app->mt_flags |= INPUT_MT_POINTER; 54 | 55 | -- 56 | 2.42.0 57 | 58 | -------------------------------------------------------------------------------- /1011-HID-multitouch-add-device-ID-for-Apple-Touch-Bars.patch: -------------------------------------------------------------------------------- 1 | From a74de0b6f2e1b79d54e84dbeab1b310232275d6c Mon Sep 17 00:00:00 2001 2 | From: Kerem Karabay 3 | Date: Wed, 19 Jul 2023 19:46:02 +0300 4 | Subject: [PATCH 08/12] HID: multitouch: add device ID for Apple Touch Bars 5 | 6 | Note that this is device ID is for T2 Macs. Testing on T1 Macs would be 7 | appreciated. 8 | 9 | Signed-off-by: Kerem Karabay 10 | --- 11 | drivers/hid/Kconfig | 1 + 12 | drivers/hid/hid-multitouch.c | 26 ++++++++++++++++++++++---- 13 | 2 files changed, 23 insertions(+), 4 deletions(-) 14 | 15 | diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig 16 | index 852de13aa..4e238df87 100644 17 | --- a/drivers/hid/Kconfig 18 | +++ b/drivers/hid/Kconfig 19 | @@ -737,6 +737,7 @@ config HID_MULTITOUCH 20 | Say Y here if you have one of the following devices: 21 | - 3M PCT touch screens 22 | - ActionStar dual touch panels 23 | + - Touch Bars on x86 MacBook Pros 24 | - Atmel panels 25 | - Cando dual touch panels 26 | - Chunghwa panels 27 | diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c 28 | index f98fb36ff..f881b19db 100644 29 | --- a/drivers/hid/hid-multitouch.c 30 | +++ b/drivers/hid/hid-multitouch.c 31 | @@ -215,6 +215,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); 32 | #define MT_CLS_GOOGLE 0x0111 33 | #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 34 | #define MT_CLS_SMART_TECH 0x0113 35 | +#define MT_CLS_APPLE_TOUCHBAR 0x0114 36 | #define MT_CLS_SIS 0x0457 37 | 38 | #define MT_DEFAULT_MAXCONTACT 10 39 | @@ -399,6 +400,13 @@ static const struct mt_class mt_classes[] = { 40 | MT_QUIRK_CONTACT_CNT_ACCURATE | 41 | MT_QUIRK_SEPARATE_APP_REPORT, 42 | }, 43 | + { .name = MT_CLS_APPLE_TOUCHBAR, 44 | + .quirks = MT_QUIRK_HOVERING | 45 | + MT_QUIRK_TOUCH_IS_TIPSTATE | 46 | + MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE, 47 | + .is_direct = true, 48 | + .maxcontacts = 11, 49 | + }, 50 | { .name = MT_CLS_SIS, 51 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | 52 | MT_QUIRK_ALWAYS_VALID | 53 | @@ -1755,6 +1763,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 54 | } 55 | } 56 | 57 | + ret = hid_parse(hdev); 58 | + if (ret != 0) 59 | + return ret; 60 | + 61 | + if (mtclass->name == MT_CLS_APPLE_TOUCHBAR && 62 | + !hid_find_field(hdev, HID_INPUT_REPORT, 63 | + HID_DG_TOUCHPAD, HID_DG_TRANSDUCER_INDEX)) 64 | + return -ENODEV; 65 | + 66 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); 67 | if (!td) { 68 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); 69 | @@ -1802,10 +1819,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 70 | 71 | timer_setup(&td->release_timer, mt_expired_timeout, 0); 72 | 73 | - ret = hid_parse(hdev); 74 | - if (ret != 0) 75 | - return ret; 76 | - 77 | if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID) 78 | mt_fix_const_fields(hdev, HID_DG_CONTACTID); 79 | 80 | @@ -2240,6 +2253,11 @@ static const struct hid_device_id mt_devices[] = { 81 | MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, 82 | USB_DEVICE_ID_XIROKU_CSR2) }, 83 | 84 | + /* Apple Touch Bars */ 85 | + { .driver_data = MT_CLS_APPLE_TOUCHBAR, 86 | + HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 87 | + USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) }, 88 | + 89 | /* Google MT devices */ 90 | { .driver_data = MT_CLS_GOOGLE, 91 | HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE, 92 | -- 93 | 2.42.0 94 | 95 | -------------------------------------------------------------------------------- /1013-lib-vsprintf-Add-support-for-generic-FourCCs-by-exte.patch: -------------------------------------------------------------------------------- 1 | From f36469772a759d953c95719dd3a8b8c78cbf61b5 Mon Sep 17 00:00:00 2001 2 | From: Hector Martin 3 | Date: Tue, 8 Apr 2025 12:17:57 +0530 4 | Subject: [PATCH 1/5] lib/vsprintf: Add support for generic FourCCs by 5 | extending %p4cc 6 | 7 | %p4cc is designed for DRM/V4L2 FourCCs with their specific quirks, but 8 | it's useful to be able to print generic 4-character codes formatted as 9 | an integer. Extend it to add format specifiers for printing generic 10 | 32-bit FourCCs with various endian semantics: 11 | 12 | %p4ch Host byte order 13 | %p4cn Network byte order 14 | %p4cl Little-endian 15 | %p4cb Big-endian 16 | 17 | The endianness determines how bytes are interpreted as a u32, and the 18 | FourCC is then always printed MSByte-first (this is the opposite of 19 | V4L/DRM FourCCs). This covers most practical cases, e.g. %p4cn would 20 | allow printing LSByte-first FourCCs stored in host endian order 21 | (other than the hex form being in character order, not the integer 22 | value). 23 | 24 | Acked-by: Rasmus Villemoes 25 | Reviewed-by: Andy Shevchenko 26 | Reviewed-by: Petr Mladek 27 | Tested-by: Petr Mladek 28 | Signed-off-by: Hector Martin 29 | Signed-off-by: Aditya Garg 30 | Reviewed-by: Kees Cook 31 | Link: https://lore.kernel.org/r/PN3PR01MB9597B01823415CB7FCD3BC27B8B52@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM 32 | Signed-off-by: Alyssa Rosenzweig 33 | --- 34 | Documentation/core-api/printk-formats.rst | 32 +++++++++++++++++++++ 35 | lib/vsprintf.c | 35 +++++++++++++++++++---- 36 | scripts/checkpatch.pl | 2 +- 37 | 3 files changed, 62 insertions(+), 7 deletions(-) 38 | 39 | diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst 40 | index 4bdc394e8..125fd0397 100644 41 | --- a/Documentation/core-api/printk-formats.rst 42 | +++ b/Documentation/core-api/printk-formats.rst 43 | @@ -648,6 +648,38 @@ Examples:: 44 | %p4cc Y10 little-endian (0x20303159) 45 | %p4cc NV12 big-endian (0xb231564e) 46 | 47 | +Generic FourCC code 48 | +------------------- 49 | + 50 | +:: 51 | + %p4c[hnlb] gP00 (0x67503030) 52 | + 53 | +Print a generic FourCC code, as both ASCII characters and its numerical 54 | +value as hexadecimal. 55 | + 56 | +The generic FourCC code is always printed in the big-endian format, 57 | +the most significant byte first. This is the opposite of V4L/DRM FourCCs. 58 | + 59 | +The additional ``h``, ``n``, ``l``, and ``b`` specifiers define what 60 | +endianness is used to load the stored bytes. The data might be interpreted 61 | +using the host byte order, network byte order, little-endian, or big-endian. 62 | + 63 | +Passed by reference. 64 | + 65 | +Examples for a little-endian machine, given &(u32)0x67503030:: 66 | + 67 | + %p4ch gP00 (0x67503030) 68 | + %p4cn 00Pg (0x30305067) 69 | + %p4cl gP00 (0x67503030) 70 | + %p4cb 00Pg (0x30305067) 71 | + 72 | +Examples for a big-endian machine, given &(u32)0x67503030:: 73 | + 74 | + %p4ch gP00 (0x67503030) 75 | + %p4cn 00Pg (0x30305067) 76 | + %p4cl 00Pg (0x30305067) 77 | + %p4cb gP00 (0x67503030) 78 | + 79 | Rust 80 | ---- 81 | 82 | diff --git a/lib/vsprintf.c b/lib/vsprintf.c 83 | index 01699852f..6bc64ae52 100644 84 | --- a/lib/vsprintf.c 85 | +++ b/lib/vsprintf.c 86 | @@ -1793,27 +1793,50 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc, 87 | char output[sizeof("0123 little-endian (0x01234567)")]; 88 | char *p = output; 89 | unsigned int i; 90 | + bool pixel_fmt = false; 91 | u32 orig, val; 92 | 93 | - if (fmt[1] != 'c' || fmt[2] != 'c') 94 | + if (fmt[1] != 'c') 95 | return error_string(buf, end, "(%p4?)", spec); 96 | 97 | if (check_pointer(&buf, end, fourcc, spec)) 98 | return buf; 99 | 100 | orig = get_unaligned(fourcc); 101 | - val = orig & ~BIT(31); 102 | + switch (fmt[2]) { 103 | + case 'h': 104 | + break; 105 | + case 'n': 106 | + orig = swab32(orig); 107 | + break; 108 | + case 'l': 109 | + orig = (__force u32)cpu_to_le32(orig); 110 | + break; 111 | + case 'b': 112 | + orig = (__force u32)cpu_to_be32(orig); 113 | + break; 114 | + case 'c': 115 | + /* Pixel formats are printed LSB-first */ 116 | + pixel_fmt = true; 117 | + break; 118 | + default: 119 | + return error_string(buf, end, "(%p4?)", spec); 120 | + } 121 | + 122 | + val = pixel_fmt ? swab32(orig & ~BIT(31)) : orig; 123 | 124 | for (i = 0; i < sizeof(u32); i++) { 125 | - unsigned char c = val >> (i * 8); 126 | + unsigned char c = val >> ((3 - i) * 8); 127 | 128 | /* Print non-control ASCII characters as-is, dot otherwise */ 129 | *p++ = isascii(c) && isprint(c) ? c : '.'; 130 | } 131 | 132 | - *p++ = ' '; 133 | - strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian"); 134 | - p += strlen(p); 135 | + if (pixel_fmt) { 136 | + *p++ = ' '; 137 | + strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian"); 138 | + p += strlen(p); 139 | + } 140 | 141 | *p++ = ' '; 142 | *p++ = '('; 143 | diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl 144 | index 3d22bf863..44e233b6f 100755 145 | --- a/scripts/checkpatch.pl 146 | +++ b/scripts/checkpatch.pl 147 | @@ -6891,7 +6891,7 @@ sub process { 148 | ($extension eq "f" && 149 | defined $qualifier && $qualifier !~ /^w/) || 150 | ($extension eq "4" && 151 | - defined $qualifier && $qualifier !~ /^cc/)) { 152 | + defined $qualifier && $qualifier !~ /^c[hnlbc]/)) { 153 | $bad_specifier = $specifier; 154 | last; 155 | } 156 | -- 157 | 2.49.0 158 | 159 | -------------------------------------------------------------------------------- /1014-printf-add-tests-for-generic-FourCCs.patch: -------------------------------------------------------------------------------- 1 | From 459024d6769c96a110d434b0eb80580ea370c4b5 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Tue, 8 Apr 2025 12:18:32 +0530 4 | Subject: [PATCH 2/5] printf: add tests for generic FourCCs 5 | 6 | This patch adds support for kunit tests of generic 32-bit FourCCs added to 7 | vsprintf. 8 | 9 | Acked-by: Tamir Duberstein 10 | Reviewed-by: Andy Shevchenko 11 | Reviewed-by: Petr Mladek 12 | Tested-by: Petr Mladek 13 | Signed-off-by: Aditya Garg 14 | Reviewed-by: Kees Cook 15 | Link: https://lore.kernel.org/r/PN3PR01MB95973AF4F6262B2D1996FB25B8B52@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM 16 | Signed-off-by: Alyssa Rosenzweig 17 | --- 18 | lib/tests/printf_kunit.c | 39 ++++++++++++++++++++++++++++++++------- 19 | 1 file changed, 32 insertions(+), 7 deletions(-) 20 | 21 | diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c 22 | index 2c9f6170b..b1fa0dcea 100644 23 | --- a/lib/tests/printf_kunit.c 24 | +++ b/lib/tests/printf_kunit.c 25 | @@ -701,21 +701,46 @@ static void fwnode_pointer(struct kunit *kunittest) 26 | software_node_unregister_node_group(group); 27 | } 28 | 29 | +struct fourcc_struct { 30 | + u32 code; 31 | + const char *str; 32 | +}; 33 | + 34 | +static void fourcc_pointer_test(struct kunit *kunittest, const struct fourcc_struct *fc, 35 | + size_t n, const char *fmt) 36 | +{ 37 | + size_t i; 38 | + 39 | + for (i = 0; i < n; i++) 40 | + test(fc[i].str, fmt, &fc[i].code); 41 | +} 42 | + 43 | static void fourcc_pointer(struct kunit *kunittest) 44 | { 45 | - struct { 46 | - u32 code; 47 | - char *str; 48 | - } const try[] = { 49 | + static const struct fourcc_struct try_cc[] = { 50 | { 0x3231564e, "NV12 little-endian (0x3231564e)", }, 51 | { 0xb231564e, "NV12 big-endian (0xb231564e)", }, 52 | { 0x10111213, ".... little-endian (0x10111213)", }, 53 | { 0x20303159, "Y10 little-endian (0x20303159)", }, 54 | }; 55 | - unsigned int i; 56 | + static const struct fourcc_struct try_ch[] = { 57 | + { 0x41424344, "ABCD (0x41424344)", }, 58 | + }; 59 | + static const struct fourcc_struct try_cn[] = { 60 | + { 0x41424344, "DCBA (0x44434241)", }, 61 | + }; 62 | + static const struct fourcc_struct try_cl[] = { 63 | + { (__force u32)cpu_to_le32(0x41424344), "ABCD (0x41424344)", }, 64 | + }; 65 | + static const struct fourcc_struct try_cb[] = { 66 | + { (__force u32)cpu_to_be32(0x41424344), "ABCD (0x41424344)", }, 67 | + }; 68 | 69 | - for (i = 0; i < ARRAY_SIZE(try); i++) 70 | - test(try[i].str, "%p4cc", &try[i].code); 71 | + fourcc_pointer_test(kunittest, try_cc, ARRAY_SIZE(try_cc), "%p4cc"); 72 | + fourcc_pointer_test(kunittest, try_ch, ARRAY_SIZE(try_ch), "%p4ch"); 73 | + fourcc_pointer_test(kunittest, try_cn, ARRAY_SIZE(try_cn), "%p4cn"); 74 | + fourcc_pointer_test(kunittest, try_cl, ARRAY_SIZE(try_cl), "%p4cl"); 75 | + fourcc_pointer_test(kunittest, try_cb, ARRAY_SIZE(try_cb), "%p4cb"); 76 | } 77 | 78 | static void 79 | -- 80 | 2.49.0 81 | 82 | -------------------------------------------------------------------------------- /1015-drm-appletbdrm-use-p4cl-instead-of-p4cc.patch: -------------------------------------------------------------------------------- 1 | From f58df41bb14f6e1cf5cd88eb9b681ac57eaed8b0 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Tue, 8 Apr 2025 12:19:11 +0530 4 | Subject: [PATCH 3/5] drm/appletbdrm: use %p4cl instead of %p4cc 5 | 6 | Due to lack of a proper format specifier, %p4cc was being used instead 7 | of %p4cl for the purpose of printing FourCCs. But the disadvange was 8 | that they were being printed in a reverse order. %p4cl should correct 9 | this issue. 10 | 11 | Reviewed-by: Alyssa Rosenzweig 12 | Signed-off-by: Aditya Garg 13 | Link: https://lore.kernel.org/r/PN3PR01MB959783DC6377C4CAB203D7ADB8B52@PN3PR01MB9597.INDPRD01.PROD.OUTLOOK.COM 14 | Signed-off-by: Alyssa Rosenzweig 15 | --- 16 | drivers/gpu/drm/tiny/appletbdrm.c | 4 ++-- 17 | 1 file changed, 2 insertions(+), 2 deletions(-) 18 | 19 | diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c 20 | index 4370ba22d..8643216ba 100644 21 | --- a/drivers/gpu/drm/tiny/appletbdrm.c 22 | +++ b/drivers/gpu/drm/tiny/appletbdrm.c 23 | @@ -214,7 +214,7 @@ static int appletbdrm_read_response(struct appletbdrm_device *adev, 24 | } 25 | 26 | if (response->msg != expected_response) { 27 | - drm_err(drm, "Unexpected response from device (expected %p4cc found %p4cc)\n", 28 | + drm_err(drm, "Unexpected response from device (expected %p4cl found %p4cl)\n", 29 | &expected_response, &response->msg); 30 | return -EIO; 31 | } 32 | @@ -288,7 +288,7 @@ static int appletbdrm_get_information(struct appletbdrm_device *adev) 33 | } 34 | 35 | if (pixel_format != APPLETBDRM_PIXEL_FORMAT) { 36 | - drm_err(drm, "Encountered unknown pixel format (%p4cc)\n", &pixel_format); 37 | + drm_err(drm, "Encountered unknown pixel format (%p4cl)\n", &pixel_format); 38 | ret = -EINVAL; 39 | goto free_info; 40 | } 41 | -- 42 | 2.49.0 43 | 44 | -------------------------------------------------------------------------------- /1016-vsprintf-Use-p4chR-instead-of-p4cn-for-reading-data-.patch: -------------------------------------------------------------------------------- 1 | From 391f6d69ac9f0ce2f16636505c8b74025a93889b Mon Sep 17 00:00:00 2001 2 | From: Petr Mladek 3 | Date: Mon, 28 Apr 2025 14:31:32 +0200 4 | Subject: [PATCH 4/5] vsprintf: Use %p4chR instead of %p4cn for reading data in 5 | reversed host ordering 6 | 7 | The generic FourCC format always prints the data using the big endian 8 | order. It is generic because it allows to read the data using a custom 9 | ordering. 10 | 11 | The current code uses "n" for reading data in the reverse host ordering. 12 | It makes the 4 variants [hnbl] consistent with the generic printing 13 | of IPv4 addresses. 14 | 15 | Unfortunately, it creates confusion on big endian systems. For example, 16 | it shows the data &(u32)0x67503030 as 17 | 18 | %p4cn 00Pg (0x30305067) 19 | 20 | But people expect that the ordering stays the same. The network ordering 21 | is a big-endian ordering. 22 | 23 | The problem is that the semantic is not the same. The modifiers affect 24 | the output ordering of IPv4 addresses while they affect the reading order 25 | in case of FourCC code. 26 | 27 | Avoid the confusion by replacing the "n" modifier with "hR", aka 28 | reverse host ordering. It is inspired by the existing %p[mM]R printf 29 | format. 30 | 31 | Reported-by: Geert Uytterhoeven 32 | Closes: https://lore.kernel.org/r/CAMuHMdV9tX=TG7E_CrSF=2PY206tXf+_yYRuacG48EWEtJLo-Q@mail.gmail.com 33 | Signed-off-by: Petr Mladek 34 | Acked-by: Alyssa Rosenzweig 35 | Reviewed-by: Geert Uytterhoeven 36 | Reviewed-by: Aditya Garg 37 | Link: https://lore.kernel.org/r/20250428123132.578771-1-pmladek@suse.com 38 | Signed-off-by: Alyssa Rosenzweig 39 | --- 40 | Documentation/core-api/printk-formats.rst | 10 +++++----- 41 | lib/tests/printf_kunit.c | 4 ++-- 42 | lib/vsprintf.c | 11 ++++++++--- 43 | 3 files changed, 15 insertions(+), 10 deletions(-) 44 | 45 | diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst 46 | index 125fd0397..f531873bb 100644 47 | --- a/Documentation/core-api/printk-formats.rst 48 | +++ b/Documentation/core-api/printk-formats.rst 49 | @@ -652,7 +652,7 @@ Generic FourCC code 50 | ------------------- 51 | 52 | :: 53 | - %p4c[hnlb] gP00 (0x67503030) 54 | + %p4c[h[R]lb] gP00 (0x67503030) 55 | 56 | Print a generic FourCC code, as both ASCII characters and its numerical 57 | value as hexadecimal. 58 | @@ -660,23 +660,23 @@ value as hexadecimal. 59 | The generic FourCC code is always printed in the big-endian format, 60 | the most significant byte first. This is the opposite of V4L/DRM FourCCs. 61 | 62 | -The additional ``h``, ``n``, ``l``, and ``b`` specifiers define what 63 | +The additional ``h``, ``hR``, ``l``, and ``b`` specifiers define what 64 | endianness is used to load the stored bytes. The data might be interpreted 65 | -using the host byte order, network byte order, little-endian, or big-endian. 66 | +using the host, reversed host byte order, little-endian, or big-endian. 67 | 68 | Passed by reference. 69 | 70 | Examples for a little-endian machine, given &(u32)0x67503030:: 71 | 72 | %p4ch gP00 (0x67503030) 73 | - %p4cn 00Pg (0x30305067) 74 | + %p4chR 00Pg (0x30305067) 75 | %p4cl gP00 (0x67503030) 76 | %p4cb 00Pg (0x30305067) 77 | 78 | Examples for a big-endian machine, given &(u32)0x67503030:: 79 | 80 | %p4ch gP00 (0x67503030) 81 | - %p4cn 00Pg (0x30305067) 82 | + %p4chR 00Pg (0x30305067) 83 | %p4cl 00Pg (0x30305067) 84 | %p4cb gP00 (0x67503030) 85 | 86 | diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c 87 | index b1fa0dcea..bc54cca2d 100644 88 | --- a/lib/tests/printf_kunit.c 89 | +++ b/lib/tests/printf_kunit.c 90 | @@ -726,7 +726,7 @@ static void fourcc_pointer(struct kunit *kunittest) 91 | static const struct fourcc_struct try_ch[] = { 92 | { 0x41424344, "ABCD (0x41424344)", }, 93 | }; 94 | - static const struct fourcc_struct try_cn[] = { 95 | + static const struct fourcc_struct try_chR[] = { 96 | { 0x41424344, "DCBA (0x44434241)", }, 97 | }; 98 | static const struct fourcc_struct try_cl[] = { 99 | @@ -738,7 +738,7 @@ static void fourcc_pointer(struct kunit *kunittest) 100 | 101 | fourcc_pointer_test(kunittest, try_cc, ARRAY_SIZE(try_cc), "%p4cc"); 102 | fourcc_pointer_test(kunittest, try_ch, ARRAY_SIZE(try_ch), "%p4ch"); 103 | - fourcc_pointer_test(kunittest, try_cn, ARRAY_SIZE(try_cn), "%p4cn"); 104 | + fourcc_pointer_test(kunittest, try_chR, ARRAY_SIZE(try_chR), "%p4chR"); 105 | fourcc_pointer_test(kunittest, try_cl, ARRAY_SIZE(try_cl), "%p4cl"); 106 | fourcc_pointer_test(kunittest, try_cb, ARRAY_SIZE(try_cb), "%p4cb"); 107 | } 108 | diff --git a/lib/vsprintf.c b/lib/vsprintf.c 109 | index 6bc64ae52..d8a2ec083 100644 110 | --- a/lib/vsprintf.c 111 | +++ b/lib/vsprintf.c 112 | @@ -1805,9 +1805,8 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc, 113 | orig = get_unaligned(fourcc); 114 | switch (fmt[2]) { 115 | case 'h': 116 | - break; 117 | - case 'n': 118 | - orig = swab32(orig); 119 | + if (fmt[3] == 'R') 120 | + orig = swab32(orig); 121 | break; 122 | case 'l': 123 | orig = (__force u32)cpu_to_le32(orig); 124 | @@ -2397,6 +2396,12 @@ early_param("no_hash_pointers", no_hash_pointers_enable); 125 | * read the documentation (path below) first. 126 | * - 'NF' For a netdev_features_t 127 | * - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value. 128 | + * - '4c[h[R]lb]' For generic FourCC code with raw numerical value. Both are 129 | + * displayed in the big-endian format. This is the opposite of V4L2 or 130 | + * DRM FourCCs. 131 | + * The additional specifiers define what endianness is used to load 132 | + * the stored bytes. The data might be interpreted using the host, 133 | + * reversed host byte order, little-endian, or big-endian. 134 | * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with 135 | * a certain separator (' ' by default): 136 | * C colon 137 | -- 138 | 2.49.0 139 | 140 | -------------------------------------------------------------------------------- /1017-checkpatch-remove-p4cn.patch: -------------------------------------------------------------------------------- 1 | From 1b4d677851177100a28d372838fd56a3f3c5a3e2 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Wed, 30 Apr 2025 19:19:08 +0530 4 | Subject: [PATCH 5/5] checkpatch: remove %p4cn 5 | 6 | %p4cn was recently removed and replaced by %p4chR in vsprintf. So, 7 | remove the check for %p4cn from checkpatch.pl. 8 | 9 | Fixes: 37eed892cc5f ("vsprintf: Use %p4chR instead of %p4cn for reading data in reversed host ordering") 10 | Signed-off-by: Aditya Garg 11 | --- 12 | scripts/checkpatch.pl | 2 +- 13 | 1 file changed, 1 insertion(+), 1 deletion(-) 14 | 15 | diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl 16 | index 44e233b6f..d5bde8322 100755 17 | --- a/scripts/checkpatch.pl 18 | +++ b/scripts/checkpatch.pl 19 | @@ -6891,7 +6891,7 @@ sub process { 20 | ($extension eq "f" && 21 | defined $qualifier && $qualifier !~ /^w/) || 22 | ($extension eq "4" && 23 | - defined $qualifier && $qualifier !~ /^c[hnlbc]/)) { 24 | + defined $qualifier && $qualifier !~ /^c(?:[hlbc]|hR)$/)) { 25 | $bad_specifier = $specifier; 26 | last; 27 | } 28 | -- 29 | 2.49.0 30 | 31 | -------------------------------------------------------------------------------- /2008-i915-4-lane-quirk-for-mbp15-1.patch: -------------------------------------------------------------------------------- 1 | From 8a84123c2f8619a14f9fc493db2528e59fcc0db8 Mon Sep 17 00:00:00 2001 2 | From: Orlando Chamberlain 3 | Date: Fri, 28 Jun 2024 04:43:50 +0000 4 | Subject: [PATCH 8/9] i915: 4 lane quirk for mbp15,1 5 | 6 | Needed to use iGPU when dGPU was boot GPU 7 | 8 | Patch written by Kerem Karabay 9 | --- 10 | drivers/gpu/drm/i915/display/intel_ddi.c | 4 ++++ 11 | drivers/gpu/drm/i915/display/intel_quirks.c | 15 +++++++++++++++ 12 | drivers/gpu/drm/i915/display/intel_quirks.h | 1 + 13 | 3 files changed, 20 insertions(+) 14 | 15 | diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c 16 | index 49b5cc01c..1435f49f2 100644 17 | --- a/drivers/gpu/drm/i915/display/intel_ddi.c 18 | +++ b/drivers/gpu/drm/i915/display/intel_ddi.c 19 | @@ -4685,6 +4685,7 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port) 20 | 21 | static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port) 22 | { 23 | + struct intel_display *display = to_intel_display(dig_port); 24 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); 25 | 26 | if (dig_port->base.port != PORT_A) 27 | @@ -4693,6 +4694,9 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port) 28 | if (dig_port->ddi_a_4_lanes) 29 | return false; 30 | 31 | + if (intel_has_quirk(display, QUIRK_DDI_A_FORCE_4_LANES)) 32 | + return true; 33 | + 34 | /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only 35 | * supported configuration 36 | */ 37 | diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c 38 | index 28f497ae7..c2952b0f8 100644 39 | --- a/drivers/gpu/drm/i915/display/intel_quirks.c 40 | +++ b/drivers/gpu/drm/i915/display/intel_quirks.c 41 | @@ -64,6 +64,18 @@ static void quirk_increase_ddi_disabled_time(struct intel_display *display) 42 | drm_info(display->drm, "Applying Increase DDI Disabled quirk\n"); 43 | } 44 | 45 | +/* 46 | + * In some cases, the firmware might not set the lane count to 4 (for example, 47 | + * when booting in some dual GPU Macs with the dGPU as the default GPU), this 48 | + * quirk is used to force it as otherwise it might not be possible to compute a 49 | + * valid link configuration. 50 | + */ 51 | +static void quirk_ddi_a_force_4_lanes(struct intel_display *display) 52 | +{ 53 | + intel_set_quirk(display, QUIRK_DDI_A_FORCE_4_LANES); 54 | + drm_info(display->drm, "Applying DDI A Forced 4 Lanes quirk\n"); 55 | +} 56 | + 57 | static void quirk_no_pps_backlight_power_hook(struct intel_display *display) 58 | { 59 | intel_set_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK); 60 | @@ -229,6 +241,9 @@ static struct intel_quirk intel_quirks[] = { 61 | { 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time }, 62 | /* HP Notebook - 14-r206nv */ 63 | { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness }, 64 | + 65 | + /* Apple MacBookPro15,1 */ 66 | + { 0x3e9b, 0x106b, 0x0176, quirk_ddi_a_force_4_lanes }, 67 | }; 68 | 69 | static const struct intel_dpcd_quirk intel_dpcd_quirks[] = { 70 | diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h 71 | index cafdebda7..a5296f827 100644 72 | --- a/drivers/gpu/drm/i915/display/intel_quirks.h 73 | +++ b/drivers/gpu/drm/i915/display/intel_quirks.h 74 | @@ -20,6 +20,7 @@ enum intel_quirk_id { 75 | QUIRK_LVDS_SSC_DISABLE, 76 | QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK, 77 | QUIRK_FW_SYNC_LEN, 78 | + QUIRK_DDI_A_FORCE_4_LANES, 79 | }; 80 | 81 | void intel_init_quirks(struct intel_display *display); 82 | -- 83 | 2.48.1 84 | 85 | -------------------------------------------------------------------------------- /2009-apple-gmux-allow-switching-to-igpu-at-probe.patch: -------------------------------------------------------------------------------- 1 | From bd8e785c74e22978648ced004552eb9c137f1eb6 Mon Sep 17 00:00:00 2001 2 | From: Orlando Chamberlain 3 | Date: Fri, 10 Feb 2023 22:45:00 +1100 4 | Subject: [PATCH 9/9] apple-gmux: allow switching to igpu at probe 5 | 6 | This means user don't need to set the gpu-power-prefs efivar to use the 7 | igpu while runtime switching isn't working, so macOS will be unaffected. 8 | 9 | This isn't really upstreamable, what we want upstream is the ability to 10 | switch at runtime (so both gpus need to be able to probe the eDP panel). 11 | 12 | Based off of work by Kerem Karabay 13 | --- 14 | drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +++ 15 | drivers/gpu/vga/vga_switcheroo.c | 7 +------ 16 | drivers/pci/vgaarb.c | 1 + 17 | drivers/platform/x86/apple-gmux.c | 18 ++++++++++++++++++ 18 | 4 files changed, 23 insertions(+), 6 deletions(-) 19 | 20 | diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 21 | index 81edf66dbea8..8f3daf28665b 100644 22 | --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 23 | +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 24 | @@ -2051,6 +2051,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, 25 | int ret, retry = 0, i; 26 | bool supports_atomic = false; 27 | 28 | + if (vga_switcheroo_client_probe_defer(pdev)) 29 | + return -EPROBE_DEFER; 30 | + 31 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA || 32 | (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) { 33 | if (drm_firmware_drivers_only() && amdgpu_modeset == -1) 34 | diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c 35 | index 365e6ddbe90f..cf357cd3389d 100644 36 | --- a/drivers/gpu/vga/vga_switcheroo.c 37 | +++ b/drivers/gpu/vga/vga_switcheroo.c 38 | @@ -438,12 +438,7 @@ find_active_client(struct list_head *head) 39 | bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) 40 | { 41 | if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 42 | - /* 43 | - * apple-gmux is needed on pre-retina MacBook Pro 44 | - * to probe the panel if pdev is the inactive GPU. 45 | - */ 46 | - if (apple_gmux_present() && pdev != vga_default_device() && 47 | - !vgasr_priv.handler_flags) 48 | + if (apple_gmux_present() && !vgasr_priv.handler_flags) 49 | return true; 50 | } 51 | 52 | diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c 53 | index 5e6b1eb54c64..1f11701d37d1 100644 54 | --- a/drivers/pci/vgaarb.c 55 | +++ b/drivers/pci/vgaarb.c 56 | @@ -143,6 +143,7 @@ void vga_set_default_device(struct pci_dev *pdev) 57 | pci_dev_put(vga_default); 58 | vga_default = pci_dev_get(pdev); 59 | } 60 | +EXPORT_SYMBOL_GPL(vga_set_default_device); 61 | 62 | /** 63 | * vga_remove_vgacon - deactivate VGA console 64 | diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c 65 | index 1417e230edbd..e69785af8e1d 100644 66 | --- a/drivers/platform/x86/apple-gmux.c 67 | +++ b/drivers/platform/x86/apple-gmux.c 68 | @@ -21,6 +21,7 @@ 69 | #include 70 | #include 71 | #include 72 | +#include 73 | #include 74 | #include 75 | #include 76 | @@ -107,6 +108,10 @@ struct apple_gmux_config { 77 | 78 | # define MMIO_GMUX_MAX_BRIGHTNESS 0xffff 79 | 80 | +static bool force_igd; 81 | +module_param(force_igd, bool, 0); 82 | +MODULE_PARM_DESC(force_idg, "Switch gpu to igd on module load. Make sure that you have apple-set-os set up and the iGPU is in `lspci -s 00:02.0`. (default: false) (bool)"); 83 | + 84 | static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) 85 | { 86 | return inb(gmux_data->iostart + port); 87 | @@ -945,6 +950,19 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) 88 | gmux_enable_interrupts(gmux_data); 89 | gmux_read_switch_state(gmux_data); 90 | 91 | + if (force_igd) { 92 | + struct pci_dev *pdev; 93 | + 94 | + pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(2, 0)); 95 | + if (pdev) { 96 | + pr_info("Switching to IGD"); 97 | + gmux_switchto(VGA_SWITCHEROO_IGD); 98 | + vga_set_default_device(pdev); 99 | + } else { 100 | + pr_err("force_idg is true, but couldn't find iGPU at 00:02.0! Is apple-set-os working?"); 101 | + } 102 | + } 103 | + 104 | /* 105 | * Retina MacBook Pros cannot switch the panel's AUX separately 106 | * and need eDP pre-calibration. They are distinguishable from 107 | -- 108 | 2.43.0 109 | 110 | -------------------------------------------------------------------------------- /3001-applesmc-convert-static-structures-to-drvdata.patch: -------------------------------------------------------------------------------- 1 | From aa8cbca2aa7fa99119fe0e7de616d5b0dcde3a15 Mon Sep 17 00:00:00 2001 2 | From: Paul Pawlowski 3 | Date: Sun, 17 Nov 2019 23:12:55 +0100 4 | Subject: [PATCH 1/9] applesmc: convert static structures to drvdata 5 | 6 | All static data structures have been moved to an applesmc_device struct, 7 | which is then associated with the platform device. 8 | This change is intended to ease the migration to an acpi_device, where 9 | static data would preferably be avoided. 10 | 11 | Signed-off-by: Aun-Ali Zaidi 12 | --- 13 | drivers/hwmon/applesmc.c | 540 +++++++++++++++++++++++---------------- 14 | 1 file changed, 319 insertions(+), 221 deletions(-) 15 | 16 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 17 | index fc6d6a905..7fb40738d 100644 18 | --- a/drivers/hwmon/applesmc.c 19 | +++ b/drivers/hwmon/applesmc.c 20 | @@ -6,6 +6,7 @@ 21 | * 22 | * Copyright (C) 2007 Nicolas Boichat 23 | * Copyright (C) 2010 Henrik Rydberg 24 | + * Copyright (C) 2019 Paul Pawlowski 25 | * 26 | * Based on hdaps.c driver: 27 | * Copyright (C) 2005 Robert Love 28 | @@ -119,7 +120,7 @@ struct applesmc_entry { 29 | }; 30 | 31 | /* Register lookup and registers common to all SMCs */ 32 | -static struct applesmc_registers { 33 | +struct applesmc_registers { 34 | struct mutex mutex; /* register read/write mutex */ 35 | unsigned int key_count; /* number of SMC registers */ 36 | unsigned int fan_count; /* number of fans */ 37 | @@ -133,26 +134,32 @@ static struct applesmc_registers { 38 | bool init_complete; /* true when fully initialized */ 39 | struct applesmc_entry *cache; /* cached key entries */ 40 | const char **index; /* temperature key index */ 41 | -} smcreg = { 42 | - .mutex = __MUTEX_INITIALIZER(smcreg.mutex), 43 | }; 44 | 45 | -static const int debug; 46 | -static struct platform_device *pdev; 47 | -static s16 rest_x; 48 | -static s16 rest_y; 49 | -static u8 backlight_state[2]; 50 | +struct applesmc_device { 51 | + struct platform_device *dev; 52 | + struct applesmc_registers reg; 53 | 54 | -static struct device *hwmon_dev; 55 | -static struct input_dev *applesmc_idev; 56 | + s16 rest_x; 57 | + s16 rest_y; 58 | 59 | -/* 60 | - * Last index written to key_at_index sysfs file, and value to use for all other 61 | - * key_at_index_* sysfs files. 62 | - */ 63 | -static unsigned int key_at_index; 64 | + u8 backlight_state[2]; 65 | + 66 | + struct device *hwmon_dev; 67 | + struct input_dev *idev; 68 | + 69 | + /* 70 | + * Last index written to key_at_index sysfs file, and value to use for all other 71 | + * key_at_index_* sysfs files. 72 | + */ 73 | + unsigned int key_at_index; 74 | + 75 | + struct workqueue_struct *backlight_wq; 76 | + struct work_struct backlight_work; 77 | + struct led_classdev backlight_dev; 78 | +}; 79 | 80 | -static struct workqueue_struct *applesmc_led_wq; 81 | +static const int debug; 82 | 83 | /* 84 | * Wait for specific status bits with a mask on the SMC. 85 | @@ -338,36 +345,37 @@ static int read_register_count(unsigned int *count) 86 | * All functions below are concurrency safe - callers should NOT hold lock. 87 | */ 88 | 89 | -static int applesmc_read_entry(const struct applesmc_entry *entry, 90 | - u8 *buf, u8 len) 91 | +static int applesmc_read_entry(struct applesmc_device *smc, 92 | + const struct applesmc_entry *entry, u8 *buf, u8 len) 93 | { 94 | int ret; 95 | 96 | if (entry->len != len) 97 | return -EINVAL; 98 | - mutex_lock(&smcreg.mutex); 99 | + mutex_lock(&smc->reg.mutex); 100 | ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); 101 | - mutex_unlock(&smcreg.mutex); 102 | + mutex_unlock(&smc->reg.mutex); 103 | 104 | return ret; 105 | } 106 | 107 | -static int applesmc_write_entry(const struct applesmc_entry *entry, 108 | - const u8 *buf, u8 len) 109 | +static int applesmc_write_entry(struct applesmc_device *smc, 110 | + const struct applesmc_entry *entry, const u8 *buf, u8 len) 111 | { 112 | int ret; 113 | 114 | if (entry->len != len) 115 | return -EINVAL; 116 | - mutex_lock(&smcreg.mutex); 117 | + mutex_lock(&smc->reg.mutex); 118 | ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); 119 | - mutex_unlock(&smcreg.mutex); 120 | + mutex_unlock(&smc->reg.mutex); 121 | return ret; 122 | } 123 | 124 | -static const struct applesmc_entry *applesmc_get_entry_by_index(int index) 125 | +static const struct applesmc_entry *applesmc_get_entry_by_index( 126 | + struct applesmc_device *smc, int index) 127 | { 128 | - struct applesmc_entry *cache = &smcreg.cache[index]; 129 | + struct applesmc_entry *cache = &smc->reg.cache[index]; 130 | u8 key[4], info[6]; 131 | __be32 be; 132 | int ret = 0; 133 | @@ -375,7 +383,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) 134 | if (cache->valid) 135 | return cache; 136 | 137 | - mutex_lock(&smcreg.mutex); 138 | + mutex_lock(&smc->reg.mutex); 139 | 140 | if (cache->valid) 141 | goto out; 142 | @@ -394,20 +402,21 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) 143 | cache->valid = true; 144 | 145 | out: 146 | - mutex_unlock(&smcreg.mutex); 147 | + mutex_unlock(&smc->reg.mutex); 148 | if (ret) 149 | return ERR_PTR(ret); 150 | return cache; 151 | } 152 | 153 | -static int applesmc_get_lower_bound(unsigned int *lo, const char *key) 154 | +static int applesmc_get_lower_bound(struct applesmc_device *smc, 155 | + unsigned int *lo, const char *key) 156 | { 157 | - int begin = 0, end = smcreg.key_count; 158 | + int begin = 0, end = smc->reg.key_count; 159 | const struct applesmc_entry *entry; 160 | 161 | while (begin != end) { 162 | int middle = begin + (end - begin) / 2; 163 | - entry = applesmc_get_entry_by_index(middle); 164 | + entry = applesmc_get_entry_by_index(smc, middle); 165 | if (IS_ERR(entry)) { 166 | *lo = 0; 167 | return PTR_ERR(entry); 168 | @@ -422,16 +431,17 @@ static int applesmc_get_lower_bound(unsigned int *lo, const char *key) 169 | return 0; 170 | } 171 | 172 | -static int applesmc_get_upper_bound(unsigned int *hi, const char *key) 173 | +static int applesmc_get_upper_bound(struct applesmc_device *smc, 174 | + unsigned int *hi, const char *key) 175 | { 176 | - int begin = 0, end = smcreg.key_count; 177 | + int begin = 0, end = smc->reg.key_count; 178 | const struct applesmc_entry *entry; 179 | 180 | while (begin != end) { 181 | int middle = begin + (end - begin) / 2; 182 | - entry = applesmc_get_entry_by_index(middle); 183 | + entry = applesmc_get_entry_by_index(smc, middle); 184 | if (IS_ERR(entry)) { 185 | - *hi = smcreg.key_count; 186 | + *hi = smc->reg.key_count; 187 | return PTR_ERR(entry); 188 | } 189 | if (strcmp(key, entry->key) < 0) 190 | @@ -444,50 +454,54 @@ static int applesmc_get_upper_bound(unsigned int *hi, const char *key) 191 | return 0; 192 | } 193 | 194 | -static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) 195 | +static const struct applesmc_entry *applesmc_get_entry_by_key( 196 | + struct applesmc_device *smc, const char *key) 197 | { 198 | int begin, end; 199 | int ret; 200 | 201 | - ret = applesmc_get_lower_bound(&begin, key); 202 | + ret = applesmc_get_lower_bound(smc, &begin, key); 203 | if (ret) 204 | return ERR_PTR(ret); 205 | - ret = applesmc_get_upper_bound(&end, key); 206 | + ret = applesmc_get_upper_bound(smc, &end, key); 207 | if (ret) 208 | return ERR_PTR(ret); 209 | if (end - begin != 1) 210 | return ERR_PTR(-EINVAL); 211 | 212 | - return applesmc_get_entry_by_index(begin); 213 | + return applesmc_get_entry_by_index(smc, begin); 214 | } 215 | 216 | -static int applesmc_read_key(const char *key, u8 *buffer, u8 len) 217 | +static int applesmc_read_key(struct applesmc_device *smc, 218 | + const char *key, u8 *buffer, u8 len) 219 | { 220 | const struct applesmc_entry *entry; 221 | 222 | - entry = applesmc_get_entry_by_key(key); 223 | + entry = applesmc_get_entry_by_key(smc, key); 224 | if (IS_ERR(entry)) 225 | return PTR_ERR(entry); 226 | 227 | - return applesmc_read_entry(entry, buffer, len); 228 | + return applesmc_read_entry(smc, entry, buffer, len); 229 | } 230 | 231 | -static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) 232 | +static int applesmc_write_key(struct applesmc_device *smc, 233 | + const char *key, const u8 *buffer, u8 len) 234 | { 235 | const struct applesmc_entry *entry; 236 | 237 | - entry = applesmc_get_entry_by_key(key); 238 | + entry = applesmc_get_entry_by_key(smc, key); 239 | if (IS_ERR(entry)) 240 | return PTR_ERR(entry); 241 | 242 | - return applesmc_write_entry(entry, buffer, len); 243 | + return applesmc_write_entry(smc, entry, buffer, len); 244 | } 245 | 246 | -static int applesmc_has_key(const char *key, bool *value) 247 | +static int applesmc_has_key(struct applesmc_device *smc, 248 | + const char *key, bool *value) 249 | { 250 | const struct applesmc_entry *entry; 251 | 252 | - entry = applesmc_get_entry_by_key(key); 253 | + entry = applesmc_get_entry_by_key(smc, key); 254 | if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL) 255 | return PTR_ERR(entry); 256 | 257 | @@ -498,12 +512,13 @@ static int applesmc_has_key(const char *key, bool *value) 258 | /* 259 | * applesmc_read_s16 - Read 16-bit signed big endian register 260 | */ 261 | -static int applesmc_read_s16(const char *key, s16 *value) 262 | +static int applesmc_read_s16(struct applesmc_device *smc, 263 | + const char *key, s16 *value) 264 | { 265 | u8 buffer[2]; 266 | int ret; 267 | 268 | - ret = applesmc_read_key(key, buffer, 2); 269 | + ret = applesmc_read_key(smc, key, buffer, 2); 270 | if (ret) 271 | return ret; 272 | 273 | @@ -514,28 +529,29 @@ static int applesmc_read_s16(const char *key, s16 *value) 274 | /* 275 | * applesmc_device_init - initialize the accelerometer. Can sleep. 276 | */ 277 | -static void applesmc_device_init(void) 278 | +static void applesmc_device_init(struct applesmc_device *smc) 279 | { 280 | int total; 281 | u8 buffer[2]; 282 | 283 | - if (!smcreg.has_accelerometer) 284 | + if (!smc->reg.has_accelerometer) 285 | return; 286 | 287 | for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { 288 | - if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && 289 | + if (!applesmc_read_key(smc, MOTION_SENSOR_KEY, buffer, 2) && 290 | (buffer[0] != 0x00 || buffer[1] != 0x00)) 291 | return; 292 | buffer[0] = 0xe0; 293 | buffer[1] = 0x00; 294 | - applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); 295 | + applesmc_write_key(smc, MOTION_SENSOR_KEY, buffer, 2); 296 | msleep(INIT_WAIT_MSECS); 297 | } 298 | 299 | pr_warn("failed to init the device\n"); 300 | } 301 | 302 | -static int applesmc_init_index(struct applesmc_registers *s) 303 | +static int applesmc_init_index(struct applesmc_device *smc, 304 | + struct applesmc_registers *s) 305 | { 306 | const struct applesmc_entry *entry; 307 | unsigned int i; 308 | @@ -548,7 +564,7 @@ static int applesmc_init_index(struct applesmc_registers *s) 309 | return -ENOMEM; 310 | 311 | for (i = s->temp_begin; i < s->temp_end; i++) { 312 | - entry = applesmc_get_entry_by_index(i); 313 | + entry = applesmc_get_entry_by_index(smc, i); 314 | if (IS_ERR(entry)) 315 | continue; 316 | if (strcmp(entry->type, TEMP_SENSOR_TYPE)) 317 | @@ -562,9 +578,9 @@ static int applesmc_init_index(struct applesmc_registers *s) 318 | /* 319 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. 320 | */ 321 | -static int applesmc_init_smcreg_try(void) 322 | +static int applesmc_init_smcreg_try(struct applesmc_device *smc) 323 | { 324 | - struct applesmc_registers *s = &smcreg; 325 | + struct applesmc_registers *s = &smc->reg; 326 | bool left_light_sensor = false, right_light_sensor = false; 327 | unsigned int count; 328 | u8 tmp[1]; 329 | @@ -590,35 +606,35 @@ static int applesmc_init_smcreg_try(void) 330 | if (!s->cache) 331 | return -ENOMEM; 332 | 333 | - ret = applesmc_read_key(FANS_COUNT, tmp, 1); 334 | + ret = applesmc_read_key(smc, FANS_COUNT, tmp, 1); 335 | if (ret) 336 | return ret; 337 | s->fan_count = tmp[0]; 338 | if (s->fan_count > 10) 339 | s->fan_count = 10; 340 | 341 | - ret = applesmc_get_lower_bound(&s->temp_begin, "T"); 342 | + ret = applesmc_get_lower_bound(smc, &s->temp_begin, "T"); 343 | if (ret) 344 | return ret; 345 | - ret = applesmc_get_lower_bound(&s->temp_end, "U"); 346 | + ret = applesmc_get_lower_bound(smc, &s->temp_end, "U"); 347 | if (ret) 348 | return ret; 349 | s->temp_count = s->temp_end - s->temp_begin; 350 | 351 | - ret = applesmc_init_index(s); 352 | + ret = applesmc_init_index(smc, s); 353 | if (ret) 354 | return ret; 355 | 356 | - ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); 357 | + ret = applesmc_has_key(smc, LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); 358 | if (ret) 359 | return ret; 360 | - ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); 361 | + ret = applesmc_has_key(smc, LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); 362 | if (ret) 363 | return ret; 364 | - ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer); 365 | + ret = applesmc_has_key(smc, MOTION_SENSOR_KEY, &s->has_accelerometer); 366 | if (ret) 367 | return ret; 368 | - ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight); 369 | + ret = applesmc_has_key(smc, BACKLIGHT_KEY, &s->has_key_backlight); 370 | if (ret) 371 | return ret; 372 | 373 | @@ -634,13 +650,13 @@ static int applesmc_init_smcreg_try(void) 374 | return 0; 375 | } 376 | 377 | -static void applesmc_destroy_smcreg(void) 378 | +static void applesmc_destroy_smcreg(struct applesmc_device *smc) 379 | { 380 | - kfree(smcreg.index); 381 | - smcreg.index = NULL; 382 | - kfree(smcreg.cache); 383 | - smcreg.cache = NULL; 384 | - smcreg.init_complete = false; 385 | + kfree(smc->reg.index); 386 | + smc->reg.index = NULL; 387 | + kfree(smc->reg.cache); 388 | + smc->reg.cache = NULL; 389 | + smc->reg.init_complete = false; 390 | } 391 | 392 | /* 393 | @@ -649,12 +665,12 @@ static void applesmc_destroy_smcreg(void) 394 | * Retries until initialization is successful, or the operation times out. 395 | * 396 | */ 397 | -static int applesmc_init_smcreg(void) 398 | +static int applesmc_init_smcreg(struct applesmc_device *smc) 399 | { 400 | int ms, ret; 401 | 402 | for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) { 403 | - ret = applesmc_init_smcreg_try(); 404 | + ret = applesmc_init_smcreg_try(smc); 405 | if (!ret) { 406 | if (ms) 407 | pr_info("init_smcreg() took %d ms\n", ms); 408 | @@ -663,21 +679,58 @@ static int applesmc_init_smcreg(void) 409 | msleep(INIT_WAIT_MSECS); 410 | } 411 | 412 | - applesmc_destroy_smcreg(); 413 | + applesmc_destroy_smcreg(smc); 414 | 415 | return ret; 416 | } 417 | 418 | /* Device model stuff */ 419 | +static int applesmc_create_modules(struct applesmc_device *smc); 420 | +static void applesmc_destroy_modules(struct applesmc_device *smc); 421 | static int applesmc_probe(struct platform_device *dev) 422 | { 423 | + struct applesmc_device *smc; 424 | int ret; 425 | 426 | - ret = applesmc_init_smcreg(); 427 | + smc = kzalloc(sizeof(struct applesmc_device), GFP_KERNEL); 428 | + if (!smc) 429 | + return -ENOMEM; 430 | + smc->dev = dev; 431 | + mutex_init(&smc->reg.mutex); 432 | + 433 | + platform_set_drvdata(dev, smc); 434 | + 435 | + ret = applesmc_init_smcreg(smc); 436 | if (ret) 437 | - return ret; 438 | + goto out_mem; 439 | + 440 | + applesmc_device_init(smc); 441 | + 442 | + ret = applesmc_create_modules(smc); 443 | + if (ret) 444 | + goto out_reg; 445 | + 446 | + return 0; 447 | + 448 | +out_reg: 449 | + applesmc_destroy_smcreg(smc); 450 | +out_mem: 451 | + platform_set_drvdata(dev, NULL); 452 | + mutex_destroy(&smc->reg.mutex); 453 | + kfree(smc); 454 | 455 | - applesmc_device_init(); 456 | + return ret; 457 | +} 458 | + 459 | +static int applesmc_remove(struct platform_device *dev) 460 | +{ 461 | + struct applesmc_device *smc = platform_get_drvdata(dev); 462 | + 463 | + applesmc_destroy_modules(smc); 464 | + applesmc_destroy_smcreg(smc); 465 | + 466 | + mutex_destroy(&smc->reg.mutex); 467 | + kfree(smc); 468 | 469 | return 0; 470 | } 471 | @@ -685,15 +738,21 @@ static int applesmc_probe(struct platform_device *dev) 472 | /* Synchronize device with memorized backlight state */ 473 | static int applesmc_pm_resume(struct device *dev) 474 | { 475 | - if (smcreg.has_key_backlight) 476 | - applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); 477 | + struct applesmc_device *smc = dev_get_drvdata(dev); 478 | + 479 | + if (smc->reg.has_key_backlight) 480 | + applesmc_write_key(smc, BACKLIGHT_KEY, smc->backlight_state, 2); 481 | + 482 | return 0; 483 | } 484 | 485 | /* Reinitialize device on resume from hibernation */ 486 | static int applesmc_pm_restore(struct device *dev) 487 | { 488 | - applesmc_device_init(); 489 | + struct applesmc_device *smc = dev_get_drvdata(dev); 490 | + 491 | + applesmc_device_init(smc); 492 | + 493 | return applesmc_pm_resume(dev); 494 | } 495 | 496 | @@ -704,6 +763,7 @@ static const struct dev_pm_ops applesmc_pm_ops = { 497 | 498 | static struct platform_driver applesmc_driver = { 499 | .probe = applesmc_probe, 500 | + .remove = applesmc_remove, 501 | .driver = { 502 | .name = "applesmc", 503 | .pm = &applesmc_pm_ops, 504 | @@ -714,25 +774,26 @@ static struct platform_driver applesmc_driver = { 505 | * applesmc_calibrate - Set our "resting" values. Callers must 506 | * hold applesmc_lock. 507 | */ 508 | -static void applesmc_calibrate(void) 509 | +static void applesmc_calibrate(struct applesmc_device *smc) 510 | { 511 | - applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x); 512 | - applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y); 513 | - rest_x = -rest_x; 514 | + applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &smc->rest_x); 515 | + applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &smc->rest_y); 516 | + smc->rest_x = -smc->rest_x; 517 | } 518 | 519 | static void applesmc_idev_poll(struct input_dev *idev) 520 | { 521 | + struct applesmc_device *smc = dev_get_drvdata(&idev->dev); 522 | s16 x, y; 523 | 524 | - if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x)) 525 | + if (applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &x)) 526 | return; 527 | - if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y)) 528 | + if (applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &y)) 529 | return; 530 | 531 | x = -x; 532 | - input_report_abs(idev, ABS_X, x - rest_x); 533 | - input_report_abs(idev, ABS_Y, y - rest_y); 534 | + input_report_abs(idev, ABS_X, x - smc->rest_x); 535 | + input_report_abs(idev, ABS_Y, y - smc->rest_y); 536 | input_sync(idev); 537 | } 538 | 539 | @@ -747,16 +808,17 @@ static ssize_t applesmc_name_show(struct device *dev, 540 | static ssize_t applesmc_position_show(struct device *dev, 541 | struct device_attribute *attr, char *buf) 542 | { 543 | + struct applesmc_device *smc = dev_get_drvdata(dev); 544 | int ret; 545 | s16 x, y, z; 546 | 547 | - ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x); 548 | + ret = applesmc_read_s16(smc, MOTION_SENSOR_X_KEY, &x); 549 | if (ret) 550 | goto out; 551 | - ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y); 552 | + ret = applesmc_read_s16(smc, MOTION_SENSOR_Y_KEY, &y); 553 | if (ret) 554 | goto out; 555 | - ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z); 556 | + ret = applesmc_read_s16(smc, MOTION_SENSOR_Z_KEY, &z); 557 | if (ret) 558 | goto out; 559 | 560 | @@ -770,6 +832,7 @@ static ssize_t applesmc_position_show(struct device *dev, 561 | static ssize_t applesmc_light_show(struct device *dev, 562 | struct device_attribute *attr, char *sysfsbuf) 563 | { 564 | + struct applesmc_device *smc = dev_get_drvdata(dev); 565 | const struct applesmc_entry *entry; 566 | static int data_length; 567 | int ret; 568 | @@ -777,7 +840,7 @@ static ssize_t applesmc_light_show(struct device *dev, 569 | u8 buffer[10]; 570 | 571 | if (!data_length) { 572 | - entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); 573 | + entry = applesmc_get_entry_by_key(smc, LIGHT_SENSOR_LEFT_KEY); 574 | if (IS_ERR(entry)) 575 | return PTR_ERR(entry); 576 | if (entry->len > 10) 577 | @@ -786,7 +849,7 @@ static ssize_t applesmc_light_show(struct device *dev, 578 | pr_info("light sensor data length set to %d\n", data_length); 579 | } 580 | 581 | - ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); 582 | + ret = applesmc_read_key(smc, LIGHT_SENSOR_LEFT_KEY, buffer, data_length); 583 | if (ret) 584 | goto out; 585 | /* newer macbooks report a single 10-bit bigendian value */ 586 | @@ -796,7 +859,7 @@ static ssize_t applesmc_light_show(struct device *dev, 587 | } 588 | left = buffer[2]; 589 | 590 | - ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); 591 | + ret = applesmc_read_key(smc, LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); 592 | if (ret) 593 | goto out; 594 | right = buffer[2]; 595 | @@ -812,7 +875,8 @@ static ssize_t applesmc_light_show(struct device *dev, 596 | static ssize_t applesmc_show_sensor_label(struct device *dev, 597 | struct device_attribute *devattr, char *sysfsbuf) 598 | { 599 | - const char *key = smcreg.index[to_index(devattr)]; 600 | + struct applesmc_device *smc = dev_get_drvdata(dev); 601 | + const char *key = smc->reg.index[to_index(devattr)]; 602 | 603 | return sysfs_emit(sysfsbuf, "%s\n", key); 604 | } 605 | @@ -821,12 +885,13 @@ static ssize_t applesmc_show_sensor_label(struct device *dev, 606 | static ssize_t applesmc_show_temperature(struct device *dev, 607 | struct device_attribute *devattr, char *sysfsbuf) 608 | { 609 | - const char *key = smcreg.index[to_index(devattr)]; 610 | + struct applesmc_device *smc = dev_get_drvdata(dev); 611 | + const char *key = smc->reg.index[to_index(devattr)]; 612 | int ret; 613 | s16 value; 614 | int temp; 615 | 616 | - ret = applesmc_read_s16(key, &value); 617 | + ret = applesmc_read_s16(smc, key, &value); 618 | if (ret) 619 | return ret; 620 | 621 | @@ -838,6 +903,7 @@ static ssize_t applesmc_show_temperature(struct device *dev, 622 | static ssize_t applesmc_show_fan_speed(struct device *dev, 623 | struct device_attribute *attr, char *sysfsbuf) 624 | { 625 | + struct applesmc_device *smc = dev_get_drvdata(dev); 626 | int ret; 627 | unsigned int speed = 0; 628 | char newkey[5]; 629 | @@ -846,7 +912,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, 630 | scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], 631 | to_index(attr)); 632 | 633 | - ret = applesmc_read_key(newkey, buffer, 2); 634 | + ret = applesmc_read_key(smc, newkey, buffer, 2); 635 | if (ret) 636 | return ret; 637 | 638 | @@ -858,6 +924,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, 639 | struct device_attribute *attr, 640 | const char *sysfsbuf, size_t count) 641 | { 642 | + struct applesmc_device *smc = dev_get_drvdata(dev); 643 | int ret; 644 | unsigned long speed; 645 | char newkey[5]; 646 | @@ -871,7 +938,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, 647 | 648 | buffer[0] = (speed >> 6) & 0xff; 649 | buffer[1] = (speed << 2) & 0xff; 650 | - ret = applesmc_write_key(newkey, buffer, 2); 651 | + ret = applesmc_write_key(smc, newkey, buffer, 2); 652 | 653 | if (ret) 654 | return ret; 655 | @@ -882,11 +949,12 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, 656 | static ssize_t applesmc_show_fan_manual(struct device *dev, 657 | struct device_attribute *attr, char *sysfsbuf) 658 | { 659 | + struct applesmc_device *smc = dev_get_drvdata(dev); 660 | int ret; 661 | u16 manual = 0; 662 | u8 buffer[2]; 663 | 664 | - ret = applesmc_read_key(FANS_MANUAL, buffer, 2); 665 | + ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 666 | if (ret) 667 | return ret; 668 | 669 | @@ -898,6 +966,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, 670 | struct device_attribute *attr, 671 | const char *sysfsbuf, size_t count) 672 | { 673 | + struct applesmc_device *smc = dev_get_drvdata(dev); 674 | int ret; 675 | u8 buffer[2]; 676 | unsigned long input; 677 | @@ -906,7 +975,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, 678 | if (kstrtoul(sysfsbuf, 10, &input) < 0) 679 | return -EINVAL; 680 | 681 | - ret = applesmc_read_key(FANS_MANUAL, buffer, 2); 682 | + ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 683 | if (ret) 684 | goto out; 685 | 686 | @@ -920,7 +989,7 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, 687 | buffer[0] = (val >> 8) & 0xFF; 688 | buffer[1] = val & 0xFF; 689 | 690 | - ret = applesmc_write_key(FANS_MANUAL, buffer, 2); 691 | + ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); 692 | 693 | out: 694 | if (ret) 695 | @@ -932,13 +1001,14 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, 696 | static ssize_t applesmc_show_fan_position(struct device *dev, 697 | struct device_attribute *attr, char *sysfsbuf) 698 | { 699 | + struct applesmc_device *smc = dev_get_drvdata(dev); 700 | int ret; 701 | char newkey[5]; 702 | u8 buffer[17]; 703 | 704 | scnprintf(newkey, sizeof(newkey), FAN_ID_FMT, to_index(attr)); 705 | 706 | - ret = applesmc_read_key(newkey, buffer, 16); 707 | + ret = applesmc_read_key(smc, newkey, buffer, 16); 708 | buffer[16] = 0; 709 | 710 | if (ret) 711 | @@ -950,30 +1020,36 @@ static ssize_t applesmc_show_fan_position(struct device *dev, 712 | static ssize_t applesmc_calibrate_show(struct device *dev, 713 | struct device_attribute *attr, char *sysfsbuf) 714 | { 715 | - return sysfs_emit(sysfsbuf, "(%d,%d)\n", rest_x, rest_y); 716 | + struct applesmc_device *smc = dev_get_drvdata(dev); 717 | + 718 | + return sysfs_emit(sysfsbuf, "(%d,%d)\n", smc->rest_x, smc->rest_y); 719 | } 720 | 721 | static ssize_t applesmc_calibrate_store(struct device *dev, 722 | struct device_attribute *attr, const char *sysfsbuf, size_t count) 723 | { 724 | - applesmc_calibrate(); 725 | + struct applesmc_device *smc = dev_get_drvdata(dev); 726 | + 727 | + applesmc_calibrate(smc); 728 | 729 | return count; 730 | } 731 | 732 | static void applesmc_backlight_set(struct work_struct *work) 733 | { 734 | - applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); 735 | + struct applesmc_device *smc = container_of(work, struct applesmc_device, backlight_work); 736 | + 737 | + applesmc_write_key(smc, BACKLIGHT_KEY, smc->backlight_state, 2); 738 | } 739 | -static DECLARE_WORK(backlight_work, &applesmc_backlight_set); 740 | 741 | static void applesmc_brightness_set(struct led_classdev *led_cdev, 742 | enum led_brightness value) 743 | { 744 | + struct applesmc_device *smc = dev_get_drvdata(led_cdev->dev); 745 | int ret; 746 | 747 | - backlight_state[0] = value; 748 | - ret = queue_work(applesmc_led_wq, &backlight_work); 749 | + smc->backlight_state[0] = value; 750 | + ret = queue_work(smc->backlight_wq, &smc->backlight_work); 751 | 752 | if (debug && (!ret)) 753 | dev_dbg(led_cdev->dev, "work was already on the queue.\n"); 754 | @@ -982,11 +1058,12 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev, 755 | static ssize_t applesmc_key_count_show(struct device *dev, 756 | struct device_attribute *attr, char *sysfsbuf) 757 | { 758 | + struct applesmc_device *smc = dev_get_drvdata(dev); 759 | int ret; 760 | u8 buffer[4]; 761 | u32 count; 762 | 763 | - ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); 764 | + ret = applesmc_read_key(smc, KEY_COUNT_KEY, buffer, 4); 765 | if (ret) 766 | return ret; 767 | 768 | @@ -998,13 +1075,14 @@ static ssize_t applesmc_key_count_show(struct device *dev, 769 | static ssize_t applesmc_key_at_index_read_show(struct device *dev, 770 | struct device_attribute *attr, char *sysfsbuf) 771 | { 772 | + struct applesmc_device *smc = dev_get_drvdata(dev); 773 | const struct applesmc_entry *entry; 774 | int ret; 775 | 776 | - entry = applesmc_get_entry_by_index(key_at_index); 777 | + entry = applesmc_get_entry_by_index(smc, smc->key_at_index); 778 | if (IS_ERR(entry)) 779 | return PTR_ERR(entry); 780 | - ret = applesmc_read_entry(entry, sysfsbuf, entry->len); 781 | + ret = applesmc_read_entry(smc, entry, sysfsbuf, entry->len); 782 | if (ret) 783 | return ret; 784 | 785 | @@ -1014,9 +1092,10 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev, 786 | static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, 787 | struct device_attribute *attr, char *sysfsbuf) 788 | { 789 | + struct applesmc_device *smc = dev_get_drvdata(dev); 790 | const struct applesmc_entry *entry; 791 | 792 | - entry = applesmc_get_entry_by_index(key_at_index); 793 | + entry = applesmc_get_entry_by_index(smc, smc->key_at_index); 794 | if (IS_ERR(entry)) 795 | return PTR_ERR(entry); 796 | 797 | @@ -1026,9 +1105,10 @@ static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, 798 | static ssize_t applesmc_key_at_index_type_show(struct device *dev, 799 | struct device_attribute *attr, char *sysfsbuf) 800 | { 801 | + struct applesmc_device *smc = dev_get_drvdata(dev); 802 | const struct applesmc_entry *entry; 803 | 804 | - entry = applesmc_get_entry_by_index(key_at_index); 805 | + entry = applesmc_get_entry_by_index(smc, smc->key_at_index); 806 | if (IS_ERR(entry)) 807 | return PTR_ERR(entry); 808 | 809 | @@ -1038,9 +1118,10 @@ static ssize_t applesmc_key_at_index_type_show(struct device *dev, 810 | static ssize_t applesmc_key_at_index_name_show(struct device *dev, 811 | struct device_attribute *attr, char *sysfsbuf) 812 | { 813 | + struct applesmc_device *smc = dev_get_drvdata(dev); 814 | const struct applesmc_entry *entry; 815 | 816 | - entry = applesmc_get_entry_by_index(key_at_index); 817 | + entry = applesmc_get_entry_by_index(smc, smc->key_at_index); 818 | if (IS_ERR(entry)) 819 | return PTR_ERR(entry); 820 | 821 | @@ -1050,28 +1131,25 @@ static ssize_t applesmc_key_at_index_name_show(struct device *dev, 822 | static ssize_t applesmc_key_at_index_show(struct device *dev, 823 | struct device_attribute *attr, char *sysfsbuf) 824 | { 825 | - return sysfs_emit(sysfsbuf, "%d\n", key_at_index); 826 | + struct applesmc_device *smc = dev_get_drvdata(dev); 827 | + 828 | + return sysfs_emit(sysfsbuf, "%d\n", smc->key_at_index); 829 | } 830 | 831 | static ssize_t applesmc_key_at_index_store(struct device *dev, 832 | struct device_attribute *attr, const char *sysfsbuf, size_t count) 833 | { 834 | + struct applesmc_device *smc = dev_get_drvdata(dev); 835 | unsigned long newkey; 836 | 837 | if (kstrtoul(sysfsbuf, 10, &newkey) < 0 838 | - || newkey >= smcreg.key_count) 839 | + || newkey >= smc->reg.key_count) 840 | return -EINVAL; 841 | 842 | - key_at_index = newkey; 843 | + smc->key_at_index = newkey; 844 | return count; 845 | } 846 | 847 | -static struct led_classdev applesmc_backlight = { 848 | - .name = "smc::kbd_backlight", 849 | - .default_trigger = "nand-disk", 850 | - .brightness_set = applesmc_brightness_set, 851 | -}; 852 | - 853 | static struct applesmc_node_group info_group[] = { 854 | { "name", applesmc_name_show }, 855 | { "key_count", applesmc_key_count_show }, 856 | @@ -1116,14 +1194,15 @@ static struct applesmc_node_group temp_group[] = { 857 | /* 858 | * applesmc_destroy_nodes - remove files and free associated memory 859 | */ 860 | -static void applesmc_destroy_nodes(struct applesmc_node_group *groups) 861 | +static void applesmc_destroy_nodes(struct applesmc_device *smc, 862 | + struct applesmc_node_group *groups) 863 | { 864 | struct applesmc_node_group *grp; 865 | struct applesmc_dev_attr *node; 866 | 867 | for (grp = groups; grp->nodes; grp++) { 868 | for (node = grp->nodes; node->sda.dev_attr.attr.name; node++) 869 | - sysfs_remove_file(&pdev->dev.kobj, 870 | + sysfs_remove_file(&smc->dev->dev.kobj, 871 | &node->sda.dev_attr.attr); 872 | kfree(grp->nodes); 873 | grp->nodes = NULL; 874 | @@ -1133,7 +1212,8 @@ static void applesmc_destroy_nodes(struct applesmc_node_group *groups) 875 | /* 876 | * applesmc_create_nodes - create a two-dimensional group of sysfs files 877 | */ 878 | -static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) 879 | +static int applesmc_create_nodes(struct applesmc_device *smc, 880 | + struct applesmc_node_group *groups, int num) 881 | { 882 | struct applesmc_node_group *grp; 883 | struct applesmc_dev_attr *node; 884 | @@ -1157,7 +1237,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) 885 | sysfs_attr_init(attr); 886 | attr->name = node->name; 887 | attr->mode = 0444 | (grp->store ? 0200 : 0); 888 | - ret = sysfs_create_file(&pdev->dev.kobj, attr); 889 | + ret = sysfs_create_file(&smc->dev->dev.kobj, attr); 890 | if (ret) { 891 | attr->name = NULL; 892 | goto out; 893 | @@ -1167,57 +1247,57 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) 894 | 895 | return 0; 896 | out: 897 | - applesmc_destroy_nodes(groups); 898 | + applesmc_destroy_nodes(smc, groups); 899 | return ret; 900 | } 901 | 902 | /* Create accelerometer resources */ 903 | -static int applesmc_create_accelerometer(void) 904 | +static int applesmc_create_accelerometer(struct applesmc_device *smc) 905 | { 906 | int ret; 907 | 908 | - if (!smcreg.has_accelerometer) 909 | + if (!smc->reg.has_accelerometer) 910 | return 0; 911 | 912 | - ret = applesmc_create_nodes(accelerometer_group, 1); 913 | + ret = applesmc_create_nodes(smc, accelerometer_group, 1); 914 | if (ret) 915 | goto out; 916 | 917 | - applesmc_idev = input_allocate_device(); 918 | - if (!applesmc_idev) { 919 | + smc->idev = input_allocate_device(); 920 | + if (!smc->idev) { 921 | ret = -ENOMEM; 922 | goto out_sysfs; 923 | } 924 | 925 | /* initial calibrate for the input device */ 926 | - applesmc_calibrate(); 927 | + applesmc_calibrate(smc); 928 | 929 | /* initialize the input device */ 930 | - applesmc_idev->name = "applesmc"; 931 | - applesmc_idev->id.bustype = BUS_HOST; 932 | - applesmc_idev->dev.parent = &pdev->dev; 933 | - input_set_abs_params(applesmc_idev, ABS_X, 934 | + smc->idev->name = "applesmc"; 935 | + smc->idev->id.bustype = BUS_HOST; 936 | + smc->idev->dev.parent = &smc->dev->dev; 937 | + input_set_abs_params(smc->idev, ABS_X, 938 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); 939 | - input_set_abs_params(applesmc_idev, ABS_Y, 940 | + input_set_abs_params(smc->idev, ABS_Y, 941 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); 942 | 943 | - ret = input_setup_polling(applesmc_idev, applesmc_idev_poll); 944 | + ret = input_setup_polling(smc->idev, applesmc_idev_poll); 945 | if (ret) 946 | goto out_idev; 947 | 948 | - input_set_poll_interval(applesmc_idev, APPLESMC_POLL_INTERVAL); 949 | + input_set_poll_interval(smc->idev, APPLESMC_POLL_INTERVAL); 950 | 951 | - ret = input_register_device(applesmc_idev); 952 | + ret = input_register_device(smc->idev); 953 | if (ret) 954 | goto out_idev; 955 | 956 | return 0; 957 | 958 | out_idev: 959 | - input_free_device(applesmc_idev); 960 | + input_free_device(smc->idev); 961 | 962 | out_sysfs: 963 | - applesmc_destroy_nodes(accelerometer_group); 964 | + applesmc_destroy_nodes(smc, accelerometer_group); 965 | 966 | out: 967 | pr_warn("driver init failed (ret=%d)!\n", ret); 968 | @@ -1225,44 +1305,55 @@ static int applesmc_create_accelerometer(void) 969 | } 970 | 971 | /* Release all resources used by the accelerometer */ 972 | -static void applesmc_release_accelerometer(void) 973 | +static void applesmc_release_accelerometer(struct applesmc_device *smc) 974 | { 975 | - if (!smcreg.has_accelerometer) 976 | + if (!smc->reg.has_accelerometer) 977 | return; 978 | - input_unregister_device(applesmc_idev); 979 | - applesmc_destroy_nodes(accelerometer_group); 980 | + input_unregister_device(smc->idev); 981 | + applesmc_destroy_nodes(smc, accelerometer_group); 982 | } 983 | 984 | -static int applesmc_create_light_sensor(void) 985 | +static int applesmc_create_light_sensor(struct applesmc_device *smc) 986 | { 987 | - if (!smcreg.num_light_sensors) 988 | + if (!smc->reg.num_light_sensors) 989 | return 0; 990 | - return applesmc_create_nodes(light_sensor_group, 1); 991 | + return applesmc_create_nodes(smc, light_sensor_group, 1); 992 | } 993 | 994 | -static void applesmc_release_light_sensor(void) 995 | +static void applesmc_release_light_sensor(struct applesmc_device *smc) 996 | { 997 | - if (!smcreg.num_light_sensors) 998 | + if (!smc->reg.num_light_sensors) 999 | return; 1000 | - applesmc_destroy_nodes(light_sensor_group); 1001 | + applesmc_destroy_nodes(smc, light_sensor_group); 1002 | } 1003 | 1004 | -static int applesmc_create_key_backlight(void) 1005 | +static int applesmc_create_key_backlight(struct applesmc_device *smc) 1006 | { 1007 | - if (!smcreg.has_key_backlight) 1008 | + int ret; 1009 | + 1010 | + if (!smc->reg.has_key_backlight) 1011 | return 0; 1012 | - applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); 1013 | - if (!applesmc_led_wq) 1014 | + smc->backlight_wq = create_singlethread_workqueue("applesmc-led"); 1015 | + if (!smc->backlight_wq) 1016 | return -ENOMEM; 1017 | - return led_classdev_register(&pdev->dev, &applesmc_backlight); 1018 | + 1019 | + INIT_WORK(&smc->backlight_work, applesmc_backlight_set); 1020 | + smc->backlight_dev.name = "smc::kbd_backlight"; 1021 | + smc->backlight_dev.default_trigger = "nand-disk"; 1022 | + smc->backlight_dev.brightness_set = applesmc_brightness_set; 1023 | + ret = led_classdev_register(&smc->dev->dev, &smc->backlight_dev); 1024 | + if (ret) 1025 | + destroy_workqueue(smc->backlight_wq); 1026 | + 1027 | + return ret; 1028 | } 1029 | 1030 | -static void applesmc_release_key_backlight(void) 1031 | +static void applesmc_release_key_backlight(struct applesmc_device *smc) 1032 | { 1033 | - if (!smcreg.has_key_backlight) 1034 | + if (!smc->reg.has_key_backlight) 1035 | return; 1036 | - led_classdev_unregister(&applesmc_backlight); 1037 | - destroy_workqueue(applesmc_led_wq); 1038 | + led_classdev_unregister(&smc->backlight_dev); 1039 | + destroy_workqueue(smc->backlight_wq); 1040 | } 1041 | 1042 | static int applesmc_dmi_match(const struct dmi_system_id *id) 1043 | @@ -1306,86 +1397,100 @@ static const struct dmi_system_id applesmc_whitelist[] __initconst = { 1044 | { .ident = NULL } 1045 | }; 1046 | 1047 | -static int __init applesmc_init(void) 1048 | +static int applesmc_create_modules(struct applesmc_device *smc) 1049 | { 1050 | int ret; 1051 | 1052 | - if (!dmi_check_system(applesmc_whitelist)) { 1053 | - pr_warn("supported laptop not found!\n"); 1054 | - ret = -ENODEV; 1055 | - goto out; 1056 | - } 1057 | - 1058 | - if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, 1059 | - "applesmc")) { 1060 | - ret = -ENXIO; 1061 | - goto out; 1062 | - } 1063 | - 1064 | - ret = platform_driver_register(&applesmc_driver); 1065 | - if (ret) 1066 | - goto out_region; 1067 | - 1068 | - pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, 1069 | - NULL, 0); 1070 | - if (IS_ERR(pdev)) { 1071 | - ret = PTR_ERR(pdev); 1072 | - goto out_driver; 1073 | - } 1074 | - 1075 | - /* create register cache */ 1076 | - ret = applesmc_init_smcreg(); 1077 | - if (ret) 1078 | - goto out_device; 1079 | - 1080 | - ret = applesmc_create_nodes(info_group, 1); 1081 | + ret = applesmc_create_nodes(smc, info_group, 1); 1082 | if (ret) 1083 | - goto out_smcreg; 1084 | + goto out; 1085 | 1086 | - ret = applesmc_create_nodes(fan_group, smcreg.fan_count); 1087 | + ret = applesmc_create_nodes(smc, fan_group, smc->reg.fan_count); 1088 | if (ret) 1089 | goto out_info; 1090 | 1091 | - ret = applesmc_create_nodes(temp_group, smcreg.index_count); 1092 | + ret = applesmc_create_nodes(smc, temp_group, smc->reg.index_count); 1093 | if (ret) 1094 | goto out_fans; 1095 | 1096 | - ret = applesmc_create_accelerometer(); 1097 | + ret = applesmc_create_accelerometer(smc); 1098 | if (ret) 1099 | goto out_temperature; 1100 | 1101 | - ret = applesmc_create_light_sensor(); 1102 | + ret = applesmc_create_light_sensor(smc); 1103 | if (ret) 1104 | goto out_accelerometer; 1105 | 1106 | - ret = applesmc_create_key_backlight(); 1107 | + ret = applesmc_create_key_backlight(smc); 1108 | if (ret) 1109 | goto out_light_sysfs; 1110 | 1111 | - hwmon_dev = hwmon_device_register(&pdev->dev); 1112 | - if (IS_ERR(hwmon_dev)) { 1113 | - ret = PTR_ERR(hwmon_dev); 1114 | + smc->hwmon_dev = hwmon_device_register(&smc->dev->dev); 1115 | + if (IS_ERR(smc->hwmon_dev)) { 1116 | + ret = PTR_ERR(smc->hwmon_dev); 1117 | goto out_light_ledclass; 1118 | } 1119 | 1120 | return 0; 1121 | 1122 | out_light_ledclass: 1123 | - applesmc_release_key_backlight(); 1124 | + applesmc_release_key_backlight(smc); 1125 | out_light_sysfs: 1126 | - applesmc_release_light_sensor(); 1127 | + applesmc_release_light_sensor(smc); 1128 | out_accelerometer: 1129 | - applesmc_release_accelerometer(); 1130 | + applesmc_release_accelerometer(smc); 1131 | out_temperature: 1132 | - applesmc_destroy_nodes(temp_group); 1133 | + applesmc_destroy_nodes(smc, temp_group); 1134 | out_fans: 1135 | - applesmc_destroy_nodes(fan_group); 1136 | + applesmc_destroy_nodes(smc, fan_group); 1137 | out_info: 1138 | - applesmc_destroy_nodes(info_group); 1139 | -out_smcreg: 1140 | - applesmc_destroy_smcreg(); 1141 | -out_device: 1142 | - platform_device_unregister(pdev); 1143 | + applesmc_destroy_nodes(smc, info_group); 1144 | +out: 1145 | + return ret; 1146 | +} 1147 | + 1148 | +static void applesmc_destroy_modules(struct applesmc_device *smc) 1149 | +{ 1150 | + hwmon_device_unregister(smc->hwmon_dev); 1151 | + applesmc_release_key_backlight(smc); 1152 | + applesmc_release_light_sensor(smc); 1153 | + applesmc_release_accelerometer(smc); 1154 | + applesmc_destroy_nodes(smc, temp_group); 1155 | + applesmc_destroy_nodes(smc, fan_group); 1156 | + applesmc_destroy_nodes(smc, info_group); 1157 | +} 1158 | + 1159 | +static struct platform_device *pdev; 1160 | + 1161 | +static int __init applesmc_init(void) 1162 | +{ 1163 | + int ret; 1164 | + 1165 | + if (!dmi_check_system(applesmc_whitelist)) { 1166 | + pr_warn("supported laptop not found!\n"); 1167 | + ret = -ENODEV; 1168 | + goto out; 1169 | + } 1170 | + 1171 | + if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, 1172 | + "applesmc")) { 1173 | + ret = -ENXIO; 1174 | + goto out; 1175 | + } 1176 | + 1177 | + ret = platform_driver_register(&applesmc_driver); 1178 | + if (ret) 1179 | + goto out_region; 1180 | + 1181 | + pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, 1182 | + NULL, 0); 1183 | + if (IS_ERR(pdev)) { 1184 | + ret = PTR_ERR(pdev); 1185 | + goto out_driver; 1186 | + } 1187 | + 1188 | + return 0; 1189 | + 1190 | out_driver: 1191 | platform_driver_unregister(&applesmc_driver); 1192 | out_region: 1193 | @@ -1397,14 +1502,6 @@ static int __init applesmc_init(void) 1194 | 1195 | static void __exit applesmc_exit(void) 1196 | { 1197 | - hwmon_device_unregister(hwmon_dev); 1198 | - applesmc_release_key_backlight(); 1199 | - applesmc_release_light_sensor(); 1200 | - applesmc_release_accelerometer(); 1201 | - applesmc_destroy_nodes(temp_group); 1202 | - applesmc_destroy_nodes(fan_group); 1203 | - applesmc_destroy_nodes(info_group); 1204 | - applesmc_destroy_smcreg(); 1205 | platform_device_unregister(pdev); 1206 | platform_driver_unregister(&applesmc_driver); 1207 | release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); 1208 | @@ -1414,6 +1511,7 @@ module_init(applesmc_init); 1209 | module_exit(applesmc_exit); 1210 | 1211 | MODULE_AUTHOR("Nicolas Boichat"); 1212 | +MODULE_AUTHOR("Paul Pawlowski"); 1213 | MODULE_DESCRIPTION("Apple SMC"); 1214 | MODULE_LICENSE("GPL v2"); 1215 | MODULE_DEVICE_TABLE(dmi, applesmc_whitelist); 1216 | -- 1217 | 2.45.2 1218 | 1219 | -------------------------------------------------------------------------------- /3002-applesmc-make-io-port-base-addr-dynamic.patch: -------------------------------------------------------------------------------- 1 | From d0b5f668d43281eda94dd64d48e39973139d107c Mon Sep 17 00:00:00 2001 2 | From: Paul Pawlowski 3 | Date: Sun, 17 Nov 2019 23:11:56 +0100 4 | Subject: [PATCH 2/9] applesmc: make io port base addr dynamic 5 | 6 | This change makes the port base runtime configurable. 7 | The reason why this change is made is so that when we switch to an 8 | acpi_device we can resolve the port base addr from ACPI. 9 | 10 | This change is not strictly required for T2 support - the base 11 | address is still 0x300 on T2 Macs. 12 | 13 | Signed-off-by: Aun-Ali Zaidi 14 | --- 15 | drivers/hwmon/applesmc.c | 91 +++++++++++++++++++++------------------- 16 | 1 file changed, 49 insertions(+), 42 deletions(-) 17 | 18 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 19 | index 7fb40738d..a599db68b 100644 20 | --- a/drivers/hwmon/applesmc.c 21 | +++ b/drivers/hwmon/applesmc.c 22 | @@ -35,10 +35,11 @@ 23 | #include 24 | #include 25 | 26 | +#define APPLESMC_PORT_BASE 0x300 27 | /* data port used by Apple SMC */ 28 | -#define APPLESMC_DATA_PORT 0x300 29 | +#define APPLESMC_DATA_PORT 0 30 | /* command/status port used by Apple SMC */ 31 | -#define APPLESMC_CMD_PORT 0x304 32 | +#define APPLESMC_CMD_PORT 4 33 | 34 | #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */ 35 | 36 | @@ -140,6 +141,8 @@ struct applesmc_device { 37 | struct platform_device *dev; 38 | struct applesmc_registers reg; 39 | 40 | + u16 port_base; 41 | + 42 | s16 rest_x; 43 | s16 rest_y; 44 | 45 | @@ -169,7 +172,7 @@ static const int debug; 46 | * run out past 500ms. 47 | */ 48 | 49 | -static int wait_status(u8 val, u8 mask) 50 | +static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) 51 | { 52 | u8 status; 53 | int us; 54 | @@ -177,7 +180,7 @@ static int wait_status(u8 val, u8 mask) 55 | 56 | us = APPLESMC_MIN_WAIT; 57 | for (i = 0; i < 24 ; i++) { 58 | - status = inb(APPLESMC_CMD_PORT); 59 | + status = inb(smc->port_base + APPLESMC_CMD_PORT); 60 | if ((status & mask) == val) 61 | return 0; 62 | usleep_range(us, us * 2); 63 | @@ -189,11 +192,11 @@ static int wait_status(u8 val, u8 mask) 64 | 65 | /* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ 66 | 67 | -static int send_byte(u8 cmd, u16 port) 68 | +static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) 69 | { 70 | int status; 71 | 72 | - status = wait_status(0, SMC_STATUS_IB_CLOSED); 73 | + status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 74 | if (status) 75 | return status; 76 | /* 77 | @@ -202,24 +205,24 @@ static int send_byte(u8 cmd, u16 port) 78 | * this extra read may not happen if status returns both 79 | * simultaneously and this would appear to be required. 80 | */ 81 | - status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY); 82 | + status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); 83 | if (status) 84 | return status; 85 | 86 | - outb(cmd, port); 87 | + outb(cmd, smc->port_base + port); 88 | return 0; 89 | } 90 | 91 | /* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ 92 | 93 | -static int send_command(u8 cmd) 94 | +static int send_command(struct applesmc_device *smc, u8 cmd) 95 | { 96 | int ret; 97 | 98 | - ret = wait_status(0, SMC_STATUS_IB_CLOSED); 99 | + ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 100 | if (ret) 101 | return ret; 102 | - outb(cmd, APPLESMC_CMD_PORT); 103 | + outb(cmd, smc->port_base + APPLESMC_CMD_PORT); 104 | return 0; 105 | } 106 | 107 | @@ -229,108 +232,112 @@ static int send_command(u8 cmd) 108 | * If busy is stuck high after the command then the SMC is jammed. 109 | */ 110 | 111 | -static int smc_sane(void) 112 | +static int smc_sane(struct applesmc_device *smc) 113 | { 114 | int ret; 115 | 116 | - ret = wait_status(0, SMC_STATUS_BUSY); 117 | + ret = wait_status(smc, 0, SMC_STATUS_BUSY); 118 | if (!ret) 119 | return ret; 120 | - ret = send_command(APPLESMC_READ_CMD); 121 | + ret = send_command(smc, APPLESMC_READ_CMD); 122 | if (ret) 123 | return ret; 124 | - return wait_status(0, SMC_STATUS_BUSY); 125 | + return wait_status(smc, 0, SMC_STATUS_BUSY); 126 | } 127 | 128 | -static int send_argument(const char *key) 129 | +static int send_argument(struct applesmc_device *smc, const char *key) 130 | { 131 | int i; 132 | 133 | for (i = 0; i < 4; i++) 134 | - if (send_byte(key[i], APPLESMC_DATA_PORT)) 135 | + if (send_byte(smc, key[i], APPLESMC_DATA_PORT)) 136 | return -EIO; 137 | return 0; 138 | } 139 | 140 | -static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) 141 | +static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, 142 | + u8 *buffer, u8 len) 143 | { 144 | u8 status, data = 0; 145 | int i; 146 | int ret; 147 | 148 | - ret = smc_sane(); 149 | + ret = smc_sane(smc); 150 | if (ret) 151 | return ret; 152 | 153 | - if (send_command(cmd) || send_argument(key)) { 154 | + if (send_command(smc, cmd) || send_argument(smc, key)) { 155 | pr_warn("%.4s: read arg fail\n", key); 156 | return -EIO; 157 | } 158 | 159 | /* This has no effect on newer (2012) SMCs */ 160 | - if (send_byte(len, APPLESMC_DATA_PORT)) { 161 | + if (send_byte(smc, len, APPLESMC_DATA_PORT)) { 162 | pr_warn("%.4s: read len fail\n", key); 163 | return -EIO; 164 | } 165 | 166 | for (i = 0; i < len; i++) { 167 | - if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, 168 | + if (wait_status(smc, 169 | + SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, 170 | SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) { 171 | pr_warn("%.4s: read data[%d] fail\n", key, i); 172 | return -EIO; 173 | } 174 | - buffer[i] = inb(APPLESMC_DATA_PORT); 175 | + buffer[i] = inb(smc->port_base + APPLESMC_DATA_PORT); 176 | } 177 | 178 | /* Read the data port until bit0 is cleared */ 179 | for (i = 0; i < 16; i++) { 180 | udelay(APPLESMC_MIN_WAIT); 181 | - status = inb(APPLESMC_CMD_PORT); 182 | + status = inb(smc->port_base + APPLESMC_CMD_PORT); 183 | if (!(status & SMC_STATUS_AWAITING_DATA)) 184 | break; 185 | - data = inb(APPLESMC_DATA_PORT); 186 | + data = inb(smc->port_base + APPLESMC_DATA_PORT); 187 | } 188 | if (i) 189 | pr_warn("flushed %d bytes, last value is: %d\n", i, data); 190 | 191 | - return wait_status(0, SMC_STATUS_BUSY); 192 | + return wait_status(smc, 0, SMC_STATUS_BUSY); 193 | } 194 | 195 | -static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) 196 | +static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key, 197 | + const u8 *buffer, u8 len) 198 | { 199 | int i; 200 | int ret; 201 | 202 | - ret = smc_sane(); 203 | + ret = smc_sane(smc); 204 | if (ret) 205 | return ret; 206 | 207 | - if (send_command(cmd) || send_argument(key)) { 208 | + if (send_command(smc, cmd) || send_argument(smc, key)) { 209 | pr_warn("%s: write arg fail\n", key); 210 | return -EIO; 211 | } 212 | 213 | - if (send_byte(len, APPLESMC_DATA_PORT)) { 214 | + if (send_byte(smc, len, APPLESMC_DATA_PORT)) { 215 | pr_warn("%.4s: write len fail\n", key); 216 | return -EIO; 217 | } 218 | 219 | for (i = 0; i < len; i++) { 220 | - if (send_byte(buffer[i], APPLESMC_DATA_PORT)) { 221 | + if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { 222 | pr_warn("%s: write data fail\n", key); 223 | return -EIO; 224 | } 225 | } 226 | 227 | - return wait_status(0, SMC_STATUS_BUSY); 228 | + return wait_status(smc, 0, SMC_STATUS_BUSY); 229 | } 230 | 231 | -static int read_register_count(unsigned int *count) 232 | +static int read_register_count(struct applesmc_device *smc, 233 | + unsigned int *count) 234 | { 235 | __be32 be; 236 | int ret; 237 | 238 | - ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); 239 | + ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); 240 | if (ret) 241 | return ret; 242 | 243 | @@ -353,7 +360,7 @@ static int applesmc_read_entry(struct applesmc_device *smc, 244 | if (entry->len != len) 245 | return -EINVAL; 246 | mutex_lock(&smc->reg.mutex); 247 | - ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); 248 | + ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len); 249 | mutex_unlock(&smc->reg.mutex); 250 | 251 | return ret; 252 | @@ -367,7 +374,7 @@ static int applesmc_write_entry(struct applesmc_device *smc, 253 | if (entry->len != len) 254 | return -EINVAL; 255 | mutex_lock(&smc->reg.mutex); 256 | - ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); 257 | + ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len); 258 | mutex_unlock(&smc->reg.mutex); 259 | return ret; 260 | } 261 | @@ -388,10 +395,10 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( 262 | if (cache->valid) 263 | goto out; 264 | be = cpu_to_be32(index); 265 | - ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); 266 | + ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); 267 | if (ret) 268 | goto out; 269 | - ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); 270 | + ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); 271 | if (ret) 272 | goto out; 273 | 274 | @@ -589,7 +596,7 @@ static int applesmc_init_smcreg_try(struct applesmc_device *smc) 275 | if (s->init_complete) 276 | return 0; 277 | 278 | - ret = read_register_count(&count); 279 | + ret = read_register_count(smc, &count); 280 | if (ret) 281 | return ret; 282 | 283 | @@ -1472,7 +1479,7 @@ static int __init applesmc_init(void) 284 | goto out; 285 | } 286 | 287 | - if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, 288 | + if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS, 289 | "applesmc")) { 290 | ret = -ENXIO; 291 | goto out; 292 | @@ -1494,7 +1501,7 @@ static int __init applesmc_init(void) 293 | out_driver: 294 | platform_driver_unregister(&applesmc_driver); 295 | out_region: 296 | - release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); 297 | + release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); 298 | out: 299 | pr_warn("driver init failed (ret=%d)!\n", ret); 300 | return ret; 301 | @@ -1504,7 +1511,7 @@ static void __exit applesmc_exit(void) 302 | { 303 | platform_device_unregister(pdev); 304 | platform_driver_unregister(&applesmc_driver); 305 | - release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); 306 | + release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); 307 | } 308 | 309 | module_init(applesmc_init); 310 | -- 311 | 2.45.2 312 | 313 | -------------------------------------------------------------------------------- /3003-applesmc-switch-to-acpi_device-from-platform.patch: -------------------------------------------------------------------------------- 1 | From c405f826e30e0035581b350084d61457ddde6146 Mon Sep 17 00:00:00 2001 2 | From: Paul Pawlowski 3 | Date: Sat, 29 Jun 2024 04:49:16 +0000 4 | Subject: [PATCH 3/9] applesmc: switch to acpi_device (from platform) 5 | 6 | This change makes the change from platform_device 7 | to acpi_device. The rationale for this change is 8 | that on T2 Macs, an additional FixedMemory32 9 | region is needed for device operation, and it can 10 | be easily resolved via ACPI tables (this will be 11 | done in another commit). 12 | 13 | Additionally, on older Macs, the OS X driver also 14 | looks for the specified ACPI device to resolve 15 | its memory regions, and therefore this change 16 | should not result in any incompatibilities. 17 | 18 | Signed-off-by: Aun-Ali Zaidi 19 | --- 20 | drivers/hwmon/applesmc.c | 124 ++++++++++++++++++++++++++------------- 21 | 1 file changed, 84 insertions(+), 40 deletions(-) 22 | 23 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 24 | index a599db68b..b4fe412c0 100644 25 | --- a/drivers/hwmon/applesmc.c 26 | +++ b/drivers/hwmon/applesmc.c 27 | @@ -19,7 +19,7 @@ 28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 29 | 30 | #include 31 | -#include 32 | +#include 33 | #include 34 | #include 35 | #include 36 | @@ -35,7 +35,6 @@ 37 | #include 38 | #include 39 | 40 | -#define APPLESMC_PORT_BASE 0x300 41 | /* data port used by Apple SMC */ 42 | #define APPLESMC_DATA_PORT 0 43 | /* command/status port used by Apple SMC */ 44 | @@ -138,9 +137,10 @@ struct applesmc_registers { 45 | }; 46 | 47 | struct applesmc_device { 48 | - struct platform_device *dev; 49 | + struct acpi_device *dev; 50 | struct applesmc_registers reg; 51 | 52 | + bool port_base_set; 53 | u16 port_base; 54 | 55 | s16 rest_x; 56 | @@ -692,9 +692,13 @@ static int applesmc_init_smcreg(struct applesmc_device *smc) 57 | } 58 | 59 | /* Device model stuff */ 60 | + 61 | +static int applesmc_init_resources(struct applesmc_device *smc); 62 | +static void applesmc_free_resources(struct applesmc_device *smc); 63 | static int applesmc_create_modules(struct applesmc_device *smc); 64 | static void applesmc_destroy_modules(struct applesmc_device *smc); 65 | -static int applesmc_probe(struct platform_device *dev) 66 | + 67 | +static int applesmc_add(struct acpi_device *dev) 68 | { 69 | struct applesmc_device *smc; 70 | int ret; 71 | @@ -705,12 +709,16 @@ static int applesmc_probe(struct platform_device *dev) 72 | smc->dev = dev; 73 | mutex_init(&smc->reg.mutex); 74 | 75 | - platform_set_drvdata(dev, smc); 76 | + dev_set_drvdata(&dev->dev, smc); 77 | 78 | - ret = applesmc_init_smcreg(smc); 79 | + ret = applesmc_init_resources(smc); 80 | if (ret) 81 | goto out_mem; 82 | 83 | + ret = applesmc_init_smcreg(smc); 84 | + if (ret) 85 | + goto out_res; 86 | + 87 | applesmc_device_init(smc); 88 | 89 | ret = applesmc_create_modules(smc); 90 | @@ -721,20 +729,23 @@ static int applesmc_probe(struct platform_device *dev) 91 | 92 | out_reg: 93 | applesmc_destroy_smcreg(smc); 94 | +out_res: 95 | + applesmc_free_resources(smc); 96 | out_mem: 97 | - platform_set_drvdata(dev, NULL); 98 | + dev_set_drvdata(&dev->dev, NULL); 99 | mutex_destroy(&smc->reg.mutex); 100 | kfree(smc); 101 | 102 | return ret; 103 | } 104 | 105 | -static int applesmc_remove(struct platform_device *dev) 106 | +static int applesmc_remove(struct acpi_device *dev) 107 | { 108 | - struct applesmc_device *smc = platform_get_drvdata(dev); 109 | + struct applesmc_device *smc = dev_get_drvdata(&dev->dev); 110 | 111 | applesmc_destroy_modules(smc); 112 | applesmc_destroy_smcreg(smc); 113 | + applesmc_free_resources(smc); 114 | 115 | mutex_destroy(&smc->reg.mutex); 116 | kfree(smc); 117 | @@ -742,6 +753,52 @@ static int applesmc_remove(struct platform_device *dev) 118 | return 0; 119 | } 120 | 121 | +static acpi_status applesmc_walk_resources(struct acpi_resource *res, 122 | + void *data) 123 | +{ 124 | + struct applesmc_device *smc = data; 125 | + 126 | + switch (res->type) { 127 | + case ACPI_RESOURCE_TYPE_IO: 128 | + if (!smc->port_base_set) { 129 | + if (res->data.io.address_length < APPLESMC_NR_PORTS) 130 | + return AE_ERROR; 131 | + smc->port_base = res->data.io.minimum; 132 | + smc->port_base_set = true; 133 | + } 134 | + return AE_OK; 135 | + 136 | + case ACPI_RESOURCE_TYPE_END_TAG: 137 | + if (smc->port_base_set) 138 | + return AE_OK; 139 | + else 140 | + return AE_NOT_FOUND; 141 | + 142 | + default: 143 | + return AE_OK; 144 | + } 145 | +} 146 | + 147 | +static int applesmc_init_resources(struct applesmc_device *smc) 148 | +{ 149 | + int ret; 150 | + 151 | + ret = acpi_walk_resources(smc->dev->handle, METHOD_NAME__CRS, 152 | + applesmc_walk_resources, smc); 153 | + if (ACPI_FAILURE(ret)) 154 | + return -ENXIO; 155 | + 156 | + if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc")) 157 | + return -ENXIO; 158 | + 159 | + return 0; 160 | +} 161 | + 162 | +static void applesmc_free_resources(struct applesmc_device *smc) 163 | +{ 164 | + release_region(smc->port_base, APPLESMC_NR_PORTS); 165 | +} 166 | + 167 | /* Synchronize device with memorized backlight state */ 168 | static int applesmc_pm_resume(struct device *dev) 169 | { 170 | @@ -763,17 +820,26 @@ static int applesmc_pm_restore(struct device *dev) 171 | return applesmc_pm_resume(dev); 172 | } 173 | 174 | +static const struct acpi_device_id applesmc_ids[] = { 175 | + {"APP0001", 0}, 176 | + {"", 0}, 177 | +}; 178 | + 179 | static const struct dev_pm_ops applesmc_pm_ops = { 180 | .resume = applesmc_pm_resume, 181 | .restore = applesmc_pm_restore, 182 | }; 183 | 184 | -static struct platform_driver applesmc_driver = { 185 | - .probe = applesmc_probe, 186 | - .remove = applesmc_remove, 187 | - .driver = { 188 | - .name = "applesmc", 189 | - .pm = &applesmc_pm_ops, 190 | +static struct acpi_driver applesmc_driver = { 191 | + .name = "applesmc", 192 | + .class = "applesmc", 193 | + .ids = applesmc_ids, 194 | + .ops = { 195 | + .add = applesmc_add, 196 | + .remove = applesmc_remove 197 | + }, 198 | + .drv = { 199 | + .pm = &applesmc_pm_ops 200 | }, 201 | }; 202 | 203 | @@ -1262,7 +1328,6 @@ static int applesmc_create_nodes(struct applesmc_device *smc, 204 | static int applesmc_create_accelerometer(struct applesmc_device *smc) 205 | { 206 | int ret; 207 | - 208 | if (!smc->reg.has_accelerometer) 209 | return 0; 210 | 211 | @@ -1467,8 +1532,6 @@ static void applesmc_destroy_modules(struct applesmc_device *smc) 212 | applesmc_destroy_nodes(smc, info_group); 213 | } 214 | 215 | -static struct platform_device *pdev; 216 | - 217 | static int __init applesmc_init(void) 218 | { 219 | int ret; 220 | @@ -1479,29 +1542,12 @@ static int __init applesmc_init(void) 221 | goto out; 222 | } 223 | 224 | - if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS, 225 | - "applesmc")) { 226 | - ret = -ENXIO; 227 | - goto out; 228 | - } 229 | - 230 | - ret = platform_driver_register(&applesmc_driver); 231 | + ret = acpi_bus_register_driver(&applesmc_driver); 232 | if (ret) 233 | - goto out_region; 234 | - 235 | - pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, 236 | - NULL, 0); 237 | - if (IS_ERR(pdev)) { 238 | - ret = PTR_ERR(pdev); 239 | - goto out_driver; 240 | - } 241 | + goto out; 242 | 243 | return 0; 244 | 245 | -out_driver: 246 | - platform_driver_unregister(&applesmc_driver); 247 | -out_region: 248 | - release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); 249 | out: 250 | pr_warn("driver init failed (ret=%d)!\n", ret); 251 | return ret; 252 | @@ -1509,9 +1555,7 @@ static int __init applesmc_init(void) 253 | 254 | static void __exit applesmc_exit(void) 255 | { 256 | - platform_device_unregister(pdev); 257 | - platform_driver_unregister(&applesmc_driver); 258 | - release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS); 259 | + acpi_bus_unregister_driver(&applesmc_driver); 260 | } 261 | 262 | module_init(applesmc_init); 263 | -- 264 | 2.45.2 265 | 266 | -------------------------------------------------------------------------------- /3004-applesmc-key-interface-wrappers.patch: -------------------------------------------------------------------------------- 1 | From 1ce5dd27e4464383ddfba3ee0d7ffdc7020bd81c Mon Sep 17 00:00:00 2001 2 | From: Paul Pawlowski 3 | Date: Sun, 17 Nov 2019 23:12:14 +0100 4 | Subject: [PATCH 4/9] applesmc: key interface wrappers 5 | 6 | This change replaces the read_smc and write_smc 7 | methods with wrappers, additionally removing the 8 | command id parameter from them (and introducing 9 | get_smc_key_by_index and get_smc_key_info). 10 | 11 | This is done as to allow simple implementation 12 | replacement on T2 Macs. The newly introduced 13 | methods mentioned in the previous paragraph need 14 | special handling on T2 and as such had to be 15 | separated. 16 | 17 | Signed-off-by: Aun-Ali Zaidi 18 | --- 19 | drivers/hwmon/applesmc.c | 119 ++++++++++++++++++++++++++------------- 20 | 1 file changed, 79 insertions(+), 40 deletions(-) 21 | 22 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 23 | index b4fe412c0..5442897e3 100644 24 | --- a/drivers/hwmon/applesmc.c 25 | +++ b/drivers/hwmon/applesmc.c 26 | @@ -172,7 +172,7 @@ static const int debug; 27 | * run out past 500ms. 28 | */ 29 | 30 | -static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) 31 | +static int port_wait_status(struct applesmc_device *smc, u8 val, u8 mask) 32 | { 33 | u8 status; 34 | int us; 35 | @@ -190,13 +190,13 @@ static int wait_status(struct applesmc_device *smc, u8 val, u8 mask) 36 | return -EIO; 37 | } 38 | 39 | -/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ 40 | +/* port_send_byte - Write to SMC data port. Callers must hold applesmc_lock. */ 41 | 42 | -static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) 43 | +static int port_send_byte(struct applesmc_device *smc, u8 cmd, u16 port) 44 | { 45 | int status; 46 | 47 | - status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 48 | + status = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 49 | if (status) 50 | return status; 51 | /* 52 | @@ -205,7 +205,7 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) 53 | * this extra read may not happen if status returns both 54 | * simultaneously and this would appear to be required. 55 | */ 56 | - status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); 57 | + status = port_wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY); 58 | if (status) 59 | return status; 60 | 61 | @@ -213,15 +213,16 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port) 62 | return 0; 63 | } 64 | 65 | -/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ 66 | +/* port_send_command - Write a command to the SMC. Callers must hold applesmc_lock. */ 67 | 68 | -static int send_command(struct applesmc_device *smc, u8 cmd) 69 | +static int port_send_command(struct applesmc_device *smc, u8 cmd) 70 | { 71 | int ret; 72 | 73 | - ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 74 | + ret = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED); 75 | if (ret) 76 | return ret; 77 | + 78 | outb(cmd, smc->port_base + APPLESMC_CMD_PORT); 79 | return 0; 80 | } 81 | @@ -232,53 +233,53 @@ static int send_command(struct applesmc_device *smc, u8 cmd) 82 | * If busy is stuck high after the command then the SMC is jammed. 83 | */ 84 | 85 | -static int smc_sane(struct applesmc_device *smc) 86 | +static int port_smc_sane(struct applesmc_device *smc) 87 | { 88 | int ret; 89 | 90 | - ret = wait_status(smc, 0, SMC_STATUS_BUSY); 91 | + ret = port_wait_status(smc, 0, SMC_STATUS_BUSY); 92 | if (!ret) 93 | return ret; 94 | - ret = send_command(smc, APPLESMC_READ_CMD); 95 | + ret = port_send_command(smc, APPLESMC_READ_CMD); 96 | if (ret) 97 | return ret; 98 | - return wait_status(smc, 0, SMC_STATUS_BUSY); 99 | + return port_wait_status(smc, 0, SMC_STATUS_BUSY); 100 | } 101 | 102 | -static int send_argument(struct applesmc_device *smc, const char *key) 103 | +static int port_send_argument(struct applesmc_device *smc, const char *key) 104 | { 105 | int i; 106 | 107 | for (i = 0; i < 4; i++) 108 | - if (send_byte(smc, key[i], APPLESMC_DATA_PORT)) 109 | + if (port_send_byte(smc, key[i], APPLESMC_DATA_PORT)) 110 | return -EIO; 111 | return 0; 112 | } 113 | 114 | -static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, 115 | +static int port_read_smc(struct applesmc_device *smc, u8 cmd, const char *key, 116 | u8 *buffer, u8 len) 117 | { 118 | u8 status, data = 0; 119 | int i; 120 | int ret; 121 | 122 | - ret = smc_sane(smc); 123 | + ret = port_smc_sane(smc); 124 | if (ret) 125 | return ret; 126 | 127 | - if (send_command(smc, cmd) || send_argument(smc, key)) { 128 | + if (port_send_command(smc, cmd) || port_send_argument(smc, key)) { 129 | pr_warn("%.4s: read arg fail\n", key); 130 | return -EIO; 131 | } 132 | 133 | /* This has no effect on newer (2012) SMCs */ 134 | - if (send_byte(smc, len, APPLESMC_DATA_PORT)) { 135 | + if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) { 136 | pr_warn("%.4s: read len fail\n", key); 137 | return -EIO; 138 | } 139 | 140 | for (i = 0; i < len; i++) { 141 | - if (wait_status(smc, 142 | + if (port_wait_status(smc, 143 | SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY, 144 | SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) { 145 | pr_warn("%.4s: read data[%d] fail\n", key, i); 146 | @@ -298,37 +299,80 @@ static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key, 147 | if (i) 148 | pr_warn("flushed %d bytes, last value is: %d\n", i, data); 149 | 150 | - return wait_status(smc, 0, SMC_STATUS_BUSY); 151 | + return port_wait_status(smc, 0, SMC_STATUS_BUSY); 152 | } 153 | 154 | -static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key, 155 | +static int port_write_smc(struct applesmc_device *smc, u8 cmd, const char *key, 156 | const u8 *buffer, u8 len) 157 | { 158 | int i; 159 | int ret; 160 | 161 | - ret = smc_sane(smc); 162 | + ret = port_smc_sane(smc); 163 | if (ret) 164 | return ret; 165 | 166 | - if (send_command(smc, cmd) || send_argument(smc, key)) { 167 | + if (port_send_command(smc, cmd) || port_send_argument(smc, key)) { 168 | pr_warn("%s: write arg fail\n", key); 169 | return -EIO; 170 | } 171 | 172 | - if (send_byte(smc, len, APPLESMC_DATA_PORT)) { 173 | + if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) { 174 | pr_warn("%.4s: write len fail\n", key); 175 | return -EIO; 176 | } 177 | 178 | for (i = 0; i < len; i++) { 179 | - if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { 180 | + if (port_send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) { 181 | pr_warn("%s: write data fail\n", key); 182 | return -EIO; 183 | } 184 | } 185 | 186 | - return wait_status(smc, 0, SMC_STATUS_BUSY); 187 | + return port_wait_status(smc, 0, SMC_STATUS_BUSY); 188 | +} 189 | + 190 | +static int port_get_smc_key_info(struct applesmc_device *smc, 191 | + const char *key, struct applesmc_entry *info) 192 | +{ 193 | + int ret; 194 | + u8 raw[6]; 195 | + 196 | + ret = port_read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, raw, 6); 197 | + if (ret) 198 | + return ret; 199 | + info->len = raw[0]; 200 | + memcpy(info->type, &raw[1], 4); 201 | + info->flags = raw[5]; 202 | + return 0; 203 | +} 204 | + 205 | +static int read_smc(struct applesmc_device *smc, const char *key, 206 | + u8 *buffer, u8 len) 207 | +{ 208 | + return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); 209 | +} 210 | + 211 | +static int write_smc(struct applesmc_device *smc, const char *key, 212 | + const u8 *buffer, u8 len) 213 | +{ 214 | + return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); 215 | +} 216 | + 217 | +static int get_smc_key_by_index(struct applesmc_device *smc, 218 | + unsigned int index, char *key) 219 | +{ 220 | + __be32 be; 221 | + 222 | + be = cpu_to_be32(index); 223 | + return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, 224 | + (const char *) &be, (u8 *) key, 4); 225 | +} 226 | + 227 | +static int get_smc_key_info(struct applesmc_device *smc, const char *key, 228 | + struct applesmc_entry *info) 229 | +{ 230 | + return port_get_smc_key_info(smc, key, info); 231 | } 232 | 233 | static int read_register_count(struct applesmc_device *smc, 234 | @@ -337,8 +381,8 @@ static int read_register_count(struct applesmc_device *smc, 235 | __be32 be; 236 | int ret; 237 | 238 | - ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); 239 | - if (ret) 240 | + ret = read_smc(smc, KEY_COUNT_KEY, (u8 *)&be, 4); 241 | + if (ret < 0) 242 | return ret; 243 | 244 | *count = be32_to_cpu(be); 245 | @@ -360,7 +404,7 @@ static int applesmc_read_entry(struct applesmc_device *smc, 246 | if (entry->len != len) 247 | return -EINVAL; 248 | mutex_lock(&smc->reg.mutex); 249 | - ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len); 250 | + ret = read_smc(smc, entry->key, buf, len); 251 | mutex_unlock(&smc->reg.mutex); 252 | 253 | return ret; 254 | @@ -374,7 +418,7 @@ static int applesmc_write_entry(struct applesmc_device *smc, 255 | if (entry->len != len) 256 | return -EINVAL; 257 | mutex_lock(&smc->reg.mutex); 258 | - ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len); 259 | + ret = write_smc(smc, entry->key, buf, len); 260 | mutex_unlock(&smc->reg.mutex); 261 | return ret; 262 | } 263 | @@ -383,8 +427,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( 264 | struct applesmc_device *smc, int index) 265 | { 266 | struct applesmc_entry *cache = &smc->reg.cache[index]; 267 | - u8 key[4], info[6]; 268 | - __be32 be; 269 | + char key[4]; 270 | int ret = 0; 271 | 272 | if (cache->valid) 273 | @@ -394,18 +437,14 @@ static const struct applesmc_entry *applesmc_get_entry_by_index( 274 | 275 | if (cache->valid) 276 | goto out; 277 | - be = cpu_to_be32(index); 278 | - ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); 279 | + ret = get_smc_key_by_index(smc, index, key); 280 | if (ret) 281 | goto out; 282 | - ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); 283 | + memcpy(cache->key, key, 4); 284 | + 285 | + ret = get_smc_key_info(smc, key, cache); 286 | if (ret) 287 | goto out; 288 | - 289 | - memcpy(cache->key, key, 4); 290 | - cache->len = info[0]; 291 | - memcpy(cache->type, &info[1], 4); 292 | - cache->flags = info[5]; 293 | cache->valid = true; 294 | 295 | out: 296 | -- 297 | 2.45.2 298 | 299 | -------------------------------------------------------------------------------- /3005-applesmc-basic-mmio-interface-implementation.patch: -------------------------------------------------------------------------------- 1 | From 665609158a43eb6ab3d79e6ee06b9c1edf1cd331 Mon Sep 17 00:00:00 2001 2 | From: Aun-Ali Zaidi 3 | Date: Sun, 17 Nov 2019 23:12:16 +0100 4 | Subject: [PATCH 5/9] applesmc: basic mmio interface implementation 5 | 6 | This change introduces a basic MMIO-based 7 | interface implementation required to communicate 8 | with the SMC on T2 Macs. The MMIO interface is 9 | enabled only when it's supported on the running 10 | system. 11 | 12 | The MMIO interface replaces legacy port-based SMC 13 | key reads, writes and metadata requests (getting 14 | key by index and getting key info). 15 | 16 | (Based on patch by @mcmrarm) 17 | 18 | Signed-off-by: Aun-Ali Zaidi 19 | --- 20 | drivers/hwmon/applesmc.c | 237 ++++++++++++++++++++++++++++++++++++++- 21 | 1 file changed, 231 insertions(+), 6 deletions(-) 22 | 23 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 24 | index 5442897e3..435541f9f 100644 25 | --- a/drivers/hwmon/applesmc.c 26 | +++ b/drivers/hwmon/applesmc.c 27 | @@ -42,6 +42,18 @@ 28 | 29 | #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */ 30 | 31 | +#define APPLESMC_IOMEM_KEY_DATA 0 32 | +#define APPLESMC_IOMEM_KEY_STATUS 0x4005 33 | +#define APPLESMC_IOMEM_KEY_NAME 0x78 34 | +#define APPLESMC_IOMEM_KEY_DATA_LEN 0x7D 35 | +#define APPLESMC_IOMEM_KEY_SMC_ID 0x7E 36 | +#define APPLESMC_IOMEM_KEY_CMD 0x7F 37 | +#define APPLESMC_IOMEM_MIN_SIZE 0x4006 38 | + 39 | +#define APPLESMC_IOMEM_KEY_TYPE_CODE 0 40 | +#define APPLESMC_IOMEM_KEY_TYPE_DATA_LEN 5 41 | +#define APPLESMC_IOMEM_KEY_TYPE_FLAGS 6 42 | + 43 | #define APPLESMC_MAX_DATA_LENGTH 32 44 | 45 | /* Apple SMC status bits */ 46 | @@ -138,10 +150,13 @@ struct applesmc_registers { 47 | 48 | struct applesmc_device { 49 | struct acpi_device *dev; 50 | + struct device *ldev; 51 | struct applesmc_registers reg; 52 | 53 | - bool port_base_set; 54 | + bool port_base_set, iomem_base_set; 55 | u16 port_base; 56 | + u8 *__iomem iomem_base; 57 | + u32 iomem_base_addr, iomem_base_size; 58 | 59 | s16 rest_x; 60 | s16 rest_y; 61 | @@ -347,16 +362,156 @@ static int port_get_smc_key_info(struct applesmc_device *smc, 62 | return 0; 63 | } 64 | 65 | + 66 | +/* 67 | + * MMIO based communication. 68 | + * TODO: Use updated mechanism for cmd timeout/retry 69 | + */ 70 | + 71 | +static void iomem_clear_status(struct applesmc_device *smc) 72 | +{ 73 | + if (ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS)) 74 | + iowrite8(0, smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); 75 | +} 76 | + 77 | +static int iomem_wait_read(struct applesmc_device *smc) 78 | +{ 79 | + u8 status; 80 | + int us; 81 | + int i; 82 | + 83 | + us = APPLESMC_MIN_WAIT; 84 | + for (i = 0; i < 24 ; i++) { 85 | + status = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); 86 | + if (status & 0x20) 87 | + return 0; 88 | + usleep_range(us, us * 2); 89 | + if (i > 9) 90 | + us <<= 1; 91 | + } 92 | + 93 | + dev_warn(smc->ldev, "%s... timeout\n", __func__); 94 | + return -EIO; 95 | +} 96 | + 97 | +static int iomem_read_smc(struct applesmc_device *smc, u8 cmd, const char *key, 98 | + u8 *buffer, u8 len) 99 | +{ 100 | + u8 err, remote_len; 101 | + u32 key_int = *((u32 *) key); 102 | + 103 | + iomem_clear_status(smc); 104 | + iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); 105 | + iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); 106 | + iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 107 | + 108 | + if (iomem_wait_read(smc)) 109 | + return -EIO; 110 | + 111 | + err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 112 | + if (err != 0) { 113 | + dev_warn(smc->ldev, "read_smc_mmio(%x %8x/%.4s) failed: %u\n", 114 | + cmd, key_int, key, err); 115 | + return -EIO; 116 | + } 117 | + 118 | + if (cmd == APPLESMC_READ_CMD) { 119 | + remote_len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN); 120 | + if (remote_len != len) { 121 | + dev_warn(smc->ldev, 122 | + "read_smc_mmio(%x %8x/%.4s) failed: buffer length mismatch (remote = %u, requested = %u)\n", 123 | + cmd, key_int, key, remote_len, len); 124 | + return -EINVAL; 125 | + } 126 | + } else { 127 | + remote_len = len; 128 | + } 129 | + 130 | + memcpy_fromio(buffer, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, 131 | + remote_len); 132 | + 133 | + dev_dbg(smc->ldev, "read_smc_mmio(%x %8x/%.4s): buflen=%u reslen=%u\n", 134 | + cmd, key_int, key, len, remote_len); 135 | + print_hex_dump_bytes("read_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, remote_len); 136 | + return 0; 137 | +} 138 | + 139 | +static int iomem_get_smc_key_type(struct applesmc_device *smc, const char *key, 140 | + struct applesmc_entry *e) 141 | +{ 142 | + u8 err; 143 | + u8 cmd = APPLESMC_GET_KEY_TYPE_CMD; 144 | + u32 key_int = *((u32 *) key); 145 | + 146 | + iomem_clear_status(smc); 147 | + iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); 148 | + iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); 149 | + iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 150 | + 151 | + if (iomem_wait_read(smc)) 152 | + return -EIO; 153 | + 154 | + err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 155 | + if (err != 0) { 156 | + dev_warn(smc->ldev, "get_smc_key_type_mmio(%.4s) failed: %u\n", key, err); 157 | + return -EIO; 158 | + } 159 | + 160 | + e->len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_DATA_LEN); 161 | + *((uint32_t *) e->type) = ioread32( 162 | + smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_CODE); 163 | + e->flags = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_FLAGS); 164 | + 165 | + dev_dbg(smc->ldev, "get_smc_key_type_mmio(%.4s): len=%u type=%.4s flags=%x\n", 166 | + key, e->len, e->type, e->flags); 167 | + return 0; 168 | +} 169 | + 170 | +static int iomem_write_smc(struct applesmc_device *smc, u8 cmd, const char *key, 171 | + const u8 *buffer, u8 len) 172 | +{ 173 | + u8 err; 174 | + u32 key_int = *((u32 *) key); 175 | + 176 | + iomem_clear_status(smc); 177 | + iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME); 178 | + memcpy_toio(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, buffer, len); 179 | + iowrite32(len, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN); 180 | + iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID); 181 | + iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 182 | + 183 | + if (iomem_wait_read(smc)) 184 | + return -EIO; 185 | + 186 | + err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD); 187 | + if (err != 0) { 188 | + dev_warn(smc->ldev, "write_smc_mmio(%x %.4s) failed: %u\n", cmd, key, err); 189 | + print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len); 190 | + return -EIO; 191 | + } 192 | + 193 | + dev_dbg(smc->ldev, "write_smc_mmio(%x %.4s): buflen=%u\n", cmd, key, len); 194 | + print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len); 195 | + return 0; 196 | +} 197 | + 198 | + 199 | static int read_smc(struct applesmc_device *smc, const char *key, 200 | u8 *buffer, u8 len) 201 | { 202 | - return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); 203 | + if (smc->iomem_base_set) 204 | + return iomem_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); 205 | + else 206 | + return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len); 207 | } 208 | 209 | static int write_smc(struct applesmc_device *smc, const char *key, 210 | const u8 *buffer, u8 len) 211 | { 212 | - return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); 213 | + if (smc->iomem_base_set) 214 | + return iomem_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); 215 | + else 216 | + return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len); 217 | } 218 | 219 | static int get_smc_key_by_index(struct applesmc_device *smc, 220 | @@ -365,14 +520,21 @@ static int get_smc_key_by_index(struct applesmc_device *smc, 221 | __be32 be; 222 | 223 | be = cpu_to_be32(index); 224 | - return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, 225 | - (const char *) &be, (u8 *) key, 4); 226 | + if (smc->iomem_base_set) 227 | + return iomem_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, 228 | + (const char *) &be, (u8 *) key, 4); 229 | + else 230 | + return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, 231 | + (const char *) &be, (u8 *) key, 4); 232 | } 233 | 234 | static int get_smc_key_info(struct applesmc_device *smc, const char *key, 235 | struct applesmc_entry *info) 236 | { 237 | - return port_get_smc_key_info(smc, key, info); 238 | + if (smc->iomem_base_set) 239 | + return iomem_get_smc_key_type(smc, key, info); 240 | + else 241 | + return port_get_smc_key_info(smc, key, info); 242 | } 243 | 244 | static int read_register_count(struct applesmc_device *smc, 245 | @@ -746,6 +908,7 @@ static int applesmc_add(struct acpi_device *dev) 246 | if (!smc) 247 | return -ENOMEM; 248 | smc->dev = dev; 249 | + smc->ldev = &dev->dev; 250 | mutex_init(&smc->reg.mutex); 251 | 252 | dev_set_drvdata(&dev->dev, smc); 253 | @@ -807,6 +970,20 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res, 254 | } 255 | return AE_OK; 256 | 257 | + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 258 | + if (!smc->iomem_base_set) { 259 | + if (res->data.fixed_memory32.address_length < 260 | + APPLESMC_IOMEM_MIN_SIZE) { 261 | + dev_warn(smc->ldev, "found iomem but it's too small: %u\n", 262 | + res->data.fixed_memory32.address_length); 263 | + return AE_OK; 264 | + } 265 | + smc->iomem_base_addr = res->data.fixed_memory32.address; 266 | + smc->iomem_base_size = res->data.fixed_memory32.address_length; 267 | + smc->iomem_base_set = true; 268 | + } 269 | + return AE_OK; 270 | + 271 | case ACPI_RESOURCE_TYPE_END_TAG: 272 | if (smc->port_base_set) 273 | return AE_OK; 274 | @@ -818,6 +995,8 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res, 275 | } 276 | } 277 | 278 | +static int applesmc_try_enable_iomem(struct applesmc_device *smc); 279 | + 280 | static int applesmc_init_resources(struct applesmc_device *smc) 281 | { 282 | int ret; 283 | @@ -830,11 +1009,57 @@ static int applesmc_init_resources(struct applesmc_device *smc) 284 | if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc")) 285 | return -ENXIO; 286 | 287 | + if (smc->iomem_base_set) { 288 | + if (applesmc_try_enable_iomem(smc)) 289 | + smc->iomem_base_set = false; 290 | + } 291 | + 292 | return 0; 293 | } 294 | 295 | +static int applesmc_try_enable_iomem(struct applesmc_device *smc) 296 | +{ 297 | + u8 test_val, ldkn_version; 298 | + 299 | + dev_dbg(smc->ldev, "Trying to enable iomem based communication\n"); 300 | + smc->iomem_base = ioremap(smc->iomem_base_addr, smc->iomem_base_size); 301 | + if (!smc->iomem_base) 302 | + goto out; 303 | + 304 | + /* Apple's driver does this check for some reason */ 305 | + test_val = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS); 306 | + if (test_val == 0xff) { 307 | + dev_warn(smc->ldev, 308 | + "iomem enable failed: initial status is 0xff (is %x)\n", 309 | + test_val); 310 | + goto out_iomem; 311 | + } 312 | + 313 | + if (read_smc(smc, "LDKN", &ldkn_version, 1)) { 314 | + dev_warn(smc->ldev, "iomem enable failed: ldkn read failed\n"); 315 | + goto out_iomem; 316 | + } 317 | + 318 | + if (ldkn_version < 2) { 319 | + dev_warn(smc->ldev, 320 | + "iomem enable failed: ldkn version %u is less than minimum (2)\n", 321 | + ldkn_version); 322 | + goto out_iomem; 323 | + } 324 | + 325 | + return 0; 326 | + 327 | +out_iomem: 328 | + iounmap(smc->iomem_base); 329 | + 330 | +out: 331 | + return -ENXIO; 332 | +} 333 | + 334 | static void applesmc_free_resources(struct applesmc_device *smc) 335 | { 336 | + if (smc->iomem_base_set) 337 | + iounmap(smc->iomem_base); 338 | release_region(smc->port_base, APPLESMC_NR_PORTS); 339 | } 340 | 341 | -- 342 | 2.45.2 343 | 344 | -------------------------------------------------------------------------------- /3006-applesmc-fan-support-on-T2-Macs.patch: -------------------------------------------------------------------------------- 1 | From e77e6a12cd389d1d61b861a1c88a6f393daa6d91 Mon Sep 17 00:00:00 2001 2 | From: Paul Pawlowski 3 | Date: Sun, 17 Nov 2019 23:12:18 +0100 4 | Subject: [PATCH 6/9] applesmc: fan support on T2 Macs 5 | 6 | T2 Macs changed the fan values from shorts to 7 | floats, and changed the fan manual override 8 | setting from a bitmask to a per-fan boolean 9 | named F0Md (thanks to @kleuter for mentioning 10 | it). 11 | 12 | A minimal soft-float implementation has been 13 | written for convert floats to integers (and vice 14 | versa). 15 | 16 | Signed-off-by: Aun-Ali Zaidi 17 | --- 18 | drivers/hwmon/applesmc.c | 119 +++++++++++++++++++++++++++++++++------ 19 | 1 file changed, 102 insertions(+), 17 deletions(-) 20 | 21 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 22 | index 435541f9f..46b64eba7 100644 23 | --- a/drivers/hwmon/applesmc.c 24 | +++ b/drivers/hwmon/applesmc.c 25 | @@ -87,6 +87,7 @@ 26 | #define FAN_ID_FMT "F%dID" /* r-o char[16] */ 27 | 28 | #define TEMP_SENSOR_TYPE "sp78" 29 | +#define FLOAT_TYPE "flt " 30 | 31 | /* List of keys used to read/write fan speeds */ 32 | static const char *const fan_speed_fmt[] = { 33 | @@ -96,6 +97,7 @@ static const char *const fan_speed_fmt[] = { 34 | "F%dSf", /* safe speed - not all models */ 35 | "F%dTg", /* target speed (manual: rw) */ 36 | }; 37 | +#define FAN_MANUAL_FMT "F%dMd" 38 | 39 | #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ 40 | #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ 41 | @@ -734,6 +736,42 @@ static int applesmc_read_s16(struct applesmc_device *smc, 42 | return 0; 43 | } 44 | 45 | +/** 46 | + * applesmc_float_to_u32 - Retrieve the integral part of a float. 47 | + * This is needed because Apple made fans use float values in the T2. 48 | + * The fractional point is not significantly useful though, and the integral 49 | + * part can be easily extracted. 50 | + */ 51 | +static inline u32 applesmc_float_to_u32(u32 d) 52 | +{ 53 | + u8 sign = (u8) ((d >> 31) & 1); 54 | + s32 exp = (s32) ((d >> 23) & 0xff) - 0x7f; 55 | + u32 fr = d & ((1u << 23) - 1); 56 | + 57 | + if (sign || exp < 0) 58 | + return 0; 59 | + 60 | + return (u32) ((1u << exp) + (fr >> (23 - exp))); 61 | +} 62 | + 63 | +/** 64 | + * applesmc_u32_to_float - Convert an u32 into a float. 65 | + * See applesmc_float_to_u32 for a rationale. 66 | + */ 67 | +static inline u32 applesmc_u32_to_float(u32 d) 68 | +{ 69 | + u32 dc = d, bc = 0, exp; 70 | + 71 | + if (!d) 72 | + return 0; 73 | + 74 | + while (dc >>= 1) 75 | + ++bc; 76 | + exp = 0x7f + bc; 77 | + 78 | + return (u32) ((exp << 23) | 79 | + ((d << (23 - (exp - 0x7f))) & ((1u << 23) - 1))); 80 | +} 81 | /* 82 | * applesmc_device_init - initialize the accelerometer. Can sleep. 83 | */ 84 | @@ -1241,6 +1279,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, 85 | struct device_attribute *attr, char *sysfsbuf) 86 | { 87 | struct applesmc_device *smc = dev_get_drvdata(dev); 88 | + const struct applesmc_entry *entry; 89 | int ret; 90 | unsigned int speed = 0; 91 | char newkey[5]; 92 | @@ -1249,11 +1288,21 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, 93 | scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], 94 | to_index(attr)); 95 | 96 | - ret = applesmc_read_key(smc, newkey, buffer, 2); 97 | + entry = applesmc_get_entry_by_key(smc, newkey); 98 | + if (IS_ERR(entry)) 99 | + return PTR_ERR(entry); 100 | + 101 | + if (!strcmp(entry->type, FLOAT_TYPE)) { 102 | + ret = applesmc_read_entry(smc, entry, (u8 *) &speed, 4); 103 | + speed = applesmc_float_to_u32(speed); 104 | + } else { 105 | + ret = applesmc_read_entry(smc, entry, buffer, 2); 106 | + speed = ((buffer[0] << 8 | buffer[1]) >> 2); 107 | + } 108 | + 109 | if (ret) 110 | return ret; 111 | 112 | - speed = ((buffer[0] << 8 | buffer[1]) >> 2); 113 | return sysfs_emit(sysfsbuf, "%u\n", speed); 114 | } 115 | 116 | @@ -1262,6 +1311,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, 117 | const char *sysfsbuf, size_t count) 118 | { 119 | struct applesmc_device *smc = dev_get_drvdata(dev); 120 | + const struct applesmc_entry *entry; 121 | int ret; 122 | unsigned long speed; 123 | char newkey[5]; 124 | @@ -1273,9 +1323,18 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, 125 | scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)], 126 | to_index(attr)); 127 | 128 | - buffer[0] = (speed >> 6) & 0xff; 129 | - buffer[1] = (speed << 2) & 0xff; 130 | - ret = applesmc_write_key(smc, newkey, buffer, 2); 131 | + entry = applesmc_get_entry_by_key(smc, newkey); 132 | + if (IS_ERR(entry)) 133 | + return PTR_ERR(entry); 134 | + 135 | + if (!strcmp(entry->type, FLOAT_TYPE)) { 136 | + speed = applesmc_u32_to_float(speed); 137 | + ret = applesmc_write_entry(smc, entry, (u8 *) &speed, 4); 138 | + } else { 139 | + buffer[0] = (speed >> 6) & 0xff; 140 | + buffer[1] = (speed << 2) & 0xff; 141 | + ret = applesmc_write_key(smc, newkey, buffer, 2); 142 | + } 143 | 144 | if (ret) 145 | return ret; 146 | @@ -1290,12 +1349,26 @@ static ssize_t applesmc_show_fan_manual(struct device *dev, 147 | int ret; 148 | u16 manual = 0; 149 | u8 buffer[2]; 150 | + char newkey[5]; 151 | + bool has_newkey = false; 152 | + 153 | + scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr)); 154 | + 155 | + ret = applesmc_has_key(smc, newkey, &has_newkey); 156 | + if (ret) 157 | + return ret; 158 | + 159 | + if (has_newkey) { 160 | + ret = applesmc_read_key(smc, newkey, buffer, 1); 161 | + manual = buffer[0]; 162 | + } else { 163 | + ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 164 | + manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; 165 | + } 166 | 167 | - ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 168 | if (ret) 169 | return ret; 170 | 171 | - manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; 172 | return sysfs_emit(sysfsbuf, "%d\n", manual); 173 | } 174 | 175 | @@ -1306,27 +1379,39 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, 176 | struct applesmc_device *smc = dev_get_drvdata(dev); 177 | int ret; 178 | u8 buffer[2]; 179 | + char newkey[5]; 180 | + bool has_newkey = false; 181 | unsigned long input; 182 | u16 val; 183 | 184 | if (kstrtoul(sysfsbuf, 10, &input) < 0) 185 | return -EINVAL; 186 | 187 | - ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 188 | + scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr)); 189 | + 190 | + ret = applesmc_has_key(smc, newkey, &has_newkey); 191 | if (ret) 192 | - goto out; 193 | + return ret; 194 | 195 | - val = (buffer[0] << 8 | buffer[1]); 196 | + if (has_newkey) { 197 | + buffer[0] = input & 1; 198 | + ret = applesmc_write_key(smc, newkey, buffer, 1); 199 | + } else { 200 | + ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2); 201 | + val = (buffer[0] << 8 | buffer[1]); 202 | + if (ret) 203 | + goto out; 204 | 205 | - if (input) 206 | - val = val | (0x01 << to_index(attr)); 207 | - else 208 | - val = val & ~(0x01 << to_index(attr)); 209 | + if (input) 210 | + val = val | (0x01 << to_index(attr)); 211 | + else 212 | + val = val & ~(0x01 << to_index(attr)); 213 | 214 | - buffer[0] = (val >> 8) & 0xFF; 215 | - buffer[1] = val & 0xFF; 216 | + buffer[0] = (val >> 8) & 0xFF; 217 | + buffer[1] = val & 0xFF; 218 | 219 | - ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); 220 | + ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2); 221 | + } 222 | 223 | out: 224 | if (ret) 225 | -- 226 | 2.45.2 227 | 228 | -------------------------------------------------------------------------------- /3007-applesmc-Add-iMacPro-to-applesmc_whitelist.patch: -------------------------------------------------------------------------------- 1 | From 5c95c8e1ada14babfba0f21a2f481d7ff53d17c7 Mon Sep 17 00:00:00 2001 2 | From: Orlando Chamberlain 3 | Date: Sun, 9 Oct 2022 15:59:01 +0530 4 | Subject: [PATCH 7/9] applesmc: Add iMacPro to applesmc_whitelist 5 | 6 | The iMacPro1,1 is the only iMacPro released before the line was 7 | discontinued. Add it to the applesmc_whitelist. 8 | 9 | Signed-off-by: Orlando Chamberlain 10 | --- 11 | drivers/hwmon/applesmc.c | 4 ++++ 12 | 1 file changed, 4 insertions(+) 13 | 14 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 15 | index 46b64eba7..8c7b2e2cd 100644 16 | --- a/drivers/hwmon/applesmc.c 17 | +++ b/drivers/hwmon/applesmc.c 18 | @@ -1803,6 +1803,10 @@ static const struct dmi_system_id applesmc_whitelist[] __initconst = { 19 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), 20 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") }, 21 | }, 22 | + { applesmc_dmi_match, "Apple iMacPro", { 23 | + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), 24 | + DMI_MATCH(DMI_PRODUCT_NAME, "iMacPro") }, 25 | + }, 26 | { applesmc_dmi_match, "Apple MacPro", { 27 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), 28 | DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, 29 | -- 30 | 2.45.2 31 | 32 | -------------------------------------------------------------------------------- /3008-applesmc-make-applesmc_remove-void.patch: -------------------------------------------------------------------------------- 1 | From 4d444d98c6f5f7f39540386b97aa8d77102ada74 Mon Sep 17 00:00:00 2001 2 | From: Orlando Chamberlain 3 | Date: Tue, 24 Jan 2023 15:46:48 +1100 4 | Subject: [PATCH 8/9] applesmc: make applesmc_remove void 5 | 6 | for linux6.2 compatibility 7 | --- 8 | drivers/hwmon/applesmc.c | 4 ++-- 9 | 1 file changed, 2 insertions(+), 2 deletions(-) 10 | 11 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 12 | index 8c7b2e2cd..5f67d7362 100644 13 | --- a/drivers/hwmon/applesmc.c 14 | +++ b/drivers/hwmon/applesmc.c 15 | @@ -979,7 +979,7 @@ static int applesmc_add(struct acpi_device *dev) 16 | return ret; 17 | } 18 | 19 | -static int applesmc_remove(struct acpi_device *dev) 20 | +static void applesmc_remove(struct acpi_device *dev) 21 | { 22 | struct applesmc_device *smc = dev_get_drvdata(&dev->dev); 23 | 24 | @@ -990,7 +990,7 @@ static int applesmc_remove(struct acpi_device *dev) 25 | mutex_destroy(&smc->reg.mutex); 26 | kfree(smc); 27 | 28 | - return 0; 29 | + return; 30 | } 31 | 32 | static acpi_status applesmc_walk_resources(struct acpi_resource *res, 33 | -- 34 | 2.45.2 35 | 36 | -------------------------------------------------------------------------------- /3009-applesmc-battery-charge-limiter.patch: -------------------------------------------------------------------------------- 1 | From add0db8b96c3f90b844586a3b9ea32041bae4b2c Mon Sep 17 00:00:00 2001 2 | From: Orlando Chamberlain 3 | Date: Mon, 30 Jan 2023 18:42:21 +1100 4 | Subject: [PATCH 9/9] applesmc: battery charge limiter 5 | 6 | --- 7 | drivers/hwmon/applesmc.c | 42 +++++++++++++++++++++++++++++++++++++++- 8 | 1 file changed, 41 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c 11 | index 5f67d7362..698f44794 100644 12 | --- a/drivers/hwmon/applesmc.c 13 | +++ b/drivers/hwmon/applesmc.c 14 | @@ -1477,6 +1477,35 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev, 15 | dev_dbg(led_cdev->dev, "work was already on the queue.\n"); 16 | } 17 | 18 | +static ssize_t applesmc_BCLM_store(struct device *dev, 19 | + struct device_attribute *attr, char *sysfsbuf, size_t count) 20 | +{ 21 | + struct applesmc_device *smc = dev_get_drvdata(dev); 22 | + u8 val; 23 | + 24 | + if (kstrtou8(sysfsbuf, 10, &val) < 0) 25 | + return -EINVAL; 26 | + 27 | + if (val < 0 || val > 100) 28 | + return -EINVAL; 29 | + 30 | + if (applesmc_write_key(smc, "BCLM", &val, 1)) 31 | + return -ENODEV; 32 | + return count; 33 | +} 34 | + 35 | +static ssize_t applesmc_BCLM_show(struct device *dev, 36 | + struct device_attribute *attr, char *sysfsbuf) 37 | +{ 38 | + struct applesmc_device *smc = dev_get_drvdata(dev); 39 | + u8 val; 40 | + 41 | + if (applesmc_read_key(smc, "BCLM", &val, 1)) 42 | + return -ENODEV; 43 | + 44 | + return sysfs_emit(sysfsbuf, "%d\n", val); 45 | +} 46 | + 47 | static ssize_t applesmc_key_count_show(struct device *dev, 48 | struct device_attribute *attr, char *sysfsbuf) 49 | { 50 | @@ -1611,6 +1640,11 @@ static struct applesmc_node_group temp_group[] = { 51 | { } 52 | }; 53 | 54 | +static struct applesmc_node_group BCLM_group[] = { 55 | + { "battery_charge_limit", applesmc_BCLM_show, applesmc_BCLM_store }, 56 | + { } 57 | +}; 58 | + 59 | /* Module stuff */ 60 | 61 | /* 62 | @@ -1829,10 +1863,13 @@ static int applesmc_create_modules(struct applesmc_device *smc) 63 | ret = applesmc_create_nodes(smc, info_group, 1); 64 | if (ret) 65 | goto out; 66 | + ret = applesmc_create_nodes(smc, BCLM_group, 1); 67 | + if (ret) 68 | + goto out_info; 69 | 70 | ret = applesmc_create_nodes(smc, fan_group, smc->reg.fan_count); 71 | if (ret) 72 | - goto out_info; 73 | + goto out_bclm; 74 | 75 | ret = applesmc_create_nodes(smc, temp_group, smc->reg.index_count); 76 | if (ret) 77 | @@ -1868,6 +1905,8 @@ static int applesmc_create_modules(struct applesmc_device *smc) 78 | applesmc_destroy_nodes(smc, temp_group); 79 | out_fans: 80 | applesmc_destroy_nodes(smc, fan_group); 81 | +out_bclm: 82 | + applesmc_destroy_nodes(smc, BCLM_group); 83 | out_info: 84 | applesmc_destroy_nodes(smc, info_group); 85 | out: 86 | @@ -1882,6 +1921,7 @@ static void applesmc_destroy_modules(struct applesmc_device *smc) 87 | applesmc_release_accelerometer(smc); 88 | applesmc_destroy_nodes(smc, temp_group); 89 | applesmc_destroy_nodes(smc, fan_group); 90 | + applesmc_destroy_nodes(smc, BCLM_group); 91 | applesmc_destroy_nodes(smc, info_group); 92 | } 93 | 94 | -- 95 | 2.45.2 96 | 97 | -------------------------------------------------------------------------------- /4002-HID-quirks-remove-T2-devices-from-hid_mouse_ignore_l.patch: -------------------------------------------------------------------------------- 1 | From 165066841c211201b3f228f03e18e28423e98e94 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Mon, 10 Mar 2025 22:53:28 +0530 4 | Subject: [PATCH 1/5] HID: quirks: remove T2 devices from hid_mouse_ignore_list 5 | 6 | In order to use hid-magicmouse for T2 trackpads, we need to 7 | remove them from hid_mouse_ignore_list 8 | 9 | Signed-off-by: Aditya Garg 10 | --- 11 | drivers/hid/hid-quirks.c | 8 -------- 12 | 1 file changed, 8 deletions(-) 13 | 14 | diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c 15 | index e0bbf0c63..2eb15a7ae 100644 16 | --- a/drivers/hid/hid-quirks.c 17 | +++ b/drivers/hid/hid-quirks.c 18 | @@ -956,14 +956,6 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { 19 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, 20 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, 21 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, 22 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, 23 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, 24 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, 25 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, 26 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, 27 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, 28 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, 29 | - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) }, 30 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, 31 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, 32 | { } 33 | -- 34 | 2.43.0 35 | 36 | -------------------------------------------------------------------------------- /4003-HID-apple-ignore-the-trackpad-on-T2-Macs.patch: -------------------------------------------------------------------------------- 1 | From cc2712238a3179b046f7cd36a24a9a606b99aa81 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Mon, 10 Mar 2025 23:03:29 +0530 4 | Subject: [PATCH 2/5] HID: apple: ignore the trackpad on T2 Macs 5 | 6 | In order to manage the trackpad on T2 Macs by hid-magicmouse driver 7 | we need to ensure that it is not bound by the hid-apple driver. Use 8 | the existing APPLE_IGNORE_MOUSE quirk for the same. 9 | 10 | Signed-off-by: Aditya Garg 11 | --- 12 | drivers/hid/hid-apple.c | 23 +++++++++++++++-------- 13 | 1 file changed, 15 insertions(+), 8 deletions(-) 14 | 15 | diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c 16 | index a33260293..fdfbfe6ab 100644 17 | --- a/drivers/hid/hid-apple.c 18 | +++ b/drivers/hid/hid-apple.c 19 | @@ -963,6 +963,9 @@ static int apple_probe(struct hid_device *hdev, 20 | hdev->type != HID_TYPE_SPI_KEYBOARD) 21 | return -ENODEV; 22 | 23 | + if (quirks & APPLE_IGNORE_MOUSE && hdev->type == HID_TYPE_USBMOUSE) 24 | + return -ENODEV; 25 | + 26 | asc = devm_kzalloc(&hdev->dev, sizeof(*asc), GFP_KERNEL); 27 | if (asc == NULL) { 28 | hid_err(hdev, "can't alloc apple descriptor\n"); 29 | @@ -1180,21 +1183,25 @@ static const struct hid_device_id apple_devices[] = { 30 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), 31 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 32 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), 33 | - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 34 | + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 35 | + APPLE_IGNORE_MOUSE }, 36 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), 37 | - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 38 | + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 39 | + APPLE_IGNORE_MOUSE }, 40 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), 41 | - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 42 | + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 43 | + APPLE_IGNORE_MOUSE }, 44 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), 45 | - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 46 | + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 47 | + APPLE_IGNORE_MOUSE }, 48 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), 49 | - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 50 | + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE }, 51 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), 52 | - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 53 | + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE }, 54 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), 55 | - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 56 | + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE }, 57 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), 58 | - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 59 | + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE }, 60 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), 61 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 62 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), 63 | -- 64 | 2.43.0 65 | 66 | -------------------------------------------------------------------------------- /4004-HID-magicmouse-Add-support-for-trackpads-found-on-T2.patch: -------------------------------------------------------------------------------- 1 | From 333c1742167b64aea0802996601b9bdc5aaa0a6e Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Tue, 11 Mar 2025 18:44:06 +0530 4 | Subject: [PATCH 3/5] HID: magicmouse: Add support for trackpads found on T2 5 | Macs 6 | 7 | This patch adds support for trackpads found on Macs with the T2 8 | Security Chip. The touch report format differs from other trackpads. 9 | It is the same format as type 4 in bcm5974.c 10 | 11 | Signed-off-by: Aditya Garg 12 | --- 13 | drivers/hid/hid-magicmouse.c | 371 +++++++++++++++++++++++++++++------ 14 | 1 file changed, 313 insertions(+), 58 deletions(-) 15 | 16 | diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c 17 | index d5ab547b1..eb62752d7 100644 18 | --- a/drivers/hid/hid-magicmouse.c 19 | +++ b/drivers/hid/hid-magicmouse.c 20 | @@ -117,6 +117,94 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie 21 | #define TRACKPAD2_RES_Y \ 22 | ((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100)) 23 | 24 | +#define J140K_TP_DIMENSION_X (float)12100 25 | +#define J140K_TP_MIN_X -5318 26 | +#define J140K_TP_MAX_X 5787 27 | +#define J140K_TP_RES_X \ 28 | + ((J140K_TP_MAX_X - J140K_TP_MIN_X) / (J140K_TP_DIMENSION_X / 100)) 29 | +#define J140K_TP_DIMENSION_Y (float)8200 30 | +#define J140K_TP_MIN_Y -157 31 | +#define J140K_TP_MAX_Y 7102 32 | +#define J140K_TP_RES_Y \ 33 | + ((J140K_TP_MAX_Y - J140K_TP_MIN_Y) / (J140K_TP_DIMENSION_Y / 100)) 34 | + 35 | +#define J132_TP_DIMENSION_X (float)13500 36 | +#define J132_TP_MIN_X -6243 37 | +#define J132_TP_MAX_X 6749 38 | +#define J132_TP_RES_X \ 39 | + ((J132_TP_MAX_X - J132_TP_MIN_X) / (J132_TP_DIMENSION_X / 100)) 40 | +#define J132_TP_DIMENSION_Y (float)8400 41 | +#define J132_TP_MIN_Y -170 42 | +#define J132_TP_MAX_Y 7685 43 | +#define J132_TP_RES_Y \ 44 | + ((J132_TP_MAX_Y - J132_TP_MIN_Y) / (J132_TP_DIMENSION_Y / 100)) 45 | + 46 | +#define J680_TP_DIMENSION_X (float)16000 47 | +#define J680_TP_MIN_X -7456 48 | +#define J680_TP_MAX_X 7976 49 | +#define J680_TP_RES_X \ 50 | + ((J680_TP_MAX_X - J680_TP_MIN_X) / (J680_TP_DIMENSION_X / 100)) 51 | +#define J680_TP_DIMENSION_Y (float)10000 52 | +#define J680_TP_MIN_Y -163 53 | +#define J680_TP_MAX_Y 9283 54 | +#define J680_TP_RES_Y \ 55 | + ((J680_TP_MAX_Y - J680_TP_MIN_Y) / (J680_TP_DIMENSION_Y / 100)) 56 | + 57 | +#define J213_TP_DIMENSION_X (float)13500 58 | +#define J213_TP_MIN_X -6243 59 | +#define J213_TP_MAX_X 6749 60 | +#define J213_TP_RES_X \ 61 | + ((J213_TP_MAX_X - J213_TP_MIN_X) / (J213_TP_DIMENSION_X / 100)) 62 | +#define J213_TP_DIMENSION_Y (float)8400 63 | +#define J213_TP_MIN_Y -170 64 | +#define J213_TP_MAX_Y 7685 65 | +#define J213_TP_RES_Y \ 66 | + ((J213_TP_MAX_Y - J213_TP_MIN_Y) / (J213_TP_DIMENSION_Y / 100)) 67 | + 68 | +#define J214K_TP_DIMENSION_X (float)13200 69 | +#define J214K_TP_MIN_X -6046 70 | +#define J214K_TP_MAX_X 6536 71 | +#define J214K_TP_RES_X \ 72 | + ((J214K_TP_MAX_X - J214K_TP_MIN_X) / (J214K_TP_DIMENSION_X / 100)) 73 | +#define J214K_TP_DIMENSION_Y (float)8200 74 | +#define J214K_TP_MIN_Y -164 75 | +#define J214K_TP_MAX_Y 7439 76 | +#define J214K_TP_RES_Y \ 77 | + ((J214K_TP_MAX_Y - J214K_TP_MIN_Y) / (J214K_TP_DIMENSION_Y / 100)) 78 | + 79 | +#define J223_TP_DIMENSION_X (float)13200 80 | +#define J223_TP_MIN_X -6046 81 | +#define J223_TP_MAX_X 6536 82 | +#define J223_TP_RES_X \ 83 | + ((J223_TP_MAX_X - J223_TP_MIN_X) / (J223_TP_DIMENSION_X / 100)) 84 | +#define J223_TP_DIMENSION_Y (float)8200 85 | +#define J223_TP_MIN_Y -164 86 | +#define J223_TP_MAX_Y 7439 87 | +#define J223_TP_RES_Y \ 88 | + ((J223_TP_MAX_Y - J223_TP_MIN_Y) / (J223_TP_DIMENSION_Y / 100)) 89 | + 90 | +#define J230K_TP_DIMENSION_X (float)12100 91 | +#define J230K_TP_MIN_X -5318 92 | +#define J230K_TP_MAX_X 5787 93 | +#define J230K_TP_RES_X \ 94 | + ((J230K_TP_MAX_X - J230K_TP_MIN_X) / (J230K_TP_DIMENSION_X / 100)) 95 | +#define J230K_TP_DIMENSION_Y (float)8200 96 | +#define J230K_TP_MIN_Y -157 97 | +#define J230K_TP_MAX_Y 7102 98 | +#define J230K_TP_RES_Y \ 99 | + ((J230K_TP_MAX_Y - J230K_TP_MIN_Y) / (J230K_TP_DIMENSION_Y / 100)) 100 | + 101 | +#define J152F_TP_DIMENSION_X (float)16000 102 | +#define J152F_TP_MIN_X -7456 103 | +#define J152F_TP_MAX_X 7976 104 | +#define J152F_TP_RES_X \ 105 | + ((J152F_TP_MAX_X - J152F_TP_MIN_X) / (J152F_TP_DIMENSION_X / 100)) 106 | +#define J152F_TP_DIMENSION_Y (float)10000 107 | +#define J152F_TP_MIN_Y -163 108 | +#define J152F_TP_MAX_Y 9283 109 | +#define J152F_TP_RES_Y \ 110 | + ((J152F_TP_MAX_Y - J152F_TP_MIN_Y) / (J152F_TP_DIMENSION_Y / 100)) 111 | + 112 | /* These are fallback values, since the real values will be queried from the device. */ 113 | #define J314_TP_DIMENSION_X (float)13000 114 | #define J314_TP_MIN_X -5900 115 | @@ -129,7 +217,11 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie 116 | #define J314_TP_RES_Y \ 117 | ((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100)) 118 | 119 | -#define J314_TP_MAX_FINGER_ORIENTATION 16384 120 | +#define T2_TOUCHPAD_ENTRY(model) \ 121 | + { USB_DEVICE_ID_APPLE_WELLSPRINGT2_##model, model##_TP_MIN_X, model##_TP_MIN_Y, \ 122 | +model##_TP_MAX_X, model##_TP_MAX_Y, model##_TP_RES_X, model##_TP_RES_Y } 123 | + 124 | +#define INTERNAL_TP_MAX_FINGER_ORIENTATION 16384 125 | 126 | struct magicmouse_input_ops { 127 | int (*raw_event)(struct hid_device *hdev, 128 | @@ -196,24 +288,45 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev) 129 | int ret; 130 | int feature_size; 131 | 132 | - if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || 133 | - hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) { 134 | - if (hdev->vendor == BT_VENDOR_ID_APPLE) { 135 | - feature_size = sizeof(feature_mt_trackpad2_bt); 136 | - feature = feature_mt_trackpad2_bt; 137 | - } else { /* USB_VENDOR_ID_APPLE */ 138 | + switch (hdev->bus) { 139 | + case BUS_SPI: 140 | + case BUS_HOST: 141 | + feature_size = sizeof(feature_mt_trackpad2_usb); 142 | + feature = feature_mt_trackpad2_usb; 143 | + break; 144 | + default: 145 | + switch (hdev->product) { 146 | + case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2: 147 | + case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC: 148 | + switch (hdev->vendor) { 149 | + case BT_VENDOR_ID_APPLE: 150 | + feature_size = sizeof(feature_mt_trackpad2_bt); 151 | + feature = feature_mt_trackpad2_bt; 152 | + break; 153 | + default: /* USB_VENDOR_ID_APPLE */ 154 | + feature_size = sizeof(feature_mt_trackpad2_usb); 155 | + feature = feature_mt_trackpad2_usb; 156 | + } 157 | + break; 158 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 159 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 160 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 161 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 162 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 163 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 164 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K: 165 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F: 166 | feature_size = sizeof(feature_mt_trackpad2_usb); 167 | feature = feature_mt_trackpad2_usb; 168 | + break; 169 | + case USB_DEVICE_ID_APPLE_MAGICMOUSE2: 170 | + feature_size = sizeof(feature_mt_mouse2); 171 | + feature = feature_mt_mouse2; 172 | + break; 173 | + default: 174 | + feature_size = sizeof(feature_mt); 175 | + feature = feature_mt; 176 | } 177 | - } else if (hdev->vendor == SPI_VENDOR_ID_APPLE) { 178 | - feature_size = sizeof(feature_mt_trackpad2_usb); 179 | - feature = feature_mt_trackpad2_usb; 180 | - } else if (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 181 | - feature_size = sizeof(feature_mt_mouse2); 182 | - feature = feature_mt_mouse2; 183 | - } else { 184 | - feature_size = sizeof(feature_mt); 185 | - feature = feature_mt; 186 | } 187 | 188 | buf = kmemdup(feature, feature_size, GFP_KERNEL); 189 | @@ -784,7 +897,7 @@ static void report_finger_data(struct input_dev *input, int slot, 190 | input_report_abs(input, ABS_MT_WIDTH_MINOR, 191 | le16_to_int(f->tool_minor) << 1); 192 | input_report_abs(input, ABS_MT_ORIENTATION, 193 | - J314_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation)); 194 | + INTERNAL_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation)); 195 | input_report_abs(input, ABS_MT_PRESSURE, le16_to_int(f->pressure)); 196 | input_report_abs(input, ABS_MT_POSITION_X, pos->x); 197 | input_report_abs(input, ABS_MT_POSITION_Y, pos->y); 198 | @@ -872,6 +985,20 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev, 199 | return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz); 200 | } 201 | 202 | +static int magicmouse_raw_event_t2(struct hid_device *hdev, 203 | + struct hid_report *report, u8 *data, int size) 204 | +{ 205 | + const size_t hdr_sz = sizeof(struct tp_mouse_report); 206 | + 207 | + if (!size) 208 | + return 0; 209 | + 210 | + if (data[0] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz) 211 | + return 0; 212 | + 213 | + return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz); 214 | +} 215 | + 216 | static int magicmouse_event(struct hid_device *hdev, struct hid_field *field, 217 | struct hid_usage *usage, __s32 value) 218 | { 219 | @@ -1063,8 +1190,31 @@ static int magicmouse_setup_input_usb(struct input_dev *input, 220 | return 0; 221 | } 222 | 223 | -static int magicmouse_setup_input_mtp(struct input_dev *input, 224 | - struct hid_device *hdev) 225 | +struct magicmouse_t2_properties { 226 | + u32 id; 227 | + int min_x; 228 | + int min_y; 229 | + int max_x; 230 | + int max_y; 231 | + int res_x; 232 | + int res_y; 233 | +}; 234 | + 235 | +static const struct magicmouse_t2_properties magicmouse_t2_configs[] = { 236 | + T2_TOUCHPAD_ENTRY(J140K), 237 | + T2_TOUCHPAD_ENTRY(J132), 238 | + T2_TOUCHPAD_ENTRY(J680), 239 | + T2_TOUCHPAD_ENTRY(J213), 240 | + T2_TOUCHPAD_ENTRY(J214K), 241 | + T2_TOUCHPAD_ENTRY(J223), 242 | + T2_TOUCHPAD_ENTRY(J230K), 243 | + T2_TOUCHPAD_ENTRY(J152F), 244 | +}; 245 | + 246 | +static int magicmouse_setup_input_int_tpd(struct input_dev *input, 247 | + struct hid_device *hdev, int min_x, int min_y, 248 | + int max_x, int max_y, int res_x, int res_y, 249 | + bool query_dimensions) 250 | { 251 | int error; 252 | int mt_flags = 0; 253 | @@ -1105,19 +1255,17 @@ static int magicmouse_setup_input_mtp(struct input_dev *input, 254 | input_abs_set_res(input, ABS_MT_PRESSURE, 1); 255 | 256 | /* finger orientation */ 257 | - input_set_abs_params(input, ABS_MT_ORIENTATION, -J314_TP_MAX_FINGER_ORIENTATION, 258 | - J314_TP_MAX_FINGER_ORIENTATION, 0, 0); 259 | + input_set_abs_params(input, ABS_MT_ORIENTATION, -INTERNAL_TP_MAX_FINGER_ORIENTATION, 260 | + INTERNAL_TP_MAX_FINGER_ORIENTATION, 0, 0); 261 | 262 | /* finger position */ 263 | - input_set_abs_params(input, ABS_MT_POSITION_X, J314_TP_MIN_X, J314_TP_MAX_X, 264 | - 0, 0); 265 | + input_set_abs_params(input, ABS_MT_POSITION_X, min_x, max_x, 0, 0); 266 | /* Y axis is inverted */ 267 | - input_set_abs_params(input, ABS_MT_POSITION_Y, -J314_TP_MAX_Y, -J314_TP_MIN_Y, 268 | - 0, 0); 269 | + input_set_abs_params(input, ABS_MT_POSITION_Y, -max_y, -min_y, 0, 0); 270 | 271 | /* X/Y resolution */ 272 | - input_abs_set_res(input, ABS_MT_POSITION_X, J314_TP_RES_X); 273 | - input_abs_set_res(input, ABS_MT_POSITION_Y, J314_TP_RES_Y); 274 | + input_abs_set_res(input, ABS_MT_POSITION_X, res_x); 275 | + input_abs_set_res(input, ABS_MT_POSITION_Y, res_y); 276 | 277 | input_set_events_per_packet(input, 60); 278 | 279 | @@ -1144,7 +1292,20 @@ static int magicmouse_setup_input_mtp(struct input_dev *input, 280 | */ 281 | input->open = magicmouse_open; 282 | input->close = magicmouse_close; 283 | - msc->query_dimensions = true; 284 | + msc->query_dimensions = query_dimensions; 285 | + 286 | + return 0; 287 | +} 288 | + 289 | +static int magicmouse_setup_input_mtp(struct input_dev *input, 290 | + struct hid_device *hdev) 291 | +{ 292 | + int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X, 293 | + J314_TP_MIN_Y, J314_TP_MAX_X, 294 | + J314_TP_MAX_Y, J314_TP_RES_X, 295 | + J314_TP_RES_Y, true); 296 | + if (ret) 297 | + return ret; 298 | 299 | return 0; 300 | } 301 | @@ -1152,7 +1313,34 @@ static int magicmouse_setup_input_mtp(struct input_dev *input, 302 | static int magicmouse_setup_input_spi(struct input_dev *input, 303 | struct hid_device *hdev) 304 | { 305 | - int ret = magicmouse_setup_input_mtp(input, hdev); 306 | + int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X, 307 | + J314_TP_MIN_Y, J314_TP_MAX_X, 308 | + J314_TP_MAX_Y, J314_TP_RES_X, 309 | + J314_TP_RES_Y, true); 310 | + if (ret) 311 | + return ret; 312 | + 313 | + return 0; 314 | +} 315 | + 316 | +static int magicmouse_setup_input_t2(struct input_dev *input, 317 | + struct hid_device *hdev) 318 | +{ 319 | + int min_x, min_y, max_x, max_y, res_x, res_y; 320 | + 321 | + for (size_t i = 0; i < ARRAY_SIZE(magicmouse_t2_configs); i++) { 322 | + if (magicmouse_t2_configs[i].id == hdev->product) { 323 | + min_x = magicmouse_t2_configs[i].min_x; 324 | + min_y = magicmouse_t2_configs[i].min_y; 325 | + max_x = magicmouse_t2_configs[i].max_x; 326 | + max_y = magicmouse_t2_configs[i].max_y; 327 | + res_x = magicmouse_t2_configs[i].res_x; 328 | + res_y = magicmouse_t2_configs[i].res_y; 329 | + } 330 | + } 331 | + 332 | + int ret = magicmouse_setup_input_int_tpd(input, hdev, min_x, min_y, 333 | + max_x, max_y, res_x, res_y, false); 334 | if (ret) 335 | return ret; 336 | 337 | @@ -1244,8 +1432,22 @@ static int magicmouse_probe(struct hid_device *hdev, 338 | int ret; 339 | 340 | if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE && 341 | - hdev->type != HID_TYPE_SPI_MOUSE) 342 | - return -ENODEV; 343 | + hdev->type != HID_TYPE_SPI_MOUSE) 344 | + return -ENODEV; 345 | + 346 | + switch (id->product) { 347 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 348 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 349 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 350 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 351 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 352 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 353 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K: 354 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F: 355 | + if (hdev->type != HID_TYPE_USBMOUSE) 356 | + return -ENODEV; 357 | + break; 358 | + } 359 | 360 | msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL); 361 | if (msc == NULL) { 362 | @@ -1255,16 +1457,32 @@ static int magicmouse_probe(struct hid_device *hdev, 363 | 364 | // internal trackpad use a data format use input ops to avoid 365 | // conflicts with the report ID. 366 | - if (id->bus == BUS_HOST) { 367 | + switch (id->bus) { 368 | + case BUS_HOST: 369 | msc->input_ops.raw_event = magicmouse_raw_event_mtp; 370 | msc->input_ops.setup_input = magicmouse_setup_input_mtp; 371 | - } else if (id->bus == BUS_SPI) { 372 | + break; 373 | + case BUS_SPI: 374 | msc->input_ops.raw_event = magicmouse_raw_event_spi; 375 | msc->input_ops.setup_input = magicmouse_setup_input_spi; 376 | - 377 | - } else { 378 | - msc->input_ops.raw_event = magicmouse_raw_event_usb; 379 | - msc->input_ops.setup_input = magicmouse_setup_input_usb; 380 | + break; 381 | + default: 382 | + switch (id->product) { 383 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 384 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 385 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 386 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 387 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 388 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 389 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K: 390 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F: 391 | + msc->input_ops.raw_event = magicmouse_raw_event_t2; 392 | + msc->input_ops.setup_input = magicmouse_setup_input_t2; 393 | + break; 394 | + default: 395 | + msc->input_ops.raw_event = magicmouse_raw_event_usb; 396 | + msc->input_ops.setup_input = magicmouse_setup_input_usb; 397 | + } 398 | } 399 | 400 | msc->scroll_accel = SCROLL_ACCEL_DEFAULT; 401 | @@ -1304,29 +1522,50 @@ static int magicmouse_probe(struct hid_device *hdev, 402 | goto err_stop_hw; 403 | } 404 | 405 | - if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) 406 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 407 | - MOUSE_REPORT_ID, 0); 408 | - else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) 409 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 410 | - MOUSE2_REPORT_ID, 0); 411 | - else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || 412 | - id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) { 413 | - if (id->vendor == BT_VENDOR_ID_APPLE) 414 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 415 | - TRACKPAD2_BT_REPORT_ID, 0); 416 | - else /* USB_VENDOR_ID_APPLE */ 417 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 418 | - TRACKPAD2_USB_REPORT_ID, 0); 419 | - } else if (id->bus == BUS_SPI) { 420 | + switch (id->bus) { 421 | + case BUS_SPI: 422 | report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0); 423 | - } else if (id->bus == BUS_HOST) { 424 | + break; 425 | + case BUS_HOST: 426 | report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0); 427 | - } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ 428 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 429 | - TRACKPAD_REPORT_ID, 0); 430 | - report = hid_register_report(hdev, HID_INPUT_REPORT, 431 | - DOUBLE_REPORT_ID, 0); 432 | + break; 433 | + default: 434 | + switch (id->product) { 435 | + case USB_DEVICE_ID_APPLE_MAGICMOUSE: 436 | + report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE_REPORT_ID, 0); 437 | + break; 438 | + case USB_DEVICE_ID_APPLE_MAGICMOUSE2: 439 | + report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE2_REPORT_ID, 0); 440 | + break; 441 | + case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2: 442 | + case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC: 443 | + switch (id->vendor) { 444 | + case BT_VENDOR_ID_APPLE: 445 | + report = hid_register_report(hdev, HID_INPUT_REPORT, 446 | + TRACKPAD2_BT_REPORT_ID, 0); 447 | + break; 448 | + default: 449 | + report = hid_register_report(hdev, HID_INPUT_REPORT, 450 | + TRACKPAD2_USB_REPORT_ID, 0); 451 | + } 452 | + break; 453 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 454 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 455 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 456 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 457 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 458 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 459 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K: 460 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F: 461 | + report = hid_register_report(hdev, HID_INPUT_REPORT, 462 | + TRACKPAD2_USB_REPORT_ID, 0); 463 | + break; 464 | + default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ 465 | + report = hid_register_report(hdev, HID_INPUT_REPORT, 466 | + TRACKPAD_REPORT_ID, 0); 467 | + report = hid_register_report(hdev, HID_INPUT_REPORT, 468 | + DOUBLE_REPORT_ID, 0); 469 | + } 470 | } 471 | 472 | if (!report) { 473 | @@ -1414,6 +1653,22 @@ static const struct hid_device_id magic_mice[] = { 474 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 }, 475 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 476 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 }, 477 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 478 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), .driver_data = 0 }, 479 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 480 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), .driver_data = 0 }, 481 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 482 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), .driver_data = 0 }, 483 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 484 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), .driver_data = 0 }, 485 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 486 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), .driver_data = 0 }, 487 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 488 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), .driver_data = 0 }, 489 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 490 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), .driver_data = 0 }, 491 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 492 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), .driver_data = 0 }, 493 | { HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID), 494 | .driver_data = 0 }, 495 | { HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE, 496 | -- 497 | 2.43.0 498 | 499 | -------------------------------------------------------------------------------- /4005-HID-apple-Add-necessary-IDs-and-support-for-replacem.patch: -------------------------------------------------------------------------------- 1 | From 96ae78d70a21e7ba765daf870efc8577092d5ff0 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Tue, 18 Mar 2025 21:25:05 +0530 4 | Subject: [PATCH 4/5] HID: apple: Add necessary IDs and support for replacement 5 | trackpad on MacBookPro15,1 6 | 7 | Some third party trackpad replacements like that of HAWSON may have a 8 | different PID than the stock trackpad. This commit adds one such trackpad 9 | to hid-apple. 10 | 11 | Signed-off-by: Aditya Garg 12 | --- 13 | drivers/hid/hid-apple.c | 4 ++++ 14 | drivers/hid/hid-ids.h | 17 +++++++++-------- 15 | drivers/hid/hid-quirks.c | 1 + 16 | 3 files changed, 14 insertions(+), 8 deletions(-) 17 | 18 | diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c 19 | index fdfbfe6ab..dd84a387e 100644 20 | --- a/drivers/hid/hid-apple.c 21 | +++ b/drivers/hid/hid-apple.c 22 | @@ -523,6 +523,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, 23 | table = apple2021_fn_keys; 24 | else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 || 25 | hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 || 26 | + hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT || 27 | hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) 28 | table = macbookpro_no_esc_fn_keys; 29 | else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K || 30 | @@ -1191,6 +1192,9 @@ static const struct hid_device_id apple_devices[] = { 31 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), 32 | .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 33 | APPLE_IGNORE_MOUSE }, 34 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), 35 | + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 36 | + APPLE_IGNORE_MOUSE }, 37 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), 38 | .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 39 | APPLE_IGNORE_MOUSE }, 40 | diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h 41 | index 192c09c27..f4b803c5b 100644 42 | --- a/drivers/hid/hid-ids.h 43 | +++ b/drivers/hid/hid-ids.h 44 | @@ -170,14 +170,15 @@ 45 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 46 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 47 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 48 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a 49 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b 50 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c 51 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d 52 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e 53 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f 54 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 55 | -#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 56 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a 57 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b 58 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c 59 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT 0x0278 60 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d 61 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e 62 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f 63 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 64 | +#define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 65 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a 66 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b 67 | #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 68 | diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c 69 | index 2eb15a7ae..ecfb1c3a8 100644 70 | --- a/drivers/hid/hid-quirks.c 71 | +++ b/drivers/hid/hid-quirks.c 72 | @@ -312,6 +312,7 @@ static const struct hid_device_id hid_have_special_driver[] = { 73 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, 74 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, 75 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, 76 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT) }, 77 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, 78 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, 79 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, 80 | -- 81 | 2.43.0 82 | 83 | -------------------------------------------------------------------------------- /4006-HID-magicmouse-Add-MacBookPro15-1-replacement-trackp.patch: -------------------------------------------------------------------------------- 1 | From 8a980335aa7495020760fb507bb906975b864ada Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg 3 | Date: Tue, 18 Mar 2025 21:27:25 +0530 4 | Subject: [PATCH 5/5] HID: magicmouse: Add MacBookPro15,1 replacement trackpad 5 | support 6 | 7 | This commit adds support for third party replacement trackpad for 8 | MacBookPro15,1 with a different PID in hid-magicmouse. 9 | 10 | Signed-off-by: Aditya Garg 11 | --- 12 | drivers/hid/hid-magicmouse.c | 18 ++++++++++++++++++ 13 | 1 file changed, 18 insertions(+) 14 | 15 | diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c 16 | index eb62752d7..769c31706 100644 17 | --- a/drivers/hid/hid-magicmouse.c 18 | +++ b/drivers/hid/hid-magicmouse.c 19 | @@ -150,6 +150,17 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie 20 | #define J680_TP_RES_Y \ 21 | ((J680_TP_MAX_Y - J680_TP_MIN_Y) / (J680_TP_DIMENSION_Y / 100)) 22 | 23 | +#define J680_ALT_TP_DIMENSION_X (float)16000 24 | +#define J680_ALT_TP_MIN_X -7456 25 | +#define J680_ALT_TP_MAX_X 7976 26 | +#define J680_ALT_TP_RES_X \ 27 | + ((J680_ALT_TP_MAX_X - J680_ALT_TP_MIN_X) / (J680_ALT_TP_DIMENSION_X / 100)) 28 | +#define J680_ALT_TP_DIMENSION_Y (float)10000 29 | +#define J680_ALT_TP_MIN_Y -163 30 | +#define J680_ALT_TP_MAX_Y 9283 31 | +#define J680_ALT_TP_RES_Y \ 32 | + ((J680_ALT_TP_MAX_Y - J680_ALT_TP_MIN_Y) / (J680_ALT_TP_DIMENSION_Y / 100)) 33 | + 34 | #define J213_TP_DIMENSION_X (float)13500 35 | #define J213_TP_MIN_X -6243 36 | #define J213_TP_MAX_X 6749 37 | @@ -311,6 +322,7 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev) 38 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 39 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 40 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 41 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT: 42 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 43 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 44 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 45 | @@ -1204,6 +1216,7 @@ static const struct magicmouse_t2_properties magicmouse_t2_configs[] = { 46 | T2_TOUCHPAD_ENTRY(J140K), 47 | T2_TOUCHPAD_ENTRY(J132), 48 | T2_TOUCHPAD_ENTRY(J680), 49 | + T2_TOUCHPAD_ENTRY(J680_ALT), 50 | T2_TOUCHPAD_ENTRY(J213), 51 | T2_TOUCHPAD_ENTRY(J214K), 52 | T2_TOUCHPAD_ENTRY(J223), 53 | @@ -1439,6 +1452,7 @@ static int magicmouse_probe(struct hid_device *hdev, 54 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 55 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 56 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 57 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT: 58 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 59 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 60 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 61 | @@ -1471,6 +1485,7 @@ static int magicmouse_probe(struct hid_device *hdev, 62 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 63 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 64 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 65 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT: 66 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 67 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 68 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 69 | @@ -1552,6 +1567,7 @@ static int magicmouse_probe(struct hid_device *hdev, 70 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 71 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 72 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 73 | + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT: 74 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 75 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 76 | case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 77 | @@ -1659,6 +1675,8 @@ static const struct hid_device_id magic_mice[] = { 78 | USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), .driver_data = 0 }, 79 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 80 | USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), .driver_data = 0 }, 81 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 82 | + USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), .driver_data = 0 }, 83 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 84 | USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), .driver_data = 0 }, 85 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 86 | -- 87 | 2.43.0 88 | 89 | -------------------------------------------------------------------------------- /7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch: -------------------------------------------------------------------------------- 1 | From: Ashish Arora 2 | Subject: Re: [PATCH] drm/i915: Discard large BIOS framebuffers causing display corruption. 3 | Date: Sat, 08 Jan 2022 21:43:18 +1100 4 | 5 | On certain 4k panels, the BIOS framebuffer is larger than what panel 6 | requires causing display corruption. Introduce a check for the same. 7 | 8 | Signed-off-by: Ashish Arora 9 | --- 10 | drivers/gpu/drm/i915/display/intel_fbdev.c | 6 +++--- 11 | 1 file changed, 3 insertions(+), 3 deletions(-) 12 | 13 | diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c 14 | index 49a1ac4f549195..c8c10a6104c4e9 100644 15 | --- a/drivers/gpu/drm/i915/display/intel_fbdev.c 16 | +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c 17 | @@ -199,10 +199,10 @@ static int intelfb_create(struct drm_fb_helper *helper, 18 | ifbdev->fb = NULL; 19 | 20 | if (fb && 21 | - (sizes->fb_width > fb->base.width || 22 | - sizes->fb_height > fb->base.height)) { 23 | + (sizes->fb_width != fb->base.width || 24 | + sizes->fb_height != fb->base.height)) { 25 | drm_dbg_kms(&dev_priv->drm, 26 | - "BIOS fb too small (%dx%d), we require (%dx%d)," 27 | + "BIOS fb not valid (%dx%d), we require (%dx%d)," 28 | " releasing it\n", 29 | fb->base.width, fb->base.height, 30 | sizes->fb_width, sizes->fb_height); 31 | -- 32 | 1.8.3.1 33 | 34 | -------------------------------------------------------------------------------- /8002-Necessary-modifications-to-build-APFS-with-the-kerne.patch: -------------------------------------------------------------------------------- 1 | From 918ebea43ba3c425e6ffefdbde0db6b55e445b77 Mon Sep 17 00:00:00 2001 2 | From: Aditya Garg <85610623+AdityaGarg8@users.noreply.github.com> 3 | Date: Sun, 10 Nov 2024 15:31:18 +0530 4 | Subject: [PATCH] Necessary modifications to build APFS with the kernel 5 | 6 | --- 7 | fs/Kconfig | 1 + 8 | fs/Makefile | 1 + 9 | fs/apfs/Kconfig | 13 +++++++++++++ 10 | fs/apfs/Makefile | 22 ++-------------------- 11 | 4 files changed, 17 insertions(+), 20 deletions(-) 12 | create mode 100644 fs/apfs/Kconfig 13 | 14 | diff --git a/fs/Kconfig b/fs/Kconfig 15 | index aae170fc2..5131d5b3c 100644 16 | --- a/fs/Kconfig 17 | +++ b/fs/Kconfig 18 | @@ -321,6 +321,7 @@ source "fs/affs/Kconfig" 19 | source "fs/ecryptfs/Kconfig" 20 | source "fs/hfs/Kconfig" 21 | source "fs/hfsplus/Kconfig" 22 | +source "fs/apfs/Kconfig" 23 | source "fs/befs/Kconfig" 24 | source "fs/bfs/Kconfig" 25 | source "fs/efs/Kconfig" 26 | diff --git a/fs/Makefile b/fs/Makefile 27 | index 61679fd58..8a17c50d7 100644 28 | --- a/fs/Makefile 29 | +++ b/fs/Makefile 30 | @@ -120,6 +120,7 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/ 31 | obj-$(CONFIG_TRACING) += tracefs/ 32 | obj-$(CONFIG_OCFS2_FS) += ocfs2/ 33 | obj-$(CONFIG_BTRFS_FS) += btrfs/ 34 | +obj-$(CONFIG_APFS_FS) += apfs/ 35 | obj-$(CONFIG_GFS2_FS) += gfs2/ 36 | obj-$(CONFIG_F2FS_FS) += f2fs/ 37 | obj-$(CONFIG_BCACHEFS_FS) += bcachefs/ 38 | diff --git a/fs/apfs/Kconfig b/fs/apfs/Kconfig 39 | new file mode 100644 40 | index 000000000..99caf203a 41 | --- /dev/null 42 | +++ b/fs/apfs/Kconfig 43 | @@ -0,0 +1,13 @@ 44 | +# SPDX-License-Identifier: GPL-2.0-only 45 | +config APFS_FS 46 | + tristate "Apple file system support" 47 | + select LIBCRC32C 48 | + select ZLIB_INFLATE 49 | + select NLS 50 | + select BUFFER_HEAD 51 | + select FS_IOMAP 52 | + select LEGACY_DIRECT_IO 53 | + help 54 | + If you say Y here, you will be able to mount APFS partitions 55 | + with read-only access. Write access is experimental and will 56 | + corrupt your container. 57 | diff --git a/fs/apfs/Makefile b/fs/apfs/Makefile 58 | index a2dbed980..bc7bc8cc5 100644 59 | --- a/fs/apfs/Makefile 60 | +++ b/fs/apfs/Makefile 61 | @@ -1,28 +1,10 @@ 62 | # SPDX-License-Identifier: GPL-2.0-only 63 | # 64 | -# Makefile for the out-of-tree Linux APFS module. 65 | +# Makefile for the Linux APFS module. 66 | # 67 | 68 | -KERNELRELEASE ?= $(shell uname -r) 69 | -KERNEL_DIR ?= /lib/modules/$(KERNELRELEASE)/build 70 | -PWD := $(shell pwd) 71 | - 72 | -obj-m = apfs.o 73 | +obj-$(CONFIG_APFS_FS) = apfs.o 74 | apfs-y := btree.o compress.o dir.o extents.o file.o inode.o key.o libzbitmap.o \ 75 | lzfse/lzfse_decode.o lzfse/lzfse_decode_base.o lzfse/lzfse_fse.o \ 76 | lzfse/lzvn_decode_base.o message.o namei.o node.o object.o snapshot.o \ 77 | spaceman.o super.o symlink.o transaction.o unicode.o xattr.o xfield.o 78 | - 79 | -# If you want mounts to be writable by default, run the build as: 80 | -# make CONFIG=-DCONFIG_APFS_RW_ALWAYS 81 | -# This is risky and not generally recommended. 82 | -ccflags-y += $(CONFIG) 83 | - 84 | -default: 85 | - ./genver.sh 86 | - make -C $(KERNEL_DIR) M=$(PWD) 87 | -install: 88 | - make -C $(KERNEL_DIR) M=$(PWD) modules_install 89 | -clean: 90 | - rm -f version.h 91 | - make -C $(KERNEL_DIR) M=$(PWD) clean 92 | -- 93 | 2.39.5 (Apple Git-154) 94 | 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | linux-t2-patches 2 | ======== 3 | 4 | Patches for T2 Macs 5 | -------------------------------------------------------------------------------- /apfs_ver: -------------------------------------------------------------------------------- 1 | CURRENT_HASH=7d8dc8821e4177ead41d17c298d777df3bfc1c3f 2 | RELEASE_VER=0.3.14-1 3 | -------------------------------------------------------------------------------- /extra_config: -------------------------------------------------------------------------------- 1 | CONFIG_APPLE_BCE=m 2 | CONFIG_APPLE_GMUX=m 3 | CONFIG_BRCMFMAC=m 4 | CONFIG_BT_BCM=m 5 | CONFIG_BT_HCIBCM4377=m 6 | CONFIG_BT_HCIUART_BCM=y 7 | CONFIG_BT_HCIUART=m 8 | CONFIG_HID_APPLETB_BL=m 9 | CONFIG_HID_APPLETB_KBD=m 10 | CONFIG_HID_APPLE=m 11 | CONFIG_HID_MAGICMOUSE=m 12 | CONFIG_DRM_APPLETBDRM=m 13 | CONFIG_DRM_KUNIT_TEST=m 14 | CONFIG_HID_SENSOR_ALS=m 15 | CONFIG_SENSORS_APPLESMC=m 16 | CONFIG_SND_PCM=m 17 | CONFIG_STAGING=y 18 | CONFIG_APFS_FS=m 19 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | KVER=6.15 2 | --------------------------------------------------------------------------------