mpp.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * arch/arm/mach-orion5x/mpp.c
  3. *
  4. * MPP functions for Marvell Orion 5x SoCs
  5. *
  6. * This file is licensed under the terms of the GNU General Public
  7. * License version 2. This program is licensed "as is" without any
  8. * warranty of any kind, whether express or implied.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/mbus.h>
  13. #include <linux/io.h>
  14. #include <asm/gpio.h>
  15. #include <mach/hardware.h>
  16. #include "common.h"
  17. #include "mpp.h"
  18. static int is_5181l(void)
  19. {
  20. u32 dev;
  21. u32 rev;
  22. orion5x_pcie_id(&dev, &rev);
  23. return !!(dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0);
  24. }
  25. static int is_5182(void)
  26. {
  27. u32 dev;
  28. u32 rev;
  29. orion5x_pcie_id(&dev, &rev);
  30. return !!(dev == MV88F5182_DEV_ID);
  31. }
  32. static int is_5281(void)
  33. {
  34. u32 dev;
  35. u32 rev;
  36. orion5x_pcie_id(&dev, &rev);
  37. return !!(dev == MV88F5281_DEV_ID);
  38. }
  39. static int __init determine_type_encoding(int mpp, enum orion5x_mpp_type type)
  40. {
  41. switch (type) {
  42. case MPP_UNUSED:
  43. case MPP_GPIO:
  44. if (mpp == 0)
  45. return 3;
  46. if (mpp >= 1 && mpp <= 15)
  47. return 0;
  48. if (mpp >= 16 && mpp <= 19) {
  49. if (is_5182())
  50. return 5;
  51. if (type == MPP_UNUSED)
  52. return 0;
  53. }
  54. return -1;
  55. case MPP_PCIE_RST_OUTn:
  56. if (mpp == 0)
  57. return 0;
  58. return -1;
  59. case MPP_PCI_ARB:
  60. if (mpp >= 0 && mpp <= 7)
  61. return 2;
  62. return -1;
  63. case MPP_PCI_PMEn:
  64. if (mpp == 2)
  65. return 3;
  66. return -1;
  67. case MPP_GIGE:
  68. if (mpp >= 8 && mpp <= 19)
  69. return 1;
  70. return -1;
  71. case MPP_NAND:
  72. if (is_5182() || is_5281()) {
  73. if (mpp >= 4 && mpp <= 7)
  74. return 4;
  75. if (mpp >= 12 && mpp <= 17)
  76. return 4;
  77. }
  78. return -1;
  79. case MPP_PCI_CLK:
  80. if (is_5181l() && mpp >= 6 && mpp <= 7)
  81. return 5;
  82. return -1;
  83. case MPP_SATA_LED:
  84. if (is_5182()) {
  85. if (mpp >= 4 && mpp <= 7)
  86. return 5;
  87. if (mpp >= 12 && mpp <= 15)
  88. return 5;
  89. }
  90. return -1;
  91. case MPP_UART:
  92. if (mpp >= 16 && mpp <= 19)
  93. return 0;
  94. return -1;
  95. }
  96. printk(KERN_INFO "unknown MPP type %d\n", type);
  97. return -1;
  98. }
  99. void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode)
  100. {
  101. u32 mpp_0_7_ctrl = readl(MPP_0_7_CTRL);
  102. u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL);
  103. u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL);
  104. /* Initialize gpiolib. */
  105. orion_gpio_init();
  106. while (mode->mpp >= 0) {
  107. u32 *reg;
  108. int num_type;
  109. int shift;
  110. if (mode->mpp >= 0 && mode->mpp <= 7)
  111. reg = &mpp_0_7_ctrl;
  112. else if (mode->mpp >= 8 && mode->mpp <= 15)
  113. reg = &mpp_8_15_ctrl;
  114. else if (mode->mpp >= 16 && mode->mpp <= 19)
  115. reg = &mpp_16_19_ctrl;
  116. else {
  117. printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
  118. "(%d)\n", mode->mpp);
  119. continue;
  120. }
  121. num_type = determine_type_encoding(mode->mpp, mode->type);
  122. if (num_type < 0) {
  123. printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
  124. "combination (%d, %d)\n", mode->mpp,
  125. mode->type);
  126. continue;
  127. }
  128. shift = (mode->mpp & 7) << 2;
  129. *reg &= ~(0xf << shift);
  130. *reg |= (num_type & 0xf) << shift;
  131. if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182()))
  132. orion_gpio_set_unused(mode->mpp);
  133. orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
  134. mode++;
  135. }
  136. writel(mpp_0_7_ctrl, MPP_0_7_CTRL);
  137. writel(mpp_8_15_ctrl, MPP_8_15_CTRL);
  138. writel(mpp_16_19_ctrl, MPP_16_19_CTRL);
  139. }