This particular SD controller from O2 / Bayhub only allows dword accesses to its LTR max latency registers: https://github.com/rajatxjain/public_shared/blob/main/OZ711LV2_appnote.pdf Thus add a quirk that saves and restores these registers manually using dword acesses: LTR Max Snoop Latency Register LTR Max No-Snoop Latency Register Signed-off-by: Rajat Jain <rajatja@xxxxxxxxxx> --- drivers/mmc/host/sdhci-pci.h | 1 - drivers/pci/quirks.c | 39 ++++++++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 5e3193278ff9..d47cc0ba7ca4 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -10,7 +10,6 @@ #define PCI_DEVICE_ID_O2_SDS1 0x8421 #define PCI_DEVICE_ID_O2_FUJIN2 0x8520 #define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 -#define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 003950c738d2..b7bd19802744 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5857,3 +5857,42 @@ static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING; } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); + +/* + * Bayhub OZ711LV2 SD controller has an errata that only allows DWORD accesses + * to the LTR max latency registers. Thus need to save and restore these + * registers manually. + */ +static void o2_seabird1_save_ltr(struct pci_dev *dev) +{ + struct pci_cap_saved_state *save_state; + u32 *reg32; + + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); + if (save_state) { + reg32 = &save_state->cap.data[0]; + /* Preserve PCI_LTR_MAX_SNOOP_LAT & PCI_LTR_MAX_NOSNOOP_LAT */ + pci_read_config_dword(dev, 0x234, reg32); + } else { + pci_err(dev, "quirk can't save LTR snoop latency\n"); + } +} + +static void o2_seabird1_restore_ltr(struct pci_dev *dev) +{ + struct pci_cap_saved_state *save_state; + u32 *reg32; + + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); + if (save_state) { + reg32 = &save_state->cap.data[0]; + /* Restore PCI_LTR_MAX_SNOOP_LAT & PCI_LTR_MAX_NOSNOOP_LAT */ + pci_write_config_dword(dev, 0x234, *reg32); + } else { + pci_err(dev, "quirk can't restore LTR snoop latency\n"); + } +} +DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_SEABIRD1, + o2_seabird1_save_ltr); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_SEABIRD1, + o2_seabird1_restore_ltr); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 011f2f1ea5bb..6ed16aa38196 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1717,6 +1717,7 @@ #define PCI_DEVICE_ID_O2_8221 0x8221 #define PCI_DEVICE_ID_O2_8320 0x8320 #define PCI_DEVICE_ID_O2_8321 0x8321 +#define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 #define PCI_VENDOR_ID_3DFX 0x121a #define PCI_DEVICE_ID_3DFX_VOODOO 0x0001 -- 2.34.1.400.ga245620fadb-goog