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 
pcibios_map_irq(const struct pci_dev * dev,u8 slot,u8 pin)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 */
pcibios_plat_dev_init(struct pci_dev * dev)93 int pcibios_plat_dev_init(struct pci_dev *dev)
94 {
95 	return 0;
96 }
97 
98 /* CS5536 SPEC. fixup */
loongson_cs5536_isa_fixup(struct pci_dev * pdev)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 
loongson_cs5536_ide_fixup(struct pci_dev * pdev)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 
loongson_cs5536_acc_fixup(struct pci_dev * pdev)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 
loongson_cs5536_ohci_fixup(struct pci_dev * pdev)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 
loongson_cs5536_ehci_fixup(struct pci_dev * pdev)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 << 3), lo);
135 
136 	/* setting the USB2.0 micro frame length */
137 	pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
138 }
139 
loongson_nec_fixup(struct pci_dev * pdev)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);
161