| Ralf Baechle | 79d7cd3 | 2010-08-05 13:25:56 +0100 | [diff] [blame] | 1 | /* | 
 | 2 |  * | 
 | 3 |  * BRIEF MODULE DESCRIPTION | 
 | 4 |  * | 
 | 5 |  * Author: source@mvista.com | 
 | 6 |  * | 
 | 7 |  *  This program is free software; you can distribute it and/or modify it | 
 | 8 |  *  under the terms of the GNU General Public License (Version 2) as | 
 | 9 |  *  published by the Free Software Foundation. | 
 | 10 |  * | 
 | 11 |  *  This program is distributed in the hope it will be useful, but WITHOUT | 
 | 12 |  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 | 13 |  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
 | 14 |  *  for more details. | 
 | 15 |  * | 
 | 16 |  *  You should have received a copy of the GNU General Public License along | 
 | 17 |  *  with this program; if not, write to the Free Software Foundation, Inc., | 
 | 18 |  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | 
 | 19 |  */ | 
 | 20 | #include <linux/types.h> | 
 | 21 | #include <linux/pci.h> | 
 | 22 | #include <linux/kernel.h> | 
 | 23 | #include <linux/init.h> | 
 | 24 |  | 
 | 25 | #include <pci.h> | 
 | 26 | #include <glb.h> | 
 | 27 | #include <nand.h> | 
 | 28 |  | 
 | 29 | static struct resource pci_io_resource = { | 
 | 30 | 	.start	= PNX8550_PCIIO + 0x1000,	/* reserve regacy I/O space */ | 
 | 31 | 	.end	= PNX8550_PCIIO + PNX8550_PCIIO_SIZE, | 
 | 32 | 	.name	= "pci IO space", | 
 | 33 | 	.flags	= IORESOURCE_IO | 
 | 34 | }; | 
 | 35 |  | 
 | 36 | static struct resource pci_mem_resource = { | 
 | 37 | 	.start	= PNX8550_PCIMEM, | 
 | 38 | 	.end	= PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1, | 
 | 39 | 	.name	= "pci memory space", | 
 | 40 | 	.flags	= IORESOURCE_MEM | 
 | 41 | }; | 
 | 42 |  | 
 | 43 | extern struct pci_ops pnx8550_pci_ops; | 
 | 44 |  | 
 | 45 | static struct pci_controller pnx8550_controller = { | 
 | 46 | 	.pci_ops	= &pnx8550_pci_ops, | 
 | 47 | 	.io_map_base	= PNX8550_PORT_BASE, | 
 | 48 | 	.io_resource	= &pci_io_resource, | 
 | 49 | 	.mem_resource	= &pci_mem_resource, | 
 | 50 | }; | 
 | 51 |  | 
 | 52 | /* Return the total size of DRAM-memory, (RANK0 + RANK1) */ | 
 | 53 | static inline unsigned long get_system_mem_size(void) | 
 | 54 | { | 
 | 55 | 	/* Read IP2031_RANK0_ADDR_LO */ | 
 | 56 | 	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); | 
 | 57 | 	/* Read IP2031_RANK1_ADDR_HI */ | 
 | 58 | 	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); | 
 | 59 |  | 
 | 60 | 	return dram_r1_hi - dram_r0_lo + 1; | 
 | 61 | } | 
 | 62 |  | 
 | 63 | static int __init pnx8550_pci_setup(void) | 
 | 64 | { | 
 | 65 | 	int pci_mem_code; | 
 | 66 | 	int mem_size = get_system_mem_size() >> 20; | 
 | 67 |  | 
 | 68 | 	/* Clear the Global 2 Register, PCI Inta Output Enable Registers | 
 | 69 | 	   Bit 1:Enable DAC Powerdown | 
 | 70 | 	  -> 0:DACs are enabled and are working normally | 
 | 71 | 	     1:DACs are powerdown | 
 | 72 | 	   Bit 0:Enable of PCI inta output | 
 | 73 | 	  -> 0 = Disable PCI inta output | 
 | 74 | 	     1 = Enable PCI inta output | 
 | 75 | 	*/ | 
 | 76 | 	PNX8550_GLB2_ENAB_INTA_O = 0; | 
 | 77 |  | 
 | 78 | 	/* Calc the PCI mem size code */ | 
 | 79 | 	if (mem_size >= 128) | 
 | 80 | 		pci_mem_code = SIZE_128M; | 
 | 81 | 	else if (mem_size >= 64) | 
 | 82 | 		pci_mem_code = SIZE_64M; | 
 | 83 | 	else if (mem_size >= 32) | 
 | 84 | 		pci_mem_code = SIZE_32M; | 
 | 85 | 	else | 
 | 86 | 		pci_mem_code = SIZE_16M; | 
 | 87 |  | 
 | 88 | 	/* Set PCI_XIO registers */ | 
 | 89 | 	outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO); | 
 | 90 | 	outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI); | 
 | 91 | 	outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO); | 
 | 92 | 	outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI); | 
 | 93 |  | 
 | 94 | 	/* Send memory transaction via PCI_BASE2 */ | 
 | 95 | 	outl(0x00000001, PCI_BASE | PCI_IO); | 
 | 96 |  | 
 | 97 | 	/* Unlock the setup register */ | 
 | 98 | 	outl(0xca, PCI_BASE | PCI_UNLOCKREG); | 
 | 99 |  | 
 | 100 | 	/* | 
 | 101 | 	 * BAR0 of PNX8550 (pci base 10) must be zero in order for ide | 
 | 102 | 	 * to work, and in order for bus_to_baddr to work without any | 
 | 103 | 	 * hacks. | 
 | 104 | 	 */ | 
 | 105 | 	outl(0x00000000, PCI_BASE | PCI_BASE10); | 
 | 106 |  | 
 | 107 | 	/* | 
 | 108 | 	 *These two bars are set by default or the boot code. | 
 | 109 | 	 * However, it's safer to set them here so we're not boot | 
 | 110 | 	 * code dependent. | 
 | 111 | 	 */ | 
 | 112 | 	outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */ | 
 | 113 | 	outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */ | 
 | 114 |  | 
 | 115 | 	outl(PCI_EN_TA | | 
 | 116 | 	     PCI_EN_PCI2MMI | | 
 | 117 | 	     PCI_EN_XIO | | 
 | 118 | 	     PCI_SETUP_BASE18_SIZE(SIZE_32M) | | 
 | 119 | 	     PCI_SETUP_BASE18_EN | | 
 | 120 | 	     PCI_SETUP_BASE14_EN | | 
 | 121 | 	     PCI_SETUP_BASE10_PREF | | 
 | 122 | 	     PCI_SETUP_BASE10_SIZE(pci_mem_code) | | 
 | 123 | 	     PCI_SETUP_CFGMANAGE_EN | | 
 | 124 | 	     PCI_SETUP_PCIARB_EN, | 
 | 125 | 	     PCI_BASE | | 
 | 126 | 	     PCI_SETUP);	/* PCI_SETUP */ | 
 | 127 | 	outl(0x00000000, PCI_BASE | PCI_CTRL);	/* PCI_CONTROL */ | 
 | 128 |  | 
 | 129 | 	register_pci_controller(&pnx8550_controller); | 
 | 130 |  | 
 | 131 | 	return 0; | 
 | 132 | } | 
 | 133 |  | 
 | 134 | arch_initcall(pnx8550_pci_setup); |