~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-dove/pcie.c

Version: ~ [ linux-5.8-rc4 ] ~ [ linux-5.7.7 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.50 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.131 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.187 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.229 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.229 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * arch/arm/mach-dove/pcie.c
  3  *
  4  * PCIe functions for Marvell Dove 88AP510 SoC
  5  *
  6  * This file is licensed under the terms of the GNU General Public
  7  * License version 2. This program is licensed "as is" without any
  8  * warranty of any kind, whether express or implied.
  9  */
 10 
 11 #include <linux/kernel.h>
 12 #include <linux/pci.h>
 13 #include <linux/clk.h>
 14 #include <video/vga.h>
 15 #include <asm/mach/pci.h>
 16 #include <asm/mach/arch.h>
 17 #include <asm/setup.h>
 18 #include <asm/delay.h>
 19 #include <plat/pcie.h>
 20 #include <mach/irqs.h>
 21 #include <mach/bridge-regs.h>
 22 #include <plat/addr-map.h>
 23 #include "common.h"
 24 
 25 struct pcie_port {
 26         u8                      index;
 27         u8                      root_bus_nr;
 28         void __iomem            *base;
 29         spinlock_t              conf_lock;
 30         char                    mem_space_name[16];
 31         struct resource         res;
 32 };
 33 
 34 static struct pcie_port pcie_port[2];
 35 static int num_pcie_ports;
 36 
 37 
 38 static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
 39 {
 40         struct pcie_port *pp;
 41 
 42         if (nr >= num_pcie_ports)
 43                 return 0;
 44 
 45         pp = &pcie_port[nr];
 46         sys->private_data = pp;
 47         pp->root_bus_nr = sys->busnr;
 48 
 49         /*
 50          * Generic PCIe unit setup.
 51          */
 52         orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
 53 
 54         orion_pcie_setup(pp->base);
 55 
 56         if (pp->index == 0)
 57                 pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE0_IO_PHYS_BASE);
 58         else
 59                 pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE1_IO_PHYS_BASE);
 60 
 61         /*
 62          * IORESOURCE_MEM
 63          */
 64         snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
 65                  "PCIe %d MEM", pp->index);
 66         pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
 67         pp->res.name = pp->mem_space_name;
 68         if (pp->index == 0) {
 69                 pp->res.start = DOVE_PCIE0_MEM_PHYS_BASE;
 70                 pp->res.end = pp->res.start + DOVE_PCIE0_MEM_SIZE - 1;
 71         } else {
 72                 pp->res.start = DOVE_PCIE1_MEM_PHYS_BASE;
 73                 pp->res.end = pp->res.start + DOVE_PCIE1_MEM_SIZE - 1;
 74         }
 75         pp->res.flags = IORESOURCE_MEM;
 76         if (request_resource(&iomem_resource, &pp->res))
 77                 panic("Request PCIe Memory resource failed\n");
 78         pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
 79 
 80         return 1;
 81 }
 82 
 83 static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
 84 {
 85         /*
 86          * Don't go out when trying to access nonexisting devices
 87          * on the local bus.
 88          */
 89         if (bus == pp->root_bus_nr && dev > 1)
 90                 return 0;
 91 
 92         return 1;
 93 }
 94 
 95 static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 96                         int size, u32 *val)
 97 {
 98         struct pci_sys_data *sys = bus->sysdata;
 99         struct pcie_port *pp = sys->private_data;
100         unsigned long flags;
101         int ret;
102 
103         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
104                 *val = 0xffffffff;
105                 return PCIBIOS_DEVICE_NOT_FOUND;
106         }
107 
108         spin_lock_irqsave(&pp->conf_lock, flags);
109         ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
110         spin_unlock_irqrestore(&pp->conf_lock, flags);
111 
112         return ret;
113 }
114 
115 static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
116                         int where, int size, u32 val)
117 {
118         struct pci_sys_data *sys = bus->sysdata;
119         struct pcie_port *pp = sys->private_data;
120         unsigned long flags;
121         int ret;
122 
123         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
124                 return PCIBIOS_DEVICE_NOT_FOUND;
125 
126         spin_lock_irqsave(&pp->conf_lock, flags);
127         ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
128         spin_unlock_irqrestore(&pp->conf_lock, flags);
129 
130         return ret;
131 }
132 
133 static struct pci_ops pcie_ops = {
134         .read = pcie_rd_conf,
135         .write = pcie_wr_conf,
136 };
137 
138 static void rc_pci_fixup(struct pci_dev *dev)
139 {
140         /*
141          * Prevent enumeration of root complex.
142          */
143         if (dev->bus->parent == NULL && dev->devfn == 0) {
144                 int i;
145 
146                 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
147                         dev->resource[i].start = 0;
148                         dev->resource[i].end   = 0;
149                         dev->resource[i].flags = 0;
150                 }
151         }
152 }
153 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
154 
155 static struct pci_bus __init *
156 dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
157 {
158         if (nr >= num_pcie_ports) {
159                 BUG();
160                 return NULL;
161         }
162 
163         return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
164                                  &sys->resources);
165 }
166 
167 static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
168 {
169         struct pci_sys_data *sys = dev->sysdata;
170         struct pcie_port *pp = sys->private_data;
171 
172         return pp->index ? IRQ_DOVE_PCIE1 : IRQ_DOVE_PCIE0;
173 }
174 
175 static struct hw_pci dove_pci __initdata = {
176         .nr_controllers = 2,
177         .setup          = dove_pcie_setup,
178         .scan           = dove_pcie_scan_bus,
179         .map_irq        = dove_pcie_map_irq,
180 };
181 
182 static void __init add_pcie_port(int index, void __iomem *base)
183 {
184         printk(KERN_INFO "Dove PCIe port %d: ", index);
185 
186         if (orion_pcie_link_up(base)) {
187                 struct pcie_port *pp = &pcie_port[num_pcie_ports++];
188                 struct clk *clk = clk_get_sys("pcie", (index ? "1" : ""));
189 
190                 if (!IS_ERR(clk))
191                         clk_prepare_enable(clk);
192 
193                 printk(KERN_INFO "link up\n");
194 
195                 pp->index = index;
196                 pp->root_bus_nr = -1;
197                 pp->base = base;
198                 spin_lock_init(&pp->conf_lock);
199                 memset(&pp->res, 0, sizeof(pp->res));
200         } else {
201                 printk(KERN_INFO "link down, ignoring\n");
202         }
203 }
204 
205 void __init dove_pcie_init(int init_port0, int init_port1)
206 {
207         vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
208 
209         if (init_port0)
210                 add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
211 
212         if (init_port1)
213                 add_pcie_port(1, DOVE_PCIE1_VIRT_BASE);
214 
215         pci_common_init(&dove_pci);
216 }
217 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp