1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2008 Lemote Technology 4 * Copyright (C) 2004 ICT CAS 5 * Author: Li xiaoyu, lixy@ict.ac.cn 6 * 7 * Copyright (C) 2007 Lemote, Inc. 8 * Author: Fuxin Zhang, zhangfx@lemote.com 9 */ 10 #include <linux/init.h> 11 #include <linux/pci.h> 12 13 #include <loongson.h> 14 #include <cs5536/cs5536.h> 15 #include <cs5536/cs5536_pci.h> 16 17 /* PCI interrupt pins 18 * 19 * These should not be changed, or you should consider loongson2f interrupt 20 * register and your pci card dispatch 21 */ 22 23 #define PCIA 4 24 #define PCIB 5 25 #define PCIC 6 26 #define PCID 7 27 28 /* all the pci device has the PCIA pin, check the datasheet. */ 29 static char irq_tab[][5] = { 30 /* INTA INTB INTC INTD */ 31 {0, 0, 0, 0, 0}, /* 11: Unused */ 32 {0, 0, 0, 0, 0}, /* 12: Unused */ 33 {0, 0, 0, 0, 0}, /* 13: Unused */ 34 {0, 0, 0, 0, 0}, /* 14: Unused */ 35 {0, 0, 0, 0, 0}, /* 15: Unused */ 36 {0, 0, 0, 0, 0}, /* 16: Unused */ 37 {0, PCIA, 0, 0, 0}, /* 17: RTL8110-0 */ 38 {0, PCIB, 0, 0, 0}, /* 18: RTL8110-1 */ 39 {0, PCIC, 0, 0, 0}, /* 19: SiI3114 */ 40 {0, PCID, 0, 0, 0}, /* 20: 3-ports nec usb */ 41 {0, PCIA, PCIB, PCIC, PCID}, /* 21: PCI-SLOT */ 42 {0, 0, 0, 0, 0}, /* 22: Unused */ 43 {0, 0, 0, 0, 0}, /* 23: Unused */ 44 {0, 0, 0, 0, 0}, /* 24: Unused */ 45 {0, 0, 0, 0, 0}, /* 25: Unused */ 46 {0, 0, 0, 0, 0}, /* 26: Unused */ 47 {0, 0, 0, 0, 0}, /* 27: Unused */ 48 }; 49 50 int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 51 { 52 int virq; 53 54 if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536) 55 && (PCI_SLOT(dev->devfn) < 32)) { 56 virq = irq_tab[slot][pin]; 57 printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin, 58 virq + LOONGSON_IRQ_BASE); 59 if (virq != 0) 60 return LOONGSON_IRQ_BASE + virq; 61 else 62 return 0; 63 } else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) { /* cs5536 */ 64 switch (PCI_FUNC(dev->devfn)) { 65 case 2: 66 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 67 CS5536_IDE_INTR); 68 return CS5536_IDE_INTR; /* for IDE */ 69 case 3: 70 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 71 CS5536_ACC_INTR); 72 return CS5536_ACC_INTR; /* for AUDIO */ 73 case 4: /* for OHCI */ 74 case 5: /* for EHCI */ 75 case 6: /* for UDC */ 76 case 7: /* for OTG */ 77 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 78 CS5536_USB_INTR); 79 return CS5536_USB_INTR; 80 } 81 return dev->irq; 82 } else { 83 printk(KERN_INFO " strange pci slot number.\n"); 84 return 0; 85 } 86 } 87 88 /* Do platform specific device initialization at pci_enable_device() time */ 89 int pcibios_plat_dev_init(struct pci_dev *dev) 90 { 91 return 0; 92 } 93 94 /* CS5536 SPEC. fixup */ 95 static void loongson_cs5536_isa_fixup(struct pci_dev *pdev) 96 { 97 /* the uart1 and uart2 interrupt in PIC is enabled as default */ 98 pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1); 99 pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1); 100 } 101 102 static void loongson_cs5536_ide_fixup(struct pci_dev *pdev) 103 { 104 /* setting the mutex pin as IDE function */ 105 pci_write_config_dword(pdev, PCI_IDE_CFG_REG, 106 CS5536_IDE_FLASH_SIGNATURE); 107 } 108 109 static void loongson_cs5536_acc_fixup(struct pci_dev *pdev) 110 { 111 /* enable the AUDIO interrupt in PIC */ 112 pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1); 113 114 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0); 115 } 116 117 static void loongson_cs5536_ohci_fixup(struct pci_dev *pdev) 118 { 119 /* enable the OHCI interrupt in PIC */ 120 /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */ 121 pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1); 122 } 123 124 static void loongson_cs5536_ehci_fixup(struct pci_dev *pdev) 125 { 126 u32 hi, lo; 127 128 /* Serial short detect enable */ 129 _rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo); 130 _wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 3), lo); 131 132 /* setting the USB2.0 micro frame length */ 133 pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000); 134 } 135 136 static void loongson_nec_fixup(struct pci_dev *pdev) 137 { 138 unsigned int val; 139 140 pci_read_config_dword(pdev, 0xe0, &val); 141 /* Only 2 port be used */ 142 pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2); 143 } 144 145 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 146 loongson_cs5536_isa_fixup); 147 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC, 148 loongson_cs5536_ohci_fixup); 149 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC, 150 loongson_cs5536_ehci_fixup); 151 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, 152 loongson_cs5536_acc_fixup); 153 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, 154 loongson_cs5536_ide_fixup); 155 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, 156 loongson_nec_fixup); 157