mcf5225x_gpio.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright 2012 by Embedded Technologies s.r.o
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. #include <arch/m68k.h>
  33. #include <dev/gpio.h>
  34. #include <sys/nutdebug.h>
  35. enum pin_type {
  36. DUAL, QUAD
  37. };
  38. struct bank_layout {
  39. enum pin_type pins_type;
  40. uint8_t pins_configurable;
  41. };
  42. struct bank_layout * BankLayout(int bank)
  43. {
  44. static struct bank_layout layout;
  45. switch (bank) {
  46. case PORTDD:
  47. case PORTAN:
  48. case PORTTE:
  49. case PORTTF:
  50. case PORTTG:
  51. case PORTTI:
  52. case PORTTJ:
  53. layout.pins_type = DUAL;
  54. layout.pins_configurable = 0xFF;
  55. break;
  56. case PORTAS:
  57. layout.pins_type = QUAD;
  58. layout.pins_configurable = 0x07;
  59. break;
  60. case PORTQS:
  61. layout.pins_type = QUAD;
  62. layout.pins_configurable = 0x6F;
  63. break;
  64. case PORTTA:
  65. case PORTTC:
  66. case PORTUA:
  67. case PORTUB:
  68. case PORTUC:
  69. layout.pins_type = QUAD;
  70. layout.pins_configurable = 0x0F;
  71. break;
  72. case PORTTH:
  73. layout.pins_type = QUAD;
  74. layout.pins_configurable = 0xFF;
  75. break;
  76. case PORTNQ:
  77. layout.pins_type = QUAD;
  78. layout.pins_configurable = 0xAA;
  79. break;
  80. default:
  81. return NULL;
  82. break;
  83. }
  84. return &layout;
  85. }
  86. /*!
  87. * \brief Get pin configuration.
  88. *
  89. * \param bank GPIO bank/port number.
  90. * \param bit Bit number of the specified bank/port.
  91. *
  92. * \return Attribute flags of the pin.
  93. */
  94. uint32_t GpioPinConfigGet(int bank, int bit)
  95. {
  96. uint32_t rc = 0;
  97. struct bank_layout *bank_cfg;
  98. /* Get & check bank layout */
  99. bank_cfg = BankLayout(bank);
  100. if ((!bank_cfg) || !(bank_cfg->pins_configurable & _BV(bit)))
  101. return 0;
  102. /* Read pin role (pin assignment register) */
  103. switch (bank_cfg->pins_type) {
  104. case DUAL:
  105. rc = (MCF_GPIO_PAR8(bank) >> bit) & 0x1;
  106. break;
  107. case QUAD:
  108. if (bank_cfg->pins_configurable & 0xF0) {
  109. rc = (MCF_GPIO_PAR16(bank) >> (2 * bit)) & 0x3;
  110. } else {
  111. rc = (MCF_GPIO_PAR8(bank) >> (2 * bit)) & 0x3;
  112. }
  113. break;
  114. }
  115. /* Read GPIO direction */
  116. if (rc == GPIO_CFG_INPUT) {
  117. if (MCF_GPIO_DDR(bank) & _BV(bit)) {
  118. rc = GPIO_CFG_OUTPUT;
  119. }
  120. }
  121. return rc;
  122. }
  123. /*!
  124. * \brief Set pin configuration.
  125. *
  126. * Applications may also use this function to make sure, that a specific
  127. * attribute is available for a specific pin.
  128. *
  129. * \note GPIO pins are typically initialized to a safe state after power
  130. * up. This routine is not able to determine the consequences of
  131. * changing pin configurations. In the worst case you may permanently
  132. * damage your hardware by bad pin settings.
  133. *
  134. * \param bank GPIO bank/port number.
  135. * \param bit Bit number of the specified bank/port.
  136. * \param flags Attribute flags.
  137. *
  138. * \return 0 if all attributes had been set, -1 otherwise.
  139. */
  140. int GpioPinConfigSet(int bank, int bit, uint32_t flags)
  141. {
  142. GpioPortConfigSet(bank, _BV(bit), flags);
  143. /* Check the result. */
  144. if (GpioPinConfigGet(bank, bit) != flags) {
  145. return -1;
  146. }
  147. return 0;
  148. }
  149. /*!
  150. * \brief Set port wide pin configuration.
  151. *
  152. * \note This function does not check for undefined ports and pins or
  153. * invalid attributes. If this is required, use GpioPinConfigSet().
  154. *
  155. * \param bank GPIO bank/port number.
  156. * \param mask The given attributes are set for a specific pin, if the
  157. * corresponding bit in this mask is 1.
  158. * \param flags Attribute flags to set.
  159. *
  160. * \return Always 0.
  161. */
  162. int GpioPortConfigSet(int bank, uint32_t mask, uint32_t flags)
  163. {
  164. struct bank_layout *bank_cfg;
  165. uint32_t role = flags & (GPIO_CFG_PERIPHERAL_MASK | GPIO_CFG_OUTPUT);
  166. uint32_t role_mask;
  167. int i;
  168. /* Get bank layout */
  169. bank_cfg = BankLayout(bank);
  170. /* Return if the bank is unknown */
  171. if (!bank_cfg) {
  172. return 0;
  173. }
  174. /* Return if roles are not applicable. */
  175. if (bank_cfg->pins_type != QUAD && ((role == GPIO_CFG_PERIPHERAL1) || (role == GPIO_CFG_PERIPHERAL2))) {
  176. return 0;
  177. }
  178. /* Configure the configurable pins only */
  179. mask &= bank_cfg->pins_configurable;
  180. /* Configure GPIO direction first */
  181. if (role == GPIO_CFG_OUTPUT) {
  182. MCF_GPIO_DDR(bank) |= mask;
  183. } else if (role == GPIO_CFG_INPUT) {
  184. MCF_GPIO_DDR(bank) &= ~mask;
  185. }
  186. /* Then configure pin role */
  187. if (bank_cfg->pins_type == DUAL) {
  188. /* Read old roles */
  189. role_mask = MCF_GPIO_PAR8(bank);
  190. /* Update roles */
  191. if (role == GPIO_CFG_PERIPHERAL0) {
  192. role_mask |= mask;
  193. } else {
  194. role_mask &= ~mask;
  195. }
  196. /* Apply new roles */
  197. MCF_GPIO_PAR8(bank) = (uint8_t) role_mask;
  198. } else /* if (bank_cfg->pins_type == QUAD) */{
  199. /* Read old roles */
  200. role_mask = (bank_cfg->pins_configurable & 0xF0) ? MCF_GPIO_PAR16(bank) : MCF_GPIO_PAR8(bank);
  201. /* Shift in new roles */
  202. for (i = 0; i < 7; i++) {
  203. if (mask & (1 << i)) {
  204. /* Erase old role */
  205. role_mask &= ~(GPIO_CFG_PERIPHERAL_MASK << (2 * i));
  206. /* Set new role */
  207. role_mask |= (role & GPIO_CFG_PERIPHERAL_MASK) << (2 * i);
  208. }
  209. }
  210. /* Write back new roles */
  211. if (bank_cfg->pins_configurable & 0xF0) {
  212. MCF_GPIO_PAR16(bank) = (uint16_t) role_mask;
  213. } else {
  214. MCF_GPIO_PAR8(bank) = (uint8_t) role_mask;
  215. }
  216. }
  217. return 0;
  218. }