| David S. Miller | 16ce82d | 2007-04-26 21:08:21 -0700 | [diff] [blame] | 1 | /* pci_sabre.c: Sabre specific PCI controller support. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2 |  * | 
| David S. Miller | 16ce82d | 2007-04-26 21:08:21 -0700 | [diff] [blame] | 3 |  * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4 |  * Copyright (C) 1998, 1999 Eddie C. Dost   (ecd@skynet.be) | 
 | 5 |  * Copyright (C) 1999 Jakub Jelinek   (jakub@redhat.com) | 
 | 6 |  */ | 
 | 7 |  | 
 | 8 | #include <linux/kernel.h> | 
 | 9 | #include <linux/types.h> | 
 | 10 | #include <linux/pci.h> | 
 | 11 | #include <linux/init.h> | 
 | 12 | #include <linux/slab.h> | 
 | 13 | #include <linux/interrupt.h> | 
| Stephen Rothwell | 764f257 | 2008-08-07 15:33:36 -0700 | [diff] [blame] | 14 | #include <linux/of_device.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 |  | 
 | 16 | #include <asm/apb.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 | #include <asm/iommu.h> | 
 | 18 | #include <asm/irq.h> | 
| David S. Miller | e87dc35 | 2006-06-21 18:18:47 -0700 | [diff] [blame] | 19 | #include <asm/prom.h> | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 20 | #include <asm/upa.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
 | 22 | #include "pci_impl.h" | 
 | 23 | #include "iommu_common.h" | 
| David S. Miller | a21cff3 | 2008-09-10 03:07:03 -0700 | [diff] [blame] | 24 | #include "psycho_common.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 26 | #define DRIVER_NAME	"sabre" | 
 | 27 | #define PFX		DRIVER_NAME ": " | 
 | 28 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | /* SABRE PCI controller register offsets and definitions. */ | 
 | 30 | #define SABRE_UE_AFSR		0x0030UL | 
 | 31 | #define  SABRE_UEAFSR_PDRD	 0x4000000000000000UL	/* Primary PCI DMA Read */ | 
 | 32 | #define  SABRE_UEAFSR_PDWR	 0x2000000000000000UL	/* Primary PCI DMA Write */ | 
 | 33 | #define  SABRE_UEAFSR_SDRD	 0x0800000000000000UL	/* Secondary PCI DMA Read */ | 
 | 34 | #define  SABRE_UEAFSR_SDWR	 0x0400000000000000UL	/* Secondary PCI DMA Write */ | 
 | 35 | #define  SABRE_UEAFSR_SDTE	 0x0200000000000000UL	/* Secondary DMA Translation Error */ | 
 | 36 | #define  SABRE_UEAFSR_PDTE	 0x0100000000000000UL	/* Primary DMA Translation Error */ | 
 | 37 | #define  SABRE_UEAFSR_BMSK	 0x0000ffff00000000UL	/* Bytemask */ | 
 | 38 | #define  SABRE_UEAFSR_OFF	 0x00000000e0000000UL	/* Offset (AFAR bits [5:3] */ | 
 | 39 | #define  SABRE_UEAFSR_BLK	 0x0000000000800000UL	/* Was block operation */ | 
 | 40 | #define SABRE_UECE_AFAR		0x0038UL | 
 | 41 | #define SABRE_CE_AFSR		0x0040UL | 
 | 42 | #define  SABRE_CEAFSR_PDRD	 0x4000000000000000UL	/* Primary PCI DMA Read */ | 
 | 43 | #define  SABRE_CEAFSR_PDWR	 0x2000000000000000UL	/* Primary PCI DMA Write */ | 
 | 44 | #define  SABRE_CEAFSR_SDRD	 0x0800000000000000UL	/* Secondary PCI DMA Read */ | 
 | 45 | #define  SABRE_CEAFSR_SDWR	 0x0400000000000000UL	/* Secondary PCI DMA Write */ | 
 | 46 | #define  SABRE_CEAFSR_ESYND	 0x00ff000000000000UL	/* ECC Syndrome */ | 
 | 47 | #define  SABRE_CEAFSR_BMSK	 0x0000ffff00000000UL	/* Bytemask */ | 
 | 48 | #define  SABRE_CEAFSR_OFF	 0x00000000e0000000UL	/* Offset */ | 
 | 49 | #define  SABRE_CEAFSR_BLK	 0x0000000000800000UL	/* Was block operation */ | 
 | 50 | #define SABRE_UECE_AFAR_ALIAS	0x0048UL	/* Aliases to 0x0038 */ | 
 | 51 | #define SABRE_IOMMU_CONTROL	0x0200UL | 
 | 52 | #define  SABRE_IOMMUCTRL_ERRSTS	 0x0000000006000000UL	/* Error status bits */ | 
 | 53 | #define  SABRE_IOMMUCTRL_ERR	 0x0000000001000000UL	/* Error present in IOTLB */ | 
 | 54 | #define  SABRE_IOMMUCTRL_LCKEN	 0x0000000000800000UL	/* IOTLB lock enable */ | 
 | 55 | #define  SABRE_IOMMUCTRL_LCKPTR	 0x0000000000780000UL	/* IOTLB lock pointer */ | 
 | 56 | #define  SABRE_IOMMUCTRL_TSBSZ	 0x0000000000070000UL	/* TSB Size */ | 
 | 57 | #define  SABRE_IOMMU_TSBSZ_1K   0x0000000000000000 | 
 | 58 | #define  SABRE_IOMMU_TSBSZ_2K   0x0000000000010000 | 
 | 59 | #define  SABRE_IOMMU_TSBSZ_4K   0x0000000000020000 | 
 | 60 | #define  SABRE_IOMMU_TSBSZ_8K   0x0000000000030000 | 
 | 61 | #define  SABRE_IOMMU_TSBSZ_16K  0x0000000000040000 | 
 | 62 | #define  SABRE_IOMMU_TSBSZ_32K  0x0000000000050000 | 
 | 63 | #define  SABRE_IOMMU_TSBSZ_64K  0x0000000000060000 | 
 | 64 | #define  SABRE_IOMMU_TSBSZ_128K 0x0000000000070000 | 
 | 65 | #define  SABRE_IOMMUCTRL_TBWSZ	 0x0000000000000004UL	/* TSB assumed page size */ | 
 | 66 | #define  SABRE_IOMMUCTRL_DENAB	 0x0000000000000002UL	/* Diagnostic Mode Enable */ | 
 | 67 | #define  SABRE_IOMMUCTRL_ENAB	 0x0000000000000001UL	/* IOMMU Enable */ | 
 | 68 | #define SABRE_IOMMU_TSBBASE	0x0208UL | 
 | 69 | #define SABRE_IOMMU_FLUSH	0x0210UL | 
 | 70 | #define SABRE_IMAP_A_SLOT0	0x0c00UL | 
 | 71 | #define SABRE_IMAP_B_SLOT0	0x0c20UL | 
 | 72 | #define SABRE_IMAP_SCSI		0x1000UL | 
 | 73 | #define SABRE_IMAP_ETH		0x1008UL | 
 | 74 | #define SABRE_IMAP_BPP		0x1010UL | 
 | 75 | #define SABRE_IMAP_AU_REC	0x1018UL | 
 | 76 | #define SABRE_IMAP_AU_PLAY	0x1020UL | 
 | 77 | #define SABRE_IMAP_PFAIL	0x1028UL | 
 | 78 | #define SABRE_IMAP_KMS		0x1030UL | 
 | 79 | #define SABRE_IMAP_FLPY		0x1038UL | 
 | 80 | #define SABRE_IMAP_SHW		0x1040UL | 
 | 81 | #define SABRE_IMAP_KBD		0x1048UL | 
 | 82 | #define SABRE_IMAP_MS		0x1050UL | 
 | 83 | #define SABRE_IMAP_SER		0x1058UL | 
 | 84 | #define SABRE_IMAP_UE		0x1070UL | 
 | 85 | #define SABRE_IMAP_CE		0x1078UL | 
 | 86 | #define SABRE_IMAP_PCIERR	0x1080UL | 
 | 87 | #define SABRE_IMAP_GFX		0x1098UL | 
 | 88 | #define SABRE_IMAP_EUPA		0x10a0UL | 
 | 89 | #define SABRE_ICLR_A_SLOT0	0x1400UL | 
 | 90 | #define SABRE_ICLR_B_SLOT0	0x1480UL | 
 | 91 | #define SABRE_ICLR_SCSI		0x1800UL | 
 | 92 | #define SABRE_ICLR_ETH		0x1808UL | 
 | 93 | #define SABRE_ICLR_BPP		0x1810UL | 
 | 94 | #define SABRE_ICLR_AU_REC	0x1818UL | 
 | 95 | #define SABRE_ICLR_AU_PLAY	0x1820UL | 
 | 96 | #define SABRE_ICLR_PFAIL	0x1828UL | 
 | 97 | #define SABRE_ICLR_KMS		0x1830UL | 
 | 98 | #define SABRE_ICLR_FLPY		0x1838UL | 
 | 99 | #define SABRE_ICLR_SHW		0x1840UL | 
 | 100 | #define SABRE_ICLR_KBD		0x1848UL | 
 | 101 | #define SABRE_ICLR_MS		0x1850UL | 
 | 102 | #define SABRE_ICLR_SER		0x1858UL | 
 | 103 | #define SABRE_ICLR_UE		0x1870UL | 
 | 104 | #define SABRE_ICLR_CE		0x1878UL | 
 | 105 | #define SABRE_ICLR_PCIERR	0x1880UL | 
 | 106 | #define SABRE_WRSYNC		0x1c20UL | 
 | 107 | #define SABRE_PCICTRL		0x2000UL | 
 | 108 | #define  SABRE_PCICTRL_MRLEN	 0x0000001000000000UL	/* Use MemoryReadLine for block loads/stores */ | 
 | 109 | #define  SABRE_PCICTRL_SERR	 0x0000000400000000UL	/* Set when SERR asserted on PCI bus */ | 
 | 110 | #define  SABRE_PCICTRL_ARBPARK	 0x0000000000200000UL	/* Bus Parking 0=Ultra-IIi 1=prev-bus-owner */ | 
 | 111 | #define  SABRE_PCICTRL_CPUPRIO	 0x0000000000100000UL	/* Ultra-IIi granted every other bus cycle */ | 
 | 112 | #define  SABRE_PCICTRL_ARBPRIO	 0x00000000000f0000UL	/* Slot which is granted every other bus cycle */ | 
 | 113 | #define  SABRE_PCICTRL_ERREN	 0x0000000000000100UL	/* PCI Error Interrupt Enable */ | 
 | 114 | #define  SABRE_PCICTRL_RTRYWE	 0x0000000000000080UL	/* DMA Flow Control 0=wait-if-possible 1=retry */ | 
 | 115 | #define  SABRE_PCICTRL_AEN	 0x000000000000000fUL	/* Slot PCI arbitration enables */ | 
 | 116 | #define SABRE_PIOAFSR		0x2010UL | 
 | 117 | #define  SABRE_PIOAFSR_PMA	 0x8000000000000000UL	/* Primary Master Abort */ | 
 | 118 | #define  SABRE_PIOAFSR_PTA	 0x4000000000000000UL	/* Primary Target Abort */ | 
 | 119 | #define  SABRE_PIOAFSR_PRTRY	 0x2000000000000000UL	/* Primary Excessive Retries */ | 
 | 120 | #define  SABRE_PIOAFSR_PPERR	 0x1000000000000000UL	/* Primary Parity Error */ | 
 | 121 | #define  SABRE_PIOAFSR_SMA	 0x0800000000000000UL	/* Secondary Master Abort */ | 
 | 122 | #define  SABRE_PIOAFSR_STA	 0x0400000000000000UL	/* Secondary Target Abort */ | 
 | 123 | #define  SABRE_PIOAFSR_SRTRY	 0x0200000000000000UL	/* Secondary Excessive Retries */ | 
 | 124 | #define  SABRE_PIOAFSR_SPERR	 0x0100000000000000UL	/* Secondary Parity Error */ | 
 | 125 | #define  SABRE_PIOAFSR_BMSK	 0x0000ffff00000000UL	/* Byte Mask */ | 
 | 126 | #define  SABRE_PIOAFSR_BLK	 0x0000000080000000UL	/* Was Block Operation */ | 
 | 127 | #define SABRE_PIOAFAR		0x2018UL | 
 | 128 | #define SABRE_PCIDIAG		0x2020UL | 
 | 129 | #define  SABRE_PCIDIAG_DRTRY	 0x0000000000000040UL	/* Disable PIO Retry Limit */ | 
 | 130 | #define  SABRE_PCIDIAG_IPAPAR	 0x0000000000000008UL	/* Invert PIO Address Parity */ | 
 | 131 | #define  SABRE_PCIDIAG_IPDPAR	 0x0000000000000004UL	/* Invert PIO Data Parity */ | 
 | 132 | #define  SABRE_PCIDIAG_IDDPAR	 0x0000000000000002UL	/* Invert DMA Data Parity */ | 
 | 133 | #define  SABRE_PCIDIAG_ELPBK	 0x0000000000000001UL	/* Loopback Enable - not supported */ | 
 | 134 | #define SABRE_PCITASR		0x2028UL | 
 | 135 | #define  SABRE_PCITASR_EF	 0x0000000000000080UL	/* Respond to 0xe0000000-0xffffffff */ | 
 | 136 | #define  SABRE_PCITASR_CD	 0x0000000000000040UL	/* Respond to 0xc0000000-0xdfffffff */ | 
 | 137 | #define  SABRE_PCITASR_AB	 0x0000000000000020UL	/* Respond to 0xa0000000-0xbfffffff */ | 
 | 138 | #define  SABRE_PCITASR_89	 0x0000000000000010UL	/* Respond to 0x80000000-0x9fffffff */ | 
 | 139 | #define  SABRE_PCITASR_67	 0x0000000000000008UL	/* Respond to 0x60000000-0x7fffffff */ | 
 | 140 | #define  SABRE_PCITASR_45	 0x0000000000000004UL	/* Respond to 0x40000000-0x5fffffff */ | 
 | 141 | #define  SABRE_PCITASR_23	 0x0000000000000002UL	/* Respond to 0x20000000-0x3fffffff */ | 
 | 142 | #define  SABRE_PCITASR_01	 0x0000000000000001UL	/* Respond to 0x00000000-0x1fffffff */ | 
 | 143 | #define SABRE_PIOBUF_DIAG	0x5000UL | 
 | 144 | #define SABRE_DMABUF_DIAGLO	0x5100UL | 
 | 145 | #define SABRE_DMABUF_DIAGHI	0x51c0UL | 
 | 146 | #define SABRE_IMAP_GFX_ALIAS	0x6000UL	/* Aliases to 0x1098 */ | 
 | 147 | #define SABRE_IMAP_EUPA_ALIAS	0x8000UL	/* Aliases to 0x10a0 */ | 
 | 148 | #define SABRE_IOMMU_VADIAG	0xa400UL | 
 | 149 | #define SABRE_IOMMU_TCDIAG	0xa408UL | 
 | 150 | #define SABRE_IOMMU_TAG		0xa580UL | 
 | 151 | #define  SABRE_IOMMUTAG_ERRSTS	 0x0000000001800000UL	/* Error status bits */ | 
 | 152 | #define  SABRE_IOMMUTAG_ERR	 0x0000000000400000UL	/* Error present */ | 
 | 153 | #define  SABRE_IOMMUTAG_WRITE	 0x0000000000200000UL	/* Page is writable */ | 
 | 154 | #define  SABRE_IOMMUTAG_STREAM	 0x0000000000100000UL	/* Streamable bit - unused */ | 
 | 155 | #define  SABRE_IOMMUTAG_SIZE	 0x0000000000080000UL	/* 0=8k 1=16k */ | 
 | 156 | #define  SABRE_IOMMUTAG_VPN	 0x000000000007ffffUL	/* Virtual Page Number [31:13] */ | 
 | 157 | #define SABRE_IOMMU_DATA	0xa600UL | 
 | 158 | #define SABRE_IOMMUDATA_VALID	 0x0000000040000000UL	/* Valid */ | 
 | 159 | #define SABRE_IOMMUDATA_USED	 0x0000000020000000UL	/* Used (for LRU algorithm) */ | 
 | 160 | #define SABRE_IOMMUDATA_CACHE	 0x0000000010000000UL	/* Cacheable */ | 
 | 161 | #define SABRE_IOMMUDATA_PPN	 0x00000000001fffffUL	/* Physical Page Number [33:13] */ | 
 | 162 | #define SABRE_PCI_IRQSTATE	0xa800UL | 
 | 163 | #define SABRE_OBIO_IRQSTATE	0xa808UL | 
 | 164 | #define SABRE_FFBCFG		0xf000UL | 
 | 165 | #define  SABRE_FFBCFG_SPRQS	 0x000000000f000000	/* Slave P_RQST queue size */ | 
 | 166 | #define  SABRE_FFBCFG_ONEREAD	 0x0000000000004000	/* Slave supports one outstanding read */ | 
 | 167 | #define SABRE_MCCTRL0		0xf010UL | 
 | 168 | #define  SABRE_MCCTRL0_RENAB	 0x0000000080000000	/* Refresh Enable */ | 
 | 169 | #define  SABRE_MCCTRL0_EENAB	 0x0000000010000000	/* Enable all ECC functions */ | 
 | 170 | #define  SABRE_MCCTRL0_11BIT	 0x0000000000001000	/* Enable 11-bit column addressing */ | 
 | 171 | #define  SABRE_MCCTRL0_DPP	 0x0000000000000f00	/* DIMM Pair Present Bits */ | 
 | 172 | #define  SABRE_MCCTRL0_RINTVL	 0x00000000000000ff	/* Refresh Interval */ | 
 | 173 | #define SABRE_MCCTRL1		0xf018UL | 
 | 174 | #define  SABRE_MCCTRL1_AMDC	 0x0000000038000000	/* Advance Memdata Clock */ | 
 | 175 | #define  SABRE_MCCTRL1_ARDC	 0x0000000007000000	/* Advance DRAM Read Data Clock */ | 
 | 176 | #define  SABRE_MCCTRL1_CSR	 0x0000000000e00000	/* CAS to RAS delay for CBR refresh */ | 
 | 177 | #define  SABRE_MCCTRL1_CASRW	 0x00000000001c0000	/* CAS length for read/write */ | 
 | 178 | #define  SABRE_MCCTRL1_RCD	 0x0000000000038000	/* RAS to CAS delay */ | 
 | 179 | #define  SABRE_MCCTRL1_CP	 0x0000000000007000	/* CAS Precharge */ | 
 | 180 | #define  SABRE_MCCTRL1_RP	 0x0000000000000e00	/* RAS Precharge */ | 
 | 181 | #define  SABRE_MCCTRL1_RAS	 0x00000000000001c0	/* Length of RAS for refresh */ | 
 | 182 | #define  SABRE_MCCTRL1_CASRW2	 0x0000000000000038	/* Must be same as CASRW */ | 
 | 183 | #define  SABRE_MCCTRL1_RSC	 0x0000000000000007	/* RAS after CAS hold time */ | 
 | 184 | #define SABRE_RESETCTRL		0xf020UL | 
 | 185 |  | 
 | 186 | #define SABRE_CONFIGSPACE	0x001000000UL | 
 | 187 | #define SABRE_IOSPACE		0x002000000UL | 
 | 188 | #define SABRE_IOSPACE_SIZE	0x000ffffffUL | 
 | 189 | #define SABRE_MEMSPACE		0x100000000UL | 
 | 190 | #define SABRE_MEMSPACE_SIZE	0x07fffffffUL | 
 | 191 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 192 | static int hummingbird_p; | 
 | 193 | static struct pci_bus *sabre_root_bus; | 
 | 194 |  | 
| Al Viro | 6d24c8d | 2006-10-08 08:23:28 -0400 | [diff] [blame] | 195 | static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 196 | { | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 197 | 	struct pci_pbm_info *pbm = dev_id; | 
 | 198 | 	unsigned long afsr_reg = pbm->controller_regs + SABRE_UE_AFSR; | 
 | 199 | 	unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 200 | 	unsigned long afsr, afar, error_bits; | 
 | 201 | 	int reported; | 
 | 202 |  | 
 | 203 | 	/* Latch uncorrectable error status. */ | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 204 | 	afar = upa_readq(afar_reg); | 
 | 205 | 	afsr = upa_readq(afsr_reg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 206 |  | 
 | 207 | 	/* Clear the primary/secondary error status bits. */ | 
 | 208 | 	error_bits = afsr & | 
 | 209 | 		(SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | | 
 | 210 | 		 SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | | 
 | 211 | 		 SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); | 
 | 212 | 	if (!error_bits) | 
 | 213 | 		return IRQ_NONE; | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 214 | 	upa_writeq(error_bits, afsr_reg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 215 |  | 
 | 216 | 	/* Log the error. */ | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 217 | 	printk("%s: Uncorrectable Error, primary error type[%s%s]\n", | 
 | 218 | 	       pbm->name, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 219 | 	       ((error_bits & SABRE_UEAFSR_PDRD) ? | 
 | 220 | 		"DMA Read" : | 
 | 221 | 		((error_bits & SABRE_UEAFSR_PDWR) ? | 
 | 222 | 		 "DMA Write" : "???")), | 
 | 223 | 	       ((error_bits & SABRE_UEAFSR_PDTE) ? | 
 | 224 | 		":Translation Error" : "")); | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 225 | 	printk("%s: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", | 
 | 226 | 	       pbm->name, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 | 	       (afsr & SABRE_UEAFSR_BMSK) >> 32UL, | 
 | 228 | 	       (afsr & SABRE_UEAFSR_OFF) >> 29UL, | 
 | 229 | 	       ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0)); | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 230 | 	printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); | 
 | 231 | 	printk("%s: UE Secondary errors [", pbm->name); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 232 | 	reported = 0; | 
 | 233 | 	if (afsr & SABRE_UEAFSR_SDRD) { | 
 | 234 | 		reported++; | 
 | 235 | 		printk("(DMA Read)"); | 
 | 236 | 	} | 
 | 237 | 	if (afsr & SABRE_UEAFSR_SDWR) { | 
 | 238 | 		reported++; | 
 | 239 | 		printk("(DMA Write)"); | 
 | 240 | 	} | 
 | 241 | 	if (afsr & SABRE_UEAFSR_SDTE) { | 
 | 242 | 		reported++; | 
 | 243 | 		printk("(Translation Error)"); | 
 | 244 | 	} | 
 | 245 | 	if (!reported) | 
 | 246 | 		printk("(none)"); | 
 | 247 | 	printk("]\n"); | 
 | 248 |  | 
 | 249 | 	/* Interrogate IOMMU for error status. */ | 
| David S. Miller | e6e0037 | 2008-09-10 03:52:51 -0700 | [diff] [blame] | 250 | 	psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 251 |  | 
 | 252 | 	return IRQ_HANDLED; | 
 | 253 | } | 
 | 254 |  | 
| Al Viro | 6d24c8d | 2006-10-08 08:23:28 -0400 | [diff] [blame] | 255 | static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 256 | { | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 257 | 	struct pci_pbm_info *pbm = dev_id; | 
 | 258 | 	unsigned long afsr_reg = pbm->controller_regs + SABRE_CE_AFSR; | 
 | 259 | 	unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 260 | 	unsigned long afsr, afar, error_bits; | 
 | 261 | 	int reported; | 
 | 262 |  | 
 | 263 | 	/* Latch error status. */ | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 264 | 	afar = upa_readq(afar_reg); | 
 | 265 | 	afsr = upa_readq(afsr_reg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 266 |  | 
 | 267 | 	/* Clear primary/secondary error status bits. */ | 
 | 268 | 	error_bits = afsr & | 
 | 269 | 		(SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | | 
 | 270 | 		 SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); | 
 | 271 | 	if (!error_bits) | 
 | 272 | 		return IRQ_NONE; | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 273 | 	upa_writeq(error_bits, afsr_reg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 274 |  | 
 | 275 | 	/* Log the error. */ | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 276 | 	printk("%s: Correctable Error, primary error type[%s]\n", | 
 | 277 | 	       pbm->name, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 278 | 	       ((error_bits & SABRE_CEAFSR_PDRD) ? | 
 | 279 | 		"DMA Read" : | 
 | 280 | 		((error_bits & SABRE_CEAFSR_PDWR) ? | 
 | 281 | 		 "DMA Write" : "???"))); | 
 | 282 |  | 
 | 283 | 	/* XXX Use syndrome and afar to print out module string just like | 
 | 284 | 	 * XXX UDB CE trap handler does... -DaveM | 
 | 285 | 	 */ | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 286 | 	printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 287 | 	       "was_block(%d)\n", | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 288 | 	       pbm->name, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 289 | 	       (afsr & SABRE_CEAFSR_ESYND) >> 48UL, | 
 | 290 | 	       (afsr & SABRE_CEAFSR_BMSK) >> 32UL, | 
 | 291 | 	       (afsr & SABRE_CEAFSR_OFF) >> 29UL, | 
 | 292 | 	       ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0)); | 
| David S. Miller | 6c108f1 | 2007-05-07 23:49:01 -0700 | [diff] [blame] | 293 | 	printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); | 
 | 294 | 	printk("%s: CE Secondary errors [", pbm->name); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 295 | 	reported = 0; | 
 | 296 | 	if (afsr & SABRE_CEAFSR_SDRD) { | 
 | 297 | 		reported++; | 
 | 298 | 		printk("(DMA Read)"); | 
 | 299 | 	} | 
 | 300 | 	if (afsr & SABRE_CEAFSR_SDWR) { | 
 | 301 | 		reported++; | 
 | 302 | 		printk("(DMA Write)"); | 
 | 303 | 	} | 
 | 304 | 	if (!reported) | 
 | 305 | 		printk("(none)"); | 
 | 306 | 	printk("]\n"); | 
 | 307 |  | 
 | 308 | 	return IRQ_HANDLED; | 
 | 309 | } | 
 | 310 |  | 
| David S. Miller | 34768bc | 2007-05-07 23:06:27 -0700 | [diff] [blame] | 311 | static void sabre_register_error_handlers(struct pci_pbm_info *pbm) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 312 | { | 
| David S. Miller | 22fecba | 2008-09-10 00:19:28 -0700 | [diff] [blame] | 313 | 	struct device_node *dp = pbm->op->node; | 
| David S. Miller | 2b1e597 | 2006-06-29 15:07:37 -0700 | [diff] [blame] | 314 | 	struct of_device *op; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 315 | 	unsigned long base = pbm->controller_regs; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 316 | 	u64 tmp; | 
| David S. Miller | af80318 | 2007-05-08 17:23:31 -0700 | [diff] [blame] | 317 | 	int err; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 318 |  | 
| David S. Miller | 2b1e597 | 2006-06-29 15:07:37 -0700 | [diff] [blame] | 319 | 	if (pbm->chip_type == PBM_CHIP_TYPE_SABRE) | 
 | 320 | 		dp = dp->parent; | 
 | 321 |  | 
 | 322 | 	op = of_find_device_by_node(dp); | 
 | 323 | 	if (!op) | 
 | 324 | 		return; | 
 | 325 |  | 
 | 326 | 	/* Sabre/Hummingbird IRQ property layout is: | 
 | 327 | 	 * 0: PCI ERR | 
 | 328 | 	 * 1: UE ERR | 
 | 329 | 	 * 2: CE ERR | 
 | 330 | 	 * 3: POWER FAIL | 
 | 331 | 	 */ | 
 | 332 | 	if (op->num_irqs < 4) | 
 | 333 | 		return; | 
 | 334 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 335 | 	/* We clear the error bits in the appropriate AFSR before | 
 | 336 | 	 * registering the handler so that we don't get spurious | 
 | 337 | 	 * interrupts. | 
 | 338 | 	 */ | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 339 | 	upa_writeq((SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | | 
 | 340 | 		    SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | | 
 | 341 | 		    SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), | 
 | 342 | 		   base + SABRE_UE_AFSR); | 
| David S. Miller | 2b1e597 | 2006-06-29 15:07:37 -0700 | [diff] [blame] | 343 |  | 
| David S. Miller | af80318 | 2007-05-08 17:23:31 -0700 | [diff] [blame] | 344 | 	err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); | 
 | 345 | 	if (err) | 
 | 346 | 		printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", | 
 | 347 | 		       pbm->name, err); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 348 |  | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 349 | 	upa_writeq((SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | | 
 | 350 | 		    SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR), | 
 | 351 | 		   base + SABRE_CE_AFSR); | 
 | 352 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 353 |  | 
| David S. Miller | af80318 | 2007-05-08 17:23:31 -0700 | [diff] [blame] | 354 | 	err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); | 
 | 355 | 	if (err) | 
 | 356 | 		printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", | 
 | 357 | 		       pbm->name, err); | 
| David S. Miller | e6e0037 | 2008-09-10 03:52:51 -0700 | [diff] [blame] | 358 | 	err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, | 
| David S. Miller | af80318 | 2007-05-08 17:23:31 -0700 | [diff] [blame] | 359 | 			  "SABRE_PCIERR", pbm); | 
 | 360 | 	if (err) | 
 | 361 | 		printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", | 
 | 362 | 		       pbm->name, err); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 363 |  | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 364 | 	tmp = upa_readq(base + SABRE_PCICTRL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 365 | 	tmp |= SABRE_PCICTRL_ERREN; | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 366 | 	upa_writeq(tmp, base + SABRE_PCICTRL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 367 | } | 
 | 368 |  | 
| David S. Miller | 34768bc | 2007-05-07 23:06:27 -0700 | [diff] [blame] | 369 | static void apb_init(struct pci_bus *sabre_bus) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 370 | { | 
 | 371 | 	struct pci_dev *pdev; | 
 | 372 |  | 
 | 373 | 	list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 374 | 		if (pdev->vendor == PCI_VENDOR_ID_SUN && | 
 | 375 | 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 376 | 			u16 word16; | 
 | 377 |  | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 378 | 			pci_read_config_word(pdev, PCI_COMMAND, &word16); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 379 | 			word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | | 
 | 380 | 				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | | 
 | 381 | 				PCI_COMMAND_IO; | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 382 | 			pci_write_config_word(pdev, PCI_COMMAND, word16); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 383 |  | 
 | 384 | 			/* Status register bits are "write 1 to clear". */ | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 385 | 			pci_write_config_word(pdev, PCI_STATUS, 0xffff); | 
 | 386 | 			pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 387 |  | 
 | 388 | 			/* Use a primary/seconday latency timer value | 
 | 389 | 			 * of 64. | 
 | 390 | 			 */ | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 391 | 			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); | 
 | 392 | 			pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 393 |  | 
 | 394 | 			/* Enable reporting/forwarding of master aborts, | 
 | 395 | 			 * parity, and SERR. | 
 | 396 | 			 */ | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 397 | 			pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL, | 
 | 398 | 					      (PCI_BRIDGE_CTL_PARITY | | 
 | 399 | 					       PCI_BRIDGE_CTL_SERR | | 
 | 400 | 					       PCI_BRIDGE_CTL_MASTER_ABORT)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 401 | 		} | 
 | 402 | 	} | 
 | 403 | } | 
 | 404 |  | 
| David S. Miller | 9a2ed5c | 2009-04-07 01:03:58 -0700 | [diff] [blame] | 405 | static void __devinit sabre_scan_bus(struct pci_pbm_info *pbm, | 
 | 406 | 				     struct device *parent) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 407 | { | 
 | 408 | 	static int once; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 409 |  | 
 | 410 | 	/* The APB bridge speaks to the Sabre host PCI bridge | 
 | 411 | 	 * at 66Mhz, but the front side of APB runs at 33Mhz | 
 | 412 | 	 * for both segments. | 
| David S. Miller | 321566c | 2007-06-06 14:03:08 -0700 | [diff] [blame] | 413 | 	 * | 
 | 414 | 	 * Hummingbird systems do not use APB, so they run | 
 | 415 | 	 * at 66MHZ. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 416 | 	 */ | 
| David S. Miller | 321566c | 2007-06-06 14:03:08 -0700 | [diff] [blame] | 417 | 	if (hummingbird_p) | 
 | 418 | 		pbm->is_66mhz_capable = 1; | 
 | 419 | 	else | 
 | 420 | 		pbm->is_66mhz_capable = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 421 |  | 
 | 422 | 	/* This driver has not been verified to handle | 
 | 423 | 	 * multiple SABREs yet, so trap this. | 
 | 424 | 	 * | 
 | 425 | 	 * Also note that the SABRE host bridge is hardwired | 
 | 426 | 	 * to live at bus 0. | 
 | 427 | 	 */ | 
 | 428 | 	if (once != 0) { | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 429 | 		printk(KERN_ERR PFX "Multiple controllers unsupported.\n"); | 
 | 430 | 		return; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 431 | 	} | 
 | 432 | 	once++; | 
 | 433 |  | 
| David S. Miller | e822358a | 2008-09-01 18:32:22 -0700 | [diff] [blame] | 434 | 	pbm->pci_bus = pci_scan_one_pbm(pbm, parent); | 
| David S. Miller | 321566c | 2007-06-06 14:03:08 -0700 | [diff] [blame] | 435 | 	if (!pbm->pci_bus) | 
| David S. Miller | a2fb23a | 2007-02-28 23:35:04 -0800 | [diff] [blame] | 436 | 		return; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 437 |  | 
| David S. Miller | 321566c | 2007-06-06 14:03:08 -0700 | [diff] [blame] | 438 | 	sabre_root_bus = pbm->pci_bus; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 439 |  | 
| David S. Miller | 321566c | 2007-06-06 14:03:08 -0700 | [diff] [blame] | 440 | 	apb_init(pbm->pci_bus); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 441 |  | 
| David S. Miller | 34768bc | 2007-05-07 23:06:27 -0700 | [diff] [blame] | 442 | 	sabre_register_error_handlers(pbm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 443 | } | 
 | 444 |  | 
| David S. Miller | 9a2ed5c | 2009-04-07 01:03:58 -0700 | [diff] [blame] | 445 | static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm, | 
 | 446 | 				     struct of_device *op) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 447 | { | 
| David S. Miller | 1c03a55 | 2008-09-10 03:15:56 -0700 | [diff] [blame] | 448 | 	psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); | 
| David S. Miller | e6e0037 | 2008-09-10 03:52:51 -0700 | [diff] [blame] | 449 | 	pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; | 
 | 450 | 	pbm->pci_afar = pbm->controller_regs + SABRE_PIOAFAR; | 
 | 451 | 	pbm->pci_csr = pbm->controller_regs + SABRE_PCICTRL; | 
| David S. Miller | e822358a | 2008-09-01 18:32:22 -0700 | [diff] [blame] | 452 | 	sabre_scan_bus(pbm, &op->dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 453 | } | 
 | 454 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 455 | static int __devinit sabre_probe(struct of_device *op, | 
 | 456 | 				 const struct of_device_id *match) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 457 | { | 
| David S. Miller | a165b42 | 2007-03-29 01:50:16 -0700 | [diff] [blame] | 458 | 	const struct linux_prom64_registers *pr_regs; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 459 | 	struct device_node *dp = op->node; | 
| David S. Miller | 28113a9 | 2007-05-08 00:19:02 -0700 | [diff] [blame] | 460 | 	struct pci_pbm_info *pbm; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 461 | 	u32 upa_portid, dma_mask; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 462 | 	struct iommu *iommu; | 
 | 463 | 	int tsbsize, err; | 
 | 464 | 	const u32 *vdma; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 465 | 	u64 clear_irq; | 
 | 466 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 467 | 	hummingbird_p = (match->data != NULL); | 
 | 468 | 	if (!hummingbird_p) { | 
 | 469 | 		struct device_node *cpu_dp; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 470 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 471 | 		/* Of course, Sun has to encode things a thousand | 
 | 472 | 		 * different ways, inconsistently. | 
 | 473 | 		 */ | 
 | 474 | 		for_each_node_by_type(cpu_dp, "cpu") { | 
 | 475 | 			if (!strcmp(cpu_dp->name, "SUNW,UltraSPARC-IIe")) | 
 | 476 | 				hummingbird_p = 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 477 | 		} | 
 | 478 | 	} | 
 | 479 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 480 | 	err = -ENOMEM; | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 481 | 	pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); | 
 | 482 | 	if (!pbm) { | 
 | 483 | 		printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 484 | 		goto out_err; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 485 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 486 |  | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 487 | 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 488 | 	if (!iommu) { | 
 | 489 | 		printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 490 | 		goto out_free_controller; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 491 | 	} | 
 | 492 |  | 
| David S. Miller | 28113a9 | 2007-05-08 00:19:02 -0700 | [diff] [blame] | 493 | 	pbm->iommu = iommu; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 494 |  | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 495 | 	upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 496 |  | 
| David S. Miller | 28113a9 | 2007-05-08 00:19:02 -0700 | [diff] [blame] | 497 | 	pbm->portid = upa_portid; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 498 |  | 
 | 499 | 	/* | 
 | 500 | 	 * Map in SABRE register set and report the presence of this SABRE. | 
 | 501 | 	 */ | 
| David S. Miller | e87dc35 | 2006-06-21 18:18:47 -0700 | [diff] [blame] | 502 | 	 | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 503 | 	pr_regs = of_get_property(dp, "reg", NULL); | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 504 | 	err = -ENODEV; | 
 | 505 | 	if (!pr_regs) { | 
 | 506 | 		printk(KERN_ERR PFX "No reg property\n"); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 507 | 		goto out_free_iommu; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 508 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 509 |  | 
 | 510 | 	/* | 
 | 511 | 	 * First REG in property is base of entire SABRE register space. | 
 | 512 | 	 */ | 
| David S. Miller | 28113a9 | 2007-05-08 00:19:02 -0700 | [diff] [blame] | 513 | 	pbm->controller_regs = pr_regs[0].phys_addr; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 514 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 515 | 	/* Clear interrupts */ | 
 | 516 |  | 
 | 517 | 	/* PCI first */ | 
 | 518 | 	for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 519 | 		upa_writeq(0x0UL, pbm->controller_regs + clear_irq); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 520 |  | 
 | 521 | 	/* Then OBIO */ | 
 | 522 | 	for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 523 | 		upa_writeq(0x0UL, pbm->controller_regs + clear_irq); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 524 |  | 
 | 525 | 	/* Error interrupts are enabled later after the bus scan. */ | 
| David S. Miller | 87395fc | 2008-09-10 04:13:10 -0700 | [diff] [blame] | 526 | 	upa_writeq((SABRE_PCICTRL_MRLEN   | SABRE_PCICTRL_SERR | | 
 | 527 | 		    SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN), | 
 | 528 | 		   pbm->controller_regs + SABRE_PCICTRL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 529 |  | 
 | 530 | 	/* Now map in PCI config space for entire SABRE. */ | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 531 | 	pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 532 |  | 
| David S. Miller | 01f94c4 | 2007-03-04 12:53:19 -0800 | [diff] [blame] | 533 | 	vdma = of_get_property(dp, "virtual-dma", NULL); | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 534 | 	if (!vdma) { | 
 | 535 | 		printk(KERN_ERR PFX "No virtual-dma property\n"); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 536 | 		goto out_free_iommu; | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 537 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 538 |  | 
 | 539 | 	dma_mask = vdma[0]; | 
 | 540 | 	switch(vdma[1]) { | 
 | 541 | 		case 0x20000000: | 
 | 542 | 			dma_mask |= 0x1fffffff; | 
 | 543 | 			tsbsize = 64; | 
 | 544 | 			break; | 
 | 545 | 		case 0x40000000: | 
 | 546 | 			dma_mask |= 0x3fffffff; | 
 | 547 | 			tsbsize = 128; | 
 | 548 | 			break; | 
 | 549 |  | 
 | 550 | 		case 0x80000000: | 
 | 551 | 			dma_mask |= 0x7fffffff; | 
 | 552 | 			tsbsize = 128; | 
 | 553 | 			break; | 
 | 554 | 		default: | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 555 | 			printk(KERN_ERR PFX "Strange virtual-dma size.\n"); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 556 | 			goto out_free_iommu; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 557 | 	} | 
 | 558 |  | 
| David S. Miller | a21cff3 | 2008-09-10 03:07:03 -0700 | [diff] [blame] | 559 | 	err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC); | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 560 | 	if (err) | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 561 | 		goto out_free_iommu; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 562 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 563 | 	/* | 
 | 564 | 	 * Look for APB underneath. | 
 | 565 | 	 */ | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 566 | 	sabre_pbm_init(pbm, op); | 
 | 567 |  | 
 | 568 | 	pbm->next = pci_pbm_root; | 
 | 569 | 	pci_pbm_root = pbm; | 
 | 570 |  | 
 | 571 | 	dev_set_drvdata(&op->dev, pbm); | 
 | 572 |  | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 573 | 	return 0; | 
| David S. Miller | ad7ad57 | 2007-07-27 22:39:14 -0700 | [diff] [blame] | 574 |  | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 575 | out_free_iommu: | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 576 | 	kfree(pbm->iommu); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 577 |  | 
 | 578 | out_free_controller: | 
| David S. Miller | d3ae4b5 | 2008-09-09 23:54:02 -0700 | [diff] [blame] | 579 | 	kfree(pbm); | 
| David S. Miller | d7472c3 | 2008-08-31 01:33:52 -0700 | [diff] [blame] | 580 |  | 
 | 581 | out_err: | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 582 | 	return err; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 583 | } | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 584 |  | 
| David S. Miller | fd09831 | 2008-08-31 01:23:17 -0700 | [diff] [blame] | 585 | static struct of_device_id __initdata sabre_match[] = { | 
| David S. Miller | edbe805 | 2008-08-30 03:14:01 -0700 | [diff] [blame] | 586 | 	{ | 
 | 587 | 		.name = "pci", | 
 | 588 | 		.compatible = "pci108e,a001", | 
 | 589 | 		.data = (void *) 1, | 
 | 590 | 	}, | 
 | 591 | 	{ | 
 | 592 | 		.name = "pci", | 
 | 593 | 		.compatible = "pci108e,a000", | 
 | 594 | 	}, | 
 | 595 | 	{}, | 
 | 596 | }; | 
 | 597 |  | 
 | 598 | static struct of_platform_driver sabre_driver = { | 
 | 599 | 	.name		= DRIVER_NAME, | 
 | 600 | 	.match_table	= sabre_match, | 
 | 601 | 	.probe		= sabre_probe, | 
 | 602 | }; | 
 | 603 |  | 
 | 604 | static int __init sabre_init(void) | 
 | 605 | { | 
 | 606 | 	return of_register_driver(&sabre_driver, &of_bus_type); | 
 | 607 | } | 
 | 608 |  | 
 | 609 | subsys_initcall(sabre_init); |