12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21032bce3SWu Zhangjin /* 31032bce3SWu Zhangjin * Copyright (C) 2008 Lemote Technology 41032bce3SWu Zhangjin * Copyright (C) 2004 ICT CAS 51032bce3SWu Zhangjin * Author: Li xiaoyu, lixy@ict.ac.cn 61032bce3SWu Zhangjin * 71032bce3SWu Zhangjin * Copyright (C) 2007 Lemote, Inc. 81032bce3SWu Zhangjin * Author: Fuxin Zhang, zhangfx@lemote.com 91032bce3SWu Zhangjin */ 101032bce3SWu Zhangjin #include <linux/init.h> 111032bce3SWu Zhangjin #include <linux/pci.h> 121032bce3SWu Zhangjin 131032bce3SWu Zhangjin #include <loongson.h> 141032bce3SWu Zhangjin #include <cs5536/cs5536.h> 151032bce3SWu Zhangjin #include <cs5536/cs5536_pci.h> 161032bce3SWu Zhangjin 171032bce3SWu Zhangjin /* PCI interrupt pins 181032bce3SWu Zhangjin * 191032bce3SWu Zhangjin * These should not be changed, or you should consider loongson2f interrupt 201032bce3SWu Zhangjin * register and your pci card dispatch 211032bce3SWu Zhangjin */ 221032bce3SWu Zhangjin 231032bce3SWu Zhangjin #define PCIA 4 241032bce3SWu Zhangjin #define PCIB 5 251032bce3SWu Zhangjin #define PCIC 6 261032bce3SWu Zhangjin #define PCID 7 271032bce3SWu Zhangjin 281032bce3SWu Zhangjin /* all the pci device has the PCIA pin, check the datasheet. */ 2919a8d6b7SLorenzo Pieralisi static char irq_tab[][5] = { 301032bce3SWu Zhangjin /* INTA INTB INTC INTD */ 311032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 11: Unused */ 321032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 12: Unused */ 331032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 13: Unused */ 341032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 14: Unused */ 351032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 15: Unused */ 361032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 16: Unused */ 371032bce3SWu Zhangjin {0, PCIA, 0, 0, 0}, /* 17: RTL8110-0 */ 381032bce3SWu Zhangjin {0, PCIB, 0, 0, 0}, /* 18: RTL8110-1 */ 391032bce3SWu Zhangjin {0, PCIC, 0, 0, 0}, /* 19: SiI3114 */ 401032bce3SWu Zhangjin {0, PCID, 0, 0, 0}, /* 20: 3-ports nec usb */ 411032bce3SWu Zhangjin {0, PCIA, PCIB, PCIC, PCID}, /* 21: PCI-SLOT */ 421032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 22: Unused */ 431032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 23: Unused */ 441032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 24: Unused */ 451032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 25: Unused */ 461032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 26: Unused */ 471032bce3SWu Zhangjin {0, 0, 0, 0, 0}, /* 27: Unused */ 481032bce3SWu Zhangjin }; 491032bce3SWu Zhangjin 5019a8d6b7SLorenzo Pieralisi int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 511032bce3SWu Zhangjin { 521032bce3SWu Zhangjin int virq; 531032bce3SWu Zhangjin 541032bce3SWu Zhangjin if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536) 551032bce3SWu Zhangjin && (PCI_SLOT(dev->devfn) < 32)) { 561032bce3SWu Zhangjin virq = irq_tab[slot][pin]; 571032bce3SWu Zhangjin printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin, 581032bce3SWu Zhangjin virq + LOONGSON_IRQ_BASE); 591032bce3SWu Zhangjin if (virq != 0) 601032bce3SWu Zhangjin return LOONGSON_IRQ_BASE + virq; 611032bce3SWu Zhangjin else 621032bce3SWu Zhangjin return 0; 631032bce3SWu Zhangjin } else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) { /* cs5536 */ 641032bce3SWu Zhangjin switch (PCI_FUNC(dev->devfn)) { 651032bce3SWu Zhangjin case 2: 661032bce3SWu Zhangjin pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 671032bce3SWu Zhangjin CS5536_IDE_INTR); 681032bce3SWu Zhangjin return CS5536_IDE_INTR; /* for IDE */ 691032bce3SWu Zhangjin case 3: 701032bce3SWu Zhangjin pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 711032bce3SWu Zhangjin CS5536_ACC_INTR); 721032bce3SWu Zhangjin return CS5536_ACC_INTR; /* for AUDIO */ 731032bce3SWu Zhangjin case 4: /* for OHCI */ 741032bce3SWu Zhangjin case 5: /* for EHCI */ 751032bce3SWu Zhangjin case 6: /* for UDC */ 761032bce3SWu Zhangjin case 7: /* for OTG */ 771032bce3SWu Zhangjin pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 781032bce3SWu Zhangjin CS5536_USB_INTR); 791032bce3SWu Zhangjin return CS5536_USB_INTR; 801032bce3SWu Zhangjin } 811032bce3SWu Zhangjin return dev->irq; 821032bce3SWu Zhangjin } else { 83*9c9de823SColin Ian King printk(KERN_INFO "strange PCI slot number.\n"); 841032bce3SWu Zhangjin return 0; 851032bce3SWu Zhangjin } 861032bce3SWu Zhangjin } 871032bce3SWu Zhangjin 881032bce3SWu Zhangjin /* Do platform specific device initialization at pci_enable_device() time */ 891032bce3SWu Zhangjin int pcibios_plat_dev_init(struct pci_dev *dev) 901032bce3SWu Zhangjin { 911032bce3SWu Zhangjin return 0; 921032bce3SWu Zhangjin } 931032bce3SWu Zhangjin 941032bce3SWu Zhangjin /* CS5536 SPEC. fixup */ 9528eb0e46SGreg Kroah-Hartman static void loongson_cs5536_isa_fixup(struct pci_dev *pdev) 961032bce3SWu Zhangjin { 971032bce3SWu Zhangjin /* the uart1 and uart2 interrupt in PIC is enabled as default */ 981032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1); 991032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1); 1001032bce3SWu Zhangjin } 1011032bce3SWu Zhangjin 10228eb0e46SGreg Kroah-Hartman static void loongson_cs5536_ide_fixup(struct pci_dev *pdev) 1031032bce3SWu Zhangjin { 1041032bce3SWu Zhangjin /* setting the mutex pin as IDE function */ 1051032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_IDE_CFG_REG, 1061032bce3SWu Zhangjin CS5536_IDE_FLASH_SIGNATURE); 1071032bce3SWu Zhangjin } 1081032bce3SWu Zhangjin 10928eb0e46SGreg Kroah-Hartman static void loongson_cs5536_acc_fixup(struct pci_dev *pdev) 1101032bce3SWu Zhangjin { 1111032bce3SWu Zhangjin /* enable the AUDIO interrupt in PIC */ 1121032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1); 1131032bce3SWu Zhangjin 1141032bce3SWu Zhangjin pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0); 1151032bce3SWu Zhangjin } 1161032bce3SWu Zhangjin 11728eb0e46SGreg Kroah-Hartman static void loongson_cs5536_ohci_fixup(struct pci_dev *pdev) 1181032bce3SWu Zhangjin { 1191032bce3SWu Zhangjin /* enable the OHCI interrupt in PIC */ 1201032bce3SWu Zhangjin /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */ 1211032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1); 1221032bce3SWu Zhangjin } 1231032bce3SWu Zhangjin 12428eb0e46SGreg Kroah-Hartman static void loongson_cs5536_ehci_fixup(struct pci_dev *pdev) 1251032bce3SWu Zhangjin { 1261032bce3SWu Zhangjin u32 hi, lo; 1271032bce3SWu Zhangjin 1281032bce3SWu Zhangjin /* Serial short detect enable */ 1291032bce3SWu Zhangjin _rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo); 130c70798f1SWu Zhangjin _wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 3), lo); 1311032bce3SWu Zhangjin 1321032bce3SWu Zhangjin /* setting the USB2.0 micro frame length */ 1331032bce3SWu Zhangjin pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000); 1341032bce3SWu Zhangjin } 1351032bce3SWu Zhangjin 13628eb0e46SGreg Kroah-Hartman static void loongson_nec_fixup(struct pci_dev *pdev) 1371032bce3SWu Zhangjin { 1381032bce3SWu Zhangjin unsigned int val; 1391032bce3SWu Zhangjin 1401032bce3SWu Zhangjin pci_read_config_dword(pdev, 0xe0, &val); 1411032bce3SWu Zhangjin /* Only 2 port be used */ 1421032bce3SWu Zhangjin pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2); 1431032bce3SWu Zhangjin } 1441032bce3SWu Zhangjin 1451032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 1461032bce3SWu Zhangjin loongson_cs5536_isa_fixup); 1471032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC, 1481032bce3SWu Zhangjin loongson_cs5536_ohci_fixup); 1491032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC, 1501032bce3SWu Zhangjin loongson_cs5536_ehci_fixup); 1511032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, 1521032bce3SWu Zhangjin loongson_cs5536_acc_fixup); 1531032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, 1541032bce3SWu Zhangjin loongson_cs5536_ide_fixup); 1551032bce3SWu Zhangjin DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, 1561032bce3SWu Zhangjin loongson_nec_fixup); 157