Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Marvel systems use the IO7 I/O chip provides PCI/PCIX/AGP access |
| 3 | * |
| 4 | * This file is based on: |
| 5 | * |
| 6 | * Marvel / EV7 System Programmer's Manual |
| 7 | * Revision 1.00 |
| 8 | * 14 May 2001 |
| 9 | */ |
| 10 | |
| 11 | #ifndef __ALPHA_MARVEL__H__ |
| 12 | #define __ALPHA_MARVEL__H__ |
| 13 | |
| 14 | #include <linux/types.h> |
| 15 | #include <linux/pci.h> |
| 16 | #include <linux/spinlock.h> |
| 17 | |
| 18 | #include <asm/compiler.h> |
| 19 | |
| 20 | #define MARVEL_MAX_PIDS 32 /* as long as we rely on 43-bit superpage */ |
| 21 | #define MARVEL_IRQ_VEC_PE_SHIFT (10) |
| 22 | #define MARVEL_IRQ_VEC_IRQ_MASK ((1 << MARVEL_IRQ_VEC_PE_SHIFT) - 1) |
| 23 | #define MARVEL_NR_IRQS \ |
| 24 | (16 + (MARVEL_MAX_PIDS * (1 << MARVEL_IRQ_VEC_PE_SHIFT))) |
| 25 | |
| 26 | /* |
| 27 | * EV7 RBOX Registers |
| 28 | */ |
| 29 | typedef struct { |
| 30 | volatile unsigned long csr __attribute__((aligned(16))); |
| 31 | } ev7_csr; |
| 32 | |
| 33 | typedef struct { |
| 34 | ev7_csr RBOX_CFG; /* 0x0000 */ |
| 35 | ev7_csr RBOX_NSVC; |
| 36 | ev7_csr RBOX_EWVC; |
| 37 | ev7_csr RBOX_WHAMI; |
| 38 | ev7_csr RBOX_TCTL; /* 0x0040 */ |
| 39 | ev7_csr RBOX_INT; |
| 40 | ev7_csr RBOX_IMASK; |
| 41 | ev7_csr RBOX_IREQ; |
| 42 | ev7_csr RBOX_INTQ; /* 0x0080 */ |
| 43 | ev7_csr RBOX_INTA; |
| 44 | ev7_csr RBOX_IT; |
| 45 | ev7_csr RBOX_SCRATCH1; |
| 46 | ev7_csr RBOX_SCRATCH2; /* 0x00c0 */ |
| 47 | ev7_csr RBOX_L_ERR; |
| 48 | } ev7_csrs; |
| 49 | |
| 50 | /* |
| 51 | * EV7 CSR addressing macros |
| 52 | */ |
| 53 | #define EV7_MASK40(addr) ((addr) & ((1UL << 41) - 1)) |
| 54 | #define EV7_KERN_ADDR(addr) ((void *)(IDENT_ADDR | EV7_MASK40(addr))) |
| 55 | |
| 56 | #define EV7_PE_MASK 0x1ffUL /* 9 bits ( 256 + mem/io ) */ |
| 57 | #define EV7_IPE(pe) ((~((long)(pe)) & EV7_PE_MASK) << 35) |
| 58 | |
| 59 | #define EV7_CSR_PHYS(pe, off) (EV7_IPE(pe) | (0x7FFCUL << 20) | (off)) |
| 60 | #define EV7_CSRS_PHYS(pe) (EV7_CSR_PHYS(pe, 0UL)) |
| 61 | |
| 62 | #define EV7_CSR_KERN(pe, off) (EV7_KERN_ADDR(EV7_CSR_PHYS(pe, off))) |
| 63 | #define EV7_CSRS_KERN(pe) (EV7_KERN_ADDR(EV7_CSRS_PHYS(pe))) |
| 64 | |
| 65 | #define EV7_CSR_OFFSET(name) ((unsigned long)&((ev7_csrs *)NULL)->name.csr) |
| 66 | |
| 67 | /* |
| 68 | * IO7 registers |
| 69 | */ |
| 70 | typedef struct { |
| 71 | volatile unsigned long csr __attribute__((aligned(64))); |
| 72 | } io7_csr; |
| 73 | |
| 74 | typedef struct { |
| 75 | /* I/O Port Control Registers */ |
| 76 | io7_csr POx_CTRL; /* 0x0000 */ |
| 77 | io7_csr POx_CACHE_CTL; |
| 78 | io7_csr POx_TIMER; |
| 79 | io7_csr POx_IO_ADR_EXT; |
| 80 | io7_csr POx_MEM_ADR_EXT; /* 0x0100 */ |
| 81 | io7_csr POx_XCAL_CTRL; |
| 82 | io7_csr rsvd1[2]; /* ?? spec doesn't show 0x180 */ |
| 83 | io7_csr POx_DM_SOURCE; /* 0x0200 */ |
| 84 | io7_csr POx_DM_DEST; |
| 85 | io7_csr POx_DM_SIZE; |
| 86 | io7_csr POx_DM_CTRL; |
| 87 | io7_csr rsvd2[4]; /* 0x0300 */ |
| 88 | |
| 89 | /* AGP Control Registers -- port 3 only */ |
| 90 | io7_csr AGP_CAP_ID; /* 0x0400 */ |
| 91 | io7_csr AGP_STAT; |
| 92 | io7_csr AGP_CMD; |
| 93 | io7_csr rsvd3; |
| 94 | |
| 95 | /* I/O Port Monitor Registers */ |
| 96 | io7_csr POx_MONCTL; /* 0x0500 */ |
| 97 | io7_csr POx_CTRA; |
| 98 | io7_csr POx_CTRB; |
| 99 | io7_csr POx_CTR56; |
| 100 | io7_csr POx_SCRATCH; /* 0x0600 */ |
| 101 | io7_csr POx_XTRA_A; |
| 102 | io7_csr POx_XTRA_TS; |
| 103 | io7_csr POx_XTRA_Z; |
| 104 | io7_csr rsvd4; /* 0x0700 */ |
| 105 | io7_csr POx_THRESHA; |
| 106 | io7_csr POx_THRESHB; |
| 107 | io7_csr rsvd5[33]; |
| 108 | |
| 109 | /* System Address Space Window Control Registers */ |
| 110 | |
| 111 | io7_csr POx_WBASE[4]; /* 0x1000 */ |
| 112 | io7_csr POx_WMASK[4]; |
| 113 | io7_csr POx_TBASE[4]; |
| 114 | io7_csr POx_SG_TBIA; |
| 115 | io7_csr POx_MSI_WBASE; |
| 116 | io7_csr rsvd6[50]; |
| 117 | |
| 118 | /* I/O Port Error Registers */ |
| 119 | io7_csr POx_ERR_SUM; |
| 120 | io7_csr POx_FIRST_ERR; |
| 121 | io7_csr POx_MSK_HEI; |
| 122 | io7_csr POx_TLB_ERR; |
| 123 | io7_csr POx_SPL_COMPLT; |
| 124 | io7_csr POx_TRANS_SUM; |
| 125 | io7_csr POx_FRC_PCI_ERR; |
| 126 | io7_csr POx_MULT_ERR; |
| 127 | io7_csr rsvd7[8]; |
| 128 | |
| 129 | /* I/O Port End of Interrupt Registers */ |
| 130 | io7_csr EOI_DAT; |
| 131 | io7_csr rsvd8[7]; |
| 132 | io7_csr POx_IACK_SPECIAL; |
| 133 | io7_csr rsvd9[103]; |
| 134 | } io7_ioport_csrs; |
| 135 | |
| 136 | typedef struct { |
| 137 | io7_csr IO_ASIC_REV; /* 0x30.0000 */ |
| 138 | io7_csr IO_SYS_REV; |
| 139 | io7_csr SER_CHAIN3; |
| 140 | io7_csr PO7_RST1; |
| 141 | io7_csr PO7_RST2; /* 0x30.0100 */ |
| 142 | io7_csr POx_RST[4]; |
| 143 | io7_csr IO7_DWNH; |
| 144 | io7_csr IO7_MAF; |
| 145 | io7_csr IO7_MAF_TO; |
| 146 | io7_csr IO7_ACC_CLUMP; /* 0x30.0300 */ |
| 147 | io7_csr IO7_PMASK; |
| 148 | io7_csr IO7_IOMASK; |
| 149 | io7_csr IO7_UPH; |
| 150 | io7_csr IO7_UPH_TO; /* 0x30.0400 */ |
| 151 | io7_csr RBX_IREQ_OFF; |
| 152 | io7_csr RBX_INTA_OFF; |
| 153 | io7_csr INT_RTY; |
| 154 | io7_csr PO7_MONCTL; /* 0x30.0500 */ |
| 155 | io7_csr PO7_CTRA; |
| 156 | io7_csr PO7_CTRB; |
| 157 | io7_csr PO7_CTR56; |
| 158 | io7_csr PO7_SCRATCH; /* 0x30.0600 */ |
| 159 | io7_csr PO7_XTRA_A; |
| 160 | io7_csr PO7_XTRA_TS; |
| 161 | io7_csr PO7_XTRA_Z; |
| 162 | io7_csr PO7_PMASK; /* 0x30.0700 */ |
| 163 | io7_csr PO7_THRESHA; |
| 164 | io7_csr PO7_THRESHB; |
| 165 | io7_csr rsvd1[97]; |
| 166 | io7_csr PO7_ERROR_SUM; /* 0x30.2000 */ |
| 167 | io7_csr PO7_BHOLE_MASK; |
| 168 | io7_csr PO7_HEI_MSK; |
| 169 | io7_csr PO7_CRD_MSK; |
| 170 | io7_csr PO7_UNCRR_SYM; /* 0x30.2100 */ |
| 171 | io7_csr PO7_CRRCT_SYM; |
| 172 | io7_csr PO7_ERR_PKT[2]; |
| 173 | io7_csr PO7_UGBGE_SYM; /* 0x30.2200 */ |
| 174 | io7_csr rsbv2[887]; |
| 175 | io7_csr PO7_LSI_CTL[128]; /* 0x31.0000 */ |
| 176 | io7_csr rsvd3[123]; |
| 177 | io7_csr HLT_CTL; /* 0x31.3ec0 */ |
| 178 | io7_csr HPI_CTL; /* 0x31.3f00 */ |
| 179 | io7_csr CRD_CTL; |
| 180 | io7_csr STV_CTL; |
| 181 | io7_csr HEI_CTL; |
| 182 | io7_csr PO7_MSI_CTL[16]; /* 0x31.4000 */ |
| 183 | io7_csr rsvd4[240]; |
| 184 | |
| 185 | /* |
| 186 | * Interrupt Diagnostic / Test |
| 187 | */ |
| 188 | struct { |
| 189 | io7_csr INT_PND; |
| 190 | io7_csr INT_CLR; |
| 191 | io7_csr INT_EOI; |
| 192 | io7_csr rsvd[29]; |
| 193 | } INT_DIAG[4]; |
| 194 | io7_csr rsvd5[125]; /* 0x31.a000 */ |
| 195 | io7_csr MISC_PND; /* 0x31.b800 */ |
| 196 | io7_csr rsvd6[31]; |
| 197 | io7_csr MSI_PND[16]; /* 0x31.c000 */ |
| 198 | io7_csr rsvd7[16]; |
| 199 | io7_csr MSI_CLR[16]; /* 0x31.c800 */ |
| 200 | } io7_port7_csrs; |
| 201 | |
| 202 | /* |
| 203 | * IO7 DMA Window Base register (POx_WBASEx) |
| 204 | */ |
| 205 | #define wbase_m_ena 0x1 |
| 206 | #define wbase_m_sg 0x2 |
| 207 | #define wbase_m_dac 0x4 |
| 208 | #define wbase_m_addr 0xFFF00000 |
| 209 | union IO7_POx_WBASE { |
| 210 | struct { |
| 211 | unsigned ena : 1; /* <0> */ |
| 212 | unsigned sg : 1; /* <1> */ |
| 213 | unsigned dac : 1; /* <2> -- window 3 only */ |
| 214 | unsigned rsvd1 : 17; |
| 215 | unsigned addr : 12; /* <31:20> */ |
| 216 | unsigned rsvd2 : 32; |
| 217 | } bits; |
| 218 | unsigned as_long[2]; |
| 219 | unsigned as_quad; |
| 220 | }; |
| 221 | |
| 222 | /* |
| 223 | * IO7 IID (Interrupt IDentifier) format |
| 224 | * |
| 225 | * For level-sensative interrupts, int_num is encoded as: |
| 226 | * |
| 227 | * bus/port slot/device INTx |
| 228 | * <7:5> <4:2> <1:0> |
| 229 | */ |
| 230 | union IO7_IID { |
| 231 | struct { |
| 232 | unsigned int_num : 9; /* <8:0> */ |
| 233 | unsigned tpu_mask : 4; /* <12:9> rsvd */ |
| 234 | unsigned msi : 1; /* 13 */ |
| 235 | unsigned ipe : 10; /* <23:14> */ |
| 236 | unsigned long rsvd : 40; |
| 237 | } bits; |
| 238 | unsigned int as_long[2]; |
| 239 | unsigned long as_quad; |
| 240 | }; |
| 241 | |
| 242 | /* |
| 243 | * IO7 addressing macros |
| 244 | */ |
| 245 | #define IO7_KERN_ADDR(addr) (EV7_KERN_ADDR(addr)) |
| 246 | |
| 247 | #define IO7_PORT_MASK 0x07UL /* 3 bits of port */ |
| 248 | |
| 249 | #define IO7_IPE(pe) (EV7_IPE(pe)) |
| 250 | #define IO7_IPORT(port) ((~((long)(port)) & IO7_PORT_MASK) << 32) |
| 251 | |
| 252 | #define IO7_HOSE(pe, port) (IO7_IPE(pe) | IO7_IPORT(port)) |
| 253 | |
| 254 | #define IO7_MEM_PHYS(pe, port) (IO7_HOSE(pe, port) | 0x00000000UL) |
| 255 | #define IO7_CONF_PHYS(pe, port) (IO7_HOSE(pe, port) | 0xFE000000UL) |
| 256 | #define IO7_IO_PHYS(pe, port) (IO7_HOSE(pe, port) | 0xFF000000UL) |
| 257 | #define IO7_CSR_PHYS(pe, port, off) \ |
| 258 | (IO7_HOSE(pe, port) | 0xFF800000UL | (off)) |
| 259 | #define IO7_CSRS_PHYS(pe, port) (IO7_CSR_PHYS(pe, port, 0UL)) |
| 260 | #define IO7_PORT7_CSRS_PHYS(pe) (IO7_CSR_PHYS(pe, 7, 0x300000UL)) |
| 261 | |
| 262 | #define IO7_MEM_KERN(pe, port) (IO7_KERN_ADDR(IO7_MEM_PHYS(pe, port))) |
| 263 | #define IO7_CONF_KERN(pe, port) (IO7_KERN_ADDR(IO7_CONF_PHYS(pe, port))) |
| 264 | #define IO7_IO_KERN(pe, port) (IO7_KERN_ADDR(IO7_IO_PHYS(pe, port))) |
| 265 | #define IO7_CSR_KERN(pe, port, off) (IO7_KERN_ADDR(IO7_CSR_PHYS(pe,port,off))) |
| 266 | #define IO7_CSRS_KERN(pe, port) (IO7_KERN_ADDR(IO7_CSRS_PHYS(pe, port))) |
| 267 | #define IO7_PORT7_CSRS_KERN(pe) (IO7_KERN_ADDR(IO7_PORT7_CSRS_PHYS(pe))) |
| 268 | |
| 269 | #define IO7_PLL_RNGA(pll) (((pll) >> 3) & 0x7) |
| 270 | #define IO7_PLL_RNGB(pll) (((pll) >> 6) & 0x7) |
| 271 | |
| 272 | #define IO7_MEM_SPACE (2UL * 1024 * 1024 * 1024) /* 2GB MEM */ |
| 273 | #define IO7_IO_SPACE (8UL * 1024 * 1024) /* 8MB I/O */ |
| 274 | |
| 275 | |
| 276 | /* |
| 277 | * Offset between ram physical addresses and pci64 DAC addresses |
| 278 | */ |
| 279 | #define IO7_DAC_OFFSET (1UL << 49) |
| 280 | |
| 281 | /* |
| 282 | * This is needed to satisify the IO() macro used in initializing the machvec |
| 283 | */ |
| 284 | #define MARVEL_IACK_SC \ |
| 285 | ((unsigned long) \ |
| 286 | (&(((io7_ioport_csrs *)IO7_CSRS_KERN(0, 0))->POx_IACK_SPECIAL))) |
| 287 | |
| 288 | #ifdef __KERNEL__ |
| 289 | |
| 290 | /* |
| 291 | * IO7 structs |
| 292 | */ |
| 293 | #define IO7_NUM_PORTS 4 |
| 294 | #define IO7_AGP_PORT 3 |
| 295 | |
| 296 | struct io7_port { |
| 297 | struct io7 *io7; |
| 298 | struct pci_controller *hose; |
| 299 | |
| 300 | int enabled; |
| 301 | unsigned int port; |
| 302 | io7_ioport_csrs *csrs; |
| 303 | |
| 304 | unsigned long saved_wbase[4]; |
| 305 | unsigned long saved_wmask[4]; |
| 306 | unsigned long saved_tbase[4]; |
| 307 | }; |
| 308 | |
| 309 | struct io7 { |
| 310 | struct io7 *next; |
| 311 | |
| 312 | unsigned int pe; |
| 313 | io7_port7_csrs *csrs; |
| 314 | struct io7_port ports[IO7_NUM_PORTS]; |
| 315 | |
| 316 | spinlock_t irq_lock; |
| 317 | }; |
| 318 | |
| 319 | #ifndef __EXTERN_INLINE |
| 320 | # define __EXTERN_INLINE extern inline |
| 321 | # define __IO_EXTERN_INLINE |
| 322 | #endif |
| 323 | |
| 324 | /* |
| 325 | * I/O functions. All access through linear space. |
| 326 | */ |
| 327 | |
| 328 | /* |
| 329 | * Memory functions. All accesses through linear space. |
| 330 | */ |
| 331 | |
| 332 | #define vucp volatile unsigned char __force * |
| 333 | #define vusp volatile unsigned short __force * |
| 334 | |
| 335 | extern unsigned int marvel_ioread8(void __iomem *); |
| 336 | extern void marvel_iowrite8(u8 b, void __iomem *); |
| 337 | |
| 338 | __EXTERN_INLINE unsigned int marvel_ioread16(void __iomem *addr) |
| 339 | { |
| 340 | return __kernel_ldwu(*(vusp)addr); |
| 341 | } |
| 342 | |
| 343 | __EXTERN_INLINE void marvel_iowrite16(u16 b, void __iomem *addr) |
| 344 | { |
| 345 | __kernel_stw(b, *(vusp)addr); |
| 346 | } |
| 347 | |
| 348 | extern void __iomem *marvel_ioremap(unsigned long addr, unsigned long size); |
| 349 | extern void marvel_iounmap(volatile void __iomem *addr); |
| 350 | extern void __iomem *marvel_ioportmap (unsigned long addr); |
| 351 | |
| 352 | __EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr) |
| 353 | { |
| 354 | return (addr >> 40) & 1; |
| 355 | } |
| 356 | |
| 357 | extern int marvel_is_mmio(const volatile void __iomem *); |
| 358 | |
| 359 | #undef vucp |
| 360 | #undef vusp |
| 361 | |
| 362 | #undef __IO_PREFIX |
| 363 | #define __IO_PREFIX marvel |
| 364 | #define marvel_trivial_rw_bw 1 |
| 365 | #define marvel_trivial_rw_lq 1 |
| 366 | #define marvel_trivial_io_bw 0 |
| 367 | #define marvel_trivial_io_lq 1 |
| 368 | #define marvel_trivial_iounmap 0 |
| 369 | #include <asm/io_trivial.h> |
| 370 | |
| 371 | #ifdef __IO_EXTERN_INLINE |
| 372 | # undef __EXTERN_INLINE |
| 373 | # undef __IO_EXTERN_INLINE |
| 374 | #endif |
| 375 | |
| 376 | #endif /* __KERNEL__ */ |
| 377 | |
| 378 | #endif /* __ALPHA_MARVEL__H__ */ |