at v2.6.24 609 lines 15 kB view raw
1/* 2 * General Purpose functions for the global management of the 3 * Communication Processor Module. 4 * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) 5 * 6 * In addition to the individual control of the communication 7 * channels, there are a few functions that globally affect the 8 * communication processor. 9 * 10 * Buffer descriptors must be allocated from the dual ported memory 11 * space. The allocator for that is here. When the communication 12 * process is reset, we reclaim the memory available. There is 13 * currently no deallocator for this memory. 14 * The amount of space available is platform dependent. On the 15 * MBX, the EPPC software loads additional microcode into the 16 * communication processor, and uses some of the DP ram for this 17 * purpose. Current, the first 512 bytes and the last 256 bytes of 18 * memory are used. Right now I am conservative and only use the 19 * memory that can never be used for microcode. If there are 20 * applications that require more DP ram, we can expand the boundaries 21 * but then we have to be careful of any downloaded microcode. 22 */ 23#include <linux/errno.h> 24#include <linux/sched.h> 25#include <linux/kernel.h> 26#include <linux/dma-mapping.h> 27#include <linux/param.h> 28#include <linux/string.h> 29#include <linux/mm.h> 30#include <linux/interrupt.h> 31#include <linux/irq.h> 32#include <linux/module.h> 33#include <asm/mpc8xx.h> 34#include <asm/page.h> 35#include <asm/pgtable.h> 36#include <asm/8xx_immap.h> 37#include <asm/commproc.h> 38#include <asm/io.h> 39#include <asm/tlbflush.h> 40#include <asm/rheap.h> 41#include <asm/prom.h> 42#include <asm/cpm.h> 43 44#include <asm/fs_pd.h> 45 46#define CPM_MAP_SIZE (0x4000) 47 48#ifndef CONFIG_PPC_CPM_NEW_BINDING 49static void m8xx_cpm_dpinit(void); 50#endif 51static uint host_buffer; /* One page of host buffer */ 52static uint host_end; /* end + 1 */ 53cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ 54immap_t __iomem *mpc8xx_immr; 55static cpic8xx_t __iomem *cpic_reg; 56 57static struct irq_host *cpm_pic_host; 58 59static void cpm_mask_irq(unsigned int irq) 60{ 61 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq; 62 63 clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec)); 64} 65 66static void cpm_unmask_irq(unsigned int irq) 67{ 68 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq; 69 70 setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec)); 71} 72 73static void cpm_end_irq(unsigned int irq) 74{ 75 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq; 76 77 out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec)); 78} 79 80static struct irq_chip cpm_pic = { 81 .typename = " CPM PIC ", 82 .mask = cpm_mask_irq, 83 .unmask = cpm_unmask_irq, 84 .eoi = cpm_end_irq, 85}; 86 87int cpm_get_irq(void) 88{ 89 int cpm_vec; 90 91 /* Get the vector by setting the ACK bit and then reading 92 * the register. 93 */ 94 out_be16(&cpic_reg->cpic_civr, 1); 95 cpm_vec = in_be16(&cpic_reg->cpic_civr); 96 cpm_vec >>= 11; 97 98 return irq_linear_revmap(cpm_pic_host, cpm_vec); 99} 100 101static int cpm_pic_host_map(struct irq_host *h, unsigned int virq, 102 irq_hw_number_t hw) 103{ 104 pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); 105 106 get_irq_desc(virq)->status |= IRQ_LEVEL; 107 set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); 108 return 0; 109} 110 111/* The CPM can generate the error interrupt when there is a race condition 112 * between generating and masking interrupts. All we have to do is ACK it 113 * and return. This is a no-op function so we don't need any special 114 * tests in the interrupt handler. 115 */ 116static irqreturn_t cpm_error_interrupt(int irq, void *dev) 117{ 118 return IRQ_HANDLED; 119} 120 121static struct irqaction cpm_error_irqaction = { 122 .handler = cpm_error_interrupt, 123 .mask = CPU_MASK_NONE, 124 .name = "error", 125}; 126 127static struct irq_host_ops cpm_pic_host_ops = { 128 .map = cpm_pic_host_map, 129}; 130 131unsigned int cpm_pic_init(void) 132{ 133 struct device_node *np = NULL; 134 struct resource res; 135 unsigned int sirq = NO_IRQ, hwirq, eirq; 136 int ret; 137 138 pr_debug("cpm_pic_init\n"); 139 140 np = of_find_compatible_node(NULL, NULL, "fsl,cpm1-pic"); 141 if (np == NULL) 142 np = of_find_compatible_node(NULL, "cpm-pic", "CPM"); 143 if (np == NULL) { 144 printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n"); 145 return sirq; 146 } 147 148 ret = of_address_to_resource(np, 0, &res); 149 if (ret) 150 goto end; 151 152 cpic_reg = ioremap(res.start, res.end - res.start + 1); 153 if (cpic_reg == NULL) 154 goto end; 155 156 sirq = irq_of_parse_and_map(np, 0); 157 if (sirq == NO_IRQ) 158 goto end; 159 160 /* Initialize the CPM interrupt controller. */ 161 hwirq = (unsigned int)irq_map[sirq].hwirq; 162 out_be32(&cpic_reg->cpic_cicr, 163 (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | 164 ((hwirq/2) << 13) | CICR_HP_MASK); 165 166 out_be32(&cpic_reg->cpic_cimr, 0); 167 168 cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR, 169 64, &cpm_pic_host_ops, 64); 170 if (cpm_pic_host == NULL) { 171 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); 172 sirq = NO_IRQ; 173 goto end; 174 } 175 176 /* Install our own error handler. */ 177 np = of_find_compatible_node(NULL, NULL, "fsl,cpm1"); 178 if (np == NULL) 179 np = of_find_node_by_type(NULL, "cpm"); 180 if (np == NULL) { 181 printk(KERN_ERR "CPM PIC init: can not find cpm node\n"); 182 goto end; 183 } 184 185 eirq = irq_of_parse_and_map(np, 0); 186 if (eirq == NO_IRQ) 187 goto end; 188 189 if (setup_irq(eirq, &cpm_error_irqaction)) 190 printk(KERN_ERR "Could not allocate CPM error IRQ!"); 191 192 setbits32(&cpic_reg->cpic_cicr, CICR_IEN); 193 194end: 195 of_node_put(np); 196 return sirq; 197} 198 199void __init cpm_reset(void) 200{ 201 sysconf8xx_t __iomem *siu_conf; 202 203 mpc8xx_immr = ioremap(get_immrbase(), 0x4000); 204 if (!mpc8xx_immr) { 205 printk(KERN_CRIT "Could not map IMMR\n"); 206 return; 207 } 208 209 cpmp = &mpc8xx_immr->im_cpm; 210 211#ifndef CONFIG_PPC_EARLY_DEBUG_CPM 212 /* Perform a reset. 213 */ 214 out_be16(&cpmp->cp_cpcr, CPM_CR_RST | CPM_CR_FLG); 215 216 /* Wait for it. 217 */ 218 while (in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG); 219#endif 220 221#ifdef CONFIG_UCODE_PATCH 222 cpm_load_patch(cpmp); 223#endif 224 225 /* Set SDMA Bus Request priority 5. 226 * On 860T, this also enables FEC priority 6. I am not sure 227 * this is what we realy want for some applications, but the 228 * manual recommends it. 229 * Bit 25, FAM can also be set to use FEC aggressive mode (860T). 230 */ 231 siu_conf = immr_map(im_siu_conf); 232 out_be32(&siu_conf->sc_sdcr, 1); 233 immr_unmap(siu_conf); 234 235#ifdef CONFIG_PPC_CPM_NEW_BINDING 236 cpm_muram_init(); 237#else 238 /* Reclaim the DP memory for our use. */ 239 m8xx_cpm_dpinit(); 240#endif 241} 242 243/* We used to do this earlier, but have to postpone as long as possible 244 * to ensure the kernel VM is now running. 245 */ 246static void 247alloc_host_memory(void) 248{ 249 dma_addr_t physaddr; 250 251 /* Set the host page for allocation. 252 */ 253 host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr, 254 GFP_KERNEL); 255 host_end = host_buffer + PAGE_SIZE; 256} 257 258/* We also own one page of host buffer space for the allocation of 259 * UART "fifos" and the like. 260 */ 261uint 262m8xx_cpm_hostalloc(uint size) 263{ 264 uint retloc; 265 266 if (host_buffer == 0) 267 alloc_host_memory(); 268 269 if ((host_buffer + size) >= host_end) 270 return(0); 271 272 retloc = host_buffer; 273 host_buffer += size; 274 275 return(retloc); 276} 277 278/* Set a baud rate generator. This needs lots of work. There are 279 * four BRGs, any of which can be wired to any channel. 280 * The internal baud rate clock is the system clock divided by 16. 281 * This assumes the baudrate is 16x oversampled by the uart. 282 */ 283#define BRG_INT_CLK (get_brgfreq()) 284#define BRG_UART_CLK (BRG_INT_CLK/16) 285#define BRG_UART_CLK_DIV16 (BRG_UART_CLK/16) 286 287void 288cpm_setbrg(uint brg, uint rate) 289{ 290 u32 __iomem *bp; 291 292 /* This is good enough to get SMCs running..... 293 */ 294 bp = &cpmp->cp_brgc1; 295 bp += brg; 296 /* The BRG has a 12-bit counter. For really slow baud rates (or 297 * really fast processors), we may have to further divide by 16. 298 */ 299 if (((BRG_UART_CLK / rate) - 1) < 4096) 300 out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN); 301 else 302 out_be32(bp, (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) | 303 CPM_BRG_EN | CPM_BRG_DIV16); 304} 305 306#ifndef CONFIG_PPC_CPM_NEW_BINDING 307/* 308 * dpalloc / dpfree bits. 309 */ 310static spinlock_t cpm_dpmem_lock; 311/* 312 * 16 blocks should be enough to satisfy all requests 313 * until the memory subsystem goes up... 314 */ 315static rh_block_t cpm_boot_dpmem_rh_block[16]; 316static rh_info_t cpm_dpmem_info; 317 318#define CPM_DPMEM_ALIGNMENT 8 319static u8 __iomem *dpram_vbase; 320static phys_addr_t dpram_pbase; 321 322static void m8xx_cpm_dpinit(void) 323{ 324 spin_lock_init(&cpm_dpmem_lock); 325 326 dpram_vbase = cpmp->cp_dpmem; 327 dpram_pbase = get_immrbase() + offsetof(immap_t, im_cpm.cp_dpmem); 328 329 /* Initialize the info header */ 330 rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT, 331 sizeof(cpm_boot_dpmem_rh_block) / 332 sizeof(cpm_boot_dpmem_rh_block[0]), 333 cpm_boot_dpmem_rh_block); 334 335 /* 336 * Attach the usable dpmem area. 337 * XXX: This is actually crap. CPM_DATAONLY_BASE and 338 * CPM_DATAONLY_SIZE are a subset of the available dparm. It varies 339 * with the processor and the microcode patches applied / activated. 340 * But the following should be at least safe. 341 */ 342 rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); 343} 344 345/* 346 * Allocate the requested size worth of DP memory. 347 * This function returns an offset into the DPRAM area. 348 * Use cpm_dpram_addr() to get the virtual address of the area. 349 */ 350unsigned long cpm_dpalloc(uint size, uint align) 351{ 352 unsigned long start; 353 unsigned long flags; 354 355 spin_lock_irqsave(&cpm_dpmem_lock, flags); 356 cpm_dpmem_info.alignment = align; 357 start = rh_alloc(&cpm_dpmem_info, size, "commproc"); 358 spin_unlock_irqrestore(&cpm_dpmem_lock, flags); 359 360 return (uint)start; 361} 362EXPORT_SYMBOL(cpm_dpalloc); 363 364int cpm_dpfree(unsigned long offset) 365{ 366 int ret; 367 unsigned long flags; 368 369 spin_lock_irqsave(&cpm_dpmem_lock, flags); 370 ret = rh_free(&cpm_dpmem_info, offset); 371 spin_unlock_irqrestore(&cpm_dpmem_lock, flags); 372 373 return ret; 374} 375EXPORT_SYMBOL(cpm_dpfree); 376 377unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align) 378{ 379 unsigned long start; 380 unsigned long flags; 381 382 spin_lock_irqsave(&cpm_dpmem_lock, flags); 383 cpm_dpmem_info.alignment = align; 384 start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc"); 385 spin_unlock_irqrestore(&cpm_dpmem_lock, flags); 386 387 return start; 388} 389EXPORT_SYMBOL(cpm_dpalloc_fixed); 390 391void cpm_dpdump(void) 392{ 393 rh_dump(&cpm_dpmem_info); 394} 395EXPORT_SYMBOL(cpm_dpdump); 396 397void *cpm_dpram_addr(unsigned long offset) 398{ 399 return (void *)(dpram_vbase + offset); 400} 401EXPORT_SYMBOL(cpm_dpram_addr); 402 403uint cpm_dpram_phys(u8 *addr) 404{ 405 return (dpram_pbase + (uint)(addr - dpram_vbase)); 406} 407EXPORT_SYMBOL(cpm_dpram_phys); 408#endif /* !CONFIG_PPC_CPM_NEW_BINDING */ 409 410struct cpm_ioport16 { 411 __be16 dir, par, sor, dat, intr; 412 __be16 res[3]; 413}; 414 415struct cpm_ioport32 { 416 __be32 dir, par, sor; 417}; 418 419static void cpm1_set_pin32(int port, int pin, int flags) 420{ 421 struct cpm_ioport32 __iomem *iop; 422 pin = 1 << (31 - pin); 423 424 if (port == CPM_PORTB) 425 iop = (struct cpm_ioport32 __iomem *) 426 &mpc8xx_immr->im_cpm.cp_pbdir; 427 else 428 iop = (struct cpm_ioport32 __iomem *) 429 &mpc8xx_immr->im_cpm.cp_pedir; 430 431 if (flags & CPM_PIN_OUTPUT) 432 setbits32(&iop->dir, pin); 433 else 434 clrbits32(&iop->dir, pin); 435 436 if (!(flags & CPM_PIN_GPIO)) 437 setbits32(&iop->par, pin); 438 else 439 clrbits32(&iop->par, pin); 440 441 if (port == CPM_PORTE) { 442 if (flags & CPM_PIN_SECONDARY) 443 setbits32(&iop->sor, pin); 444 else 445 clrbits32(&iop->sor, pin); 446 447 if (flags & CPM_PIN_OPENDRAIN) 448 setbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin); 449 else 450 clrbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin); 451 } 452} 453 454static void cpm1_set_pin16(int port, int pin, int flags) 455{ 456 struct cpm_ioport16 __iomem *iop = 457 (struct cpm_ioport16 __iomem *)&mpc8xx_immr->im_ioport; 458 459 pin = 1 << (15 - pin); 460 461 if (port != 0) 462 iop += port - 1; 463 464 if (flags & CPM_PIN_OUTPUT) 465 setbits16(&iop->dir, pin); 466 else 467 clrbits16(&iop->dir, pin); 468 469 if (!(flags & CPM_PIN_GPIO)) 470 setbits16(&iop->par, pin); 471 else 472 clrbits16(&iop->par, pin); 473 474 if (port == CPM_PORTC) { 475 if (flags & CPM_PIN_SECONDARY) 476 setbits16(&iop->sor, pin); 477 else 478 clrbits16(&iop->sor, pin); 479 } 480} 481 482void cpm1_set_pin(enum cpm_port port, int pin, int flags) 483{ 484 if (port == CPM_PORTB || port == CPM_PORTE) 485 cpm1_set_pin32(port, pin, flags); 486 else 487 cpm1_set_pin16(port, pin, flags); 488} 489 490int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode) 491{ 492 int shift; 493 int i, bits = 0; 494 u32 __iomem *reg; 495 u32 mask = 7; 496 497 u8 clk_map[][3] = { 498 {CPM_CLK_SCC1, CPM_BRG1, 0}, 499 {CPM_CLK_SCC1, CPM_BRG2, 1}, 500 {CPM_CLK_SCC1, CPM_BRG3, 2}, 501 {CPM_CLK_SCC1, CPM_BRG4, 3}, 502 {CPM_CLK_SCC1, CPM_CLK1, 4}, 503 {CPM_CLK_SCC1, CPM_CLK2, 5}, 504 {CPM_CLK_SCC1, CPM_CLK3, 6}, 505 {CPM_CLK_SCC1, CPM_CLK4, 7}, 506 507 {CPM_CLK_SCC2, CPM_BRG1, 0}, 508 {CPM_CLK_SCC2, CPM_BRG2, 1}, 509 {CPM_CLK_SCC2, CPM_BRG3, 2}, 510 {CPM_CLK_SCC2, CPM_BRG4, 3}, 511 {CPM_CLK_SCC2, CPM_CLK1, 4}, 512 {CPM_CLK_SCC2, CPM_CLK2, 5}, 513 {CPM_CLK_SCC2, CPM_CLK3, 6}, 514 {CPM_CLK_SCC2, CPM_CLK4, 7}, 515 516 {CPM_CLK_SCC3, CPM_BRG1, 0}, 517 {CPM_CLK_SCC3, CPM_BRG2, 1}, 518 {CPM_CLK_SCC3, CPM_BRG3, 2}, 519 {CPM_CLK_SCC3, CPM_BRG4, 3}, 520 {CPM_CLK_SCC3, CPM_CLK5, 4}, 521 {CPM_CLK_SCC3, CPM_CLK6, 5}, 522 {CPM_CLK_SCC3, CPM_CLK7, 6}, 523 {CPM_CLK_SCC3, CPM_CLK8, 7}, 524 525 {CPM_CLK_SCC4, CPM_BRG1, 0}, 526 {CPM_CLK_SCC4, CPM_BRG2, 1}, 527 {CPM_CLK_SCC4, CPM_BRG3, 2}, 528 {CPM_CLK_SCC4, CPM_BRG4, 3}, 529 {CPM_CLK_SCC4, CPM_CLK5, 4}, 530 {CPM_CLK_SCC4, CPM_CLK6, 5}, 531 {CPM_CLK_SCC4, CPM_CLK7, 6}, 532 {CPM_CLK_SCC4, CPM_CLK8, 7}, 533 534 {CPM_CLK_SMC1, CPM_BRG1, 0}, 535 {CPM_CLK_SMC1, CPM_BRG2, 1}, 536 {CPM_CLK_SMC1, CPM_BRG3, 2}, 537 {CPM_CLK_SMC1, CPM_BRG4, 3}, 538 {CPM_CLK_SMC1, CPM_CLK1, 4}, 539 {CPM_CLK_SMC1, CPM_CLK2, 5}, 540 {CPM_CLK_SMC1, CPM_CLK3, 6}, 541 {CPM_CLK_SMC1, CPM_CLK4, 7}, 542 543 {CPM_CLK_SMC2, CPM_BRG1, 0}, 544 {CPM_CLK_SMC2, CPM_BRG2, 1}, 545 {CPM_CLK_SMC2, CPM_BRG3, 2}, 546 {CPM_CLK_SMC2, CPM_BRG4, 3}, 547 {CPM_CLK_SMC2, CPM_CLK5, 4}, 548 {CPM_CLK_SMC2, CPM_CLK6, 5}, 549 {CPM_CLK_SMC2, CPM_CLK7, 6}, 550 {CPM_CLK_SMC2, CPM_CLK8, 7}, 551 }; 552 553 switch (target) { 554 case CPM_CLK_SCC1: 555 reg = &mpc8xx_immr->im_cpm.cp_sicr; 556 shift = 0; 557 break; 558 559 case CPM_CLK_SCC2: 560 reg = &mpc8xx_immr->im_cpm.cp_sicr; 561 shift = 8; 562 break; 563 564 case CPM_CLK_SCC3: 565 reg = &mpc8xx_immr->im_cpm.cp_sicr; 566 shift = 16; 567 break; 568 569 case CPM_CLK_SCC4: 570 reg = &mpc8xx_immr->im_cpm.cp_sicr; 571 shift = 24; 572 break; 573 574 case CPM_CLK_SMC1: 575 reg = &mpc8xx_immr->im_cpm.cp_simode; 576 shift = 12; 577 break; 578 579 case CPM_CLK_SMC2: 580 reg = &mpc8xx_immr->im_cpm.cp_simode; 581 shift = 28; 582 break; 583 584 default: 585 printk(KERN_ERR "cpm1_clock_setup: invalid clock target\n"); 586 return -EINVAL; 587 } 588 589 if (reg == &mpc8xx_immr->im_cpm.cp_sicr && mode == CPM_CLK_RX) 590 shift += 3; 591 592 for (i = 0; i < ARRAY_SIZE(clk_map); i++) { 593 if (clk_map[i][0] == target && clk_map[i][1] == clock) { 594 bits = clk_map[i][2]; 595 break; 596 } 597 } 598 599 if (i == ARRAY_SIZE(clk_map)) { 600 printk(KERN_ERR "cpm1_clock_setup: invalid clock combination\n"); 601 return -EINVAL; 602 } 603 604 bits <<= shift; 605 mask <<= shift; 606 out_be32(reg, (in_be32(reg) & ~mask) | bits); 607 608 return 0; 609}