xref: /openbmc/linux/arch/mips/pci/pci-malta.c (revision 237036de)
10dad5d26SRalf Baechle /*
20dad5d26SRalf Baechle  * Copyright (C) 1999, 2000, 2004, 2005	 MIPS Technologies, Inc.
30dad5d26SRalf Baechle  *	All rights reserved.
40dad5d26SRalf Baechle  *	Authors: Carsten Langgaard <carstenl@mips.com>
50dad5d26SRalf Baechle  *		 Maciej W. Rozycki <macro@mips.com>
60dad5d26SRalf Baechle  *
70dad5d26SRalf Baechle  * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
80dad5d26SRalf Baechle  *
90dad5d26SRalf Baechle  *  This program is free software; you can distribute it and/or modify it
100dad5d26SRalf Baechle  *  under the terms of the GNU General Public License (Version 2) as
110dad5d26SRalf Baechle  *  published by the Free Software Foundation.
120dad5d26SRalf Baechle  *
130dad5d26SRalf Baechle  *  This program is distributed in the hope it will be useful, but WITHOUT
140dad5d26SRalf Baechle  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
150dad5d26SRalf Baechle  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
160dad5d26SRalf Baechle  *  for more details.
170dad5d26SRalf Baechle  *
180dad5d26SRalf Baechle  *  You should have received a copy of the GNU General Public License along
190dad5d26SRalf Baechle  *  with this program; if not, write to the Free Software Foundation, Inc.,
200dad5d26SRalf Baechle  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
210dad5d26SRalf Baechle  *
220dad5d26SRalf Baechle  * MIPS boards specific PCI support.
230dad5d26SRalf Baechle  */
240dad5d26SRalf Baechle #include <linux/types.h>
250dad5d26SRalf Baechle #include <linux/pci.h>
260dad5d26SRalf Baechle #include <linux/kernel.h>
270dad5d26SRalf Baechle #include <linux/init.h>
280dad5d26SRalf Baechle 
290dad5d26SRalf Baechle #include <asm/gt64120.h>
30237036deSPaul Burton #include <asm/mips-cm.h>
310dad5d26SRalf Baechle #include <asm/mips-boards/generic.h>
320dad5d26SRalf Baechle #include <asm/mips-boards/bonito64.h>
330dad5d26SRalf Baechle #include <asm/mips-boards/msc01_pci.h>
340dad5d26SRalf Baechle 
350dad5d26SRalf Baechle static struct resource bonito64_mem_resource = {
360dad5d26SRalf Baechle 	.name	= "Bonito PCI MEM",
370dad5d26SRalf Baechle 	.flags	= IORESOURCE_MEM,
380dad5d26SRalf Baechle };
390dad5d26SRalf Baechle 
400dad5d26SRalf Baechle static struct resource bonito64_io_resource = {
410dad5d26SRalf Baechle 	.name	= "Bonito PCI I/O",
420dad5d26SRalf Baechle 	.start	= 0x00000000UL,
430dad5d26SRalf Baechle 	.end	= 0x000fffffUL,
440dad5d26SRalf Baechle 	.flags	= IORESOURCE_IO,
450dad5d26SRalf Baechle };
460dad5d26SRalf Baechle 
470dad5d26SRalf Baechle static struct resource gt64120_mem_resource = {
480dad5d26SRalf Baechle 	.name	= "GT-64120 PCI MEM",
490dad5d26SRalf Baechle 	.flags	= IORESOURCE_MEM,
500dad5d26SRalf Baechle };
510dad5d26SRalf Baechle 
520dad5d26SRalf Baechle static struct resource gt64120_io_resource = {
530dad5d26SRalf Baechle 	.name	= "GT-64120 PCI I/O",
540dad5d26SRalf Baechle 	.flags	= IORESOURCE_IO,
550dad5d26SRalf Baechle };
560dad5d26SRalf Baechle 
570dad5d26SRalf Baechle static struct resource msc_mem_resource = {
580dad5d26SRalf Baechle 	.name	= "MSC PCI MEM",
590dad5d26SRalf Baechle 	.flags	= IORESOURCE_MEM,
600dad5d26SRalf Baechle };
610dad5d26SRalf Baechle 
620dad5d26SRalf Baechle static struct resource msc_io_resource = {
630dad5d26SRalf Baechle 	.name	= "MSC PCI I/O",
640dad5d26SRalf Baechle 	.flags	= IORESOURCE_IO,
650dad5d26SRalf Baechle };
660dad5d26SRalf Baechle 
670dad5d26SRalf Baechle extern struct pci_ops bonito64_pci_ops;
680dad5d26SRalf Baechle extern struct pci_ops gt64xxx_pci0_ops;
690dad5d26SRalf Baechle extern struct pci_ops msc_pci_ops;
700dad5d26SRalf Baechle 
710dad5d26SRalf Baechle static struct pci_controller bonito64_controller = {
720dad5d26SRalf Baechle 	.pci_ops	= &bonito64_pci_ops,
730dad5d26SRalf Baechle 	.io_resource	= &bonito64_io_resource,
740dad5d26SRalf Baechle 	.mem_resource	= &bonito64_mem_resource,
750dad5d26SRalf Baechle 	.io_offset	= 0x00000000UL,
760dad5d26SRalf Baechle };
770dad5d26SRalf Baechle 
780dad5d26SRalf Baechle static struct pci_controller gt64120_controller = {
790dad5d26SRalf Baechle 	.pci_ops	= &gt64xxx_pci0_ops,
800dad5d26SRalf Baechle 	.io_resource	= &gt64120_io_resource,
810dad5d26SRalf Baechle 	.mem_resource	= &gt64120_mem_resource,
820dad5d26SRalf Baechle };
830dad5d26SRalf Baechle 
840dad5d26SRalf Baechle static struct pci_controller msc_controller = {
850dad5d26SRalf Baechle 	.pci_ops	= &msc_pci_ops,
860dad5d26SRalf Baechle 	.io_resource	= &msc_io_resource,
870dad5d26SRalf Baechle 	.mem_resource	= &msc_mem_resource,
880dad5d26SRalf Baechle };
890dad5d26SRalf Baechle 
900dad5d26SRalf Baechle void __init mips_pcibios_init(void)
910dad5d26SRalf Baechle {
920dad5d26SRalf Baechle 	struct pci_controller *controller;
930dad5d26SRalf Baechle 	resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
940dad5d26SRalf Baechle 
950dad5d26SRalf Baechle 	switch (mips_revision_sconid) {
960dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_GT64120:
970dad5d26SRalf Baechle 		/*
980dad5d26SRalf Baechle 		 * Due to a bug in the Galileo system controller, we need
990dad5d26SRalf Baechle 		 * to setup the PCI BAR for the Galileo internal registers.
1000dad5d26SRalf Baechle 		 * This should be done in the bios/bootprom and will be
1010dad5d26SRalf Baechle 		 * fixed in a later revision of YAMON (the MIPS boards
1020dad5d26SRalf Baechle 		 * boot prom).
1030dad5d26SRalf Baechle 		 */
1040dad5d26SRalf Baechle 		GT_WRITE(GT_PCI0_CFGADDR_OFS,
1050dad5d26SRalf Baechle 			 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
1060dad5d26SRalf Baechle 			 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
1070dad5d26SRalf Baechle 			 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
1080dad5d26SRalf Baechle 			 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
1090dad5d26SRalf Baechle 			 GT_PCI0_CFGADDR_CONFIGEN_BIT);
1100dad5d26SRalf Baechle 
1110dad5d26SRalf Baechle 		/* Perform the write */
1120dad5d26SRalf Baechle 		GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
1130dad5d26SRalf Baechle 
1140dad5d26SRalf Baechle 		/* Set up resource ranges from the controller's registers.  */
1150dad5d26SRalf Baechle 		start = GT_READ(GT_PCI0M0LD_OFS);
1160dad5d26SRalf Baechle 		end = GT_READ(GT_PCI0M0HD_OFS);
1170dad5d26SRalf Baechle 		map = GT_READ(GT_PCI0M0REMAP_OFS);
1180dad5d26SRalf Baechle 		end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
1190dad5d26SRalf Baechle 		start1 = GT_READ(GT_PCI0M1LD_OFS);
1200dad5d26SRalf Baechle 		end1 = GT_READ(GT_PCI0M1HD_OFS);
1210dad5d26SRalf Baechle 		map1 = GT_READ(GT_PCI0M1REMAP_OFS);
1220dad5d26SRalf Baechle 		end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
1230dad5d26SRalf Baechle 		/* Cannot support multiple windows, use the wider.  */
1240dad5d26SRalf Baechle 		if (end1 - start1 > end - start) {
1250dad5d26SRalf Baechle 			start = start1;
1260dad5d26SRalf Baechle 			end = end1;
1270dad5d26SRalf Baechle 			map = map1;
1280dad5d26SRalf Baechle 		}
1290dad5d26SRalf Baechle 		mask = ~(start ^ end);
1300dad5d26SRalf Baechle 		/* We don't support remapping with a discontiguous mask.  */
1310dad5d26SRalf Baechle 		BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
1320dad5d26SRalf Baechle 		       mask != ~((mask & -mask) - 1));
1330dad5d26SRalf Baechle 		gt64120_mem_resource.start = start;
1340dad5d26SRalf Baechle 		gt64120_mem_resource.end = end;
1350dad5d26SRalf Baechle 		gt64120_controller.mem_offset = (start & mask) - (map & mask);
1360dad5d26SRalf Baechle 		/* Addresses are 36-bit, so do shifts in the destinations.  */
1370dad5d26SRalf Baechle 		gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
1380dad5d26SRalf Baechle 		gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
1390dad5d26SRalf Baechle 		gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
1400dad5d26SRalf Baechle 		gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
1410dad5d26SRalf Baechle 
1420dad5d26SRalf Baechle 		start = GT_READ(GT_PCI0IOLD_OFS);
1430dad5d26SRalf Baechle 		end = GT_READ(GT_PCI0IOHD_OFS);
1440dad5d26SRalf Baechle 		map = GT_READ(GT_PCI0IOREMAP_OFS);
1450dad5d26SRalf Baechle 		end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
1460dad5d26SRalf Baechle 		mask = ~(start ^ end);
1470dad5d26SRalf Baechle 		/* We don't support remapping with a discontiguous mask.  */
1480dad5d26SRalf Baechle 		BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
1490dad5d26SRalf Baechle 		       mask != ~((mask & -mask) - 1));
1500dad5d26SRalf Baechle 		gt64120_io_resource.start = map & mask;
1510dad5d26SRalf Baechle 		gt64120_io_resource.end = (map & mask) | ~mask;
1520dad5d26SRalf Baechle 		gt64120_controller.io_offset = 0;
1530dad5d26SRalf Baechle 		/* Addresses are 36-bit, so do shifts in the destinations.  */
1540dad5d26SRalf Baechle 		gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
1550dad5d26SRalf Baechle 		gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
1560dad5d26SRalf Baechle 		gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
1570dad5d26SRalf Baechle 
1580dad5d26SRalf Baechle 		controller = &gt64120_controller;
1590dad5d26SRalf Baechle 		break;
1600dad5d26SRalf Baechle 
1610dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_BONITO:
1620dad5d26SRalf Baechle 		/* Set up resource ranges from the controller's registers.  */
1630dad5d26SRalf Baechle 		map = BONITO_PCIMAP;
1640dad5d26SRalf Baechle 		map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
1650dad5d26SRalf Baechle 		       BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
1660dad5d26SRalf Baechle 		map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
1670dad5d26SRalf Baechle 		       BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
1680dad5d26SRalf Baechle 		map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
1690dad5d26SRalf Baechle 		       BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
1700dad5d26SRalf Baechle 		/* Combine as many adjacent windows as possible.  */
1710dad5d26SRalf Baechle 		map = map1;
1720dad5d26SRalf Baechle 		start = BONITO_PCILO0_BASE;
1730dad5d26SRalf Baechle 		end = 1;
1740dad5d26SRalf Baechle 		if (map3 == map2 + 1) {
1750dad5d26SRalf Baechle 			map = map2;
1760dad5d26SRalf Baechle 			start = BONITO_PCILO1_BASE;
1770dad5d26SRalf Baechle 			end++;
1780dad5d26SRalf Baechle 		}
1790dad5d26SRalf Baechle 		if (map2 == map1 + 1) {
1800dad5d26SRalf Baechle 			map = map1;
1810dad5d26SRalf Baechle 			start = BONITO_PCILO0_BASE;
1820dad5d26SRalf Baechle 			end++;
1830dad5d26SRalf Baechle 		}
1840dad5d26SRalf Baechle 		bonito64_mem_resource.start = start;
1850dad5d26SRalf Baechle 		bonito64_mem_resource.end = start +
1860dad5d26SRalf Baechle 					    BONITO_PCIMAP_WINBASE(end) - 1;
1870dad5d26SRalf Baechle 		bonito64_controller.mem_offset = start -
1880dad5d26SRalf Baechle 						 BONITO_PCIMAP_WINBASE(map);
1890dad5d26SRalf Baechle 
1900dad5d26SRalf Baechle 		controller = &bonito64_controller;
1910dad5d26SRalf Baechle 		break;
1920dad5d26SRalf Baechle 
1930dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_SOCIT:
1940dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_ROCIT:
1950dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_SOCITSC:
1960dad5d26SRalf Baechle 	case MIPS_REVISION_SCON_SOCITSCP:
1970dad5d26SRalf Baechle 		/* Set up resource ranges from the controller's registers.  */
1980dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PMBASL, start);
1990dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
2000dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PMMAPL, map);
2010dad5d26SRalf Baechle 		msc_mem_resource.start = start & mask;
2020dad5d26SRalf Baechle 		msc_mem_resource.end = (start & mask) | ~mask;
2030dad5d26SRalf Baechle 		msc_controller.mem_offset = (start & mask) - (map & mask);
204237036deSPaul Burton 		if (mips_cm_numiocu()) {
205237036deSPaul Burton 			write_gcr_reg0_base(start);
206237036deSPaul Burton 			write_gcr_reg0_mask(mask |
207237036deSPaul Burton 					    CM_GCR_REGn_MASK_CMTGT_IOCU0);
208237036deSPaul Burton 		}
2090dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PIOBASL, start);
2100dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
2110dad5d26SRalf Baechle 		MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
2120dad5d26SRalf Baechle 		msc_io_resource.start = map & mask;
2130dad5d26SRalf Baechle 		msc_io_resource.end = (map & mask) | ~mask;
2140dad5d26SRalf Baechle 		msc_controller.io_offset = 0;
2150dad5d26SRalf Baechle 		ioport_resource.end = ~mask;
216237036deSPaul Burton 		if (mips_cm_numiocu()) {
217237036deSPaul Burton 			write_gcr_reg1_base(start);
218237036deSPaul Burton 			write_gcr_reg1_mask(mask |
219237036deSPaul Burton 					    CM_GCR_REGn_MASK_CMTGT_IOCU0);
220237036deSPaul Burton 		}
2210dad5d26SRalf Baechle 		/* If ranges overlap I/O takes precedence.  */
2220dad5d26SRalf Baechle 		start = start & mask;
2230dad5d26SRalf Baechle 		end = start | ~mask;
2240dad5d26SRalf Baechle 		if ((start >= msc_mem_resource.start &&
2250dad5d26SRalf Baechle 		     start <= msc_mem_resource.end) ||
2260dad5d26SRalf Baechle 		    (end >= msc_mem_resource.start &&
2270dad5d26SRalf Baechle 		     end <= msc_mem_resource.end)) {
2280dad5d26SRalf Baechle 			/* Use the larger space.  */
2290dad5d26SRalf Baechle 			start = max(start, msc_mem_resource.start);
2300dad5d26SRalf Baechle 			end = min(end, msc_mem_resource.end);
2310dad5d26SRalf Baechle 			if (start - msc_mem_resource.start >=
2320dad5d26SRalf Baechle 			    msc_mem_resource.end - end)
2330dad5d26SRalf Baechle 				msc_mem_resource.end = start - 1;
2340dad5d26SRalf Baechle 			else
2350dad5d26SRalf Baechle 				msc_mem_resource.start = end + 1;
2360dad5d26SRalf Baechle 		}
2370dad5d26SRalf Baechle 
2380dad5d26SRalf Baechle 		controller = &msc_controller;
2390dad5d26SRalf Baechle 		break;
2400dad5d26SRalf Baechle 	default:
2410dad5d26SRalf Baechle 		return;
2420dad5d26SRalf Baechle 	}
2430dad5d26SRalf Baechle 
24427547abfSDeng-Cheng Zhu 	/* PIIX4 ACPI starts at 0x1000 */
24527547abfSDeng-Cheng Zhu 	if (controller->io_resource->start < 0x00001000UL)
24627547abfSDeng-Cheng Zhu 		controller->io_resource->start = 0x00001000UL;
2470dad5d26SRalf Baechle 
2480dad5d26SRalf Baechle 	iomem_resource.end &= 0xfffffffffULL;			/* 64 GB */
2490dad5d26SRalf Baechle 	ioport_resource.end = controller->io_resource->end;
2500dad5d26SRalf Baechle 
2510dad5d26SRalf Baechle 	controller->io_map_base = mips_io_port_base;
2520dad5d26SRalf Baechle 
2530dad5d26SRalf Baechle 	register_pci_controller(controller);
2540dad5d26SRalf Baechle }
255