gpio  1.4.2
General Purpose I/O Package
mmapGpio.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: gpio
4 //
5 // Library: libgpio
6 //
7 // File: mmapGpio.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-04-09 15:03:13 -0600 (Thu, 09 Apr 2015) $
12  * $Rev: 3916 $
13  *
14  * \brief GPIO library definitions using the memory mapped device interface.
15  *
16  * \par Original Code
17  * \author Markham Thomas
18  * (https://github.com/mlinuxguy/odpygpio)\n
19  * version 1.2 October 15, 2013\n
20  * Support Odroid-XU. The Python library for odroid-x and x2 boards from
21  * hardkernel implements mmap'd GPIO address space for performance.
22  *
23  * \author Robin Knight (robin.knight@roadnarrows.com)
24  *
25  * \par Copyright:
26  * (http://www.roadnarrows.com)
27  * \n All Rights Reserved
28  */
29 /*
30  * @EulaBegin@
31 // Permission is hereby granted, without written agreement and without
32 // license or royalty fees, to use, copy, modify, and distribute this
33 // software and its documentation for any purpose, provided that
34 // (1) The above copyright notice and the following two paragraphs
35 // appear in all copies of the source code and (2) redistributions
36 // including binaries reproduces these notices in the supporting
37 // documentation. Substantial modifications to this software may be
38 // copyrighted by their authors and need not follow the licensing terms
39 // described here, provided that the new terms are clearly indicated in
40 // all files where they apply.
41 //
42 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
43 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
44 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
45 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
46 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
47 // THE POSSIBILITY OF SUCH DAMAGE.
48 //
49 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
50 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
51 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
52 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
53 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
54  * @EulaEnd@
55  */
56 //
57 ////////////////////////////////////////////////////////////////////////////////
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <assert.h>
62 #include <unistd.h>
63 #include <errno.h>
64 #include <fcntl.h>
65 #include <sys/mman.h>
66 #include <sys/types.h>
67 #include <sys/stat.h>
68 #include <signal.h>
69 
70 #include "rnr/rnrconfig.h"
71 #include "rnr/log.h"
72 
73 #include "rnr/gpio.h"
74 
75 #ifdef MMAP_GPIO
76 
77 #if defined(ARCH_odroid)
78 
79 // ---------------------------------------------------------------------------
80 // Private Interface
81 // ---------------------------------------------------------------------------
82 
83 #define MAP_SIZE 4096UL ///< 4k memory map size
84 #define MAP_MASK (MAP_SIZE - 1) ///< memory map mask
85 
86 // Switch the defines for the correct board.
87 #define ODROIDXU3
88 #undef ODROIDXU
89 #undef ODROIDX2
90 
91 #define EXYNOS4_PA_GPIO1 0x11400000 ///< base address for GPIO registers
92 #define EXYNOS_5410 0x13400000 ///< base address for GPIO registers
93 #define EXYNOS_5422 0x13400000 ///< base address for GPIO registers
94 
95 #if defined(ODROIDXU3)
96  #define EXYNOS EXYNOS_5422
97 
98 #elif defined(ODROIDXU)
99  #define EXYNOS EXYNOS_5410
100 
101 #elif defined(ODROIDX2)
102  #define EXYNOS EXYNOS4_PA_GPIO1
103 
104 #else
105  #error "Unknown Odroid version"
106 #endif
107 
108 #define GPIO_GPCONREG 4 // subtract 4 from DATA register base to get CON reg
109 #define GPIO_UPDOWN 4 // add 4 to DATA register base to get UPD register
110 #define GPIO_DRIVESTR 8 // add 8 to DATA register base to get drive str ctl reg
111 
112 // example:
113 // GPF0CON = 0x0180 low/high nibbles are either 0000=input, 0001=output
114 // GPF0DAT = 0x0184 data bits for input or output
115 // GPF0UPD = 0x0188 every 2 bits is a GPIO pin 00=up/down disabled,
116 // 01=pull down, 10=pull up, 00
117 // GPF0DRV = 0x018c drive str control reg (2-bits each pin)
118 // 00=1x, 10=2x, 01=3x, 11=4x
119 
120 /*!
121  * \brief System GPIO exported number - pin number association structure.
122  */
123 typedef struct
124 {
125  int pin; ///< external header pin number
126  int gpio; ///< exported gpio number
127 } gpio_sysfs_t;
128 
129 /*!
130  * \brief GPIO memory mapped offset channel and bit position structure.
131  */
132 typedef struct
133 {
134  int channel; ///< offset
135  int bit; ///< bit
136 } gpio_address_t;
137 
138 #define NOPIN {0, 0} ///< no mapped pin to GPIO
139 
140 #if defined(ODROIDXU3)
141 
142 /*!
143  * \brief Associates the CON10 header pin number to sysfs exported GPIO number.
144  */
145 static gpio_sysfs_t GpioSysfsTbl[] =
146 {
147  {4, 173}, {5, 174}, {6, 171}, {7, 192},
148  {8, 172}, {9, 191}, {10, 189}, {11, 190},
149  {13, 21}, {14, 210}, {15, 18}, {16, 209},
150  {17, 22}, {18, 19}, {19, 30}, {20, 28},
151  {21, 29}, {22, 31}, {24, 25}, {26, 24}
152 };
153 
154 #if 0
155 /*!
156  * \brief Maps the CON10 header GPIO pin to the memory mapped offset and bit.
157  *
158  * Indexed by pin number.
159  */
160 static gpio_address_t PinAddrTbl[] =
161 {
162  NOPIN, // 0
163 
164  // 5V0 GND
165  NOPIN, NOPIN, // 1, 2
166 
167  // ADC_0.AIN0 UART_0.RTSN
168  // gpio 173
169  NOPIN, NOPIN, // 3, 4
170 
171  // UART_0.CTSN UART_O.RXD
172  // gpio 174 gpio 171
173  NOPIN, NOPIN, // 5, 6
174 
175  // SPI_1.MOISI UART_O.TXD
176  // gpio 192 gpio 172
177  NOPIN, NOPIN, // 7, 8
178 
179  // SPI_1.MISO SPI_1.CLK
180  // gpio 191 gpio 189
181  NOPIN, NOPIN, // 9, 10
182 
183  // SPI_1.CSN PWRON
184  // gpio 190
185  NOPIN, NOPIN, // 11, 12
186 
187  // XE.INT13 I2C_1.SCL
188  // gpio 21 gpio 210
189  {0x0c24,5}, NOPIN, // 13, 14
190 
191  // XE.INT10 I2C_1.SDA
192  // gpio 18 gpio 209
193  {0x0c24,2}, NOPIN, // 15, 16
194 
195  // XE.INT14 XE.INT11
196  {0x0c24,6}, {0x0c24,3}, // 17, 18
197 
198  // XE.INT22 XE.INT20
199  {0x0c44,6}, {0x0c44,4}, // 19, 20
200 
201  // XE.INT21 XE.INT23
202  {0x0c44,5}, {0x0c44,7}, // 21, 22
203 
204  // XE.INT18 XE.INT17
205  {0x0c44,2}, {0x0c44,1}, // 23, 24
206 
207  // XE.INT15 XE.INT16
208  {0x0c24,7}, {0x0c44,0}, // 25, 26
209 
210  // XE.INT25 GND
211  {0x0c64,1}, NOPIN, // 27, 28
212 
213  // VDD_IO GND
214  NOPIN, NOPIN, // 29, 30
215 };
216 #endif // 0
217 
218 /*!
219  * \brief Maps exported GPIO number to the memory mapped offset and bit.
220  *
221  * Indexed by GPIO number.
222  */
223 static gpio_address_t GpioAddrTbl[514];
224 
225 /*!
226  * \brief Fill device memory address offset and bit lookup table.
227  *
228  * \todo Need to find mapping for GPIO: 23 171 172 173 ...
229  */
230 static void mmapFillLookupTbl()
231 {
232  memset(GpioAddrTbl, 0, sizeof(GpioAddrTbl));
233 
234  // GPIO: 18 Pin: 15 Net: XE.INT10
235  GpioAddrTbl[18].channel = 0x0c24;
236  GpioAddrTbl[18].bit = 2;
237 
238  // GPIO: 19 Pin: 18 Net: XE.INT11
239  GpioAddrTbl[19].channel = 0x0c24;
240  GpioAddrTbl[19].bit = 3;
241 
242  // GPIO: 21 Pin: 13 Net: XE.INT13
243  GpioAddrTbl[21].channel = 0x0c24;
244  GpioAddrTbl[21].bit = 5;
245 
246  // GPIO: 22 Pin: 17 Net: XE.INT14
247  GpioAddrTbl[22].channel = 0x0c24;
248  GpioAddrTbl[22].bit = 6;
249 
250  // GPIO: 24 Pin: 26 Net: XE.INT16
251  GpioAddrTbl[24].channel = 0x0c44;
252  GpioAddrTbl[24].bit = 0;
253 
254  // GPIO: 25 Pin: 24 Net: XE.INT17
255  GpioAddrTbl[25].channel = 0x0c44;
256  GpioAddrTbl[25].bit = 1;
257 
258  // GPIO: 28 Pin: 20 Net: XE.INT20
259  GpioAddrTbl[28].channel = 0x0c44;
260  GpioAddrTbl[28].bit = 4;
261 
262  // GPIO: 29 Pin: 21 Net: XE.INT21
263  GpioAddrTbl[29].channel = 0x0c44;
264  GpioAddrTbl[29].bit = 5;
265 
266  // GPIO: 30 Pin: 19 Net: XE.INT22
267  GpioAddrTbl[30].channel = 0x0c44;
268  GpioAddrTbl[30].bit = 6;
269 
270  // GPIO: 31 Pin: 22 Net: XE.INT23
271  GpioAddrTbl[31].channel = 0x0c44;
272  GpioAddrTbl[31].bit = 7;
273 }
274 
275 #elif defined(ODROIDXU) || defined(ODROIDX2)
276 
277 /*!
278  * \brief Associates the CON10 header pin number to sysfs exported GPIO number.
279  */
280 static gpio_sysfs_t GpioSysfsTbl[] =
281 {
282  {13, 309}, {14, 316}, {15, 306}, {16, 304},
283  {17, 310}, {18, 307}, {19, 319}, {20, 317},
284  {21, 318}, {22, 320}, {23, 315}, {24, 314},
285  {25, 311}, {26, 313}, {27, 323}
286 };
287 
288 /*!
289  * \brief Maps the CON10 header GPIO pin to the memory mapped offset and bit.
290  *
291  * Indexed by pin number.
292  */
293 static gpio_address_t GpioAddrTbl[] =
294 {
295  NOPIN, // 0
296 
297  // 5V0 GND
298  NOPIN, NOPIN, // 1, 2
299 
300  // ADC_0.AIN0 UART_0.RTSN
301  NOPIN, NOPIN, // 3, 4
302 
303  // UART_0.CTSN UART_O.RXD
304  NOPIN, NOPIN, // 5, 6
305 
306  // SPI_1.MOISI UART_O.TXD
307  NOPIN, NOPIN, // 7, 8
308 
309  // SPI_1.MISO SPI_1.CLK
310  NOPIN, NOPIN, // 9, 10
311 
312  // SPI_1.CSN PWRON
313  NOPIN, NOPIN, // 11, 12
314 
315  // XE.INT13 XE.INT19
316  {0x0c24,5}, {0x0c44,3}, // 13, 14
317 
318  // XE.INT10 XE.INT8
319  {0x0c24,2}, {0x0c24,0}, // 15, 16
320 
321  // XE.INT14 XE.INT11
322  {0x0c24,6}, {0x0c24,3}, // 17, 18
323 
324  // XE.INT22 XE.INT20
325  {0x0c44,6}, {0x0c44,4}, // 19, 20
326 
327  // XE.INT21 XE.INT23
328  {0x0c44,5}, {0x0c44,7}, // 21, 22
329 
330  // XE.INT18 XE.INT17
331  {0x0c44,2}, {0x0c44,1}, // 23, 24
332 
333  // XE.INT15 XE.INT16
334  {0x0c24,7}, {0x0c44,0}, // 25, 26
335 
336  // XE.INT25 GND
337  {0x0c64,1}, NOPIN, // 27, 28
338 
339  // VDD_IO GND
340  NOPIN, NOPIN, // 29, 30
341 };
342 
343 #endif // defined(ODROIDXU) || defined(ODROIDX2)
344 
345 static void *MapBase; ///< the gpio base address
346 
347 /*!
348  * \brief Test if exported gpio number has a known mapped memory area.
349  *
350  * \param gpio Exported GPIO number.
351  *
352  * \return Returns 1 if has map, 0 otherwise.
353  */
354 static int hasmap(int gpio)
355 {
356  if( (gpio < 0) || (gpio >= arraysize(GpioAddrTbl)) )
357  {
358  return 0;
359  }
360  else if( (GpioAddrTbl[gpio].channel == 0) && (GpioAddrTbl[gpio].bit == 0) )
361  {
362  return 0;
363  }
364  else
365  {
366  return 1;
367  }
368 }
369 
370 static const char *ErrStrNoMapFound = "GPIO block has not been memory mapped.";
371 static const char *ErrStrGpioNoMap = "No memory mapped address offset found.";
372 
373 
374 // ---------------------------------------------------------------------------
375 // Public Interface
376 // ---------------------------------------------------------------------------
377 
378 int gpioExportedToPin(int gpio)
379 {
380  size_t i;
381 
382  for(i=0; i<arraysize(GpioSysfsTbl); ++i)
383  {
384  if( GpioSysfsTbl[i].gpio == gpio )
385  {
386  return GpioSysfsTbl[i].pin;
387  }
388  }
389  return RC_ERROR;
390 }
391 
392 int gpioPinToExported(int pin)
393 {
394  size_t i;
395 
396  for(i=0; i<arraysize(GpioSysfsTbl); ++i)
397  {
398  if( GpioSysfsTbl[i].pin == pin )
399  {
400  return GpioSysfsTbl[i].gpio;
401  }
402  }
403  return RC_ERROR;
404 }
405 
406 int mmapGpioMap()
407 {
408  int fd;
409  off_t target = EXYNOS;
410 
411  MapBase = 0;
412 
413  if( (fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1 )
414  {
415  LOGSYSERROR("Could not open /dev/mem device.");
416  return RC_ERROR;
417  }
418 
419  // Map one page
420  MapBase = mmap(NULL,
421  MAP_SIZE,
422  PROT_READ | PROT_WRITE,
423  MAP_SHARED,
424  fd,
425  target & (off_t)~MAP_MASK);
426 
427  close(fd);
428 
429  if( MapBase == (void *) -1 )
430  {
431  LOGSYSERROR("Memory map failed.");
432  return RC_ERROR;
433  }
434 
435  mmapFillLookupTbl();
436 
437  LOGDIAG3("Memory mapped GPIO setup at address 0x%0lx.", target);
438 
439  return OK;
440 }
441 
442 int mmapGpioUnmap()
443 {
444  if( MapBase == 0 )
445  {
446  LOGWARN("%s", ErrStrNoMapFound);
447  return OK;
448  }
449  else if( munmap(MapBase, MAP_SIZE) == -1 )
450  {
451  LOGSYSERROR("Memory unmap failed.");
452  return RC_ERROR;
453  }
454  else
455  {
456  MapBase = 0;
457  LOGDIAG3("Memory mapped GPIO torn down.");
458  return OK;
459  }
460 }
461 
462 int mmapGpioSetDirection(int gpio, int dir)
463 {
464  int channel, bit;
465  div_t div_res;
466  byte_t val;
467  byte_t *base;
468  const char *sOp;
469 
470  if( MapBase == NULL )
471  {
472  LOGERROR("%s", ErrStrNoMapFound);
473  return RC_ERROR;
474  }
475 
476  if( !hasmap(gpio) )
477  {
478  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
479  return RC_ERROR;
480  }
481 
482  channel = GpioAddrTbl[gpio].channel;
483  bit = GpioAddrTbl[gpio].bit;
484 
485  base = (MapBase + channel) - GPIO_GPCONREG;
486 
487  div_res = div(bit, 2); // 2 nibbles per byte so divide by 2
488 
489  base += div_res.quot;
490 
491  // read
492  val = *(byte_t *)base;
493 
494  switch( dir )
495  {
496  // set to output
497  case GPIO_DIR_OUT:
498  sOp = GPIO_DIR_OUT_STR;
499 
500  // if remainder then its upper nibble
501  if( div_res.rem )
502  {
503  val &= 0b00011111; // upper nibble, not always def to zero
504  val |= 0b00010000; // set upper nibble as output
505  }
506  // otherwise its lower nibble
507  else
508  {
509  val &= 0b11110001; // not always def to zero on boot
510  val |= 0b00000001; // set lower nibble as output
511  }
512  break;
513 
514  // set to input
515  case GPIO_DIR_IN:
516  sOp = GPIO_DIR_IN_STR;
517 
518  // if remainder then its upper nibble
519  if( div_res.rem )
520  {
521  val &= 0b00001111; // clear upper nibble to be input
522  }
523  // otherwise its lower nibble
524  else
525  {
526  val &= 0b11110000; // clear lower nibble to be input
527  }
528  break;
529 
530  // invalid direction
531  default:
532  LOGERROR("GPIO %d: Invalid direction. Must be one of: %d(=in) %d(=out).",
533  gpio, GPIO_DIR_IN, GPIO_DIR_OUT);
534  return RC_ERROR;
535  }
536 
537  // write
538  *(byte_t *)base = val;
539 
540  LOGDIAG3("GPIO %d: Configured for %sput.", gpio, sOp);
541 
542  return OK;
543 }
544 
545 int mmapGpioSetPull(int gpio, int pull)
546 {
547  int channel, bit;
548  byte_t val, v, hld;
549  byte_t *base;
550  const char *sOp;
551 
552  if( MapBase == NULL )
553  {
554  LOGERROR("%s", ErrStrNoMapFound);
555  return RC_ERROR;
556  }
557 
558  if( !hasmap(gpio) )
559  {
560  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
561  return RC_ERROR;
562  }
563 
564  channel = GpioAddrTbl[gpio].channel;
565  bit = GpioAddrTbl[gpio].bit;
566 
567  base = (MapBase + channel) + GPIO_UPDOWN;
568 
569  switch( pull )
570  {
571  // disable pullup/down
572  case GPIO_PULL_DS:
573  sOp = GPIO_PULL_DS_STR;
574  v = 0;
575  break;
576 
577  // pullup enabled
578  case GPIO_PULL_UP:
579  sOp = GPIO_PULL_UP_STR;
580  v = 0b00000010;
581  break;
582 
583  // pulldown enabled
584  case GPIO_PULL_DN:
585  sOp = GPIO_PULL_DN_STR;
586  v = 0b00000001;
587  break;
588 
589  // invalid pull
590  default:
591  LOGERROR("GPIO %d: Invalid pull. "
592  "Must be one of: %d(=disabled) %d(=up) %d(=down).",
594  return RC_ERROR;
595  }
596 
597  if( bit < 4 )
598  {
599  hld = (byte_t)(v << (bit*2)); // shift the 2 bits to their proper location
600  }
601  else
602  {
603  bit = bit - 4;
604  hld = (byte_t)(v << (bit*2)); // shift the 2 bits to their proper location
605  base++; // move up to next byte
606  }
607 
608  // read
609  val = *(byte_t *)base;
610 
611  // set
612  val |= hld;
613 
614  // write
615  *(byte_t *)base = val;
616 
617  LOGDIAG3("GPIO %d: Configured for pull %s.", gpio, sOp);
618 
619  return OK;
620 }
621 
622 int mmapGpioProbe(int gpio, gpio_info_t *p)
623 {
624  int channel, bit;
625  div_t div_res;
626  byte_t value;
627  byte_t dir;
628  byte_t pull;
629 
630  if( MapBase == NULL )
631  {
632  LOGERROR("%s", ErrStrNoMapFound);
633  return RC_ERROR;
634  }
635 
636  if( !hasmap(gpio) )
637  {
638  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
639  return RC_ERROR;
640  }
641 
642  channel = GpioAddrTbl[gpio].channel;
643  bit = GpioAddrTbl[gpio].bit;
644  div_res = div(bit, 2); // 2 nibbles per byte so divide by 2
645 
646  p->base = EXYNOS;
647  p->gpio = gpio;
648  p->pin = gpioExportedToPin(gpio);
649  p->channel = channel;
650  p->bit = bit;
651 
652  //
653  // Value
654  //
655  value = *(byte_t *)(MapBase + channel);
656 
657  // high
658  if( value & (1 << bit) )
659  {
660  p->value = 1;
661  }
662  // low
663  else
664  {
665  p->value = 0;
666  }
667 
668  //
669  // Direction
670  //
671  dir = *(byte_t *)(MapBase + channel - GPIO_GPCONREG);
672 
673  // if remainder then its upper nibble
674  if( div_res.rem )
675  {
676  if( dir & 0b00010000 )
677  {
678  p->dir = GPIO_DIR_OUT;
679  }
680  else
681  {
682  p->dir = GPIO_DIR_IN;
683  }
684  }
685  // otherwise its lower nibble
686  else
687  {
688  if( dir & 0b00000001 )
689  {
690  p->dir = GPIO_DIR_OUT;
691  }
692  else
693  {
694  p->dir = GPIO_DIR_IN;
695  }
696  }
697 
698  //
699  // Pull state
700  //
701  if( bit < 4 )
702  {
703  // read pull state
704  pull = *(byte_t *)(MapBase + channel + GPIO_UPDOWN);
705  // shift the 2 bits to their proper location
706  pull = (byte_t)(pull >> (bit*2));
707  }
708  else
709  {
710  // read pull state
711  pull = *(byte_t *)(MapBase + channel + GPIO_UPDOWN + 1);
712  // shift the 2 bits to their proper location
713  pull = (byte_t)(pull >> ((bit-4)*2));
714  }
715 
716  pull &= 0x03;
717 
718  // pullup enabled
719  if( pull == 0b00000010 )
720  {
721  p->pull = GPIO_PULL_UP;
722  }
723  // pulldown enabled
724  else if( pull == 0b00000001 )
725  {
726  p->pull = GPIO_PULL_DN;
727  }
728  // disable pullup/down
729  else
730  {
731  p->pull = GPIO_PULL_DS;
732  }
733 
734  return OK;
735 }
736 
737 int mmapGpioRead(int gpio)
738 {
739  int channel, bit;
740  byte_t input;
741  int value;
742 
743  if( MapBase == NULL )
744  {
745  LOGERROR("%s", ErrStrNoMapFound);
746  return RC_ERROR;
747  }
748 
749  if( !hasmap(gpio) )
750  {
751  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
752  return RC_ERROR;
753  }
754 
755  channel = GpioAddrTbl[gpio].channel;
756  bit = GpioAddrTbl[gpio].bit;
757 
758  input = *(byte_t *)(MapBase + channel);
759 
760  if( input & (1 << bit) )
761  {
762  value = 1;
763  }
764  else
765  {
766  value = 0;
767  }
768 
769  return value;
770 }
771 
772 int mmapGpioWrite(int gpio, int value)
773 {
774  int channel, bit;
775  void *virtAddr;
776  byte_t output;
777 
778  if( MapBase == NULL )
779  {
780  LOGERROR("%s", ErrStrNoMapFound);
781  return RC_ERROR;
782  }
783 
784  if( !hasmap(gpio) )
785  {
786  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
787  return RC_ERROR;
788  }
789 
790  channel = GpioAddrTbl[gpio].channel;
791  bit = GpioAddrTbl[gpio].bit;
792 
793  virtAddr = MapBase + channel; // offset of the GPIO
794 
795  // get the current bits
796  output = *(byte_t *)virtAddr;
797 
798  if( value )
799  {
800  output |= (byte_t)(1 << bit); // set the bit
801  }
802  else
803  {
804  output &= (byte_t)(~(1 << bit)); // clear the bit
805  }
806 
807  // write the newly set bit out
808  *(byte_t *)virtAddr = output;
809 
810  return OK;
811 }
812 
813 int mmapGpioToggle(int gpio, int count)
814 {
815  int channel, bit;
816  void *virtAddr;
817  byte_t val, vbl, vcl, sbit;
818  int i;
819 
820  if( MapBase == NULL )
821  {
822  LOGERROR("%s", ErrStrNoMapFound);
823  return RC_ERROR;
824  }
825 
826  if( !hasmap(gpio) )
827  {
828  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
829  return RC_ERROR;
830  }
831 
832  channel = GpioAddrTbl[gpio].channel;
833  bit = GpioAddrTbl[gpio].bit;
834 
835  virtAddr = MapBase + channel; // offset of the GPIO
836 
837  val = *(byte_t *)virtAddr; // get the current bits
838 
839  sbit = (byte_t)(1 << bit); // our bit to toggle
840  sbit &= 0xff; // sanity
841  vbl = val ^ sbit; // toggle the bit one way
842  vcl = vbl ^ sbit; // toggle the bit the other way
843 
844  // wiggle
845  for(i=0; i<count; ++i)
846  {
847  //val ^= sbit; // toggle the bit
848  *(byte_t *)virtAddr = vbl; // write the newly changed bit out
849  *(byte_t *)virtAddr = vcl; // write the newly changed bit out
850  }
851 
852  return OK;
853 }
854 
855 int mmapGpioBitBang(int gpio,
856  byte_t pattern[],
857  size_t bitCount,
858  unsigned int usecIbd)
859 {
860  size_t byteCount = (bitCount + 7) / 8;
861  size_t i, j, k;
862  int mask, value;
863 
864  if( MapBase == NULL )
865  {
866  LOGERROR("%s", ErrStrNoMapFound);
867  return RC_ERROR;
868  }
869 
870  if( !hasmap(gpio) )
871  {
872  LOGERROR("GPIO %d: %s", gpio, ErrStrGpioNoMap);
873  return RC_ERROR;
874  }
875 
876  for(i=0, k=0; i<byteCount; ++i)
877  {
878  for(j=0, mask=0x80; j<8 && k<bitCount; ++j, ++k)
879  {
880  if( usecIbd > 0 )
881  {
882  usleep(usecIbd);
883  }
884  value = pattern[i] & mask? 1: 0;
885  mask >>= 1;
886  if( mmapGpioWrite(gpio, value) < 0 )
887  {
888  return RC_ERROR;
889  }
890  }
891  }
892 
893  return OK;
894 }
895 
896 #else // unsupported target architectures
897 
898 static const char *ErrStrArchNoMap = "No memory mapped GPIO support.";
899 
900 #define NO_SOUP "Architecture %s: %s."
901 
902 
903 int gpioExportedToPin(int gpio)
904 {
905  return RC_ERROR;
906 }
907 
908 int gpioPinToExported(int pin)
909 {
910  return RC_ERROR;
911 }
912 
913 int mmapGpioMap()
914 {
915  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
916  return RC_ERROR;
917 }
918 
919 int mmapGpioUnmap()
920 {
921  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
922  return RC_ERROR;
923 }
924 
925 int mmapGpioSetDirection(int pin, int dir)
926 {
927  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
928  return RC_ERROR;
929 }
930 
931 int mmapGpioSetPull(int pin, int pull)
932 {
933  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
934  return RC_ERROR;
935 }
936 
937 int mmapGpioProbe(int pin, gpio_info_t *p)
938 {
939  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
940  return RC_ERROR;
941 }
942 
943 int mmapGpioRead(int pin)
944 {
945  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
946  return RC_ERROR;
947 }
948 
949 int mmapGpioWrite(int pin, int value)
950 {
951  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
952  return RC_ERROR;
953 }
954 
955 int mmapGpioToggle(int pin, int count)
956 {
957  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
958  return RC_ERROR;
959 }
960 
961 int mmapGpioBitBang(int pin,
962  byte_t pattern[],
963  size_t bitCount,
964  unsigned int usecIbd)
965 {
966  LOGERROR(NO_SOUP, ARCH, ErrStrArchNoMap);
967  return RC_ERROR;
968 }
969 
970 #endif // architecture
971 
972 #endif // MMAP_GPIO
#define GPIO_PULL_DN_STR
enable pulldown string
Definition: gpio.h:93
int pull
pull state
Definition: gpio.h:104
#define GPIO_PULL_DS
disable pullup/down
Definition: gpio.h:88
int gpio
sysfs exported gpio number
Definition: gpio.h:100
GPIO interface declarations and defines.
#define GPIO_DIR_IN
input
Definition: gpio.h:68
#define GPIO_PULL_DS_STR
disable pullup/down string
Definition: gpio.h:91
#define GPIO_PULL_UP_STR
enable pullup string
Definition: gpio.h:92
#define GPIO_DIR_OUT_STR
output string
Definition: gpio.h:71
#define GPIO_PULL_DN
enable pulldown
Definition: gpio.h:90
GPIO info structure.
Definition: gpio.h:98
int dir
gpio direction
Definition: gpio.h:102
#define GPIO_DIR_OUT
output
Definition: gpio.h:69
#define GPIO_DIR_IN_STR
input string
Definition: gpio.h:70
int pin
external header pin number
Definition: gpio.h:101
#define GPIO_PULL_UP
enable pullup
Definition: gpio.h:89
int value
current value
Definition: gpio.h:105