Commit | Line | Data |
---|---|---|
89d63fe1 AN |
1 | /* |
2 | * linux/arch/mips/pci/pci-tx4938.c | |
3 | * | |
4 | * Based on linux/arch/mips/txx9/rbtx4938/setup.c, | |
5 | * and RBTX49xx patch from CELF patch archive. | |
6 | * | |
7 | * Copyright 2001, 2003-2005 MontaVista Software Inc. | |
8 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | |
9 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | |
10 | * | |
11 | * This file is subject to the terms and conditions of the GNU General Public | |
12 | * License. See the file "COPYING" in the main directory of this archive | |
13 | * for more details. | |
14 | */ | |
15 | #include <linux/init.h> | |
16 | #include <linux/pci.h> | |
17 | #include <linux/kernel.h> | |
455cc256 | 18 | #include <linux/interrupt.h> |
89d63fe1 AN |
19 | #include <asm/txx9/generic.h> |
20 | #include <asm/txx9/tx4938.h> | |
21 | ||
22 | int __init tx4938_report_pciclk(void) | |
23 | { | |
24 | int pciclk = 0; | |
25 | ||
26 | printk(KERN_INFO "PCIC --%s PCICLK:", | |
27 | (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) ? | |
28 | " PCI66" : ""); | |
29 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) { | |
30 | u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); | |
31 | switch ((unsigned long)ccfg & | |
32 | TX4938_CCFG_PCIDIVMODE_MASK) { | |
33 | case TX4938_CCFG_PCIDIVMODE_4: | |
34 | pciclk = txx9_cpu_clock / 4; break; | |
35 | case TX4938_CCFG_PCIDIVMODE_4_5: | |
36 | pciclk = txx9_cpu_clock * 2 / 9; break; | |
37 | case TX4938_CCFG_PCIDIVMODE_5: | |
38 | pciclk = txx9_cpu_clock / 5; break; | |
39 | case TX4938_CCFG_PCIDIVMODE_5_5: | |
40 | pciclk = txx9_cpu_clock * 2 / 11; break; | |
41 | case TX4938_CCFG_PCIDIVMODE_8: | |
42 | pciclk = txx9_cpu_clock / 8; break; | |
43 | case TX4938_CCFG_PCIDIVMODE_9: | |
44 | pciclk = txx9_cpu_clock / 9; break; | |
45 | case TX4938_CCFG_PCIDIVMODE_10: | |
46 | pciclk = txx9_cpu_clock / 10; break; | |
47 | case TX4938_CCFG_PCIDIVMODE_11: | |
48 | pciclk = txx9_cpu_clock / 11; break; | |
49 | } | |
50 | printk("Internal(%u.%uMHz)", | |
51 | (pciclk + 50000) / 1000000, | |
52 | ((pciclk + 50000) / 100000) % 10); | |
53 | } else { | |
54 | printk("External"); | |
55 | pciclk = -1; | |
56 | } | |
57 | printk("\n"); | |
58 | return pciclk; | |
59 | } | |
60 | ||
61 | void __init tx4938_report_pci1clk(void) | |
62 | { | |
63 | __u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); | |
64 | unsigned int pciclk = | |
65 | txx9_gbus_clock / ((ccfg & TX4938_CCFG_PCI1DMD) ? 4 : 2); | |
66 | ||
67 | printk(KERN_INFO "PCIC1 -- %sPCICLK:%u.%uMHz\n", | |
68 | (ccfg & TX4938_CCFG_PCI1_66) ? "PCI66 " : "", | |
69 | (pciclk + 50000) / 1000000, | |
70 | ((pciclk + 50000) / 100000) % 10); | |
71 | } | |
72 | ||
73 | int __init tx4938_pciclk66_setup(void) | |
74 | { | |
75 | int pciclk; | |
76 | ||
77 | /* Assert M66EN */ | |
78 | tx4938_ccfg_set(TX4938_CCFG_PCI66); | |
79 | /* Double PCICLK (if possible) */ | |
80 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) { | |
81 | unsigned int pcidivmode = 0; | |
82 | u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); | |
83 | pcidivmode = (unsigned long)ccfg & | |
84 | TX4938_CCFG_PCIDIVMODE_MASK; | |
85 | switch (pcidivmode) { | |
86 | case TX4938_CCFG_PCIDIVMODE_8: | |
87 | case TX4938_CCFG_PCIDIVMODE_4: | |
88 | pcidivmode = TX4938_CCFG_PCIDIVMODE_4; | |
89 | pciclk = txx9_cpu_clock / 4; | |
90 | break; | |
91 | case TX4938_CCFG_PCIDIVMODE_9: | |
92 | case TX4938_CCFG_PCIDIVMODE_4_5: | |
93 | pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5; | |
94 | pciclk = txx9_cpu_clock * 2 / 9; | |
95 | break; | |
96 | case TX4938_CCFG_PCIDIVMODE_10: | |
97 | case TX4938_CCFG_PCIDIVMODE_5: | |
98 | pcidivmode = TX4938_CCFG_PCIDIVMODE_5; | |
99 | pciclk = txx9_cpu_clock / 5; | |
100 | break; | |
101 | case TX4938_CCFG_PCIDIVMODE_11: | |
102 | case TX4938_CCFG_PCIDIVMODE_5_5: | |
103 | default: | |
104 | pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5; | |
105 | pciclk = txx9_cpu_clock * 2 / 11; | |
106 | break; | |
107 | } | |
108 | tx4938_ccfg_change(TX4938_CCFG_PCIDIVMODE_MASK, | |
109 | pcidivmode); | |
110 | printk(KERN_DEBUG "PCICLK: ccfg:%08lx\n", | |
111 | (unsigned long)__raw_readq(&tx4938_ccfgptr->ccfg)); | |
112 | } else | |
113 | pciclk = -1; | |
114 | return pciclk; | |
115 | } | |
116 | ||
117 | int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) | |
118 | { | |
119 | if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) { | |
120 | switch (slot) { | |
121 | case TX4927_PCIC_IDSEL_AD_TO_SLOT(31): | |
122 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & | |
123 | TX4938_PCFG_ETH0_SEL) | |
124 | return TXX9_IRQ_BASE + TX4938_IR_ETH0; | |
125 | break; | |
126 | case TX4927_PCIC_IDSEL_AD_TO_SLOT(30): | |
127 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & | |
128 | TX4938_PCFG_ETH1_SEL) | |
129 | return TXX9_IRQ_BASE + TX4938_IR_ETH1; | |
130 | break; | |
131 | } | |
132 | return 0; | |
133 | } | |
134 | return -1; | |
135 | } | |
455cc256 AN |
136 | |
137 | void __init tx4938_setup_pcierr_irq(void) | |
138 | { | |
139 | if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, | |
140 | tx4927_pcierr_interrupt, | |
141 | IRQF_DISABLED, "PCI error", | |
142 | (void *)TX4927_PCIC_REG)) | |
143 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | |
144 | } |