Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Lemote 2F: Add PCI support

PCI support for the Fuloong 2E and Lemote Loongson 2F family machines is
mostly identical with the exception of CS5536 support.

Rename ops-fuloong2e.c to ops-loongson2.c then add the CS5536 support to
share most of the source code among Loongson machines.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: zhangfx@lemote.com
Cc: yanh@lemote.com
Cc: huhb@lemote.com
Cc: Nicholas Mc Guire <hofrat@hofr.at>
Cc: Arnaud Patard <apatard@mandriva.com>
Cc: loongson-dev@googlegroups.com
Cc: linux-mips@linux-mips.org
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Wu Zhangjin and committed by
Ralf Baechle
1032bce3 22c21003

+216 -1
+2 -1
arch/mips/pci/Makefile
··· 28 28 obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o 29 29 obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o 30 30 obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o 31 - obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-fuloong2e.o 31 + obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o 32 + obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o 32 33 obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o 33 34 obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o 34 35 obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
+160
arch/mips/pci/fixup-lemote2f.c
··· 1 + /* 2 + * Copyright (C) 2008 Lemote Technology 3 + * Copyright (C) 2004 ICT CAS 4 + * Author: Li xiaoyu, lixy@ict.ac.cn 5 + * 6 + * Copyright (C) 2007 Lemote, Inc. 7 + * Author: Fuxin Zhang, zhangfx@lemote.com 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the 11 + * Free Software Foundation; either version 2 of the License, or (at your 12 + * option) any later version. 13 + */ 14 + #include <linux/init.h> 15 + #include <linux/pci.h> 16 + 17 + #include <loongson.h> 18 + #include <cs5536/cs5536.h> 19 + #include <cs5536/cs5536_pci.h> 20 + 21 + /* PCI interrupt pins 22 + * 23 + * These should not be changed, or you should consider loongson2f interrupt 24 + * register and your pci card dispatch 25 + */ 26 + 27 + #define PCIA 4 28 + #define PCIB 5 29 + #define PCIC 6 30 + #define PCID 7 31 + 32 + /* all the pci device has the PCIA pin, check the datasheet. */ 33 + static char irq_tab[][5] __initdata = { 34 + /* INTA INTB INTC INTD */ 35 + {0, 0, 0, 0, 0}, /* 11: Unused */ 36 + {0, 0, 0, 0, 0}, /* 12: Unused */ 37 + {0, 0, 0, 0, 0}, /* 13: Unused */ 38 + {0, 0, 0, 0, 0}, /* 14: Unused */ 39 + {0, 0, 0, 0, 0}, /* 15: Unused */ 40 + {0, 0, 0, 0, 0}, /* 16: Unused */ 41 + {0, PCIA, 0, 0, 0}, /* 17: RTL8110-0 */ 42 + {0, PCIB, 0, 0, 0}, /* 18: RTL8110-1 */ 43 + {0, PCIC, 0, 0, 0}, /* 19: SiI3114 */ 44 + {0, PCID, 0, 0, 0}, /* 20: 3-ports nec usb */ 45 + {0, PCIA, PCIB, PCIC, PCID}, /* 21: PCI-SLOT */ 46 + {0, 0, 0, 0, 0}, /* 22: Unused */ 47 + {0, 0, 0, 0, 0}, /* 23: Unused */ 48 + {0, 0, 0, 0, 0}, /* 24: Unused */ 49 + {0, 0, 0, 0, 0}, /* 25: Unused */ 50 + {0, 0, 0, 0, 0}, /* 26: Unused */ 51 + {0, 0, 0, 0, 0}, /* 27: Unused */ 52 + }; 53 + 54 + int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 55 + { 56 + int virq; 57 + 58 + if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536) 59 + && (PCI_SLOT(dev->devfn) < 32)) { 60 + virq = irq_tab[slot][pin]; 61 + printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin, 62 + virq + LOONGSON_IRQ_BASE); 63 + if (virq != 0) 64 + return LOONGSON_IRQ_BASE + virq; 65 + else 66 + return 0; 67 + } else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) { /* cs5536 */ 68 + switch (PCI_FUNC(dev->devfn)) { 69 + case 2: 70 + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 71 + CS5536_IDE_INTR); 72 + return CS5536_IDE_INTR; /* for IDE */ 73 + case 3: 74 + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 75 + CS5536_ACC_INTR); 76 + return CS5536_ACC_INTR; /* for AUDIO */ 77 + case 4: /* for OHCI */ 78 + case 5: /* for EHCI */ 79 + case 6: /* for UDC */ 80 + case 7: /* for OTG */ 81 + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 82 + CS5536_USB_INTR); 83 + return CS5536_USB_INTR; 84 + } 85 + return dev->irq; 86 + } else { 87 + printk(KERN_INFO " strange pci slot number.\n"); 88 + return 0; 89 + } 90 + } 91 + 92 + /* Do platform specific device initialization at pci_enable_device() time */ 93 + int pcibios_plat_dev_init(struct pci_dev *dev) 94 + { 95 + return 0; 96 + } 97 + 98 + /* CS5536 SPEC. fixup */ 99 + static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev) 100 + { 101 + /* the uart1 and uart2 interrupt in PIC is enabled as default */ 102 + pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1); 103 + pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1); 104 + } 105 + 106 + static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev) 107 + { 108 + /* setting the mutex pin as IDE function */ 109 + pci_write_config_dword(pdev, PCI_IDE_CFG_REG, 110 + CS5536_IDE_FLASH_SIGNATURE); 111 + } 112 + 113 + static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev) 114 + { 115 + /* enable the AUDIO interrupt in PIC */ 116 + pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1); 117 + 118 + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0); 119 + } 120 + 121 + static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev) 122 + { 123 + /* enable the OHCI interrupt in PIC */ 124 + /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */ 125 + pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1); 126 + } 127 + 128 + static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev) 129 + { 130 + u32 hi, lo; 131 + 132 + /* Serial short detect enable */ 133 + _rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo); 134 + _wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 2) | (1 << 3), lo); 135 + 136 + /* setting the USB2.0 micro frame length */ 137 + pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000); 138 + } 139 + 140 + static void __init loongson_nec_fixup(struct pci_dev *pdev) 141 + { 142 + unsigned int val; 143 + 144 + pci_read_config_dword(pdev, 0xe0, &val); 145 + /* Only 2 port be used */ 146 + pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2); 147 + } 148 + 149 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 150 + loongson_cs5536_isa_fixup); 151 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC, 152 + loongson_cs5536_ohci_fixup); 153 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC, 154 + loongson_cs5536_ehci_fixup); 155 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, 156 + loongson_cs5536_acc_fixup); 157 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, 158 + loongson_cs5536_ide_fixup); 159 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, 160 + loongson_nec_fixup);
+54
arch/mips/pci/ops-fuloong2e.c arch/mips/pci/ops-loongson2.c
··· 20 20 21 21 #include <loongson.h> 22 22 23 + #ifdef CONFIG_CS5536 24 + #include <cs5536/cs5536_pci.h> 25 + #include <cs5536/cs5536.h> 26 + #endif 27 + 23 28 #define PCI_ACCESS_READ 0 24 29 #define PCI_ACCESS_WRITE 1 25 30 ··· 48 43 int reg = where & ~3; 49 44 50 45 if (busnum == 0) { 46 + /* board-specific part,currently,only fuloong2f,yeeloong2f 47 + * use CS5536, fuloong2e use via686b, gdium has no 48 + * south bridge 49 + */ 50 + #ifdef CONFIG_CS5536 51 + /* cs5536_pci_conf_read4/write4() will call _rdmsr/_wrmsr() to 52 + * access the regsters PCI_MSR_ADDR, PCI_MSR_DATA_LO, 53 + * PCI_MSR_DATA_HI, which is bigger than PCI_MSR_CTRL, so, it 54 + * will not go this branch, but the others. so, no calling dead 55 + * loop here. 56 + */ 57 + if ((PCI_IDSEL_CS5536 == device) && (reg < PCI_MSR_CTRL)) { 58 + switch (access_type) { 59 + case PCI_ACCESS_READ: 60 + *data = cs5536_pci_conf_read4(function, reg); 61 + break; 62 + case PCI_ACCESS_WRITE: 63 + cs5536_pci_conf_write4(function, reg, *data); 64 + break; 65 + } 66 + return 0; 67 + } 68 + #endif 51 69 /* Type 0 configuration for onboard PCI bus */ 52 70 if (device > MAX_DEV_NUM) 53 71 return -1; ··· 180 152 .read = loongson_pcibios_read, 181 153 .write = loongson_pcibios_write 182 154 }; 155 + 156 + #ifdef CONFIG_CS5536 157 + void _rdmsr(u32 msr, u32 *hi, u32 *lo) 158 + { 159 + struct pci_bus bus = { 160 + .number = PCI_BUS_CS5536 161 + }; 162 + u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0); 163 + loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr); 164 + loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo); 165 + loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi); 166 + } 167 + EXPORT_SYMBOL(_rdmsr); 168 + 169 + void _wrmsr(u32 msr, u32 hi, u32 lo) 170 + { 171 + struct pci_bus bus = { 172 + .number = PCI_BUS_CS5536 173 + }; 174 + u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0); 175 + loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr); 176 + loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo); 177 + loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi); 178 + } 179 + EXPORT_SYMBOL(_wrmsr); 180 + #endif