Change ACPI tables to add HID-over-I2C device?
Hi,
I need to add an entry for a HID-over-I2C device to the ACPI DSDT table.
I noticed that the Up Xtreme is supported by Intel's edk2 firmware project:
https://github.com/tianocore/edk2-platforms/tree/master/Platform/Intel#aaeon
Before I buy an Up Xtreme and try to build edk2, I figured I would ask about existing HID-over-I2C support. Are there any existing HID-over-I2C entries in the stock ACPI table? If so, what is their configuration? (I2C bus, speed, etc).
If there are no existing entries, is it really necessary to build edk2 in order to change the contents of the ACPI DSDT table? (I need to use Windows 10 and not Linux). Is there an easier way to do it?
Thanks!
Comments
-
@razor1000
We don't have existing HID-over-I2C in ACPI table, you can refer Microsoft's document to add ACPI table in test mode https://docs.microsoft.com/en-us/previous-versions/windows/hardware/design/dn642101(v=vs.85)HID-over-I2C spec document you can refer this document https://docs.microsoft.com/en-us/previous-versions/windows/hardware/design/dn642101(v=vs.85)
-
@garyw said:
We don't have existing HID-over-I2C in ACPI table, you can refer Microsoft's document to add ACPI table in test modeDid you mean to link to the HID-over-I2C spec twice?
I am very familiar with the HID-over-I2C spec. I have created a working HID-over-I2C device. I have tested it on Linux and it works fine. Linux allows me to modify the DSDT table and compile the modified table into the kernel. But Windows does not allow that, and I need to certify my HID-over-I2C device on Windows 10.
Is it possible to modify the DSDT table on the UP Xtreme?
-
@razor1000
Sorry for wrong link, you can refer this link to add ACPI in windows https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/enable-usermode-access#compile-and-load-asl-with-acpitabldat -
This is great! It looks like rhproxy is exactly what I need. Thank you!
Can you provide me with the ASL code for the serial busses and GPIOs that are available for use on the UP Xtreme?
Thanks!
-
@razor1000
rhproxy is different with HID-over-I2C, if you just want to access I2C bus, you can through our UpFramework SDK https://downloads.up-community.org/download/up-sdk-for-windows-10-and-windows-iot/windows demo app you can refer this link https://github.com/aaeonaeu/win-demo-apps
if you still want to try rhproxy , you can refer attached patch file for Up Xtreme.
-
@garyw
I received my UP Xtreme board, and I discovered that it is possible to add a custom HID-over-I2C device using the CRB BIOS settings.
This is an even easier method than I had hoped for! I can add a HID-over-I2C device to I2C0 and/or I2C1. So now I just need to know how to connect my device to I2C0 or I2C1, and a GPIO.What I2C bus # are the I2C pins on the eDP connector connected to? Are they 3.3V or 1.8V?
The INT pin used for touchpanels is normally E7; is that routed out somewhere? If not, is there a different pin I can use?
(The interrupt can also come from the NVIC, but I'm not sure how to set that up).Thanks!
-
The following connectors have I2C ports:
- M.2 2280 M-key connector (CN4) - The manual says I2C1, but not clear if that correlates to chipset I2C1 or not.
- EDP connector (CN13) - unclear which chipset port that connects to.
- HAT connector (CN22) - they're labeled I2C1 and I2C0 in the manual, but actually connect to I2C4 and I2C3 on the chipset respectively.
- Docking II connector (CN26) - that one is labeled I2C4 in the manual.
The 2 I2C ports on the HAT connector are definitely I2C3 and I2C4. Hopefully someone at AAEON can fill in / confirm the other I2C ports.
The 2 I2C ports on the HAT connector are definitely 1.8V. The other ones (on M.2, EDP, and Docking II) are probably 1.8V as well since there's no good reason to level shift them, but again, someone at AAEON would need to confirm. The one on the Docking II connector is actually labeled 1V8 in the manual, so that's a pretty safe bet there.
As far as INT, every GPIO pin on the HAT connector can be configured as an INT pin via ACPI overrides. Those are all at 3.3V though via MAX V level shifters.
-
I received my UP Xtreme board, and I discovered that it is possible to add a custom HID-over-I2C device using the CRB BIOS settings.
This is an even easier method than I had hoped for! I can add a HID-over-I2C device to I2C0 and/or I2C1. So now I just need to know how to connect my device to I2C0 or I2C1, and a GPIO.Where did you find that HID-over-I2C setting in BIOS?
-
@jayman said:
Where did you find that HID-over-I2C setting in BIOS?It's in the CRB setup.
Main->
CRB Setup->
CRB Chipset->
PCH-IO Configuration->
SerialIo ConfigurationIf I2C0 and I2C1 are enabled, some options show up in the "Serial IO I2C# Settings" further down.
I2C0 Controller [Enabled]
I2C1 Controller [Enabled]For I2C0, there's settings for a "Touch Pad". There are a couple pre-configured devices, but you can also select "Custom Device", which lets you pick the I2C address, HID descriptor address, and I2C bus speed. Oh, and you can select either APIC or GPIO for the interrupt source.
For I2C1, it's basically the same thing, except it's called "Touch Panel".
Unfortunately there are no options for the other I2C bus numbers, even if they are enabled.Serial IO I2C0 Settings->
Serial IO Touch Pad Settings->
Touch Pad [Custom Device]Touch Pad Interrupt Mode [APIC Interrupt/GPIO Interrupt]
Device's bus address 0
Device's HID address 0
Device's bus speed [100kHz/400kHz/1MHz]Serial IO I2C1 Settings->
Serial IO Touch Panel Settings->
Touch Panel [Custom Device]Touch Panel Interrupt Mode [APIC Interrupt/GPIO Interrupt]
Device's bus address 0
Device's HID address 0
Device's bus speed [100kHz/400kHz/1MHz] -
@jayman said:
The following connectors have I2C ports:- M.2 2280 M-key connector (CN4) - The manual says I2C1, but not clear if that correlates to chipset I2C1 or not.
- EDP connector (CN13) - unclear which chipset port that connects to.
- HAT connector (CN22) - they're labeled I2C1 and I2C0 in the manual, but actually connect to I2C4 and I2C3 on the chipset respectively.
- Docking II connector (CN26) - that one is labeled I2C4 in the manual.
The 2 I2C ports on the HAT connector are definitely I2C3 and I2C4. Hopefully someone at AAEON can fill in / confirm the other I2C ports.
The 2 I2C ports on the HAT connector are definitely 1.8V. The other ones (on M.2, EDP, and Docking II) are probably 1.8V as well since there's no good reason to level shift them, but again, someone at AAEON would need to confirm. The one on the Docking II connector is actually labeled 1V8 in the manual, so that's a pretty safe bet there.
As far as INT, every GPIO pin on the HAT connector can be configured as an INT pin via ACPI overrides. Those are all at 3.3V though via MAX V level shifters.
Just to confirm, the bus that is labeled I2C1 on the HAT connector is definitely I2C4, and it does seem to be at 1.8V. I couldn't confirm which one I2C0 is; I tried it without a shifter, and that wasn't likely to work. I was lucky that writes to the other bus showed up.
I made an ACPITABL.dat for rhproxy that has an entry for all 6 I2C bus numbers. I hooked up a logic analyzer to the pins, and then used I2cTestTool.exe to write to a unique address for each bus, and then I checked which address came through.
It's too bad the CRB BIOS option won't work, but I was planning to use a different method, anyway. I just need to verify that I can override a GPIO entry in the ACPI tables and make it generate an interrupt. I'll probably use rhproxy again to figure out which GPIOs map to which pin numbers in the APCI tables. It's a quick way to check this kind of stuff.
-
Yes, I2C1 on HAT is definitely chipset I2C4, and I2C0 on HAT is definitely chipset I2C3.
You can confirm that in the BIOS setup under Advanced > HAT Configurations. If you toggle I2C3 on/off, pins 27/28 will toggle between I2C and GPIO. Likewise if you toggle I2C4 on/off, pins 3/5 will toggle between I2C and GPIO.
I also have I2C devices attached to the I2C ports on the HAT, and they do respond correctly when I access the chipset I2C3 / I2C4 resources.
-
Just an update: I was able to make GPIOs wiggle with rhproxy and GpioTestTool.exe (I think I compiled it from the sample code that is pointed to in the rhproxy page that is linked above, but I can't remember). I dumped all the ACPI tables with iasl, and the SSDT labeled "PINCTRL" is the one that defines the GPIOs on the HAT connector. I copied the first 14 entries in _CRS section of that file, and put them in the rhproxy ASL file. Rhproxy requires that all GPIOs have a GpioInt entry, as well as a GpioIO entry, and you can't use "PullDefault" for the drive mode, so this is what I used for each pin:
// Entry for GPIO0
GpioIo (Exclusive, PullUp, 0x0000, 0x0000, IoRestrictionNone, "\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,) {0x00A8}
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\_SB.PCI0.GPI0",) { 0x00A8 }This setup worked fine for inputs, but I needed to go into the BIOS Setup and define a pin as "OUTPUT" in order to get a pin to work consistently as an output. To test it, I left GPIO12 as an input, and set GPIO13 as an output (in the BIOS), connected the two with a 10k resistor, and hooked up my Saleae to verify. I opened 2 command windows, and started GpioTestTool.exe in each, connected to GPIO12 as input, and connected GPIO13 (changing it to output in the software). I toggled the state of GPIO13, and GPIO12 reflected the state change each time. A Saleae capture verified that the pins were physically toggling, and that the software wasn't just reading a shadow register value.
The only thing that didn't work using GpioTestTool.exe was interrupts, and I'm hoping that is just a limitation of rhproxy.
So now that I knew the pin mapping in the "PINCTRL" table was correct, I moved on to overriding the ACPI tables using asl.exe.
(Rhproxy is an easy way to check things out, but it only lets you use the SPB driver. I tried adding an entry for a HID-over-I2C device, but it did not show up in device manager).I won't go into detail about the table-override process, because I haven't verified everything works, yet, but the short version is that I made a copy of the "PINCTRL" table, added a HID-over-I2C entry to it, incremented the revision number, and then used asl.exe from the WDK to override the existing table. After a reboot, a banged-out HID-over-I2C device showed up in device manager. When I did a disable/enable of the device, the Saleae trace of the I2C traffic showed the system was trying to talk to the I2C address I specified in the SSDT. So it is looking good!
The next step is to hook up a 3.3V level shifter for my HID-over-I2C, so I need to find an easily-accessible 1.8V reference for the low side of the shifter. (I know where one is, this was just a good stopping point).
For reference, here's some links:
Rhproxy - https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/enable-usermode-access
GpioTestTool source - https://github.com/microsoft/Windows-iotcore-samples/tree/master/BusTools
ASL compiler's table-load feature: https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/microsoft-asl-compiler#using-the-microsoft-asl-compilers-acpi-table-load-feature -
Good stuff!
FYI, the first page you linked states:
The ShareType field of both descriptors must be Shared
I have definitely found this to be true. The GpioClx controller driver would error out on me if that condition was not met. Looks like you had success regardless, but it's probably safer to fix it.
Also, as you already stated, the direction setting for each GPIO pin in the BIOS setup page must match your resource declaration in ACPI. Those are 2 different things. The ACPI config is used by the GpioClx controller driver to configure the actual chipset pin. The direction setting in the BIOS is used to configure the MAX V CPLD, which acts as a level shifter. If the 2 don't match you will not get any good results.
-
@jayman said:
Good stuff!FYI, the first page you linked states:
The ShareType field of both descriptors must be Shared
I have definitely found this to be true. The GpioClx controller driver would error out on me if that condition was not met. Looks like you had success regardless, but it's probably safer to fix it.
Also, as you already stated, the direction setting for each GPIO pin in the BIOS setup page must match your resource declaration in ACPI. Those are 2 different things. The ACPI config is used by the GpioClx controller driver to configure the actual chipset pin. The direction setting in the BIOS is used to configure the MAX V CPLD, which acts as a level shifter. If the 2 don't match you will not get any good results.
Ooo, nice catch. I copied the GpioInt entry from the rhproxy page, but I copied the GpioIo entry for each pin from the "PINCTRL" ACPI table. Maybe that is why the interrupts didn't work inside GpioTestTool.exe.
I finally got my level shifter hooked up, and my HID-over-I2C device successfully enumerates! I need to double-check that the interrupt pin is actually causing interrupts before I declare complete success. (You can successfully enumerate without the pin ever toggling, I think).
I also spent some time and figured out how the pin numbering in the ACPI table works. I found the datasheet for the PCH that is used, and was able to go from the port group letter + pin number from the datasheet to the number in the number in the ACPI table, and they all line up. I'm hoping this will help me track down the GPIOs that are available on the docking port connectors, since the GPIO controller reports that max pins = 40, but there are only 34 pins in the "PINCTRL" table (and 6 of those are not available on the HAT).
-
I have all the mappings between HAT pins and chipset GPIO. Let me know if you need anything.
Regarding GPIO pin numbers, there are hundreds of GPIO pins on the chipset (most of which are multiplexed with other functions and not actually available as GPIO). That said, there are 34 GpioIo resources declared under the ACPI\VEN_AANT&DEV_0F04 device, the first 28 of which are routed to the HAT header (via MAX V CPLD) and the last 6 are used to communicate with and configure the MAX V CPLD. Those last 6 GpioIo resources are not available at the HAT header, only the first 28. Add to that 4 power pins and 8 GND pins and you get a total of 40 pins on that HAT header, so it all works out
The mapping of the "STACK_GPIO[7:1]" pins on the DOCKING II (CN26) connector to chipset pins remains a mystery. This has been asked many times and never addressed by the folks from AAEON. They could possibly map to the ISH_GP[7:1] pins, but that's pure speculation on my part and has never been confirmed. But if they do map in that fashion, that would mean they're available as regular GPIO pins (GPP_A12, GPP_A[17:23]) as long as ISH is disabled in BIOS.
-
@jayman
See below for the STACK_GPIO[7:1] mapping
STACK_GPIO1 = GPP_F0/CNV_PA_BLANKING
STACK_GPIO2 = GPP_F1
STACK_GPIO3 = GPP_F2
STACK_GPIO4 = GPP_F8/CNV_MFUART2_RXD
STACK_GPIO5 = GPP_F9/CNV_MFUART2_TXD
STACK_GPIO6 = GPP_F10
STACK_GPIO7 = GPP_F3 -
Thanks so much for that info Roger! Really appreciate it!
And that's really fantastic news that there are 7 more GPIO pins available for easy end user access.
Do you offer some kind of breakout cable that mates with the CN26 connector? I know you have the one that connects between CN26 and Net Plus / Vision Plus, but that one only carries a few signals and none of the GPIO.
If you don't offer a breakout cable, could you please provide the part number of the mating connector that you on your cable so we can order them and build our own breakout cable?
Thanks again for you support!
-
@Jayman,
Yes, we don't offer a breakout cable for CN26, but you can refer to the information below- Wafer Male connector (CN26) information - CATCH.1204-710-30SMP, 1.00mm pitch connector, 2x15P
- Wafer Female connector information - Housing JCTC. 11002H00-2x15P and Terminal JCTC. 11002TOP-2E
or port that's compatible with CN26 spec
-
Thanks Roger. Could you let me know where we can order those mating (female) connectors?
-
@jayman said:
Thanks Roger. Could you let me know where we can order those mating (female) connectors?I just got some of these today. The housing fits perfectly, although I haven't tried crimping the connectors yet.
JST
SHDR-30V-S-B
CONN HOUSING SHD 30POS 1MM WHITE
https://www.digikey.com/en/products/detail/jst-sales-america-inc/SHDR-30V-S-B/759926JST
SSH-003GA-P0.2
CONN SOCKET 28-32AWG CRIMP GOLD
https://www.digikey.com/en/products/detail/jst-sales-america-inc/SSH-003GA-P0-2/759924 -
I was able to test I2C and GPIO on the DOCKING II connector and I can confirm that the GPIO pin mapping @rogertsai(AAEON) posted above is correct. Also, the I2C port on CN26 connects to chipset I2C0, despite the manual showing it as I2C4.
Both I2C and GPIO are at 1.8 V. SMBus is at 3.3 V.
So in summary:
- CN22.I2C0 --> _SB.PCI0.I2C3
- CN22.I2C1 --> _SB.PCI0.I2C4
- CN26.I2C4 --> _SB.PCI0.I2C0
-
Nice work! Do you have any idea where the I2C1, I2C2, and I2C5 are routed?
According to the manual, one I2C bus is available on the M-keyed NGFF slot (CN4), and one is available on the EDP connector (CN13), but there's no telling which is which.Side question: do you happen to know the I2C address of the ADC?
-
I do not know which I2C bus is routed to CN4 and CN13. Perhaps @rogertsai(AAEON) could provide this information to us?
The resource declaration for the TI ADC081C can be found in ssdt2.asl as follows:
Name (_HID, "ADC081C") // _HID: Hardware ID Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings { Name (UBUF, ResourceTemplate () { I2cSerialBusV2 (0x0054, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.I2C0", 0x00, ResourceConsumer, , Exclusive, ) }) Return (UBUF) /* \_SB_.PCI0.I2C0.ADC0._CRS.UBUF */ }
So I2C slave address 0x54 (in 7-bit notation) on I2C bus 0. I have communicated with that ADC and confirmed the above to be correct.
-
@jayman
The CN4 (M-Key) doesn't have a I2C bus. And the I2C bus 0 is for CN13 (eDP, pin 35 is SCL, pin 36 is SDA) -
@jayman said:
I do not know which I2C bus is routed to CN4 and CN13. Perhaps @rogertsai(AAEON) could provide this information to us?The resource declaration for the TI ADC081C can be found in ssdt2.asl as follows:
Name (_HID, "ADC081C") // _HID: Hardware ID Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings { Name (UBUF, ResourceTemplate () { I2cSerialBusV2 (0x0054, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.I2C0", 0x00, ResourceConsumer, , Exclusive, ) }) Return (UBUF) /* \_SB_.PCI0.I2C0.ADC0._CRS.UBUF */ }
So I2C slave address 0x54 (in 7-bit notation) on I2C bus 0. I have communicated with that ADC and confirmed the above to be correct.
Thanks!
It's strange, your ACPI table is very different from mine. The ADC entry in my tables is in ssdt3 instead of ssdt2, and IASL couldn't dump that table for some reason. I was able to get it with RWEverything, but it looks like this:Scope(\_SB.PCI0.I2C0) { Device(ADC0) { Name(_HID, "ADC081C") Method(_CRS, 0, Serialized) { Name(UBUF, Buffer(0x23) { 0x8E, 0x1E, 0x00, 0x02, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x06, 0x00, 0x80, 0x1A, 0x06, 0x00, 0x54, 0x00, 0x5C, 0x5F, 0x53, 0x42, 0x2E, 0x50, 0x43, 0x49, 0x30, 0x2E, 0x49, 0x32, 0x43, 0x30, 0x00, 0x79, 0x00 }) Return(UBUF) } Method(_STA, 0, NotSerialized) { If(LEqual(ADCE, One)) { Return(0x0F) } Else { Return(Zero) } } } }
What software tool did you use to dump your tables?
-
@rogertsai(AAEON) said:
@jayman
The CN4 (M-Key) doesn't have a I2C bus.The manual says it does (pins 40/42). Is that not correct?
-
@jayman
Yes, it's wrong to I2C (pin 40, 42) , these pins are NC and no signal connection -
I use
acpidump -b
to pull the ACPI tables and create the .dat files. On the UP Xtreme, it creates ssdt.dat and then ssdt1.dat all the way through ssdt10.dat, so 12 SSDTs in total. Perhaps you used a different tool and that's why your file names are off by one.You are correct, the Intel compiler will not disassemble ssdt2.dat:
D:\>iasl -df ssdt2.dat Intel ACPI Component Architecture ASL+ Optimizing Compiler/Disassembler version 20210105 Copyright (c) 2000 - 2021 Intel Corporation File appears to be binary: found 1214 non-ASCII characters, disassembling Binary file does not contain a valid ACPI table
However, the MS compiler has no problem with it:
D:\>asl /u /ResDecode ssdt2.dat Microsoft ACPI Source Language Assembler Version 5.0.0NT Copyright (c) 1996,2014 Microsoft Corporation Compliant with the ACPI 5.0 Specification
Here's the full content of the resulting ssdt2.asl file for your reference:
// CreatorID=INTL CreatorRev=20.16.1319 // FileLength=181 FileChkSum=0x1a DefinitionBlock("ssdt2.dat", "SSDT", 0x01, "AAEON", "ADC081C", 0x00000001) { If(Zero) { External(_SB_.PCI0.I2C0, DeviceObj, UnknownObj) External(ADCE, UnknownObj, UnknownObj) } Scope(\_SB_.PCI0.I2C0) { Device(ADC0) { Name(_HID, "ADC081C") Method(_CRS, 0x0, Serialized) { Name(UBUF, ResourceTemplate() { I2CSerialBusV2(0x54, ControllerInitiated, 0x61a80, AddressingMode7Bit, "\\_SB.PCI0.I2C0", 0, ResourceConsumer, , Exclusive, ) }) Return(UBUF) } Method(_STA, 0x0, NotSerialized) { If(LEqual(ADCE, One)) { Return(0xf) } Else { Return(Zero) } } } } }
-
@rogertsai(AAEON) said:
@jayman
See below for the STACK_GPIO[7:1] mapping
STACK_GPIO1 = GPP_F0/CNV_PA_BLANKING
STACK_GPIO2 = GPP_F1
STACK_GPIO3 = GPP_F2
STACK_GPIO4 = GPP_F8/CNV_MFUART2_RXD
STACK_GPIO5 = GPP_F9/CNV_MFUART2_TXD
STACK_GPIO6 = GPP_F10
STACK_GPIO7 = GPP_F3What are the Linux GPIO numbers and ACPI references for these GPP_Fx ?
-
@RFitzgerald said:
@rogertsai(AAEON) said:
@jayman
See below for the STACK_GPIO[7:1] mapping
STACK_GPIO1 = GPP_F0/CNV_PA_BLANKING
STACK_GPIO2 = GPP_F1
STACK_GPIO3 = GPP_F2
STACK_GPIO4 = GPP_F8/CNV_MFUART2_RXD
STACK_GPIO5 = GPP_F9/CNV_MFUART2_TXD
STACK_GPIO6 = GPP_F10
STACK_GPIO7 = GPP_F3What are the Linux GPIO numbers and ACPI references for these GPP_Fx ?
I don't know what the Linux GPIO numbers are, but this is what I have for the ACPI pin numbers:
GPP_F0 128
GPP_F1 129
GPP_F2 130
GPP_F3 131
GPP_F8 136
GPP_F9 137
GPP_F10 138