diff mbox series

PCI: loongson: Add quirk for OHCI device rev 0x02

Message ID 20250121114225.2727684-1-chenhuacai@loongson.cn (mailing list archive)
State New
Delegated to: Krzysztof Wilczyński
Headers show
Series PCI: loongson: Add quirk for OHCI device rev 0x02 | expand

Commit Message

Huacai Chen Jan. 21, 2025, 11:42 a.m. UTC
The OHCI controller (rev 0x02) under LS7A PCI host has a hardware flaw.
MMIO register with offset 0x60/0x64 is treated as legacy PS2-compatible
keyboard/mouse interface, which confuse the OHCI controller. Since OHCI
only use a 4KB BAR resource indeed, the LS7A OHCI controller's 32KB BAR
is wrapped around (the second 4KB BAR space is the same as the first 4KB
internally). So we can add an 4KB offset (0x1000) to the BAR resource as
a workaround.

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 drivers/pci/controller/pci-loongson.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Mingcong Bai Jan. 22, 2025, 3:12 p.m. UTC | #1
Hi Huacai,

在 2025/1/21 19:42, Huacai Chen 写道:
> The OHCI controller (rev 0x02) under LS7A PCI host has a hardware flaw.
> MMIO register with offset 0x60/0x64 is treated as legacy PS2-compatible
> keyboard/mouse interface, which confuse the OHCI controller. Since OHCI
> only use a 4KB BAR resource indeed, the LS7A OHCI controller's 32KB BAR
> is wrapped around (the second 4KB BAR space is the same as the first 4KB
> internally). So we can add an 4KB offset (0x1000) to the BAR resource as
> a workaround.
> 
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>   drivers/pci/controller/pci-loongson.c | 8 ++++++++
>   1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/pci/controller/pci-loongson.c b/drivers/pci/controller/pci-loongson.c
> index bc630ab8a283..977f7b15f3a7 100644
> --- a/drivers/pci/controller/pci-loongson.c
> +++ b/drivers/pci/controller/pci-loongson.c
> @@ -32,6 +32,7 @@
>   #define DEV_LS7A_CONF	0x7a10
>   #define DEV_LS7A_GNET	0x7a13
>   #define DEV_LS7A_EHCI	0x7a14
> +#define DEV_LS7A_OHCI	0x7a24
>   #define DEV_LS7A_DC2	0x7a36
>   #define DEV_LS7A_HDMI	0x7a37
>   
> @@ -144,6 +145,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
>   DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
>   			DEV_LS7A_PCIE_PORT6, loongson_mrrs_quirk);
>   
> +static void loongson_ohci_quirk(struct pci_dev *dev)
> +{
> +	if (dev->revision == 0x2)
> +		dev->resource[0].start += 0x1000;
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_OHCI, loongson_ohci_quirk);
> +
>   static void loongson_pci_pin_quirk(struct pci_dev *pdev)
>   {
>   	pdev->pin = 1 + (PCI_FUNC(pdev->devfn) & 3);

I have tested this patch and can confirm that it fixes USB full-speed 
and low-speed devices (such as keyboards and mice) on ASUS XC-LS3A6M 
boards. The full-/low-speed devices only work consistently with this 
specific patch applied, or at least one of the two full-/low-speed 
devices would not work.

P.S., With more than one SuperSpeed devices plugged in, the issue 
reproduced more reliably, where at least one of the two full-/low-speed 
devices would not work. With three SuperSpeed devices plugged in, 
filling all five downstream facing ports at the back of the board along 
with the two full-/low-speed devices, the issue reproduced consistently.

Similar issues have also been reported by mini PC (NUC) users, but I do 
not own such a device.

Tested-by: Mingcong Bai <jeffbai@aosc.io>

Best Regards,
Mingcong Bai
diff mbox series

Patch

diff --git a/drivers/pci/controller/pci-loongson.c b/drivers/pci/controller/pci-loongson.c
index bc630ab8a283..977f7b15f3a7 100644
--- a/drivers/pci/controller/pci-loongson.c
+++ b/drivers/pci/controller/pci-loongson.c
@@ -32,6 +32,7 @@ 
 #define DEV_LS7A_CONF	0x7a10
 #define DEV_LS7A_GNET	0x7a13
 #define DEV_LS7A_EHCI	0x7a14
+#define DEV_LS7A_OHCI	0x7a24
 #define DEV_LS7A_DC2	0x7a36
 #define DEV_LS7A_HDMI	0x7a37
 
@@ -144,6 +145,13 @@  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
 			DEV_LS7A_PCIE_PORT6, loongson_mrrs_quirk);
 
+static void loongson_ohci_quirk(struct pci_dev *dev)
+{
+	if (dev->revision == 0x2)
+		dev->resource[0].start += 0x1000;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_OHCI, loongson_ohci_quirk);
+
 static void loongson_pci_pin_quirk(struct pci_dev *pdev)
 {
 	pdev->pin = 1 + (PCI_FUNC(pdev->devfn) & 3);