Skip to content

Commit

Permalink
usb: pci-quirks: group AMD specific quirk code together
Browse files Browse the repository at this point in the history
A follow on patch will introduce CONFIG_USB_PCI_AMD governing the AMD
quirk and adding its compile time dependency on HAS_IOPORT. In order to
minimize the number of #ifdefs in C files and make that patch easier
to read first group the code together. This is pure code movement
no functional change is intended.

Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Link: https://lore.kernel.org/r/20230911125653.1393895-2-schnelle@linux.ibm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Niklas Schnelle authored and Greg Kroah-Hartman committed Oct 2, 2023
1 parent 80920e2 commit 7ca9f9b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 65 deletions.
119 changes: 60 additions & 59 deletions drivers/usb/host/pci-quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@
#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */

/* ASMEDIA quirk use */
#define ASMT_DATA_WRITE0_REG 0xF8
#define ASMT_DATA_WRITE1_REG 0xFC
#define ASMT_CONTROL_REG 0xE0
#define ASMT_CONTROL_WRITE_BIT 0x02
#define ASMT_WRITEREG_CMD 0x10423
#define ASMT_FLOWCTL_ADDR 0xFA30
#define ASMT_FLOWCTL_DATA 0xBA
#define ASMT_PSEUDO_DATA 0

/* Intel quirk use */
#define USB_INTEL_XUSB2PR 0xD0
#define USB_INTEL_USB2PRM 0xD4
#define USB_INTEL_USB3_PSSEN 0xD8
#define USB_INTEL_USB3PRM 0xDC

/* AMD quirk use */
#define AB_REG_BAR_LOW 0xe0
#define AB_REG_BAR_HIGH 0xe1
Expand Down Expand Up @@ -93,21 +109,6 @@
#define NB_PIF0_PWRDOWN_0 0x01100012
#define NB_PIF0_PWRDOWN_1 0x01100013

#define USB_INTEL_XUSB2PR 0xD0
#define USB_INTEL_USB2PRM 0xD4
#define USB_INTEL_USB3_PSSEN 0xD8
#define USB_INTEL_USB3PRM 0xDC

/* ASMEDIA quirk use */
#define ASMT_DATA_WRITE0_REG 0xF8
#define ASMT_DATA_WRITE1_REG 0xFC
#define ASMT_CONTROL_REG 0xE0
#define ASMT_CONTROL_WRITE_BIT 0x02
#define ASMT_WRITEREG_CMD 0x10423
#define ASMT_FLOWCTL_ADDR 0xFA30
#define ASMT_FLOWCTL_DATA 0xBA
#define ASMT_PSEUDO_DATA 0

/*
* amd_chipset_gen values represent AMD different chipset generations
*/
Expand Down Expand Up @@ -458,50 +459,6 @@ void usb_amd_quirk_pll_disable(void)
}
EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);

static int usb_asmedia_wait_write(struct pci_dev *pdev)
{
unsigned long retry_count;
unsigned char value;

for (retry_count = 1000; retry_count > 0; --retry_count) {

pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);

if (value == 0xff) {
dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
return -EIO;
}

if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
return 0;

udelay(50);
}

dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
return -ETIMEDOUT;
}

void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
{
if (usb_asmedia_wait_write(pdev) != 0)
return;

/* send command and address to device */
pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);

if (usb_asmedia_wait_write(pdev) != 0)
return;

/* send data to device */
pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
}
EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);

void usb_amd_quirk_pll_enable(void)
{
usb_amd_quirk_pll(0);
Expand Down Expand Up @@ -631,6 +588,50 @@ bool usb_amd_pt_check_port(struct device *device, int port)
}
EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);

static int usb_asmedia_wait_write(struct pci_dev *pdev)
{
unsigned long retry_count;
unsigned char value;

for (retry_count = 1000; retry_count > 0; --retry_count) {

pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);

if (value == 0xff) {
dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
return -EIO;
}

if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
return 0;

udelay(50);
}

dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
return -ETIMEDOUT;
}

void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
{
if (usb_asmedia_wait_write(pdev) != 0)
return;

/* send command and address to device */
pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);

if (usb_asmedia_wait_write(pdev) != 0)
return;

/* send data to device */
pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
}
EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);

/*
* Make sure the controller is completely inactive, unable to
* generate interrupts or do DMA.
Expand Down
14 changes: 8 additions & 6 deletions drivers/usb/host/pci-quirks.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,34 @@
#define __LINUX_USB_PCI_QUIRKS_H

#ifdef CONFIG_USB_PCI
void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
bool usb_amd_hang_symptom_quirk(void);
bool usb_amd_prefetch_quirk(void);
void usb_amd_dev_put(void);
bool usb_amd_quirk_pll_check(void);
void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
void sb800_prefetch(struct device *dev, int on);
bool usb_amd_pt_check_port(struct device *device, int port);

void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
void sb800_prefetch(struct device *dev, int on);
bool usb_amd_pt_check_port(struct device *device, int port);
#else
struct pci_dev;
static inline void usb_amd_quirk_pll_disable(void) {}
static inline void usb_amd_quirk_pll_enable(void) {}
static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
static inline void usb_amd_dev_put(void) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
static inline void sb800_prefetch(struct device *dev, int on) {}
static inline bool usb_amd_pt_check_port(struct device *device, int port)
{
return false;
}

static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
#endif /* CONFIG_USB_PCI */

#endif /* __LINUX_USB_PCI_QUIRKS_H */

0 comments on commit 7ca9f9b

Please sign in to comment.