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

TOMOYO Linux Cross Reference
Linux/arch/m68k/coldfire/pci.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * pci.c -- PCI bus support for ColdFire processors
  3  *
  4  * (C) Copyright 2012, Greg Ungerer <gerg@uclinux.com>
  5  *
  6  * This file is subject to the terms and conditions of the GNU General Public
  7  * License.  See the file COPYING in the main directory of this archive
  8  * for more details.
  9  */
 10 
 11 #include <linux/types.h>
 12 #include <linux/module.h>
 13 #include <linux/init.h>
 14 #include <linux/kernel.h>
 15 #include <linux/interrupt.h>
 16 #include <linux/irq.h>
 17 #include <linux/io.h>
 18 #include <linux/pci.h>
 19 #include <linux/delay.h>
 20 #include <asm/coldfire.h>
 21 #include <asm/mcfsim.h>
 22 #include <asm/m54xxpci.h>
 23 
 24 /*
 25  * Memory and IO mappings. We use a 1:1 mapping for local host memory to
 26  * PCI bus memory (no reason not to really). IO space is mapped in its own
 27  * separate address region. The device configuration space is mapped over
 28  * the IO map space when we enable it in the PCICAR register.
 29  */
 30 static struct pci_bus *rootbus;
 31 static unsigned long iospace;
 32 
 33 /*
 34  * We need to be careful probing on bus 0 (directly connected to host
 35  * bridge). We should only access the well defined possible devices in
 36  * use, ignore aliases and the like.
 37  */
 38 static unsigned char mcf_host_slot2sid[32] = {
 39         0, 0, 0, 0, 0, 0, 0, 0,
 40         0, 0, 0, 0, 0, 0, 0, 0,
 41         0, 1, 2, 0, 3, 4, 0, 0,
 42         0, 0, 0, 0, 0, 0, 0, 0,
 43 };
 44 
 45 static unsigned char mcf_host_irq[] = {
 46         0, 69, 69, 71, 71,
 47 };
 48 
 49 /*
 50  * Configuration space access functions. Configuration space access is
 51  * through the IO mapping window, enabling it via the PCICAR register.
 52  */
 53 static unsigned long mcf_mk_pcicar(int bus, unsigned int devfn, int where)
 54 {
 55         return (bus << PCICAR_BUSN) | (devfn << PCICAR_DEVFNN) | (where & 0xfc);
 56 }
 57 
 58 static int mcf_pci_readconfig(struct pci_bus *bus, unsigned int devfn,
 59         int where, int size, u32 *value)
 60 {
 61         unsigned long addr;
 62 
 63         *value = 0xffffffff;
 64 
 65         if (bus->number == 0) {
 66                 if (mcf_host_slot2sid[PCI_SLOT(devfn)] == 0)
 67                         return PCIBIOS_SUCCESSFUL;
 68         }
 69 
 70         addr = mcf_mk_pcicar(bus->number, devfn, where);
 71         __raw_writel(PCICAR_E | addr, PCICAR);
 72         __raw_readl(PCICAR);
 73         addr = iospace + (where & 0x3);
 74 
 75         switch (size) {
 76         case 1:
 77                 *value = __raw_readb(addr);
 78                 break;
 79         case 2:
 80                 *value = le16_to_cpu(__raw_readw(addr));
 81                 break;
 82         default:
 83                 *value = le32_to_cpu(__raw_readl(addr));
 84                 break;
 85         }
 86 
 87         __raw_writel(0, PCICAR);
 88         __raw_readl(PCICAR);
 89         return PCIBIOS_SUCCESSFUL;
 90 }
 91 
 92 static int mcf_pci_writeconfig(struct pci_bus *bus, unsigned int devfn,
 93         int where, int size, u32 value)
 94 {
 95         unsigned long addr;
 96 
 97         if (bus->number == 0) {
 98                 if (mcf_host_slot2sid[PCI_SLOT(devfn)] == 0)
 99                         return PCIBIOS_SUCCESSFUL;
100         }
101 
102         addr = mcf_mk_pcicar(bus->number, devfn, where);
103         __raw_writel(PCICAR_E | addr, PCICAR);
104         __raw_readl(PCICAR);
105         addr = iospace + (where & 0x3);
106 
107         switch (size) {
108         case 1:
109                  __raw_writeb(value, addr);
110                 break;
111         case 2:
112                 __raw_writew(cpu_to_le16(value), addr);
113                 break;
114         default:
115                 __raw_writel(cpu_to_le32(value), addr);
116                 break;
117         }
118 
119         __raw_writel(0, PCICAR);
120         __raw_readl(PCICAR);
121         return PCIBIOS_SUCCESSFUL;
122 }
123 
124 static struct pci_ops mcf_pci_ops = {
125         .read   = mcf_pci_readconfig,
126         .write  = mcf_pci_writeconfig,
127 };
128 
129 /*
130  * Initialize the PCI bus registers, and scan the bus.
131  */
132 static struct resource mcf_pci_mem = {
133         .name   = "PCI Memory space",
134         .start  = PCI_MEM_PA,
135         .end    = PCI_MEM_PA + PCI_MEM_SIZE - 1,
136         .flags  = IORESOURCE_MEM,
137 };
138 
139 static struct resource mcf_pci_io = {
140         .name   = "PCI IO space",
141         .start  = 0x400,
142         .end    = 0x10000 - 1,
143         .flags  = IORESOURCE_IO,
144 };
145 
146 static struct resource busn_resource = {
147         .name   = "PCI busn",
148         .start  = 0,
149         .end    = 255,
150         .flags  = IORESOURCE_BUS,
151 };
152 
153 /*
154  * Interrupt mapping and setting.
155  */
156 static int mcf_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
157 {
158         int sid;
159 
160         sid = mcf_host_slot2sid[slot];
161         if (sid)
162                 return mcf_host_irq[sid];
163         return 0;
164 }
165 
166 static int __init mcf_pci_init(void)
167 {
168         struct pci_host_bridge *bridge;
169         int ret;
170 
171         bridge = pci_alloc_host_bridge(0);
172         if (!bridge)
173                 return -ENOMEM;
174 
175         pr_info("ColdFire: PCI bus initialization...\n");
176 
177         /* Reset the external PCI bus */
178         __raw_writel(PCIGSCR_RESET, PCIGSCR);
179         __raw_writel(0, PCITCR);
180 
181         request_resource(&iomem_resource, &mcf_pci_mem);
182         request_resource(&iomem_resource, &mcf_pci_io);
183 
184         /* Configure PCI arbiter */
185         __raw_writel(PACR_INTMPRI | PACR_INTMINTE | PACR_EXTMPRI(0x1f) |
186                 PACR_EXTMINTE(0x1f), PACR);
187 
188         /* Set required multi-function pins for PCI bus use */
189         __raw_writew(0x3ff, MCFGPIO_PAR_PCIBG);
190         __raw_writew(0x3ff, MCFGPIO_PAR_PCIBR);
191 
192         /* Set up config space for local host bus controller */
193         __raw_writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
194                 PCI_COMMAND_INVALIDATE, PCISCR);
195         __raw_writel(PCICR1_LT(32) | PCICR1_CL(8), PCICR1);
196         __raw_writel(0, PCICR2);
197 
198         /*
199          * Set up the initiator windows for memory and IO mapping.
200          * These give the CPU bus access onto the PCI bus. One for each of
201          * PCI memory and IO address spaces.
202          */
203         __raw_writel(WXBTAR(PCI_MEM_PA, PCI_MEM_BA, PCI_MEM_SIZE),
204                 PCIIW0BTAR);
205         __raw_writel(WXBTAR(PCI_IO_PA, PCI_IO_BA, PCI_IO_SIZE),
206                 PCIIW1BTAR);
207         __raw_writel(PCIIWCR_W0_MEM /*| PCIIWCR_W0_MRDL*/ | PCIIWCR_W0_E |
208                 PCIIWCR_W1_IO | PCIIWCR_W1_E, PCIIWCR);
209 
210         /*
211          * Set up the target windows for access from the PCI bus back to the
212          * CPU bus. All we need is access to system RAM (for mastering).
213          */
214         __raw_writel(CONFIG_RAMBASE, PCIBAR1);
215         __raw_writel(CONFIG_RAMBASE | PCITBATR1_E, PCITBATR1);
216 
217         /* Keep a virtual mapping to IO/config space active */
218         iospace = (unsigned long) ioremap(PCI_IO_PA, PCI_IO_SIZE);
219         if (iospace == 0) {
220                 pci_free_host_bridge(bridge);
221                 return -ENODEV;
222         }
223         pr_info("Coldfire: PCI IO/config window mapped to 0x%x\n",
224                 (u32) iospace);
225 
226         /* Turn of PCI reset, and wait for devices to settle */
227         __raw_writel(0, PCIGSCR);
228         set_current_state(TASK_UNINTERRUPTIBLE);
229         schedule_timeout(msecs_to_jiffies(200));
230 
231 
232         pci_add_resource(&bridge->windows, &ioport_resource);
233         pci_add_resource(&bridge->windows, &iomem_resource);
234         pci_add_resource(&bridge->windows, &busn_resource);
235         bridge->dev.parent = NULL;
236         bridge->sysdata = NULL;
237         bridge->busnr = 0;
238         bridge->ops = &mcf_pci_ops;
239         bridge->swizzle_irq = pci_common_swizzle;
240         bridge->map_irq = mcf_pci_map_irq;
241 
242         ret = pci_scan_root_bus_bridge(bridge);
243         if (ret) {
244                 pci_free_host_bridge(bridge);
245                 return ret;
246         }
247 
248         rootbus = bridge->bus;
249 
250         rootbus->resource[0] = &mcf_pci_io;
251         rootbus->resource[1] = &mcf_pci_mem;
252 
253         pci_bus_size_bridges(rootbus);
254         pci_bus_assign_resources(rootbus);
255         pci_bus_add_devices(rootbus);
256         return 0;
257 }
258 
259 subsys_initcall(mcf_pci_init);
260 

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php