1 /* 2 * linux/arch/alpha/kernel/sys_marvel.c 3 * 4 * Marvel / IO7 support 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/types.h> 9 #include <linux/mm.h> 10 #include <linux/sched.h> 11 #include <linux/pci.h> 12 #include <linux/init.h> 13 #include <linux/bitops.h> 14 15 #include <asm/ptrace.h> 16 #include <asm/dma.h> 17 #include <asm/irq.h> 18 #include <asm/mmu_context.h> 19 #include <asm/io.h> 20 #include <asm/pgtable.h> 21 #include <asm/core_marvel.h> 22 #include <asm/hwrpb.h> 23 #include <asm/tlbflush.h> 24 #include <asm/vga.h> 25 #include <asm/rtc.h> 26 27 #include "proto.h" 28 #include "err_impl.h" 29 #include "irq_impl.h" 30 #include "pci_impl.h" 31 #include "machvec_impl.h" 32 33 #if NR_IRQS < MARVEL_NR_IRQS 34 # error NR_IRQS < MARVEL_NR_IRQS !!! 35 #endif 36 37 38 /* 39 * Interrupt handling. 40 */ 41 static void 42 io7_device_interrupt(unsigned long vector) 43 { 44 unsigned int pid; 45 unsigned int irq; 46 47 /* 48 * Vector is 0x800 + (interrupt) 49 * 50 * where (interrupt) is: 51 * 52 * ...16|15 14|13 4|3 0 53 * -----+-----+--------+--- 54 * PE | 0 | irq | 0 55 * 56 * where (irq) is 57 * 58 * 0x0800 - 0x0ff0 - 0x0800 + (LSI id << 4) 59 * 0x1000 - 0x2ff0 - 0x1000 + (MSI_DAT<8:0> << 4) 60 */ 61 pid = vector >> 16; 62 irq = ((vector & 0xffff) - 0x800) >> 4; 63 64 irq += 16; /* offset for legacy */ 65 irq &= MARVEL_IRQ_VEC_IRQ_MASK; /* not too many bits */ 66 irq |= pid << MARVEL_IRQ_VEC_PE_SHIFT; /* merge the pid */ 67 68 handle_irq(irq); 69 } 70 71 static volatile unsigned long * 72 io7_get_irq_ctl(unsigned int irq, struct io7 **pio7) 73 { 74 volatile unsigned long *ctl; 75 unsigned int pid; 76 struct io7 *io7; 77 78 pid = irq >> MARVEL_IRQ_VEC_PE_SHIFT; 79 80 if (!(io7 = marvel_find_io7(pid))) { 81 printk(KERN_ERR 82 "%s for nonexistent io7 -- vec %x, pid %d\n", 83 __func__, irq, pid); 84 return NULL; 85 } 86 87 irq &= MARVEL_IRQ_VEC_IRQ_MASK; /* isolate the vector */ 88 irq -= 16; /* subtract legacy bias */ 89 90 if (irq >= 0x180) { 91 printk(KERN_ERR 92 "%s for invalid irq -- pid %d adjusted irq %x\n", 93 __func__, pid, irq); 94 return NULL; 95 } 96 97 ctl = &io7->csrs->PO7_LSI_CTL[irq & 0xff].csr; /* assume LSI */ 98 if (irq >= 0x80) /* MSI */ 99 ctl = &io7->csrs->PO7_MSI_CTL[((irq - 0x80) >> 5) & 0x0f].csr; 100 101 if (pio7) *pio7 = io7; 102 return ctl; 103 } 104 105 static void 106 io7_enable_irq(struct irq_data *d) 107 { 108 volatile unsigned long *ctl; 109 unsigned int irq = d->irq; 110 struct io7 *io7; 111 112 ctl = io7_get_irq_ctl(irq, &io7); 113 if (!ctl || !io7) { 114 printk(KERN_ERR "%s: get_ctl failed for irq %x\n", 115 __func__, irq); 116 return; 117 } 118 119 spin_lock(&io7->irq_lock); 120 *ctl |= 1UL << 24; 121 mb(); 122 *ctl; 123 spin_unlock(&io7->irq_lock); 124 } 125 126 static void 127 io7_disable_irq(struct irq_data *d) 128 { 129 volatile unsigned long *ctl; 130 unsigned int irq = d->irq; 131 struct io7 *io7; 132 133 ctl = io7_get_irq_ctl(irq, &io7); 134 if (!ctl || !io7) { 135 printk(KERN_ERR "%s: get_ctl failed for irq %x\n", 136 __func__, irq); 137 return; 138 } 139 140 spin_lock(&io7->irq_lock); 141 *ctl &= ~(1UL << 24); 142 mb(); 143 *ctl; 144 spin_unlock(&io7->irq_lock); 145 } 146 147 static void 148 marvel_irq_noop(struct irq_data *d) 149 { 150 return; 151 } 152 153 static struct irq_chip marvel_legacy_irq_type = { 154 .name = "LEGACY", 155 .irq_mask = marvel_irq_noop, 156 .irq_unmask = marvel_irq_noop, 157 }; 158 159 static struct irq_chip io7_lsi_irq_type = { 160 .name = "LSI", 161 .irq_unmask = io7_enable_irq, 162 .irq_mask = io7_disable_irq, 163 .irq_mask_ack = io7_disable_irq, 164 }; 165 166 static struct irq_chip io7_msi_irq_type = { 167 .name = "MSI", 168 .irq_unmask = io7_enable_irq, 169 .irq_mask = io7_disable_irq, 170 .irq_ack = marvel_irq_noop, 171 }; 172 173 static void 174 io7_redirect_irq(struct io7 *io7, 175 volatile unsigned long *csr, 176 unsigned int where) 177 { 178 unsigned long val; 179 180 val = *csr; 181 val &= ~(0x1ffUL << 24); /* clear the target pid */ 182 val |= ((unsigned long)where << 24); /* set the new target pid */ 183 184 *csr = val; 185 mb(); 186 *csr; 187 } 188 189 static void 190 io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where) 191 { 192 unsigned long val; 193 194 /* 195 * LSI_CTL has target PID @ 14 196 */ 197 val = io7->csrs->PO7_LSI_CTL[which].csr; 198 val &= ~(0x1ffUL << 14); /* clear the target pid */ 199 val |= ((unsigned long)where << 14); /* set the new target pid */ 200 201 io7->csrs->PO7_LSI_CTL[which].csr = val; 202 mb(); 203 io7->csrs->PO7_LSI_CTL[which].csr; 204 } 205 206 static void 207 io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where) 208 { 209 unsigned long val; 210 211 /* 212 * MSI_CTL has target PID @ 14 213 */ 214 val = io7->csrs->PO7_MSI_CTL[which].csr; 215 val &= ~(0x1ffUL << 14); /* clear the target pid */ 216 val |= ((unsigned long)where << 14); /* set the new target pid */ 217 218 io7->csrs->PO7_MSI_CTL[which].csr = val; 219 mb(); 220 io7->csrs->PO7_MSI_CTL[which].csr; 221 } 222 223 static void __init 224 init_one_io7_lsi(struct io7 *io7, unsigned int which, unsigned int where) 225 { 226 /* 227 * LSI_CTL has target PID @ 14 228 */ 229 io7->csrs->PO7_LSI_CTL[which].csr = ((unsigned long)where << 14); 230 mb(); 231 io7->csrs->PO7_LSI_CTL[which].csr; 232 } 233 234 static void __init 235 init_one_io7_msi(struct io7 *io7, unsigned int which, unsigned int where) 236 { 237 /* 238 * MSI_CTL has target PID @ 14 239 */ 240 io7->csrs->PO7_MSI_CTL[which].csr = ((unsigned long)where << 14); 241 mb(); 242 io7->csrs->PO7_MSI_CTL[which].csr; 243 } 244 245 static void __init 246 init_io7_irqs(struct io7 *io7, 247 struct irq_chip *lsi_ops, 248 struct irq_chip *msi_ops) 249 { 250 long base = (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT) + 16; 251 long i; 252 253 printk("Initializing interrupts for IO7 at PE %u - base %lx\n", 254 io7->pe, base); 255 256 /* 257 * Where should interrupts from this IO7 go? 258 * 259 * They really should be sent to the local CPU to avoid having to 260 * traverse the mesh, but if it's not an SMP kernel, they have to 261 * go to the boot CPU. Send them all to the boot CPU for now, 262 * as each secondary starts, it can redirect it's local device 263 * interrupts. 264 */ 265 printk(" Interrupts reported to CPU at PE %u\n", boot_cpuid); 266 267 spin_lock(&io7->irq_lock); 268 269 /* set up the error irqs */ 270 io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, boot_cpuid); 271 io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, boot_cpuid); 272 io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, boot_cpuid); 273 io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid); 274 io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid); 275 276 /* Set up the lsi irqs. */ 277 for (i = 0; i < 128; ++i) { 278 irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq); 279 irq_set_status_flags(i, IRQ_LEVEL); 280 } 281 282 /* Disable the implemented irqs in hardware. */ 283 for (i = 0; i < 0x60; ++i) 284 init_one_io7_lsi(io7, i, boot_cpuid); 285 286 init_one_io7_lsi(io7, 0x74, boot_cpuid); 287 init_one_io7_lsi(io7, 0x75, boot_cpuid); 288 289 290 /* Set up the msi irqs. */ 291 for (i = 128; i < (128 + 512); ++i) { 292 irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq); 293 irq_set_status_flags(i, IRQ_LEVEL); 294 } 295 296 for (i = 0; i < 16; ++i) 297 init_one_io7_msi(io7, i, boot_cpuid); 298 299 spin_unlock(&io7->irq_lock); 300 } 301 302 static void __init 303 marvel_init_irq(void) 304 { 305 int i; 306 struct io7 *io7 = NULL; 307 308 /* Reserve the legacy irqs. */ 309 for (i = 0; i < 16; ++i) { 310 irq_set_chip_and_handler(i, &marvel_legacy_irq_type, 311 handle_level_irq); 312 } 313 314 /* Init the io7 irqs. */ 315 for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) 316 init_io7_irqs(io7, &io7_lsi_irq_type, &io7_msi_irq_type); 317 } 318 319 static int 320 marvel_map_irq(const struct pci_dev *cdev, u8 slot, u8 pin) 321 { 322 struct pci_dev *dev = (struct pci_dev *)cdev; 323 struct pci_controller *hose = dev->sysdata; 324 struct io7_port *io7_port = hose->sysdata; 325 struct io7 *io7 = io7_port->io7; 326 int msi_loc, msi_data_off; 327 u16 msg_ctl; 328 u16 msg_dat; 329 u8 intline; 330 int irq; 331 332 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline); 333 irq = intline; 334 335 msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI); 336 msg_ctl = 0; 337 if (msi_loc) 338 pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl); 339 340 if (msg_ctl & PCI_MSI_FLAGS_ENABLE) { 341 msi_data_off = PCI_MSI_DATA_32; 342 if (msg_ctl & PCI_MSI_FLAGS_64BIT) 343 msi_data_off = PCI_MSI_DATA_64; 344 pci_read_config_word(dev, msi_loc + msi_data_off, &msg_dat); 345 346 irq = msg_dat & 0x1ff; /* we use msg_data<8:0> */ 347 irq += 0x80; /* offset for lsi */ 348 349 #if 1 350 printk("PCI:%d:%d:%d (hose %d) is using MSI\n", 351 dev->bus->number, 352 PCI_SLOT(dev->devfn), 353 PCI_FUNC(dev->devfn), 354 hose->index); 355 printk(" %d message(s) from 0x%04x\n", 356 1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4), 357 msg_dat); 358 printk(" reporting on %d IRQ(s) from %d (0x%x)\n", 359 1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4), 360 (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT), 361 (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT)); 362 #endif 363 364 #if 0 365 pci_write_config_word(dev, msi_loc + PCI_MSI_FLAGS, 366 msg_ctl & ~PCI_MSI_FLAGS_ENABLE); 367 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline); 368 irq = intline; 369 370 printk(" forcing LSI interrupt on irq %d [0x%x]\n", irq, irq); 371 #endif 372 } 373 374 irq += 16; /* offset for legacy */ 375 irq |= io7->pe << MARVEL_IRQ_VEC_PE_SHIFT; /* merge the pid */ 376 377 return irq; 378 } 379 380 static void __init 381 marvel_init_pci(void) 382 { 383 struct io7 *io7; 384 385 marvel_register_error_handlers(); 386 387 /* Indicate that we trust the console to configure things properly */ 388 pci_set_flags(PCI_PROBE_ONLY); 389 common_init_pci(); 390 locate_and_init_vga(NULL); 391 392 /* Clear any io7 errors. */ 393 for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) 394 io7_clear_errors(io7); 395 } 396 397 static void __init 398 marvel_init_rtc(void) 399 { 400 init_rtc_irq(); 401 } 402 403 struct marvel_rtc_time { 404 struct rtc_time *time; 405 int retval; 406 }; 407 408 #ifdef CONFIG_SMP 409 static void 410 smp_get_rtc_time(void *data) 411 { 412 struct marvel_rtc_time *mrt = data; 413 mrt->retval = __get_rtc_time(mrt->time); 414 } 415 416 static void 417 smp_set_rtc_time(void *data) 418 { 419 struct marvel_rtc_time *mrt = data; 420 mrt->retval = __set_rtc_time(mrt->time); 421 } 422 #endif 423 424 static unsigned int 425 marvel_get_rtc_time(struct rtc_time *time) 426 { 427 #ifdef CONFIG_SMP 428 struct marvel_rtc_time mrt; 429 430 if (smp_processor_id() != boot_cpuid) { 431 mrt.time = time; 432 smp_call_function_single(boot_cpuid, smp_get_rtc_time, &mrt, 1); 433 return mrt.retval; 434 } 435 #endif 436 return __get_rtc_time(time); 437 } 438 439 static int 440 marvel_set_rtc_time(struct rtc_time *time) 441 { 442 #ifdef CONFIG_SMP 443 struct marvel_rtc_time mrt; 444 445 if (smp_processor_id() != boot_cpuid) { 446 mrt.time = time; 447 smp_call_function_single(boot_cpuid, smp_set_rtc_time, &mrt, 1); 448 return mrt.retval; 449 } 450 #endif 451 return __set_rtc_time(time); 452 } 453 454 static void 455 marvel_smp_callin(void) 456 { 457 int cpuid = hard_smp_processor_id(); 458 struct io7 *io7 = marvel_find_io7(cpuid); 459 unsigned int i; 460 461 if (!io7) 462 return; 463 464 /* 465 * There is a local IO7 - redirect all of its interrupts here. 466 */ 467 printk("Redirecting IO7 interrupts to local CPU at PE %u\n", cpuid); 468 469 /* Redirect the error IRQS here. */ 470 io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, cpuid); 471 io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, cpuid); 472 io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, cpuid); 473 io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, cpuid); 474 io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, cpuid); 475 476 /* Redirect the implemented LSIs here. */ 477 for (i = 0; i < 0x60; ++i) 478 io7_redirect_one_lsi(io7, i, cpuid); 479 480 io7_redirect_one_lsi(io7, 0x74, cpuid); 481 io7_redirect_one_lsi(io7, 0x75, cpuid); 482 483 /* Redirect the MSIs here. */ 484 for (i = 0; i < 16; ++i) 485 io7_redirect_one_msi(io7, i, cpuid); 486 } 487 488 /* 489 * System Vectors 490 */ 491 struct alpha_machine_vector marvel_ev7_mv __initmv = { 492 .vector_name = "MARVEL/EV7", 493 DO_EV7_MMU, 494 .rtc_port = 0x70, 495 .rtc_get_time = marvel_get_rtc_time, 496 .rtc_set_time = marvel_set_rtc_time, 497 DO_MARVEL_IO, 498 .machine_check = marvel_machine_check, 499 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 500 .min_io_address = DEFAULT_IO_BASE, 501 .min_mem_address = DEFAULT_MEM_BASE, 502 .pci_dac_offset = IO7_DAC_OFFSET, 503 504 .nr_irqs = MARVEL_NR_IRQS, 505 .device_interrupt = io7_device_interrupt, 506 507 .agp_info = marvel_agp_info, 508 509 .smp_callin = marvel_smp_callin, 510 .init_arch = marvel_init_arch, 511 .init_irq = marvel_init_irq, 512 .init_rtc = marvel_init_rtc, 513 .init_pci = marvel_init_pci, 514 .kill_arch = marvel_kill_arch, 515 .pci_map_irq = marvel_map_irq, 516 .pci_swizzle = common_swizzle, 517 518 .pa_to_nid = marvel_pa_to_nid, 519 .cpuid_to_nid = marvel_cpuid_to_nid, 520 .node_mem_start = marvel_node_mem_start, 521 .node_mem_size = marvel_node_mem_size, 522 }; 523 ALIAS_MV(marvel_ev7) 524