mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-01 00:54:15 +08:00
usb: pci-quirks: refactor AMD quirk to abstract AMD chipset types
This patch abstracts out a AMD chipset type which includes southbridge generation and its revision. When os excutes usb_amd_find_chipset_info routine to initialize AMD chipset type, driver will know which kind of chipset is used. This update has below benifits: - Driver is able to confirm which southbridge generations and their revision are used, with chipset detection once. - To describe chipset generations with enumeration types brings better readability. - It's flexible to filter AMD platforms to implement new quirks in future. Signed-off-by: Huang Rui <ray.huang@amd.com> Cc: Andiry Xu <andiry.xu@gmail.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d47aa4536d
commit
22b4f0cd1d
@ -79,11 +79,30 @@
|
|||||||
#define USB_INTEL_USB3_PSSEN 0xD8
|
#define USB_INTEL_USB3_PSSEN 0xD8
|
||||||
#define USB_INTEL_USB3PRM 0xDC
|
#define USB_INTEL_USB3PRM 0xDC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* amd_chipset_gen values represent AMD different chipset generations
|
||||||
|
*/
|
||||||
|
enum amd_chipset_gen {
|
||||||
|
NOT_AMD_CHIPSET = 0,
|
||||||
|
AMD_CHIPSET_SB600,
|
||||||
|
AMD_CHIPSET_SB700,
|
||||||
|
AMD_CHIPSET_SB800,
|
||||||
|
AMD_CHIPSET_HUDSON2,
|
||||||
|
AMD_CHIPSET_BOLTON,
|
||||||
|
AMD_CHIPSET_YANGTZE,
|
||||||
|
AMD_CHIPSET_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct amd_chipset_type {
|
||||||
|
enum amd_chipset_gen gen;
|
||||||
|
u8 rev;
|
||||||
|
};
|
||||||
|
|
||||||
static struct amd_chipset_info {
|
static struct amd_chipset_info {
|
||||||
struct pci_dev *nb_dev;
|
struct pci_dev *nb_dev;
|
||||||
struct pci_dev *smbus_dev;
|
struct pci_dev *smbus_dev;
|
||||||
int nb_type;
|
int nb_type;
|
||||||
int sb_type;
|
struct amd_chipset_type sb_type;
|
||||||
int isoc_reqs;
|
int isoc_reqs;
|
||||||
int probe_count;
|
int probe_count;
|
||||||
int probe_result;
|
int probe_result;
|
||||||
@ -91,6 +110,51 @@ static struct amd_chipset_info {
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(amd_lock);
|
static DEFINE_SPINLOCK(amd_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* amd_chipset_sb_type_init - initialize amd chipset southbridge type
|
||||||
|
*
|
||||||
|
* AMD FCH/SB generation and revision is identified by SMBus controller
|
||||||
|
* vendor, device and revision IDs.
|
||||||
|
*
|
||||||
|
* Returns: 1 if it is an AMD chipset, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
|
||||||
|
{
|
||||||
|
u8 rev = 0;
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_UNKNOWN;
|
||||||
|
|
||||||
|
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
|
||||||
|
PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
|
||||||
|
if (pinfo->smbus_dev) {
|
||||||
|
rev = pinfo->smbus_dev->revision;
|
||||||
|
if (rev >= 0x10 && rev <= 0x1f)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_SB600;
|
||||||
|
else if (rev >= 0x30 && rev <= 0x3f)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_SB700;
|
||||||
|
else if (rev >= 0x40 && rev <= 0x4f)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_SB800;
|
||||||
|
} else {
|
||||||
|
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
||||||
|
PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
|
||||||
|
|
||||||
|
if (!pinfo->smbus_dev) {
|
||||||
|
pinfo->sb_type.gen = NOT_AMD_CHIPSET;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rev = pinfo->smbus_dev->revision;
|
||||||
|
if (rev >= 0x11 && rev <= 0x14)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
|
||||||
|
else if (rev >= 0x15 && rev <= 0x18)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
|
||||||
|
else if (rev >= 0x39 && rev <= 0x3a)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinfo->sb_type.rev = rev;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void sb800_prefetch(struct device *dev, int on)
|
void sb800_prefetch(struct device *dev, int on)
|
||||||
{
|
{
|
||||||
u16 misc;
|
u16 misc;
|
||||||
@ -106,7 +170,6 @@ EXPORT_SYMBOL_GPL(sb800_prefetch);
|
|||||||
|
|
||||||
int usb_amd_find_chipset_info(void)
|
int usb_amd_find_chipset_info(void)
|
||||||
{
|
{
|
||||||
u8 rev = 0;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct amd_chipset_info info;
|
struct amd_chipset_info info;
|
||||||
int ret;
|
int ret;
|
||||||
@ -122,27 +185,17 @@ int usb_amd_find_chipset_info(void)
|
|||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
spin_unlock_irqrestore(&amd_lock, flags);
|
spin_unlock_irqrestore(&amd_lock, flags);
|
||||||
|
|
||||||
info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
|
if (!amd_chipset_sb_type_init(&info)) {
|
||||||
if (info.smbus_dev) {
|
ret = 0;
|
||||||
rev = info.smbus_dev->revision;
|
goto commit;
|
||||||
if (rev >= 0x40)
|
|
||||||
info.sb_type = 1;
|
|
||||||
else if (rev >= 0x30 && rev <= 0x3b)
|
|
||||||
info.sb_type = 3;
|
|
||||||
} else {
|
|
||||||
info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
|
||||||
0x780b, NULL);
|
|
||||||
if (!info.smbus_dev) {
|
|
||||||
ret = 0;
|
|
||||||
goto commit;
|
|
||||||
}
|
|
||||||
|
|
||||||
rev = info.smbus_dev->revision;
|
|
||||||
if (rev >= 0x11 && rev <= 0x18)
|
|
||||||
info.sb_type = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.sb_type == 0) {
|
/* Below chipset generations needn't enable AMD PLL quirk */
|
||||||
|
if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN ||
|
||||||
|
info.sb_type.gen == AMD_CHIPSET_SB600 ||
|
||||||
|
info.sb_type.gen == AMD_CHIPSET_YANGTZE ||
|
||||||
|
(info.sb_type.gen == AMD_CHIPSET_SB700 &&
|
||||||
|
info.sb_type.rev > 0x3b)) {
|
||||||
if (info.smbus_dev) {
|
if (info.smbus_dev) {
|
||||||
pci_dev_put(info.smbus_dev);
|
pci_dev_put(info.smbus_dev);
|
||||||
info.smbus_dev = NULL;
|
info.smbus_dev = NULL;
|
||||||
@ -229,7 +282,9 @@ static void usb_amd_quirk_pll(int disable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
|
if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB800 ||
|
||||||
|
amd_chipset.sb_type.gen == AMD_CHIPSET_HUDSON2 ||
|
||||||
|
amd_chipset.sb_type.gen == AMD_CHIPSET_BOLTON) {
|
||||||
outb_p(AB_REG_BAR_LOW, 0xcd6);
|
outb_p(AB_REG_BAR_LOW, 0xcd6);
|
||||||
addr_low = inb_p(0xcd7);
|
addr_low = inb_p(0xcd7);
|
||||||
outb_p(AB_REG_BAR_HIGH, 0xcd6);
|
outb_p(AB_REG_BAR_HIGH, 0xcd6);
|
||||||
@ -240,7 +295,8 @@ static void usb_amd_quirk_pll(int disable)
|
|||||||
outl_p(0x40, AB_DATA(addr));
|
outl_p(0x40, AB_DATA(addr));
|
||||||
outl_p(0x34, AB_INDX(addr));
|
outl_p(0x34, AB_INDX(addr));
|
||||||
val = inl_p(AB_DATA(addr));
|
val = inl_p(AB_DATA(addr));
|
||||||
} else if (amd_chipset.sb_type == 3) {
|
} else if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 &&
|
||||||
|
amd_chipset.sb_type.rev <= 0x3b) {
|
||||||
pci_read_config_dword(amd_chipset.smbus_dev,
|
pci_read_config_dword(amd_chipset.smbus_dev,
|
||||||
AB_REG_BAR_SB700, &addr);
|
AB_REG_BAR_SB700, &addr);
|
||||||
outl(AX_INDXC, AB_INDX(addr));
|
outl(AX_INDXC, AB_INDX(addr));
|
||||||
@ -353,7 +409,7 @@ void usb_amd_dev_put(void)
|
|||||||
amd_chipset.nb_dev = NULL;
|
amd_chipset.nb_dev = NULL;
|
||||||
amd_chipset.smbus_dev = NULL;
|
amd_chipset.smbus_dev = NULL;
|
||||||
amd_chipset.nb_type = 0;
|
amd_chipset.nb_type = 0;
|
||||||
amd_chipset.sb_type = 0;
|
memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type));
|
||||||
amd_chipset.isoc_reqs = 0;
|
amd_chipset.isoc_reqs = 0;
|
||||||
amd_chipset.probe_result = 0;
|
amd_chipset.probe_result = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user