]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - arch/mips/pci/pci-xlr.c
Merge branch 'next' into for-linus
[linux-3.10.git] / arch / mips / pci / pci-xlr.c
1 /*
2  * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3  * reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the NetLogic
9  * license below:
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in
19  *    the documentation and/or other materials provided with the
20  *    distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <linux/types.h>
36 #include <linux/pci.h>
37 #include <linux/kernel.h>
38 #include <linux/init.h>
39 #include <linux/mm.h>
40 #include <linux/console.h>
41
42 #include <asm/io.h>
43
44 #include <asm/netlogic/interrupt.h>
45 #include <asm/netlogic/xlr/iomap.h>
46 #include <asm/netlogic/xlr/pic.h>
47 #include <asm/netlogic/xlr/xlr.h>
48
49 static void *pci_config_base;
50
51 #define pci_cfg_addr(bus, devfn, off) (((bus) << 16) | ((devfn) << 8) | (off))
52
53 /* PCI ops */
54 static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
55         int where)
56 {
57         u32 data;
58         u32 *cfgaddr;
59
60         cfgaddr = (u32 *)(pci_config_base +
61                         pci_cfg_addr(bus->number, devfn, where & ~3));
62         data = *cfgaddr;
63         return cpu_to_le32(data);
64 }
65
66 static inline void pci_cfg_write_32bit(struct pci_bus *bus, unsigned int devfn,
67         int where, u32 data)
68 {
69         u32 *cfgaddr;
70
71         cfgaddr = (u32 *)(pci_config_base +
72                         pci_cfg_addr(bus->number, devfn, where & ~3));
73         *cfgaddr = cpu_to_le32(data);
74 }
75
76 static int nlm_pcibios_read(struct pci_bus *bus, unsigned int devfn,
77         int where, int size, u32 *val)
78 {
79         u32 data;
80
81         if ((size == 2) && (where & 1))
82                 return PCIBIOS_BAD_REGISTER_NUMBER;
83         else if ((size == 4) && (where & 3))
84                 return PCIBIOS_BAD_REGISTER_NUMBER;
85
86         data = pci_cfg_read_32bit(bus, devfn, where);
87
88         if (size == 1)
89                 *val = (data >> ((where & 3) << 3)) & 0xff;
90         else if (size == 2)
91                 *val = (data >> ((where & 3) << 3)) & 0xffff;
92         else
93                 *val = data;
94
95         return PCIBIOS_SUCCESSFUL;
96 }
97
98
99 static int nlm_pcibios_write(struct pci_bus *bus, unsigned int devfn,
100                 int where, int size, u32 val)
101 {
102         u32 data;
103
104         if ((size == 2) && (where & 1))
105                 return PCIBIOS_BAD_REGISTER_NUMBER;
106         else if ((size == 4) && (where & 3))
107                 return PCIBIOS_BAD_REGISTER_NUMBER;
108
109         data = pci_cfg_read_32bit(bus, devfn, where);
110
111         if (size == 1)
112                 data = (data & ~(0xff << ((where & 3) << 3))) |
113                         (val << ((where & 3) << 3));
114         else if (size == 2)
115                 data = (data & ~(0xffff << ((where & 3) << 3))) |
116                         (val << ((where & 3) << 3));
117         else
118                 data = val;
119
120         pci_cfg_write_32bit(bus, devfn, where, data);
121
122         return PCIBIOS_SUCCESSFUL;
123 }
124
125 struct pci_ops nlm_pci_ops = {
126         .read  = nlm_pcibios_read,
127         .write = nlm_pcibios_write
128 };
129
130 static struct resource nlm_pci_mem_resource = {
131         .name           = "XLR PCI MEM",
132         .start          = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */
133         .end            = 0xdfffffffUL,
134         .flags          = IORESOURCE_MEM,
135 };
136
137 static struct resource nlm_pci_io_resource = {
138         .name           = "XLR IO MEM",
139         .start          = 0x10000000UL, /* 16MB PCI IO @ 0x1000_0000 */
140         .end            = 0x100fffffUL,
141         .flags          = IORESOURCE_IO,
142 };
143
144 struct pci_controller nlm_pci_controller = {
145         .index          = 0,
146         .pci_ops        = &nlm_pci_ops,
147         .mem_resource   = &nlm_pci_mem_resource,
148         .mem_offset     = 0x00000000UL,
149         .io_resource    = &nlm_pci_io_resource,
150         .io_offset      = 0x00000000UL,
151 };
152
153 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
154 {
155         if (!nlm_chip_is_xls())
156                 return  PIC_PCIX_IRQ;   /* for XLR just one IRQ*/
157
158         /*
159          * For XLS PCIe, there is an IRQ per Link, find out which
160          * link the device is on to assign interrupts
161         */
162         if (dev->bus->self == NULL)
163                 return 0;
164
165         switch  (dev->bus->self->devfn) {
166         case 0x0:
167                 return PIC_PCIE_LINK0_IRQ;
168         case 0x8:
169                 return PIC_PCIE_LINK1_IRQ;
170         case 0x10:
171                 if (nlm_chip_is_xls_b())
172                         return PIC_PCIE_XLSB0_LINK2_IRQ;
173                 else
174                         return PIC_PCIE_LINK2_IRQ;
175         case 0x18:
176                 if (nlm_chip_is_xls_b())
177                         return PIC_PCIE_XLSB0_LINK3_IRQ;
178                 else
179                         return PIC_PCIE_LINK3_IRQ;
180         }
181         WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
182         return 0;
183 }
184
185 /* Do platform specific device initialization at pci_enable_device() time */
186 int pcibios_plat_dev_init(struct pci_dev *dev)
187 {
188         return 0;
189 }
190
191 static int __init pcibios_init(void)
192 {
193         /* PSB assigns PCI resources */
194         pci_probe_only = 1;
195         pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
196
197         /* Extend IO port for memory mapped io */
198         ioport_resource.start =  0;
199         ioport_resource.end   = ~0;
200
201         set_io_port_base(CKSEG1);
202         nlm_pci_controller.io_map_base = CKSEG1;
203
204         pr_info("Registering XLR/XLS PCIX/PCIE Controller.\n");
205         register_pci_controller(&nlm_pci_controller);
206
207         return 0;
208 }
209
210 arch_initcall(pcibios_init);
211
212 struct pci_fixup pcibios_fixups[] = {
213         {0}
214 };