18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004 ICT CAS 48c2ecf20Sopenharmony_ci * Author: Li xiaoyu, ICT CAS 58c2ecf20Sopenharmony_ci * lixy@ict.ac.cn 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology 88c2ecf20Sopenharmony_ci * Author: Fuxin Zhang, zhangfx@lemote.com 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/pci.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <loongson.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* South bridge slot number is set by the pci probe process */ 168c2ecf20Sopenharmony_cistatic u8 sb_slot = 5; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciint pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci int irq = 0; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci if (slot == sb_slot) { 238c2ecf20Sopenharmony_ci switch (PCI_FUNC(dev->devfn)) { 248c2ecf20Sopenharmony_ci case 2: 258c2ecf20Sopenharmony_ci irq = 10; 268c2ecf20Sopenharmony_ci break; 278c2ecf20Sopenharmony_ci case 3: 288c2ecf20Sopenharmony_ci irq = 11; 298c2ecf20Sopenharmony_ci break; 308c2ecf20Sopenharmony_ci case 5: 318c2ecf20Sopenharmony_ci irq = 9; 328c2ecf20Sopenharmony_ci break; 338c2ecf20Sopenharmony_ci } 348c2ecf20Sopenharmony_ci } else { 358c2ecf20Sopenharmony_ci irq = LOONGSON_IRQ_BASE + 25 + pin; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci return irq; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Do platform specific device initialization at pci_enable_device() time */ 428c2ecf20Sopenharmony_ciint pcibios_plat_dev_init(struct pci_dev *dev) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci return 0; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void loongson2e_nec_fixup(struct pci_dev *pdev) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci unsigned int val; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* Configures port 1, 2, 3, 4 to be validate*/ 528c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0xe0, &val); 538c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x4); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* System clock is 48-MHz Oscillator. */ 568c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0xe4, 1 << 5); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic void loongson2e_686b_func0_fixup(struct pci_dev *pdev) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci unsigned char c; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci sb_slot = PCI_SLOT(pdev->devfn); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci printk(KERN_INFO "via686b fix: ISA bridge\n"); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* Enable I/O Recovery time */ 688c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x40, 0x08); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Enable ISA refresh */ 718c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0x01); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* disable ISA line buffer */ 748c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x45, 0x00); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Gate INTR, and flush line buffer */ 778c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x46, 0xe0); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */ 808c2ecf20Sopenharmony_ci /* pci_write_config_byte(pdev, 0x47, 0x20); */ 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* 838c2ecf20Sopenharmony_ci * enable PCI Delay Transaction, Enable EISA ports 4D0/4D1. 848c2ecf20Sopenharmony_ci * enable time-out timer 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x47, 0xe6); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * enable level trigger on pci irqs: 9,10,11,13 908c2ecf20Sopenharmony_ci * important! without this PCI interrupts won't work 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci outb(0x2e, 0x4d1); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* 512 K PCI Decode */ 958c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x48, 0x01); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* Wait for PGNT before grant to ISA Master/DMA */ 988c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x4a, 0x84); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* 1018c2ecf20Sopenharmony_ci * Plug'n'Play 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * Parallel DRQ 3, Floppy DRQ 2 (default) 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x50, 0x0e); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* 1088c2ecf20Sopenharmony_ci * IRQ Routing for Floppy and Parallel port 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * IRQ 6 for floppy, IRQ 7 for parallel port 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x51, 0x76); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* IRQ Routing for serial ports (take IRQ 3 and 4) */ 1158c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x52, 0x34); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* All IRQ's level triggered. */ 1188c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x54, 0x00); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* route PIRQA-D irq */ 1218c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x55, 0x90); /* bit 7-4, PIRQA */ 1228c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x56, 0xba); /* bit 7-4, PIRQC; */ 1238c2ecf20Sopenharmony_ci /* 3-0, PIRQB */ 1248c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x57, 0xd0); /* bit 7-4, PIRQD */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* enable function 5/6, audio/modem */ 1278c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x85, &c); 1288c2ecf20Sopenharmony_ci c &= ~(0x3 << 2); 1298c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x85, c); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci printk(KERN_INFO"via686b fix: ISA bridge done\n"); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic void loongson2e_686b_func1_fixup(struct pci_dev *pdev) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci printk(KERN_INFO"via686b fix: IDE\n"); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* Modify IDE controller setup */ 1398c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 48); 1408c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_COMMAND, 1418c2ecf20Sopenharmony_ci PCI_COMMAND_IO | PCI_COMMAND_MEMORY | 1428c2ecf20Sopenharmony_ci PCI_COMMAND_MASTER); 1438c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x40, 0x0b); 1448c2ecf20Sopenharmony_ci /* legacy mode */ 1458c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x42, 0x09); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */ 1488c2ecf20Sopenharmony_ci /* disable read prefetch/write post buffers */ 1498c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0x02); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* use 3/4 as fifo thresh hold */ 1528c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x43, 0x0a); 1538c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x44, 0x00); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x45, 0x00); 1568c2ecf20Sopenharmony_ci#else 1578c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0xc2); 1588c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x43, 0x35); 1598c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x44, 0x1c); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x45, 0x10); 1628c2ecf20Sopenharmony_ci#endif 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci printk(KERN_INFO"via686b fix: IDE done\n"); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void loongson2e_686b_func2_fixup(struct pci_dev *pdev) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci /* irq routing */ 1708c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void loongson2e_686b_func3_fixup(struct pci_dev *pdev) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci /* irq routing */ 1768c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11); 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic void loongson2e_686b_func5_fixup(struct pci_dev *pdev) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci unsigned int val; 1828c2ecf20Sopenharmony_ci unsigned char c; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* enable IO */ 1858c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_COMMAND, 1868c2ecf20Sopenharmony_ci PCI_COMMAND_IO | PCI_COMMAND_MEMORY | 1878c2ecf20Sopenharmony_ci PCI_COMMAND_MASTER); 1888c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0x4, &val); 1898c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0x4, val | 1); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* route ac97 IRQ */ 1928c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x3c, 9); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x8, &c); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* link control: enable link & SGD PCM output */ 1978c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x41, 0xcc); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* disable game port, FM, midi, sb, enable write to reg2c-2f */ 2008c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x42, 0x20); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* we are using Avance logic codec */ 2038c2ecf20Sopenharmony_ci pci_write_config_word(pdev, 0x2c, 0x1005); 2048c2ecf20Sopenharmony_ci pci_write_config_word(pdev, 0x2e, 0x4710); 2058c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0x2c, &val); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x42, 0x0); 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, 2118c2ecf20Sopenharmony_ci loongson2e_686b_func0_fixup); 2128c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, 2138c2ecf20Sopenharmony_ci loongson2e_686b_func1_fixup); 2148c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 2158c2ecf20Sopenharmony_ci loongson2e_686b_func2_fixup); 2168c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, 2178c2ecf20Sopenharmony_ci loongson2e_686b_func3_fixup); 2188c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, 2198c2ecf20Sopenharmony_ci loongson2e_686b_func5_fixup); 2208c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, 2218c2ecf20Sopenharmony_ci loongson2e_nec_fixup); 222