All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Miroslav Bendík" <miroslav.bendik@gmail.com>
To: linux-i2c@vger.kernel.org, linux-input@vger.kernel.org,
	Mario Limonciello <superm1@gmail.com>,
	Andrew Duggan <aduggan@synaptics.com>
Subject: Re: Wrong piix4_smbus address / slow trackpoint on Thinkpad P14s gen 2 (AMD)
Date: Sat, 8 Jan 2022 19:42:27 +0100	[thread overview]
Message-ID: <5fc2c68d-a9df-402a-58b5-fdd531f86b55@gmail.com> (raw)
In-Reply-To: <CAPoEpV0ZSidL6aMXvB6LN1uS-3CUHS4ggT8RwFgmkzzCiYJ-XQ@mail.gmail.com>

Summary of synaptics_intertouch problem on Thinkpad with Ryzen 5850U:

Problem with wrong base address is fixed using this patch:
https://lore.kernel.org/all/20210715221828.244536-1-Terry.Bowman@amd.com/

Second problem is, that RMI4 driver don't work with i2c-piix4, because 
it needs
I2C_FUNC_SMBUS_HOST_NOTIFY. I have added I2C_FUNC_SMBUS_HOST_NOTIFY to
piix4_func and psmouse can be loaded with synaptics_intertouch=1 
parameter. Here
is output with rmi_core debug_flags=0xfffd - https://pastebin.com/xGRHyyXV

Synaptics is on address 0x2c (value 0x58/0x59 in SMBus register, bit 1 
is r/w).
Command i2cdetect -l can see i2c busses:

i2cdetect -l
i2c-3   i2c             AMDGPU DM i2c hw bus 1                  I2C adapter
i2c-10  smbus           SMBus PIIX4 adapter port 2 at 0b00 SMBus adapter
i2c-1   i2c             Synopsys DesignWare I2C adapter         I2C adapter
i2c-8   i2c             AMDGPU DM aux hw bus 3                  I2C adapter
i2c-6   i2c             AMDGPU DM aux hw bus 0                  I2C adapter
i2c-4   i2c             AMDGPU DM i2c hw bus 2                  I2C adapter
i2c-11  smbus           SMBus PIIX4 adapter port 1 at 0b20 SMBus adapter
i2c-2   i2c             AMDGPU DM i2c hw bus 0                  I2C adapter
i2c-0   i2c             Synopsys DesignWare I2C adapter         I2C adapter
i2c-9   smbus           SMBus PIIX4 adapter port 0 at 0b00 SMBus adapter
i2c-7   i2c             AMDGPU DM aux hw bus 2                  I2C adapter
i2c-5   i2c             AMDGPU DM i2c hw bus 3                  I2C adapter

Device is visible on address 0x2c (output when psmouse is loaded with
smbus_intertouch):

i2cdetect -q -y 11
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- 1c -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

I can add this call

i2c_handle_smbus_host_notify(piix4_aux_adapter, 0x2c);

to end of piix4_transaction and i have working touchpad / trackpoint. I can
move, i can click and evhz reports rate 100Hz, which is much better than 
39 with
PS/2 protocol. I know, this is endless loop, which generates on my 
machine 2000
interrupts/s and it can break some features like sleep.

Current state is, that everything works with one exception - cursor moved
/ click interrupt. I don't know which interrupt / pin generates this event.

Now what i have tried:

Interrupt line can be retrieved using ACPI. More informations and links 
to full
ACPI tables are here:
https://lore.kernel.org/all/CAPoEpV0ZSidL6aMXvB6LN1uS-3CUHS4ggT8RwFgmkzzCiYJ-XQ@mail.gmail.com/

I have added this code to end of piix_probe:

retval = devm_request_irq(&dev->dev, dev->irq, piix4_isr, IRQF_SHARED, 
"piix4_smbus", piix4_aux_adapter);
if (!retval) {
     printk(KERN_INFO "smbus Using irq %d\n", dev->irq);
}
else {
     printk(KERN_INFO "smbus No irq %d\n", dev->irq);
}

PCI IRQ is set, because i have added it to PCI quirks (temporary hack).
Synaptics is connected to aux adaptor, i am registering irq wit aux adapter.
I have added InterruptEnable call (bit 0) in SMBUSx02 SMBusControl register
(register numbers are from AMD BKDG
- https://www.amd.com/en/support/tech-docs?keyword=bkdg):

unsigned short piix4_smba = 0xb20;
outb_p(0x01, (0x02 + piix4_smba));

Now i have tried to check SMBusStatus and SMBusSlaveStatus in interrupt 
handler,
but they are not usable. First register is cleared directly in transfer
function, which is called before interrupt handler and second is always 
zero. It
looks, that interrupt is triggered only after data transfer, but not for 
host
notification event from slave.

I have added some print statements, to see, what happended. This code 
dumps registers:

static void piix4_dump_registers(struct i2c_adapter *piix4_adapter, char 
*label)
{
     struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
     unsigned short piix4_smba = adapdata->smba;
     int i;
     u8 d[16];

     for (i = 0; i < 16; ++i) {
         if (i == 2 || i == 7)
             d[i] = 0;
         else
             d[i] = inb_p(i + piix4_smba);
     }

     printk(KERN_INFO "smb registers: %s    %02x%02x ...);
}

There are problems with reading form registers 2 and 7. It breaks 
communication,
i don't know why.

Now this is interrupt handler:

static irqreturn_t piix4_isr(int irq, void *dev_id)
{
     struct i2c_adapter *piix4_adapter = (struct i2c_adapter *)dev_id;
     piix4_dump_registers(piix4_adapter, "isr              ");

     return IRQ_HANDLED;
}

I have added piix4_dump_register after transaction, but before clearing 
status.
Output is on this link: https://pastebin.com/4mLBk0U7

After last line there is no output from RMI4/SMBus. Only this line has 
set 0x0a
register (SMBusSlaveEvent) which looks like event from slave. This line is
generated after transaction, but not from interrupt handler. Interrupt 
is not
called for slave events.

Now i have tried to enable interrupts from slave events. I have added 
this code
to probe function (again, numeric addresses, but i can find numbers 
faster in
reference documentation):

outb_p(0x80, (0x02 + piix4_smba)); // Reset to  SMBusControl
outb_p(0x01, (0x02 + piix4_smba)); // InterruptEnable to SMBusControl
outb_p(inb_p(0x01 + piix4_smba) | 0x02, (0x01 + piix4_smba)); // 
SlaveInit to  SMBusSlaveStatus

outb_p(0x2c << 1, (0x04 + piix4_smba)); // write 0x2c address ?
outb_p(0xff, (0x0a + piix4_smba)); // enable all slave events 
onSMBusSlaveEvent
outb_p(0xff, (0x0b + piix4_smba)); // enable all slave events
outb_p(inb_p(0x08 + piix4_smba) | 0x01, (0x08 + piix4_smba)); // SlaveEnable
outb_p(inb_p(0x08 + piix4_smba) | 0x08, (0x08 + piix4_smba)); // 
SMBusAlertEnable
outb_p(inb_p(0x08 + piix4_smba) | 0x02, (0x08 + piix4_smba)); // 
SMBusShadow1EN
outb_p(inb_p(0x08 + piix4_smba) | 0x04, (0x08 + piix4_smba)); // 
SMBusShadow2EN

I have tried other combinations, but without success. This part of 
documentation
looks like description of SMBus host notify:

SMBusShadow1En. Read-write. Reset: 0. Enable the generation of an 
interrupt or
resume event upon an external SMBus master generating a transaction with an
address that matches the SMBus Shadow 1 register.
SlaveEnable. Read-write. Reset: 0. Enable the generation of an interrupt or
resume event upon an external SMBus master generating a transaction with an
address that matches the host controller slave port of 10h, a command 
field that
matches the SMBus slave control register, and a match of corresponding 
enabled
events.

I don't know how should i exactly interpret this part. I don't know what is
SMBus slave control register. It looks like this part is copied from PIIX4
documentation from intel
(https://www.intel.com/Assets/PDF/datasheet/290562.pdf), but without exact
description how matching works.

I have looked at other options how to retrieve interrupt, for example 
amd_pinctl
GPIO. This looked promising:

cat /sys/kernel/debug/pinctrl/AMDI0030\:00/pingroups
registered pin groups:
group: i2c0
pin 145 (GPIO_145)
pin 146 (GPIO_146)

group: i2c1
pin 147 (GPIO_147)
pin 148 (GPIO_148)

group: i2c2
pin 113 (GPIO_113)
pin 114 (GPIO_114)

group: i2c3
pin 19 (GPIO_19)
pin 20 (GPIO_20)

Pins 19/20 are normally idle, but after loading psmouse with intertouch, 
then
there is constant activity (i can capture cca 2000 evnets/s using gpiomon,
frequency is probably much higher). I don't know if this is usable, but 
looks,
that this is i2c line from synaptics. I have not found interrupt pin.

On this link is output of gpiomon --num-events=5000  gpiochip0 19 20:
https://pastebin.com/B9XamDZA

This is everything, that i know. It thin, that i have forgotten some trivial
call, to unmask interrupt, but really, i don't know what. With working
interrupt, enabling RMI4 over piix4-smbus should be trivial.

  parent reply	other threads:[~2022-01-08 18:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-11 12:14 Wrong piix4_smbus address / slow trackpoint on Thinkpad P14s gen 2 (AMD) Miroslav Bendik
2022-01-05 17:57 ` Miroslav Bendík
2022-01-06 12:57   ` Wolfram Sang
2022-01-06 17:54     ` Miroslav Bendík
2022-01-06 18:27   ` Andrea Ippolito
2022-01-07  5:41     ` Miroslav Bendík
2022-01-06 12:52 ` Wolfram Sang
2022-01-08 18:42 ` Miroslav Bendík [this message]
2022-01-11 12:35   ` Wolfram Sang
2022-02-12 17:42 ` Miroslav Bendík

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5fc2c68d-a9df-402a-58b5-fdd531f86b55@gmail.com \
    --to=miroslav.bendik@gmail.com \
    --cc=aduggan@synaptics.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=superm1@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.