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