Use SPI device pins as GPIO

      Use SPI device pins as GPIO

      Hi,

      I'm trying to use pins 12, 14, 16, 17 (of the 66 pins connector) as GPIO output.
      First I've used the /sys/class/gpio interface.
      Then I've tested a C program that directly writes into the registers.
      The result is the same.
      I can only change the status of pin 14.
      Pins 12, 16, 17 are always high.

      Any suggestion?

      This is my test C program:

      C Source Code

      1. #include <stdio.h>
      2. #include <stdlib.h>
      3. #include <errno.h>
      4. #include <fcntl.h>
      5. #include <sys/mman.h>
      6. #include <errno.h>
      7. #include <string.h>
      8. #include <stdint.h>
      9. #include <unistd.h>
      10. ////////////////////////////////////////////////////////////////////////////
      11. #define IOMUXC 0x020E0000
      12. //////////////////////////////////////////////////////// GPIO2_IO26 (EIM_RW)
      13. #define IOMUXC_SW_MUX_CTL_PAD_EIM_RW 0x0104
      14. #define GPIO2_IO26_MUX IOMUXC_SW_MUX_CTL_PAD_EIM_RW
      15. #define GPIO2_IO26_POS 26
      16. /////////////////////////////////////////////////////// GPIO3_IO16 (EIM_D16)
      17. #define IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16 0x0090
      18. #define GPIO3_IO16_MUX IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16
      19. #define GPIO3_IO16_POS 16
      20. /////////////////////////////////////////////////////// GPIO3_IO17 (EIM_D17)
      21. #define IOMUXC_SW_MUX_CTL_PAD_EIM_DATA17 0x0094
      22. #define GPIO3_IO17_MUX IOMUXC_SW_MUX_CTL_PAD_EIM_DATA17
      23. #define GPIO3_IO17_POS 17
      24. /////////////////////////////////////////////////////// GPIO3_IO18 (EIM_D18)
      25. #define IOMUXC_SW_MUX_CTL_PAD_EIM_DATA18 0x0098
      26. #define GPIO3_IO18_MUX IOMUXC_SW_MUX_CTL_PAD_EIM_DATA18
      27. #define GPIO3_IO18_POS 18
      28. ////////////////////////////////////////////////////////////////////////////
      29. #define GPIO2_BASE 0x020A0000
      30. #define GPIO3_BASE 0x020A4000
      31. #define GPIOx_DR 0x0000
      32. #define GPIOx_GDIR 0x0004
      33. ////////////////////////////////////////////////////////////////////////////
      34. static volatile uint32_t *iomux;
      35. static volatile uint32_t *gpio2;
      36. static volatile uint32_t *gpio3;
      37. ////////////////////////////////////////////////////////////////////////////
      38. int main(int argc, char **argv)
      39. {
      40. int fd ;
      41. printf("\n");
      42. /////////////////////////////////////// obtain handle to physical memory
      43. if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
      44. {
      45. printf("Unable to open /dev/mem: %s\n", strerror(errno));
      46. return -1;
      47. }
      48. //////////////////////////////////////////////////// map IOMUX registers
      49. iomux = (uint32_t *)mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, IOMUXC);
      50. if ((int32_t)iomux < 0)
      51. {
      52. printf("IOMUX mmap failed: %s\n", strerror(errno));
      53. exit(1);
      54. }
      55. ///////////////////////////////////////////// select GPIO2_IO26 function
      56. *(iomux + GPIO2_IO26_MUX/4) = 0x5;
      57. ///////////////////////////////////////////// select GPIO3_IO16 function
      58. *(iomux + GPIO3_IO16_MUX/4) = 0x5;
      59. ///////////////////////////////////////////// select GPIO3_IO17 function
      60. *(iomux + GPIO3_IO17_MUX/4) = 0x5;
      61. ///////////////////////////////////////////// select GPIO3_IO18 function
      62. *(iomux + GPIO3_IO18_MUX/4) = 0x5;
      63. ////////////////////////////////////////////////// unmap IOMUX registers
      64. if ((munmap((void *)iomux, 0x1000)) < 0)
      65. {
      66. printf("IOMUX munmap failed: %s\n", strerror(errno));
      67. exit(1);
      68. }
      69. //////////////////////////////////////////// map GPIO2 control registers
      70. gpio2 = (uint32_t *)mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO2_BASE);
      71. if ((int32_t)gpio2 < 0)
      72. {
      73. printf("GPIO2 mmap failed: %s\n", strerror(errno));
      74. exit(1);
      75. }
      76. //////////////////////////////////////////// map GPIO3 control registers
      77. gpio3 = (uint32_t *)mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO3_BASE);
      78. if ((int32_t)gpio3 < 0)
      79. {
      80. printf("GPIO3 mmap failed: %s\n", strerror(errno));
      81. exit(1);
      82. }
      83. ///////////////////////////////////////////// setup GPIO2_IO26 as output
      84. *(gpio2 + GPIOx_GDIR/4) = *(gpio2 + GPIOx_GDIR/4) | 1<<GPIO2_IO26_POS;
      85. ///////////////////////////////////////////// setup GPIO3_IO16 as output
      86. *(gpio3 + GPIOx_GDIR/4) = *(gpio3 + GPIOx_GDIR/4) | 1<<GPIO3_IO16_POS;
      87. ///////////////////////////////////////////// setup GPIO3_IO17 as output
      88. *(gpio3 + GPIOx_GDIR/4) = *(gpio3 + GPIOx_GDIR/4) | 1<<GPIO3_IO17_POS;
      89. ///////////////////////////////////////////// setup GPIO3_IO18 as output
      90. *(gpio3 + GPIOx_GDIR/4) = *(gpio3 + GPIOx_GDIR/4) | 1<<GPIO3_IO18_POS;
      91. ////////////////////////////////////////////////////// toggle GPIOx_IOxx
      92. while (1)
      93. {
      94. *(gpio2 + GPIOx_DR/4) = *(gpio2 + GPIOx_DR/4) ^ 1<<GPIO2_IO26_POS;
      95. *(gpio3 + GPIOx_DR/4) = *(gpio3 + GPIOx_DR/4) ^ 1<<GPIO3_IO16_POS;
      96. *(gpio3 + GPIOx_DR/4) = *(gpio3 + GPIOx_DR/4) ^ 1<<GPIO3_IO17_POS;
      97. *(gpio3 + GPIOx_DR/4) = *(gpio3 + GPIOx_DR/4) ^ 1<<GPIO3_IO18_POS;
      98. usleep(250000);
      99. }
      100. }

      Post was edited 1 time, last by “fs-support_HK”: Use code tags for source code, fix indentation ().

      Hi,

      The pins are used for SPI by default. So the internal iomux-controller of the SOC is configured to bring the SPI signals to the pads. Pin 14 works because it is used as chip select which is in fact a GPIO.
      The other pins can't work, especially when testing with /sys/class...

      The common way to configure the iomux controller is by editing the device tree.
      You have to deactivate SPI_A and configure every of the four pins as GPIO. (Also No. 14 must be configured because it will also be disabled when deactivating SPI_A.)

      This is how the configuration is done in the device tree:

      - Deactivate SPI_A: remove/comment CONFIG_ARMSTONEA9_SPI_A in arch/arm/boot/dts/armstonea9dl.dts
      (Solo/DualLite) or arch/arm/boot/dts/armstonea9q.dts (Dual/Quad) depending on the processor you have.

      - Open the file arch/arm/boot/dts/armstonea9qdl.dtsi and go to the ' pinctrl_hog_1' node. Here you can see
      some pads that are configured as GPIO. Here you have to set every pin.
      E.G. for pin 14 it looks like this:

      MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x80000000

      - Recompile the devicetree and install it on the board.


      Best Regards
      Your F&S Support Team

      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.

      Post was edited 1 time, last by “fs-support_PH” ().

      Dear Mr. Dgrechi,

      thanks for this hint. I checked the pins and found out that we have something wrong in our document "armStoneA9-GPIO-ReferenceCard_eng.pdf". The GPIO3IO16, GPIO3IO17, GPIO3IO18 were wrong documented. I fixed this document and uploaded it to our server. Now you can download the newest version from our homepage. Download link below:
      fs-net.de/assets/download/docu…PIO-ReferenceCard_eng.pdf

      Best Regards
      Your F&S Support Team
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.
      Thank you for the reply.

      I'm using fsimx6-V2.1 without Device Tree.
      So I'm trying to directly program the i.mx6 resgisters.

      I've configured the "ALT5" (0x5) function in the iomux registers related to 12, 14, 16, 17 pins (EIM_D16, EIM_RW, EIM_D17, EIM_D18 respectively): this should configure pins as GPIO.

      Then I've set the output direction through the GPIOx_GDIR registers.

      But, as I mentioned, I can't change the EIM16, EIM_D17, EIM_D18 status.

      What is missing?