Message ID | CAPoEpV0ZSidL6aMXvB6LN1uS-3CUHS4ggT8RwFgmkzzCiYJ-XQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | Wrong piix4_smbus address / slow trackpoint on Thinkpad P14s gen 2 (AMD) | expand |
Hi Miroslav, > On Thinkpad P14s gen 2 with AMD (model 21A00003CK, BIOS R1MET43W - 1.13) SMBus > address detection don't work and trackpoint has slow rate (30 Hz) because can't > use SMBus. Email is divided to SMBus and trackpoint section, there are issues in > both modules. Do you think this is this the same issue as described in https://bugzilla.kernel.org/show_bug.cgi?id=214597? Thank you for your detailed analysis! Wolfram
Hello, > Do you think this is this the same issue as described in > https://bugzilla.kernel.org/show_bug.cgi?id=214597 <https://bugzilla.kernel.org/show_bug.cgi?id=214597>? Probably not. > Isn't the interrupt described in the ACPI tables? Probably not. I am just web developer, i am not 100% sure, but i have not seen anything usable in ACPI tables: https://mireq.linuxos.sk/kernel/p14s_gen2_amd_acpi_tables.tar.xz Most important section with SMBus is here: https://lore.kernel.org/all/CAPoEpV0ZSidL6aMXvB6LN1uS-3CUHS4ggT8RwFgmkzzCiYJ-XQ@mail.gmail.com/ This section looked promising: Scope (_SB.I2CB) { Device (TPNL) { Name (_HID, "XXXX0000") // _HID: Hardware ID Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID Name (_S0W, 0x03) // _S0W: S0 Device Wake State Name (HID2, 0x00) Name (POIO, 0x00) Name (SBFB, ResourceTemplate () { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.I2CB", 0x00, ResourceConsumer, _Y0C, Exclusive, ) }) Name (SBFG, ResourceTemplate () { GpioInt (Level, ActiveLow, ExclusiveAndWake, PullNone, 0x0000, "\\_SB.GPIO", 0x00, ResourceConsumer, , ) { // Pin list 0x0005 } }) CreateWordField (SBFB, \_SB.I2CB.TPNL._Y0C._ADR, BADR) // _ADR: Address CreateDWordField (SBFB, \_SB.I2CB.TPNL._Y0C._SPE, SPED) // _SPE: Speed Name (ITML, Package (0x0A) { Package (0x07) { 0x04F3, 0x2A3B, 0x10, 0x01, 0x01, "ELAN901C", 0x01 }, but method _STA returned 0x0 (device not present). There is no activity on pin 5. My device has synaptics trackpoint/touchpad, not elantech. I think, that this section is for touchscreen (not on my device). More infomations to GPIO: Following command does nothing if psmouse is loaded without synaptics_intertouch: gpiomon --num-events=1000 gpiochip0 19 After loading psmouse with intertouch it catches constantly cca 2000 changes/s. There are some changes like two rising / falling edges directly behind each other. I think, that clok is much faster, than gpiomon monitoring speed, catching communication with this command would be useless. I don't know why there is constant communication from trackpoint/touchpad to GPIO 19/20. Maybe some notification mechanism, attention, maybe something which stops after clearing some bit, i dont know. Schematic from Lenovo, documentation or anything useful wold be great, but whithout this i am just guessing. Pins 19/20 should be SCL/SDA of I2C3 (from coreboot, id don't know source of pin description: https://github.com/coreboot/coreboot/blob/cf39336ccfcc363162395bddf65113900aaf19fe/src/soc/amd/cezanne/include/soc/gpio.h#L152
Hello, i think, that SMBus works now pretty good and last problem is screaming interrupt from synaptics (1000 irq/s). I need little help to solve this problem. Little summary first: On this thinkpad is synaptics trackpoint/touchpad connected to PIIX4. To enable RMI4 mode, SMBus driver should support host notify protocol. I have added support of host notify and replaced active waiting transaction with completer + interrupt. Driver is now pretty stable and works way better, than old implementation. For example i2c-detect shows real devices (previous transaction code showed all addresses from 0x1c as active). Patch on following link is still hack, has hardcoded IRQ and supports host notifications and interrupts only on auxiliary port. I can implement other ports later. Patch: https://lore.kernel.org/all/c9b0b147-2907-ff41-4f13-464b3b891c50@wisdomtech.sk/ This patch includes PM register access using MMIO: https://lore.kernel.org/all/20210715221828.244536-1-Terry.Bowman@amd.com/ Now i can load psmouse synaptics_intertouch=1 and everything works great, but it uses 5% CPU and interrupt is called 1000/s. I have changed interrupt from rising edge to active low (it's PCIE, PCIE has active low) and i have many times checked if all interrupt bits are cleared in interrupt request. Yes, they are always cleared. Interrupts are generated only after first touch if i have compiled only F12. If i compile F03, then interrupts are generated immediately after load of psmouse. After unload, interrupts are not generated (i2c-piix4 still loaded). On this machine I2C is accessible using GPIO 19(SCL), 20(SDA). Using kernel thread with RT priority on isolated core i have tried to record pin values on GPIO pins. Latency is too high to record all transferred data. Some state changes are lost (approximately 1/50 bits). Not too low to read reliably all data, but good enough to see what happens at bus level. Here is recorded file: https://mireq.linuxos.sk/kernel/thinkpad_p14s/i2c_scl_sda.xz. Every byte is sample, first bit is SCL, second SDA. Sample rate is cca 500 000 Hz, but often drops under 100 000 (lost bit). On this screenshot is typical activity on bus: https://mireq.linuxos.sk/kernel/thinkpad_p14s/i2c_1.png (pulseview with imported raw file) Zoom to two packet is here: https://mireq.linuxos.sk/kernel/thinkpad_p14s/i2c_2.png First packet is SMBus host notify. Address 0x08 is SMBus host address and 0x58 is address of synaptics (0x2c << 1). Second packet is reading of interrupt status registers. Data 02 is length of interrupt status register (9 bits) and last 2 bytes are zero (idle, when moving cursor, then interrupt status register contains one bit set). Zoomed out: https://mireq.linuxos.sk/kernel/thinkpad_p14s/i2c_3.png Before transaction SMBus slave state machine is disabled and after transaction enabled. If notification is received when state machine is disabled, then device writes only address and don't get response. If driver runs with always enabled slave state machine, then output will contain only notify + read interrupt status pairs and no separate addresses, but with this mode bus collisions occur more often. Here is dmesg output: https://pastebin.com/RdDYHJn0 Cursor is moved until 2862.8, then i have not touched trackpoint. Idle device don't produce bus collisions. Moving cursor produces collisions, but sample rate is stable 100Hz, which is way better, than <40 Hz with PS/2 mode. I don't know how to solve collisions. Maybe they are related to not silenced host notifications. If i were to be optimistic, then i would say that clearing interrupt vector will solve all problems. According old RMI4 documentation, reading from interrupt status register should clear interrupts (status register is cleared), but this don't prevent device form sending host notifications. Maybe exists new way to disable interrupts. I don't know, i have no access to current documentation. My device has this signature: Synaptics, product: TM3471-030, fw id: 3418235 Any help welcome.
diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c index a472489cc..6205f8d65 100644 --- a/drivers/input/mouse/psmouse-smbus.c +++ b/drivers/input/mouse/psmouse-smbus.c @@ -30,8 +30,8 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter) { struct psmouse_smbus_dev *smbdev; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) - return; + //if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) + // return; mutex_lock(&psmouse_smbus_mutex); @@ -196,8 +196,8 @@ static int psmouse_smbus_create_companion(struct device *dev, void *data) if (!adapter) return 0; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) - return 0; + //if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) + // return 0; client = i2c_new_scanned_device(adapter, &smbdev->board, addr_list, NULL); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ffad14280..2f476dce7 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1765,7 +1765,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse, }; const struct i2c_board_info intertouch_board = { I2C_BOARD_INFO("rmi4_smbus", 0x2c), - .flags = I2C_CLIENT_HOST_NOTIFY, + //.flags = I2C_CLIENT_HOST_NOTIFY, }; return psmouse_smbus_init(psmouse, &intertouch_board, diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index 2407ea43d..3eb7193b4 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -281,14 +281,17 @@ static int rmi_smb_probe(struct i2c_client *client, return -ENOMEM; } + //if (!i2c_check_functionality(client->adapter, + // I2C_FUNC_SMBUS_READ_BLOCK_DATA | + // I2C_FUNC_SMBUS_HOST_NOTIFY)) { if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BLOCK_DATA | - I2C_FUNC_SMBUS_HOST_NOTIFY)) { + I2C_FUNC_SMBUS_READ_BLOCK_DATA)) { dev_err(&client->dev, "adapter does not support required functionality\n"); return -ENODEV; } + client->irq = 7; if (client->irq <= 0) { dev_err(&client->dev, "no IRQ provided, giving up\n"); return client->irq ? client->irq : -ENODEV;