Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AMD CPU: Waking from suspend doesn't work without external keyboard #80

Open
PandorasFox opened this issue Dec 28, 2019 · 57 comments
Open
Labels
C: bug (upstream) Category: Upstream bug D: Surface Laptop 3 Device: Surface Laptop 3

Comments

@PandorasFox
Copy link

Generally the same overall, with a couple minor differences:

  • Non-optimal firmware image in linux-firmware for the wireless card. The proper image is here and should replace.... /usr/lib/firmware/ath10k/QCA6174L/hw(2.1|3.0)/board(-2).bin. I'll have to check the exact 3-4 files again later.
  • Suspend/etc don't work - I'm assuming this is since the gpelid stuff isn't loaded/configured for the SL3 15".

The second bit is the more annoying bit for right now; I'm not really sure what needs doing to fix that.

@archseer
Copy link
Member

Thanks for the update! I'll include these in the README, as well as the pinctrl_amd module you mentioned here: jakeday/linux-surface#621

For the lid events, I think we just need to find the correct ID for the AMD version:
https://github.com/qzed/linux-surfacegen5-acpi/blob/993b99fa0a6e6b26624d3352e52b7b28bbdf2460/module/surface_sam_sid_gpelid.c#L117-L118

Can you provide me the output of dmidecode? (you might need to install it first from a package)

@archseer
Copy link
Member

Updated the README, keeping this issue open so we can discuss the lid.

@PandorasFox
Copy link
Author

PandorasFox commented Dec 28, 2019

Full dmidecode output - looks like the SKU to DMI match on is Surface_Laptop_3_1873, though I'm not sure how to get the GPE number for the lid (or is that just set dynamically to an unused number?)

wifi_fw.sh - I should probably rewrite this to drop the 'good' fw image somewhere in /usr/local/ so that later uses of this can just copy the file out of there (and then write this as a pacman hook).

@PandorasFox
Copy link
Author

PandorasFox commented Dec 28, 2019

so actually - I don't think that the gpelid stuff is needed for this, since as it is I see the lid in /proc/acpi/button/LID0/ && logind correctly suspends by default on lid close (and if I disable that, then I can verify that the lid state correctly updates from open to closed and vice versa). However, it's the resuming that never works for whatever reason - just suspending from the cli puts the laptop into an unrecoverable state, and it has to be power cycled.

e: similar issues when suspending in a text-only session, so it's not graphics-related, at least.

Also notably, the fn/capslock lights still work in the low-power suspended state

@PandorasFox
Copy link
Author

PandorasFox commented Dec 29, 2019

Alright, so adding acpi_os_name="Windows 2015" to my bootline sorta fixed it - I can now resume, but there's graphical issues/etc and I have to drop to another tty and restart the session. (also apparently it works when it's set to an empty string, will poke at some different values and see what exactly works (I noticed 'Windows 2012' in the acpi tables as well, so that might work differently)

I'll keep poking at it to see if I can sort out the graphical issues with resuming (probably need to disable one of amdgpu/radeon) and report back on that when I get it sorted out totally.

Having a usb keyboard plugged in (hello, yubikey) ((or probably, any USB device)) causes the suspend to fail into a broken state, not for it to succeed once. The xhci device doesn't enter a low-power state quickly enough on the first time; the next time it succeeds. Dunno why.

Quick question before I poke at this more: does resuming on the intel version only work via opening the laptop lid? Or can you just systemctl suspend from a terminal and then mash the keyboard/hit the power button to wake up the laptop?

As it is, there appears to just be no way to resume the 15" SL3 right now.

$ cat /proc/acpi/wakeup
Device  S-state   Status   Sysfs node
$

@archseer
Copy link
Member

So on Intel I'm able to resume by opening the lid or by pressing the power button (though, I had to remap it from shutting down the computer first). I think for the keyboard itself to wake the device, I would have to mark them as a wakeup source somehow

@archseer
Copy link
Member

\cc @qzed since he has a bit more insight on how the system is set up

Was trying to transfer this issue over to linux-surface but I can't transfer from personal -> org sadly

@qzed
Copy link
Member

qzed commented Dec 30, 2019

Quick question before I poke at this more: does resuming on the intel version only work via opening the laptop lid? Or can you just systemctl suspend from a terminal and then mash the keyboard/hit the power button to wake up the laptop?

That should only work via the lid at the moment. Since the keyboard is connected via the EC, you could try to enable wakeup via the EC by running echo enabled | sudo tee /sys/bus/serial/devices/serial0-0/power/wakeup. I think this should work, but the reason that is currently disabled by default is that the EC wakes up the device quite frequently. I think on Windows there are additional checks when the EC signals a wake-interrupt to verify that and optionally put it back to sleep. Unfortunately I haven't found a way to do that on Linux yet.

Not sure what's going wrong with the xhci device.

I don't think that the gpelid stuff is needed for this

As far as I can tell, the AMD variant uses ACPI GPIO interrupt handling for that instead of GPE interrupts (compare SL3 with e.g. SB2 where _L17 is the level-triggered GPE 0x17 event handler). The GPIO is marked as ExclusiveAndWake so I'd expect that it'd work. Maybe configuring it as wake capable is somehow broken/not implemented?

@PandorasFox
Copy link
Author

I unfortunately tried a blanket find | xargs sudo tee one liner to mark every sysfs device as wakeup-enabled, and still couldn't get the device to resume after suspend.

I'm going to experiment over the next few days - I saw one report where suspending/etc on fedora worked fine, so it might be a weird combination kernel+distro stuff, somehow. My userspace stuff is pretty trivial to migrate to a new install so I'll try a fresh arch install (and a fedora install if that fails).

The fact that I see nothing listed in /proc/acpi/wakeup is sorta concerning; I feel like I should at least be seeing the lid or power button (since those should just work out of the box?) or /something/ not dependent on the EC.

@qzed
Copy link
Member

qzed commented Dec 31, 2019

The /proc/acpi/wakeup file isn't really exhaustive. On the SB2 there are also no entries for the power button and lid. The power button isn't really a standard ACPI device but a GPIO interrupt that uses another driver, and the lid has some (although apparently standard) uncommon definition. Usually there should be a link in the ACPI lid definition to the wakeup source (e.g. GPE, not sure how that works on the AMD variant with the GPIOs) which tells Linux to configure that GPE for wake. There will be an entry for that in the wakeup file only if that is specified. Of course MS doesn't do that and that's the reason why there is the gpelid driver, which then has to manually figure out the GPE number and configure that GPE. And of course there's no clean way to add that to the wakeup file outside of the ACPI core, so it doesn't show up there. I suspect that it's similar for GPIOs.

If you want to try something out, you can enable the wakeup on the SSH device (should be /sys/bus/serial/devices/serial0-0/), then manually suspend the EC which will enable the GPIO interrupt and then type on the keyboard and grep dmesg for wake irq triggered and see if anything lines up. I'm not sure if the EC will actually trigger a wakeup interrupt for the keyboard, so that would be a good way to find that out.

To suspend the EC only (without the whole system), you'll need to run the sysfs_rqst.py script. Basically you have to directly send commands to it. To do that you need to set the "suspend" command data here. To re-arm after the IRQ triggered once, you will need to send the "resume" command and then suspend it again (you should probably just adapt the script for that and throw in some functions...). The command are

[  TC,  CID,  IID,  PRI,  SNC,  CDL]
[0x01, 0x15, 0x00, 0x01, 0x01, 0x00]    # suspend
[0x01, 0x16, 0x00, 0x01, 0x01, 0x00]    # resume

@PandorasFox
Copy link
Author

PandorasFox commented Dec 31, 2019

Cool! I watched dmesg --follow in another pane and rubbing the trackpad/keyboard would issue a deluge of surface_sam_ssh serial0-0: wake irq triggered messages (e: and to be clear, no other messages of any kind during that period). So we've got that going for us, at least.

So, there's definitely wake requests being issued, and the device is definitely marked as wakeup-enabled in sysfs at the time I invoke a system suspend - so I'm not really sure about why the irq just isn't waking the kernel properly.

It's been ages since I've had the (mis)fortune of poking at irqs so nothing really jumps out at me currently. There's no obvious issues with the enable_irq_wake setup (though maybe it's worth testing with that force-enabled?).

@qzed
Copy link
Member

qzed commented Dec 31, 2019

I think the enable_irq_wake setup should be correct. At least it wakes my SB2 and I don't see any reason why it shouldn't on the SL3. Have you tried playing around with rtcwake (e.g. rtcwake -m mem -s 5 or something like that, maybe also try freeze instead of mem)? Resume via the power button also doesn't work, right? It kind of looks like there's something else broken.

@PandorasFox
Copy link
Author

PandorasFox commented Dec 31, 2019

so, I actually tried to do an rtc timer -> suspend a couple days ago, but the rtc timer isn't wakeup capable so I can't set rtcwake. (I assumed that this was maybe reasonable for a laptop, and neglected to mention that). Resume via power button also doesn't work, either.

I think that freeze/mem actually do the same suspend, since /sys/power/mem_sleep only lists s2idle - so freeze/mem should just both be going to s2idle, I think.

I've poked through most of these debugging steps; suspending in textmode && the mainline kernel have the same problems, so it's not like there's something broken being done in the module, there's just..... some arcane piece missing that's preventing the laptop from ever resuming, as far as I can tell.

I did notice once or twice that a sleep would fail with cfg80211 or xhci stuff not unloading in time and it would send the system into a broken sleep - but I'm fairly certain that most of the time the suspends are working and it's just failing to resume.

I'll go rebuild my kernel with PM_DEBUG (PM_DEBUG=y by default, nice) and go delve in a bit more deeply to make sure that the errors aren't on the suspend side.

@PandorasFox
Copy link
Author

PandorasFox commented Dec 31, 2019

Alright, so pm_test at the freezer level works fine; devices immediately chokes with the normal symptoms. I'll try to narrow down to a specific module now.

e: after unloading ath10k_pci & its deps, every level of pm_test succeeds. However, once it's set to none, my laptop suspends and then cannot resume - it just sits, waiting for a wakeup. So it looks like there's two issues at hand: wifi sometimes putting the device into a broken sleep, and resuming just not working.

@PandorasFox
Copy link
Author

Resuming by pressing a key on a USB keyboard worked. I'm honestly dumbfounded that this works but not the lid/power button/keyboard (earlier I thought that a usb keyboard was causing suspend issues, but it looks like ath10k was the actual culprit?).

So. That's something; I can at least suspend and wake now, so I can grab suspend logs more easily now.

@qzed
Copy link
Member

qzed commented Jan 1, 2020

so, I actually tried to do an rtc timer -> suspend a couple days ago, but the rtc timer isn't wakeup capable so I can't set rtcwake. (I assumed that this was maybe reasonable for a laptop, and neglected to mention that).

Oh, I kind of though that pretty much every device should support that. Interesting.

I think that freeze/mem actually do the same suspend, since /sys/power/mem_sleep only lists s2idle - so freeze/mem should just both be going to s2idle, I think.

I somehow thought they'd be a bit different but after looking at the docs it seems you are right, sorry.

e: after unloading ath10k_pci & its deps, every level of pm_test succeeds. However, once it's set to none, my laptop suspends and then cannot resume - it just sits, waiting for a wakeup. So it looks like there's two issues at hand: wifi sometimes putting the device into a broken sleep, and resuming just not working.

Yeah, that sounds like two different issues.

Resuming by pressing a key on a USB keyboard worked. I'm honestly dumbfounded that this works but not the lid/power button/keyboard

Okay, so that's definitely weird. Can you wake the device via the power button if you have the USB keyboard connected (that could then be an issue with some XHCI driver not suspending correctly if nothing is attached, but I kind-of doubt that)?

Also the power button does work while powered on, right? I'm just wondering if the power button uses a different driver. The MSHW0040-based power-button driver that is used on the other devices does also use GPIO interrupts (same as the lid), so maybe something isn't working correctly in some GPIO core driver and GPIO interrupts can't wake the devices. That'd at least be a connection. Based on the DSDT it should use MSHW0040. To make absolutely sure it uses the same driver as the previous models you can modprobe -r soc_button_array and test it while the device is on.

@PandorasFox
Copy link
Author

Okay, so that's definitely weird. Can you wake the device via the power button if you have the USB keyboard connected

It doesn't (as far as I can tell only a USB device works (on either the A port or the C port; same keyboard using different cables), but weirdly, as soon as the laptop resumes, it will poweroff, as if I pressed the power button as soon as the device woke - so maybe whatever handles the power button / lid aren't being suspended properly? Dunno what's wrong with the keyboard, though.

Also the power button does work while powered on, right?

Yeah; I haven't configured anything for it so normally pressing it will cause the laptop to just immediately shutdown.

To make absolutely sure it uses the same driver as the previous models you can modprobe -r soc_button_array and test it while the device is on.

Correct; unloading this prevented the power button from doing anything (and then once I reloaded it and pressed the power button, it shut off immediately as normal. Nothing weird with buffered presses like when it was simply suspended).

@qzed
Copy link
Member

qzed commented Jan 1, 2020

So that all kind-of fits together: Power-button, lid, and EC-wake are all GPIO interrupts. And it kind-of looks like those are not handled properly when the device is suspended.

There's probably some (maybe hardware-)logic that keeps track of interrupts (something set-interrupt/clear-interrupt), which would explain the interrupt being detected after resume. So they are detected but don't wake the device.

To be honest, I have absolutely no idea how to debug this. But looks like an issue in the GPIO driver stack.

@PandorasFox
Copy link
Author

Hm, that should lie mostly in pinctrl-amd (which iirc - I needed that for SAM to correctly work in my initrd). Possibly it's just something with dependency load order during suspend, but I'll take a poke through that and see what I can come up with.

@qzed
Copy link
Member

qzed commented Jan 1, 2020

Possibly it's just something with dependency load order during suspend

I think it's probably a bit more than that, looks like an upstream bug. I'll try to have a peek at it.

I'll take a poke through that and see what I can come up with.

Good luck!

@PandorasFox
Copy link
Author

PandorasFox commented Jan 1, 2020

Here's a quick dump from the pinctrl_amd debugfs: gist

(or in a massive collapsible here)

gpiochip0: GPIOs 256-511, parent: platform/AMDI0030:00, AMDI0030:00:
GPIO bank0	pin0	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin1	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin2	Edge trigger| Active low| interrupt is enabled| interrupt is masked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x5ea00
pin3	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin4	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin5	Edge trigger| Active high| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x24f860
pin6	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin7	Edge trigger| Active high| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x4f860
pin8	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin9	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is low| output is enabled| 0x840000
pin10	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin11	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x53ce3
pin12	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin13	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x11ce3
pin14	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x11ce3
pin15	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin16	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin17	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin18	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin19	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin20	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin21	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin22	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x14fc60
pin23	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x4fc60
pin24	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin25	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin26	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin27	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240000
pin28	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin29	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin30	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin31	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin32	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin33	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin34	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin35	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin36	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin37	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin38	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin39	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin40	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin41	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin42	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin43	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin44	Edge trigger| Active high| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x3800
pin45	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin46	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin47	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin48	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin49	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin50	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin51	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin52	Level trigger| Active high| interrupt is enabled| interrupt is masked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0xe900
pin53	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin54	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin55	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin56	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin57	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin58	Level trigger| Active high| interrupt is enabled| interrupt is masked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0xe900
pin59	Level trigger| Active high| interrupt is enabled| interrupt is masked| enable wakeup in S0i3 state| enable wakeup in S3 state|
 enable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0xe900
pin60	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin61	Level trigger| Active high| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x3900
pin62	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
GPIO bank1	pin64	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin65	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin66	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin67	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40800
pin68	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240000
pin69	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is low| output is enabled| 0x840000
pin70	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin71	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin72	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin73	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin74	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin75	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin76	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin77	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin78	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin79	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin80	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin81	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin82	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin83	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin84	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150000
pin85	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin86	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150000
pin87	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin88	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is low| output is enabled| 0x840000
pin89	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin90	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin91	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin92	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin93	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin94	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin95	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin96	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin97	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin98	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin99	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin100	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin101	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin102	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin103	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin104	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin105	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin106	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin107	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin108	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin109	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin110	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin111	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin112	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin113	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin114	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin115	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin116	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
pin117	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin118	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin119	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin120	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50800
pin121	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin122	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin123	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin124	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin125	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin126	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin127	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
GPIO bank2	pin128	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin129	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150000
pin130	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin131	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin132	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin133	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin134	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin135	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40800
pin136	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin137	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40800
pin138	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin139	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state|     pull-up is disabled| Pull-down is disabled| output is high| output is enabled| 0xc50000
pin140	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| pull-down is enabled|   output is disabled| 0x240800
pin141	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin142	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x150800
pin143	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
pin144	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
pin145	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin146	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin147	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin148	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin149	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin150	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin151	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin152	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin153	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin154	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin155	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin156	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin157	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin158	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin159	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin160	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin161	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin162	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin163	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin164	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin165	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin166	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin167	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin168	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin169	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin170	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin171	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin172	Level trigger| Active high| interrupt is enabled| interrupt is masked| enable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x2900
pin173	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin174	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin175	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x10000
pin176	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin177	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin178	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin179	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin180	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin181	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin182	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x10000
pin183	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x10000
GPIO bank3	pin192	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin193	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin194	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin195	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin196	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin197	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin198	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin199	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin200	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin201	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin202	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin203	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin204	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin205	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin206	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin207	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin208	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin209	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin210	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin211	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin212	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin213	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin214	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin215	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin216	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin217	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin218	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin219	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin220	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin221	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin222	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0
pin223	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
 disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x0

So normally, only the following pins are wakeup enabled in s0: 2, 5, 7, 11, 22, 23, 44, 52, 58, 59, 61, 172


I grabbed the gpio states with the lid open & closed and got the following diff:

--- /tmp/gpio_lid_open	2020-01-01 15:42:01.157652893 -0800
+++ /tmp/gpio_lid_close	2020-01-01 15:42:14.970985511 -0800
@@ -46,3 +46,3 @@
 pin22	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
- enable wakeup in S4/S5 state| input is low| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x14fc60
+ enable wakeup in S4/S5 state| input is high| 4k pull-up| pull-up is enabled| Pull-down is disabled|   output is disabled| 0x15fc60
 pin23	Edge trigger| Active on both| interrupt is enabled| interrupt is unmasked| enable wakeup in S0i3 state| enable wakeup in S3 state|
@@ -148,5 +148,5 @@
 pin74	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
- disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40800
+ disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
 pin75	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
- disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40800
+ disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50800
 pin76	Edge trigger| Active high| interrupt is enabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
@@ -184,3 +184,3 @@
 pin92	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|
- disable wakeup in S4/S5 state| input is low|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x40000
+ disable wakeup in S4/S5 state| input is high|   pull-up is disabled| Pull-down is disabled|   output is disabled| 0x50000
 pin93	    interrupt is disabled| interrupt is masked| disable wakeup in S0i3 state| disable wakeup in S3 state|

It's not entirely yet clear to me how to easily figure out which pins map to what / how the module (un)masks/enables interrupts on them, but it should be possible to jankily force the lid into working, at least, I think. (iirc they come from the acpi tables?)

@qzed
Copy link
Member

qzed commented Jan 2, 2020

It's not entirely yet clear to me how to easily figure out which pins map to what

AFAIK the ACPI pin number is the pin offset of the chip plus the pin number local to the chip. But I don't really know more than that. Never looked into that stuff before (pinctrl drivers and IRQ implementations, that is).

@PandorasFox
Copy link
Author

filed an upstream bug with hopefully enough information.

As best I can tell, the interrupts/wakeups for gpio pins comes from the acpi tables; I'm not sure why pins 74/75 are masked - my guess is that whatever underlying bug there is might just be causing the interrupts to be masked during suspend so that the irqs never fire.

@PandorasFox
Copy link
Author

PandorasFox commented Jan 4, 2020

I haven't really been able to figure out too much over the past few days, but I did notice a couple things:

One curious thing I've noticed recently is that although pinctrl_amd is loaded, I never actually see anything from it in dmesg - i.e. no "amd gpio driver loaded", but the info from the gpio debugfs is definitely what's printed by the pinctrl amd module.

Also one other curious line:

[ 1.037163] hpet_acpi_add: no address or irqs in _CRS

So, I'm thinking this may actually just be an acpi bug - something that microsoft works around in their drivers (I poked through the SL3A windows driver/firmware package and they do have a specific GPIO controller driver for it - so maybe rather than fix the acpi tables, they just have a driver override?). In which case, I may just try to patch the acpi tables and load a manual dsdt override to handle this.

Really hoping this isn't the case, and I really hope that Microsoft would at least just fix their own device's acpi table instead of doing this, but who knows?

Will do some more debugging into the acpi stuff now, I guess, since gpio was more or less a dead end.

Also, I did verify that I have the latest firmware for everything (pulled the windows drivers/firmware msi, extracted everything, checked versions), so it's also not something that's been fixed already.

@qzed
Copy link
Member

qzed commented Jan 8, 2020

Really hoping this isn't the case, and I really hope that Microsoft would at least just fix their own device's acpi table instead of doing this, but who knows?

I'd hope so, too...

I never actually see anything from it in dmesg - i.e. no "amd gpio driver loaded", but the info from the gpio debugfs is definitely what's printed by the pinctrl amd module.

Maybe debug output isn't enabled yet when that loads? Tbh. I haven't used the dbg prints often as I'm too lazy to always re-enable that and just use dev_info etc. while testing, so not sure about that.

[ 1.037163] hpet_acpi_add: no address or irqs in _CRS

HPET is High Precison Event Timer, so I'd assume that it should normally have an IRQ. No idea if that's connected, but might also be a symptom of the root cause. Seems at least non-standard. Or some weird edge-case in the standard that only MS uses.

If you find a fix via ACPI let me know. I'm sure we can somehow figure out how to transfer that in kernel code.

@qzed
Copy link
Member

qzed commented Jan 8, 2020

Also if no one responds to your bug, you could try and ask on the linux-gpio mailing list directly. According to ./scripts/get_maintainer.pl you could also CC Linus Walleij <linus.walleij@linaro.org>. Maybe also CC the platform-drivers-x86 list. I think you should get more responses there.

@PandorasFox
Copy link
Author

PandorasFox commented Jan 8, 2020

Maybe debug output isn't enabled yet when that loads? Tbh. I haven't used the dbg prints often as I'm too lazy to always re-enable that and just use dev_info etc. while testing, so not sure about that.

Maybe, though there's also nothing when ignore_loglevel is set, so I'd expect it to print. I don't see a path for it to load, not print that, and not unload. There's definitely something incredibly weird going on with gpio/acpi somewhere in there.

If you find a fix via ACPI let me know. I'm sure we can somehow figure out how to transfer that in kernel code.

Hopefully it doesn't come down to patching the acpi table. If that is the case, then SL3-A users will have to just add an additional initrd image alongside the amd ucode. Not the worst, but it will be uefi-version specific and it's definitely a pain.

Also if no one responds to your bug, you could try and ask on the linux-gpio mailing list directly. According to ./scripts/get_maintainer.pl you could also CC Linus Walleij <linus.walleij@linaro.org>. Maybe also CC the platform-drivers-x86 list. I think you should get more responses there.

Will do all of these later today; I'll try to consolidate all the info a bit better when I do so.

I vaguely know someone on the surface firmware team at msft so I also poked them about this, since having this fixed properly in a firmware update would be great. At the least, they might be able to at least confirm it's a bug, even if it's not fixed ever.

@qzed
Copy link
Member

qzed commented Jan 8, 2020

Maybe, though there's also nothing when ignore_loglevel is set, so I'd expect it to print.

Right, setting that as boot parameter should normally do the trick. I suspect that it's could be somehow due to the GPIO driver loading at a very early stage, but tbh. I don't know and I'm just guessing.

Hopefully it doesn't come down to patching the acpi table. If that is the case, then SL3-A users will have to just add an additional initrd image alongside the amd ucode. Not the worst, but it will be uefi-version specific and it's definitely a pain.

Yeah, this is not a solution that I'd consider acceptable in the long term. I'm sure we can figure something out on how to bring a fix into the kernel as some kind of quirk once we've got a better idea of why this is happening and how a fix would look like as ACPI patch.

@PandorasFox
Copy link
Author

PandorasFox commented Jan 8, 2020

Some good news: I can patch the acpi table to have it always make a notify () request in the LID0 handler, and the laptop will now always wake immediately upon a suspend!

If I understand the SL3-I table correctly, it has an additional function it calls (ULID or something) that has a bunch of logic and then, at the end, makes a notify() call. I just replaced that with a blind notify(). Hopefully it's possible to replicate the logic in the SL3-I table and have a patched acpi table do this, or to otherwise properly mark the relevant GPIOs in a driver.

(It's also nice that I can definitely somewhat-easily patch my acpi table and poke at this).

The big downside is that, as I understand it, the "correct" solution is usually to just load a patched ACPI table and wait for a firmware update. I sorta doubt we'll see a firmware update fixing this.

I'm going to hold off on soliciting more responses to the kernel bug for now, since I think there's two bugs we're looking at: the gpio bug with the chip not initializing properly (or something to that effect), and the firmware bug with a very janky acpi table. The Gpio bug is probably not directly caused by the acpi shenanigans, but I wouldn't write it off yet.


I'm going to poke through the surface drivers package on windows and see if there's a patched acpi table I can extract and use; hopefully they just patch the acpi table, since that would be an easier starting point.

@qzed
Copy link
Member

qzed commented Jan 10, 2020

Some good news: I can patch the acpi table to have it always make a notify () request in the LID0 handler, and the laptop will now always wake immediately upon a suspend!

Can you upload a diff? If I understand you correctly that solution will cause a loop in ACPI: _LID is always evaluated after a Notify (LID0, 0x80). Thus placing Notify (LID0, 0x80) unconditionally inside of the _LID method will spin in kworker/0:0+kacpi_notify (you could check with top if that's an issue). I'm not sure if this could prevent the device from going to sleep properly. The Notify (LID0, 0x80) in ULID on the SL3-I could be something like a re-check in case something is not ready.

Speaking of not-ready: That can actually be an issue. If the GPIO pin triggers and _LID is queried before the state has been updated, the device will go back to sleep thinking the lid is still closed. That would however not explain why the other as wake configured GPIOs don't wake the device, but as you've mentioned that could be a different issue. If that's the case, I think you should see this message. You could try delaying the state check by inserting a Sleep (1000) at the beginning of _LID.

@PandorasFox
Copy link
Author

Correct on the former - the acpi table is just, frankly, broken on the SL3's November 2019 firmware. I still haven't been able to sufficiently patch the table sufficiently for the wakes to properly be handled.

I did just look and see that there was a firmware update put out on Jan 30th. I'll check tonight and see if that fixes the issue, since that would be incredibly ideal.

@PandorasFox
Copy link
Author

No diffs to the acpi tables. The firmware was built on 2019-12-10 (or at least, that's the timestamp on its 'release' in the fwupd package).

I don't think Microsoft will fix this at a firmware level in any reasonable amount of time, if ever, and I unfortunately don't have the time right now to disassemble windows drivers to figure out exactly how they're handling this, since my stabs in the dark with patching the acpi tables haven't gone anywhere productive.

@k3mist
Copy link

k3mist commented Mar 11, 2020

First off, thank you @qzed @PandorasFox for all the work here. This doesn't help much, but I was unable to wake with external KB attached. I'm not sure if there was anything else I needed to do for that to work but. But AMD SL3 on this update https://www.microsoft.com/en-us/download/details.aspx?id=100428

edit; adding screenshot in case page is updated by microsoft

image

@PandorasFox
Copy link
Author

I didn't try the March 4th firmware since that was after I gave my SL3 to a windows-using friend of mine, but it's odd that you can't wake via an external keyboard.

You might want to go try some of the sleep debugging steps I linked in this comment above and see if you can narrow it down, I guess.

@k3mist
Copy link

k3mist commented Mar 13, 2020

Thanks! I'll take a look when I get some time this coming week hopefully. Everything is working great except suspend.

@qzed
Copy link
Member

qzed commented Mar 13, 2020

I was unable to wake with external KB attached

It could be that you have to enable keyboard/USB wake-ups (see e.g. https://askubuntu.com/questions/848698/wake-up-from-suspend-using-wireless-usb-keyboard-or-mouse-for-any-linux-distro) as they might be disabled by default.

@k3mist
Copy link

k3mist commented Apr 5, 2020

@qzed sorry about the delay. I was able to wake with KB attached (almost). panel backlight comes on, usb has power, kb lights up, but it doesn't make it any further, screen stays black (just powered on). tried to switch to a tty but no go.

i'd be able to debug but i really have no idea what im doing when it comes to this stuff. if theres anything i can do tho more than happy to help

@andysalerno
Copy link

I'm curious if there's been progress toward a fix for this -- right now it's the only issue preventing me from having a perfectly-working Linux experience on my SL3 AMD.
I'd be happy to investigate, if anyone has any tips for where to look (first time hacking on a kernel). Even a very ugly hack would improve the situation, like if there was some way to simulate input from a fake USB device to wake the laptop... anything is better than a forced power cycle.

@archseer
Copy link
Member

None of us own the AMD model sadly. You might be able to get it working if you mess with the DSDT table and write an override.

#80 (comment)

@keplersj
Copy link

keplersj commented Mar 5, 2021

Hi @archseer, sorry to resurrect this thread but I just got an AMD Surface Laptop 3 and would love to see this issue resolved. I don't have a ton of kernel experience, but I have a dump of the the decompiled DSDT with the latest firmware and a diff from it against the DSDT in linux-surface/acpidumps. If someone could point me in the right direction I'd love to help contribute a fix for this!

@coreyberla
Copy link

I've been testing suspend / wake on my Surface Laptop 3 (AMD). On Arch Linux kernel 5.16.16 I am unable to wake, but it's not 100% clear yet if it's from an issue with the AMDGPU driver or related to the above mentioned issues. I can say that I've successfully gone in and out of sleep using just the lid close/open and via commandline / power button on kernel 5.17.

@keplersj
Copy link

I've been running the 5.16 linux-surface kernel for Arch on my machine and have been hibernating to S4 instead of suspending to S3, because AMDGPU fails on S3 with visual corruption on the screen on wakeup. But 5.17 potentially solving this would make sense, I do remember reading that some changes to AMDGPU were added by Valve and AMD for the Steam Deck. Could make sense if those benefit the AMD APU in the Surface Laptops.

@coreyberla
Copy link

Which surface laptop do you have? On SL3 (AMD) I don't have an option for S3 (just s2idle)

@tejasraman
Copy link

has this been fixed yet?

@TannerNelson16
Copy link

Would love to see a fix for this. It's the only reason I keep windows as a dual boot option on my SL3 AMD. That, and maybe the touchscreen...

@k3mist
Copy link

k3mist commented Apr 9, 2023

@qzed @PandorasFox i have working amd sl3 i can provide. are either of you in the US?

@qzed
Copy link
Member

qzed commented Apr 9, 2023

@k3mist Thank you for the offer, but unfortunately I live in Germany.

@KyleGospo
Copy link

KyleGospo commented Apr 9, 2023

@qzed if you're willing to do the work I'm willing to pitch in on shipping to get it to you.

Contact me @k3mist if you go that route

@k3mist
Copy link

k3mist commented Apr 9, 2023

@KyleGospo im ok with that if @qzed is interested

@TannerNelson16
Copy link

@k3mist I could pitch in on shipping as well!

@qzed
Copy link
Member

qzed commented Apr 10, 2023

Alright, I thought a bit about this, but I don't think that (at the moment at least) I'll have the time to properly look into all the issues on this device and do this justice. But thanks to all of you for the offers. Maybe someone else is interested in giving it a try?

@Lopicl
Copy link

Lopicl commented Jun 9, 2023

I would love to see linux properly working on this device, unfortunately i dont know anything about kernel debugging/development so the only thing i can offer is testing. Just sending this message to show interest. Thank you all for the hard work you do!

@TannerNelson16
Copy link

Not sure when it happened, but this pretty much isn't an issue for me any more. Not sure when it happened but I'm pretty happy about it. All that's left is the touch screen for the SL3 AMD

@keplersj
Copy link

Absolutely agree with @TannerNelson16. The Surface Laptop 3 experience has only improved as Valve and AMD have continued to upstream their AMD APU-related code, with stability really taking a step up sometime around the release of kernel 6.2. I don't have touchscreen on my SL3 running Fedora Silverblue, although I'm not complaining. The high GPU memory usage with increased system uptime is a little concerning, with occasional screen tearing and lock up with high uptime. But a restart always resolves it. Sleep/wake is still a problem, but with Gnome configured not to sleep on power, it's not too bad. The lid switch is problematic, although if I recall correctly that is related to the hardware mechanism triggering shutdowns and suspends the kernel isn't aware and not handling.


AMD Surface Laptop 3 running Linux 6.7.9-1.surface.fc39.x86_64 on Fedora Linux 39.20240311.0 (Silverblue).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: bug (upstream) Category: Upstream bug D: Surface Laptop 3 Device: Surface Laptop 3
Projects
None yet
Development

No branches or pull requests