diff options
Diffstat (limited to 'arch/powerpc/sysdev/commproc.c')
-rw-r--r-- | arch/powerpc/sysdev/commproc.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c index f8f3741acd87..428eb8c151b9 100644 --- a/arch/powerpc/sysdev/commproc.c +++ b/arch/powerpc/sysdev/commproc.c | |||
@@ -397,3 +397,204 @@ uint cpm_dpram_phys(u8 *addr) | |||
397 | return (dpram_pbase + (uint)(addr - dpram_vbase)); | 397 | return (dpram_pbase + (uint)(addr - dpram_vbase)); |
398 | } | 398 | } |
399 | EXPORT_SYMBOL(cpm_dpram_phys); | 399 | EXPORT_SYMBOL(cpm_dpram_phys); |
400 | |||
401 | struct cpm_ioport16 { | ||
402 | __be16 dir, par, sor, dat, intr; | ||
403 | __be16 res[3]; | ||
404 | }; | ||
405 | |||
406 | struct cpm_ioport32 { | ||
407 | __be32 dir, par, sor; | ||
408 | }; | ||
409 | |||
410 | static void cpm1_set_pin32(int port, int pin, int flags) | ||
411 | { | ||
412 | struct cpm_ioport32 __iomem *iop; | ||
413 | pin = 1 << (31 - pin); | ||
414 | |||
415 | if (port == CPM_PORTB) | ||
416 | iop = (struct cpm_ioport32 __iomem *) | ||
417 | &mpc8xx_immr->im_cpm.cp_pbdir; | ||
418 | else | ||
419 | iop = (struct cpm_ioport32 __iomem *) | ||
420 | &mpc8xx_immr->im_cpm.cp_pedir; | ||
421 | |||
422 | if (flags & CPM_PIN_OUTPUT) | ||
423 | setbits32(&iop->dir, pin); | ||
424 | else | ||
425 | clrbits32(&iop->dir, pin); | ||
426 | |||
427 | if (!(flags & CPM_PIN_GPIO)) | ||
428 | setbits32(&iop->par, pin); | ||
429 | else | ||
430 | clrbits32(&iop->par, pin); | ||
431 | |||
432 | if (port == CPM_PORTE) { | ||
433 | if (flags & CPM_PIN_SECONDARY) | ||
434 | setbits32(&iop->sor, pin); | ||
435 | else | ||
436 | clrbits32(&iop->sor, pin); | ||
437 | |||
438 | if (flags & CPM_PIN_OPENDRAIN) | ||
439 | setbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin); | ||
440 | else | ||
441 | clrbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | static void cpm1_set_pin16(int port, int pin, int flags) | ||
446 | { | ||
447 | struct cpm_ioport16 __iomem *iop = | ||
448 | (struct cpm_ioport16 __iomem *)&mpc8xx_immr->im_ioport; | ||
449 | |||
450 | pin = 1 << (15 - pin); | ||
451 | |||
452 | if (port != 0) | ||
453 | iop += port - 1; | ||
454 | |||
455 | if (flags & CPM_PIN_OUTPUT) | ||
456 | setbits16(&iop->dir, pin); | ||
457 | else | ||
458 | clrbits16(&iop->dir, pin); | ||
459 | |||
460 | if (!(flags & CPM_PIN_GPIO)) | ||
461 | setbits16(&iop->par, pin); | ||
462 | else | ||
463 | clrbits16(&iop->par, pin); | ||
464 | |||
465 | if (port == CPM_PORTC) { | ||
466 | if (flags & CPM_PIN_SECONDARY) | ||
467 | setbits16(&iop->sor, pin); | ||
468 | else | ||
469 | clrbits16(&iop->sor, pin); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | void cpm1_set_pin(enum cpm_port port, int pin, int flags) | ||
474 | { | ||
475 | if (port == CPM_PORTB || port == CPM_PORTE) | ||
476 | cpm1_set_pin32(port, pin, flags); | ||
477 | else | ||
478 | cpm1_set_pin16(port, pin, flags); | ||
479 | } | ||
480 | |||
481 | int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode) | ||
482 | { | ||
483 | int shift; | ||
484 | int i, bits = 0; | ||
485 | u32 __iomem *reg; | ||
486 | u32 mask = 7; | ||
487 | |||
488 | u8 clk_map[][3] = { | ||
489 | {CPM_CLK_SCC1, CPM_BRG1, 0}, | ||
490 | {CPM_CLK_SCC1, CPM_BRG2, 1}, | ||
491 | {CPM_CLK_SCC1, CPM_BRG3, 2}, | ||
492 | {CPM_CLK_SCC1, CPM_BRG4, 3}, | ||
493 | {CPM_CLK_SCC1, CPM_CLK1, 4}, | ||
494 | {CPM_CLK_SCC1, CPM_CLK2, 5}, | ||
495 | {CPM_CLK_SCC1, CPM_CLK3, 6}, | ||
496 | {CPM_CLK_SCC1, CPM_CLK4, 7}, | ||
497 | |||
498 | {CPM_CLK_SCC2, CPM_BRG1, 0}, | ||
499 | {CPM_CLK_SCC2, CPM_BRG2, 1}, | ||
500 | {CPM_CLK_SCC2, CPM_BRG3, 2}, | ||
501 | {CPM_CLK_SCC2, CPM_BRG4, 3}, | ||
502 | {CPM_CLK_SCC2, CPM_CLK1, 4}, | ||
503 | {CPM_CLK_SCC2, CPM_CLK2, 5}, | ||
504 | {CPM_CLK_SCC2, CPM_CLK3, 6}, | ||
505 | {CPM_CLK_SCC2, CPM_CLK4, 7}, | ||
506 | |||
507 | {CPM_CLK_SCC3, CPM_BRG1, 0}, | ||
508 | {CPM_CLK_SCC3, CPM_BRG2, 1}, | ||
509 | {CPM_CLK_SCC3, CPM_BRG3, 2}, | ||
510 | {CPM_CLK_SCC3, CPM_BRG4, 3}, | ||
511 | {CPM_CLK_SCC3, CPM_CLK5, 4}, | ||
512 | {CPM_CLK_SCC3, CPM_CLK6, 5}, | ||
513 | {CPM_CLK_SCC3, CPM_CLK7, 6}, | ||
514 | {CPM_CLK_SCC3, CPM_CLK8, 7}, | ||
515 | |||
516 | {CPM_CLK_SCC4, CPM_BRG1, 0}, | ||
517 | {CPM_CLK_SCC4, CPM_BRG2, 1}, | ||
518 | {CPM_CLK_SCC4, CPM_BRG3, 2}, | ||
519 | {CPM_CLK_SCC4, CPM_BRG4, 3}, | ||
520 | {CPM_CLK_SCC4, CPM_CLK5, 4}, | ||
521 | {CPM_CLK_SCC4, CPM_CLK6, 5}, | ||
522 | {CPM_CLK_SCC4, CPM_CLK7, 6}, | ||
523 | {CPM_CLK_SCC4, CPM_CLK8, 7}, | ||
524 | |||
525 | {CPM_CLK_SMC1, CPM_BRG1, 0}, | ||
526 | {CPM_CLK_SMC1, CPM_BRG2, 1}, | ||
527 | {CPM_CLK_SMC1, CPM_BRG3, 2}, | ||
528 | {CPM_CLK_SMC1, CPM_BRG4, 3}, | ||
529 | {CPM_CLK_SMC1, CPM_CLK1, 4}, | ||
530 | {CPM_CLK_SMC1, CPM_CLK2, 5}, | ||
531 | {CPM_CLK_SMC1, CPM_CLK3, 6}, | ||
532 | {CPM_CLK_SMC1, CPM_CLK4, 7}, | ||
533 | |||
534 | {CPM_CLK_SMC2, CPM_BRG1, 0}, | ||
535 | {CPM_CLK_SMC2, CPM_BRG2, 1}, | ||
536 | {CPM_CLK_SMC2, CPM_BRG3, 2}, | ||
537 | {CPM_CLK_SMC2, CPM_BRG4, 3}, | ||
538 | {CPM_CLK_SMC2, CPM_CLK5, 4}, | ||
539 | {CPM_CLK_SMC2, CPM_CLK6, 5}, | ||
540 | {CPM_CLK_SMC2, CPM_CLK7, 6}, | ||
541 | {CPM_CLK_SMC2, CPM_CLK8, 7}, | ||
542 | }; | ||
543 | |||
544 | switch (target) { | ||
545 | case CPM_CLK_SCC1: | ||
546 | reg = &mpc8xx_immr->im_cpm.cp_sicr; | ||
547 | shift = 0; | ||
548 | break; | ||
549 | |||
550 | case CPM_CLK_SCC2: | ||
551 | reg = &mpc8xx_immr->im_cpm.cp_sicr; | ||
552 | shift = 8; | ||
553 | break; | ||
554 | |||
555 | case CPM_CLK_SCC3: | ||
556 | reg = &mpc8xx_immr->im_cpm.cp_sicr; | ||
557 | shift = 16; | ||
558 | break; | ||
559 | |||
560 | case CPM_CLK_SCC4: | ||
561 | reg = &mpc8xx_immr->im_cpm.cp_sicr; | ||
562 | shift = 24; | ||
563 | break; | ||
564 | |||
565 | case CPM_CLK_SMC1: | ||
566 | reg = &mpc8xx_immr->im_cpm.cp_simode; | ||
567 | shift = 12; | ||
568 | break; | ||
569 | |||
570 | case CPM_CLK_SMC2: | ||
571 | reg = &mpc8xx_immr->im_cpm.cp_simode; | ||
572 | shift = 28; | ||
573 | break; | ||
574 | |||
575 | default: | ||
576 | printk(KERN_ERR "cpm1_clock_setup: invalid clock target\n"); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | |||
580 | if (reg == &mpc8xx_immr->im_cpm.cp_sicr && mode == CPM_CLK_RX) | ||
581 | shift += 3; | ||
582 | |||
583 | for (i = 0; i < ARRAY_SIZE(clk_map); i++) { | ||
584 | if (clk_map[i][0] == target && clk_map[i][1] == clock) { | ||
585 | bits = clk_map[i][2]; | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if (i == ARRAY_SIZE(clk_map)) { | ||
591 | printk(KERN_ERR "cpm1_clock_setup: invalid clock combination\n"); | ||
592 | return -EINVAL; | ||
593 | } | ||
594 | |||
595 | bits <<= shift; | ||
596 | mask <<= shift; | ||
597 | out_be32(reg, (in_be32(reg) & ~mask) | bits); | ||
598 | |||
599 | return 0; | ||
600 | } | ||